使用FFMPEG的sws_scale函數實現各種原始顏色格式互轉(YUV\RGB\)

一、環境介紹

FFMPEG版本: 4.2.2 

測試系統:ubuntu18.04

二、示例代碼

/*
YUYV轉QImage格式
*/
QImage YUYV422_TO_QImage(uint8_t *yuyv422,int image_width,int image_height)
{
    uint8_t *out_buffer= nullptr;
    AVFrame *Input_pFrame= nullptr;
    AVFrame *Output_pFrame = nullptr;
    struct SwsContext *img_convert_ctx=nullptr;  //用於解碼後的視頻格式轉換
    /*1. 申請空間*/
    Output_pFrame = av_frame_alloc();  //存放RGB數據的緩衝區
    Input_pFrame = av_frame_alloc();//存放YUV數據的緩衝區
    /*2.設置轉碼參數*/
    img_convert_ctx=sws_getContext(image_width, image_height,AV_PIX_FMT_YUYV422,
                                   image_width, image_height,AV_PIX_FMT_RGB24,
                                   SWS_BICUBIC, nullptr, nullptr, nullptr);
    /*3. 申請轉碼需要空間*/
    //獲取轉碼後數據需要的內存空間大小
    int numBytes = avpicture_get_size(AV_PIX_FMT_RGB24,image_width,image_height);
    //申請空間
    out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
    /*4. 設置轉碼的源數據地址*/
    avpicture_fill((AVPicture *) Output_pFrame, out_buffer, AV_PIX_FMT_RGB24,image_width, image_height);
    avpicture_fill((AVPicture *) Input_pFrame, yuyv422, AV_PIX_FMT_YUYV422,image_width, image_height);

    //轉格式
    sws_scale(img_convert_ctx,
     (uint8_t const **) Input_pFrame->data,
     Input_pFrame->linesize, 0, image_height, Output_pFrame->data,
     Output_pFrame->linesize);

    //加載圖片數據
    QImage image(out_buffer,image_width,image_height,QImage::Format_RGB888);

    //釋放空間
    if(Input_pFrame)av_free(Input_pFrame);
    if(Output_pFrame)av_free(Output_pFrame);
    if(out_buffer) av_free(out_buffer);
    if(img_convert_ctx)sws_freeContext(img_convert_ctx);
    return image.copy();
}

/*
YUYV轉YUV420P格式
*/
void YUYV422_TO_YUV420P(uint8_t *yuyv422,uint8_t *yuv420p,int video_width,int video_height)
{
    AVFrame *Input_pFrame= nullptr;
    AVFrame *Output_pFrame = nullptr;
    struct SwsContext *img_convert_ctx=nullptr; //用於解碼後的格式轉換
    /*1. 申請空間*/
    Input_pFrame = av_frame_alloc();
    Output_pFrame = av_frame_alloc();
    /*2.設置轉碼參數*/
    img_convert_ctx=sws_getContext(video_width, video_height,AV_PIX_FMT_YUYV422, //輸入
                                   video_width, video_height,AV_PIX_FMT_YUV420P,   //輸出
                                   SWS_BICUBIC, nullptr, nullptr, nullptr);
    /*3. 申請轉碼需要空間*/
    /*4. 設置轉碼的源數據地址*/
    avpicture_fill((AVPicture *) Input_pFrame, yuyv422, AV_PIX_FMT_YUYV422,video_width, video_height);
    avpicture_fill((AVPicture *) Output_pFrame, yuv420p, AV_PIX_FMT_YUV420P,video_width, video_height);

    //轉格式
    sws_scale(img_convert_ctx,
     (uint8_t const **) Input_pFrame->data,Input_pFrame->linesize,
      0, video_height, Output_pFrame->data,Output_pFrame->linesize);
    //釋放空間
    if(Input_pFrame)av_free(Input_pFrame);
    if(Output_pFrame)av_free(Output_pFrame);
    if(img_convert_ctx)sws_freeContext(img_convert_ctx);
}

/*
YUYV422轉RGB888格式
*/
void YUYV422_TO_RGB888(uint8_t *yuyv422,uint8_t *rgb888,int image_width,int image_height)
{
    AVFrame *Input_pFrame= nullptr;
    AVFrame *Output_pFrame = nullptr;
    struct SwsContext *img_convert_ctx=nullptr;  //用於解碼後的視頻格式轉換
    /*1. 申請空間*/
    Output_pFrame = av_frame_alloc();  //存放RGB數據的緩衝區
    Input_pFrame = av_frame_alloc();//存放YUV數據的緩衝區
    /*2.設置轉碼參數*/
    img_convert_ctx=sws_getContext(image_width, image_height,AV_PIX_FMT_YUYV422,
                                   image_width, image_height,AV_PIX_FMT_RGB24,
                                   SWS_BICUBIC, nullptr, nullptr, nullptr);
    /*4. 設置轉碼的源數據地址*/
    avpicture_fill((AVPicture *) Output_pFrame, rgb888, AV_PIX_FMT_RGB24,image_width, image_height);
    avpicture_fill((AVPicture *) Input_pFrame, yuyv422, AV_PIX_FMT_YUYV422,image_width, image_height);

    //轉格式
    sws_scale(img_convert_ctx,
     (uint8_t const **) Input_pFrame->data,
     Input_pFrame->linesize, 0, image_height, Output_pFrame->data,
     Output_pFrame->linesize);

    //釋放空間
    if(Input_pFrame)av_free(Input_pFrame);
    if(Output_pFrame)av_free(Output_pFrame);
    if(img_convert_ctx)sws_freeContext(img_convert_ctx);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章