• FFMPEG的解码后的数据格式


    这两天在阅读电视转发服务器中的流媒体底层库的源码时,在看到显示部分的时候,遇到了一些疑问:

    就是在用d3d做显示时候,我们显示的数据格式,指定为yv12,对于YV12的数据格式在内存中的分布,可以参考YV12的相关文章,这里我就暂时略过。

    下面是将数据拷贝到显示的锁定内存中,用于显示:

    for(i = 0;i < h;i ++){//Y数据拷贝
    memcpy(p + i * stride,item->output + i * w, w);
    }
    for(i = 0;i < h/2;i ++){//U数据拷贝
    memcpy(p + stride * h + i * stride / 2,item->output + w * h + w * h / 4 + i * w / 2, w / 2);
    }
    for(i = 0;i < h/2;i ++){//V数据拷贝
    memcpy(p + stride * h + stride * h / 4 + i * stride / 2,item->output + w * h + i * w / 2, w / 2);
    }

    而在显示之前,也就是解码的时候,也进行过数据的拷贝:

    memcpy(&(pItemF.head),&(m_tRecentItem.head),sizeof(AV_HEAD_PARAM));
    for (int i=0;i<m_tRecentItem.head.height;i++)//Y数据拷贝   
    memcpy(pYUVBuf+i*m_tRecentItem.head.width , m_tRecentItem.picture->data[0]+i*m_tRecentItem.picture ->linesize[0], m_tRecentItem.head.width);
    for (int i=0;i<m_tRecentItem.head.height/2;i++)//U数据拷贝
    memcpy(pYUVBuf+m_tRecentItem.head.height*m_tRecentItem.head.width+i*m_tRecentItem.head.width/2 , m_tRecentItem.picture->data[1]+i*m_tRecentItem.picture ->linesize[1], m_tRecentItem.head.width/2);
    for (int i=0;i<m_tRecentItem.head.height/2;i++)//V数据拷贝
    memcpy(pYUVBuf + m_tRecentItem.head.height*m_tRecentItem.head.width + m_tRecentItem.head.height/2 * m_tRecentItem.head.width/2 + i*m_tRecentItem.head.width/2 , m_tRecentItem.picture->data[2]+i*m_tRecentItem.picture ->linesize[2], m_tRecentItem.head.width/2);

    而上面的item->output=pYUVBuf

    如果显示的数据是YV12,那么解码以后的数据格式又是怎么样的格式?

    --------------------------------------------------------------

    在经过一番查找资料以后知道,解码以后的数据格式是I420.

    在此博客中提过:http://blog.sina.com.cn/s/blog_4ae178ba01018o7q.html

    解码

    如果您只要求解成YUV 420I数据,只需一次调用就可以了:

    avcodec_decode_video(g_pCodecCtx, g_pavfFrame, (int *)&nGot, (unsigned __int8 *)pSrcData, dwDataLen);

    这里,nGot用来返回解码成功与否,avcodec_decode_video调用完成后,如果nGot不等于0,则表示解码成功,否则未解出视频帧。

    pSrcData是待解的H264编码的一段数据流,dwDataLen表示该段数据流的长度,单位是byte。

    解 码后的视频帧(YUV数据)被存入g_pavfFrame,g_pavfFrame->data[0]、 g_pavfFrame->data[1]、g_pavfFrame->data[2]即是YUV数据。下面的示例代码把YUV数据压在了一 块内存里,排列方式为:

    YY

    YY

    U

    V

    该函数有返回值:如果解码成功,则返回本次解码使用的码流字节数,否则返回0。

    ------------------------------------------------------------------------

    YV12和I420的区别
    一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Bit,RGB32的size=width×heigth×4,如果是I420(即YUV标准格式4:2:0)的数据量是 size=width×heigth×1.5 Bit。
    在采集到RGB24数据后,需要对这个格式的数据进行第一次压缩。即将图像的颜色空间由RGB2YUV。因为,X264在进行编码的时候需要标准的YUV(4:2:0)。但是这里需要注意的是,虽然YV12也是(4:2:0),但是YV12和I420的却是不同的,在存储空间上面有些区别。如下:
    YV12 : 亮度(行×列) + V(行×列/4) + U(行×列/4)
    I420 : 亮度(行×列) + U(行×列/4) + V(行×列/4)
    可以看出,YV12和I420基本上是一样的,就是UV的顺序不同。
    ------------------------------------------------------------------

     从上面这段话,我们可以知道,在做显示的时候,因为i420的格式数据和yv12格式的数据uv存储顺序不一样,所以我们在做显示的时候,对数据进行了一次从新存储。

  • 相关阅读:
    GAN阶段性小结(损失函数、收敛性分析、训练技巧、应用“高分辨率、domain2domain”、研究方向)
    MMD :maximum mean discrepancy
    Chinese-BERT-wwm
    VGG16学习笔记
    jupyter notebook使用技巧--命令行模式以及在Markdown模式使用的操作(4)
    不同领域公开数据集下载
    数据挖掘竞赛,算法刷题网址汇总
    在keras下实现多个模型的融合
    问题集合
    开源测试数据集合
  • 原文地址:https://www.cnblogs.com/lihaiping/p/ffmpeg.html
Copyright © 2020-2023  润新知