场景
指定海康摄像机的分辨率是1920*1080P,I帧间隔是25,视频帧率是25fps。查看AVFormatContext结构体中streams数组中的第一个元素codec
codec_id=AV_CODEC_ID_H264, width=1920, height=1080, coded_with=1920, coded_height=1088, pix_fmt=AV_PIX_FMT_YUVJ420P
疑问
coded_height为什么不是1080
解答
当前SPS的帧的宽 = (sps_info.pic_width_in_mbs_minus1 + 1) * 16
当前SPS的帧的高 = (sps_info.pic_height_in_map_units_minus1 + 1) * 16
通过如下代码计算得到的宽高(1888 x 1920)却不完全等同于源视频的宽高(1920 x 1080)。
根据编码规则计算到的宽高是1920x1088,而MP4中读取的是1920x1080。那么,如何FFmpeg是如何修正SPS里的宽高计算呢?
实际上,SPS还有crop系列字段,由crop表示帧是否被裁剪、crop_left、crop_right、crop_top和crop_bottom表示要裁剪的值得到正确的宽高值。
相关知识
sps和pps的结构参考:h264编码 里面的Sequence parameter set RBSP syntax
0x00000001或者0x000001是起始码,0x67是sps的开头,0x68是pps的开头。
0x42代表profile_idc,后面八位是constraint_set0_flag和reserved_zero_4bits,都设为0,0x0a是level_idc,
接着后面为图方便能用0表示的都用了。这里要注意是ue(v)表示该域是可变位,使用的指数-哥伦布编码
我的目的主要是设置正确帧高度和帧高度,所以只要填充 pic_width_in_mbs_minus1和 pic_height_in_map_units_minus1,
将它们的十六进制数写入sps_pps,
如果宽度和高度不是16的倍数,要填frame_cropping_flag
参考
http://m.blog.youkuaiyun.com/stn_lcd/article/details/74390636
http://m.blog.youkuaiyun.com/leixiaohua1020/article/details/45001033
static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_slice)
{
const SPS *sps;
int needs_reinit = 0, must_reinit, ret;
if (first_slice) {
av_buffer_unref(&h->ps.pps_ref);
h->ps.pps = NULL;
h->ps.pps_ref = av_buffer_ref(h->ps.pps_list[sl->pps_id]);
if (!h->ps.pps_ref)
return AVERROR(ENOMEM);
h->ps.pps = (const PPS*)h->ps.pps_ref->data;
}
if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
av_buffer_unref(&
指定海康摄像机的分辨率是1920*1080P,I帧间隔是25,视频帧率是25fps。查看AVFormatContext结构体中streams数组中的第一个元素codec
codec_id=AV_CODEC_ID_H264, width=1920, height=1080, coded_with=1920, coded_height=1088, pix_fmt=AV_PIX_FMT_YUVJ420P
疑问
coded_height为什么不是1080
解答
当前SPS的帧的宽 = (sps_info.pic_width_in_mbs_minus1 + 1) * 16
当前SPS的帧的高 = (sps_info.pic_height_in_map_units_minus1 + 1) * 16
通过如下代码计算得到的宽高(1888 x 1920)却不完全等同于源视频的宽高(1920 x 1080)。
根据编码规则计算到的宽高是1920x1088,而MP4中读取的是1920x1080。那么,如何FFmpeg是如何修正SPS里的宽高计算呢?
实际上,SPS还有crop系列字段,由crop表示帧是否被裁剪、crop_left、crop_right、crop_top和crop_bottom表示要裁剪的值得到正确的宽高值。
相关知识
sps和pps的结构参考:h264编码 里面的Sequence parameter set RBSP syntax
0x00000001或者0x000001是起始码,0x67是sps的开头,0x68是pps的开头。
0x42代表profile_idc,后面八位是constraint_set0_flag和reserved_zero_4bits,都设为0,0x0a是level_idc,
接着后面为图方便能用0表示的都用了。这里要注意是ue(v)表示该域是可变位,使用的指数-哥伦布编码
我的目的主要是设置正确帧高度和帧高度,所以只要填充 pic_width_in_mbs_minus1和 pic_height_in_map_units_minus1,
将它们的十六进制数写入sps_pps,
如果宽度和高度不是16的倍数,要填frame_cropping_flag
参考
http://m.blog.youkuaiyun.com/stn_lcd/article/details/74390636
http://m.blog.youkuaiyun.com/leixiaohua1020/article/details/45001033
static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_slice)
{
const SPS *sps;
int needs_reinit = 0, must_reinit, ret;
if (first_slice) {
av_buffer_unref(&h->ps.pps_ref);
h->ps.pps = NULL;
h->ps.pps_ref = av_buffer_ref(h->ps.pps_list[sl->pps_id]);
if (!h->ps.pps_ref)
return AVERROR(ENOMEM);
h->ps.pps = (const PPS*)h->ps.pps_ref->data;
}
if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
av_buffer_unref(&