ffmpeg通过opencv显示的bug分析--Apple的学习笔记

昨晚参考其它blog,将之前的SDL框架的显示改成了opencv显示。结果学习过程中遇到2个bug,结果都顺利解决,主要是图像格式转换问题。

问题1

显示变色


image.png

通过vs2017中调试,对比正常变色的数据,发现rgb和bgr颠倒了


image.png
    cv::Mat frameImage(cv::Size(width, height), CV_8UC3, cv::Scalar(0));
    stepWidth = frameImage.step;
    nChannels = frameImage.channels();
    pData = frameImage.data;
    //frameImage.data = pFrame->data[0];
#if 1
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            pData[i * stepWidth + j * nChannels + 0] = pFrame->data[0][i * pFrame->linesize[0] + j * nChannels + 2];
            pData[i * stepWidth + j * nChannels + 1] = pFrame->data[0][i * pFrame->linesize[0] + j * nChannels + 1];
            pData[i * stepWidth + j * nChannels + 2] = pFrame->data[0][i * pFrame->linesize[0] + j * nChannels + 0];
        }
    }
#endif

    cv::namedWindow("Video", CV_WINDOW_AUTOSIZE);
    cv::imshow("Video", frameImage);

小结:正常sws_scale函数转换格式后,应该frameImage.data = pFrame->data[0]; 就可以通过cv::imshow显示了,不需要再进行data赋值,此赋值代码中把RGB和BGR进行了转换,导致的变色。

问题2

显示3段,而且是灰色调的,图像也不太正常


image.png

调试数据

0x00000292744DD080  12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12  ...................
0x00000292744DD093  12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12  ...................
0x00000292744DD0A6  12 12 12 12 12 12 12 12 12 12 13 13 13 13 13 13 13 13 13  ...................
0x00000292744DD0B9  13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13  ...................
0x00000292744DD0CC  13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13  ...................
0x00000292744DD0DF  13 13 13 13 13 13 13 13 13 13 13 13 13 14 14 14 14 14 14  ...................
0x00000292744DD0F2  14 14 14 15 14 14 15 15 15 15 15 15 16 16 15 16 16 16 16  ...................
0x00000292744DD105  16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16  ...................
0x00000292744DD118  16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16  ...................
0x00000292744DD12B  17 17 16 19 18 18 1c 1b 1a 1e 1e 1d 20 20 1f 20 20 20 21  ............  .   !
0x00000292744DD13E  21 20 21 21 21 21 21 21 20 21 21 20 20 20 20 20 20 21 21  ! !!!!!! !!      !!
0x00000292744DD151  20 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21   !!!!!!!!!!!!!!!!!!
0x00000292744DD164  21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!!!!
0x00000292744DD177  21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!!!!
0x00000292744DD18A  21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!!!!
0x00000292744DD19D  21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21  !!!!!!!!!!!!!!!!!!!
0x00000292744DD1B0  21 21 21 21 21 21 21 21 21 21 21 21 21 21 22 21 21 22 22  !!!!!!!!!!!!!!"!!""
0x00000292744DD1C3  22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22  """""""""""""""""""

问题分析:因为图像转换的时候都用了AV_PIX_FMT_YUV420P,而此格式是planar。而把3个byte的Y(灰度)数据给了合并为一个RGB数据,导致看上去有3片灰色的
YUV420 planar数据, 以720×488大小图象YUV420 planar为例,
其存储格式是: 共大小为(720×480×3>>1)字节,
分为三个部分:Y,U和V
Y分量: (720×480)个字节
U(Cb)分量:(720×480>>2)个字节
V(Cr)分量:(720×480>>2)个字节
三个部分内部均是行优先存储,三个部分之间是Y,U,V 顺序存储。
即YUV数据的0--720×480字节是Y分量值,
720×480--720×480×5/4字节是U分量
720×480×5/4 --720×480×3/2字节是V分量。
sws_scale经过YUV转换后的数组有3个,一个是Y数组,一个是U数组,一个是V数组。而进入RGB转换数组只有1个,存储方式是RGB交叉排列的

找到根本原因后,问题顺利解决。

参考网址
1.图像原始格式(YUV444 YUV422 YUV420)一探究竟
2.yuv422/yuv420格式

你可能感兴趣的:(ffmpeg通过opencv显示的bug分析--Apple的学习笔记)