首页 > 代码库 > 显示器如何显示一个YUV420格式的图形

显示器如何显示一个YUV420格式的图形

记录在开发过程中对知识点的一些理解:

在开发渲染程序的过程中,需要对视屏文件进行解码解码后特效文件的叠加,使用的技术是(FFmpeg+DirectX)

解码出来的视屏数据格式是YUYV(YUV420),使用DirectX的创建的纹理格式为RGBA,

(1):视屏的宽高分别为Width和Height,则视屏最后在显卡中显示为RGBA的缓存大小:Width*4*Height。

(2):FFmpeg解码为YUYV格式的缓存大小为:Width*2*Height,因为每个像素采样一个Y,每两个像素采样一个UV。那么则创建一个宽度为Width*2,高度为Height的DirectX纹理来存储解码后的YUYV数据,将此数据送入定点作色器和像素作色器进行采样。其大概流程为:

  解码后的YUYV数据 -> DirectX纹理数据 -> 作色器采样(还原为2倍大小)-> 显示器输出显示

  技术分享

  YUYV数据和RGBA纹理中的数据完全一样,都是YUYVYUYVYUYV……的格式和大小,并没有带有真正的透明度信息(即YUYV分别对应RGBA,其实A存储的为V信息),数据只有在进行采样的时候送入顶点和像素作色器才被还原为原来的大小,在作色器中才有数据格式的变化,将YUV转化为RGB,然后给A的透明度填充为固定值,不透明。

 (3):下面来分析采样的方式:

  技术分享

  目的:将一个宽度只有显示一半的纹理数据(YUYV)完整的显示在显示器上,即将一个大小为【W/2 * H】的YUV/RGBA纹理变化为一个大小为【w * H】的RGBA数据,并且显示在显示器上面

  分析:如何将一个大小不等于显示屏宽度的图像全屏完整的显示出来呢?答案是:在横向和纵向进行屏幕显示分辨率的宽度个数次采样,假如屏幕的分辨率是1920*1080,则将要显示的图像进行横向1920次采样,纵向1080次采样。

  则for(int i = 0;i<1080;i++)

    {

      for(int j = 0; j< 1920; j++)

      {

        //Samplate 对需要输出的原始图形进行采样,则每次采样的位置为(src.i/1920*src.w)

        //假如原图像的宽高为960*1080,则第一次C采样的点位(0,0),第二次采样的地位(0,0),第三次(1.0),第四次(1.0)

        //则纹理坐标为(0/960,0/1080)映射到(0/1920,0/1080)

        //则纹理坐标为(0/960,0/1080)映射到(1/1920,0/1080)    

        //则纹理坐标为(1/960,0/1080)映射到(2/1920,0/1080)

        //则纹理坐标为(1/960,0/1080)映射到(3/1920,0/1080)

      }

    }

  如下图所示:

  其实作色器会在原始图像中每个像素采样两次;每次采样的纹理坐标为(i/1920,j),i为的范围是【0-960】

  技术分享

 

显示器如何显示一个YUV420格式的图形