美文网首页
使用FFmpeg进行yuv420转rgba

使用FFmpeg进行yuv420转rgba

作者: 蛋西 | 来源:发表于2018-07-13 19:03 被阅读0次

    讲解一下将获取到视频数据,进行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


    image.png

    OSX下:


    image.png

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

    相关文章

      网友评论

          本文标题:使用FFmpeg进行yuv420转rgba

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