移植ffmpeg过程中,遇到swscale的用法问题,所以查到这篇文章。文章虽然已经过去很长时间,但是还有颇多可以借鉴之处。谢谢“咕咕鐘"。

转自:http://guguclock.blogspot.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; 
}

=====================================================================================

以下兩張圖為執行結果

Input Image

Output Image

 
0

sws_scale函数的用法-具体应用的更多相关文章

  1. ffmpeg的API函数用法 :sws_scale函数的用法-具体应用

    移植ffmpeg过程中,遇到swscale的用法问题,所以查到这篇文章.文章虽然已经过去很长时间,但是还有颇多可以借鉴之处.谢谢“咕咕钟. 转自:http://guguclock.blogspot.c ...

  2. 有关日期的函数操作用法总结,to_date(),trunc(),add_months();

    相关知识链接: Oracle trunc()函数的用法 oracle add_months函数 Oracle日期格式转换,tochar(),todate() №2:取得当前日期是一个星期中的第几天,注 ...

  3. Oracle to_date()函数的用法

    Oracle to_date()函数的用法 to_date()是Oracle数据库函数的代表函数之一,下文对Oracle to_date()函数的几种用法作了详细的介绍说明,供您参考学习. 在Orac ...

  4. js中bind、call、apply函数的用法

    最近一直在用 js 写游戏服务器,我也接触 js 时间不长,大学的时候用 js 做过一个 H3C 的 web的项目,然后在腾讯实习的时候用 js 写过一些奇怪的程序,自己也用 js 写过几个的网站.但 ...

  5. Oracle trunc()函数的用法

    Oracle trunc()函数的用法 /**************日期********************/1.select trunc(sysdate) from dual --2013-0 ...

  6. freemarker内置函数和用法

    原文链接:http://www.iteye.com/topic/908500 在我们应用Freemarker 过程中,经常会操作例如字符串,数字,集合等,却不清楚Freemrker 有没有类似于Jav ...

  7. matlab中patch函数的用法

    http://blog.sina.com.cn/s/blog_707b64550100z1nz.html matlab中patch函数的用法——emily (2011-11-18 17:20:33) ...

  8. JavaScript中常见的数组操作函数及用法

    JavaScript中常见的数组操作函数及用法 昨天写了个帖子,汇总了下常见的JavaScript中的字符串操作函数及用法.今天正好有时间,也去把JavaScript中常见的数组操作函数及用法总结一下 ...

  9. JavaScript中常见的字符串操作函数及用法

    JavaScript中常见的字符串操作函数及用法 最近几次参加前端实习生招聘的笔试,发现很多笔试题都会考到字符串的处理,比方说去哪儿网笔试题.淘宝的笔试题等.如果你经常参加笔试或者也是一个过来人,相信 ...

随机推荐

  1. Laravel开发:多用户登录验证(1)

    之前实现了一次,后来代码忘记放哪了,所以有跳了一次坑. 先贴上Laravel自带的验证代码: 路由:routes/web.php // Authentication Routes... $this-& ...

  2. linux php.ini又一次载入问题

    今天发现自己server改动php.ini之后无法又一次载入! .无法使用php-fpm reload,奇怪.! 后来查了一下.能够使用 /etc/init.d/php-fpm reload 来又一次 ...

  3. 在UIWebView中设置cookie

     本文转载至 http://blog.csdn.net/chengyakun11/article/details/8863878 项目中,需要在打开3g网页时,通过cookie传递一些信息. 实现代码 ...

  4. 洛谷P1038 神经网络==codevs1088 神经网络

    P1038 神经网络 题目背景 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别.函数逼近及贷款风险评估等诸多领域有广泛的应用.对神 ...

  5. Spring中的国际化资源以及视图跳转

    一.SpringMVC对国际化的支持 SpringMVC进行资源国际化主要是通过ResourceBundleMessageSource实现的,xml如下配置: <bean id="me ...

  6. java拾遗2----XML解析(二) SAX解析

    XML解析之SAX解析: SAX解析器:SAXParser类同DOM一样也在javax.xml.parsers包下,此类的实例可以从 SAXParserFactory.newSAXParser() 方 ...

  7. JVM相关的几个基本概念

    1.虚拟机是指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统 2.常见的虚拟机有VMWare,Visual Box,JVM等 VMWare或者Visual Box模拟的 ...

  8. 程序运行之ELF文件结构

    ELF目标文件格式的最前部是ELF文件头.包含了整个文件的基本属性.比如ELF文件版本,目标机器型号,程序入口地址等.然后是ELF的各个段,其中ELF文件中与段有关的重要结构就是段表.段表描述了ELF ...

  9. 保护眼睛,win7家庭版如何修改窗口的背景颜色

    win7的窗口背景色为白色,长时间使用电脑对眼睛的刺激比较大,为了保护眼睛建议改成浅灰色或者淡绿.淡黄色等,可是win7的家庭版里没有[个性化]菜单,那么我们如何修改呢? 首先在[开始]处找到[控制面 ...

  10. selenium鼠标悬停操作

    有些网页一打开会有一个弹窗,弹窗不消失无法进行取元素操作,只有把鼠标悬停在上面弹窗才会消失,这时就用到了selenium的悬停操作 鼠标悬停  move_to_element() 定位到要悬停的元素 ...