summaryrefslogtreecommitdiffstats
path: root/thirdparties/win32/include/directshow/winutil.h
blob: 641b53a49077f5c9d1321782dc3d6115a063991c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
//------------------------------------------------------------------------------
// File: WinUtil.h
//
// Desc: DirectShow base classes - defines generic handler classes.
//
// Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------


// Make sure that you call PrepareWindow to initialise the window after
// the object has been constructed. It is a separate method so that
// derived classes can override useful methods like MessageLoop. Also
// any derived class must call DoneWithWindow in its destructor. If it
// doesn't a message may be retrieved and call a derived class member
// function while a thread is executing the base class destructor code

#ifndef __WINUTIL__
#define __WINUTIL__

const int DEFWIDTH = 320;                    // Initial window width
const int DEFHEIGHT = 240;                   // Initial window height
const int CAPTION = 256;                     // Maximum length of caption
const int TIMELENGTH = 50;                   // Maximum length of times
const int PROFILESTR = 128;                  // Normal profile string
const WORD PALVERSION = 0x300;               // GDI palette version
const LONG PALETTE_VERSION = (LONG) 1;       // Initial palette version
const COLORREF VIDEO_COLOUR = 0;             // Defaults to black background
const HANDLE hMEMORY = (HANDLE) (-1);        // Says to open as memory file

#define WIDTH(x) ((*(x)).right - (*(x)).left)
#define HEIGHT(x) ((*(x)).bottom - (*(x)).top)
#define SHOWSTAGE TEXT("WM_SHOWSTAGE")
#define SHOWSTAGETOP TEXT("WM_SHOWSTAGETOP")
#define REALIZEPALETTE TEXT("WM_REALIZEPALETTE")

class AM_NOVTABLE CBaseWindow
{
protected:

    HINSTANCE m_hInstance;          // Global module instance handle
    HWND m_hwnd;                    // Handle for our window
    HDC m_hdc;                      // Device context for the window
    LONG m_Width;                   // Client window width
    LONG m_Height;                  // Client window height
    BOOL m_bActivated;              // Has the window been activated
    LPTSTR m_pClassName;            // Static string holding class name
    DWORD m_ClassStyles;            // Passed in to our constructor
    DWORD m_WindowStyles;           // Likewise the initial window styles
    DWORD m_WindowStylesEx;         // And the extended window styles
    UINT m_ShowStageMessage;        // Have the window shown with focus
    UINT m_ShowStageTop;            // Makes the window WS_EX_TOPMOST
    UINT m_RealizePalette;          // Makes us realize our new palette
    HDC m_MemoryDC;                 // Used for fast BitBlt operations
    HPALETTE m_hPalette;            // Handle to any palette we may have
    BYTE m_bNoRealize;              // Don't realize palette now
    BYTE m_bBackground;             // Should we realise in background
    BYTE m_bRealizing;              // already realizing the palette
    CCritSec m_WindowLock;          // Serialise window object access
    BOOL m_bDoGetDC;                // Should this window get a DC
    bool m_bDoPostToDestroy;        // Use PostMessage to destroy
    CCritSec m_PaletteLock;         // This lock protects m_hPalette.
                                    // It should be held anytime the
                                    // program use the value of m_hPalette.

    // Maps windows message procedure into C++ methods
    friend LRESULT CALLBACK WndProc(HWND hwnd,      // Window handle
                                    UINT uMsg,      // Message ID
                                    WPARAM wParam,  // First parameter
                                    LPARAM lParam); // Other parameter

    virtual LRESULT OnPaletteChange(HWND hwnd, UINT Message);

public:

    CBaseWindow(BOOL bDoGetDC = TRUE, bool bPostToDestroy = false);

#ifdef DEBUG
    virtual ~CBaseWindow();
#endif

    virtual HRESULT DoneWithWindow();
    virtual HRESULT PrepareWindow();
    virtual HRESULT InactivateWindow();
    virtual HRESULT ActivateWindow();
    virtual BOOL OnSize(LONG Width, LONG Height);
    virtual BOOL OnClose();
    virtual RECT GetDefaultRect();
    virtual HRESULT UninitialiseWindow();
    virtual HRESULT InitialiseWindow(HWND hwnd);

    HRESULT CompleteConnect();
    HRESULT DoCreateWindow();

    HRESULT PerformanceAlignWindow();
    HRESULT DoShowWindow(LONG ShowCmd);
    void PaintWindow(BOOL bErase);
    void DoSetWindowForeground(BOOL bFocus);
    virtual HRESULT SetPalette(HPALETTE hPalette);
    void SetRealize(BOOL bRealize)
    {
        m_bNoRealize = !bRealize;
    }

    //  Jump over to the window thread to set the current palette
    HRESULT SetPalette();
    void UnsetPalette(void);
    virtual HRESULT DoRealisePalette(BOOL bForceBackground = FALSE);

    void LockPaletteLock();
    void UnlockPaletteLock();

    virtual BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
	    { return FALSE; };

    // Access our window information

    bool WindowExists();
    LONG GetWindowWidth();
    LONG GetWindowHeight();
    HWND GetWindowHWND();
    HDC GetMemoryHDC();
    HDC GetWindowHDC();

    #ifdef DEBUG
    HPALETTE GetPalette();
    #endif // DEBUG

    // This is the window procedure the derived object should override

    virtual LRESULT OnReceiveMessage(HWND hwnd,          // Window handle
                                     UINT uMsg,          // Message ID
                                     WPARAM wParam,      // First parameter
                                     LPARAM lParam);     // Other parameter

    // Must be overriden to return class and window styles

    virtual LPTSTR GetClassWindowStyles(
                            __out DWORD *pClassStyles,          // Class styles
                            __out DWORD *pWindowStyles,         // Window styles
                            __out DWORD *pWindowStylesEx) PURE; // Extended styles
};


// This helper class is entirely subservient to the owning CBaseWindow object
// All this object does is to split out the actual drawing operation from the
// main object (because it was becoming too large). We have a number of entry
// points to set things like the draw device contexts, to implement the actual
// drawing and to set the destination rectangle in the client window. We have
// no critical section locking in this class because we are used exclusively
// by the owning window object which looks after serialising calls into us

// If you want to use this class make sure you call NotifyAllocator once the
// allocate has been agreed, also call NotifyMediaType with a pointer to a
// NON stack based CMediaType once that has been set (we keep a pointer to
// the original rather than taking a copy). When the palette changes call
// IncrementPaletteVersion (easiest thing to do is to also call this method
// in the SetMediaType method most filters implement). Finally before you
// start rendering anything call SetDrawContext so that we can get the HDCs
// for drawing from the CBaseWindow object we are given during construction

class CDrawImage
{
protected:

    CBaseWindow *m_pBaseWindow;     // Owning video window object
    CRefTime m_StartSample;         // Start time for the current sample
    CRefTime m_EndSample;           // And likewise it's end sample time
    HDC m_hdc;                      // Main window device context
    HDC m_MemoryDC;                 // Offscreen draw device context
    RECT m_TargetRect;              // Target destination rectangle
    RECT m_SourceRect;              // Source image rectangle
    BOOL m_bStretch;                // Do we have to stretch the images
    BOOL m_bUsingImageAllocator;    // Are the samples shared DIBSECTIONs
    CMediaType *m_pMediaType;       // Pointer to the current format
    int m_perfidRenderTime;         // Time taken to render an image
    LONG m_PaletteVersion;          // Current palette version cookie

    // Draw the video images in the window

    void SlowRender(IMediaSample *pMediaSample);
    void FastRender(IMediaSample *pMediaSample);
    void DisplaySampleTimes(IMediaSample *pSample);
    void UpdateColourTable(HDC hdc,__in BITMAPINFOHEADER *pbmi);
    void SetStretchMode();

public:

    // Used to control the image drawing

    CDrawImage(__inout CBaseWindow *pBaseWindow);
    BOOL DrawImage(IMediaSample *pMediaSample);
    BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample,
                            __in LPRECT lprcSrc, __in LPRECT lprcDst);
    void SetDrawContext();
    void SetTargetRect(__in RECT *pTargetRect);
    void SetSourceRect(__in RECT *pSourceRect);
    void GetTargetRect(__out RECT *pTargetRect);
    void GetSourceRect(__out RECT *pSourceRect);
    virtual RECT ScaleSourceRect(const RECT *pSource);

    // Handle updating palettes as they change

    LONG GetPaletteVersion();
    void ResetPaletteVersion();
    void IncrementPaletteVersion();

    // Tell us media types and allocator assignments

    void NotifyAllocator(BOOL bUsingImageAllocator);
    void NotifyMediaType(__in CMediaType *pMediaType);
    BOOL UsingImageAllocator();

    // Called when we are about to draw an image

    void NotifyStartDraw() {
        MSR_START(m_perfidRenderTime);
    };

    // Called when we complete an image rendering

    void NotifyEndDraw() {
        MSR_STOP(m_perfidRenderTime);
    };
};


// This is the structure used to keep information about each GDI DIB. All the
// samples we create from our allocator will have a DIBSECTION allocated to
// them. When we receive the sample we know we can BitBlt straight to an HDC

typedef struct tagDIBDATA {

    LONG        PaletteVersion;     // Current palette version in use
    DIBSECTION  DibSection;         // Details of DIB section allocated
    HBITMAP     hBitmap;            // Handle to bitmap for drawing
    HANDLE      hMapping;           // Handle to shared memory block
    BYTE        *pBase;             // Pointer to base memory address

} DIBDATA;


// This class inherits from CMediaSample and uses all of it's methods but it
// overrides the constructor to initialise itself with the DIBDATA structure
// When we come to render an IMediaSample we will know if we are using our own
// allocator, and if we are, we can cast the IMediaSample to a pointer to one
// of these are retrieve the DIB section information and hence the HBITMAP

class CImageSample : public CMediaSample
{
protected:

    DIBDATA m_DibData;      // Information about the DIBSECTION
    BOOL m_bInit;           // Is the DIB information setup

public:

    // Constructor

    CImageSample(__inout CBaseAllocator *pAllocator,
                 __in_opt LPCTSTR pName,
                 __inout HRESULT *phr,
                 __in_bcount(length) LPBYTE pBuffer,
                 LONG length);

    // Maintain the DIB/DirectDraw state

    void SetDIBData(__in DIBDATA *pDibData);
    __out DIBDATA *GetDIBData();
};


// This is an allocator based on the abstract CBaseAllocator base class that
// allocates sample buffers in shared memory. The number and size of these
// are determined when the output pin calls Prepare on us. The shared memory
// blocks are used in subsequent calls to GDI CreateDIBSection, once that
// has been done the output pin can fill the buffers with data which will
// then be handed to GDI through BitBlt calls and thereby remove one copy

class CImageAllocator : public CBaseAllocator
{
protected:

    CBaseFilter *m_pFilter;   // Delegate reference counts to
    CMediaType *m_pMediaType;           // Pointer to the current format

    // Used to create and delete samples

    HRESULT Alloc();
    void Free();

    // Manage the shared DIBSECTION and DCI/DirectDraw buffers

    HRESULT CreateDIB(LONG InSize,DIBDATA &DibData);
    STDMETHODIMP CheckSizes(__in ALLOCATOR_PROPERTIES *pRequest);
    virtual CImageSample *CreateImageSample(__in_bcount(Length) LPBYTE pData,LONG Length);

public:

    // Constructor and destructor

    CImageAllocator(__inout CBaseFilter *pFilter,__in_opt LPCTSTR pName,__inout HRESULT *phr);
#ifdef DEBUG
    ~CImageAllocator();
#endif

    STDMETHODIMP_(ULONG) NonDelegatingAddRef();
    STDMETHODIMP_(ULONG) NonDelegatingRelease();
    void NotifyMediaType(__in CMediaType *pMediaType);

    // Agree the number of buffers to be used and their size

    STDMETHODIMP SetProperties(
        __in ALLOCATOR_PROPERTIES *pRequest,
        __out ALLOCATOR_PROPERTIES *pActual);
};


// This class is a fairly specialised helper class for image renderers that
// have to create and manage palettes. The CBaseWindow class looks after
// realising palettes once they have been installed. This class can be used
// to create the palette handles from a media format (which must contain a
// VIDEOINFO structure in the format block). We try to make the palette an
// identity palette to maximise performance and also only change palettes
// if actually required to (we compare palette colours before updating).
// All the methods are virtual so that they can be overriden if so required

class CImagePalette
{
protected:

    CBaseWindow *m_pBaseWindow;             // Window to realise palette in
    CBaseFilter *m_pFilter;                 // Media filter to send events
    CDrawImage *m_pDrawImage;               // Object who will be drawing
    HPALETTE m_hPalette;                    // The palette handle we own

public:

    CImagePalette(__inout CBaseFilter *pBaseFilter,
                  __inout CBaseWindow *pBaseWindow,
                  __inout CDrawImage *pDrawImage);

#ifdef DEBUG
    virtual ~CImagePalette();
#endif

    static HPALETTE MakePalette(const VIDEOINFOHEADER *pVideoInfo, __in LPSTR szDevice);
    HRESULT RemovePalette();
    static HRESULT MakeIdentityPalette(__inout_ecount_full(iColours) PALETTEENTRY *pEntry,INT iColours, __in LPSTR szDevice);
    HRESULT CopyPalette(const CMediaType *pSrc,__out CMediaType *pDest);
    BOOL ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,const VIDEOINFOHEADER *pOldInfo);
    HRESULT PreparePalette(const CMediaType *pmtNew,const CMediaType *pmtOld,__in LPSTR szDevice);

    BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample, __in LPRECT lprcSrc, __in LPRECT lprcDst)
    {
        return m_pDrawImage->DrawVideoImageHere(hdc, pMediaSample, lprcSrc,lprcDst);
    }
};


// Another helper class really for video based renderers. Most such renderers
// need to know what the display format is to some degree or another. This
// class initialises itself with the display format. The format can be asked
// for through GetDisplayFormat and various other accessor functions. If a
// filter detects a display format change (perhaps it gets a WM_DEVMODECHANGE
// message then it can call RefreshDisplayType to reset that format). Also
// many video renderers will want to check formats as they are proposed by
// source filters. This class provides methods to check formats and only
// accept those video formats that can be efficiently drawn using GDI calls

class CImageDisplay : public CCritSec
{
protected:

    // This holds the display format; biSize should not be too big, so we can
    // safely use the VIDEOINFO structure
    VIDEOINFO m_Display;

    static DWORD CountSetBits(const DWORD Field);
    static DWORD CountPrefixBits(const DWORD Field);
    static BOOL CheckBitFields(const VIDEOINFO *pInput);

public:

    // Constructor and destructor

    CImageDisplay();

    // Used to manage BITMAPINFOHEADERs and the display format

    const VIDEOINFO *GetDisplayFormat();
    HRESULT RefreshDisplayType(__in_opt LPSTR szDeviceName);
    static BOOL CheckHeaderValidity(const VIDEOINFO *pInput);
    static BOOL CheckPaletteHeader(const VIDEOINFO *pInput);
    BOOL IsPalettised();
    WORD GetDisplayDepth();

    // Provide simple video format type checking

    HRESULT CheckMediaType(const CMediaType *pmtIn);
    HRESULT CheckVideoType(const VIDEOINFO *pInput);
    HRESULT UpdateFormat(__inout VIDEOINFO *pVideoInfo);
    const DWORD *GetBitMasks(const VIDEOINFO *pVideoInfo);

    BOOL GetColourMask(__out DWORD *pMaskRed,
                       __out DWORD *pMaskGreen,
                       __out DWORD *pMaskBlue);
};

//  Convert a FORMAT_VideoInfo to FORMAT_VideoInfo2
STDAPI ConvertVideoInfoToVideoInfo2(__inout AM_MEDIA_TYPE *pmt);

//  Check a media type containing VIDEOINFOHEADER
STDAPI CheckVideoInfoType(const AM_MEDIA_TYPE *pmt);

//  Check a media type containing VIDEOINFOHEADER
STDAPI CheckVideoInfo2Type(const AM_MEDIA_TYPE *pmt);

#endif // __WINUTIL__

OpenPOWER on IntegriCloud