|
I've mentioned that in my code for decoding i-frames from an mpeg
stream, I used a buffer for the decoded yuv data that I passed to the
constructor of a Bitmap object. If you look at the possible
constructors for the Bitmap object, none can take raw yuv data. You
have to perform a colorspace tranform but then if you save the Bitmap
object as jpeg, the save method has to perform the reverse operation.
Since I just wanted to look at the result, I tried to created a
Direct3D surface with a fourcc code as a pixel format but my hardware
wouldn't allow it (an integrate vidcard on a laptop). So I went back to
the antiques store and used a clipper object for a DirectDraw surface
to do the job. Here's the code for the InitializeGraphics methods which
is passed a pointer to the raw yuv data as argument.
// we need this to create surfaces
SurfaceDescription description = new SurfaceDescription();
// our DirectDraw device
device = new Device();
// set the cooperative level to normal (ie not fullscreen)
device.SetCooperativeLevel(this, CooperativeLevelFlags.Normal);
// set the display mode width and height, and 32 bit color depth.
// you might want to change this to your monitor settings
device.SetDisplayMode(800, 600, 32, 0, false);
// create a primary surface
description.SurfaceCaps.PrimarySurface = true;
// create the primary surface
primary = new Surface(description, device);
// set a clipper object around our form
Clipper clipper = new Clipper(device);
clipper.Window = this;
primary.Clipper = clipper;
// clear out the SurfaceDescription structure.
description.Clear();
// our similated backBuffer will cover the client area
description.Width = this.ClientRectangle.Width;
description.Height = this.ClientRectangle.Height;
// create a fourcc code for NV12 and set the surf descr
int NV12 = MakeFourCC('N', 'V', '1', '2' );
PixelFormat pf = new PixelFormat();
pf.FourCC = NV12;
pf.FourCcIsValid = true;
description.PixelFormatStructure = pf;
// we want an offscreen surface in vid mem
SurfaceCaps caps = new SurfaceCaps();
caps.OffScreenPlain = true;
caps.VideoMemory = true;
description.SurfaceCaps = caps;
// Create the backbuffer
backBuffer = new Surface(description, device);
// scan0 points to our yuv data
byte * scanPtr = (byte *)scan0;
// we have 12 bits per pixel in NV12 with
// one plane for the y's and another plane for pack u's and v's
int lenght = width*height*12/8;
// lock the buffer and copy the data in (might want to optimize this)
GraphicsStream gs = backBuffer.Lock(LockFlags.WriteOnly).Data;
for( int i = 0; i < lenght; i++ )
gs.Write(*scanPtr++);
backBuffer.Unlock();
Then
I just blit to the primary surface in the OnPaint method. I used the
fourcc code NV12 because my card supports it and MS recommends it.
|