How to crop AvFrame using ffmpeg's functions

2019-07-29 22:53发布

I wanna crop a picture by using the ffmpeg's functions(like av_picture_crop or vf_crop), not command line utility.

Is there any one knows how to do it?

Do you have the source code for this function?

标签: ffmpeg
1条回答
Deceive 欺骗
2楼-- · 2019-07-29 23:04

av_picture_crop() is deprecated.

To use vf_crop, use the buffer and buffersink filters in libavfilter:

#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;
}

Don't forget to unref the returned (croppped) frame using av_frame_free(). The input frame data is untouched so if you don't need it beyond this function, you need to av_frame_free() the input frame also.

If you intend to crop many frames, try to retain the filter graph between frames and only reset it (or recreate it) when the frame size/format changes. I'm leaving it up to you to figure out how to do that.

查看更多
登录 后发表回答