Recently, an ActiveX control for video playback is coming to an end. Some experiences of using DirectDraw to display YUV data are summarized as follows: (the decoding part is not compiled by me, I receive data from the network, pass the data to the decoder, and display the decoded YUV data. I first convert YUV data to RGB data in the display part, it is displayed on the screen as a bitmap, but it is found that the CPU usage is relatively high. Later, DirectDraw is used to directly display YUV data)
1. Create a YUV surface in DirectDraw
Unlike the general surface, you need to specify the pixel format and the fourcc code of YUV data when creating the YUV surface. For more information about the fourcc code, see the description on the Microsoft msdn site, the following is a specific creation method: (The yuv4: 2: 0 format is used as an example. drawwidth and drawheight are the width and height of the image to be displayed, in pixels)
Lpdirectdraw7 lpdd; // DirectDraw object pointer
Lpdirectdrawsurface7 lpddsprimary; // DirectDraw primary surface pointer
Lpdirectdrawsurface7 lpddsoffscr; // DirectDraw off-screen surface pointer
Ddsurfacedesc2 ddsd; // DirectDraw surface description
// Create a directcraw object
If (directdrawcreateex (null, (void **) & lpdd, iid_idirectdraw7, null )! = Dd_ OK)
{
// MessageBox ("error create ddraw .");
Return false;
}
// Set the collaboration Layer
If (lpdd-> setcooperativelevel (hwnd,
Ddscl_normal | ddscl_nowindowchanges )! = Dd_ OK)
{
// MessageBox ("error create level.", S );
Return false;
}
// Create the primary surface
Zeromemory (& ddsd, sizeof (ddsd ));
Ddsd. dwsize = sizeof (ddsd );
Ddsd. dwflags = ddsd_caps;
Ddsd. ddscaps. dwcaps = ddscaps_primarysurface;
If (lpdd-> createsurface (& ddsd, & lpddsprimary, null )! = Dd_ OK)
{
// MessageBox ("error create primary surface.", S );
Return false;
}
Lpdirectdrawclipper pcclipper; // cliper
If (lpdd-> createid per (0, & pcclipper, null )! = Dd_ OK)
Return false;
If (pcclipper-> sethwnd (0, hwnd )! = Dd_ OK)
{
Pcclipper-> release ();
Return false;
}
If (lpddsprimary-> setclipper (pcclipper )! = Dd_ OK)
{
Pcclipper-> release ();
Return false;
}
// Done with clipper
Pcclipper-> release ();
// Create a YUV Surface
Zeromemory (& ddsd, sizeof (ddsd ));
Ddsd. dwsize = sizeof (ddsd );
Ddsd. ddscaps. dwcaps = ddscaps_offscreenplain;
Ddsd. dwflags = ddsd_caps | ddsd_height | ddsd_width | ddsd_pixelformat;
Ddsd. dwwidth = drawwidth;
Ddsd. dwheight = drawheight;
Ddsd. ddpfpixelformat. dwsize = sizeof (ddpixelformat );
Ddsd. ddpfpixelformat. dwflags = ddpf_fourcc | ddpf_yuv;
Ddsd. ddpfpixelformat. dwfourcc = makefourcc ('y', 'V', '1', '2 ');
Ddsd. ddpfpixelformat. dwyuvbitcount = 8;
If (lpdd-> createsurface (& ddsd, & lpddsoffscr, null )! = Dd_ OK)
{
// MessageBox ("error create off surface.", S );
Return false;
}
2. Copy the decoded YUV data to the YUV surface.
Set the obtained YUV data pointers to Y, U, and V respectively. The data length of each row is BPS. The specific copy code is as follows, note that ddsd must be added to the write pointer for each row to be copied. lpitch (for Y) or ddsd. lpitch/2 (for UV ):
Lpbyte lpsurf = (lpbyte) ddsd. lpsurface;
Lpbyte ptry = y;
Lpbyte ptru = u;
Lpbyte ptrv = V;
Do {
Ddrval = lpddsoffscr-> lock (null, & ddsd, ddlock_wait | ddlock_writeonly, null );
} While (ddrval = dderr_wasstilldrawing );
If (ddrval! = Dd_ OK)
Return 1;
// Fill the off-screen surface
If (lpsurf)
{
For (INT I = 0; iheight; I ++)
{
Memcpy (lpsurf, ptry, ddsd. dwwidth );
Ptry + = BPS;
Lpsurf + = ddsd. lpitch;
}
For (INT I = 0; iheight/2; I ++)
{
Memcpy (lpsurf, ptrv, ddsd. dwwidth/2 );
Ptrv + = BPS;
Lpsurf + = ddsd. lpitch/2;
}
For (INT I = 0; iheight/2; I ++)
{
Memcpy (lpsurf, ptru, ddsd. dwwidth/2 );
Ptru + = BPS;
Lpsurf + = ddsd. lpitch/2;
}
}
Lpddsoffscr-> unlock (null );
3. YUV Surface Display
Now we can directly display the YUV surface BLT to the main surface or the backup surface: (set lpddsback as the backup surface)
Ddrval = lpddsback-> BLT (null, lpddsoffscr, null, ddblt_wait, null );
In this way, the YUV data is displayed. We can see that the DirectDraw is used for direct YUV data display, and the CPU usage is halved.