1 //------------------------------------------------------------------------------ 2 // File: WinUtil.h 3 // 4 // Desc: DirectShow base classes - defines generic handler classes. 5 // 6 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved. 7 //------------------------------------------------------------------------------ 8 9 10 // Make sure that you call PrepareWindow to initialise the window after 11 // the object has been constructed. It is a separate method so that 12 // derived classes can override useful methods like MessageLoop. Also 13 // any derived class must call DoneWithWindow in its destructor. If it 14 // doesn't a message may be retrieved and call a derived class member 15 // function while a thread is executing the base class destructor code 16 17 #ifndef __WINUTIL__ 18 #define __WINUTIL__ 19 20 const int DEFWIDTH = 320; // Initial window width 21 const int DEFHEIGHT = 240; // Initial window height 22 const int CAPTION = 256; // Maximum length of caption 23 const int TIMELENGTH = 50; // Maximum length of times 24 const int PROFILESTR = 128; // Normal profile string 25 const WORD PALVERSION = 0x300; // GDI palette version 26 const LONG PALETTE_VERSION = (LONG) 1; // Initial palette version 27 const COLORREF VIDEO_COLOUR = 0; // Defaults to black background 28 const HANDLE hMEMORY = (HANDLE) (-1); // Says to open as memory file 29 30 #define WIDTH(x) ((*(x)).right - (*(x)).left) 31 #define HEIGHT(x) ((*(x)).bottom - (*(x)).top) 32 #define SHOWSTAGE TEXT("WM_SHOWSTAGE") 33 #define SHOWSTAGETOP TEXT("WM_SHOWSTAGETOP") 34 #define REALIZEPALETTE TEXT("WM_REALIZEPALETTE") 35 36 class AM_NOVTABLE CBaseWindow 37 { 38 protected: 39 40 HINSTANCE m_hInstance; // Global module instance handle 41 HWND m_hwnd; // Handle for our window 42 HDC m_hdc; // Device context for the window 43 LONG m_Width; // Client window width 44 LONG m_Height; // Client window height 45 BOOL m_bActivated; // Has the window been activated 46 LPTSTR m_pClassName; // Static string holding class name 47 DWORD m_ClassStyles; // Passed in to our constructor 48 DWORD m_WindowStyles; // Likewise the initial window styles 49 DWORD m_WindowStylesEx; // And the extended window styles 50 UINT m_ShowStageMessage; // Have the window shown with focus 51 UINT m_ShowStageTop; // Makes the window WS_EX_TOPMOST 52 UINT m_RealizePalette; // Makes us realize our new palette 53 HDC m_MemoryDC; // Used for fast BitBlt operations 54 HPALETTE m_hPalette; // Handle to any palette we may have 55 BYTE m_bNoRealize; // Don't realize palette now 56 BYTE m_bBackground; // Should we realise in background 57 BYTE m_bRealizing; // already realizing the palette 58 CCritSec m_WindowLock; // Serialise window object access 59 BOOL m_bDoGetDC; // Should this window get a DC 60 bool m_bDoPostToDestroy; // Use PostMessage to destroy 61 CCritSec m_PaletteLock; // This lock protects m_hPalette. 62 // It should be held anytime the 63 // program use the value of m_hPalette. 64 65 // Maps windows message procedure into C++ methods 66 friend LRESULT CALLBACK WndProc(HWND hwnd, // Window handle 67 UINT uMsg, // Message ID 68 WPARAM wParam, // First parameter 69 LPARAM lParam); // Other parameter 70 71 virtual LRESULT OnPaletteChange(HWND hwnd, UINT Message); 72 73 public: 74 75 CBaseWindow(BOOL bDoGetDC = TRUE, bool bPostToDestroy = false); 76 77 #ifdef DEBUG 78 virtual ~CBaseWindow(); 79 #endif 80 81 virtual HRESULT DoneWithWindow(); 82 virtual HRESULT PrepareWindow(); 83 virtual HRESULT InactivateWindow(); 84 virtual HRESULT ActivateWindow(); 85 virtual BOOL OnSize(LONG Width, LONG Height); 86 virtual BOOL OnClose(); 87 virtual RECT GetDefaultRect(); 88 virtual HRESULT UninitialiseWindow(); 89 virtual HRESULT InitialiseWindow(HWND hwnd); 90 91 HRESULT CompleteConnect(); 92 HRESULT DoCreateWindow(); 93 94 HRESULT PerformanceAlignWindow(); 95 HRESULT DoShowWindow(LONG ShowCmd); 96 void PaintWindow(BOOL bErase); 97 void DoSetWindowForeground(BOOL bFocus); 98 virtual HRESULT SetPalette(HPALETTE hPalette); SetRealize(BOOL bRealize)99 void SetRealize(BOOL bRealize) 100 { 101 m_bNoRealize = !bRealize; 102 } 103 104 // Jump over to the window thread to set the current palette 105 HRESULT SetPalette(); 106 void UnsetPalette(void); 107 virtual HRESULT DoRealisePalette(BOOL bForceBackground = FALSE); 108 109 void LockPaletteLock(); 110 void UnlockPaletteLock(); 111 PossiblyEatMessage(UINT uMsg,WPARAM wParam,LPARAM lParam)112 virtual BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) 113 { return FALSE; }; 114 115 // Access our window information 116 117 bool WindowExists(); 118 LONG GetWindowWidth(); 119 LONG GetWindowHeight(); 120 HWND GetWindowHWND(); 121 HDC GetMemoryHDC(); 122 HDC GetWindowHDC(); 123 124 #ifdef DEBUG 125 HPALETTE GetPalette(); 126 #endif // DEBUG 127 128 // This is the window procedure the derived object should override 129 130 virtual LRESULT OnReceiveMessage(HWND hwnd, // Window handle 131 UINT uMsg, // Message ID 132 WPARAM wParam, // First parameter 133 LPARAM lParam); // Other parameter 134 135 // Must be overriden to return class and window styles 136 137 virtual LPTSTR GetClassWindowStyles( 138 DWORD *pClassStyles, // Class styles 139 DWORD *pWindowStyles, // Window styles 140 DWORD *pWindowStylesEx) PURE; // Extended styles 141 }; 142 143 144 // This helper class is entirely subservient to the owning CBaseWindow object 145 // All this object does is to split out the actual drawing operation from the 146 // main object (because it was becoming too large). We have a number of entry 147 // points to set things like the draw device contexts, to implement the actual 148 // drawing and to set the destination rectangle in the client window. We have 149 // no critical section locking in this class because we are used exclusively 150 // by the owning window object which looks after serialising calls into us 151 152 // If you want to use this class make sure you call NotifyAllocator once the 153 // allocate has been agreed, also call NotifyMediaType with a pointer to a 154 // NON stack based CMediaType once that has been set (we keep a pointer to 155 // the original rather than taking a copy). When the palette changes call 156 // IncrementPaletteVersion (easiest thing to do is to also call this method 157 // in the SetMediaType method most filters implement). Finally before you 158 // start rendering anything call SetDrawContext so that we can get the HDCs 159 // for drawing from the CBaseWindow object we are given during construction 160 161 class CDrawImage 162 { 163 protected: 164 165 CBaseWindow *m_pBaseWindow; // Owning video window object 166 CRefTime m_StartSample; // Start time for the current sample 167 CRefTime m_EndSample; // And likewise it's end sample time 168 HDC m_hdc; // Main window device context 169 HDC m_MemoryDC; // Offscreen draw device context 170 RECT m_TargetRect; // Target destination rectangle 171 RECT m_SourceRect; // Source image rectangle 172 BOOL m_bStretch; // Do we have to stretch the images 173 BOOL m_bUsingImageAllocator; // Are the samples shared DIBSECTIONs 174 CMediaType *m_pMediaType; // Pointer to the current format 175 int m_perfidRenderTime; // Time taken to render an image 176 LONG m_PaletteVersion; // Current palette version cookie 177 178 // Draw the video images in the window 179 180 void SlowRender(IMediaSample *pMediaSample); 181 void FastRender(IMediaSample *pMediaSample); 182 void DisplaySampleTimes(IMediaSample *pSample); 183 void UpdateColourTable(HDC hdc,BITMAPINFOHEADER *pbmi); 184 void SetStretchMode(); 185 186 public: 187 188 // Used to control the image drawing 189 190 CDrawImage(CBaseWindow *pBaseWindow); 191 BOOL DrawImage(IMediaSample *pMediaSample); 192 BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample, 193 LPRECT lprcSrc, LPRECT lprcDst); 194 void SetDrawContext(); 195 void SetTargetRect(RECT *pTargetRect); 196 void SetSourceRect(RECT *pSourceRect); 197 void GetTargetRect(RECT *pTargetRect); 198 void GetSourceRect(RECT *pSourceRect); 199 virtual RECT ScaleSourceRect(const RECT *pSource); 200 201 // Handle updating palettes as they change 202 203 LONG GetPaletteVersion(); 204 void ResetPaletteVersion(); 205 void IncrementPaletteVersion(); 206 207 // Tell us media types and allocator assignments 208 209 void NotifyAllocator(BOOL bUsingImageAllocator); 210 void NotifyMediaType(CMediaType *pMediaType); 211 BOOL UsingImageAllocator(); 212 213 // Called when we are about to draw an image 214 NotifyStartDraw()215 void NotifyStartDraw() { 216 MSR_START(m_perfidRenderTime); 217 }; 218 219 // Called when we complete an image rendering 220 NotifyEndDraw()221 void NotifyEndDraw() { 222 MSR_STOP(m_perfidRenderTime); 223 }; 224 }; 225 226 227 // This is the structure used to keep information about each GDI DIB. All the 228 // samples we create from our allocator will have a DIBSECTION allocated to 229 // them. When we receive the sample we know we can BitBlt straight to an HDC 230 231 typedef struct tagDIBDATA { 232 233 LONG PaletteVersion; // Current palette version in use 234 DIBSECTION DibSection; // Details of DIB section allocated 235 HBITMAP hBitmap; // Handle to bitmap for drawing 236 HANDLE hMapping; // Handle to shared memory block 237 BYTE *pBase; // Pointer to base memory address 238 239 } DIBDATA; 240 241 242 // This class inherits from CMediaSample and uses all of it's methods but it 243 // overrides the constructor to initialise itself with the DIBDATA structure 244 // When we come to render an IMediaSample we will know if we are using our own 245 // allocator, and if we are, we can cast the IMediaSample to a pointer to one 246 // of these are retrieve the DIB section information and hence the HBITMAP 247 248 class CImageSample : public CMediaSample 249 { 250 protected: 251 252 DIBDATA m_DibData; // Information about the DIBSECTION 253 BOOL m_bInit; // Is the DIB information setup 254 255 public: 256 257 // Constructor 258 259 CImageSample(CBaseAllocator *pAllocator, 260 TCHAR *pName, 261 HRESULT *phr, 262 LPBYTE pBuffer, 263 LONG length); 264 265 // Maintain the DIB/DirectDraw state 266 267 void SetDIBData(DIBDATA *pDibData); 268 DIBDATA *GetDIBData(); 269 }; 270 271 272 // This is an allocator based on the abstract CBaseAllocator base class that 273 // allocates sample buffers in shared memory. The number and size of these 274 // are determined when the output pin calls Prepare on us. The shared memory 275 // blocks are used in subsequent calls to GDI CreateDIBSection, once that 276 // has been done the output pin can fill the buffers with data which will 277 // then be handed to GDI through BitBlt calls and thereby remove one copy 278 279 class CImageAllocator : public CBaseAllocator 280 { 281 protected: 282 283 CBaseFilter *m_pFilter; // Delegate reference counts to 284 CMediaType *m_pMediaType; // Pointer to the current format 285 286 // Used to create and delete samples 287 288 HRESULT Alloc(); 289 void Free(); 290 291 // Manage the shared DIBSECTION and DCI/DirectDraw buffers 292 293 HRESULT CreateDIB(LONG InSize,DIBDATA &DibData); 294 STDMETHODIMP CheckSizes(ALLOCATOR_PROPERTIES *pRequest); 295 virtual CImageSample *CreateImageSample(LPBYTE pData,LONG Length); 296 297 public: 298 299 // Constructor and destructor 300 301 CImageAllocator(CBaseFilter *pFilter,TCHAR *pName,HRESULT *phr); 302 #ifdef DEBUG 303 ~CImageAllocator(); 304 #endif 305 306 STDMETHODIMP_(ULONG) NonDelegatingAddRef(); 307 STDMETHODIMP_(ULONG) NonDelegatingRelease(); 308 void NotifyMediaType(CMediaType *pMediaType); 309 310 // Agree the number of buffers to be used and their size 311 312 STDMETHODIMP SetProperties( 313 ALLOCATOR_PROPERTIES *pRequest, 314 ALLOCATOR_PROPERTIES *pActual); 315 }; 316 317 318 // This class is a fairly specialised helper class for image renderers that 319 // have to create and manage palettes. The CBaseWindow class looks after 320 // realising palettes once they have been installed. This class can be used 321 // to create the palette handles from a media format (which must contain a 322 // VIDEOINFO structure in the format block). We try to make the palette an 323 // identity palette to maximise performance and also only change palettes 324 // if actually required to (we compare palette colours before updating). 325 // All the methods are virtual so that they can be overriden if so required 326 327 class CImagePalette 328 { 329 protected: 330 331 CBaseWindow *m_pBaseWindow; // Window to realise palette in 332 CBaseFilter *m_pFilter; // Media filter to send events 333 CDrawImage *m_pDrawImage; // Object who will be drawing 334 HPALETTE m_hPalette; // The palette handle we own 335 336 public: 337 338 CImagePalette(CBaseFilter *pBaseFilter, 339 CBaseWindow *pBaseWindow, 340 CDrawImage *pDrawImage); 341 342 #ifdef DEBUG 343 virtual ~CImagePalette(); 344 #endif 345 346 static HPALETTE MakePalette(const VIDEOINFOHEADER *pVideoInfo, LPSTR szDevice); 347 HRESULT RemovePalette(); 348 static HRESULT MakeIdentityPalette(PALETTEENTRY *pEntry,INT iColours, LPSTR szDevice); 349 HRESULT CopyPalette(const CMediaType *pSrc,CMediaType *pDest); 350 BOOL ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,const VIDEOINFOHEADER *pOldInfo); 351 HRESULT PreparePalette(const CMediaType *pmtNew,const CMediaType *pmtOld,LPSTR szDevice); 352 DrawVideoImageHere(HDC hdc,IMediaSample * pMediaSample,LPRECT lprcSrc,LPRECT lprcDst)353 BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample, LPRECT lprcSrc, LPRECT lprcDst) 354 { 355 return m_pDrawImage->DrawVideoImageHere(hdc, pMediaSample, lprcSrc,lprcDst); 356 } 357 }; 358 359 360 // Another helper class really for video based renderers. Most such renderers 361 // need to know what the display format is to some degree or another. This 362 // class initialises itself with the display format. The format can be asked 363 // for through GetDisplayFormat and various other accessor functions. If a 364 // filter detects a display format change (perhaps it gets a WM_DEVMODECHANGE 365 // message then it can call RefreshDisplayType to reset that format). Also 366 // many video renderers will want to check formats as they are proposed by 367 // source filters. This class provides methods to check formats and only 368 // accept those video formats that can be efficiently drawn using GDI calls 369 370 class CImageDisplay : public CCritSec 371 { 372 protected: 373 374 // This holds the display format; biSize should not be too big, so we can 375 // safely use the VIDEOINFO structure 376 VIDEOINFO m_Display; 377 378 static DWORD CountSetBits(const DWORD Field); 379 static DWORD CountPrefixBits(const DWORD Field); 380 static BOOL CheckBitFields(const VIDEOINFO *pInput); 381 382 public: 383 384 // Constructor and destructor 385 386 CImageDisplay(); 387 388 // Used to manage BITMAPINFOHEADERs and the display format 389 390 const VIDEOINFO *GetDisplayFormat(); 391 HRESULT RefreshDisplayType(LPSTR szDeviceName); 392 static BOOL CheckHeaderValidity(const VIDEOINFO *pInput); 393 static BOOL CheckPaletteHeader(const VIDEOINFO *pInput); 394 BOOL IsPalettised(); 395 WORD GetDisplayDepth(); 396 397 // Provide simple video format type checking 398 399 HRESULT CheckMediaType(const CMediaType *pmtIn); 400 HRESULT CheckVideoType(const VIDEOINFO *pInput); 401 HRESULT UpdateFormat(VIDEOINFO *pVideoInfo); 402 const DWORD *GetBitMasks(const VIDEOINFO *pVideoInfo); 403 404 BOOL GetColourMask(DWORD *pMaskRed, 405 DWORD *pMaskGreen, 406 DWORD *pMaskBlue); 407 }; 408 409 // Convert a FORMAT_VideoInfo to FORMAT_VideoInfo2 410 STDAPI ConvertVideoInfoToVideoInfo2(AM_MEDIA_TYPE *pmt); 411 412 #endif // __WINUTIL__ 413 414