当前位置:   article > 正文

FFMPEG视频滤镜(一)_ffmpeg rotate

ffmpeg rotate

前言

介绍FFmpeg中旋转rotate、拼接hstack、翻转hflip、边缘edgedetect视频滤镜的使用方法。

1、 旋转滤镜

1.1 名称rotate
1.2 语法:-angle:旋转角度,-ow:输出图像宽度,-oh:输出图像高度;如:"angle=0.5*PI:ow=1920:oh=1080"
1.3 其他:若需要实时旋转图像,则需要动态创建和销毁滤镜。
1.4 示例代码

static int initFilter(AVCodecContext * codecContext0, AVCodecContext * codecContext1, double angle)
{
    int ret = 0;
    const AVFilter *bufSrc = NULL;
    const AVFilter *rotate  = NULL;
    const AVFilter *bufSink = NULL;
    AVFilterInOut *input = NULL;
    AVFilterInOut *output = NULL;

    char args[128] = {0};
    if(NULL == filterGraph)
        filterGraph = avfilter_graph_alloc();
    else
    {
        return true;
    }
    input  = avfilter_inout_alloc();
    output = avfilter_inout_alloc();
    bufSrc = avfilter_get_by_name("buffer");
    rotate  = avfilter_get_by_name("rotate");
    bufSink = avfilter_get_by_name("buffersink");

    if(NULL == filterGraph || NULL == input || NULL == output)
    {
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "alloc  failed! :" << endl;
        return false;
    }
    if(NULL == bufSrc || NULL == bufSink)
    {
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_get_by_name  failed! :" << endl;
        return false;
    }
    snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", codecContext0->width, codecContext0->height, codecContext0->pix_fmt, 1, 25, 1, 25);
//    cout << args << endl;
    // src 0
    ret = avfilter_graph_create_filter(&bufSrcContext[0], bufSrc, "in0", args, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }
    // rotate
    snprintf(args, sizeof(args), "angle=%f*PI:ow=%d:oh=%d", angle/double(180)
             , codecContext0->width+20*16, codecContext0->height+40*16);
    cout << args << endl;
    ret = avfilter_graph_create_filter(&rotateContext, rotate, "rotate", args, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }
    // sink
    ret = avfilter_graph_create_filter(&bufSinkContext, bufSink, "out", NULL, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }

    ret = avfilter_link(bufSrcContext[0], 0, rotateContext, 0);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_link  failed! :" << buf << endl;
        return false;
    }
    ret = avfilter_link(rotateContext, 0, bufSinkContext, 0);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_link  failed! :" << buf << endl;
        return false;
    }

    ret = avfilter_graph_config(filterGraph, NULL);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_config  failed! :" << buf << endl;
        return false;
    }

    if(input->next) avfilter_inout_free(&input->next);
    if(input )avfilter_inout_free(&input);
    if(output) avfilter_inout_free(&output);
    return true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

2、 左右拼接滤镜

2.1 名称hstack
2.2 语法:-inputs:输出源数量;如:"inputs=2"
2.3 其他:1)拼接后尺寸会变大,为输入源尺寸的和,buffer in0 + buffer in1;2)引申:上下拼接滤镜vstack
2.4 示例代码

static int initFilter(AVCodecContext * codecContext0, AVCodecContext * codecContext1)
{
    int ret = 0;
    const AVFilter *bufSrc = NULL;
    const AVFilter *hstack  = NULL;
    const AVFilter *bufSink = NULL;
    AVFilterInOut *input = NULL;
    AVFilterInOut *output = NULL;

    char args[128] = {0};
    if(NULL == filterGraph)
        filterGraph = avfilter_graph_alloc();
    else
    {
        return true;
    }
    input  = avfilter_inout_alloc();
    output = avfilter_inout_alloc();
    bufSrc = avfilter_get_by_name("buffer");
    hstack = avfilter_get_by_name("hstack");
    bufSink = avfilter_get_by_name("buffersink");

    if(NULL == filterGraph || NULL == input || NULL == output)
    {
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "alloc  failed! :" << endl;
        return false;
    }
    if(NULL == bufSrc || NULL == bufSink)
    {
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_get_by_name  failed! :" << endl;
        return false;
    }
    snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", codecContext0->width, codecContext0->height, codecContext0->pix_fmt, 1, 25, 1, 25);
    cout << args << endl;
    // src 0
    ret = avfilter_graph_create_filter(&bufSrcContext[0], bufSrc, "in0", args, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }
    snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", codecContext0->width, codecContext0->height, codecContext0->pix_fmt, 1, 25, 1, 25);
    cout << args << endl;
    // src 1
    ret = avfilter_graph_create_filter(&bufSrcContext[1], bufSrc, "in1", args, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }
    // hstack
    ret = avfilter_graph_create_filter(&hstackContext, hstack, "hstack", "inputs=2", NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }
    // sink
    ret = avfilter_graph_create_filter(&bufSinkContext, bufSink, "out", NULL, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }

    ret = avfilter_link(bufSrcContext[0], 0, hstackContext, 0);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_link  failed! :" << buf << endl;
        return false;
    }
    ret = avfilter_link(bufSrcContext[1], 0, hstackContext, 1);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_link  failed! :" << buf << endl;
        return false;
    }
    ret = avfilter_link(hstackContext, 0, bufSinkContext, 0);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_link  failed! :" << buf << endl;
        return false;
    }

    ret = avfilter_graph_config(filterGraph, NULL);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_config  failed! :" << buf << endl;
        return false;
    }

    if(input->next) avfilter_inout_free(&input->next);
    if(input )avfilter_inout_free(&input);
    if(output) avfilter_inout_free(&output);
    return true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112

3、水平翻转滤镜

3.1 名称hflip
3.2 语法:无配置参数
3.3 其他:引申:垂直翻转滤镜vflip
3.4 示例代码

static int initFilter(AVCodecContext * codecContext0, AVCodecContext * codecContext1)
{
    int ret = 0;
    const AVFilter *bufSrc = NULL;
    const AVFilter *hflip  = NULL;
    const AVFilter *bufSink = NULL;
    AVFilterInOut *input = NULL;
    AVFilterInOut *output = NULL;

    char args[128] = {0};
    if(NULL == filterGraph)
        filterGraph = avfilter_graph_alloc();
    else
    {
        return true;
    }
    input  = avfilter_inout_alloc();
    output = avfilter_inout_alloc();
    bufSrc = avfilter_get_by_name("buffer");
    hflip  = avfilter_get_by_name("hflip");
    bufSink = avfilter_get_by_name("buffersink");

    if(NULL == filterGraph || NULL == input || NULL == output)
    {
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "alloc  failed! :" << endl;
        return false;
    }
    if(NULL == bufSrc || NULL == bufSink)
    {
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_get_by_name  failed! :" << endl;
        return false;
    }
	snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", codecContext0->width, codecContext0->height, codecContext0->pix_fmt, 1, 25, 1, 25);
    cout << args << endl;
    // src 0
    ret = avfilter_graph_create_filter(&bufSrcContext[0], bufSrc, "in0", args, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }
    // hflip
    ret = avfilter_graph_create_filter(&hflipContext, hflip, "hflip", NULL, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }
    // sink
    ret = avfilter_graph_create_filter(&bufSinkContext, bufSink, "out", NULL, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }

    ret = avfilter_link(bufSrcContext[0], 0, hflipContext, 0);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_link  failed! :" << buf << endl;
        return false;
    }
    ret = avfilter_link(hflipContext, 0, bufSinkContext, 0);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_link  failed! :" << buf << endl;
        return false;
    }

    ret = avfilter_graph_config(filterGraph, NULL);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_config  failed! :" << buf << endl;
        return false;
    }

    if(input->next) avfilter_inout_free(&input->next);
    if(input )avfilter_inout_free(&input);
    if(output) avfilter_inout_free(&output);
    return true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

4、边缘检测滤镜

4.1 名称edgedetect
4.2 语法: -low:低阈值;-high:高阈值;必须在[0,1]范围内选择低阈值和高阈值,低阈值应小于或等于高阈值。-mode:定义绘图模式,‘wires’:黑白;‘colormix’:类似油画效果,卡通效果;默认值为wires。举例:"mode=colormix:low=0.1:high=0.4"
4.3 其他:注意滤镜输出格式为GRAY8(wires)、GBR24P(colormix)而非YUV。
4.4 示例代码

static int initFilter(AVCodecContext * codecContext0, AVCodecContext * codecContext1)
{
    int ret = 0;
    const AVFilter *bufSrc = NULL;
    const AVFilter *edgedetect  = NULL;
    const AVFilter *bufSink = NULL;
    AVFilterInOut *input = NULL;
    AVFilterInOut *output = NULL;

    char args[128] = {0};
    if(NULL == filterGraph)
        filterGraph = avfilter_graph_alloc();
    else
    {
        return true;
    }
    input  = avfilter_inout_alloc();
    output = avfilter_inout_alloc();
    bufSrc = avfilter_get_by_name("buffer");
    edgedetect  = avfilter_get_by_name("edgedetect");
    bufSink = avfilter_get_by_name("buffersink");

    if(NULL == filterGraph || NULL == input || NULL == output)
    {
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "alloc  failed! :" << endl;
        return false;
    }
    if(NULL == bufSrc || NULL == bufSink)
    {
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_get_by_name  failed! :" << endl;
        return false;
    }
    snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", codecContext0->width, codecContext0->height, codecContext0->pix_fmt, 1, 25, 1, 25);
    cout << args << endl;
    // src 0
    ret = avfilter_graph_create_filter(&bufSrcContext[0], bufSrc, "in0", args, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }
    // edgedetect
    ret = avfilter_graph_create_filter(&edgedetectContext, edgedetect, "edgedetect", "mode=colormix:low=0.1:high=0.4", NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }
    // sink
    ret = avfilter_graph_create_filter(&bufSinkContext, bufSink, "out", NULL, NULL, filterGraph);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_create_filter  failed! :" << buf << endl;
        return false;
    }

    ret = avfilter_link(bufSrcContext[0], 0, edgedetectContext, 0);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_link  failed! :" << buf << endl;
        return false;
    }
    ret = avfilter_link(edgedetectContext, 0, bufSinkContext, 0);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_link  failed! :" << buf << endl;
        return false;
    }

    ret = avfilter_graph_config(filterGraph, NULL);
    if(0 > ret)
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        cout << "[" << __FILE__ << "|" << __LINE__ << "]" << "avfilter_graph_config  failed! :" << buf << endl;
        return false;
    }

    if(input->next) avfilter_inout_free(&input->next);
    if(input )avfilter_inout_free(&input);
    if(output) avfilter_inout_free(&output);
    return true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/174747
推荐阅读
相关标签
  

闽ICP备14008679号