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

2023-11-24

TL;DR:我想从 AVI/MP4 文件读取原始 h264 流,甚至是损坏/不完整的。

几乎所有有关 h264 的文档都告诉我它由 NAL 数据包组成。好的。几乎所有地方都告诉我,数据包应该以这样的签名开头00 00 01 or 00 00 00 01。例如,https://stackoverflow.com/a/18638298/8167678, https://stackoverflow.com/a/17625537/8167678

H.264的格式是由NAL单元组成,每个单元开始 具有三个字节的起始前缀,值为 0x00、0x00、0x01 每个单位都有不同的类型,具体取决于第四个的值 这 3 个起始字节之后的字节。一个 NAL 单元不是一帧 视频中,每一帧由多个NAL单元组成。

Okay.

我下载了 random_youtube_video.mp4 并从中删除一帧:

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

And got: hexdump of AVI Red part - this is part of AVI container, other - actual data. As you can see, here I have 00 00 24 A9 instead of 00 00 00 01

这个AVI文件可以完美播放

I do same for mp4 container: hexdump of mp4

正如您所看到的,这里的字节完全相同。这个MP4文件可以完美播放

I try to strip out raw data: ffmpeg -i pic.avi -c copy pic.h264 Raw data

This file can't play in VLC or even ffmpeg, which produced this file, can't parse it: ffmpeg error

I downloaded mp4 stream analyzer and got: Analysis

MP4Box告诉我:

 Cannot find H264 start code
 Error importing pic.h264: BitStream Not Compliant

当什么都不起作用时,学习 h264 的内部结构是非常困难的。

所以,我有疑问:

  1. mp4里面的实际数据是什么?
  2. 我必须阅读什么来解码该数据(我的意思是不同的附件)
  3. 如何从这个“损坏的”原始流中读取流并获取解码图像(即使使用 ffmpeg)?

UPDATE:

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

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

这是错误?

UPDATE

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


“我想从 AVI 文件中读取原始 h264 流,甚至是损坏/不完整的文件。”

“几乎所有地方都告诉我,数据包应该以如下签名开头:
00 00 01 or 00 00 00 01"

“......如你所见,我在这里00 00 24 A9代替00 00 00 01"

您的 H264 是 AVCC 格式,这意味着它使用数据sizes(而不是数据起始码)。只有附件 B 才会有您提到的签名作为起始代码。

您寻找帧,不是通过寻找起始代码,而是只是跳过帧大小以达到(请求的)帧的最终正确偏移量......

AVI 处理:

  • 读取大小(四)字节(32 位整数,小尾数法).

  • 提取接下来的字节,直至达到 size amount。

  • 这是您的 H.264 帧(AVCC 格式),解码字节以查看图像。

  • 要转换为附件 B,请尝试替换 H.264 的前 4 个字节帧字节 with 00 00 00 01.

考虑您显示的 AVI 字节(请参阅first图片) :

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     [email protected]..(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 bytes.

  • 4C 49 53 54 D6 3C 00 00 6D 6F 76 69包括30 30 64 63= AVI“列表”标题。

  • AD 24 00 00== 小数9389是AVI自己的H264项目大小(必须读入小尾数法).

请注意,AVI 字节包括...
-的一个注释item总计size (AD 24 00 00...或反转为 Little Endian :00 00 24 AD)
-其次是item data (00 00 24 A9 65 88 84 27 ... etc ... C5 E2 7D BF).

This size包括 AVI 的 4 个字节”size" 条目 + 预期字节长度item自己的字节。可以简单地写为:

AVI_Item_Size = ( 4 + item_H264_Frame.length );

AVI 中的 H.264 视频帧字节 :

接下来是item数据,即 H.264视频帧。由于格式/字节布局的纯粹巧合,它也包含一个 4 字节条目data's size(由于您的 H264 是 AVCC 格式,如果它是附件 B,那么您将在此处看到起始代码字节而不是大小字节)。

与 AVI 字节不同,这些 H264size字节被写入大尾数法 format.

  • 00 00 24 A9= 该视频帧的字节大小(而不是起始代码:00 00 00 01).

  • 65 88 84 27 C7 11 FE B3 C7= H.264keyframe(始终以 X5 开头,其中X值基于其他设置)。

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

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

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

有时,一个帧会被分割成不同的 NAL 单元。因此,如果您提取关键帧并且它仅显示 1/2 或 1/3 而不是完整图像,只需抓取下一个或两个 NAL 并重新尝试解码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AVI、MP4 和“原始”h264 流中的 h264。 NAL 单元格式不同(或 ffmpeg bug) 的相关文章

  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • 根据属性的类型使用文本框或复选框

    如果我有这样的结构 public class Parent public string Name get set public List
  • 机器Epsilon精度差异

    我正在尝试计算 C 中双精度数和浮点数的机器 epsilon 值 作为学校作业的一部分 我在 Windows 7 64 位中使用 Cygwin 代码如下 include
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi

随机推荐