为什么渲染结果是全绿屏

1.绿屏

由于渲染支持的是RGB,而不是YUV,解码一般输出YUV,如果解码报错,一般YUV都是0;

YUV转RGB的时候

Y = 0.299 R + 0.587 G + 0.114 B

U = -0.1687 R - 0.3313 G + 0.5 B + 128

V = 0.5 R - 0.4187 G - 0.0813 B + 128

 

R = Y + 1.402 (V-128)

G= Y - 0.34414 (U-128) - 0.71414 (V-128)

B= Y + 1.772 (U-128)

将Y,U,V=0 带入

差不多就是R = -126, G = 135, B = -126
其中RGB有取值范围, 都是[0, 255]
所以最后就是R=0, G=135, B=0
查看颜色表:rgb(0,135,0) 差不多就是绿

----来自知乎 Fenngtun

2、绿边

(119+1)*16 =1920

(67+1)*16 =1088

2.1 、SPS计算待解码图像宽高有两个公式:

  当宽高是16的整数倍时:为什么选择16倍数,因为一般H264的宏块大小会使用16*16

  H.264 中有这样两个语法元素,pic_width_in_mbs_minus1 表示的值是横向宏块的个数减 1,pic_height_in_map_units_minus1 表示的值是纵向宏块的个数减 1。

  也就是说,把他们两个加上 1,就可以获得横向的宏块个数和纵向的宏块个数。那么我们已经知道一个宏块长 16 个像素,高 16 个像素,那么就可以得出视频宽高的计算公式了:

  Width = (pic_width_in_mbs_minus1+1)*16;
  Height = (pic_height_in_map_units_minus1+1)*16;

2.2、当宽高不是16的整数倍时:如宽高是1920*1080;当图像的宽高不是 16 的倍数的时候,H.264 会在图像的边沿添加一些像素,来补齐成 16 的倍数,

  然后通过 frame_crop_left_offset, frame_crop_right_offset, frame_crop_top_offset, frame_crop_bottom_offset 这 4 个量来记录上下左右补齐了多少数据。我们把这个过程称之为 Crop;裁剪;

       由于高度1080不是16的整数倍,需要裁剪,frame_corpping_flag =1 ,frame_mbs_only_flag =1;走的解析公式如下(如下代码公式2):https://blog.csdn.net/GerZhouGengCheng/article/details/107239415

  width = (119+1) * 16 - 0*2 - 0*2 = 1920
  height = (2-1) * (67+1)*16 - 0*2 - 4*2 = 1088 - 8 = 1080
      但是如果数据是软编码或者某些硬件设备中的编码程序打错了标记,1080高度没有打裁剪标记位,解码时候就还是走2.1的宽高计算,计算出来的高度是1088;然后进行解码,可是解码不出来多余的8行像素的高度数据,此时底下8行YUV就是0.转换RGB就只剩下G是【0,255】之间的值,所以渲染的时候就会在底下有一个绿边;

# 公式二
width = (sps->pic_width_in_mbs_minus1+1) * 16;
height = (2 - sps->frame_mbs_only_flag)* (sps->pic_height_in_map_units_minus1 +1) * 16);
if(sps->frame_cropping_flag)
{
unsigned int crop_unit_x;
unsigned int crop_unit_y;
if (0 == sps->chroma_format_idc) // monochrome
{
crop_unit_x = 1;
crop_unit_y = 2 - sps->frame_mbs_only_flag;
}
else if (1 == sps->chroma_format_idc) // 4:2:0
{
crop_unit_x = 2;
crop_unit_y = 2 * (2 - sps->frame_mbs_only_flag);
}
else if (2 == sps->chroma_format_idc) // 4:2:2
{
crop_unit_x = 2;
crop_unit_y = 2 - sps->frame_mbs_only_flag;
}
else // 3 == sps.chroma_format_idc // 4:4:4
{
crop_unit_x = 1;
crop_unit_y = 2 - sps->frame_mbs_only_flag;
}
width -= crop_unit_x * (sps->frame_crop_left_offset + sps->frame_crop_right_offset);
height -= crop_unit_y * (sps->frame_crop_top_offset + sps->frame_crop_bottom_offset);
}

3 绿边原因

视频文件或视频流可能采用了ATSC(美国的数字电视国家标准),Wiki上该标准对于MPEG-2有如下说明:

    The 1080-line formats are encoded with 1920 × 1088 pixel luma matrices and 960 × 540 chroma matrices, but the last 8 lines are discarded by the MPEG-2 decoding and display process.

直译意思是:1080行格式使用1920×1088像素luma矩阵和960×540色度矩阵(UV)进行编码,但最后8行被MPEG-2解码和显示过程丢弃;但是解码后最后8行没有UV信息;带入RGB转换R和B的值会偏低,G的值偏高;就是鲜艳的绿色

 

posted on 2024-06-27 11:05  邗影  阅读(66)  评论(0编辑  收藏  举报

导航