前言

介绍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视频滤镜(一)相关推荐

  1. ffmpeg视频滤镜

    过滤器分类 1.1简单过滤器 在简单过滤器中,只包含一个输入和一个输出,并且输入输出是同一类型.在下面的处理过程中,仅仅是在解码和编码之间加上一个额外的过滤步骤. 简单过滤器由per-stream-f ...

  2. LiveVideoStackCon讲师热身分享 ( 八 ) —— FFmpeg的滤镜在视频编辑场景中的应用

    LiveVideoStackCon 2018音视频技术大会是每年的多媒体技术人的盛宴,为了让参会者与大会讲师更多互动交流,我们推出了LiveVideoStackCon讲师热身分享第一季,在每周四晚19 ...

  3. ffmpeg 将拆分的数据合成一帧_FFmpeg + OpenGLES 实现视频解码播放和视频滤镜

    FFmpeg 开发系列连载: FFmpeg 开发(01):FFmpeg 编译和集成 FFmpeg 开发(02):FFmpeg + ANativeWindow 实现视频解码播放 FFmpeg 开发(03 ...

  4. ffmpeg利用滤镜合并两个视频,一左一右

    ffmpeg关于视频合并的例子,命令行的一堆,代码的感觉不多,命令行跟代码感觉还是有些差距,代码上要求还是高一些,关于滤镜的命令行,读者可以看我的一篇博客 ffmpeg利用滤镜进行视频混合(命令行) ...

  5. ffmpeg利用滤镜合并四个视频,左一右三

    今天利用ffmpeg的滤镜功能合并,左一右三方式,如下所示: 读者需要先对滤镜的描述字符串有所了解,读者可以参看我写的一篇博客: ffmpeg利用滤镜进行视频混合(命令行) 四个文件都是1920x10 ...

  6. ffmpeg利用滤镜合并两个视频,一左一右---avfilter_link实现

    之前写过一篇博客ffmpeg利用滤镜合并两个视频,一左一右 用的是滤镜字符串解析avfilter_graph_parse_ptr实现滤镜的连接,查看了avfilter_graph_parse_ptr的 ...

  7. FFmpeg进阶:音视频滤镜概述

    文章目录 滤镜示例 滤镜的格式 滤镜语法规则 滤镜图 基于时间的滤镜控制 滤镜API介绍 常用滤镜 FFmpeg的滤镜模块(libavfilter)提供了各种各样的滤镜特效.通过滤镜模块,我们可以实现 ...

  8. FFmpeg源码分析:视频滤镜介绍(上)

    FFmpeg在libavfilter模块提供音视频滤镜.所有的视频滤镜都注册在libavfilter/allfilters.c.我们也可以使用ffmpeg -filters命令行来查看当前支持的所有滤 ...

  9. FFmpeg 视频录制 - 视频添加滤镜和编码

    前言 音视频开发中,视频编码是另一个重要的部分,基于 FFmpeg 软件解码前面系列文章已经介绍过了. 接下来主要介绍软件编码这一块,包括视频编码.音频编码.为视频添加滤镜等,后续文章安排介绍 And ...

最新文章

  1. ISP PIPLINE (九_1) Denoise 之 space domain denoise
  2. 中国发布自主开发的域名系统基础软件 “红枫”
  3. 在python中如何比较两个float类型的数据是否相等
  4. linux系统迁移的重要配置文件,mylinuxbackup
  5. 博客园win8客户端开发记录5-app设置 登录 回复评论
  6. 增强型的for循环linkedlist_LinkedList的复习
  7. HTML5类选择器使用,CSS选择器种类及使用方法
  8. iPad iPhone程序增加和删除启动画面
  9. 常人不解朱啸虎,读懂已是被裁人
  10. Nacos 新增命名空间
  11. 《CCIE路由和交换认证考试指南(第5版) (第1卷)》——2.4节VLAN Trunk协议
  12. 机器学习及算法-python
  13. 实现Qt日志功能并输出到文件(qDebug\qWarning\ qCritical\qFatal)
  14. ​windows系统——更改系统音效为钢铁侠贾维斯​
  15. YARN 删除所有ACCEPTED任务的命令
  16. 仙武:开局神级召唤!(二)
  17. 导入本体到Jena TDB数据库
  18. Gstore官网学习一:知识图谱与gStore介绍
  19. 盘点认证协议 : 普及篇之ADFS , WS-Federation
  20. vue中实现附件下载

热门文章

  1. 你真的知道运维是干嘛的吗?
  2. 阶乘分之一java_阶乘公式等于e的n次方
  3. python如何限定输入类型_关于python:如何确定输入的类型?
  4. 印象笔记(Evenote)导出到Onenote的方法2022
  5. 树莓派4b:PWM调速风扇+DIY亚克力板外壳的定制降温方案
  6. ftrack获得2亿美金支持
  7. 模拟JAVA堆内存溢出和栈内存溢出
  8. 修改注册表设置ie主页
  9. Photoshop CS4 锁定图层
  10. 汇总css布局模型和常见代码缩写与长度单位