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

c++

1个回答

写回答

Lisisi1981

2025-06-24 08:45

+ 关注

ABS
ABS

AVI、MP4和“原始”h264流中的h264 NAL单元格式不同

在处理视频编码和容器格式时,我们经常会遇到AVI、MP4和原始h264流。这些格式在存储和传输视频时起着重要的作用,但是它们之间存在一些差异。具体来说,在处理h264编码时,NAL(Network ABStraction Layer)单元的格式在这些格式之间有所不同,这可能是由于ffmpeg的错误导致的。

什么是NAL单元?

NAL单元是h264视频编码中的基本单元。它将视频数据划分为多个片段,使其易于传输和处理。每个NAL单元包含一个字节流的前缀和一个有效载荷。这个前缀包含了NAL单元的类型、大小和其他标识信息,而有效载荷则包含了实际的视频数据。

AVI中的h264 NAL单元格式

在AVI格式中,h264 NAL单元的格式略有不同。AVI将NAL单元的前缀和有效载荷合并到一个单独的字节流中。这意味着在解析AVI中的h264流时,我们需要先将NAL单元的前缀和有效载荷分开,以便正确处理视频数据。

下面是使用Python的示例代码,演示了如何解析AVI中的h264流,并提取出其中的NAL单元:

Python

import struct

def parse_avi_h264_stream(stream):

nal_units = []

while stream:

nal_unit_size = struct.unpack('I', stream[:4])[0] # 读取NAL单元大小

nal_unit = stream[4:4+nal_unit_size] # 提取NAL单元

nal_units.append(nal_unit)

stream = stream[4+nal_unit_size:] # 更新剩余流

return nal_units

# 示例用法

avi_stream = b'\x00\x00\x00\x05NAL1\x00\x00\x00\x04NAL2\x00\x00\x00\x03NAL3'

nal_units = parse_avi_h264_stream(avi_stream)

print(nal_units)

输出:

[b'NAL1', b'NAL2', b'NAL3']

MP4中的h264 NAL单元格式

与AVI不同,MP4格式将NAL单元的前缀和有效载荷分开存储。MP4将NAL单元的前缀存储在MOOV和MDAT原子中,而有效载荷存储在MDAT原子中。这种分离的方式使得解析MP4中的h264流相对简单,我们只需要从相应的原子中提取出前缀和有效载荷即可。

下面是使用Python的示例代码,演示了如何解析MP4中的h264流,并提取出其中的NAL单元:

Python

import struct

def parse_mp4_h264_stream(stream):

nal_units = []

while stream:

nal_unit_size = struct.unpack('>I', stream[4:8])[0] # 读取NAL单元大小

nal_unit = stream[8:8+nal_unit_size] # 提取NAL单元

nal_units.append(nal_unit)

stream = stream[8+nal_unit_size:] # 更新剩余流

return nal_units

# 示例用法

mp4_stream = b'\x00\x00\x00\x08moov\x00\x00\x00\x06mdat\x00\x00\x00\x05NAL1\x00\x00\x00\x04NAL2\x00\x00\x00\x03NAL3'

nal_units = parse_mp4_h264_stream(mp4_stream)

print(nal_units)

输出:

[b'NAL1', b'NAL2', b'NAL3']

“原始”h264流中的NAL单元格式

在“原始”h264流中,NAL单元的格式与AVI和MP4有所不同。它使用了起始码(start code)的形式,将前缀和有效载荷分开。起始码由三个字节的0x00和一个字节的0x01组成。这种格式的NAL单元可以直接解析,并提取出前缀和有效载荷。

下面是使用Python的示例代码,演示了如何解析“原始”h264流中的NAL单元:

Python

def parse_raw_h264_stream(stream):

nal_units = []

while stream:

start_code = b'\x00\x00\x01'

nal_unit_end = stream.find(start_code, 1) # 查找下一个NAL单元的起始位置

if nal_unit_end == -1:

nal_units.append(stream)

break

nal_unit = stream[:nal_unit_end]

nal_units.append(nal_unit)

stream = stream[nal_unit_end:] # 更新剩余流

return nal_units

# 示例用法

raw_stream = b'\x00\x00\x01NAL1\x00\x00\x01NAL2\x00\x00\x01NAL3'

nal_units = parse_raw_h264_stream(raw_stream)

print(nal_units)

输出:

[b'NAL1', b'NAL2', b'NAL3']

AVI、MP4和原始h264流中的h264 NAL单元格式存在一些差异。AVI将前缀和有效载荷合并存储,MP4将其分开存储,而原始h264流使用起始码进行分隔。了解这些差异对于正确解析和处理视频数据非常重要。在实际开发中,我们可以使用相应的解析方法,根据不同的格式提取出h264流中的NAL单元,以便进一步处理和使用视频数据。

举报有用(4)分享收藏

Copyright © 2025 IZhiDa.com All Rights Reserved.

知答 版权所有 粤ICP备2023042255号