1

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

我还尝试使用 mediaextractor 播放 mp4 文件,它工作正常,但媒体编解码器的缓冲区不是以“0001”开头。

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

MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1024, 1024);
4

2 回答 2

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 最终单位手动解析分辨率。

// 注意我在这里使用 Xamarin。但是电话和事情几乎是一样的。我相当肯定 iOS VideoToolbox Xamarin Wrapper 中存在错误,所以是的。如果您曾经考虑将 Xamarin 用于视频解码,请记住这一点。它适用于一切,但任何稍微更定制或低级的东西。

于 2016-06-22T10:15:12.600 回答
0

一些特定的解码器也可能能够以“mp4”格式(使用不同类型的起始码)解码 H264 NAL 单元,但这并不能保证在所有设备上。

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

(不过,让 MediaExtractor 返回只有当前设备的解码器可以处理的数据是错误的 IMO,因为人们可能希望使用 MediaExtractor 读取文件但通过网络将压缩数据发送到另一台设备进行解码,在这些情况下,返回非标准格式的数据是错误的。)

正如 fadden 所写,MediaCodec 虽然在完整的 NAL 单元上运行,所以您需要以这种格式提供数据(即使您认为它效率低下)。如果您通过套接字接收的数据格式不容易获得此信息(关于帧边界),那么这是您的协议格式的问题(例如,实现 RTP 接收并不容易!),而不是 MediaCodec 本身 - 它是一个非常常见的限制是在解码之前需要有完整的帧,而不是在你有一个完整的帧之前能够提供随机块。除非您自己的实现效率低下,否则这不应该是低效的。

于 2016-06-16T05:37:58.573 回答