• 如何从AVFrame::data【0】里获取RGB24数据和YUYV422数据


    struct AVFrame
    {
    uint8_t *data[4];分别指向yuv三个位面及一个未知的位面或者是rgb模式下只有data[0]指向raw data
    int linesize[4];四个位面分别的内存块大小
    }

    AVFrame *avcodec_alloc_frame() //Allocates an AVFrame and sets its fields to default values
    初始化的时候AVFrame中的元素data,linesize均为空。未指向任何内存数据

    avcodec_decode_video()// Decodes a video frame from \p buf into \p picture.
    * The avcodec_decode_video() function decodes a video frame from the input
    * buffer \p buf of size \p buf_size.
    对从文件中读取的包进行解码,将解码后的yuv数据填充在 AVFrame的 data及linesize的字段内。而且经过打印发现从始至终 AVFrame一直在两组数据中间1:1变动。说明 AVFrame始终指向一块内存数据,这块内存数据有可能由avcodec_decode_video()函数内部负责去申请,然后在解码结束之后自动释 放。

    这也说明了为什么在yuv转rgb的时候需要自己去申请一块内存空间并将其绑定在AVFrame上,有可能因为
    sws_scale()并不会自动帮用户去申请内存空间,所以为了获取转化之后的RGB数据则需要自动去申请内存使用。
    sws_scale()负责图像数据的缩放及尺寸的变法
    比如:  yuv420-->yuv444

    CIF -> QCIF   QCIF-->CIF等

    如何从AVFrame::data[0]里获取RGB24数据,又如何从中获取YUYV422数据

    • 提出问题:
    我用img_convert转换了解码后的图象为RGB24,确保转换是正确的,取出数据来播放还是不正常。
    我又转为YUYV422,还是不正常。 
    反正就是数据没取对。
    
    我是从AVFrame::data[0]直接把数据Copy过来显示,
    要么图象只显示到上半窗口,要么重复了几个播放图象,怎么弄都不正确
    请问,怎么取这两种格式的图象数据啊?
    
      • 解答问题
    从AVFrame::data[0]里获取RGB24 或者 YUYV422,或者 UYVY422 都只是从data[0]里获取就可以了,忽略data[1], data[2], data[3];
    其次,我由于使用了img_convert进行了到上述目标格式的转换,但是却为转换用的AVPicture变量,调用avpicture_alloc指定的目标格式还是
    PIX_FMT_YUV420P,也就是说,分配的目标格式和转换的目标格式不匹配对应。
    因此,可能一方面导致AVPicture变量中的目标格式不正确,还导致其分配的缓冲区太小,从而导致后来取数据不正确,结果图象被隔行采样,实际视频高少了一
    半。
    
    其实只要分配和转换不发生任何问题,就只需要从AVFrame::data[0]直接Copy数据即可,而Copy数据的长度,即是一帧BMP图片的大小。
    唯有RGB24,这样一次Copy,显示后,图象倒置,需要进行一行一行Copy,才正确。
    
      • 相关解释
    AVFrame::data[0] 和 AVPicture::data[0],众所周知,都是一样的意义。
    换句话说结构体AVFrame 和 结构体AVPicture表示图象数据的字段部分完全相同,而AVFrame只是比AVPicture多了些字段。
    因此,上述问题及解答中,说“从AVFrame::data[0] 获取数据”也表达“从AVPicture::data[0]获取数据 ”同等的意思。
    
      • 相关代码
    这里同时给出FFMPEG默认的解码输出格式PIX_FMT_YUV420P,获取解码数据的方式
    
    int i, j, nshift, nBufPtr = 0;
    uint8_t*   yuv_factor;
    for( i=0; i<3; i++ )
    {
         nshift = (i == 0 ? 0:1);
        yuv_factor = m_pAVFrame->data;
        for( j = 0; j < (m_pContext->height >> nshift); j++ )
       {
           memcpy( (char*)m_pOutBuff + nBufPtr, yuv_factor, (m_pContext->width >> nshift) );
           yuv_factor += m_pAVFrame->linesize;
           nBufPtr    += (m_pContext->width >> nshift);
       }
    }
  • 相关阅读:
    三者最大实例分析
    Python eval函数
    Linux查看某个进程的线程
    将列表传递给函数
    二十四、二进制日志截取与恢复
    二十三、二进制日志事件
    二十二、二进制日志记录方式
    二十一、二进制日志介绍
    二十、错误日志
    十九、InnoDB核心参数
  • 原文地址:https://www.cnblogs.com/lidabo/p/15710763.html
Copyright © 2020-2023  润新知