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