最近我将ffmpeg从0.9升级到1.0(在Win7x64和iOS上测试),现在avcodec_decode_video2
seagfaults。长话短说:每次视频尺寸发生变化时都会发生崩溃(例如,从320x240到160x120,反之亦然)。
我从某些专有来源接收mpeg4视频流,并按如下方式对其进行解码:
// once, during initialization:
AVCodec *codec_ = avcodec_find_decoder(CODEC_ID_MPEG4);
AVCodecContext ctx_ = avcodec_alloc_context3(codec_);
avcodec_open2(ctx_, codec_, 0);
AVPacket packet_;
av_init_packet(&packet_);
AVFrame picture_ = avcodec_alloc_frame();
// on every frame:
int got_picture;
packet_.size = size;
packet_.data = (uint8_t *)buffer;
avcodec_decode_video2(ctx_, picture_, &got_picture, &packet_);
同样,以上所有内容都完美运行,直到我升级到1.0。现在,每当帧尺寸发生变化时,avcodec_decode_video2
就会崩溃。请注意,我没有在AVCodecContext中指定宽度/高度 - 既不在开头,也不在流改变时 - 是否可能是原因?
我很感激任何想法!
更新:设置ctx_.width和ctx_.height无济于事。
在崩溃之前Update2:我收到以下日志消息:
mpeg4,等级24:“找到2个未发布的缓冲区!”。 等级8:“断言i< avci-> buffer_count在libavcodec / utils.c:603失败”
Update3 升级到1.1.2修复了这次崩溃。解码器能够再次应对尺寸变化。
答案 0 :(得分:3)
您可以尝试填写AVPacket::side_data
。如果更改帧大小,编解码器将从中接收信息(请参阅libavcodec/utils.c apply_param_change function
)
此结构可按如下方式填写:
int my_ff_add_param_change(AVPacket *pkt, int32_t width, int32_t height)
{
uint32_t flags = 0;
int size = 4 * 3;
uint8_t *data;
if (!pkt)
return AVERROR(EINVAL);
flags = AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS;
data = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, size);
if (!data)
return AVERROR(ENOMEM);
((uint32_t*)data)[0] = flags;
((uint32_t*)data)[1] = width;
((uint32_t*)data)[2] = height;
return 0;
}
每次尺寸变化时都需要调用此函数。
我认为这个功能最近出现了。直到我看到新的ffmpeg来源,我才知道它。
<强> UPD 强>
在编写时,解决问题的最简单方法是执行编解码器重启。只需致电avcodec_close
/ avcodec_open2
答案 1 :(得分:0)
当我的框架在运行中改变大小时,我遇到了同样的问题。但是,调用avcodec_close / avcodec_open2是超级的。更简洁的方法是在调用avcodec_decode_video2之前重置AVPacket数据结构。这是代码:
av_init_packet(&packet_)
这里的关键是此方法将AVPacket的所有值重置为默认值。查看docs了解详情。