Log in

View Full Version : [x264] x264_image_t in YUV420 structure


MMaciek
27th April 2011, 13:37
Greetings to all,

I am about to do conversion from RGB to YUV 4:2:0, which is simple and well documented, but I need to populate x264_image_t with aquired RGB and then converted data and here comes my problem.

What is the exact interpretation of bytes in x264_image_t storing YUV?

typedef struct
{
int i_csp; /* Colorspace */
int i_plane; /* Number of image planes */
int i_stride[4]; /* Strides for each plane */
uint8_t *plane[4]; /* Pointers to each plane */
} x264_image_t;

At first I thought it straightforward:
plane[0] = YYYYYYYY...
plane[1] = UUUU...
plane[2] = VVVV....

but it's not. Such assumption led me to strangely colored and noisy pictures.

How should I interpret data from this object?

For reference - my conversion:
static char clamp(int in)
{
if(in < 0)
return 0;
if(in > 255)
return 255;
return (char)in;
}
static void YUV_TO_RGB(float Y, float U, float V, char* R, char* G, char* B)
{
float C,D,E;
C = Y - 16;
D = U - 128;
E = V - 128;
*R = clamp((int)(298 * C + 409*E + 128) >> 8);
*G = clamp((int)(298 * C - 100*D - 208*E+128) >> 8);
*B = clamp((int)(298 * C + 516*D + 128) >> 8);

}

Thanks!

nm
27th April 2011, 14:34
What is the exact interpretation of bytes in x264_image_t storing YUV?

typedef struct
{
int i_csp; /* Colorspace */
int i_plane; /* Number of image planes */
int i_stride[4]; /* Strides for each plane */
uint8_t *plane[4]; /* Pointers to each plane */
} x264_image_t;

At first I thought it straightforward:
plane[0] = YYYYYYYY...
plane[1] = UUUU...
plane[2] = VVVV....

but it's not. Such assumption led me to strangely colored and noisy pictures.

plane[0] points to a W x H area of Y (luma) values.
plane[1] points to a W/2 x H/2 area of Cr (U) values.
plane[2] points to a W/2 x H/2 area of Cb (V) values.

static void YUV_TO_RGB(float Y, float U, float V, char* R, char* G, char* B)

Your example function is for YUV -> RGB conversion while it sounded like you want to convert RGB to YUV.

MMaciek
27th April 2011, 14:38
plane[0] points to a W x H area of Y (luma) values.
plane[1] points to a W/2 x H/2 area of Cr (U) values.
plane[2] points to a W/2 x H/2 area of Cb (V) values.

Your example function is for YUV -> RGB conversion while it sounded like you want to convert RGB to YUV.

Thanks I will check it out.
Yes, my example function is only for testing whether I understand bytes correctly, because I have some ready to use YUV images from different source.

Hmm, I have series of images of size 352 x 288 which I can encode into correct h264 & mp4 file, but size of plane[0] is much bigger than 352*288*sizeof(uint8_t). The code is completely from official x264 command-line tool, so everything should be ok. Encoding works, but for plane[0] is allocated about 3 times more bytes than W*H.... It's strange for me.

I have changed:
for( x=0; x < width; ++x)
{
for( y=0; y<height;++y)
{
y = image->plane[0][y*width+x];
u = image->plane[1][(y/2)*(width/2) + (x/2)];
v = image->plane[2][(y/2)*(width/2) + (x/2)];

YUV_TO_RGB(y,u,v,&r,&g,&b);
SetPixel(x,y,r,g,b);
}
}

... but still the result is far from correct.
http://img35.imageshack.us/img35/7152/errorrz.jpg (http://img35.imageshack.us/i/errorrz.jpg/)

Uploaded with ImageShack.us (http://imageshack.us)
on the left - original, correct
on the right - my incorrect conversion

nm
27th April 2011, 15:28
Maybe your picture is not 8-bit YV12. The output is quite funky though with those wavy edges. I'd have to see the full code and your source file to help more.


Hmm, I have series of images of size 352 x 288 which I can encode into correct h264 & mp4 file, but size of plane[0] is much bigger than 352*288*sizeof(uint8_t). The code is completely from official x264 command-line tool, so everything should be ok. Encoding works, but for plane[0] is allocated about 3 times more bytes than W*H.... It's strange for me.

For normal 8-bit YV12 pictures it should be W*H*3/2. plane[0] points to the start of the memory area allocated for the picture. Other planes follow and they aren't allocated separately. See x264_picture_alloc in common/common.c