一、环境介绍
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); }