赞
踩
介绍FFmpeg中旋转rotate
、拼接hstack
、翻转hflip
、边缘edgedetect
视频滤镜的使用方法。
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; }
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; }
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; }
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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。