FFmepg--AVFilter过滤器使用以及yuv视频裁剪

文章目录

      • AVFilter 流程:
      • api
      • 核心代码
        • 变量
        • yuv视频裁剪

AVFilter 流程:

请添加图片描述

⾸先使⽤split滤波器将input流分成两路流(main和tmp),然后分别对两路流进⾏处理。对于tmp流,先经过crop滤波器进⾏裁剪处理,再经过flip滤波器进⾏垂直⽅向上的翻转操作,输出的结果命名为flip流。再将main流和flip流输⼊到overlay滤波器进⾏合成操作

input 为buffer源过滤波器,output为buffersink滤波器,图中每个节点都是⼀个AVFilterContext,每个连线就是AVFliterLink。所有这些信息都统⼀由AVFilterGraph来管理

api

  • 获取FFmpeg中定义的filter,调⽤该⽅法前需要先调⽤avfilter_register_all();进⾏滤波器注册
    AVFilter avfilter_get_by_name(const char name);
  • 往源滤波器buffer中输⼊待处理的数据
    int av_buffersrc_add_frame(AVFilterContext ctx, AVFrame frame);
  • 从⽬的滤波器buffersink中获取处理完的数据
    int av_buffersink_get_frame(AVFilterContext ctx, AVFrame frame);
  • 创建⼀个滤波器图filter graph
    AVFilterGraph *avfilter_graph_alloc(void);
  • 创建⼀个滤波器实例AVFilterContext,并添加到AVFilterGraph中
    int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
    const char name, const char args, void *opaque,
    AVFilterGraph *graph_ctx);
  • 连接两个滤波器节点
    int avfilter_link(AVFilterContext *src, unsigned srcpad,
    AVFilterContext *dst, unsigned dstpad);

核心代码

变量

– AVFilterGraph-对filters系统的整体管理

struct AVFilterGraph
{
AVFilterContext **filters;

– AVFilter结构体

AVFilter ff_vf_overlay = {.name = "overlay",.inputs = avfilter_vf_overlay_inputs,.outputs = avfilter_vf_overlay_outputs,// ..};struct AVFilterContext
{const AVFilter *filter;char *name;AVFilterPad *input_pads;AVFilterLink **inputs;unsigned nb_inputsAVFilterPad *output_pads;AVFilterLink **outputs;unsigned nb_outputs;struct AVFilterGraph *graph; // 从属于哪个AVFilterGraph
}

– AVFilterLink-定义两个filters之间的联接

	struct AVFilterLink{AVFilterContext *src;AVFilterPad *srcpad;AVFilterContext *dst;AVFilterPad *dstpad;struct AVFilterGraph *graph;}

– AVFilterPad-定义filter的输⼊/输出接⼝

struct AVFilterPad
{const char *name;AVFrame *(*get_video_buffer)(AVFilterLink *link, int w, int h);AVFrame *(*get_audio_buffer)(AVFilterLink *link, int nb_samples);int (*filter_frame)(AVFilterLink *link, AVFrame *frame);AVFilterPad-定义filter的输⼊/输出接⼝int (*request_frame)(AVFilterLink *link);
}
yuv视频裁剪

对输入yuv文件,在中间处裁剪,留下上半部分,下半部分为上半部分的镜像

#include <stdio.h>#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>int main(int argc, char* argv)
{int ret = 0;// input yuvFILE* inFile = NULL;const char* inFileName = "768x320.yuv";fopen_s(&inFile, inFileName, "rb+");int in_width = 768;int in_height = 320;// output yuvFILE* outFile = NULL;const char* outFileName = "out_crop_vfilter.yuv";fopen_s(&outFile, outFileName, "wb");avfilter_register_all();AVFilterGraph* filter_graph = avfilter_graph_alloc();// source filterchar args[512];AVFilter* bufferSrc = avfilter_get_by_name("buffer");   // AVFilterGraph的输入源AVFilterContext* bufferSrc_ctx;avfilter_graph_create_filter(&bufferSrc_ctx, bufferSrc, "in", args, NULL, filter_graph);// sink filterAVBufferSinkParams *bufferSink_params;AVFilterContext* bufferSink_ctx;AVFilter* bufferSink = avfilter_get_by_name("buffersink");enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };bufferSink_params = av_buffersink_params_alloc();bufferSink_params->pixel_fmts = pix_fmts;ret = avfilter_graph_create_filter(&bufferSink_ctx, bufferSink, "out", NULL,bufferSink_params, filter_graph);// split filterAVFilter *splitFilter = avfilter_get_by_name("split");AVFilterContext *splitFilter_ctx;avfilter_graph_create_filter(&splitFilter_ctx, splitFilter, "split", "outputs=2",NULL, filter_graph);// crop filterAVFilter *cropFilter = avfilter_get_by_name("crop");AVFilterContext *cropFilter_ctx;revfilter_graph_create_filter(&cropFilter_ctx, cropFilter, "crop","out_w=iw:out_h=ih/2:x=0:y=0", NULL, filter_graph);// vflip filterAVFilter *vflipFilter = avfilter_get_by_name("vflip");AVFilterContext *vflipFilter_ctx;avfilter_graph_create_filter(&vflipFilter_ctx, vflipFilter, "vflip", NULL, NULL, filter_graph);// overlay filterAVFilter *overlayFilter = avfilter_get_by_name("overlay");AVFilterContext *overlayFilter_ctx;avfilter_graph_create_filter(&overlayFilter_ctx, overlayFilter, "overlay","y=0:H/2", NULL, filter_graph);avfilter_link(bufferSrc_ctx, 0, splitFilter_ctx, 0);// split filter's first pad to overlay filter's main padavfilter_link(splitFilter_ctx, 0, overlayFilter_ctx, 0);// split filter's second pad to crop filteravfilter_link(splitFilter_ctx, 1, cropFilter_ctx, 0);// crop filter to vflip filteravfilter_link(cropFilter_ctx, 0, vflipFilter_ctx, 0);// vflip filter to overlay filter's second padavfilter_link(vflipFilter_ctx, 0, overlayFilter_ctx, 1);// overlay filter to sink filteravfilter_link(overlayFilter_ctx, 0, bufferSink_ctx, 0);// check filter graphavfilter_graph_config(filter_graph, NULL);char *graph_str = avfilter_graph_dump(filter_graph, NULL);FILE* graphFile = NULL;fopen_s(&graphFile, "graphFile.txt", "w");  // 打印filtergraph的具体情况fprintf(graphFile, "%s", graph_str);av_free(graph_str);AVFrame *frame_in = av_frame_alloc();unsigned char *frame_buffer_in = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, in_width, in_height, 1));av_image_fill_arrays(frame_in->data, frame_in->linesize, frame_buffer_in,AV_PIX_FMT_YUV420P, in_width, in_height, 1);AVFrame *frame_out = av_frame_alloc();unsigned char *frame_buffer_out = (unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, in_width, in_height, 1));av_image_fill_arrays(frame_out->data, frame_out->linesize, frame_buffer_out,AV_PIX_FMT_YUV420P, in_width, in_height, 1);frame_in->width = in_width;frame_in->height = in_height;frame_in->format = AV_PIX_FMT_YUV420P;uint32_t frame_count = 0;while (1) {// 读取yuv数据if (fread(frame_buffer_in, 1, in_width*in_height * 3 / 2, inFile) != in_width*in_height * 3 / 2) {break;}//input Y,U,Vframe_in->data[0] = frame_buffer_in;frame_in->data[1] = frame_buffer_in + in_width*in_height;frame_in->data[2] = frame_buffer_in + in_width*in_height * 5 / 4;if (av_buffersrc_add_frame(bufferSrc_ctx, frame_in) < 0) {printf("Error while add frame.\n");break;}// filter内部自己处理/* pull filtered pictures from the filtergraph */ret = av_buffersink_get_frame(bufferSink_ctx, frame_out);if (ret < 0)break;//output Y,U,Vif (frame_out->format == AV_PIX_FMT_YUV420P) {for (int i = 0; i < frame_out->height; i++) {fwrite(frame_out->data[0] + frame_out->linesize[0] * i, 1, frame_out->width, outFile);}for (int i = 0; i < frame_out->height / 2; i++) {fwrite(frame_out->data[1] + frame_out->linesize[1] * i, 1, frame_out->width / 2, outFile);}for (int i = 0; i < frame_out->height / 2; i++) {fwrite(frame_out->data[2] + frame_out->linesize[2] * i, 1, frame_out->width / 2, outFile);}}++frame_count;if(frame_count % 25 == 0)printf("Process %d frame!\n",frame_count);av_frame_unref(frame_out);}fclose(inFile);fclose(outFile);av_frame_free(&frame_in);av_frame_free(&frame_out);avfilter_graph_free(&filter_graph); // 内部去释放AVFilterContext产生的内存return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/766783.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kotlin零基础入门到进阶实战

教程介绍 Kotlin现在是Google官方认定Android一级开发语言&#xff0c;与Java100%互通&#xff0c;并具备诸多Java尚不支持的新特性&#xff0c;每个Android程序员必备的Kotlin课程&#xff0c;每个Java程序员都需要了解的Kotlin&#xff0c;掌握kotlin可以开发Web前端、Web后…

轻量C++IDE CodeLite的配置和使用

文章目录 下载和安装新建项目测试项目编译的配置单独项目的配置全局项目的配置开启c++11配置第三方库代码补全codelite配置文件路径解决程序中文乱码的问题中文语言支持本人用过的C++环境:Code::Block、Visual Studio、C-Free、Dev-C、QT-Creater、Geany、现在的CodeLite,Cod…

C语言:二叉树基础

一、树 1.1 树的概念 1.树是有n个节点组成的具有层次关系的集合&#xff0c;是一种非线性的结构。 2.树的第一个节点称为根&#xff0c;根没有前驱节点。 3.除了根节点&#xff0c;其余每个节点都只有一个前驱节点&#xff0c;有0个或多个后继节点。 4.节点的度&#x…

主干网络篇 | YOLOv8更换主干网络之GhostNet

前言:Hello大家好,我是小哥谈。GhostNet是2019年由华为诺亚方舟实验室发布的轻量级网络,速度和MobileNetV3相似,但是识别的准确率比MobileNetV3高,在ImageNet ILSVRC2012分类数据集的达到了75.7%的top-1精度。该论文提除了Ghost模块,通过廉价操作生成更多的特征图。基于一…

是德科技keysight DSOX3024T示波器

181/2461/8938产品概述&#xff1a; DSOX3024T 示波器 要特性与技术指标 使用电容触摸屏进行简洁的触控操作&#xff1a; •提高调试效率 •触控设计可以简化文档记录 •使用起来就像您喜欢的智能手机或平板电脑一样简单 使用 MegaZoom IV 技术揭示偶发异常&#xff1a; •超快…

思通舆情 是一款开源免费的舆情系统 介绍

思通舆情 是一款开源免费的舆情系统。 支持本地化部署&#xff0c;支持在线体验。 支持对海量舆情数据分析和挖掘。 无论你是使用者还是共同完善的开发者&#xff0c;欢迎 pull request 或者 留言对我们提出建议。 您的支持和参与就是我们坚持开源的动力&#xff01;请 sta…

申请双软认证需要哪些材料?软件功能测试报告怎么获取?

“双软认证”是指软件产品评估和软件企业评估&#xff0c;其中需要软件测试报告。 企业申请双软认证除了获得软件企业和软件产品的认证资质&#xff0c;同时也是对企业知识产权的一种保护方式&#xff0c;更可以让企业享受国家提供给软件行业的税收优惠政策。 那么&#xff0c;…

6-191 拓扑排序

一项工程由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其他子任务后才能执行。例如,下图表示了一项工程若干子任务之间的先后关系。 编写函数输出所有子任务的拓扑序列。 函数接口定义: Status Push_SeqStack(SeqStack &s, ElemType x)//入栈,x入到…

AS:32590 美国Valve公司IP地址段,抓CS:GO游戏服务器IP

抓 Valve 公司的IP地址段&#xff0c;主要用途是为了CS:GO网络游戏加速IP地址段&#xff0c;严格意义上来说&#xff0c;不同地区对于CS:GO游戏网络加速&#xff0c;需要对应到对应地区去抓IP地址段。 以CS:GO香港地区为例子&#xff1a;抓出来的IP地址基本都是新加坡、香港两…

框架结构模态分析/动力时程分析Matlab有限元编程 【Matlab源码+PPT讲义】|梁单元|地震时程动画|结果后处理|地震弹性时程分析| 隐式动力学

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

蓝桥杯单片机快速开发笔记——特训4 24C02—E2PROM存储按键触发次数

一、原理分析 HC573/HC138&#xff1a;http://t.csdnimg.cn/W0a0U 数码管&#xff1a;http://t.csdnimg.cn/kfm9Y AT24C02 E2PROM&#xff1a;http://t.csdnimg.cn/DI8XH 独立键盘&#xff1a;http://t.csdnimg.cn/YPInc 二、题目要求 在CT107D单片机综合训练平台上&#xff0…

基于springboot+vue的旅游网站

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

JavaScript 权威指南第七版(GPT 重译)(六)

第十五章&#xff1a;JavaScript 在 Web 浏览器中 JavaScript 语言是在 1994 年创建的&#xff0c;旨在使 Web 浏览器显示的文档具有动态行为。自那时以来&#xff0c;该语言已经发生了显著的演变&#xff0c;与此同时&#xff0c;Web 平台的范围和功能也迅速增长。今天&#…

2024.3.24阶段性测试题解

VJ测试链接考试链接 成绩表如下&#xff0c;信息学是非常检验平时努力的&#xff0c;而且也是一分耕耘一分收获的&#xff0c;总的来说每天订正晚训跟只订正一部分题还是有区别的…希望同学们再接再厉。 A题 简单判断题&#xff0c;单独判断首字母&#xff0c;再判断其余字母…

Java 学习和实践笔记(45):数组的遍历,复制,

数组的两种遍历方式&#xff1a; package innerClass;public class Test01 {public static void main(String[] args) {String[] cities {"北京","上海","广州","深圳",};//遍历方式一&#xff0c;这是一般的方式for (int i0; i<…

AI大模型学习:理论基石、优化之道与应用革新

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

列车票务信息管理系统设计与实现|jsp+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW调试部署环境&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java…

100道面试必会算法-11-LFU缓存

100道面试必会算法-11-LFU缓存 题目描述 最不经常使用&#xff08;LFU&#xff09;缓存算法设计并实现数据结构。 实现 LFUCache 类&#xff1a; LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象int get(int key) - 如果键 key 存在于缓存中&#xff0c;则…

mysql 事务的四大特性以及实现原理

MySQL 事务的四大特性通常指ACID&#xff0c;即原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;和持久性&#xff08;Durability&#xff09;。 原子性&#xff08;Atomicity&#xff09;&…

OpenLayers基础教程——WebGLPoints中要素样式的设置方法解析

1、前言 前一篇博客介绍了如何在OpenLayers中使用WebGLPoints加载海量数据点的方法&#xff0c;这篇博客就来介绍一下WebGLPoints图层的样式设置问题。 2、样式运算符 在VectorLayer图层中&#xff0c;我们只需要创建一个ol.style.Style对象即可&#xff0c;WebGLPoints则不…