2016-06-15 198 views
0

我正在使用mediacodec解码samsung S6,android 5.1.1上的h264流,发现输入缓冲区mediacodec必须以“0001”开头(并且不需要设置pps,sps) ,否则ACodec会报告错误。mediacodec解码h264流限制

我也尝试使用mediaextractor来播放mp4文件,它工作正常,但mediacodec的缓冲区不是以“0001”开头的。

我不知道为什么decodec h264流有这样的限制,目前我需要分析来自socket的流,并将数据分成小包(每个包以0001开头),然后将它们提供给mediacodec,但这是低效的。

MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1024, 1024); 
+0

MediaCodec在NAL单元上运行。它需要启动前缀。比照http://stackoverflow.com/questions/1685494/what-does-this-h264-nal-header-mean – fadden

回答

0

一些具体的解码器也能够在“MP4”的格式(与不同种类的起始码)的解码H264的NAL单元,但不是所有的设备保证。

如果三星的MediaExtractor版本知道他们自己的解码器可以处理它,那么它可能会以这种格式返回它。至少有一个先例,三星与MediaExtractor的版本做了同样的,非标准的事情,并带有时间戳,参见例如。 https://code.google.com/p/android/issues/detail?id=74356

(有MediaExtractor返回数据,只有当前设备的解码器可以处理是错误的IMO,但是,因为人们可能想使用MediaExtractor读取文件,但通过网络发送压缩数据到另一个设备解码,并在这些情况下,以非标准格式返回数据是错误的。)作为fadden写道,尽管MediaCodec运行在完整的NAL单元上,所以您需要以这种格式提供数据(即使您认为它感觉效率低下)。如果您通过套接字接收数据的格式并不容易获取此信息(关于帧边界),那么这就是您协议格式的问题(例如,实现RTP接收并不容易!),而不是MediaCodec本身 - 它是这是一个非常常见的限制,需要在解码之前拥有全帧,而不是在有全帧之前才能提供随机块。除非你自己实施它是低效的,否则这不应该是低效率的。

0

一般来说,android会为每个输入指定nal个单位。对于某些设备,我发现在h264的媒体格式上设置csd-0/1的功能不一致。但是,如果您将每个参数集作为输入缓冲区提供,则媒体编解码器会将其作为格式更改进行提取。

int outputBufferIndex = NativeDecoder.DequeueOutputBuffer (info, 1000); 
if (outputBufferIndex == (int)MediaCodec.InfoOutputFormatChanged) { 
    Console.WriteLine ("Format changed: {0}", NativeDecoder.OutputFormat); 
} else if (outputBufferIndex >= 0) { 
    CodecOutputBufferAvailable (NativeDecoder, outputBufferIndex, info); 
} 

还要注意它是强制性的Nexus和其他一些三星设备的设置:

formatDescription.SetInteger(MediaFormat.KeyWidth, SelectedPalette.Value.Width); 
formatDescription.SetInteger(MediaFormat.KeyHeight, SelectedPalette.Value.Height); 
formatDescription.SetInteger(MediaFormat.KeyMaxInputSize, SelectedPalette.Value.Width * SelectedPalette.Value.Height); 

我很幸运,在我的情况,我可以查询这些决议。但是,您可以从SPS和PPS nal单元手动解析分辨率。

//注意我在这里使用Xamarin。但电话和事情几乎相同。我相当确定在iOS VideoToolbox Xamarin Wrapper中存在错误,所以是的。请记住,如果您曾考虑Xamarin进行视频解码。它适用于任何事物,但稍微更加自定义或低级的事物。