zenith zenith - 2 years ago 223
Android Question

Y'UV420p (and Y'V12 or YV12) to RGB888 conversion

Am trying to show a yuv video file in android, I have a few yuv video files that am using.

This video yuv file video1 (160*120 resolution) is one that I captured from my server as raw h264 data and converted to yuv file using OpenH264.

I used YUV Player Deluxe to play the above yuv video files and it plays perfectly well.

When I try to play the same in Android am not getting the color component reproduced properly.The image almost appears black and white with a few traces of color in between of the image frame.

To display the video in Android, what I did was read the yuv video file frame by frame where each frame is of size = (w*h*1.5)bytes and obtain rgb array out of that using the code mentioned below

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;

Using the rgb[] obtained from mehod convertYUV420_NV21toARGB8888 above I constructed a bitmap to display in ImageView.

I tried various other codes to convert yuv[] to rgb[] but the result is same. Also I tried using Androids YUVImage API and the result is yet the same.

I know that the code stated above is to convert Y'UV420sp (NV21) to ARGB8888, but am not getting the difference between YUV to RGB and Y'UV420sp (NV21) to ARGB8888 conversion (just below the previous link....)

Please could anyone help me out....

Answer Source

Your main problem as you expected is that you treat input data as NV21 and not as YUV. The difference between this two formats is that in NV21 format chroma (U/V) samples are interleaved (i.e. VUVUVUVUVU...) and in YUV format they are in separate planes (i.e. UUUUU...VVVVV...) and another order so this part of you code should look like:

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

and k in loop should increase by 1 (not by 2).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download