【问题标题】:Copying a decoded ffmpeg AVFrame复制解码的 ffmpeg AVFrame
【发布时间】:2022-01-06 11:13:08
【问题描述】:

我一直在尝试复制一个 AVFrame,就像在 ffmpeg: make a copy from a decoded frame (AVFrame) 中回答的那样。但是,但我似乎无法从 av_frame_copy() 获得正返回码。

这基本上是我正在做的事情:

AVFrame *copyFrame = NULL;
copyFrame = av_frame_alloc();

int return_code = av_frame_copy(copyFrame, originalFrame);
if(return_code < 0){
    fprintf(stderr, "av_frame_copy failed with return code %d\n", return_code);
    return(1);
}

如果有帮助,我从 av_frame_copy 得到的返回码是 -22。

【问题讨论】:

  • 错误 -22 似乎意味着您的参数之一无效,根据this answer

标签: c++ c ffmpeg


【解决方案1】:

如果您阅读av_frame_copy 的文档,它会说“此函数不分配任何内容,dst 必须已经初始化并分配了与 src 相同的参数。”

av_frame_alloc 除了分配AVFrame 结构并将其初始化为一些默认值之外,什么也不做。最重要的是,它不会为帧数据分配缓冲区或准备要使用的帧。 av_frame_copy 失败,因为目标帧没有设置正确的像素格式或未分配缓冲区。

如果您想克隆帧(通过增加其引用计数器,而不是创建深层副本),您可以使用 av_frame_cloneav_frame_ref

如果你想移动框架可以使用av_frame_move_ref

但您可能想要进行适当的深层复制。这种情况下,你可以查看av_frame_make_writable的源代码。如果帧不可写,此函数会对其进行深拷贝,因此我们可以在此处使用相同的逻辑对帧进行深拷贝:

AVFrame *copyFrame = av_frame_alloc();
copyFrame->format = frame->format;
copyFrame->width = frame->width;
copyFrame->height = frame->height;
copyFrame->channels = frame->channels;
copyFrame->channel_layout = frame->channel_layout;
copyFrame->nb_samples = frame->nb_samples;
av_frame_get_buffer(copyFrame, 32);
av_frame_copy(copyFrame, frame);
av_frame_copy_props(copyFrame, frame);

请注意,我没有检查我调用的函数中的错误。你应该在你的真实代码中这样做。为简洁起见,我在这里省略了它。

【讨论】:

  • 谢谢。我阅读了文档,但一直被困在如何使用 av_frame_get_buffer() 上。我一直主要使用脚本语言,但我目前正在努力学习 C。感谢您的耐心等待。让我失望的是“int align”参数,因为我不知道 align 应该是什么。
  • 很高兴它有帮助!对齐方式取决于您正在做什么,尽管 32 对齐是非常安全的,并且几乎适用于您正在做的任何事情。一些 CPU 指令,尤其是优化例程中使用的高级 SIMD 指令,需要特定的对齐方式。您可能可以使用 1 的对齐方式,但除非您知道自己在使用对齐方式做什么,否则我建议使用 32。AVFrame.linesize 文档有更多详细信息。
【解决方案2】:

我在 GPU 上有 AVFrame *。这对我有用:

int ret;
AVFrame *dst;
dst = av_frame_alloc();

memcpy(dst,src,sizeof(AVFrame));

dst->format         = src->format;
dst->width          = src->width;
dst->height         = src->height;
dst->channels       = src->channels;
dst->channel_layout = src->channel_layout;
dst->nb_samples     = src->nb_samples;
dst->extended_data  = src->extended_data;

memcpy(dst->data, src->data, sizeof(src->data));

ret = av_frame_copy_props(dst, src);

if (ret < 0) { av_frame_unref(dst);}

【讨论】:

  • 我认为这不会稳定工作,因为 dst 中的数据没有分配,也没有深度复制。 memcpy(dst-&gt;data, src-&gt;data, sizeof(src-&gt;data)); 只复制数据指针。
  • 这样,dst->data == src->data
【解决方案3】:
        AVFrame *copyFrame = new AVFrame;
        copyFrame = av_frame_alloc();
        *copyFrame = *inAVFrame;
        if (int iRet = av_frame_copy(copyFrame, inAVFrame) == 0) {
            //av_log(NULL, AV_LOG_INFO, "Ok");
        } else {
            //av_log(NULL, AV_LOG_INFO, "Error: %s\n", AV_err2str(iRet));
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-12
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 2015-05-29
    相关资源
    最近更新 更多