Y'UV420p(和Y'V12或YV12)到RGB888的转换 [英] Y'UV420p (and Y'V12 or YV12) to RGB888 conversion

查看:140
本文介绍了Y'UV420p(和Y'V12或YV12)到RGB888的转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试在android中显示yuv视频文件时,我有一些正在使用的yuv视频文件.

此视频yuv文件video1 (160 * 120分辨率)是我从服务器上捕获的原始h264数据,并使用OpenH264转换为yuv文件.

我使用YUV Player Deluxe播放了上述yuv视频文件,并且播放效果非常好.

当我尝试在Android中播放相同内容时,无法正确再现颜色分量.图像几乎显示为黑白,在图像帧之间出现了一些颜色痕迹.

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

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;
}

使用上面的方法convertYUV420_NV21toARGB8888获得的rgb [],我构建了一个位图以显示在ImageView中.

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

我知道上述代码是将Y'UV420sp(NV21)转换为ARGB8888,但并没有获得解决方案

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

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

,循环中的k应该增加1(而不是2).

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....

解决方案

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).

这篇关于Y'UV420p(和Y'V12或YV12)到RGB888的转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆