首页 > 其他分享 >使用FFmpeg进行yuv420转rgba

使用FFmpeg进行yuv420转rgba

时间:2023-08-15 11:14:14浏览次数:41  
标签:FFmpeg int dst height yuv420 rgba data frame size

讲解一下将获取到视频数据,进行rgb转码,并且进行相应的缩放操作

// 存放解码过后的数据
unsigned char *decode_data;
int decode_size = 0;

/**
 * 解码AVFrame中的yuv420数据并且转换为rgba数据
 *
 * @param frame 需要解码的帧结构
 * @param src_width 需要转换的帧宽度
 * @param src_height 需要转换的帧高度
 * @param src_pix_fmt 需要转换的帧编码方式
 * @param dst_width 转换后目标的宽度
 * @param dst_height 转换后目标的高度
 * @return
 *
 **/
int decode_frame(AVFrame *frame, int src_width, int src_height,
                 AVPixelFormat src_pix_fmt, int dst_width, int dst_height) {
    struct SwsContext *pSwsCtx;
    // 转换后的帧结构对象
    AVFrame *dst_frameRGBA = NULL;
    // 目标帧结构初始化
    dst_frameRGBA = av_frame_alloc();

    BYTE *outBuff = NULL;
    // 初始化目标帧长度
    int dst_frame_size;
    // 计算RGBA下的目标长度
    dst_frame_size = avpicture_get_size(AV_PIX_FMT_RGBA, dst_width, dst_height);
    // 分配转换后输出的内存空间
    outBuff = (uint8_t *) av_malloc(dst_frame_size);
    // 初始化目标帧
    avpicture_fill((AVPicture *) dst_frameRGBA, outBuff, AV_PIX_FMT_RGBA,
                   dst_width, dst_height);

    // 获取缩放上下文
    pSwsCtx = sws_getContext(src_width, src_height, src_pix_fmt, dst_width, dst_height, AV_PIX_FMT_RGBA,
                             SWS_BICUBIC, NULL, NULL, NULL);
    // 缩放,结果保存在目标帧结构的dst_frameRGBA->data中
    sws_scale(pSwsCtx, frame->data,
              frame->linesize, 0, src_height,
              dst_frameRGBA->data, dst_frameRGBA->linesize);

    // 存储帧结果
    if (decode_data == NULL) {
        decode_data = malloc(dst_frame_size * sizeof(char));
        // 测试保存成文件
//        save_frame(frame, src_width, src_height);
//        save_rgb(dst_frameRGBA->data[0], dst_frame_size);
    } else if (decode_size != dst_frame_size * sizeof(char)) {
        // 如果解码过后的数据大小不满足解码区域,那么重新分配内存
        decode_data = realloc(decode_data, dst_frame_size * sizeof(char));
    }

    // 将解码后的数据拷贝到decode_data中
    memcpy(decode_data, dst_frameRGBA->data[0], dst_frame_size * sizeof(char));
    // 计算解码后的帧大小
    decode_size = dst_frame_size * sizeof(char);
    // 释放相关内容
    av_free(outBuff);
    av_free(dst_frameRGBA);
    return 1;
}

/**
 * 保存rgb数据
 * @param data
 * @param frameSize
 * */
void save_rgb(uint8_t *data, int frameSize) {

    FILE *pFile;
    char *szFilename = "/sdcard/RGB";
    int y;

    pFile = fopen(szFilename, "wb");

    if (pFile == NULL)
        return;

    //写入文件
    fwrite(data, 1, frameSize, pFile);

    // Close file
    fclose(pFile);

}

/**
 * 保存yuv数据
 * @param data
 * @param frameSize
 * */
void save_frame(AVFrame *pFrame, int width, int height) {

    FILE *pFile;
    char *szFilename = "/sdcard/frame.yuv";
    int y;

    pFile = fopen(szFilename, "wb");

    if (pFile == NULL)
        return;

    int y_size = width * height;
    int u_size = y_size / 4;
    int v_size = y_size / 4;

    //写入文件
    //首先写入Y,再是U,再是V
    //in_frame_picture->data[0]表示Y
    fwrite(pFrame->data[0], 1, y_size, pFile);
    //in_frame_picture->data[1]表示U
    fwrite(pFrame->data[1], 1, u_size, pFile);
    //in_frame_picture->data[2]表示V
    fwrite(pFrame->data[2], 1, v_size, pFile);

    // Close file
    fclose(pFile);

}

查看测试文件结果,windows下可以使用RawViewer,OSX可以使用YUView


 

OSX下:


 

注意由于我们是直接将数据保存在文件中,需要在YUView或者RawViewer中手动设置width和height属性。好了,这节就讲到这里,有什么问题,欢迎交流~~~

 

标签:FFmpeg,int,dst,height,yuv420,rgba,data,frame,size
From: https://www.cnblogs.com/lidabo/p/17630764.html

相关文章

  • FFmpeg3.2 msvc+msys 源码编译
    材料FFmpeg3.2源码x264x265fdk-aac注意:由于FFmpeg源码的版本太久,采用的第三方库是最新的,因此需要做调整基本操作编译64位FFmpeg程序Windows开始菜单->VisualStudio2022->x64NativeToolsCommandPromptforVS2019编译32位FFmpeg程序Windows开始菜单->VisualStudio2......
  • 跨平台xamarin.Android 开发之 :适配各架构(X86_64 、 X86、arm64-v8a、 armeabi-v7a )
    此代码的编写花费了脑细胞:在每次编码开启编码器到只需要一次编码器的开启优化前提:编译好FFMpeg的各平台的动态库基本上Android X86_64、X86、arm64-v8a、armeabi-v7a采用FFmpeg编码的方式基本一直。差异是内存分配和取指有所不同,如果分配不对,直接闪退。先看看通用的编码......
  • 跨平台xamarin.Android 开发之 :适配各架构(X86_64 、 X86、arm64-v8a、 armeabi-v7a )
    此代码的编写花费了脑细胞:在每次解码开启解码器到只需要一次解码器的开启优化前提:编译好FFMpeg的各平台的动态库Windows、Android(X86_64、X86、arm64-v8a、armeabi-v7a)解码相对编码要简单一些,因为不涉及到AVFrame取指转换解码包括:创建解码器、解码、释放解码器us......
  • 跨平台xamarin.Android 开发之 :适配各架构(X86_64 、 X86、arm64-v8a、 armeabi-v7a
    从事Windows,项目探索预研跨平台开发,对Android只知道有X86_64、X86、arm64-v8a、  armeabi-v7a这么个东西其他空白。编译入手采用Xamarin.Android开发。通过摸索。在Xamarin.Android中使用FFmpeg编解码,需要获取源码编译成对应Android架构的so动态库,如何编译不在此处讨论,稍......
  • 视频获取缩略图使用ffmpeg插件
      stringmp4URL=Server.MapPath("~/Upload/")+"33.mp4";stringOutURL=Server.MapPath("~/Upload/")+DateTime.Now.ToString("yyyyMMddHHmmssfff")+".png";ffmpeg(mp4URL,OutURL,3); ......
  • 关于FFmpeg释放 AVFormatContext*解码上下文的一些问题
    关于FFmpeg释放AVFormatContext*解码上下文的一些问题FFmpeg的一些常用函数用途结构体释放解码上下文FFmpeg的一些常用函数用途av_register_all()注册所有组件。avformat_open_input()打开输入视频文件。avformat_find_stream_info()获取视频文件信息。avcodec_find_d......
  • ffmpeg使用avformat_close_input()函数释放结构体时崩溃的问题
    先看一下我调试时,发现程序崩溃的代码位置  //这是我的程序释放流上下文时的操作 if(m_pAvFormatContext) { //释放视频解码器上下文 if(m_iVideoStreamIndex>=0) avcodec_free_context(&m_pVideoDecodeContext);//此处是发生崩溃......
  • C# 使用FFmpeg.Autogen对byte[]进行编解码
    C#使用FFmpeg.Autogen对byte[]进行编解码,参考:https://github.com/vanjoge/CSharpVideoDemo入口调用类:usingSystem;usingSystem.IO;usingSystem.Drawing;usingSystem.Runtime.InteropServices;usingFFmpeg.AutoGen;namespaceFFmpegAnalyzer{publicclassFFm......
  • rocky linux:安装ffmpeg(ffmpeg 5.1.3/rocky linux 9.2)
    一,ffmpeg官网:网址:http://ffmpeg.org/如图:说明:最新版本出到了6.0,我们从dnf通道安装,版本可能略低二,安装rpmfusion库[root@img~]#dnfinstall--nogpgcheckhttps://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-9.noarch.rpm[root@img~]#dnfinstall......
  • clang 静态编译 ffmpeg
    文档说明:只记录关键的地方;发文时间:2023-08-06意义:静态编译ffmpeg,可自由裁剪,使用libc构建;支持macos、linux构建;生成库依赖库图环境:alpine:3.17dockerclang备注:大部分软件源代码来源于github.com,下载过程断断续续的。请自备代理借助swoole-cli已经编写好......