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