FFmpeg: FFmepg中的sws_scale() 函数分析
FFmpeg中的 sws_scale() 函数主要是用来做视频像素格式和分辨率的转换,其优势在于:可以在同一个函数里实现:1.图像色彩空间转换, 2:分辨率缩放,3:前后图像滤波处理。不足之处在于:效率相对较低,不如libyuv或shader,其关联的函数主要有:
1.sws_getContext():
struct SwsContext *sws_getContext(
int srcW, /* 输入图像的宽度 */
int srcH, /* 输入图像的宽度 */
enum AVPixelFormat srcFormat, /* 输入图像的像素格式 */
int dstW, /* 输出图像的宽度 */
int dstH, /* 输出图像的高度 */
enum AVPixelFormat dstFormat, /* 输出图像的像素格式 */
int flags,/* 选择缩放算法(只有当输入输出图像大小不同时有效),一般选择SWS_FAST_BILINEAR */
SwsFilter *srcFilter, /* 输入图像的滤波器信息, 若不需要传NULL */
SwsFilter *dstFilter, /* 输出图像的滤波器信息, 若不需要传NULL */
const double *param /* 特定缩放算法需要的参数(?),默认为NULL */
);
与其类似的函数还有: sws_getCachedContext ,区别在于: sws_getContext 可以用于多路码流转换,为每个不同的码流都指定一个不同的转换上下文,而 sws_getCachedContext 只能用于一路码流转换。
2.sws_freeContext
// 释放sws_scale
void sws_freeContext(struct SwsContext *swsContext);
真正用来做转换的函数则是: sws_scale() ,其函数定义如下:
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[]);
下面对其函数参数进行详细说明:
1.参数 SwsContext *c, 转换格式的上下文。也就是 sws_getContext 函数返回的结果。
2.参数 const uint8_t *const srcSlice[], 输入图像的每个颜色通道的数据指针。其实就是解码后的AVFrame中的data[]数组。因为不同像素的存储格式不同,所以srcSlice[]维数
也有可能不同。
以YUV420P为例,它是planar格式,它的内存中的排布如下:
YYYYYYYY UUUU VVVV
使用FFmpeg解码后存储在AVFrame的data[]数组中时:
data[0]——-Y分量, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8…… 
data[1]——-U分量, U1, U2, U3, U4…… 
data[2]——-V分量, V1, V2, V3, V4…… 
linesize[]数组中保存的是对应通道的数据宽度 , 
linesize[0]——-Y分量的宽度 
linesize[1]——-U分量的宽度 
linesize[2]——-V分量的宽度
而RGB24,它是packed格式,它在data[]数组中则只有一维,它在存储方式如下:
data[0]: R1, G1, B1, R2, G2, B2, R3, G3, B3, R4, G4, B4……
这里要特别注意,linesize[0]的值并不一定等于图片的宽度,有时候为了对齐各解码器的CPU,实际尺寸会大于图片的宽度,这点在我们编程时(比如OpengGL硬件转换/渲染)要特别注意,否则解码出来的图像会异常。
3.参数const int srcStride[],输入图像的每个颜色通道的跨度。.也就是每个通道的行字节数,对应的是解码后的AVFrame中的linesize[]数组。根据它可以确立下一行的起始位置,不过stride和width不一定相同,这是因为:
a.由于数据帧存储的对齐,有可能会向每行后面增加一些填充字节这样 stride = width + N;
b.packet色彩空间下,每个像素几个通道数据混合在一起,例如RGB24,每个像素3字节连续存放,因此下一行的位置需要跳过3*width字节。
4.参数int srcSliceY, int srcSliceH,定义在输入图像上处理区域,srcSliceY是起始位置,srcSliceH是处理多少行。如果srcSliceY=0,srcSliceH=height,表示一次性处理完整个图像。这种设置是为了多线程并行,例如可以创建两个线程,第一个线程处理 [0, h/2-1]行,第二个线程处理 [h/2, h-1]行。并行处理加快速度。
5.参数uint8_t *const dst[], const int dstStride[]定义输出图像信息(输出的每个颜色通道数据指针,每个颜色通道行字节数)
代码示例:将解码后的数据转换成1280*720的RGBA8888 格式
1. 定义转换格式的上下文
vctx = sws_getCachedContext(
vctx,
frame->width, // 源图像的宽度
frame->height, // 源图像的高度
(AVPixelFormat)frame->format,
outWidth,
outHeight,
AV_PIX_FMT_RGBA,
SWS_FAST_BILINEAR,
, ,
);
2. 开始转换
int outWidth = ;
int outHeight = ;
char *rgb = new char[**];
uint8_t *data[AV_NUM_DATA_POINTERS] = {};
data[] = (uint8_t *)rgb;
int lines[AV_NUM_DATA_POINTERS] = {};
lines[] = outWidth * ;
int h = sws_scale(vctx,
(const uint8_t **)frame->data,
frame->linesize,
,
frame->height,
data,
lines
);
参考链接:
FFmpeg: FFmepg中的sws_scale() 函数分析的更多相关文章
- Spark Streaming中的操作函数分析
		
根据Spark官方文档中的描述,在Spark Streaming应用中,一个DStream对象可以调用多种操作,主要分为以下几类 Transformations Window Operations J ...
 - ffmpeg中的sws_scale算法性能测试
		
经常用到ffmpeg中的sws_scale来进行图像缩放和格式转换,该函数可以使用各种不同算法来对图像进行处理.以前一直很懒,懒得测试和甄 别应该使用哪种算法,最近的工作时间,很多时候需要等待别人.忙 ...
 - 【转】ffmpeg中的sws_scale算法性能测试
		
经常用到ffmpeg中的sws_scale来进行图像缩放和格式转换,该函数可以使用各种不同算法来对图像进行处理.以前一直很懒,懒得测试和甄别应该使用哪种算法,最近的工作时间,很多时候需要等待别人.忙里 ...
 - ffmpeg的API函数用法 :sws_scale函数的用法-具体应用
		
移植ffmpeg过程中,遇到swscale的用法问题,所以查到这篇文章.文章虽然已经过去很长时间,但是还有颇多可以借鉴之处.谢谢“咕咕钟. 转自:http://guguclock.blogspot.c ...
 - FFmpeg 的sws_getContext函数 、sws_scale函数
		
FFmpeg里面的sws_scale库可以在一个函数里面同时实现:1.图像色彩空间转换:2.分辨率缩放:3.前后图像滤波处理. 其核心函数主要有三个: // 初始化sws_scalestruct Sw ...
 - 解决QZ-SDK静态库libRPToolLib.a中avfoundation.o文件和kxMovie依赖的ffmpeg静态库libavdevice.a函数重复定义的问题
		
解决QZ-SDK静态库libRPToolLib.a中avfoundation.o文件和kxMovie依赖的ffmpeg静态库libavdevice.a函数重复定义的问题 在原来项目中导入全志v3相机的 ...
 - ffmpeg中AVBuffer的实现分析
		
[时间:2017-10] [状态:Open] [关键词:ffmpeg,avutil,avbuffer, 引用计数] 0 引言 AVBuffer是ffmpeg提供的基于引用计数的智能指针的一个实现版本. ...
 - C++ 类中成员函数分析
		
概述之前对成员变量的分布进行了整理,今天就对成员函数进行整理. 1.非静态成员函数C++的设计准则之一就是:非静态成员函数至少和一般的非成员函数的执行效率相同. 为了实现上衣准则,编译器会对非静态成员 ...
 - linux内核中打印栈回溯信息 - dump_stack()函数分析【转】
		
转自:http://blog.csdn.net/jasonchen_gbd/article/details/45585133 版权声明:本文为博主原创文章,转载请附上原博链接. 目录(?)[-] ...
 
随机推荐
- A - Character Encoding HDU - 6397 - 方程整数解-容斥原理
			
A - Character Encoding HDU - 6397 思路 : 隔板法就是在n个元素间的(n-1)个空中插入k-1个板,可以把n个元素分成k组的方法 普通隔板法 求方程 x+y+z=10 ...
 - 想造轮子的时候,ctrl+f一下
			
Chardet,字符编码探测器,可以自动检测文本.网页.xml的编码. colorama,主要用来给文本添加各种颜色,并且非常简单易用. Prettytable,主要用于在终端或浏览器端构建格式化的输 ...
 - ICPC Asia Regional 2015 Japan.Routing a Marathon Race(DFS)
			
vjudge \(Description\) 给定一张\(n\)个点\(m\)条边的无向图,每个点有一个权值.求一条从\(1\)到\(n\)的路径,使得代价最小,输出最小代价. 一条路径的代价定义为, ...
 - Python3基础-高级用法
			
写在前面:本文主要是python高级练习部分,介绍了一些高级用法,这些都是零散的小知识,这些可以与函数式编程合在一起使用. 函数式编程1:Python中提供的函数式编程主要有: map(函数,可迭代式 ...
 - Java并发编程(四)-- Java内存模型
			
Java内存模型 前面讲到了Java线程之间的通信采用的是共享内存模型,这里提到的共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入何时对另一个线程可见.从抽象的角 ...
 - koa2框架设置响应和请求头
			
https://koa.bootcss.com/#response 请耐心翻到网页下端,可以看到 设置响应头: ctx.set('Content-Type', 'application/zip') 添 ...
 - BZOJ4962 : 简单的字符串
			
枚举子串的中心,往两侧扩展,将两侧对应位置的字符交替写下来,得到一个字符串$S$. 若前后长度为$L$的子串循环同构,则在$S$中它们对应长度为$2L$的前缀,需要满足它可以由不超过$2$个偶回文串拼 ...
 - Flask实例化配置
			
template_folder :指定模板存放路径,默认值:temolates from flask import Flask, url_for app = Flask(__name__,templa ...
 - xcode升级至9.0之后,新建xib报错: Safe Area Layout Guide Before IOS 9.0
			
直接翻译是:iOS 9.0前安全区域布局指南. 字面意思就是safe area布局应用在iOS 9之前的版本上了. 解决方法: 1,我们可以把safe area勾掉,不用safe area布局,如下图 ...
 - session与cookie的区别是什么?如果客户端禁用了cookie功能,将会对session有什么影响?
			
cookie 和session 的区别: a.cookie数据存放在客户的浏览器上,session数据放在服务器上. b.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE ...