The attached snippet is what I use to convert from Theora's YUV to D3D's
UYVY or ARGB.
The formatting got slightly munged during the copy & pase.
-- Daniel, Epic Games Inc.
> -----Original Message-----
> From: theora-dev-bounces@xiph.org
> [mailto:theora-dev-bounces@xiph.org] On Behalf Of lluis
> Sent: Wednesday, December 08, 2004 7:30 PM
> To: theora-dev@xiph.org
> Subject: [Theora-dev] yuv2rgb
>
>
> hi all,
>
> i'm trying to code a tool to get some images from a
> ogg/theora file ....
>
> so basically i need to get a frame and convert to rgb ... and
> here is my
> question (sorry, i'm newbe here) ...
>
> how to convert a yuv_buffer to a rgb matrix ?
>
> i tryied diferent ways but my mistakes are bassically cause i don't
> understant how yuv_buffer structure works ...
>
> anybody can help? thanks a lot.
>
> ll-.
> _______________________________________________
> Theora-dev mailing list
> Theora-dev@xiph.org
> http://lists.xiph.org/mailman/listinfo/theora-dev
>
-------------- next part --------------
yuv_buffer YUVBuffer;
theora_decode_YUVout( &TheoraDecoder, &YUVBuffer );
DWORD SizeX = TheoraInfo.width,
SizeY = TheoraInfo.height;
char* SrcY = YUVBuffer.y;
char* SrcU = YUVBuffer.u;
char* SrcV = YUVBuffer.v;
check( YUVBuffer.y_width == YUVBuffer.uv_width * 2 );
check( YUVBuffer.y_height == YUVBuffer.uv_height * 2 );
check( YUVBuffer.y_width == GetSizeX() );
check( YUVBuffer.y_height == GetSizeY() );
if( GPixelFormats[PF_UYVY].Supported )
{
//@todo optimization: Converts from planar YUV to interleaved PF_UYVY format.
for( UINT y=0; y<SizeY; y++ )
{
for( UINT x=0; x<SizeX/2; x++ )
{
DWORD OffsetY0 = YUVBuffer.y_stride * y + x*2;
DWORD OffsetY1 = YUVBuffer.y_stride * y + x*2 + 1;
DWORD OffsetUV = YUVBuffer.uv_stride * (y/2) + x;
unsigned char Y0 = SrcY[OffsetY0];
unsigned char Y1 = SrcY[OffsetY1];
unsigned char U = SrcU[OffsetUV];
unsigned char V = SrcV[OffsetUV];
((DWORD*)Dest)[y*(SizeX/2) + x] = (Y1 << 24) | (V << 16) | (Y0
<< 8) | U;
}
}
}
else
{
FColor* DestColor = (FColor*) Dest;
//@todo optimization: Converts from planar YUV to interleaved ARGB. This
codepath is currently hit with NVIDIA cards!
for( UINT y=0; y<SizeY; y++ )
{
for( UINT x=0; x<SizeX/2; x++ )
{
DWORD OffsetY0 = YUVBuffer.y_stride * y + x*2;
DWORD OffsetY1 = YUVBuffer.y_stride * y + x*2 + 1;
DWORD OffsetUV = YUVBuffer.uv_stride * (y/2) + x;
unsigned char Y0 = SrcY[OffsetY0];
unsigned char Y1 = SrcY[OffsetY1];
unsigned char U = SrcU[OffsetUV];
unsigned char V = SrcV[OffsetUV];
//@todo optimization: this is a prime candidate for SSE/ Altivec or fixed
point integer or moving it to the GPU though we really ought to just avoid this
codepath altogether.
DestColor->R = Clamp( appTrunc( Y0 + 1.402f * (V-128) ), 0, 255 );
DestColor->G = Clamp( appTrunc( Y0 - 0.34414f * (U-128) - 0.71414f *
(V-128) ), 0, 255 );
DestColor->B = Clamp( appTrunc( Y0 + 1.772 * (U-128) ), 0, 255 );
DestColor->A = 255;
DestColor++;
//@todo optimization: this is a prime candidate for SSE/ Altivec or fixed
point integer or moving it to the GPU though we really ought to just avoid this
codepath altogether.
DestColor->R = Clamp( appTrunc( Y1 + 1.402f * (V-128) ), 0, 255 );
DestColor->G = Clamp( appTrunc( Y1 - 0.34414f * (U-128) - 0.71414f *
(V-128) ), 0, 255 );
DestColor->B = Clamp( appTrunc( Y1 + 1.772 * (U-128) ), 0, 255 );
DestColor->A = 255;
DestColor++;
}
}
}