解码 ffmpeg 从 mp4 文件转储的单个 (H264) 数据包

Decode a single (H264) packet dumped by ffmpeg from a mp4 file

我使用 ffmpeg 从 mp4 中的 h264 视频转储代表单个帧的数据包

ffmpeg -i video.mp4 -c copy -vframes 1 -map 0:v:0 -f data frame.bin

frame.bin 中的数据似乎没有问题,而且似乎由与 chunk/packet 中的第一个 chunk/packet 完全相同的字节组成(我不确定什么是正确的术语)来自 mdat原子.

现在我想解码那个帧。由于我知道用于创建该数据包的编解码器 (h264),我想我可以简单地准备一个编解码器上下文,将所有数据加载到一个数据包中,然后使用传统的 avcodec_send_packet(codecContext, packet) 后跟 avcodec_receive_frame() 组合.

不幸的是,对 avcodec_send_packet 的调用失败了,我收到以下错误消息

(-1094995529) Invalid data found when processing input

由于数据包数据的前 4 个字节是数据包本身的大小,我尝试在将缓冲区传递给数据包之前跳过这些字节,但也失败了。

我是跳过了某些步骤还是做错了什么?我正在尝试做的事情有可能吗? (请说是:)

ITU-T 建议书。 H.264 和附件 B

推荐 H.264 是国际电信联盟T电信标准化部门(ITU-T)定义的视频编解码器标准. 免费can be downloaded from their website

该标准定义了一种字节流格式,其最低抽象级别是NALU(网络层抽象单元)。

可以存在 32 种类型的 NALU,但约有 11 种保留或未使用。有些携带视频切片数据,有些则不携带。 两种 NALU 类型将在本次讨论的后面很重要:SPS(序列参数集)和 PPS(图片参数集)。两者都需要解码视频切片,并提供有关流的重要信息,例如其大小和原始数据的解释。

H.264 未定义这些 NALU 如何传输和成帧。但是,它确实在标准自己的附件 B 中描述了一种可能的方案。由于缺少更好的名称,该方案通常被称为 Annex B.

该方案包括在 NALU 前面加上一个易于同步的起始代码,该代码不能出现在 NALU 中:3 或 4 字节模式 00 00 0100 00 00 01。然后是 NALU 的其余部分。这种方案在硬件 and/or 流媒体情况下很流行,因为它允许轻松获取位锁定和字节对齐,定期发送 SPS/PPS “带内”,从而允许人们以一定的速度调入流随机点开始解码,并且有趣的是 属性 在 NALU 之间可以有效地发送任意数量的 0 位或字节。

ISO/IEC 14496 MPEG-4 和 AVCC

MPEG-4 是由国际标准组织 (ISO) 和国际电工委员会 (IEC) 联合制定的音频视频编码和存储标准的多个“部分”系列,称为移动图像专家组 (MPEG)。只有 MPEG-4 系列的几个部分是相关的:

  • MPEG-4 第 10 部分/高级视频编码 (AVC),在技术上与 ITU-T H.264 相同。 免费.
  • MPEG-4 第 12 部分,ISO 基本媒体文件格式 (BMFF),定义了可以专门化的通用二进制容器文件格式。 免费.
  • MPEG-4 Part 14 (MP4),专门针对一般视频的第 12 部分,并定义了 .mp4 文件扩展名和格式。这部分 非常 昂贵(88 瑞士法郎)并且 public.
  • 无法使用
  • MPEG-4 Part 15,定义了 Part 10/H.264 视频等 NALU 结构的视频数据如何存储在 Part 12 ISO BMFF 中。这部分 非常 昂贵(198 瑞士法郎),public 不可用,但它、第 14、12 和10 是常用 .mp4 容器的基础,带有 H.264 编码视频。

AVCC

不幸的是,第 15 部分也是定义 NALU 框架的新方案的部分。该方案提出将所有 SPS/PPS NALU 提取到一个名为 AVCC 的“带外”结构中,并将 NALU 前面的起始码前缀剥离并替换为(几乎总是)表示以下 NALU 的大小(以字节为单位)的 4 字节数字。

这种方案在视频数据的快速随机搜索中很流行,通过将所有视频解码器配置数据(SPS/PPS)收集到一个标准化的地方,可以在开始时配置一次视频解码器之后不用担心视频帧大小的动态变化(附件 B 允许)之类的意外惊喜。

幸运的是,在线存在有关 AVCC 结构的提示,以及在 AVCC 和 Annex B 之间进行转换的代码。

您的需求

您似乎需要 AVCC -> Annex B 转换。这可以通过 FFmpeg 的比特流过滤器来完成,h264_mp4toannexb:

ffmpeg -i INPUT.mp4 -codec copy -bsf:v h264_mp4toannexb OUTPUT.ts