文档章节

sws_scale的具体用法及实例

zhangyujsj
 zhangyujsj
发布于 2015/04/24 10:59
字数 1182
阅读 63
收藏 0
移植ffmpeg过程中,遇到swscale的用法问题,所以查到这篇文章。文章虽然已经过去很长时间,但是还有颇多可以借鉴之处。谢谢“咕咕鐘"。

    

    转自:http://guguclock.blogspot.com/2009/12/ffmpeg-swscale.html

1 相关函数介绍

    如果想將某個PixelFormat轉換至另一個PixelFormat,例如,將YUV420P轉換成YUYV422,或是想變換圖的大小,都可以使用swscale達成。

其中,PixelFormat 的列表在 libavutil/pixfmt.h 內定義。

swscale的用法可以參考libswscale/swscale-example.c的sample code。主要function有三個
sws_getContext()
sws_scale()
sws_freeContext()

A sws_getContext()

其中,我們可以把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方法。

B sws_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);

這裡應該比較好懂,可以參考上面的參數說明。

C sws_freeContext()

最後,全部處理完後,需呼叫sws_freeContext() 結束。用法很簡單,把sws_getContext 取得的參數填入即可。如下

sws_freeContext(img_convert_ctx);

最後再整理一次,要使用swscale,只要使用 sws_getContext() 進行初始化、sws_scale() 進行主要轉換、sws_freeContext() 結束,即可完成全部動作。

2 实例代码

以下為一個簡單的範例程式,可從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

本文转载自:http://blog.csdn.net/bweaglegao/article/details/8540860

共有 人打赏支持
zhangyujsj
粉丝 23
博文 358
码字总数 224241
作品 0
广州
使用 liavformat 和 libavcodec 实现解码器

使用ffmpeg 的liavformat 解封装,使用libavcodec 解codec,实现一个简单的解码器。 解码的流程,从数据结构上看就是AVFormatContext ->AVCodecContext -> AVPacket -> AVFrame。 生成AVPac...

鼎铭
07/09
0
0
dtplayer中关于sdl的集成

目录 1 概述 2 AVpicture的介绍 2 sdl的集成 3 sdl2的集成 1 概述 在原生的ffmpeg提供的播放器的例子ffplay中,audio和video的输出是依靠sdl或者sdl2来完成的,具体代码如下(来自ffplay.c)...

peter_future
2014/04/23
0
0
如何用ffmpeg合并四张图片?

请问一下,如何使用ffmpeg中的sws_scale函数来将四张图片按上下各两张的方式合成一张? 有代码的希望能够发一下。 多谢了!!!

cyh24
2012/10/12
917
0
DecimalFormat的几种用法!

package com.lee.test; import java.text.DecimalFormat; import java.util.Locale; /** * DecimalFormat的几种用法! * @author lee * @depict NumberFormat.getInstance()方法返回NumberF......

AnyLiem
2015/07/07
0
0
NumberFormat用法记录

NumberFormat.getInstance()方法返回NumberFormat的一个实例(实际上是NumberFormat具体的一个子类,例如DecimalFormat), 这适合根据本地设置格式化一个数字。你也可以使用非缺省的地区设置,...

jeffsui
2013/05/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

C++ std::thread

C++11提供了std::thread类来表示一个多线程对象。 1,首先介绍一下std::this_thread命名空间: (1)std::this_thread::get_id():返回当前线程id (2)std::this_thread::yield():用户接口...

yepanl
26分钟前
1
0
Nignx缓存文件与动态文件自动均衡的配置

下面这段nginx的配置脚本的作用是,自动判断是否存在缓存文件,如果有优先输出缓存文件,不经过php,如果没有,则回到php去处理,同时生成缓存文件。 PHP框架是ThinkPHP,最后一个rewrite有关...

swingcoder
30分钟前
1
0
20180920 usermod命令与用户密码管理

命令 usermod usermod 命令的选项和 useradd 差不多。 一个用户可以属于多个组,但是gid只有一个;除了gid,其他的组(groups)叫做扩展组。 usermod -u 1010 username # 更改用户idusermod ...

野雪球
32分钟前
0
0
Java网络编程基础

1. 简单了解网络通信协议TCP/IP网络模型相关名词 应用层(HTTP,FTP,DNS等) 传输层(TCP,UDP) 网络层(IP,ICMP等) 链路层(驱动程序,接口等) 链路层:用于定义物理传输通道,通常是对...

江左煤郎
38分钟前
1
0
使用xtrabackup完成远程备份

转载收藏,以防丢失 需求 Can I backup remote databases from my local server02-27-2013, 06:17 AMHi, I am using mysqldump so far for taking daily backups of my Production datab......

阿dai
44分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部