Sam Lantinga wrote:
I don’t want to use the YUV overlay functionality build into SDL for display
but create a 32bit surface instead that can be used for other things as
well.
What exactly do you mean?
Well, the YUV overlay routines seem to be tied to hardware accelerated display -
maybe I am wrong, but that what it looks like from the manual pages.
What if I don’t want to do that with the decoded image. Say, I want to use the
decoded YUV frame as an OpenGL texture or for some other image processing task.
So basically it would be nice to have a routine to create an RGB surface, just in
memory and without hardware acceleration, from YUV input data.
Does anyone have C code to convert planar YUV to 32bit RGB? Please post or
reference.
You can use the code in SDL itself. It’s under the BSD license.
Remember, you lose all hardware acceleration when you restrict yourself
to software surfaces.
Yes, I looked at that but couldn’t figure out how to use the internal YUV
routines.
Anyhow, I wrote a function that will work for the OpenDivX output from the Linux
decore() routine. If anyone can show me how to interface the SDL routines so I
can drop this code please do.
Ciao
Andreas
/*
Convert YUV planes (U and V are quarter size) to RGB32
*/
#define KcrR 76284
#define KcrG 53281
#define KcbG 25625
#define KcbB 132252
#define Ky 76284
int yuv2rgb32 (void *yi, void *ui, void *vi, int w, int h, void *rgb)
{
int tmp;
int i, j;
int y, crR, crG, cbG, cbB;
unsigned char *bufcr, *bufcb, *bufy, *bufoute, *bufouto;
int oskip, yskip;
oskip=w*4;
yskip=w;
bufy=(unsigned char *)yi;
bufcb=(unsigned char *)ui;
bufcr=(unsigned char *)vi;
bufoute=(unsigned char *)rgb;
bufouto=(unsigned char *)rgb;
bufouto += oskip;
for(i=0; i<(h>>1); i++)
{
for(j=0; j<w; j+=2)
{
crR=(*bufcr-128)KcrR;
crG=((bufcr++)-128)*KcrG;
cbG=(*bufcb-128)KcbG;
cbB=((bufcb++)-128)*KcbB;
y=(bufy[j]-16)*Ky;
*(bufoute++)=255;
tmp=(y+cbB)>>16;
*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp);
tmp=(y-crG-cbG)>>16;
*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp);
tmp=(y+crR)>>16;
*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp);
y=(bufy[j+1]-16)*Ky;
*(bufoute++)=255;
tmp=(y+cbB)>>16;
*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp);
tmp=(y-crG-cbG)>>16;
*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp);
tmp=(y+crR)>>16;
*(bufoute++)=(tmp>255)?255:((tmp<0)?0:tmp);
y=(bufy[j+yskip]-16)*Ky;
*(bufouto++)=255;
tmp=(y+cbB)>>16;
*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp);
tmp=(y-crG-cbG)>>16;
*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp);
tmp=(y+crR)>>16;
*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp);
y=(bufy[j+1+yskip]-16)*Ky;
*(bufouto++)=255;
tmp=(y+cbB)>>16;
*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp);
tmp=(y-crG-cbG)>>16;
*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp);
tmp=(y+crR)>>16;
*(bufouto++)=(tmp>255)?255:((tmp<0)?0:tmp);
}
bufoute+=oskip;
bufouto+=oskip;
bufy+=yskip<<1;
}
}
The target surface is created as follows:
framesurface = SDL_CreateRGBSurface(SDL_SWSURFACE, dec_param.x_dim,
dec_param.y_dim, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
/* Color space conversion into surface */
The actual call is this:
/* Decode frame */
dec_frame.length = framesize;
dec_frame.bitstream = framebuffer;
dec_frame.bmp = (void *) frameoutbuffer;
dec_frame.render_flag = 1;
decore(MY_APP_ID, 0, &dec_frame, NULL);
yuv2rgb32(frameoutbuffer[0],frameoutbuffer[1],frameoutbuffer[2],
dec_param.x_dim,dec_param.y_dim,framesurface->pixels);–
| Andreas Schiffler aschiffler at home.com |
| Senior Systems Engineer - Deskplayer Inc., Buffalo |
| 4707 Eastwood Cres., Niagara Falls, Ont L2E 1B4, Canada |
| +1-905-371-3652 (private) - +1-905-371-8834 (work/fax) |