使用没有MediaExtractor的MediaCodec解码mp4 / h.264,预期的访问单元格式

时间:2014-08-06 12:41:20

标签: android mp4 h.264 mediacodec

我正在尝试使用MediaCodec API进行解码而不使用MediaExtractor API。相反,我使用mp4parser从mp4文件中获取样本。目前,我只使用h.264 / avc编码的视频内容。

MediaCodec API州的官方文件:

  

缓冲区不会在任意字节边界上开始和结束,这不是字节流,而是访问单元流。

意思是,我必须将访问单元提供给解码器。但是,我想念这些信息中的一些细节:

对于h.264,在mp4样本中,可以有多个NAL单元,每个单元前面都有4个(默认)字节,用于指定NAL单元长度。

现在我的问题:

  1. 可以有mp4样本,其中编解码器配置NAL单元(sps,pps)与包含编码(部分)帧的NAL单元混合。在这种情况下,我应该在BUFFER_FLAG_CODEC_CONFIG的电话中通过标记queueInputBuffers()吗?

  2. mp4样本中还可以有其他(附加)NAL单元,如SEI或访问单元分隔符NAL单元。那些呢?没问题?

  3. 我尝试了不同的可能性,但我从Android获得的所有反馈都是dequeueOutputBuffer()的调用超时(或者如果我作为超时参数传递-1则不会返回)。因此,我似乎无法解决此问题。

    任何建议做什么或在哪里看都是非常受欢迎的。

2 个答案:

答案 0 :(得分:6)

NAL长度前缀,指定在传递给MediaCodec进行解码之前需要将NAL单元长度转换为Annex-B起始码(字节0x00,0x00,0x00,0x01)。 (有些解码器可能会立即接受MP4格式,但这并不常见。)

存储在文件中avcC原子中的SPS / PPS也需要转换为使用Annex-B启动码。请注意,avcC atom包含一些您不需要传递给解码器的其他字段。您可以在发送任何实际帧之前将SPS和PPS打包在一个缓冲区(在每个缓冲区之前使用启动码)并设置BUFFER_FLAG_CODEC_CONFIG标志,或者在用于配置解码器的MediaFormat中传递它们(带有附件B启动码) (在一个ByteBuffer中使用键“csd-0”,或者在两个单独的键中作为“csd-0”和“csd-1”)。

如果你的文件在每个帧中有更多的SPS / PPS,你应该能够将它们作为帧的一部分传递,并且大多数解码器应该能够应对它(特别是如果它与SPS / PPS相同)之前而不是配置更改。)

因此:将属于一个样本的所有NAL单元传递到一个缓冲区中,但将所有NAL单元长度标头重写为startcodes。并且要处理在流本身内没有碰巧有SPS / PPS的MP4文件,解析avcC原子(我不知道mp4parser以哪种格式返回)并将带有启动码的SPS和PPS传递给解码器(通过MediaFormat作为“csd-0”或作为第一个缓冲区,设置BUFFER_FLAG_CODEC_CONFIG)。

答案 1 :(得分:0)

获得-1是正常的只是进行解码你应该看到屏幕上的东西。只要它不抛出IllegalState异常就进行解码