AVI、MP4和“原始”h264流中的h264。NAL单元的不同格式(或ffmpeg错误)。

10
TL;DR: 我想从AVI/MP4文件中读取原始的h264流,即使是损坏或不完整的。
几乎所有关于h264的文档都告诉我它由NAL包组成。 好的。 几乎所有地方都告诉我数据包应该以类似00 00 0100 00 00 01的签名开头。 例如:https://dev59.com/DGYr5IYBdhLWcg3w6OKd#18638298https://stackoverflow.com/a/17625537/8167678 H.264格式的格式是由NAL单元组成的,每个单元都以三个字节的起始前缀开始,值为0x00、0x00、0x01,并且每个单元具有不同的类型,具体取决于这3个起始字节之后第4个字节的值。 一个NAL单元不是视频中的一个帧,每个帧由多个NAL单元组成。
我从random_youtube_video.mp4文件中随机提取了一帧: ffmpeg -ss 10 -i random_youtube_video.mp4 -frames 1 -c copy pic.avi 结果如下所示: hexdump of AVI 红色部分是AVI容器的一部分,其他部分是实际数据。 如您所见,此处我有00 00 24 A9而不是00 00 00 01 此AVI文件可以完美播放。
我对mp4容器执行相同的操作: hexdump of mp4 如您所见,这里是完全相同的字节。 此MP4文件可以完美播放。
我尝试提取原始数据: ffmpeg -i pic.avi -c copy pic.h264 结果如下: Raw data 此文件无法在VLC中播放,即使生成此文件的ffmpeg也无法解析它: ffmpeg error 我下载了mp4流分析器并得到了以下结果: Analysis MP4Box告诉我:
 Cannot find H264 start code
 Error importing pic.h264: BitStream Not Compliant

学习H264的内部原理是非常困难的,特别是当什么都不起作用时。

因此,我有以下问题:

  1. MP4文件中实际包含哪些数据?
  2. 我必须阅读哪些内容以解码这些数据(我指的是不同的附录)?
  3. 如何读取流并从这个“损坏”的原始流中获取解码图像(即使使用ffmpeg)?

更新:

看起来是ffmpeg的错误:

当我进行双重转换时:

         ffmpeg -ss 10 -i random_youtube_video.mp4 -frames 1 -c copy pic.mp4
         ffmpeg pic.mp4 -c copy pic.h264

enter image description here

但是直接转换文件时:

ffmpeg -ss 10 -i random_youtube_video.mp4 -frames 1 -c copy pic.h264 with NALs

我有NALs签名和一个额外的NAL单元。其他字节相同(选定)。

这是一个bug吗?

更新

不,这不是一个bug,您必须使用选项-bsf h264_mp4toannexb将流保存为“Annex B”格式(带前缀)。


4
B附录比特流将具有起始码,MP4中的AVCC格式则不会。 - Gyan
@Mulvya,定义 AVCC 格式的文档是哪个? - bukkojot
1
请查看此帖子:https://dev59.com/qGAf5IYBdhLWcg3wOQi2#24890903 - Gyan
1
无关紧要。我刚刚完成了我的项目:https://github.com/bookkojot/mp4fixer - bukkojot
1
@Mulvya, VC.One,非常感谢你们。我在我的项目页面上提到了你们的名字。 - bukkojot
显示剩余4条评论
1个回答

13
我想从AVI文件中读取原始h264流,即使是损坏/不完整的。
几乎所有地方都告诉我数据包应该以类似于以下签名开头:
00 00 0100 00 00 01"
...如您所见,这里我有00 00 24 A9而不是00 00 00 01 您的H264采用AVCC格式,这意味着它使用数据大小(而不是数据起始代码)。只有Annex-B才会有您提到的签名作为起始代码。
您通过跳过帧大小来寻找帧,而不是寻找起始代码,以达到(请求的)帧的最终正确偏移量...
AVI处理:
- 读取大小(四个)字节(32位整数,小端)。 - 提取接下来的字节,直到大小为止。 - 这是您的H.264帧(以AVCC格式),解码字节以查看图像。 - 要转换为Annex-B,请尝试将H.264帧字节的前4个字节替换为00 00 00 01
考虑您显示的AVI字节(请参见第一个图片):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ................
00 00 00 00 4C 49 53 54 BA 24 00 00 6D 6F 76 69     ....LISTº$..movi
30 30 64 63 AD 24 00 00 00 00 24 A9 65 88 84 27     00dc.$....$©eˆ„'
C7 11 FE B3 C7 83 08 00 08 2A 7B 6E 59 B5 71 E1     Ç.þ³Çƒ...*{nYµqá
E3 9C 0E 73 E7 10 50 00 18 E9 25 F7 AA 7D 9C 30     ãœ.sç.P..é%÷ª}œ0
E6 2F 0F 20 00 3A 64 AA CA 5E 4F CA FF AE 20 04     æ/. .:dªÊ^OÊÿ® .
07 81 40 00 48 00 0A 28 71 21 84 48 06 18 90 0C     ..@.H..(q!„H....
31 14 57 9E 7A CD 63 A0 E0 9B 96 69 C5 18 AE F2     1.WžzÍc à›–iÅ.®ò
E6 07 02 29 01 20 10 70 A1 0F 8C BC 73 F0 78 FA     æ..). .p¡.Œ¼sðxú
9E 1D E1 C2 BF 8C 62 CE CE AC 14 5A A4 E1 45 44     ž.á¿ŒbÎά.Z¤áED
38 38 85 DB 12 57 3E F6 E0 FB AE 03 04 21 62 8D     88…Û.W>öàû®..!b.
F6 F1 1E 37 1C A2 FF 75 1C F1 02 66 0C 92 07 06     öñ.7.¢ÿu.ñ.f.’..
15 7C 90 15 6F 7D FC BD 13 1E 2B 0C 14 3C 0C 00     .|..o}ü½..+..<..
B0 EA 6F 53 B4 98 D7 80 7A 68 3E 34 69 20 D2 FA     °êoS´˜×€zh>4i Òú
F0 91 FC 75 C6 00 01 18 C0 00 3B 9A C5 E2 7D BF     ð‘üuÆ...À.;šÅâ}¿

一些解释:

  • 忽略前导的多个 00 字节。

  • 4C 49 53 54 D6 3C 00 00 6D 6F 76 69 包括 30 30 64 63 = AVI "List" 头部。

  • AD 24 00 00 == 十进制 9389 是 AVI 的 H264 项的大小(必须以 小端 读取)。

注意,AVI 字节包括...
- 记录了 的总 大小AD 24 00 00... 或者对于小端来说是反过来的:00 00 24 AD
- 接着是 的数据(00 00 24 A9 65 88 84 27 ... 等等 ... C5 E2 7D BF)。

这个 大小 包括 AVI 的 "大小" 条目的 4 个字节和 自身字节的预期长度。可以简单地写成:

AVI_Item_Size = ( 4 + item_H264_Frame.length );

AVI文件中的H.264视频帧字节

接下来是数据,即H.264视频帧。由于格式/字节布局的巧合,它也具有一个4字节的条目,用于数据大小(如果您的H264是AVCC格式,则此处应该看到起始码字节,而不是大小字节)。

与AVI字节不同,这些H264 大小字节以大端格式编写。

  • 00 00 24 A9 = 这个视频帧的字节大小(而不是起始码:00 00 00 01)。

  • 65 88 84 27 C7 11 FE B3 C7 = H.264 关键帧(总是以X5开头,其中X值基于其他设置)。

  • 记住,在四个大小字节(或甚至起始码)之后,如果跟随...

    • 字节X5 = 关键帧(IDR),例如字节65
    • 字节X1 = P或B帧,例如字节41
    • 字节X6 = SEI(补充增强信息)。
    • 字节X7 = SPS(序列参数集)。
    • 字节X8 = PPS(图像参数集)。
    • 字节00 00 00 X9 = 访问单元分隔符。

如果您在AVI文件中搜索完全相同的字节,则可以找到H.264。请参见第三张图片,这些是您的H.264字节(它们被剪切并粘贴到AVI容器中)。

有时候一个帧会被分割成不同的NAL单元。所以如果你提取了一个关键帧,但只显示了1/2或1/3的完整图像,请获取下一个或两个NAL并尝试重新解码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接