You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FFmpeg中sws_scale后的AVFrame调用av_frame_copy返回-22如何解决

问题原因

返回值-22对应EINVAL(无效参数),触发原因是你调用av_frame_alloc()仅分配了AVFrame结构体本身的内存,没有为目标帧的像素数据分配实际缓冲区,也没有同步源帧的格式、宽高等核心参数。av_frame_copy()只会拷贝像素数据,不会自动完成缓冲区分配和参数同步,因此参数校验失败返回错误。
av_frame_clone()内部会自动完成参数同步、缓冲区分配、数据拷贝全流程,它返回空说明你的源frameYUV本身的核心参数(格式、宽、高)存在非法值,需要先校验源帧的合法性。

正确复制流程(完全独立备份,新旧帧修改互不影响)
  1. 分配空AVFrame结构体
  2. 同步源帧的核心格式参数
  3. 为目标帧分配像素数据缓冲区
  4. 拷贝元数据和像素数据
修正后的代码示例
if ( packet && packet->stream_index == this->ctl->index )
{
    if ( avcodec_send_packet(this->ctl->context, packet) == 0 )
    {
        while (1)
        {
            int ret = avcodec_receive_frame(this->ctl->context, this->ctl->frame);

            if ( ret == AVERROR(EAGAIN) || ret == AVERROR_EOF )
            {
                break;
            }

            if ( ret == 0 )
            {
                sws_scale(this->ctl->convertCtx, (const unsigned char* const*)this->ctl->frame->data, this->ctl->frame->linesize, 0, this->ctl->context->height, this->ctl->frameYUV->data, this->ctl->frameYUV->linesize);

                // 先校验源帧合法性,避免后续操作失败
                if (this->ctl->frameYUV->width <= 0 || this->ctl->frameYUV->height <= 0 || this->ctl->frameYUV->format < 0) {
                    break;
                }

                AVFrame* nf = av_frame_alloc();
                if (!nf) {
                    // 结构体分配失败,自行补充错误处理逻辑
                    break;
                }
                // 同步源帧核心参数
                nf->format = this->ctl->frameYUV->format;
                nf->width = this->ctl->frameYUV->width;
                nf->height = this->ctl->frameYUV->height;
                // 分配像素数据缓冲区,第二个参数为对齐值,0表示自动选择默认对齐
                ret = av_frame_get_buffer(nf, 0);
                if (ret < 0) {
                    av_frame_free(&nf);
                    // 缓冲区分配失败,自行补充错误处理逻辑
                    break;
                }
                // 拷贝元数据
                int re1 = av_frame_copy_props(nf, this->ctl->frameYUV);
                // 拷贝像素数据
                int re2 = av_frame_copy(nf, this->ctl->frameYUV);

                qDebug("result %d == %d ", re1, re2);

                emit decodeVideoFrame(this->ctl->frameYUV);

                usleep(21750);

            }
        }
    }
}
可选简化方案
  • 如果不需要完全独立的缓冲区,只是要延长源帧的生命周期,可以用av_frame_ref(nf, this->ctl->frameYUV),此时新旧帧共享像素缓冲区,修改其中一帧会影响另一帧,不需要的时候分别调用av_frame_free()释放即可。
  • 如果源帧参数完全合法,av_frame_clone(this->ctl->frameYUV)可以替代上面所有分配、参数同步、拷贝的流程,返回的帧就是完全独立的备份,只需要后续记得释放即可。如果该接口返回空,优先排查源frameYUV的初始化逻辑,确认你在分配frameYUV的时候有没有正确设置format/width/height参数,再调用av_frame_get_buffer分配缓冲区。

内容的提问来源于stack exchange,提问作者anduinChan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 16:15:02