美文网首页
ffmpeg libswscale实现YUV转RGB

ffmpeg libswscale实现YUV转RGB

作者: 曾大稳丶 | 来源:发表于2018-06-22 10:07 被阅读0次

    libswscale里面实现了各种图像像素格式的转换。

    主要函数如下:

    //使用参数初始化SwsContext结构体
    sws_getContext()
    //转换一帧图像
    sws_scale()
    //释放SwsContext结构体
    sws_freeContext()
    

    初始化函数:

    //为SwsContext结构体分配内存
    sws_alloc_context()
    //设置SwsContext结构体的值
    av_opt_set()/av_opt_set_XXX()
    //初始化SwsContext结构体。
    sws_init_context()
    

    这种复杂的方法可以配置一些sws_getContext()配置不了的参数。比如说设置图像的YUV像素的取值范围是JPEG标准(Y、U、V取值范围都是0-255)还是MPEG标准(Y取值范围是16-235,U、V的取值范围是16-240)

    获取像素格式信息:

    //可以获得指定像素格式的AVPixFmtDescriptor结构体
    av_pix_fmt_desc_get()
    //通过AVPixFmtDescriptor获取值
    av_get_bits_per_pixel() //获取比特数(bpp)
    
    

    图像拉伸:

    SWS_BICUBIC性能比较好;SWS_FAST_BILINEAR在性能和速度之间有一个比好好的平衡。
    

    示例将通过yuv文件生成rgb文件,代码如下:

    #include "stdafx.h"
    
    
    extern "C" {
        #include <libswscale/swscale.h>
        #include <libavutil/opt.h>
        #include <libavutil/imgutils.h>
    }
    
    
    void p(const char * msg, int d = -1123) {
        if (d == -1123) {
            printf_s("%s\n", msg);
        }
        else {
            printf_s("%s  %d \n", msg, d);
        }
    }
    
    
    int yuv2Rgb(FILE *yuvFile,FILE * rgbFile) {
    
        SwsContext *img_convert_ctx = NULL;
    
        const AVPixelFormat srcPixelFormat = AV_PIX_FMT_YUV420P;
        const AVPixelFormat dstPixelFormat = AV_PIX_FMT_RGB24;
    
        const int srcW = 1080;
        const int srcH= 720;
    
        const int dstW = 540;
        const int dstH = 360;
    
        uint8_t *src_data[4];
        int src_linesize[4];
    
        uint8_t *dst_data[4];
        int dst_linesize[4];
    
    
        //1. 获得指定像素格式的AVPixFmtDescriptor结构体
        const AVPixFmtDescriptor * pSrcPixFmtDes = av_pix_fmt_desc_get(srcPixelFormat);
        //2. 获得指定像素格式每个像素占用的比特数bpp(Bit Per Pixel) 
        int srcBpp=  av_get_bits_per_pixel(pSrcPixFmtDes);
    
        const AVPixFmtDescriptor * pDstPixFmtDes = av_pix_fmt_desc_get(dstPixelFormat);
        int dstBpp = av_get_bits_per_pixel(pDstPixFmtDes);
    
    
        
    
        //3. 根据宽高,像素格式分配buffer大小
        if (av_image_alloc(src_data, src_linesize, srcW, srcH, srcPixelFormat, 1) < 0) {
            p("Could not allocate source image");
            return -1;
        }
    
        if (av_image_alloc(dst_data, dst_linesize, dstW, dstH, dstPixelFormat, 1) < 0) {
            p("Could not allocate source image");
            return -1;
        }
    
        //4. 为SwsContext结构体分配内存。
        img_convert_ctx = sws_alloc_context();
        //Show AVOption
        av_opt_show2(img_convert_ctx, stdout, AV_OPT_FLAG_VIDEO_PARAM, 0);
    
    
    
    
        //图像拉伸   SWS_BICUBIC性能比较好;SWS_FAST_BILINEAR在性能和速度之间有一个比好好的平衡。
        //const int rescale_method = SWS_BICUBIC;
        //5. 设置值
        av_opt_set_int(img_convert_ctx, "sws_flags", SWS_BICUBIC | SWS_PRINT_INFO, 0);
        av_opt_set_int(img_convert_ctx, "srcw", srcW, 0);
        av_opt_set_int(img_convert_ctx, "srch", srcH, 0);
        av_opt_set_int(img_convert_ctx, "src_format", srcPixelFormat, 0);
        //'0' for MPEG (Y:0-235);'1' for JPEG (Y:0-255)
        av_opt_set_int(img_convert_ctx, "src_range", 1, 0);
        av_opt_set_int(img_convert_ctx, "dstw", dstW, 0);
        av_opt_set_int(img_convert_ctx, "dsth", dstH, 0);
        av_opt_set_int(img_convert_ctx, "dst_format", dstPixelFormat, 0);
        av_opt_set_int(img_convert_ctx, "dst_range", 1, 0);
        sws_init_context(img_convert_ctx, NULL, NULL);//对SwsContext中的各种变量进行赋值
    
        
        uint8_t *temp_buffer = (uint8_t *)malloc(srcW *srcH *srcBpp / 8);
    
        int frame_idx = 0;
        while (1){
            if (fread(temp_buffer, 1, srcW*srcH*srcBpp / 8, yuvFile) != srcW * srcH*srcBpp / 8) {
                break;
            }
    
            switch (srcPixelFormat) {
                case AV_PIX_FMT_GRAY8: {
                    memcpy(src_data[0], temp_buffer, srcW*srcH);
                    break;
                }
                case AV_PIX_FMT_YUV420P: {
                    memcpy(src_data[0], temp_buffer, srcW*srcH);                    //Y
                    memcpy(src_data[1], temp_buffer + srcW * srcH, srcW*srcH / 4);      //U
                    memcpy(src_data[2], temp_buffer + srcW * srcH * 5 / 4, srcW*srcH / 4);  //V
                    break;
                }
                case AV_PIX_FMT_YUV422P: {
                    memcpy(src_data[0], temp_buffer, srcW*srcH);                    //Y
                    memcpy(src_data[1], temp_buffer + srcW * srcH, srcW*srcH / 2);      //U
                    memcpy(src_data[2], temp_buffer + srcW * srcH * 3 / 2, srcW*srcH / 2);  //V
                    break;
                }
                case AV_PIX_FMT_YUV444P: {
                    memcpy(src_data[0], temp_buffer, srcW*srcH);                    //Y
                    memcpy(src_data[1], temp_buffer + srcW * srcH, srcW*srcH);        //U
                    memcpy(src_data[2], temp_buffer + srcW * srcH * 2, srcW*srcH);      //V
                    break;
                }
                case AV_PIX_FMT_YUYV422: {
                    memcpy(src_data[0], temp_buffer, srcW*srcH * 2);                  //Packed
                    break;
                }
                case AV_PIX_FMT_RGB24: {
                    memcpy(src_data[0], temp_buffer, srcW*srcH * 3);                  //Packed
                    break;
                }
                default: {
                    printf("Not Support Input Pixel Format.\n");
                    break;
                }
            }
    
            sws_scale(img_convert_ctx, src_data, src_linesize, 0, srcH, dst_data, dst_linesize);//转换像素
            printf("Finish process frame %5d\n", frame_idx);
            frame_idx++;
    
            switch (dstPixelFormat) {
                case AV_PIX_FMT_GRAY8: {
                    fwrite(dst_data[0], 1, dstW*dstH, rgbFile);
                    break;
                }
                case AV_PIX_FMT_YUV420P: {
                    fwrite(dst_data[0], 1, dstW*dstH, rgbFile);                 //Y
                    fwrite(dst_data[1], 1, dstW*dstH / 4, rgbFile);               //U
                    fwrite(dst_data[2], 1, dstW*dstH / 4, rgbFile);               //V
                    break;
                }
                case AV_PIX_FMT_YUV422P: {
                    fwrite(dst_data[0], 1, dstW*dstH, rgbFile);                 //Y
                    fwrite(dst_data[1], 1, dstW*dstH / 2, rgbFile);               //U
                    fwrite(dst_data[2], 1, dstW*dstH / 2, rgbFile);               //V
                    break;
                }
                case AV_PIX_FMT_YUV444P: {
                    fwrite(dst_data[0], 1, dstW*dstH, rgbFile);                 //Y
                    fwrite(dst_data[1], 1, dstW*dstH, rgbFile);                 //U
                    fwrite(dst_data[2], 1, dstW*dstH, rgbFile);                 //V
                    break;
                }
                case AV_PIX_FMT_YUYV422: {
                    fwrite(dst_data[0], 1, dstW*dstH * 2, rgbFile);               //Packed
                    break;
                }
                case AV_PIX_FMT_RGB24: {
                    fwrite(dst_data[0], 1, dstW*dstH * 3, rgbFile);               //Packed
                    break;
                }
                default: {
                    p("Not Support Output Pixel Format.\n");
                    break;
                }
            }
        }
    
        sws_freeContext(img_convert_ctx);
        free(temp_buffer);
        av_freep(&src_data[0]);
        av_freep(&dst_data[0]);
    
        return 0;
    
    
    }
    
    
    int main() {
        FILE* inFile;
        FILE* outFile;
        fopen_s(&inFile,"F:/视频资源/gxsp.yuv", "rb");
        fopen_s(&outFile, "F:/视频资源/gxsp.rgb", "wb");
        yuv2Rgb(inFile,outFile);
    
        fclose(inFile);
        fclose(outFile);
    
        getchar();
    
        return 0;
    }
    
    

    参考链接:
    libswscale实现YUV转RGB

    相关格式转换:
    视音频数据处理入门:RGB、YUV像素数据处理

    相关文章

      网友评论

          本文标题:ffmpeg libswscale实现YUV转RGB

          本文链接:https://www.haomeiwen.com/subject/zmahyftx.html