ffmpeg 中 swscale 的用法
http://www.guguclock.com/2009/12/ffmpeg-swscale.html
如果想將某個PixelFormat轉換至另一個PixelFormat,例如,將YUV420P轉換成YUYV422,或是想變換圖的大小,都可以使用swscale達成。
其中,PixelFormat 的列表在 libavutil/pixfmt.h 內定義。
swscale的用法可以參考libswscale/swscale-example.c的sample code。主要function有三個
- sws_getContext()
- sws_scale()
- sws_freeContext()
其中,我們可以把sws_getContext() 看成初始化函數,把sws_freeContext()看成結束函數。這兩個函數分別在起始及結束各執行一次即可。
真正主要的函數,是sws_scale()。
sws_getContext() 的宣告如下
SwsContext *sws_getContext(int srcW, int srcH, enum PixelFormat srcFormat, int dstW, int dstH, enum PixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param)
總共有十個參數,其中,較重要的是前七個;
前三個參數分別代表 source 的寬、高及PixelFormat;
四到六個參數分別代表 destination 的寬、高及PixelFormat;
第七個參數則代表要使用哪種scale的方法;此參數可用的方法可在 libswscale/swscale.h 內找到。
最後三個參數,如無使用,可以都填上NULL。
sws_getContext會回傳一個 SwsContext struct,我們可以把這個 struct 看成是個 handler,之後的sws_scale和sws_freeContext皆會用到。
以下是一個sws_getContext的簡單例子:
struct SwsContext *img_convert_ctx;
img_convert_ctx = sws_getContext(in_width, in_height, PIX_FMT_YUV420P,
out_width, out_height, PIX_FMT_YUV420P, SWS_POINT,
NULL, NULL, NULL);
一開始,我們宣告img_convert_ctx 為指向 SwsContext 的一個 pointer;接著,我們將 sws_getContext 的回傳值賦予給img_convert_ctx。
注
意sws_getContext的參數;in_width及in_height分別代表 source
的寬及高,out_width及out_height分別代表轉換後的寬與高;input 和 output 的 PixelFormat 皆為
YUV420P;使用SWS_POINT的scale方法。
初始化完成後,接著就要進行主要的 scale 動作;我們透過 sws_scale() 完成。sws_scale() 的宣告如下
int sws_scale(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t* dst[], int dstStride[])
總共有七個參數;
第一個參數即是由 sws_getContext 所取得的參數。
第二個 src 及第六個 dst 分別指向input 和 output 的 buffer。
第三個 srcStride 及第七個 dstStride 分別指向 input 及 output 的 stride;如果不知道什麼是 stride,姑且可以先把它看成是每一列的 byte 數。
第四個 srcSliceY,就註解的意思來看,是指第一列要處理的位置;這裡我是從頭處理,所以直接填0。想知道更詳細說明的人,可以參考 swscale.h 的註解。
第五個srcSliceH指的是 source slice 的高度。
舉一個例子如下
sws_scale(img_convert_ctx, inbuf, inlinesize, 0, in_height, outbuf, outlinesize);
這裡應該比較好懂,可以參考上面的參數說明。
最後,全部處理完後,需呼叫sws_freeContext() 結束。用法很簡單,把sws_getContext 取得的參數填入即可。如下
sws_freeContext(img_convert_ctx);
最後再整理一次,要使用swscale,只要使用 sws_getContext() 進行初始化、sws_scale() 進行主要轉換、sws_freeContext() 結束,即可完成全部動作。
以下為一個簡單的範例程式,可從foreman.yuv內取出第一張圖,轉換大小後存成另一張圖。
=====================================================================================
/*
* 需設定 SRCFILE 及 DSTFILE, 長寬等資訊
* 需 link libswscale
* 主要有三個 function
* sws_getContext() 是 initial 用, sws_freeContext() 是結束用
* sws_scale() 是主要運作的 function
* 預設只會轉換第一張 YUV, 如果要轉換整個檔, 可以把 Decoding loop 的註解拿掉
*/
#include "libswscale/swscale.h"
#define SRCFILE "foreman_cif.yuv"
#define DSTFILE "out.yuv"
int main()
{
// 設定原始 YUV 的長寬
const int in_width = 352;
const int in_height = 288;
// 設定目的 YUV 的長寬
const int out_width = 640;
const int out_height = 480;
const int read_size = in_width * in_height * 3 / 2;
const int write_size = out_width * out_height * 3 / 2;
struct SwsContext *img_convert_ctx;
uint8_t *inbuf[4];
uint8_t *outbuf[4];
int inlinesize[4] = {in_width, in_width/2, in_width/2, 0};
int outlinesize[4] = {out_width, out_width/2, out_width/2, 0};
uint8_t in[352*288*3>>1];
uint8_t out[640*480*3>>1];
FILE *fin = fopen(SRCFILE, "rb");
FILE *fout = fopen(DSTFILE, "wb");
if(fin == NULL) {
printf("open input file %s error.\n", SRCFILE);
return -1;
}
if(fout == NULL) {
printf("open output file %s error.\n", DSTFILE);
return -1;
}
inbuf[0] = malloc(in_width*in_height);
inbuf[1] = malloc(in_width*in_height>>2);
inbuf[2] = malloc(in_width*in_height>>2);
inbuf[3] = NULL;
outbuf[0] = malloc(out_width*out_height);
outbuf[1] = malloc(out_width*out_height>>2);
outbuf[2] = malloc(out_width*out_height>>2);
outbuf[3] = NULL;
// ********* Initialize software scaling *********
// ********* sws_getContext **********************
img_convert_ctx = sws_getContext(in_width, in_height, PIX_FMT_YUV420P,
out_width, out_height, PIX_FMT_YUV420P, SWS_POINT,
NULL, NULL, NULL);
if(img_convert_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context!\n");
return -1;
}
fread(in, 1, read_size, fin);
memcpy(inbuf[0], in, in_width*in_height);
memcpy(inbuf[1], in+in_width*in_height, in_width*in_height>>2);
memcpy(inbuf[2], in+(in_width*in_height*5>>2), in_width*in_height>>2);
// ********* 主要的 function ******
// ********* sws_scale ************
sws_scale(img_convert_ctx, inbuf, inlinesize,
0, in_height, outbuf, outlinesize);
memcpy(out, outbuf[0], out_width*out_height);
memcpy(out+out_width*out_height, outbuf[1], out_width*out_height>>2);
memcpy(out+(out_width*out_height*5>>2), outbuf[2], out_width*out_height>>2);
fwrite(out, 1, write_size, fout);
// ********* 結束的 function *******
// ********* sws_freeContext *******
sws_freeContext(img_convert_ctx);
fclose(fin);
fclose(fout);
return 0;
}
ffmpeg 中 swscale 的用法的更多相关文章
- ffmpeg中swscale 的用法
移植ffmpeg过程中,遇到swscale的用法问题,所以查到这篇文章.文章虽然已经过去很长时间,但是还有颇多可以借鉴之处.谢谢“咕咕鐘". 转自:http://guguclock.blog ...
- FFmpeg中overlay滤镜用法-水印及画中画
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10434209.html 1. overlay技术简介 overlay技术又称视频叠加技术 ...
- ffmpeg的API函数用法 :sws_scale函数的用法-具体应用
移植ffmpeg过程中,遇到swscale的用法问题,所以查到这篇文章.文章虽然已经过去很长时间,但是还有颇多可以借鉴之处.谢谢“咕咕钟. 转自:http://guguclock.blogspot.c ...
- 零基础学习视频解码之FFMpeg中比较重要的函数以及数据结构
http://www.cnblogs.com/tanlon/p/3879081.html 在正式开始解码练习前先了解下关于FFmpeg中比较重要的函数以及数据结构. 1. 数据结构: (1) AVF ...
- FFmpeg缩放swscale详解 <转>
利用ffmpeg进行图像数据格式的转换以及图片的缩放应用中,主要用到了swscale.h文件中的三个函数,分别是: struct SwsContext *sws_getContext(int srcW ...
- ffmpeg中AVOption的实现分析
[时间:2017-10] [状态:Open] [关键词:ffmpeg,avutil,AVOption] 0 引言 AVOptions提供了一种通用的options机制,可以用于任意特定结构的对象. 本 ...
- ffmpeg中av_log的实现分析
[时间:2017-10] [状态:Open] [关键词:ffmpeg,avutil,av_log, 日志输出] 0 引言 FFmpeg的libavutil中的日志输出的接口整体比较少,但是功能还是不错 ...
- ffmpeg中AVBuffer的实现分析
[时间:2017-10] [状态:Open] [关键词:ffmpeg,avutil,avbuffer, 引用计数] 0 引言 AVBuffer是ffmpeg提供的基于引用计数的智能指针的一个实现版本. ...
- [原]零基础学习视频解码之FFMpeg中比较重要的函数以及数据结构
在正式开始解码练习前先了解下关于FFmpeg中比较重要的函数以及数据结构. 1. 数据结构: (1) AVFormatContext AVFormatContext是一个贯穿始终的数据结构,很多函 ...
随机推荐
- Server Develop (七) Linux 守护进程
守护进程 守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程常常在系统引导装 ...
- [游戏学习25] MFC 橡皮筋画线效果
>_<:这是给出窗口内外不同情况的处理展示的例子. >_<:MouseCap.h #include<afxwin.h> class CMyApp :public C ...
- WPF oxyPlot 使用总结
oxyPlot能够简易的创建图表并且该库也在Github上面开源直通门.以下是笔者基础使用总结.本文例子的源码下载 1.安装与引用 新建一个wpf应用程序,然后使用Nuget控制台安装OxyPlot和 ...
- 编码剖析Spring管理bean的原理
project目录 MyClassPathXMLApplicationContext读取xml,以及实例化bean. 因为是一开始实例化配置文件所有bean,所以需要构造器完成这些工作. packag ...
- 记一次https访问握手失败(handshake failure)
文章作者:luxianghao 文章来源:http://www.cnblogs.com/luxianghao/p/6239518.html 转载请注明,谢谢合作. 免责声明:文章内容仅代表个人观点, ...
- iOS开发----地图与导航--定位和位置信息获取
要实现地图.导航功能,往往需要先熟悉定位功能,在iOS中通过Core Location框架进行定位操作.Core Location自身可以单独使用,和地图开发框架MapKit完全是独立的,但是往往地图 ...
- MYSQL操作数据表中的记录
36:操作数据表中的记录插入记录 INSERT INTO 表名 VALUES(); 或者INSERT 表名 VALUES(); UPDATE更新记录(单表更新) DELETE删除记录( ...
- Leetcode 299 Bulls and Cows 字符串处理 统计
A就是统计猜对的同位同字符的个数 B就是统计统计猜对的不同位同字符的个数 非常简单的题 class Solution { public: string getHint(string secret, s ...
- 微软BI 之SSIS 系列 - 通过设置 CheckPoints 检查点来增强 SSIS Package 流程的重用性
开篇介绍 通常一个 ETL Package 是由多个控制流和数据流共同组成,有的时候 ETL 的步骤可能会比较多,整个流程执行下来的时间可能比较长.假设在 ETL Package 中包含5个Task, ...
- android: 通过内容提供器读取系统联系人
读取系统联系人 由于我们之前一直使用的都是模拟器,电话簿里面并没有联系人存在,所以现在需要自 己手动添加几个,以便稍后进行读取.打开电话簿程序,界面如图 7.1 所示. 图 7.1 可以看到,目前 ...