Y'UV420p(和Y'V12或YV12)到RGB888的转换

时间:2014-09-26 13:22:54

标签: android h.264 yuv

我试图在Android中显示yuv视频文件,我有一些正在使用的yuv视频文件。

This video yuv file video1(160 * 120分辨率)是我从服务器捕获的原始h264数据,并使用OpenH264转换为yuv文件。

我使用YUV Player Deluxe播放上面的yuv视频文件,效果非常好。

当我尝试在Android中播放相同内容时,没有正确再现色彩成分。图像几乎呈现黑白色,图像帧之间有一些颜色痕迹。

要在Android中显示视频,我所做的是逐帧读取yuv视频文件,其中每个帧的大小为=(w * h * 1.5)字节,并使用下面提到的代码获取rgb数组< / p>

public static int[] convertYUV420_NV21toARGB8888(byte [] data, int width, int height) {
int size = width*height;
int offset = size;
int[] pixels = new int[size];
int u, v, y1, y2, y3, y4;

// i along Y and the final pixels
// k along pixels U and V
for(int i=0, k=0; i < size; i+=2, k+=2) {
    y1 = data[i  ]&0xff;
    y2 = data[i+1]&0xff;
    y3 = data[width+i  ]&0xff;
    y4 = data[width+i+1]&0xff;

    v = data[offset+k  ]&0xff;
    u = data[offset+k+1]&0xff;
    v = v-128;
    u = u-128;

    pixels[i  ] = convertYUVtoARGB(y1, u, v);
    pixels[i+1] = convertYUVtoARGB(y2, u, v);
    pixels[width+i  ] = convertYUVtoARGB(y3, u, v);
    pixels[width+i+1] = convertYUVtoARGB(y4, u, v);

    if (i!=0 && (i+2)%width==0)
        i += width;
}

return pixels;
}

private static int convertYUVtoARGB(int y, int u, int v) {
int r = y + (int)(1.772f*v);
int g = y - (int)(0.344f*v + 0.714f*u);
int b = y + (int)(1.402f*u);
r = r>255? 255 : r<0 ? 0 : r;
g = g>255? 255 : g<0 ? 0 : g;
b = b>255? 255 : b<0 ? 0 : b;
return 0xff000000 | (r<<16) | (g<<8) | b;
}

使用从上面的mehod convertYUV420_NV21toARGB8888获得的rgb []我构建了一个在ImageView中显示的位图。

我尝试了各种其他代码将yuv []转换为rgb [],但结果是一样的。我也尝试使用Androids YUVImage API,结果还是一样。

我知道上面提到的代码是将Y'UV420sp(NV21)转换为ARGB8888,但我没有得到YUV to RGB和Y'UV420sp(NV21)到ARGB8888转换之间的差异(就在上一个链接的下方) ....)

请任何人帮助我......

1 个答案:

答案 0 :(得分:1)

您预期的主要问题是您将输入数据视为NV21而不是YUV。这两种格式之间的区别在于,在NV21格式中,色度(U / V)样本是交错的(即VUVUVUVUVU ...),而在YUV格式中,它们处于不同的平面(即UUUUU ... VVVVV ...)和另一种顺序所以你这部分代码应该是这样的:

u = data[offset+k  ]&0xff;
v = data[offset+k + size/4]&0xff;
循环中的

和k应该增加1(而不是2)。