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);
// cout << args << endl;// src 0ret = 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;}// rotatesnprintf(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;}// sinkret = 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;// src 0ret = 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 1ret = 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;}// hstackret = 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;}// sinkret = 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;// src 0ret = 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;}// hflipret = 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;}// sinkret = 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;// src 0ret = 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;}// edgedetectret = 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;}// sinkret = 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视频滤镜(一)相关推荐
- ffmpeg视频滤镜
过滤器分类 1.1简单过滤器 在简单过滤器中,只包含一个输入和一个输出,并且输入输出是同一类型.在下面的处理过程中,仅仅是在解码和编码之间加上一个额外的过滤步骤. 简单过滤器由per-stream-f ...
- LiveVideoStackCon讲师热身分享 ( 八 ) —— FFmpeg的滤镜在视频编辑场景中的应用
LiveVideoStackCon 2018音视频技术大会是每年的多媒体技术人的盛宴,为了让参会者与大会讲师更多互动交流,我们推出了LiveVideoStackCon讲师热身分享第一季,在每周四晚19 ...
- ffmpeg 将拆分的数据合成一帧_FFmpeg + OpenGLES 实现视频解码播放和视频滤镜
FFmpeg 开发系列连载: FFmpeg 开发(01):FFmpeg 编译和集成 FFmpeg 开发(02):FFmpeg + ANativeWindow 实现视频解码播放 FFmpeg 开发(03 ...
- ffmpeg利用滤镜合并两个视频,一左一右
ffmpeg关于视频合并的例子,命令行的一堆,代码的感觉不多,命令行跟代码感觉还是有些差距,代码上要求还是高一些,关于滤镜的命令行,读者可以看我的一篇博客 ffmpeg利用滤镜进行视频混合(命令行) ...
- ffmpeg利用滤镜合并四个视频,左一右三
今天利用ffmpeg的滤镜功能合并,左一右三方式,如下所示: 读者需要先对滤镜的描述字符串有所了解,读者可以参看我写的一篇博客: ffmpeg利用滤镜进行视频混合(命令行) 四个文件都是1920x10 ...
- ffmpeg利用滤镜合并两个视频,一左一右---avfilter_link实现
之前写过一篇博客ffmpeg利用滤镜合并两个视频,一左一右 用的是滤镜字符串解析avfilter_graph_parse_ptr实现滤镜的连接,查看了avfilter_graph_parse_ptr的 ...
- FFmpeg进阶:音视频滤镜概述
文章目录 滤镜示例 滤镜的格式 滤镜语法规则 滤镜图 基于时间的滤镜控制 滤镜API介绍 常用滤镜 FFmpeg的滤镜模块(libavfilter)提供了各种各样的滤镜特效.通过滤镜模块,我们可以实现 ...
- FFmpeg源码分析:视频滤镜介绍(上)
FFmpeg在libavfilter模块提供音视频滤镜.所有的视频滤镜都注册在libavfilter/allfilters.c.我们也可以使用ffmpeg -filters命令行来查看当前支持的所有滤 ...
- FFmpeg 视频录制 - 视频添加滤镜和编码
前言 音视频开发中,视频编码是另一个重要的部分,基于 FFmpeg 软件解码前面系列文章已经介绍过了. 接下来主要介绍软件编码这一块,包括视频编码.音频编码.为视频添加滤镜等,后续文章安排介绍 And ...
最新文章
- ISP PIPLINE (九_1) Denoise 之 space domain denoise
- 中国发布自主开发的域名系统基础软件 “红枫”
- 在python中如何比较两个float类型的数据是否相等
- linux系统迁移的重要配置文件,mylinuxbackup
- 博客园win8客户端开发记录5-app设置 登录 回复评论
- 增强型的for循环linkedlist_LinkedList的复习
- HTML5类选择器使用,CSS选择器种类及使用方法
- iPad iPhone程序增加和删除启动画面
- 常人不解朱啸虎,读懂已是被裁人
- Nacos 新增命名空间
- 《CCIE路由和交换认证考试指南(第5版) (第1卷)》——2.4节VLAN Trunk协议
- 机器学习及算法-python
- 实现Qt日志功能并输出到文件(qDebug\qWarning\ qCritical\qFatal)
- ​windows系统——更改系统音效为钢铁侠贾维斯​
- YARN 删除所有ACCEPTED任务的命令
- 仙武:开局神级召唤!(二)
- 导入本体到Jena TDB数据库
- Gstore官网学习一:知识图谱与gStore介绍
- 盘点认证协议 : 普及篇之ADFS , WS-Federation
- vue中实现附件下载