[ffmpeg] 视频格式转换
本文主要梳理 ffmpeg 中的视频格式转换。由于上屏的数据是 rgba,编码使用的是 yuv数据,所以经常会使用到视频格式的转换。
除了使用 ffmpeg进行转换,还可以通过 libyuv 和 directX 写 shader 进行转换。
之前看到文章说 libyuv 之前是 ffmpeg 的一部分,后面独立出去了,好像 libyuv 的效率会高一点,没有实测过,后面可以对比一下。
API 调用
常用 API
struct SwsContext *sws_alloc_context(void);
int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter);
void sws_freeContext(struct SwsContext *swsContext);struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param);
struct SwsContext *sws_getCachedContext(struct SwsContext *context, int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param);
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]);
int sws_scale_frame(struct SwsContext *c, AVFrame *dst, const AVFrame *src);
初始化和销毁相关
sws_alloc_context 创建 context 上下文结构体
sws_init_context 初始化 context 结构体(不推荐使用)
sws_freeContext 销毁结构体
SwsContext class 定义 libswscale\options.c
const AVClass ff_sws_context_class = {.class_name = "SWScaler",.item_name = sws_context_to_name,.option = swscale_options,.parent_log_context_offset = OFFSET(parent),.category = AV_CLASS_CATEGORY_SWSCALER,.version = LIBAVUTIL_VERSION_INT,
};
sws_init_context 之前需要配置 context 一些参数,才能正确初始化。
context = sws_alloc_context()context->srcW = srcW;context->srcH = srcH;context->srcFormat = srcFormat;context->dstW = dstW;context->dstH = dstH;context->dstFormat = dstFormat;context->flags = flags;context->param[0] = param[0];context->param[1] = param[1];sws_init_context(context, srcFilter, dstFilter)
为了简化调用所以有了 sws_getContext 接口,其主要就是做了 1. sws_alloc_context 调用;2.参数设置;3.sws_init_context 调用。
sws_getCachedContext 在sws_getContext 基础上加了 context 的判断,如果之前使用的 context 和本次的参数都一样,则复用之前的 context,否则销毁重新创建。
if (context && (context->srcW != srcW || context->srcH != srcH || context->srcFormat != srcFormat || context->dstW != dstW || context->dstH != dstH || context->dstFormat != dstFormat || context->flags != flags || context->param[0] != param[0] || context->param[1] != param[1]))
类型转换
sws_scale
sws_scale_frame
输出结果是直接写在输入的内存上的,索引 data 需要提前分配好内存
demo 调用
m_vsc = sws_getCachedContext(m_vsc,m_inWidth, m_inHeight, (AVPixelFormat)m_inPixFormat,m_outWidth, m_outHeight, AV_PIX_FMT_YUV420P,SWS_BICUBIC,NULL, NULL, NULL);
m_yuv = av_frame_alloc();m_yuv->format = AV_PIX_FMT_YUV420P;m_yuv->width = m_outWidth;m_yuv->height = m_outHeight;m_yuv->pts = 0;
int ret = av_frame_get_buffer(m_yuv, 32);uint8_t* indata[AV_NUM_DATA_POINTERS] = { 0 };
indata[0] = (uint8_t*)rgb;
int insize[AV_NUM_DATA_POINTERS] = { 0 };
insize[0] = m_inWidth * 4;int h = sws_scale(m_vsc, indata, insize, 0, m_inHeight,
m_yuv->data, m_yuv->linesize);if (m_vsc)
{sws_freeContext(m_vsc);m_vsc = NULL;
}
其他
所有接口
unsigned swscale_version(void);
const char *swscale_configuration(void);
const char *swscale_license(void);
const int *sws_getCoefficients(int colorspace);
int sws_isSupportedInput(enum AVPixelFormat pix_fmt);
int sws_isSupportedOutput(enum AVPixelFormat pix_fmt);
int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt);
struct SwsContext *sws_alloc_context(void);
int sws_init_context(struct SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter);
void sws_freeContext(struct SwsContext *swsContext);
struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,int dstW, int dstH, enum AVPixelFormat dstFormat,int flags, SwsFilter *srcFilter,SwsFilter *dstFilter, const double *param);
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],const int srcStride[], int srcSliceY, int srcSliceH,uint8_t *const dst[], const int dstStride[]);
int sws_scale_frame(struct SwsContext *c, AVFrame *dst, const AVFrame *src);
int sws_frame_start(struct SwsContext *c, AVFrame *dst, const AVFrame *src);
void sws_frame_end(struct SwsContext *c);
int sws_send_slice(struct SwsContext *c, unsigned int slice_start,unsigned int slice_height);
int sws_receive_slice(struct SwsContext *c, unsigned int slice_start,unsigned int slice_height);
unsigned int sws_receive_slice_alignment(const struct SwsContext *c);
int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4],int srcRange, const int table[4], int dstRange,int brightness, int contrast, int saturation);
int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table,int *srcRange, int **table, int *dstRange,int *brightness, int *contrast, int *saturation);
SwsVector *sws_allocVec(int length);
SwsVector *sws_getGaussianVec(double variance, double quality);
void sws_scaleVec(SwsVector *a, double scalar);
void sws_normalizeVec(SwsVector *a, double height);void sws_freeVec(SwsVector *a);SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur,float lumaSharpen, float chromaSharpen,float chromaHShift, float chromaVShift,int verbose);
void sws_freeFilter(SwsFilter *filter);
struct SwsContext *sws_getCachedContext(struct SwsContext *context,int srcW, int srcH, enum AVPixelFormat srcFormat,int dstW, int dstH, enum AVPixelFormat dstFormat,int flags, SwsFilter *srcFilter,SwsFilter *dstFilter, const double *param);
void sws_convertPalette8ToPacked32(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette);
void sws_convertPalette8ToPacked24(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette);
const AVClass *sws_get_class(void);
class 类型
typedef enum {AV_CLASS_CATEGORY_NA = 0,AV_CLASS_CATEGORY_INPUT,AV_CLASS_CATEGORY_OUTPUT,AV_CLASS_CATEGORY_MUXER,AV_CLASS_CATEGORY_DEMUXER,AV_CLASS_CATEGORY_ENCODER,AV_CLASS_CATEGORY_DECODER,AV_CLASS_CATEGORY_FILTER,AV_CLASS_CATEGORY_BITSTREAM_FILTER,AV_CLASS_CATEGORY_SWSCALER,AV_CLASS_CATEGORY_SWRESAMPLER,AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40,AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT,AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,AV_CLASS_CATEGORY_DEVICE_OUTPUT,AV_CLASS_CATEGORY_DEVICE_INPUT,AV_CLASS_CATEGORY_NB ///< not part of ABI/API
}AVClassCategory;
相关文章:
[ffmpeg] 视频格式转换
本文主要梳理 ffmpeg 中的视频格式转换。由于上屏的数据是 rgba,编码使用的是 yuv数据,所以经常会使用到视频格式的转换。 除了使用 ffmpeg进行转换,还可以通过 libyuv 和 directX 写 shader 进行转换。 之前看到文章说 libyuv 之前是 ffmpeg…...
git-repo系列教程(3) git-repo https证书认证问题
文章目录 问题描述解决步骤1.下载证书2.测试证书是否正常3.设置环境变量 总结 问题描述 在使用git repo 同步仓库时,发现不能同步,出现如下提示错误: % Total % Received % Xferd Average Speed Time Time Time CurrentDload Upload Total Spent Left …...
中序遍历二叉树全过程图解
文章目录 中序遍历图解总结拓展:回归与回溯 中序遍历图解 首先看下中序遍历的代码,其接受一个根结点root作为参数,判断根节点是否为nil,不为nil则先递归遍历左子树。 func traversal(root *TreeNode,res *[]int) {if root nil …...
设计模式 组合模式(Composite Pattern)
组合模式简绍 组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端可以用一致的方式处理单个对象和组合对象。这样,可以在不知道对象具体类型的条…...
在vue中嵌入vitepress,基于markdown文件生成静态网页从而嵌入社团周报系统的一些想法和思路
什么是vitepress vitepress是一种将markdown文件渲染成静态网页的技术 其使用仅需几行命令即可 //在根目录安装vitepress npm add -D vitepress //初始化vitepress,添加相关配置文件,选择主题,描述,框架等 npx vitepress init //…...
神经网络面试题目
1. 批规范化(Batch Normalization)的好处都有啥?、 A. 让每一层的输入的范围都大致固定 B. 它将权重的归一化平均值和标准差 C. 它是一种非常有效的反向传播(BP)方法 D. 这些均不是 正确答案是:A 解析: batch normalization 就…...
C语言题目之单身狗2
文章目录 一、题目二、思路三、代码实现 提示:以下是本篇文章正文内容,下面案例可供参考 一、题目 二、思路 第一步 在c语言题目之打印单身狗我们已经讲解了在一组数据中出现一个单身狗的情况,而本道题是出现两个单身狗的情况。根据一个数…...
Vue2学习笔记(03关于VueComponent)
1.school组件本质是一个名为Vuecomponent的构造函数,且不是程序员定义的,是Vue.extend生成的。 2.我们只需要写<school/>或<school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new Vuecompo…...
微服务架构中常用技术框架
认证授权 Spring Security OAuth 2.0 JWT Keycloak Istio Apache Shiro 日志监控 ELK Prometheus Grafana Fluentd CI/CD Jenkins GitLab CI CircleCI ArgoCD 服务通信 gRPC REST API Apache Thrift Apache Avro Apache Dubbo OpenFegin 断路器 Hystr…...
[深度学习]Pytorch框架
1 深度学习简介 应用领域:语音交互、文本处理、计算机视觉、深度学习、人机交互、知识图谱、分析处理、问题求解2 发展历史 1956年人工智能元年2016年国内开始关注深度学习2017年出现Transformer框架2018年Bert和GPT出现2022年,chatGPT出现,进入AIGC发展阶段3 PyTorch框架简…...
华为HarmonyOS灵活高效的消息推送服务(Push Kit) - 5 发送通知消息
场景介绍 通知消息通过Push Kit通道直接下发,可在终端设备的通知中心、锁屏、横幅等展示,用户点击后拉起应用。您可以通过设置通知消息样式来吸引用户。 开通权益 Push Kit根据消息内容,将通知消息分类为服务与通讯、资讯营销两大类别&…...
[Meachines] [Medium] Querier XLSM宏+MSSQL NTLM哈希窃取(xp_dirtree)+GPP凭据泄露
信息收集 IP AddressOpening Ports10.10.10.125TCP:135, 139, 445, 1433, 5985, 47001, 49664, 49665, 49666, 49667, 49668, 49669, 49670, 49671 $ nmap -p- 10.10.10.125 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 135/tcp open msrp…...
新版ssh客户端无法连接旧版服务器sshd的方法
新安装完的windows 版本,连Linux服务器直接报错 C:\Users\wang>ssh root192.168.110.50 Unable to negotiate with 192.168.110.50 port 22: no matching key exchange method found. Their offer: diffie-hellman-group14-sha1,diffie-hellman-group1-sha1,kex…...
MyBatis操作数据库-XML实现
目录 1.MyBatis的简单介绍 2.MyBatis操作数据库的步骤 2.1 添加依赖 2.2 配置文件 2.3 写持久层代码 2.4 方法测试 3.MyBatis操作数据库(增删查改) 3.1 CRUD标签 3.2 参数传递 3.3 Insert-新增 3.4 Delete-删除 3.5 Update-修改 3.6 Select-查询(映射问题) 1.MyB…...
华为HarmonyOS地图服务 5 - 利用UI控件和手势进行地图交互
场景介绍 本章节将向您介绍如何使用地图的手势。 Map Kit提供了多种手势供用户与地图之间进行交互,如缩放、滚动、旋转和倾斜。这些手势默认开启,如果想要关闭某些手势,可以通过MapComponentController类提供的接口来控制手势的开关。 接口…...
解决DockerDesktop启动redis后采用PowerShell终端操作
如图: 在启动redis容器后,会计入以下界面 : 在进入执行界面后如图: 是否会觉得界面过于单调,于是想到使用PowerShell来操作。 步骤如下: 这样就能使用PowerShell愉快地敲命令了(颜值是第一生…...
react + antDesign封装图片预览组件(支持多张图片)
需求场景:最近在开发后台系统时经常遇到图片预览问题,如果一个一个的引用antDesign的图片预览组件就有点繁琐了,于是在antDesign图片预览组件的基础上二次封装了一下,避免重复无用代码的出现 效果 公共预览组件代码 import React…...
逻辑回归 和 支持向量机(SVM)比较
为了更好地理解为什么在二分类问题中使用 SVM,逻辑回归的区别,我们需要深入了解这两种算法的区别、优势、劣势,以及它们适用于不同场景的原因。 逻辑回归和 SVM 的比较 1. 模型的核心思想 • 逻辑回归: • 基于概率的模型&…...
GS-SLAM论文阅读笔记--TAMBRIDGE
前言 本文提出了一个自己的分类方法,传统的视觉SLAM通常使用以帧为中心的跟踪方法,但是3DGS作为一种高效的地图表达方法好像更侧重于地图的创建。这两种方法都有各自的优缺点,但是如果能取长补短,互相结合,那么就会是…...
[Redis面试高频] - zset的底层数据结构
文章目录 [Redis面试高频] - zset的底层数据结构一、引言二、zset 的底层数据结构1、zset 的编码方式1.1、ziplist 编码1.2、skiplist 编码 1.3、ziplist 编码适用条件1.4、skiplist 编码适用条件2、zset 的操作命令 三、zset 的性能考量1、内存效率2、搜索效率 四、总结 [Redi…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
