We assume that in the RGB video on the drawing (straight, rectangular, etc.), generally adopt a double buffer to continue, using memory MEMORYDC, to achieve the picture on the video display does not blink, but we know that the RGB display video is using GDI to render, which is very CPU-consuming, Then we can be in YUV video rendering, the answer is yes, using DDraw Direct display YUV is OK, can support yuv422 and yuv420 directly using the graphics card display, without CPU, but we use the DDraw display, and then in conjunction with GDI drawing ( lines or rectangles, etc.), the picture is flashing, the reason is that we ddraw directly display YUV video, using the method of the off-screen surface, the YUV data copied to the off-screen surface, and then BLT to the main surface, so with GDI drawing, and video refresh out of sync, causing flicker, So how do we solve the problem? Methods such as the following:
Add a new off-screen surface, we define the OSD off-screen surface bar, we will be the YUV data copied to the off-screen surface, the off-screen surface BLT to the OSD off-screen surface, and then on the OSD off-screen surface to draw a straight line or a rectangle, after painting in the BLT to the main surface, so that the graphics will not
Directly on the source code bar, note that I did not encapsulate the part of the drawing, interested friends can package themselves;
#ifndef_DIRECTDRAW_H_ #define_directdraw_h_#pragma once#include "ddraw.h" #define fourcc_yuyv0x32595559 // MAKEFOURCC (' y ', ' U ', ' y ', ' 2 ') #define fourcc_uyvy0x59565955 // MAKEFOURCC (' U ', ' y ', ' V ', ' y ') #define yuv_uyvy 1#define yuv_yuyv 2class __d Eclspec (dllexport) cdirectdraw{public:cdirectdraw (void); ~cdirectdraw (void); bool Directdrawinit (HWND hwnd, int width , int height,dword DWYUVFOURCC); bool Displayyuvdata (byte *pyuvdata,int byuvtype,rect RECT);
void Directdrawdeinit (void);
Protected:lpdirectdraw7 lpdd;//DirectDraw object pointer LPDIRECTDRAWSURFACE7 lpddsprimary;//DirectDraw Main surface pointer LPDIRECTDRAWSURFACE7 lpddsoffscr;//DirectDraw off-screen surface pointer ddsurfacedesc2ddsd;//DirectDraw Surface description Narrative LPDIRECTDRAWSURFACE7 m_posdsurface;//drawing surface}; #endif
DirectDraw.cpp source files such as the following:
#include "StdAfx.h" #include "DirectDraw.h" #include <string>using namespace std; Cdirectdraw::cdirectdraw (void) {lpdd=null; DirectDraw object pointer lpddsprimary=null; DirectDraw main surface pointer lpddsoffscr=null;
BOOL Cdirectdraw::D Irectdrawinit (hwnd hwnd, int width, int height,dword dwyuvfourcc) {HRESULT hr;//Create Directcraw object if ( Directdrawcreateex (null, (void**) &LPDD, IID_IDIRECTDRAW7, NULL)! = DD_OK) {return false;} Set the collaboration layer if (Lpdd->setcooperativelevel (Hwnd,ddscl_normal | ddscl_nowindowchanges)! = DD_OK) {return false;} Create main surface lpvoid lpsurface = NULL; ZeroMemory (&DDSD, sizeof (DDSD)); ZeroMemory (&ddsd.ddpfpixelformat, sizeof (Ddpixelformat));dd sd.dwsize = sizeof (DDSD);dd sd.dwflags = ddsd_caps; Ddsd.ddsCaps.dwCaps = Ddscaps_primarysurface;if (Lpdd->createsurface (&DDSD, &lpddsprimary, NULL)! = DD_OK) {return false;} Lpdirectdrawclipper Pcclipper; Cliperif (lpdd->createclipper (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 Clipperpcclipper->release ();//create YUV surface ddsd.ddscaps. dwcaps = Ddscaps_offscreenplain | Ddscaps_videomemory;dd sd.dwflags = Ddsd_caps | Ddsd_height | Ddsd_width | Ddsd_pixelformat;dd sd.dwwidth = width;ddsd.dwheight =height;ddsd.ddpfpixelformat.dwsize = sizeof (DDPIXELFORMAT); Ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC | DDPF_YUV;dd sd.ddpfPixelFormat.dwYUVBitCount = 8; Ddsd.ddpfPixelFormat.dwFourCC =dwyuvfourcc;hr=lpdd->createsurface (&DDSD, &LPDDSOFFSCR, NULL); if (hr!= DD _OK) {return false;} #if 1//Create OSD drawing off-screen surface//zeromemory (&DDSD, sizeof (DDSD));dd sd.dwsize = sizeof (DDSD);dd sd.ddsCaps.dwCaps = Ddscaps_ Offscreenplain;ddsd.dwflags = Ddsd_caps | Ddsd_height | Ddsd_width;ddsd.dwwidth = Width;ddsd.dwheight = Height;hr = Lpdd->createsurface (&DDSD, &m_pOsdSurface, NULL ); if (hr! = DD_OK) {//lpdd->release ();//lpddsprimary = NULL;//LPDD = Null;return false;} #endifreturn true;} Add RECT parameter, zooms the image into RECT bool Cdirectdraw::D isplayyuvdata (byte *pyuvdata,int byuvtype,rect RECT) {byte *psurf;int yuv_ Type=byuvtype; HRESULT Hr;hr=lpddsOffscr->lock (null,&ddsd,ddlock_surfacememoryptr| Ddlock_wait,null);//2012-02-24if (hr==dderr_surfacelost) {TRACE ("Off surface lost,restore offscr\n"); hr= Lpddsoffscr->restore (); Hr=lpddsoffscr->lock (null,&ddsd,ddlock_surfacememoryptr| Ddlock_wait,null);} if (FAILED (HR)) {return dd_false;} 2012-02-11 if (yuv_type==yuv_uyvy) {Ddsd.ddpfPixelFormat.dwFourCC =fourcc_uyvy;} ELSE{DDSD.DDPFPIXELFORMAT.DWFOURCC =fourcc_yuyv;} psurf= (LPBYTE) ddsd.lpsurface;if (Psurf) {for (unsigned int i=0; i < ddsd.dwheight; i++) {memcpy (psurf,pyuvdata), ddsd.dwwidth*2);p Yuvdata+=ddsd.dwwidth*2;psurf+=ddsd.lpitch;}} Lpddsoffscr->unlock (NULL); #if 1//increases OSD off-screen surface content HRESULT Ddrval;ddrval = M_POSDSURFACE->BLT (&rect, LPDDSOFFSCR, NULL, ddblt_wait, NULL); Ddrval! = DD_OK) {ddrval = Lpddsprimary->blt (&rect, LPDDSOFFSCR, &rect, ddblt_wait, NULL);} Else{hdc HDC = Null;ddrval = M_posdsurface->getdc (&HDC), if ((Ddrval = DD_OK) && (HDC = NULL)) {// Overlay Text SetTextColor (Hdc,rgb (255,0,0)); SetBkcolor (Hdc,rgb (0,255,0)); CString m_sosdmsg=_t ("Hello World"); TextOut (HDC, rect.left+100,rect.top+200, M_sosdmsg, M_sosdmsg.getlength ());//Draw a solid rectangle hpen hpen = CreatePen (ps_solid, 1, RGB (255, 0, 0)); SelectObject (HDC, Hpen); Hbrush hbrush = CreateSolidBrush (RGB (0, 255, 0)); Create Brush SelectObject (HDC, hbrush); Use brush Rectangle (HDC, rect.left+100, rect.top+100, rect.left+200, rect.top+200); Draw Rectangle//Draw Hollow Rectangle rect rect1;rect1.left=rect.left+200;rect1.top=rect.top+200;rect1.right=rect.left+300;rect1.bottom= rect.top+300; Framerect (Hdc,&rect1,createsolidbrush (RGB (255,0,0)));//Draw straight Movetoex (hdc,rect.left+50,rect.top+50,null); LineTo (hdc,rect.left+350,rect.top+350); M_posdsurface->releasedc (HDC); Lpddsprimary->blt (&rect, m_ Posdsurface, &rect, ddblt_wait, NULL);}} #else//Only the main surface and the off-screen surface HRESULT Ddrval;ddrval=lpddsprimary->blt (&rect, LPDDSOFFSCR, NULL, ddblt_wait, NULL); Ddrval==dderr_surfacelost) {TRACE ("primary surface Lost,restore all surfaces\n"); Lpddsprimary->restore ();} #endifreturn Dd_ok;} DDraw deinitvoid Cdirectdraw::D irectdrawdeinit (void) {if (LPDDSOFFSCR! = NULL) {lpddsoffscr->release (); LPDDSOFFSCR = NULL;} if (lpddsprimary! = null) {lpddsprimary->release (); lpddsprimary = null;} if (LPDD! = null) {lpdd->release (); lpdd = null;} if (m_posdsurface!=null) {m_posdsurface->release (); m_posdsurface=null;}}
Test results such as the following:
DDraw GDI drawing knowledge such as the following:
Because DirectDraw does not provide statements that draw points, lines, circles, and so on, we use the Windows GDI functions to complete the work. Just like the output text, we first get the HDC of the page:
HDC hdc;
LPDDSXXX->GETDC (&HDC);
Draw points are the simplest,setpixel (hdc, x, Y, RGB (R, G, b)); You can draw a point of the specified color at the (x, y) coordinates of the screen.
Suppose you need to draw a line, etc., we need to create a "brush":
Hpen Hpen = CreatePen (Ps_solid, 5, RGB (R, G, b));
The first parameter of the CreatePen is the brush style, which is often used with ps_solid (normal brushes) and ps_dot (brushes made up of discontinuities, which need to be set to a brush width of 1). The second parameter is the width of the brush, and the third is the color of the brush.
Then give the brush to HDC:
SelectObject (hdc, hpen);
Move brush to (x1,y1):
MOVETOEX (hdc, x1, y1, NULL);
Draw a line from the starting position of the drawing to (x2,y2) coordinates:
LineTo (hdc, x2, y2);
Here are some frequently used drawing statements that are almost identical in usage and drawing, and can be used when you finish setting the brush:
Rectangle (hdc, x1, y1, x2, y2); // Draw a rectangle
Ellipse (hdc, x1, y1, x2, y2); // Draw an ellipse
It is important to note that the graphics we draw will be filled by a "brush", using the simplest monochrome brush method:
Hbrush hbrush = CreateSolidBrush (RGB (R, G, b)); // Create brushes
SelectObject (hdc, hbrush); // using brushes
After the drawing, we have to remember to release the HDC:
LPDDSXXX->RELEASEDC (HDC);
How to DDraw the drawing without blinking in the video