使用FFMPEG的sws_scale函数实现各种原始颜色格式互转(YUV\RGB\)

简介: 使用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);
}

目录
相关文章
|
7月前
|
存储 编解码 数据处理
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码(三)
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码
225 0
|
7月前
|
存储 编解码 数据处理
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码(二)
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码
254 0
|
2月前
FFmpeg中结构释放小函数
本文介绍了FFmpeg中用于释放不同结构体内存的泛化变参模板函数CleanUp,以及如何特化该模板以释放AVFormatContext、AVCodecContext、AVPacket、AVFrame和uint8_t*类型的内存,并提供了一个测试文件来演示这些函数的使用。
27 3
|
2月前
FFmpeg学习笔记(二):多线程rtsp推流和ffplay拉流操作,并储存为多路avi格式的视频
这篇博客主要介绍了如何使用FFmpeg进行多线程RTSP推流和ffplay拉流操作,以及如何将视频流保存为多路AVI格式的视频文件。
348 0
|
5月前
|
存储 编解码 容器
FFmpeg avformat_open_input() 函数返回错误protocol not found解决方法(实测有效!附简单FFMPEG的编解码流程)
我个人出现这个错误的时候是在打开文件时报的错误,开始以为我需要加上资源文件,那样QT确实能检测到文件的存在,但是在Debug中他是检测不到这个文件的。
582 1
|
6月前
|
编解码 Linux 计算机视觉
python 调用ffmpeg使用usb摄像头录制视频,输出h264格式,自动获取摄像头的最佳帧率和最大画面尺寸
使用 Python 调用 FFmpeg 进行 USB 摄像头视频录制,需先确保安装 FFmpeg 和 Python 的 `subprocess` 模块。代码示例展示了如何自动获取摄像头的最佳帧率和最大分辨率,然后录制视频。首先通过 FFmpeg 列出摄像头格式获取信息,解析出帧率和分辨率,选择最优值。之后调用 FFmpeg 命令录制视频,设置帧率、分辨率等参数。注意 `/dev/video0` 是 Linux 的摄像头设备路径,Windows 系统需相应调整。代码中未直接实现自动获取最佳参数,通常需要借助其他库如 OpenCV。
|
7月前
FFmpeg开发笔记(十八)FFmpeg兼容各种音频格式的播放
《FFmpeg开发实战》一书中,第10章示例程序playaudio.c原本仅支持mp3和aac音频播放。为支持ogg、amr、wma等非固定帧率音频,需进行三处修改:1)当frame_size为0时,将输出采样数量设为512;2)遍历音频帧时,计算实际采样位数以确定播放数据大小;3)在SDL音频回调函数中,确保每次发送len字节数据。改进后的代码在chapter10/playaudio2.c,可编译运行播放ring.ogg测试,成功则显示日志并播放铃声。
131 1
FFmpeg开发笔记(十八)FFmpeg兼容各种音频格式的播放
|
7月前
|
编解码 算法 C++
【ffmpeg 基础函数】详解FFmpeg中的av_packet_ref函数
【ffmpeg 基础函数】详解FFmpeg中的av_packet_ref函数
73 0
|
2月前
|
Linux 开发工具 Android开发
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
ijkplayer是由Bilibili基于FFmpeg3.4研发并开源的播放器,适用于Android和iOS,支持本地视频及网络流媒体播放。本文详细介绍如何在新版Android Studio中导入并使用ijkplayer库,包括Gradle版本及配置更新、导入编译好的so文件以及添加直播链接播放代码等步骤,帮助开发者顺利进行App调试与开发。更多FFmpeg开发知识可参考《FFmpeg开发实战:从零基础到短视频上线》。
213 2
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
|
2月前
|
编解码 语音技术 内存技术
FFmpeg开发笔记(五十八)把32位采样的MP3转换为16位的PCM音频
《FFmpeg开发实战:从零基础到短视频上线》一书中的“5.1.2 把音频流保存为PCM文件”章节介绍了将媒体文件中的音频流转换为原始PCM音频的方法。示例代码直接保存解码后的PCM数据,保留了原始音频的采样频率、声道数量和采样位数。但在实际应用中,有时需要特定规格的PCM音频。例如,某些语音识别引擎仅接受16位PCM数据,而标准MP3音频通常采用32位采样,因此需将32位MP3音频转换为16位PCM音频。
85 0
FFmpeg开发笔记(五十八)把32位采样的MP3转换为16位的PCM音频

热门文章

最新文章