生活随笔
收集整理的這篇文章主要介紹了
FFMPEG视频滤镜(一)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
介紹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);
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
), "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;}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;
}
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
;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
;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;}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;}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;
}
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
;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;}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;}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;
}
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
;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;}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;}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;
}
總結
以上是生活随笔為你收集整理的FFMPEG视频滤镜(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。