FFmpeg crop相关记录
FFmpeg crop相关:
ffmpeg frame crop分为两种情况设置
1、NALU读取SPS、PPS获取到的crop参数,avcodec_send_packet时设置,avcodec_receive_frame时获取crop参数,判断是否裁剪。
2、初始化编码器阶段(h264_decode_init)设置H264Context->width_from_caller、H264Context->height_from_caller参数,在decode(如:h264_decode_frame)阶段(init_dimensions函数)会用H264Context->width_from_caller、H264Context->height_from_caller和当前接收流的H264Context->width、H264Context->height匹配,如果小于则裁剪。
问题描述
实践发现问题:初始化codec一个尺寸,然后运行过程中切换输入流尺寸(变大)、sps、pps参数也都修改,但是输出流还是被裁剪。原因基本如上面分析所致。
static int h264_init_context(AVCodecContext *avctx, H264Context *h)
{
int i;
h->avctx = avctx;
h->cur_chroma_format_idc = -1;
h->width_from_caller = avctx->width;
h->height_from_caller = avctx->height;
略...
}
static void init_dimensions(H264Context *h)
{
const SPS *sps = (const SPS*)h->ps.sps;
int cr = sps->crop_right;
int cl = sps->crop_left;
int ct = sps->crop_top;
int cb = sps->crop_bottom;
int width = h->width - (cr + cl);
int height = h->height - (ct + cb);
av_assert0(sps->crop_right + sps->crop_left < (unsigned)h->width);
av_assert0(sps->crop_top + sps->crop_bottom < (unsigned)h->height);
/* handle container cropping */
if (h->width_from_caller > 0 && h->height_from_caller > 0 &&
!sps->crop_top && !sps->crop_left &&
FFALIGN(h->width_from_caller, 16) == FFALIGN(width, 16) &&
FFALIGN(h->height_from_caller, 16) == FFALIGN(height, 16) &&
h->width_from_caller <= width &&
h->height_from_caller <= height) {
width = h->width_from_caller;
height = h->height_from_caller;
cl = 0;
ct = 0;
cr = h->width - width;
cb = h->height - height;
} else {
h->width_from_caller = 0;
h->height_from_caller = 0;
}
略...
}
原因分析
如上
解决方案
1、解码器初始化有设置一个参数:.update_thread_context 猜测可以用来更新AVCodecContext,使得尺寸一致。
.update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context),
2、ffmpeg内部修改(不推荐),可能导致未知错误(目前还没细看解码器尺寸修改是否影响到解码数据读取、字节对齐等)。 3、修改操作方法,播放过程中修改尺寸,未从新初始化、resize理论上不太合理。