如何使用ffmpeg函数裁剪AvFrame

时间:2016-06-29 12:22:45

标签: ffmpeg

我想使用ffmpeg的函数(如av_picture_crop或vf_crop)裁剪图片,而不是命令行实用程序。

有没有人知道怎么做?

你有这个功能的源代码吗?

1 个答案:

答案 0 :(得分:3)

av_picture_crop()deprecated

要使用vf_crop,请使用libavfilter中的bufferbuffersink过滤器:

#include "libavfilter/avfilter.h"

static AVFrame *crop_frame(const AVFrame *in, int left, int top, int right, int bottom)
{
    AVFilterContext *buffersink_ctx;
    AVFilterContext *buffersrc_ctx;
    AVFilterGraph *filter_graph = avfilter_graph_alloc();
    AVFrame *f = av_frame_alloc();
    AVFilterInOut *inputs = NULL, *outputs = NULL;
    char args[512];
    int ret;
    snprintf(args, sizeof(args),
             "buffer=video_size=%dx%d:pix_fmt=%d:time_base=1/1:pixel_aspect=0/1[in];"
             "[in]crop=x=%d:y=%d:out_w=in_w-x-%d:out_h=in_h-y-%d[out];"
             "[out]buffersink",
             frame->width, frame->height, frame->format,
             left, top, right, bottom);

    ret = avfilter_graph_parse2(filter_graph, args, &inputs, &outputs);
    if (ret < 0) return NULL;
    assert(inputs == NULL && outputs == NULL);
    ret = avfilter_graph_config(filter_graph, NULL);
    if (ret < 0) return NULL;

    buffersrc_ctx = avfilter_graph_get_filter(filter_graph, "Parsed_buffer_0");
    buffersink_ctx = avfilter_graph_get_filter(filter_graph, "Parsed_buffersink_2");
    assert(buffersrc_ctx != NULL);
    assert(buffersink_ctx != NULL);

    av_frame_ref(f, in);
    ret = av_buffersrc_add_frame(buffersrc_ctx, f);
    if (ret < 0) return NULL;
    ret = av_buffersink_get_frame(buffersink_ctx, f);
    if (ret < 0) return NULL;

    avfilter_graph_free(&filter_graph);

    return f;
}

请勿忘记使用av_frame_free()取消返回(裁剪)的框架。输入帧数据不受影响,因此如果您不需要此功能,则还需要av_frame_free()输入帧。

如果您打算裁剪多个帧,请尝试在帧之间保留过滤器图形,并在帧大小/格式更改时仅重置(或重新创建)。我想让你知道如何做到这一点。