使用FFmpeg的AVFilter转换YUV到RGB

news/2024/9/17 8:58:25 标签: ffmpeg

AVFilter 是 FFmpeg 库 libavfilter 的核心组件,提供了一套强大的音视频处理框架,用于对音视频流进行复杂的过滤、转换和效果处理。通过 AVFilter,开发者可以构建自定义的滤镜图(filter graph),实现各种音视频处理任务,如颜色空间转换、缩放、裁剪、特效添加等。

以下是对 AVFilter 的详细介绍,包括其架构、关键概念、使用方法以及示例代码。

1. AVFilter 概述

AVFilter 是 FFmpeg 提供的一个模块化框架,允许用户将多个滤镜(filters)串联起来,形成一个滤镜图(filter graph),以对音视频数据进行逐步处理。滤镜图定义了数据流的处理路径,每个滤镜节点负责特定的处理任务。

主要功能

  • 视频滤镜:调整分辨率(scale)、裁剪(crop)、旋转(transpose)、颜色调整(hue)、添加文本(drawtext)等。
  • 音频滤镜:调整音量(volume)、回声效果(aecho)、重采样(aresample)、声道平移(pan)等。
  • 混合滤镜:将多个视频流混合(blend)、拼接(concat)等。

2. AVFilter 架构

AVFilter 框架由几个关键组件组成:

2.1 AVFilterGraph

AVFilterGraph 是整个滤镜图的容器,负责管理滤镜节点及其连接关系。一个滤镜图可以包含多个滤镜节点,每个节点通过输入和输出端口连接起来。

2.2 AVFilter

AVFilter 代表一个具体的滤镜类型,例如 scalecropbuffersrcbuffersink 等。每个滤镜都有特定的功能和参数。

2.3 AVFilterContext

AVFilterContext 是某个滤镜在滤镜图中的具体实例,持有滤镜的状态和配置参数,并管理滤镜之间的数据流。

2.4 AVFilterInOut

AVFilterInOut 用于表示滤镜图中的输入和输出连接点,特别是在动态构建滤镜图时,用于连接不同滤镜的输入输出。

3. AVFilter 使用流程

使用 AVFilter 进行音视频处理通常包括以下步骤:

  1. 初始化 FFmpeg 库:确保所有必要的库和组件已初始化。
  2. 创建滤镜图:分配和初始化一个 AVFilterGraph 实例。
  3. 创建滤镜节点:根据需要添加输入、输出和处理滤镜,如 buffersrcscalebuffersink 等。
  4. 连接滤镜:将滤镜节点按照处理顺序连接起来,形成滤镜链。
  5. 配置滤镜图:完成滤镜图的配置,并进行优化和验证。
  6. 处理帧:将音视频帧输入滤镜图,通过滤镜链处理并获取输出帧。
  7. 释放资源:处理完成后,释放所有分配的资源。

4. 示例:使用 AVFilter 进行 YUV 到 RGB 转换

下面是一个使用 AVFilter 将 YUV 格式转换为 RGB 格式的示例代码。

4.1 初始化 FFmpeg

在开始任何操作之前,确保初始化 FFmpeg 库和注册所有滤镜。

#include <libavfilter/avfilter.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>

// 初始化 FFmpeg 库
av_register_all();
avfilter_register_all();

4.2 创建 AVFilterGraph

创建一个 AVFilterGraph,它将存储和管理所有滤镜节点及其连接。

AVFilterGraph *filter_graph = avfilter_graph_alloc();
if (!filter_graph) {
    fprintf(stderr, "Unable to create filter graph.\n");
    exit(1);
}

4.3 创建输入滤镜(buffersrc)和输出滤镜(buffersink)

AVFilterContext *buffersrc_ctx = NULL;
AVFilterContext *buffersink_ctx = NULL;

const AVFilter *buffersrc = avfilter_get_by_name("buffer");
const AVFilter *buffersink = avfilter_get_by_name("buffersink");

// 设置输入滤镜参数
char args[512];
snprintf(args, sizeof(args),
         "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
         width, height, AV_PIX_FMT_YUV420P,
         time_base.num, time_base.den,
         sample_aspect_ratio.num, sample_aspect_ratio.den);

// 创建 buffersrc
int ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
                                       args, NULL, filter_graph);
if (ret < 0) {
    fprintf(stderr, "Cannot create buffer source\n");
    exit(1);
}

// 设置 buffersink 的输出像素格式
enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE };
ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
                                   NULL, NULL, filter_graph);
if (ret < 0) {
    fprintf(stderr, "Cannot create buffer sink\n");
    exit(1);
}

ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts,
                          AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
    fprintf(stderr, "Cannot set output pixel format\n");
    exit(1);
}

4.4 添加颜色空间转换滤镜(scale)

const AVFilter *scale = avfilter_get_by_name("scale");
AVFilterContext *scale_ctx = NULL;

// 创建 scale 滤镜
ret = avfilter_graph_create_filter(&scale_ctx, scale, "scale",
                                   NULL, NULL, filter_graph);
if (ret < 0) {
    fprintf(stderr, "Cannot create scale filter\n");
    exit(1);
}

4.5 连接滤镜

buffersrc 连接到 scale,然后将 scale 连接到 buffersink

ret = avfilter_link(buffersrc_ctx, 0, scale_ctx, 0);
if (ret >= 0) {
    ret = avfilter_link(scale_ctx, 0, buffersink_ctx, 0);
}
if (ret < 0) {
    fprintf(stderr, "Error connecting filters\n");
    exit(1);
}

4.6 配置滤镜图

完成滤镜图的配置,使其准备好处理帧。

ret = avfilter_graph_config(filter_graph, NULL);
if (ret < 0) {
    fprintf(stderr, "Error configuring the filter graph\n");
    exit(1);
}

4.7 处理帧

使用 av_buffersrc_add_frame() 向滤镜图中添加帧,并使用 av_buffersink_get_frame() 从图中获取转换后的帧。

AVFrame *frame = av_frame_alloc();
AVFrame *filt_frame = av_frame_alloc();

// 假设 frame 已经填充了 YUV 数据

// 将帧添加到滤镜图
ret = av_buffersrc_add_frame(buffersrc_ctx, frame);
if (ret < 0) {
    fprintf(stderr, "Error while adding frame to filter graph\n");
    exit(1);
}

// 从滤镜图中获取处理后的帧
ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
if (ret < 0) {
    fprintf(stderr, "Error while getting frame from filter graph\n");
    exit(1);
}

// 此时 filt_frame 包含 RGB 数据

4.8 释放资源

处理完成后,释放所有分配的资源。

av_frame_free(&frame);
av_frame_free(&filt_frame);
avfilter_graph_free(&filter_graph);


http://www.niftyadmin.cn/n/5640942.html

相关文章

Spring中使用ResponseStatusExceptionResolver处理HTTP异常响应码

目录 常用HTTP状态码分类和HttpStatus枚举的对应关系错误请求处理过程定义ResourceBadRequestException类在监测到相应的问题时抛出对应的异常 在日常开发过程中&#xff0c;Spring中默认的HTTP状态处理并不能满足所以场景&#xff0c;可以使用ResponseStatusExceptionResolver…

【机器人工具箱Robotics Toolbox开发笔记(九)】 机器人逆运动学分析

​1. 逆运动学理论基础 机器人逆运动学的问题即已知机器人末端的工具坐标系相对于基坐标系的位姿,计算所有能够到达给定位置和姿态的关节角。 对于以上的问题,有以下几种情况: (1)不存在相应的解 当所期望的位姿离基坐标系太远,而机器人不够长时,末端执行器无法达到…

【微处理器系统原理与应用设计第二讲】微处理器的基本架构之组成原理和系统结构

本文首先讲解微处理器的重要组成部分&#xff0c;之后会穿插数电的知识进行相关功能电路的设计&#xff0c;以达到从理论到实践的效果。 一. 组成原理 1. 运算器 ALU是微处理器中执行所有算术和逻辑操作的部件。主要的功能是加减乘除&#xff0c;与或非异或比较等。&#xff…

计算机毕业设计 二手闲置交易系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

微服务中的服务降级与熔断机制

目录&#xff1a; 1、简介2、服务降级2.1. Hystrix基础配置2.2. 启用Hystrix2.3. 实现服务降级2.4. 配置Hystrix 3、熔断机制3.1. 配置熔断器3.2. 查看Hystrix Dashboard 1、简介 在微服务架构中&#xff0c;服务降级与熔断机制是保证系统稳定性和可靠性的关键技术。当系统中的…

【避坑指南】避免几个坑,OpenCV的轮廓分析速度也可以很快!

前一篇请看CSDN 博文 【性能飞升】OpenCV-Python改动一行代码性能提升百倍以上 学习《OpenCV应用开发&#xff1a;入门、进阶与工程化实践》一书 做真正的OpenCV开发者&#xff0c;从入门到入职&#xff0c;一步到位&#xff01; 缘由 这个是跟CCL分析速度很慢的姊妹篇文章&…

前端:HTML、CSS、JS、Vue

1 前端 内容概要 了解前端三件套(HTML、CSS、JS)在前端所起的作用掌握HTML标签的功能&#xff0c;掌握重要标签(a标签&#xff0c;form标签)了解CSS了解JS的基础语法掌握Vue的基础语法重点掌握Vue项目怎么启动项目掌握前后端分离是什么。前端做什么事情&#xff0c;后端做什么…

基于web的古玩网站设计与实现

三、 系统总体设计 &#xff08;一&#xff09;功能设计 根据本网站的功能需要&#xff0c;设计以下功能&#xff1a; 图3.1 古玩网站主要模块 下面对各模块进行分析&#xff1a; 首 页&#xff1a;是本系统的核心&#xff0c;对各作品进行展示、定购。 公司简介&#…