zoukankan      html  css  js  c++  java
  • ffmpeg的API函数用法 :sws_scale函数的用法-具体应用

    移植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. ", SRCFILE); 
    return -1; 


    if(fout == NULL) { 
    printf("open output file %s error. ", 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! "); 
    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

  • 相关阅读:
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Navicat查询哪些表有指定字段名
  • 原文地址:https://www.cnblogs.com/cyyljw/p/8676062.html
Copyright © 2011-2022 走看看