我正在使用mediacodec
解码samsung S6上的h264流,android 5.1.1,发现mediacodec的输入缓冲区必须以" 0001"开头#(并且不需要)设置pps,sps),或者ACodec将报告错误。
我还尝试使用mediaextractor播放mp4文件,它工作正常,但mediacodec的缓冲区不是以" 0001"开头。
我不知道为什么解码h264流有这样的限制,目前我需要分析来自套接字的流,并将数据切割成小包(每个包以0001开头),然后将它们交给mediacodec,但效率低下。
MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1024, 1024);
答案 0 :(得分:0)
某些特定解码器也可以解码“mp4”格式的H264 NAL单元(使用不同类型的起始码),但并非所有设备都能保证这一点。
如果他们知道自己的解码器可以处理它,那么三星的MediaExtractor版本可能会以这种格式返回它。至少早先的先例是三星用他们的MediaExtractor版本做了相同的,非标准的时间戳,参见例如https://code.google.com/p/android/issues/detail?id=74356
(让MediaExtractor返回只有当前设备的解码器可以处理的数据是错误的IMO,因为人们可能想要使用MediaExtractor来读取文件,但是通过网络将压缩数据发送到另一个设备进行解码,并且在这些中例如,以非标准格式返回数据是错误的。)
正如fadden所写,MediaCodec在完整的NAL单元上运行,因此您需要以这种格式提供数据(即使您认为效率低下)。如果您通过套接字接收的数据格式不容易获得此信息(关于帧边界),那么这是您的协议格式的问题(例如,实现RTP接收并不容易!),而不是MediaCodec本身 - 它是在解码之前需要拥有完整帧的一个非常常见的限制,而不是在你有一个完整的帧之前能够提供随机块。除非您自己的实现效率低下,否则这不应该是低效的。
答案 1 :(得分: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进行视频解码,请记住这一点。除了任何更多自定义或低级别的东西之外,它的一切都很棒。