从码流中获取分辨率
宽高可从SPS字段计算得到,公式如下:
width = (pic_width_in_mbs_minus1+1) * 16;
height = (2 - frame_mbs_only_flag) *(pic_height_in_map_units_minus1 +1) * 16;
但以上是针对宽高是16的整数倍的情况,当不是16整数倍时,frame_cropping_flag值为1,则调整为(计算方法参考mkvtoolnix,这里只考虑yuv420p的情况)
if (frame_cropping_flag)
{
unsigned int crop_unit_x;
unsigned int crop_unit_y;
crop_unit_x = 2;
crop_unit_y = 2 * (2 - frame_mbs_only_flag);
width -= crop_unit_x * (frame_crop_left_offset + frame_crop_right_offset);
height -= crop_unit_y * (frame_crop_top_offset + frame_crop_bottom_offset);
}
比如文件318x238分辨率(宽高必须都可以整除2)
318x238分辨率
- 第一步
width = (pic_width_in_mbs_minus1+1) * 16 = (19+1)*16 = 320;
height = (2 - frame_mbs_only_flag) *(pic_height_in_map_units_minus1 +1) * 16 = (2-1)*(14+1)*16 = 240;
- 第二步
因为frame_cropping_flag = 1,所以width和height都需要做调整。
crop_unit_x = 2;
crop_unit_y = 2 * (2 - 1) = 2;
width -= 2* (0+ 1) ;
height -= 2* (0+ 1);
即是
width -= 2;
height -= 2;
width = 320-2 = 318;
height = 240 -2 = 238;
帧率获取
-
sps 中的帧率
不是所有的编码器都带有帧率信息,在nalu 中的sps里,应为耗费带宽,通过解析nalu 中的数据结构可以发现里面有个标志位:
vui_parameters_present_flag 负责是否带帧率 -
帧率计算
framerate = time_scale/2*num_units_in_tick.
我们可以使用ffmpeg来生成码流进行测试
ffmpeg -i input.mp4 -r 15 r15.h264
ffmpeg -i input.mp4 -r 25 r25.h264
ffmpeg -i input.mp4 -r 29 r29.h264
# r15.h264
000010 timing_info_present_flag: Yes
000010 num_units_in_tick: 1 (0x00000001) - (32 bits)
000014 time_scale: 30 (0x0000001E) - (32 bits)
# r25.h264
000010 timing_info_present_flag: Yes
000010 num_units_in_tick: 1 (0x00000001) - (32 bits)
000014 time_scale: 50 (0x00000032) - (32 bits)
# r29.h264
000010 timing_info_present_flag: Yes
000010 num_units_in_tick: 1 (0x00000001) - (32 bits)
000014 time_scale: 58 (0x0000003A) - (32 bits)
网友评论