原始输出H.264码流由媒体codeC不playble [英] Raw H.264 stream output by MediaCodec not playble

查看:779
本文介绍了原始输出H.264码流由媒体codeC不playble的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建通过媒体codeC原料H.264输出流。问题是输出文件是不是在Android的默认播放器(API 16)播放。怎么会是Android的可导出文件,是不是在播放机上播放,仅在VLC在PC上。也许有些事情错了我的code?我的视频是384x288。

 公共类AvcEn $ C $ {CR私营媒体codeC媒体codeC;
私人的BufferedOutputStream的OutputStream;
私人文件f;公共AvcEn codeR(INT W,INT小时,字符串FILE_NAME)
{
    F =新的文件(FILE_NAME +.MP4);    尝试{
        的OutputStream =新的BufferedOutputStream(新的FileOutputStream(f)条);
    }赶上(例外五){
        e.printStackTrace();
    }    字符串key_mime =视频/ AVC //视频/ MP4V-ES,视频/ 3GPP,视频/ AVC
    媒体codeC =媒体codec.createEn coderByType(key_mime);
    MediaFormat mediaFormat = MediaFormat.createVideoFormat(key_mime,W,H);    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE,(W * H)< 3;);
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE,25);
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,媒体codecInfo codecCapabilities.COLOR_FormatYUV420SemiPlanar);
    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,5);    mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,Media$c$ccInfo.$c$ccProfileLevel.MPEG4ProfileMain);
    媒体codec.configure(mediaFormat,NULL,NULL,媒体codec.CONFIGURE_FLAG_EN code);
    媒体codec.start();
}公共无效的close(){
    尝试{
        媒体codec.stop();
        媒体codec.release();
        outputStream.flush();
        outputStream.close();
    }赶上(例外五){
        e.printStackTrace();
    }
}
公共无效offerEn codeR(字节[]输入){
    尝试{
        ByteBuffer的[] inputBuffers =媒体codec.getInputBuffers();
        ByteBuffer的[] outputBuffers =媒体codec.getOutputBuffers();
        INT inputBufferIndex =媒体codec.dequeueInputBuffer(0);
        如果(inputBufferIndex> = 0){
            ByteBuffer的INPUTBUFFER = inputBuffers [inputBufferIndex]
            inputBuffer.clear();
            inputBuffer.put(输入);
            媒体codec.queueInputBuffer(inputBufferIndex,0,input.length,0,0);
        }        媒体codec.BufferInfo bufferInfo =新媒体codec.BufferInfo();
        INT outputBufferIndex =媒体codec.dequeueOutputBuffer(bufferInfo,0);
        而(outputBufferIndex> = 0){
            ByteBuffer的OutputBuffer中= outputBuffers [outputBufferIndex]
            字节[] = outData新的字节[bufferInfo.size]
            outputBuffer.get(outData)以;
            outputStream.write(outData,0,outData.length);            媒体codec.releaseOutputBuffer(outputBufferIndex,FALSE);
            outputBufferIndex =媒体codec.dequeueOutputBuffer(bufferInfo,0);
        }
    }赶上(的Throwable t)的{      }
  }
}


解决方案

Android的的MediaPlayer 不处理的原始H.264视频流。

与这些流的一个困难是,H.264的NAL单元不具有时间戳的信息,因此除非该视频帧是在一个已知的固定帧速率的播放机将不知道什么时候present它们。

您可以创建自己与播放媒体codeC (见如播放视频(TextureView)中的 Grafika ),或原始数据流转换为.MP4​​文件。后者需要 MediaMuxer ,在18 API,或者使用第三方的库样的ffmpeg提供。

I am creating raw H.264 stream output by MediaCodec. The problem is the output file is not playable in android default player (API 16). How can it be that Android can export file that is not playable in player, only in VLC on the PC. Maybe some thing wrong with my code? My video is 384x288.

public class AvcEncoder {

private MediaCodec mediaCodec;
private BufferedOutputStream outputStream;
private File f;

public AvcEncoder(int w, int h, String file_name) 
{ 
    f = new File(file_name + ".mp4");

    try {
        outputStream = new BufferedOutputStream(new FileOutputStream(f));
    } catch (Exception e){ 
        e.printStackTrace();
    }

    String key_mime = "video/avc"; //video/mp4v-es, video/3gpp, video/avc
    mediaCodec = MediaCodec.createEncoderByType(key_mime);  
    MediaFormat mediaFormat = MediaFormat.createVideoFormat(key_mime, w, h);

    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, (w * h) << 3);
    mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25);
    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
    mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);

    mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,MediaCodecInfo.CodecProfileLevel.MPEG4ProfileMain);
    mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    mediaCodec.start();
}

public void close() {
    try {
        mediaCodec.stop();
        mediaCodec.release();
        outputStream.flush();
        outputStream.close();
    } catch (Exception e){ 
        e.printStackTrace();
    }
}


public void offerEncoder(byte[] input) {
    try {
        ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
        ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
        int inputBufferIndex = mediaCodec.dequeueInputBuffer(0);
        if (inputBufferIndex >= 0) {
            ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
            inputBuffer.clear();
            inputBuffer.put(input);
            mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);
        }

        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
        while (outputBufferIndex >= 0) {
            ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
            byte[] outData = new byte[bufferInfo.size];
            outputBuffer.get(outData);
            outputStream.write(outData, 0, outData.length);

            mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
            outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
        }
    } catch (Throwable t) {

      }
  }
}

解决方案

The Android MediaPlayer doesn't handle raw H.264 streams.

One difficulty with such streams is that the H.264 NAL units don't have timestamp information, so unless the video frames are at a known fixed frame rate the player wouldn't know when to present them.

You can either create your own player with MediaCodec (see e.g. "Play video (TextureView)" in Grafika), or convert the raw stream to a .mp4 file. The latter requires MediaMuxer, available in API 18, or the use of a 3rd-party library like ffmpeg.

这篇关于原始输出H.264码流由媒体codeC不playble的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆