数字电视码流分析
(转)
MPEG-2
视频解码 Ffmpeg的mpeg-2视频解码(mpeg_decode_frame)过程如下:
1、读取前4个字节的头信息,一般为
00 00 01 xx,其中xx 表示:
00 —— picture_start_code //表示一帧图像的开始
01~AF —— slice_start_code//表示一个slice的开始
B0、B1—— reserved
B2 —— user_data_start_code
B3 —— sequence_header_code//表示一个sequence的开始
B4 —— sequence_error_code
B5 —— extention_start_code
B6 —— reserved
B7 —— sequence_end_code//表示一个sequence的结束
B8 —— group_start_code
B9~FF —— system_start_code
2、判断以上头信息,如果xx= B7,表示前一个sequence结束,如果解码器中的
next_picture_ptr还保存了一帧图像时,则输出该帧,且结束该次解码过程。
3、如果xx!= B7时,判断当前解码器是否支持内部组帧操作,如果支持,则组帧开始。组帧时用到两个函数:
?
int next = ff_mpeg1_find_frame_end(&s2->parse_context, buf, buf_size, NULL, avctx->parserRtStart, avctx);
?
ff_combine_frame(&s2->parse_context, next, (const uint8_t **)&buf, &buf_size)
以下为这两个函数的说明:
函数ff_mpeg1_find_frame_end:
输入参数:码流解析上下文指针parse_context传入的码流指针buf传入的码流大小buf_size
音视频解码的统一上下文指针
返回值:
如果找到头的位置,则返回头位置
+4
(即
00 00 01 xx
之后的字节);否则,返回错误信息
函数功能:
查找一个帧(
xx==00
)头。
说明:
根据状态机所处的不同状态进行转换。如果没有找到下一个帧开始符,则只将当前的数据拷贝入解析器的
buffer
中;如果找到了下一个帧的开始符,则返回;
函数
ff_combine_frame
:
输入参数:
码流解析上下文指针
parse_context
由函数
ff_mpeg1_find_frame_end
返回的下一个帧头的起始位置信息
输出参数:
组帧之后的
buf
组帧之后的数据大小
返回值:
0
——
组帧完成;
-1
——
没有得到组完的一帧数据;
4
、主体解码过程(
decode_chunks
)(状态机的转换)
4.1
寻找起始码,根据起始码的不同,进入不同的解码流程:
SEQ_START_CODE
:
表示一个序列的开始,进入
mpeg1_decode_sequence
过程。在改过程中,可以获取视频图像的大小、
帧率索引、图像宽高比、比特率信息等,对解码用到的参数进行进一步赋值等。
PICTURE_START_CODE
:
首先进行
mpeg_decode_postinit
,即进行该帧解码前的初始化工作;
之后进行
mpeg1_decode_picture
,即解码当前帧信息,获取视频的图像类型
(
注:图像类型的获取方
法为:去掉
00 00 01
00
之后的第一、二个字节,取第
11
、
12
、
13
位,该三位即为图像类型信息,
1
——
I
帧,
2
——
P
帧,
3
——
B
帧
)
、
vbv_delay
、是否关键帧等信息;
EXT_START_CODE
:
解码一些扩展信息,如:
mpeg_decode_sequence_extension
mpeg_decode_sequence_display_extension
mpeg_decode_quant_matrix_extension
mpeg_decode_picture_display_extension
mpeg_decode_picture_coding_extension
等
USER_START_CODE
:
用户数据信息解码,
mpeg_decode_user_data
。
GOP_START_CODE
:
图像组信息解码,
mpeg_decode_gop
。
SLICE_MIN_START_CODE
:
Slice
信息解码,
主函数为
mpeg_decode_slice
,
即对每一个
slice
进行解码操作,之后会分解为一个
宏块,再到一个子块。
5
、当解码完一帧信息后,需要根据当前解码的图像类型判断是否需要输出
如果当前解码的视频序列中没有
B
帧,则每编完一帧即可进行输出;
如果当前解码的视频序列中有
B
帧,则需要进行判断:
如果当前解码完成的帧为
I
或
P
帧,并且该帧之前还有一个
I
或
P
帧没有输出,则输出其前一个
I
或
P
帧(若当前帧为第一帧则不用输出);如果当前解码完成的帧为
B
帧,则输出该帧。参考如下:
I B B P B B P B B P B B P
……
(显示顺序)
I P B B P B B P B B P B B
……
(编码顺序)
同样,
I P B B P B B P B B P B B
……
(解码顺序)
I B B P B B P B B P B B P
……
(还原显示顺序)