AJA NTV2 SDK  18.0.0.2717
NTV2 SDK 18.0.0.2717
winutil.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // File: WinUtil.cpp
3 //
4 // Desc: DirectShow base classes - implements generic window handler class.
5 //
6 // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
7 //------------------------------------------------------------------------------
8 
9 
10 #include <streams.h>
11 #include <limits.h>
12 #include <dvdmedia.h>
13 #include <strsafe.h>
14 #include <checkbmi.h>
15 
16 static UINT MsgDestroy;
17 
18 // Constructor
19 
20 CBaseWindow::CBaseWindow(BOOL bDoGetDC, bool bDoPostToDestroy) :
21  m_hInstance(g_hInst),
22  m_hwnd(NULL),
23  m_hdc(NULL),
24  m_bActivated(FALSE),
25  m_pClassName(NULL),
26  m_ClassStyles(0),
27  m_WindowStyles(0),
28  m_WindowStylesEx(0),
29  m_ShowStageMessage(0),
30  m_ShowStageTop(0),
31  m_MemoryDC(NULL),
32  m_hPalette(NULL),
33  m_bBackground(FALSE),
34 #ifdef DEBUG
35  m_bRealizing(FALSE),
36 #endif
37  m_bNoRealize(FALSE),
38  m_bDoPostToDestroy(bDoPostToDestroy)
39 {
40  m_bDoGetDC = bDoGetDC;
41 }
42 
43 
44 // Prepare a window by spinning off a worker thread to do the creation and
45 // also poll the message input queue. We leave this to be called by derived
46 // classes because they might want to override methods like MessageLoop and
47 // InitialiseWindow, if we do this during construction they'll ALWAYS call
48 // this base class methods. We make the worker thread create the window so
49 // it owns it rather than the filter graph thread which is constructing us
50 
52 {
53  if (m_hwnd) return NOERROR;
54  ASSERT(m_hwnd == NULL);
55  ASSERT(m_hdc == NULL);
56 
57  // Get the derived object's window and class styles
58 
62  if (m_pClassName == NULL) {
63  return E_FAIL;
64  }
65 
66  // Register our special private messages
67  m_ShowStageMessage = RegisterWindowMessage(SHOWSTAGE);
68 
69  // RegisterWindowMessage() returns 0 if an error occurs.
70  if (0 == m_ShowStageMessage) {
71  return AmGetLastErrorToHResult();
72  }
73 
74  m_ShowStageTop = RegisterWindowMessage(SHOWSTAGETOP);
75  if (0 == m_ShowStageTop) {
76  return AmGetLastErrorToHResult();
77  }
78 
79  m_RealizePalette = RegisterWindowMessage(REALIZEPALETTE);
80  if (0 == m_RealizePalette) {
81  return AmGetLastErrorToHResult();
82  }
83 
84  MsgDestroy = RegisterWindowMessage(TEXT("AM_DESTROY"));
85  if (0 == MsgDestroy) {
86  return AmGetLastErrorToHResult();
87  }
88 
89  return DoCreateWindow();
90 }
91 
92 
93 // Destructor just a placeholder so that we know it becomes virtual
94 // Derived classes MUST call DoneWithWindow in their destructors so
95 // that no messages arrive after the derived class constructor ends
96 
97 #ifdef DEBUG
98 CBaseWindow::~CBaseWindow()
99 {
100  ASSERT(m_hwnd == NULL);
101  ASSERT(m_hdc == NULL);
102 }
103 #endif
104 
105 
106 // We use the sync worker event to have the window destroyed. All we do is
107 // signal the event and wait on the window thread handle. Trying to send it
108 // messages causes too many problems, furthermore to be on the safe side we
109 // just wait on the thread handle while it returns WAIT_TIMEOUT or there is
110 // a sent message to process on this thread. If the constructor failed to
111 // create the thread in the first place then the loop will get terminated
112 
114 {
115  if (!IsWindow(m_hwnd) || (GetWindowThreadProcessId(m_hwnd, NULL) != GetCurrentThreadId())) {
116 
117  if (IsWindow(m_hwnd)) {
118 
119  // This code should only be executed if the window exists and if the window's
120  // messages are processed on a different thread.
121  ASSERT(GetWindowThreadProcessId(m_hwnd, NULL) != GetCurrentThreadId());
122 
123  if (m_bDoPostToDestroy) {
124 
125  HRESULT hr = S_OK;
126  CAMEvent m_evDone(FALSE, &hr);
127  if (FAILED(hr)) {
128  return hr;
129  }
130 
131  // We must post a message to destroy the window
132  // That way we can't be in the middle of processing a
133  // message posted to our window when we do go away
134  // Sending a message gives less synchronization.
135  PostMessage(m_hwnd, MsgDestroy, (WPARAM)(HANDLE)m_evDone, 0);
136  WaitDispatchingMessages(m_evDone, INFINITE);
137  } else {
138  SendMessage(m_hwnd, MsgDestroy, 0, 0);
139  }
140  }
141 
142  //
143  // This is not a leak, the window manager automatically free's
144  // hdc's that were got via GetDC, which is the case here.
145  // We set it to NULL so that we don't get any asserts later.
146  //
147  m_hdc = NULL;
148 
149  //
150  // We need to free this DC though because USER32 does not know
151  // anything about it.
152  //
153  if (m_MemoryDC)
154  {
155  EXECUTE_ASSERT(DeleteDC(m_MemoryDC));
156  m_MemoryDC = NULL;
157  }
158 
159  // Reset the window variables
160  m_hwnd = NULL;
161 
162  return NOERROR;
163  }
164  const HWND hwnd = m_hwnd;
165  if (hwnd == NULL) {
166  return NOERROR;
167  }
168 
170  NOTE("Inactivated");
171 
172  // Reset the window styles before destruction
173 
174  SetWindowLong(hwnd,GWL_STYLE,m_WindowStyles);
175  ASSERT(GetParent(hwnd) == NULL);
176  NOTE1("Reset window styles %d",m_WindowStyles);
177 
178  // UnintialiseWindow sets m_hwnd to NULL so save a copy
180  DbgLog((LOG_TRACE, 2, TEXT("Destroying 0x%8.8X"), hwnd));
181  if (!DestroyWindow(hwnd)) {
182  DbgLog((LOG_TRACE, 0, TEXT("DestroyWindow %8.8X failed code %d"),
183  hwnd, GetLastError()));
184  DbgBreak("");
185  }
186 
187  // Reset our state so we can be prepared again
188 
189  m_pClassName = NULL;
190  m_ClassStyles = 0;
191  m_WindowStyles = 0;
192  m_WindowStylesEx = 0;
193  m_ShowStageMessage = 0;
194  m_ShowStageTop = 0;
195 
196  return NOERROR;
197 }
198 
199 
200 // Called at the end to put the window in an inactive state. The pending list
201 // will always have been cleared by this time so event if the worker thread
202 // gets has been signaled and gets in to render something it will find both
203 // the state has been changed and that there are no available sample images
204 // Since we wait on the window thread to complete we don't lock the object
205 
207 {
208  // Has the window been activated
209  if (m_bActivated == FALSE) {
210  return S_FALSE;
211  }
212 
213  m_bActivated = FALSE;
214  ShowWindow(m_hwnd,SW_HIDE);
215  return NOERROR;
216 }
217 
218 
220 {
221  m_bActivated = FALSE;
222  return NOERROR;
223 }
224 
225 // This displays a normal window. We ask the base window class for default
226 // sizes which unless overriden will return DEFWIDTH and DEFHEIGHT. We go
227 // through a couple of extra hoops to get the client area the right size
228 // as the object specifies which accounts for the AdjustWindowRectEx calls
229 // We also DWORD align the left and top coordinates of the window here to
230 // maximise the chance of being able to use DCI/DirectDraw primary surface
231 
233 {
234  // Has the window been sized and positioned already
235 
236  if (m_bActivated == TRUE || GetParent(m_hwnd) != NULL) {
237 
238  SetWindowPos(m_hwnd, // Our window handle
239  HWND_TOP, // Put it at the top
240  0, 0, 0, 0, // Leave in current position
241  SWP_NOMOVE | // Don't change it's place
242  SWP_NOSIZE); // Change Z-order only
243 
244  m_bActivated = TRUE;
245  return S_FALSE;
246  }
247 
248  // Calculate the desired client rectangle
249 
250  RECT WindowRect, ClientRect = GetDefaultRect();
251  GetWindowRect(m_hwnd,&WindowRect);
252  AdjustWindowRectEx(&ClientRect,GetWindowLong(m_hwnd,GWL_STYLE),
253  FALSE,GetWindowLong(m_hwnd,GWL_EXSTYLE));
254 
255  // Align left and top edges on DWORD boundaries
256 
257  UINT WindowFlags = (SWP_NOACTIVATE | SWP_FRAMECHANGED);
258  WindowRect.left -= (WindowRect.left & 3);
259  WindowRect.top -= (WindowRect.top & 3);
260 
261  SetWindowPos(m_hwnd, // Window handle
262  HWND_TOP, // Put it at the top
263  WindowRect.left, // Align left edge
264  WindowRect.top, // And also top place
265  WIDTH(&ClientRect), // Horizontal size
266  HEIGHT(&ClientRect), // Vertical size
267  WindowFlags); // Don't show window
268 
269  m_bActivated = TRUE;
270  return NOERROR;
271 }
272 
273 
274 // This can be used to DWORD align the window for maximum performance
275 
277 {
278  RECT ClientRect,WindowRect;
279  GetWindowRect(m_hwnd,&WindowRect);
280  ASSERT(m_bActivated == TRUE);
281 
282  // Don't do this if we're owned
283 
284  if (GetParent(m_hwnd)) {
285  return NOERROR;
286  }
287 
288  // Align left and top edges on DWORD boundaries
289 
290  GetClientRect(m_hwnd, &ClientRect);
291  MapWindowPoints(m_hwnd, HWND_DESKTOP, (LPPOINT) &ClientRect, 2);
292  WindowRect.left -= (ClientRect.left & 3);
293  WindowRect.top -= (ClientRect.top & 3);
294  UINT WindowFlags = (SWP_NOACTIVATE | SWP_NOSIZE);
295 
296  SetWindowPos(m_hwnd, // Window handle
297  HWND_TOP, // Put it at the top
298  WindowRect.left, // Align left edge
299  WindowRect.top, // And also top place
300  (int) 0,(int) 0, // Ignore these sizes
301  WindowFlags); // Don't show window
302 
303  return NOERROR;
304 }
305 
306 
307 // Install a palette into the base window - we may be called by a different
308 // thread to the one that owns the window. We have to be careful how we do
309 // the palette realisation as we could be a different thread to the window
310 // which would cause an inter thread send message. Therefore we realise the
311 // palette by sending it a special message but without the window locked
312 
313 HRESULT CBaseWindow::SetPalette(HPALETTE hPalette)
314 {
315  // We must own the window lock during the change
316  {
317  CAutoLock cWindowLock(&m_WindowLock);
318  CAutoLock cPaletteLock(&m_PaletteLock);
319  ASSERT(hPalette);
320  m_hPalette = hPalette;
321  }
322  return SetPalette();
323 }
324 
325 
327 {
328  if (!m_bNoRealize) {
329  SendMessage(m_hwnd, m_RealizePalette, 0, 0);
330  return S_OK;
331  } else {
332  // Just select the palette
333  ASSERT(m_hdc);
335 
336  CAutoLock cPaletteLock(&m_PaletteLock);
337  SelectPalette(m_hdc,m_hPalette,m_bBackground);
338  SelectPalette(m_MemoryDC,m_hPalette,m_bBackground);
339 
340  return S_OK;
341  }
342 }
343 
344 
346 {
347  CAutoLock cWindowLock(&m_WindowLock);
348  CAutoLock cPaletteLock(&m_PaletteLock);
349 
350  // Get a standard VGA colour palette
351 
352  HPALETTE hPalette = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
353  ASSERT(hPalette);
354 
355  SelectPalette(GetWindowHDC(), hPalette, TRUE);
356  SelectPalette(GetMemoryHDC(), hPalette, TRUE);
357 
358  m_hPalette = NULL;
359 }
360 
361 
363 {
365 }
366 
367 
369 {
371 }
372 
373 
374 // Realise our palettes in the window and device contexts
375 
376 HRESULT CBaseWindow::DoRealisePalette(BOOL bForceBackground)
377 {
378  {
379  CAutoLock cPaletteLock(&m_PaletteLock);
380 
381  if (m_hPalette == NULL) {
382  return NOERROR;
383  }
384 
385  // Realize the palette on the window thread
386  ASSERT(m_hdc);
388 
389  SelectPalette(m_hdc,m_hPalette,m_bBackground || bForceBackground);
390  SelectPalette(m_MemoryDC,m_hPalette,m_bBackground);
391  }
392 
393  // If we grab a critical section here we can deadlock
394  // with the window thread because one of the side effects
395  // of RealizePalette is to send a WM_PALETTECHANGED message
396  // to every window in the system. In our handling
397  // of WM_PALETTECHANGED we used to grab this CS too.
398  // The really bad case is when our renderer calls DoRealisePalette()
399  // while we're in the middle of processing a palette change
400  // for another window.
401  // So don't hold the critical section while actually realising
402  // the palette. In any case USER is meant to manage palette
403  // handling - we shouldn't have to serialize everything as well
406 
407  EXECUTE_ASSERT(RealizePalette(m_hdc) != GDI_ERROR);
408  EXECUTE_ASSERT(RealizePalette(m_MemoryDC) != GDI_ERROR);
409 
410  return (GdiFlush() == FALSE ? S_FALSE : S_OK);
411 }
412 
413 
414 // This is the global window procedure
415 
416 LRESULT CALLBACK WndProc(HWND hwnd, // Window handle
417  UINT uMsg, // Message ID
418  WPARAM wParam, // First parameter
419  LPARAM lParam) // Other parameter
420 {
421 
422  // Get the window long that holds our window object pointer
423  // If it is NULL then we are initialising the window in which
424  // case the object pointer has been passed in the window creation
425  // structure. IF we get any messages before WM_NCCREATE we will
426  // pass them to DefWindowProc.
427 
428  CBaseWindow *pBaseWindow = _GetWindowLongPtr<CBaseWindow*>(hwnd,0);
429 
430  if (pBaseWindow == NULL) {
431 
432  // Get the structure pointer from the create struct.
433  // We can only do this for WM_NCCREATE which should be one of
434  // the first messages we receive. Anything before this will
435  // have to be passed to DefWindowProc (i.e. WM_GETMINMAXINFO)
436 
437  // If the message is WM_NCCREATE we set our pBaseWindow pointer
438  // and will then place it in the window structure
439 
440  // turn off WS_EX_LAYOUTRTL style for quartz windows
441  if (uMsg == WM_NCCREATE) {
442  SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~0x400000);
443  }
444 
445  if ((uMsg != WM_NCCREATE)
446  || (NULL == (pBaseWindow = *(CBaseWindow**) ((LPCREATESTRUCT)lParam)->lpCreateParams)))
447  {
448  return(DefWindowProc(hwnd, uMsg, wParam, lParam));
449  }
450 
451  // Set the window LONG to be the object who created us
452 #ifdef DEBUG
453  SetLastError(0); // because of the way SetWindowLong works
454 #endif
455 
456  LONG_PTR rc = _SetWindowLongPtr(hwnd, (DWORD) 0, pBaseWindow);
457 
458 
459 #ifdef DEBUG
460  if (0 == rc) {
461  // SetWindowLong MIGHT have failed. (Read the docs which admit
462  // that it is awkward to work out if you have had an error.)
463  LONG lasterror = GetLastError();
464  ASSERT(0 == lasterror);
465  // If this is not the case we have not set the pBaseWindow pointer
466  // into the window structure and we will blow up.
467  }
468 #endif
469 
470  }
471  // See if this is the packet of death
472  if (uMsg == MsgDestroy && uMsg != 0) {
473  pBaseWindow->DoneWithWindow();
474  if (pBaseWindow->m_bDoPostToDestroy) {
475  EXECUTE_ASSERT(SetEvent((HANDLE)wParam));
476  }
477  return 0;
478  }
479  return pBaseWindow->OnReceiveMessage(hwnd,uMsg,wParam,lParam);
480 }
481 
482 
483 // When the window size changes we adjust our member variables that
484 // contain the dimensions of the client rectangle for our window so
485 // that we come to render an image we will know whether to stretch
486 
487 BOOL CBaseWindow::OnSize(LONG Width, LONG Height)
488 {
489  m_Width = Width;
490  m_Height = Height;
491  return TRUE;
492 }
493 
494 
495 // This function handles the WM_CLOSE message
496 
498 {
499  ShowWindow(m_hwnd,SW_HIDE);
500  return TRUE;
501 }
502 
503 
504 // This is called by the worker window thread when it receives a terminate
505 // message from the window object destructor to delete all the resources we
506 // allocated during initialisation. By the time the worker thread exits all
507 // processing will have been completed as the source filter disconnection
508 // flushes the image pending sample, therefore the GdiFlush should succeed
509 
511 {
512  // Have we already cleaned up
513 
514  if (m_hwnd == NULL) {
515  ASSERT(m_hdc == NULL);
516  ASSERT(m_MemoryDC == NULL);
517  return NOERROR;
518  }
519 
520  // Release the window resources
521 
522  EXECUTE_ASSERT(GdiFlush());
523 
524  if (m_hdc)
525  {
526  EXECUTE_ASSERT(ReleaseDC(m_hwnd,m_hdc));
527  m_hdc = NULL;
528  }
529 
530  if (m_MemoryDC)
531  {
532  EXECUTE_ASSERT(DeleteDC(m_MemoryDC));
533  m_MemoryDC = NULL;
534  }
535 
536  // Reset the window variables
537  m_hwnd = NULL;
538 
539  return NOERROR;
540 }
541 
542 
543 // This is called by the worker window thread after it has created the main
544 // window and it wants to initialise the rest of the owner objects window
545 // variables such as the device contexts. We execute this function with the
546 // critical section still locked. Nothing in this function must generate any
547 // SendMessage calls to the window because this is executing on the window
548 // thread so the message will never be processed and we will deadlock
549 
551 {
552  // Initialise the window variables
553 
554  ASSERT(IsWindow(hwnd));
555  m_hwnd = hwnd;
556 
557  if (m_bDoGetDC)
558  {
559  EXECUTE_ASSERT(m_hdc = GetDC(hwnd));
560  EXECUTE_ASSERT(m_MemoryDC = CreateCompatibleDC(m_hdc));
561 
562  EXECUTE_ASSERT(SetStretchBltMode(m_hdc,COLORONCOLOR));
563  EXECUTE_ASSERT(SetStretchBltMode(m_MemoryDC,COLORONCOLOR));
564  }
565 
566  return NOERROR;
567 }
568 
570 {
571  WNDCLASS wndclass; // Used to register classes
572  BOOL bRegistered; // Is this class registered
573  HWND hwnd; // Handle to our window
574 
575  bRegistered = GetClassInfo(m_hInstance, // Module instance
576  m_pClassName, // Window class
577  &wndclass); // Info structure
578 
579  // if the window is to be used for drawing puposes and we are getting a DC
580  // for the entire lifetime of the window then changes the class style to do
581  // say so. If we don't set this flag then the DC comes from the cache and is
582  // really bad.
583  if (m_bDoGetDC)
584  {
585  m_ClassStyles |= CS_OWNDC;
586  }
587 
588  if (bRegistered == FALSE) {
589 
590  // Register the renderer window class
591 
592  wndclass.lpszClassName = m_pClassName;
593  wndclass.style = m_ClassStyles;
594  wndclass.lpfnWndProc = WndProc;
595  wndclass.cbClsExtra = 0;
596  wndclass.cbWndExtra = sizeof(CBaseWindow *);
597  wndclass.hInstance = m_hInstance;
598  wndclass.hIcon = NULL;
599  wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
600  wndclass.hbrBackground = (HBRUSH) NULL;
601  wndclass.lpszMenuName = NULL;
602 
603  RegisterClass(&wndclass);
604  }
605 
606  // Create the frame window. Pass the pBaseWindow information in the
607  // CreateStruct which allows our message handling loop to get hold of
608  // the pBaseWindow pointer.
609 
610  CBaseWindow *pBaseWindow = this; // The owner window object
611  hwnd = CreateWindowEx(m_WindowStylesEx, // Extended styles
612  m_pClassName, // Registered name
613  TEXT("ActiveMovie Window"), // Window title
614  m_WindowStyles, // Window styles
615  CW_USEDEFAULT, // Start x position
616  CW_USEDEFAULT, // Start y position
617  DEFWIDTH, // Window width
618  DEFHEIGHT, // Window height
619  NULL, // Parent handle
620  NULL, // Menu handle
621  m_hInstance, // Instance handle
622  &pBaseWindow); // Creation data
623 
624  // If we failed signal an error to the object constructor (based on the
625  // last Win32 error on this thread) then signal the constructor thread
626  // to continue, release the mutex to let others have a go and exit
627 
628  if (hwnd == NULL) {
629  DWORD Error = GetLastError();
630  return AmHresultFromWin32(Error);
631  }
632 
633  // Check the window LONG is the object who created us
634  ASSERT(GetWindowLongPtr(hwnd, 0) == (LONG_PTR)this);
635 
636  // Initialise the window and then signal the constructor so that it can
637  // continue and then finally unlock the object's critical section. The
638  // window class is left registered even after we terminate the thread
639  // as we don't know when the last window has been closed. So we allow
640  // the operating system to free the class resources as appropriate
641 
642  InitialiseWindow(hwnd);
643 
644  DbgLog((LOG_TRACE, 2, TEXT("Created window class (%s) HWND(%8.8X)"),
645  m_pClassName, hwnd));
646 
647  return S_OK;
648 }
649 
650 
651 // The base class provides some default handling and calls DefWindowProc
652 
653 LRESULT CBaseWindow::OnReceiveMessage(HWND hwnd, // Window handle
654  UINT uMsg, // Message ID
655  WPARAM wParam, // First parameter
656  LPARAM lParam) // Other parameter
657 {
658  ASSERT(IsWindow(hwnd));
659 
660  if (PossiblyEatMessage(uMsg, wParam, lParam))
661  return 0;
662 
663  // This is sent by the IVideoWindow SetWindowForeground method. If the
664  // window is invisible we will show it and make it topmost without the
665  // foreground focus. If the window is visible it will also be made the
666  // topmost window without the foreground focus. If wParam is TRUE then
667  // for both cases the window will be forced into the foreground focus
668 
669  if (uMsg == m_ShowStageMessage) {
670 
671  BOOL bVisible = IsWindowVisible(hwnd);
672  SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
673  SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
674  (bVisible ? SWP_NOACTIVATE : 0));
675 
676  // Should we bring the window to the foreground
677  if (wParam == TRUE) {
678  SetForegroundWindow(hwnd);
679  }
680  return (LRESULT) 1;
681  }
682 
683  // When we go fullscreen we have to add the WS_EX_TOPMOST style to the
684  // video window so that it comes out above any task bar (this is more
685  // relevant to WindowsNT than Windows95). However the SetWindowPos call
686  // must be on the same thread as that which created the window. The
687  // wParam parameter can be TRUE or FALSE to set and reset the topmost
688 
689  if (uMsg == m_ShowStageTop) {
690  HWND HwndTop = (wParam == TRUE ? HWND_TOPMOST : HWND_NOTOPMOST);
691  BOOL bVisible = IsWindowVisible(hwnd);
692  SetWindowPos(hwnd, HwndTop, 0, 0, 0, 0,
693  SWP_NOMOVE | SWP_NOSIZE |
694  (wParam == TRUE ? SWP_SHOWWINDOW : 0) |
695  (bVisible ? SWP_NOACTIVATE : 0));
696  return (LRESULT) 1;
697  }
698 
699  // New palette stuff
700  if (uMsg == m_RealizePalette) {
701  ASSERT(m_hwnd == hwnd);
702  return OnPaletteChange(m_hwnd,WM_QUERYNEWPALETTE);
703  }
704 
705  switch (uMsg) {
706 
707  // Repaint the window if the system colours change
708 
709  case WM_SYSCOLORCHANGE:
710 
711  InvalidateRect(hwnd,NULL,FALSE);
712  return (LRESULT) 1;
713 
714  // Somebody has changed the palette
715  case WM_PALETTECHANGED:
716 
717  OnPaletteChange((HWND)wParam,uMsg);
718  return (LRESULT) 0;
719 
720  // We are about to receive the keyboard focus so we ask GDI to realise
721  // our logical palette again and hopefully it will be fully installed
722  // without any mapping having to be done during any picture rendering
723 
724  case WM_QUERYNEWPALETTE:
725  ASSERT(m_hwnd == hwnd);
726  return OnPaletteChange(m_hwnd,uMsg);
727 
728  // do NOT fwd WM_MOVE. the parameters are the location of the parent
729  // window, NOT what the renderer should be looking at. But we need
730  // to make sure the overlay is moved with the parent window, so we
731  // do this.
732  case WM_MOVE:
733  if (IsWindowVisible(m_hwnd)) {
734  PostMessage(m_hwnd,WM_PAINT,0,0);
735  }
736  break;
737 
738  // Store the width and height as useful base class members
739 
740  case WM_SIZE:
741 
742  OnSize(LOWORD(lParam), HIWORD(lParam));
743  return (LRESULT) 0;
744 
745  // Intercept the WM_CLOSE messages to hide the window
746 
747  case WM_CLOSE:
748 
749  OnClose();
750  return (LRESULT) 0;
751  }
752  return DefWindowProc(hwnd,uMsg,wParam,lParam);
753 }
754 
755 
756 // This handles the Windows palette change messages - if we do realise our
757 // palette then we return TRUE otherwise we return FALSE. If our window is
758 // foreground application then we should get first choice of colours in the
759 // system palette entries. We get best performance when our logical palette
760 // includes the standard VGA colours (at the beginning and end) otherwise
761 // GDI may have to map from our palette to the device palette while drawing
762 
763 LRESULT CBaseWindow::OnPaletteChange(HWND hwnd,UINT Message)
764 {
765  // First check we are not changing the palette during closedown
766 
767  if (m_hwnd == NULL || hwnd == NULL) {
768  return (LRESULT) 0;
769  }
771 
772  // Should we realise our palette again
773 
774  if ((Message == WM_QUERYNEWPALETTE || hwnd != m_hwnd)) {
775  // It seems that even if we're invisible that we can get asked
776  // to realize our palette and this can cause really ugly side-effects
777  // Seems like there's another bug but this masks it a least for the
778  // shutting down case.
779  if (!IsWindowVisible(m_hwnd)) {
780  DbgLog((LOG_TRACE, 1, TEXT("Realizing when invisible!")));
781  return (LRESULT) 0;
782  }
783 
784  // Avoid recursion with multiple graphs in the same app
785 #ifdef DEBUG
786  m_bRealizing = TRUE;
787 #endif
788  DoRealisePalette(Message != WM_QUERYNEWPALETTE);
789 #ifdef DEBUG
790  m_bRealizing = FALSE;
791 #endif
792 
793  // Should we redraw the window with the new palette
794  if (Message == WM_PALETTECHANGED) {
795  InvalidateRect(m_hwnd,NULL,FALSE);
796  }
797  }
798 
799  return (LRESULT) 1;
800 }
801 
802 
803 // Determine if the window exists.
804 
806 {
807  return !!IsWindow(m_hwnd);
808 }
809 
810 
811 // Return the default window rectangle
812 
814 {
815  RECT DefaultRect = {0,0,DEFWIDTH,DEFHEIGHT};
816  ASSERT(m_hwnd);
817  // ASSERT(m_hdc);
818  return DefaultRect;
819 }
820 
821 
822 // Return the current window width
823 
825 {
826  ASSERT(m_hwnd);
827  // ASSERT(m_hdc);
828  return m_Width;
829 }
830 
831 
832 // Return the current window height
833 
835 {
836  ASSERT(m_hwnd);
837  // ASSERT(m_hdc);
838  return m_Height;
839 }
840 
841 
842 // Return the window handle
843 
845 {
846  ASSERT(m_hwnd);
847  // ASSERT(m_hdc);
848  return m_hwnd;
849 }
850 
851 
852 // Return the window drawing device context
853 
855 {
856  ASSERT(m_hwnd);
857  ASSERT(m_hdc);
858  return m_hdc;
859 }
860 
861 
862 // Return the offscreen window drawing device context
863 
865 {
866  ASSERT(m_hwnd);
868  return m_MemoryDC;
869 }
870 
871 
872 #ifdef DEBUG
873 HPALETTE CBaseWindow::GetPalette()
874 {
875  // The palette lock should always be held when accessing
876  // m_hPalette.
878  return m_hPalette;
879 }
880 #endif // DEBUG
881 
882 
883 // This is available to clients who want to change the window visiblity. It's
884 // little more than an indirection to the Win32 ShowWindow although these is
885 // some benefit in going through here as this function may change sometime
886 
887 HRESULT CBaseWindow::DoShowWindow(LONG ShowCmd)
888 {
889  ShowWindow(m_hwnd,ShowCmd);
890  return NOERROR;
891 }
892 
893 
894 // Generate a WM_PAINT message for the video window
895 
896 void CBaseWindow::PaintWindow(BOOL bErase)
897 {
898  InvalidateRect(m_hwnd,NULL,bErase);
899 }
900 
901 
902 // Allow an application to have us set the video window in the foreground. We
903 // have this because it is difficult for one thread to do do this to a window
904 // owned by another thread. Rather than expose the message we use to execute
905 // the inter thread send message we provide the interface function. All we do
906 // is to SendMessage to the video window renderer thread with a WM_SHOWSTAGE
907 
909 {
910  SendMessage(m_hwnd,m_ShowStageMessage,(WPARAM) bFocus,(LPARAM) 0);
911 }
912 
913 
914 // Constructor initialises the owning object pointer. Since we are a worker
915 // class for the main window object we have relatively few state variables to
916 // look after. We are given device context handles to use later on as well as
917 // the source and destination rectangles (but reset them here just in case)
918 
919 CDrawImage::CDrawImage(__inout CBaseWindow *pBaseWindow) :
920  m_pBaseWindow(pBaseWindow),
921  m_hdc(NULL),
922  m_MemoryDC(NULL),
923  m_bStretch(FALSE),
924  m_pMediaType(NULL),
925  m_bUsingImageAllocator(FALSE)
926 {
927  ASSERT(pBaseWindow);
929  SetRectEmpty(&m_TargetRect);
930  SetRectEmpty(&m_SourceRect);
931 
932  m_perfidRenderTime = MSR_REGISTER(TEXT("Single Blt time"));
933 }
934 
935 
936 // Overlay the image time stamps on the picture. Access to this method is
937 // serialised by the caller. We display the sample start and end times on
938 // top of the video using TextOut on the device context we are handed. If
939 // there isn't enough room in the window for the times we don't show them
940 
941 void CDrawImage::DisplaySampleTimes(IMediaSample *pSample)
942 {
943 #ifdef DEBUG
944  //
945  // Only allow the "annoying" time messages if the users has turned the
946  // logging "way up"
947  //
948  BOOL bAccept = DbgCheckModuleLevel(LOG_TRACE, 5);
949  if (bAccept == FALSE) {
950  return;
951  }
952 #endif
953 
954  TCHAR szTimes[TIMELENGTH]; // Time stamp strings
955  ASSERT(pSample); // Quick sanity check
956  RECT ClientRect; // Client window size
957  SIZE Size; // Size of text output
958 
959  // Get the time stamps and window size
960 
961  pSample->GetTime((REFERENCE_TIME*)&m_StartSample, (REFERENCE_TIME*)&m_EndSample);
962  HWND hwnd = m_pBaseWindow->GetWindowHWND();
963  EXECUTE_ASSERT(GetClientRect(hwnd,&ClientRect));
964 
965  // Format the sample time stamps
966 
967  (void)StringCchPrintf(szTimes,NUMELMS(szTimes),TEXT("%08d : %08d"),
970 
971  ASSERT(lstrlen(szTimes) < TIMELENGTH);
972 
973  // Put the times in the middle at the bottom of the window
974 
975  GetTextExtentPoint32(m_hdc,szTimes,lstrlen(szTimes),&Size);
976  INT XPos = ((ClientRect.right - ClientRect.left) - Size.cx) / 2;
977  INT YPos = ((ClientRect.bottom - ClientRect.top) - Size.cy) * 4 / 5;
978 
979  // Check the window is big enough to have sample times displayed
980 
981  if ((XPos > 0) && (YPos > 0)) {
982  TextOut(m_hdc,XPos,YPos,szTimes,lstrlen(szTimes));
983  }
984 }
985 
986 
987 // This is called when the drawing code sees that the image has a down level
988 // palette cookie. We simply call the SetDIBColorTable Windows API with the
989 // palette that is found after the BITMAPINFOHEADER - we return no errors
990 
991 void CDrawImage::UpdateColourTable(HDC hdc,__in BITMAPINFOHEADER *pbmi)
992 {
993  ASSERT(pbmi->biClrUsed);
994  RGBQUAD *pColourTable = (RGBQUAD *)(pbmi+1);
995 
996  // Set the new palette in the device context
997 
998  UINT uiReturn = SetDIBColorTable(hdc,(UINT) 0,
999  pbmi->biClrUsed,
1000  pColourTable);
1001 
1002  // Should always succeed but check in debug builds
1003  ASSERT(uiReturn == pbmi->biClrUsed);
1004 }
1005 
1006 
1007 // No source rectangle scaling is done by the base class
1008 
1009 RECT CDrawImage::ScaleSourceRect(const RECT *pSource)
1010 {
1011  ASSERT(pSource);
1012  return *pSource;
1013 }
1014 
1015 
1016 // This is called when the funky output pin uses our allocator. The samples we
1017 // allocate are special because the memory is shared between us and GDI thus
1018 // removing one copy when we ask for the image to be rendered. The source type
1019 // information is in the main renderer m_mtIn field which is initialised when
1020 // the media type is agreed in SetMediaType, the media type may be changed on
1021 // the fly if, for example, the source filter needs to change the palette
1022 
1023 void CDrawImage::FastRender(IMediaSample *pMediaSample)
1024 {
1025  BITMAPINFOHEADER *pbmi; // Image format data
1026  DIBDATA *pDibData; // Stores DIB information
1027  BYTE *pImage; // Pointer to image data
1028  HBITMAP hOldBitmap; // Store the old bitmap
1029  CImageSample *pSample; // Pointer to C++ object
1030 
1032 
1033  // From the untyped source format block get the VIDEOINFO and subsequently
1034  // the BITMAPINFOHEADER structure. We can cast the IMediaSample interface
1035  // to a CImageSample object so we can retrieve it's DIBSECTION details
1036 
1037  pbmi = HEADER(m_pMediaType->Format());
1038  pSample = (CImageSample *) pMediaSample;
1039  pDibData = pSample->GetDIBData();
1040  hOldBitmap = (HBITMAP) SelectObject(m_MemoryDC,pDibData->hBitmap);
1041 
1042  // Get a pointer to the real image data
1043 
1044  HRESULT hr = pMediaSample->GetPointer(&pImage);
1045  if (FAILED(hr)) {
1046  return;
1047  }
1048 
1049  // Do we need to update the colour table, we increment our palette cookie
1050  // each time we get a dynamic format change. The sample palette cookie is
1051  // stored in the DIBDATA structure so we try to keep the fields in sync
1052  // By the time we get to draw the images the format change will be done
1053  // so all we do is ask the renderer for what it's palette version is
1054 
1055  if (pDibData->PaletteVersion < GetPaletteVersion()) {
1056  ASSERT(pbmi->biBitCount <= iPALETTE);
1058  pDibData->PaletteVersion = GetPaletteVersion();
1059  }
1060 
1061  // This allows derived classes to change the source rectangle that we do
1062  // the drawing with. For example a renderer may ask a codec to stretch
1063  // the video from 320x240 to 640x480, in which case the source we see in
1064  // here will still be 320x240, although the source we want to draw with
1065  // should be scaled up to 640x480. The base class implementation of this
1066  // method does nothing but return the same rectangle as we are passed in
1067 
1068  RECT SourceRect = ScaleSourceRect(&m_SourceRect);
1069 
1070  // Is the window the same size as the video
1071 
1072  if (m_bStretch == FALSE) {
1073 
1074  // Put the image straight into the window
1075 
1076  BitBlt(
1077  (HDC) m_hdc, // Target device HDC
1078  m_TargetRect.left, // X sink position
1079  m_TargetRect.top, // Y sink position
1080  m_TargetRect.right - m_TargetRect.left, // Destination width
1081  m_TargetRect.bottom - m_TargetRect.top, // Destination height
1082  m_MemoryDC, // Source device context
1083  SourceRect.left, // X source position
1084  SourceRect.top, // Y source position
1085  SRCCOPY); // Simple copy
1086 
1087  } else {
1088 
1089  // Stretch the image when copying to the window
1090 
1091  StretchBlt(
1092  (HDC) m_hdc, // Target device HDC
1093  m_TargetRect.left, // X sink position
1094  m_TargetRect.top, // Y sink position
1095  m_TargetRect.right - m_TargetRect.left, // Destination width
1096  m_TargetRect.bottom - m_TargetRect.top, // Destination height
1097  m_MemoryDC, // Source device HDC
1098  SourceRect.left, // X source position
1099  SourceRect.top, // Y source position
1100  SourceRect.right - SourceRect.left, // Source width
1101  SourceRect.bottom - SourceRect.top, // Source height
1102  SRCCOPY); // Simple copy
1103  }
1104 
1105  // This displays the sample times over the top of the image. This used to
1106  // draw the times into the offscreen device context however that actually
1107  // writes the text into the image data buffer which may not be writable
1108 
1109  #ifdef DEBUG
1110  DisplaySampleTimes(pMediaSample);
1111  #endif
1112 
1113  // Put the old bitmap back into the device context so we don't leak
1114  SelectObject(m_MemoryDC,hOldBitmap);
1115 }
1116 
1117 
1118 // This is called when there is a sample ready to be drawn, unfortunately the
1119 // output pin was being rotten and didn't choose our super excellent shared
1120 // memory DIB allocator so we have to do this slow render using boring old GDI
1121 // SetDIBitsToDevice and StretchDIBits. The down side of using these GDI
1122 // functions is that the image data has to be copied across from our address
1123 // space into theirs before going to the screen (although in reality the cost
1124 // is small because all they do is to map the buffer into their address space)
1125 
1126 void CDrawImage::SlowRender(IMediaSample *pMediaSample)
1127 {
1128  // Get the BITMAPINFOHEADER for the connection
1129 
1131  BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format());
1132  BYTE *pImage;
1133 
1134  // Get the image data buffer
1135 
1136  HRESULT hr = pMediaSample->GetPointer(&pImage);
1137  if (FAILED(hr)) {
1138  return;
1139  }
1140 
1141  // This allows derived classes to change the source rectangle that we do
1142  // the drawing with. For example a renderer may ask a codec to stretch
1143  // the video from 320x240 to 640x480, in which case the source we see in
1144  // here will still be 320x240, although the source we want to draw with
1145  // should be scaled up to 640x480. The base class implementation of this
1146  // method does nothing but return the same rectangle as we are passed in
1147 
1148  RECT SourceRect = ScaleSourceRect(&m_SourceRect);
1149 
1150  LONG lAdjustedSourceTop = SourceRect.top;
1151  // if the origin of bitmap is bottom-left, adjust soruce_rect_top
1152  // to be the bottom-left corner instead of the top-left.
1153  if (pbmi->biHeight > 0) {
1154  lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom;
1155  }
1156  // Is the window the same size as the video
1157 
1158  if (m_bStretch == FALSE) {
1159 
1160  // Put the image straight into the window
1161 
1162  SetDIBitsToDevice(
1163  (HDC) m_hdc, // Target device HDC
1164  m_TargetRect.left, // X sink position
1165  m_TargetRect.top, // Y sink position
1166  m_TargetRect.right - m_TargetRect.left, // Destination width
1167  m_TargetRect.bottom - m_TargetRect.top, // Destination height
1168  SourceRect.left, // X source position
1169  lAdjustedSourceTop, // Adjusted Y source position
1170  (UINT) 0, // Start scan line
1171  pbmi->biHeight, // Scan lines present
1172  pImage, // Image data
1173  (BITMAPINFO *) pbmi, // DIB header
1174  DIB_RGB_COLORS); // Type of palette
1175 
1176  } else {
1177 
1178  // Stretch the image when copying to the window
1179 
1180  StretchDIBits(
1181  (HDC) m_hdc, // Target device HDC
1182  m_TargetRect.left, // X sink position
1183  m_TargetRect.top, // Y sink position
1184  m_TargetRect.right - m_TargetRect.left, // Destination width
1185  m_TargetRect.bottom - m_TargetRect.top, // Destination height
1186  SourceRect.left, // X source position
1187  lAdjustedSourceTop, // Adjusted Y source position
1188  SourceRect.right - SourceRect.left, // Source width
1189  SourceRect.bottom - SourceRect.top, // Source height
1190  pImage, // Image data
1191  (BITMAPINFO *) pbmi, // DIB header
1192  DIB_RGB_COLORS, // Type of palette
1193  SRCCOPY); // Simple image copy
1194  }
1195 
1196  // This shows the sample reference times over the top of the image which
1197  // looks a little flickery. I tried using GdiSetBatchLimit and GdiFlush to
1198  // control the screen updates but it doesn't quite work as expected and
1199  // only partially reduces the flicker. I also tried using a memory context
1200  // and combining the two in that before doing a final BitBlt operation to
1201  // the screen, unfortunately this has considerable performance penalties
1202  // and also means that this code is not executed when compiled retail
1203 
1204  #ifdef DEBUG
1205  DisplaySampleTimes(pMediaSample);
1206  #endif
1207 }
1208 
1209 
1210 // This is called with an IMediaSample interface on the image to be drawn. We
1211 // decide on the drawing mechanism based on who's allocator we are using. We
1212 // may be called when the window wants an image painted by WM_PAINT messages
1213 // We can't realise the palette here because we have the renderer lock, any
1214 // call to realise may cause an interthread send message to the window thread
1215 // which may in turn be waiting to get the renderer lock before servicing it
1216 
1217 BOOL CDrawImage::DrawImage(IMediaSample *pMediaSample)
1218 {
1219  ASSERT(m_hdc);
1220  ASSERT(m_MemoryDC);
1221  NotifyStartDraw();
1222 
1223  // If the output pin used our allocator then the samples passed are in
1224  // fact CVideoSample objects that contain CreateDIBSection data that we
1225  // use to do faster image rendering, they may optionally also contain a
1226  // DirectDraw surface pointer in which case we do not do the drawing
1227 
1228  if (m_bUsingImageAllocator == FALSE) {
1229  SlowRender(pMediaSample);
1230  EXECUTE_ASSERT(GdiFlush());
1231  NotifyEndDraw();
1232  return TRUE;
1233  }
1234 
1235  // This is a DIBSECTION buffer
1236 
1237  FastRender(pMediaSample);
1238  EXECUTE_ASSERT(GdiFlush());
1239  NotifyEndDraw();
1240  return TRUE;
1241 }
1242 
1243 
1245  HDC hdc,
1246  IMediaSample *pMediaSample,
1247  __in LPRECT lprcSrc,
1248  __in LPRECT lprcDst
1249  )
1250 {
1252  BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format());
1253  BYTE *pImage;
1254 
1255  // Get the image data buffer
1256 
1257  HRESULT hr = pMediaSample->GetPointer(&pImage);
1258  if (FAILED(hr)) {
1259  return FALSE;
1260  }
1261 
1262  RECT SourceRect;
1263  RECT TargetRect;
1264 
1265  if (lprcSrc) {
1266  SourceRect = *lprcSrc;
1267  }
1268  else SourceRect = ScaleSourceRect(&m_SourceRect);
1269 
1270  if (lprcDst) {
1271  TargetRect = *lprcDst;
1272  }
1273  else TargetRect = m_TargetRect;
1274 
1275  LONG lAdjustedSourceTop = SourceRect.top;
1276  // if the origin of bitmap is bottom-left, adjust soruce_rect_top
1277  // to be the bottom-left corner instead of the top-left.
1278  if (pbmi->biHeight > 0) {
1279  lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom;
1280  }
1281 
1282 
1283  // Stretch the image when copying to the DC
1284 
1285  BOOL bRet = (0 != StretchDIBits(hdc,
1286  TargetRect.left,
1287  TargetRect.top,
1288  TargetRect.right - TargetRect.left,
1289  TargetRect.bottom - TargetRect.top,
1290  SourceRect.left,
1291  lAdjustedSourceTop,
1292  SourceRect.right - SourceRect.left,
1293  SourceRect.bottom - SourceRect.top,
1294  pImage,
1295  (BITMAPINFO *)pbmi,
1296  DIB_RGB_COLORS,
1297  SRCCOPY));
1298  return bRet;
1299 }
1300 
1301 
1302 // This is called by the owning window object after it has created the window
1303 // and it's drawing contexts. We are constructed with the base window we'll
1304 // be drawing into so when given the notification we retrive the device HDCs
1305 // to draw with. We cannot call these in our constructor as they are virtual
1306 
1308 {
1311 }
1312 
1313 
1314 // This is called to set the target rectangle in the video window, it will be
1315 // called whenever a WM_SIZE message is retrieved from the message queue. We
1316 // simply store the rectangle and use it later when we do the drawing calls
1317 
1318 void CDrawImage::SetTargetRect(__in RECT *pTargetRect)
1319 {
1320  ASSERT(pTargetRect);
1321  m_TargetRect = *pTargetRect;
1322  SetStretchMode();
1323 }
1324 
1325 
1326 // Return the current target rectangle
1327 
1328 void CDrawImage::GetTargetRect(__out RECT *pTargetRect)
1329 {
1330  ASSERT(pTargetRect);
1331  *pTargetRect = m_TargetRect;
1332 }
1333 
1334 
1335 // This is called when we want to change the section of the image to draw. We
1336 // use this information in the drawing operation calls later on. We must also
1337 // see if the source and destination rectangles have the same dimensions. If
1338 // not we must stretch during the drawing rather than a direct pixel copy
1339 
1340 void CDrawImage::SetSourceRect(__in RECT *pSourceRect)
1341 {
1342  ASSERT(pSourceRect);
1343  m_SourceRect = *pSourceRect;
1344  SetStretchMode();
1345 }
1346 
1347 
1348 // Return the current source rectangle
1349 
1350 void CDrawImage::GetSourceRect(__out RECT *pSourceRect)
1351 {
1352  ASSERT(pSourceRect);
1353  *pSourceRect = m_SourceRect;
1354 }
1355 
1356 
1357 // This is called when either the source or destination rectanges change so we
1358 // can update the stretch flag. If the rectangles don't match we stretch the
1359 // video during the drawing otherwise we call the fast pixel copy functions
1360 // NOTE the source and/or the destination rectangle may be completely empty
1361 
1363 {
1364  // Calculate the overall rectangle dimensions
1365 
1366  LONG SourceWidth = m_SourceRect.right - m_SourceRect.left;
1367  LONG SinkWidth = m_TargetRect.right - m_TargetRect.left;
1368  LONG SourceHeight = m_SourceRect.bottom - m_SourceRect.top;
1369  LONG SinkHeight = m_TargetRect.bottom - m_TargetRect.top;
1370 
1371  m_bStretch = TRUE;
1372  if (SourceWidth == SinkWidth) {
1373  if (SourceHeight == SinkHeight) {
1374  m_bStretch = FALSE;
1375  }
1376  }
1377 }
1378 
1379 
1380 // Tell us whose allocator we are using. This should be called with TRUE if
1381 // the filter agrees to use an allocator based around the CImageAllocator
1382 // SDK base class - whose image buffers are made through CreateDIBSection.
1383 // Otherwise this should be called with FALSE and we will draw the images
1384 // using SetDIBitsToDevice and StretchDIBitsToDevice. None of these calls
1385 // can handle buffers which have non zero strides (like DirectDraw uses)
1386 
1387 void CDrawImage::NotifyAllocator(BOOL bUsingImageAllocator)
1388 {
1389  m_bUsingImageAllocator = bUsingImageAllocator;
1390 }
1391 
1392 
1393 // Are we using the image DIBSECTION allocator
1394 
1396 {
1397  return m_bUsingImageAllocator;
1398 }
1399 
1400 
1401 // We need the media type of the connection so that we can get the BITMAPINFO
1402 // from it. We use that in the calls to draw the image such as StretchDIBits
1403 // and also when updating the colour table held in shared memory DIBSECTIONs
1404 
1406 {
1407  m_pMediaType = pMediaType;
1408 }
1409 
1410 
1411 // We store in this object a cookie maintaining the current palette version.
1412 // Each time a palettised format is changed we increment this value so that
1413 // when we come to draw the images we look at the colour table value they
1414 // have and if less than the current we know to update it. This version is
1415 // only needed and indeed used when working with shared memory DIBSECTIONs
1416 
1418 {
1419  return m_PaletteVersion;
1420 }
1421 
1422 
1423 // Resets the current palette version number
1424 
1426 {
1428 }
1429 
1430 
1431 // Increment the current palette version
1432 
1434 {
1435  m_PaletteVersion++;
1436 }
1437 
1438 
1439 // Constructor must initialise the base allocator. Each sample we create has a
1440 // palette version cookie on board. When the source filter changes the palette
1441 // during streaming the window object increments an internal cookie counter it
1442 // keeps as well. When it comes to render the samples it looks at the cookie
1443 // values and if they don't match then it knows to update the sample's colour
1444 // table. However we always create samples with a cookie of PALETTE_VERSION
1445 // If there have been multiple format changes and we disconnect and reconnect
1446 // thereby causing the samples to be reallocated we will create them with a
1447 // cookie much lower than the current version, this isn't a problem since it
1448 // will be seen by the window object and the versions will then be updated
1449 
1451  __in_opt LPCTSTR pName,
1452  __inout HRESULT *phr) :
1453  CBaseAllocator(pName,NULL,phr,TRUE,TRUE),
1454  m_pFilter(pFilter)
1455 {
1456  ASSERT(phr);
1457  ASSERT(pFilter);
1458 }
1459 
1460 
1461 // Check our DIB buffers have been released
1462 
1463 #ifdef DEBUG
1464 CImageAllocator::~CImageAllocator()
1465 {
1466  ASSERT(m_bCommitted == FALSE);
1467 }
1468 #endif
1469 
1470 
1471 // Called from destructor and also from base class to free resources. We work
1472 // our way through the list of media samples deleting the DIBSECTION created
1473 // for each. All samples should be back in our list so there is no chance a
1474 // filter is still using one to write on the display or hold on a pending list
1475 
1477 {
1478  ASSERT(m_lAllocated == m_lFree.GetCount());
1479  EXECUTE_ASSERT(GdiFlush());
1480  CImageSample *pSample;
1481  DIBDATA *pDibData;
1482 
1483  while (m_lFree.GetCount() != 0) {
1484  pSample = (CImageSample *) m_lFree.RemoveHead();
1485  pDibData = pSample->GetDIBData();
1486  EXECUTE_ASSERT(DeleteObject(pDibData->hBitmap));
1487  EXECUTE_ASSERT(CloseHandle(pDibData->hMapping));
1488  delete pSample;
1489  }
1490 
1491  m_lAllocated = 0;
1492 }
1493 
1494 
1495 // Prepare the allocator by checking all the input parameters
1496 
1497 STDMETHODIMP CImageAllocator::CheckSizes(__in ALLOCATOR_PROPERTIES *pRequest)
1498 {
1499  // Check we have a valid connection
1500 
1501  if (m_pMediaType == NULL) {
1502  return VFW_E_NOT_CONNECTED;
1503  }
1504 
1505  // NOTE We always create a DIB section with the source format type which
1506  // may contain a source palette. When we do the BitBlt drawing operation
1507  // the target display device may contain a different palette (we may not
1508  // have the focus) in which case GDI will do after the palette mapping
1509 
1510  VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *) m_pMediaType->Format();
1511 
1512  // When we call CreateDIBSection it implicitly maps only enough memory
1513  // for the image as defined by thee BITMAPINFOHEADER. If the user asks
1514  // for an image smaller than this then we reject the call, if they ask
1515  // for an image larger than this then we return what they can have
1516 
1517  if ((DWORD) pRequest->cbBuffer < pVideoInfo->bmiHeader.biSizeImage) {
1518  return E_INVALIDARG;
1519  }
1520 
1521  // Reject buffer prefixes
1522 
1523  if (pRequest->cbPrefix > 0) {
1524  return E_INVALIDARG;
1525  }
1526 
1527  pRequest->cbBuffer = pVideoInfo->bmiHeader.biSizeImage;
1528  return NOERROR;
1529 }
1530 
1531 
1532 // Agree the number of media sample buffers and their sizes. The base class
1533 // this allocator is derived from allows samples to be aligned only on byte
1534 // boundaries NOTE the buffers are not allocated until the Commit call
1535 
1537  __in ALLOCATOR_PROPERTIES * pRequest,
1538  __out ALLOCATOR_PROPERTIES * pActual)
1539 {
1540  ALLOCATOR_PROPERTIES Adjusted = *pRequest;
1541 
1542  // Check the parameters fit with the current connection
1543 
1544  HRESULT hr = CheckSizes(&Adjusted);
1545  if (FAILED(hr)) {
1546  return hr;
1547  }
1548  return CBaseAllocator::SetProperties(&Adjusted, pActual);
1549 }
1550 
1551 
1552 // Commit the memory by allocating the agreed number of media samples. For
1553 // each sample we are committed to creating we have a CImageSample object
1554 // that we use to manage it's resources. This is initialised with a DIBDATA
1555 // structure that contains amongst other things the GDI DIBSECTION handle
1556 // We will access the renderer media type during this so we must have locked
1557 // (to prevent the format changing for example). The class overrides Commit
1558 // and Decommit to do this locking (base class Commit in turn calls Alloc)
1559 
1561 {
1563  CImageSample *pSample;
1564  DIBDATA DibData;
1565 
1566  // Check the base allocator says it's ok to continue
1567 
1568  HRESULT hr = CBaseAllocator::Alloc();
1569  if (FAILED(hr)) {
1570  return hr;
1571  }
1572 
1573  // We create a new memory mapped object although we don't map it into our
1574  // address space because GDI does that in CreateDIBSection. It is possible
1575  // that we run out of resources before creating all the samples in which
1576  // case the available sample list is left with those already created
1577 
1578  ASSERT(m_lAllocated == 0);
1579  while (m_lAllocated < m_lCount) {
1580 
1581  // Create and initialise a shared memory GDI buffer
1582 
1583  hr = CreateDIB(m_lSize,DibData);
1584  if (FAILED(hr)) {
1585  return hr;
1586  }
1587 
1588  // Create the sample object and pass it the DIBDATA
1589 
1590  pSample = CreateImageSample(DibData.pBase,m_lSize);
1591  if (pSample == NULL) {
1592  EXECUTE_ASSERT(DeleteObject(DibData.hBitmap));
1593  EXECUTE_ASSERT(CloseHandle(DibData.hMapping));
1594  return E_OUTOFMEMORY;
1595  }
1596 
1597  // Add the completed sample to the available list
1598 
1599  pSample->SetDIBData(&DibData);
1600  m_lFree.Add(pSample);
1601  m_lAllocated++;
1602  }
1603  return NOERROR;
1604 }
1605 
1606 
1607 // We have a virtual method that allocates the samples so that a derived class
1608 // may override it and allocate more specialised sample objects. So long as it
1609 // derives its samples from CImageSample then all this code will still work ok
1610 
1611 CImageSample *CImageAllocator::CreateImageSample(__in_bcount(Length) LPBYTE pData,LONG Length)
1612 {
1613  HRESULT hr = NOERROR;
1614  CImageSample *pSample;
1615 
1616  // Allocate the new sample and check the return codes
1617 
1618  pSample = new CImageSample((CBaseAllocator *) this, // Base class
1619  NAME("Video sample"), // DEBUG name
1620  (HRESULT *) &hr, // Return code
1621  (LPBYTE) pData, // DIB address
1622  (LONG) Length); // Size of DIB
1623 
1624  if (pSample == NULL || FAILED(hr)) {
1625  delete pSample;
1626  return NULL;
1627  }
1628  return pSample;
1629 }
1630 
1631 
1632 // This function allocates a shared memory block for use by the source filter
1633 // generating DIBs for us to render. The memory block is created in shared
1634 // memory so that GDI doesn't have to copy the memory when we do a BitBlt
1635 
1636 HRESULT CImageAllocator::CreateDIB(LONG InSize,DIBDATA &DibData)
1637 {
1638  BITMAPINFO *pbmi; // Format information for pin
1639  BYTE *pBase; // Pointer to the actual image
1640  HANDLE hMapping; // Handle to mapped object
1641  HBITMAP hBitmap; // DIB section bitmap handle
1642 
1643  // Create a file mapping object and map into our address space
1644 
1645  hMapping = CreateFileMapping(hMEMORY, // Use system page file
1646  NULL, // No security attributes
1647  PAGE_READWRITE, // Full access to memory
1648  (DWORD) 0, // Less than 4Gb in size
1649  InSize, // Size of buffer
1650  NULL); // No name to section
1651  if (hMapping == NULL) {
1652  DWORD Error = GetLastError();
1653  return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error);
1654  }
1655 
1656  // NOTE We always create a DIB section with the source format type which
1657  // may contain a source palette. When we do the BitBlt drawing operation
1658  // the target display device may contain a different palette (we may not
1659  // have the focus) in which case GDI will do after the palette mapping
1660 
1661  pbmi = (BITMAPINFO *) HEADER(m_pMediaType->Format());
1662  if (m_pMediaType == NULL) {
1663  DbgBreak("Invalid media type");
1664  }
1665 
1666  hBitmap = CreateDIBSection((HDC) NULL, // NO device context
1667  pbmi, // Format information
1668  DIB_RGB_COLORS, // Use the palette
1669  (VOID **) &pBase, // Pointer to image data
1670  hMapping, // Mapped memory handle
1671  (DWORD) 0); // Offset into memory
1672 
1673  if (hBitmap == NULL || pBase == NULL) {
1674  EXECUTE_ASSERT(CloseHandle(hMapping));
1675  DWORD Error = GetLastError();
1676  return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error);
1677  }
1678 
1679  // Initialise the DIB information structure
1680 
1681  DibData.hBitmap = hBitmap;
1682  DibData.hMapping = hMapping;
1683  DibData.pBase = pBase;
1684  DibData.PaletteVersion = PALETTE_VERSION;
1685  GetObject(hBitmap,sizeof(DIBSECTION),(VOID *)&DibData.DibSection);
1686 
1687  return NOERROR;
1688 }
1689 
1690 
1691 // We use the media type during the DIBSECTION creation
1692 
1694 {
1695  m_pMediaType = pMediaType;
1696 }
1697 
1698 
1699 // Overriden to increment the owning object's reference count
1700 
1701 STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingAddRef()
1702 {
1703  return m_pFilter->AddRef();
1704 }
1705 
1706 
1707 // Overriden to decrement the owning object's reference count
1708 
1709 STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingRelease()
1710 {
1711  return m_pFilter->Release();
1712 }
1713 
1714 
1715 // If you derive a class from CMediaSample that has to transport specialised
1716 // member variables and entry points then there are three alternate solutions
1717 // The first is to create a memory buffer larger than actually required by the
1718 // sample and store your information either at the beginning of it or at the
1719 // end, the former being moderately safer allowing for misbehaving transform
1720 // filters. You then adjust the buffer address when you create the base media
1721 // sample. This has the disadvantage of breaking up the memory allocated to
1722 // the samples into separate blocks. The second solution is to implement a
1723 // class derived from CMediaSample and support additional interface(s) that
1724 // convey your private data. This means defining a custom interface. The final
1725 // alternative is to create a class that inherits from CMediaSample and adds
1726 // the private data structures, when you get an IMediaSample in your Receive()
1727 // call check to see if your allocator is being used, and if it is then cast
1728 // the IMediaSample into one of your objects. Additional checks can be made
1729 // to ensure the sample's this pointer is known to be one of your own objects
1730 
1732  __in_opt LPCTSTR pName,
1733  __inout HRESULT *phr,
1734  __in_bcount(length) LPBYTE pBuffer,
1735  LONG length) :
1736  CMediaSample(pName,pAllocator,phr,pBuffer,length),
1737  m_bInit(FALSE)
1738 {
1739  ASSERT(pAllocator);
1740  ASSERT(pBuffer);
1741 }
1742 
1743 
1744 // Set the shared memory DIB information
1745 
1746 void CImageSample::SetDIBData(__in DIBDATA *pDibData)
1747 {
1748  ASSERT(pDibData);
1749  m_DibData = *pDibData;
1750  m_bInit = TRUE;
1751 }
1752 
1753 
1754 // Retrieve the shared memory DIB data
1755 
1757 {
1758  ASSERT(m_bInit == TRUE);
1759  return &m_DibData;
1760 }
1761 
1762 
1763 // This class handles the creation of a palette. It is fairly specialist and
1764 // is intended to simplify palette management for video renderer filters. It
1765 // is for this reason that the constructor requires three other objects with
1766 // which it interacts, namely a base media filter, a base window and a base
1767 // drawing object although the base window or the draw object may be NULL to
1768 // ignore that part of us. We try not to create and install palettes unless
1769 // absolutely necessary as they typically require WM_PALETTECHANGED messages
1770 // to be sent to every window thread in the system which is very expensive
1771 
1773  __inout CBaseWindow *pBaseWindow,
1774  __inout CDrawImage *pDrawImage) :
1775  m_pBaseWindow(pBaseWindow),
1776  m_pFilter(pBaseFilter),
1777  m_pDrawImage(pDrawImage),
1778  m_hPalette(NULL)
1779 {
1780  ASSERT(m_pFilter);
1781 }
1782 
1783 
1784 // Destructor
1785 
1786 #ifdef DEBUG
1787 CImagePalette::~CImagePalette()
1788 {
1789  ASSERT(m_hPalette == NULL);
1790 }
1791 #endif
1792 
1793 
1794 // We allow dynamic format changes of the palette but rather than change the
1795 // palette every time we call this to work out whether an update is required.
1796 // If the original type didn't use a palette and the new one does (or vica
1797 // versa) then we return TRUE. If neither formats use a palette we'll return
1798 // FALSE. If both formats use a palette we compare their colours and return
1799 // FALSE if they match. This therefore short circuits palette creation unless
1800 // absolutely necessary since installing palettes is an expensive operation
1801 
1802 BOOL CImagePalette::ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,
1803  const VIDEOINFOHEADER *pOldInfo)
1804 {
1805  // We may not have a current format yet
1806 
1807  if (pOldInfo == NULL) {
1808  return TRUE;
1809  }
1810 
1811  // Do both formats not require a palette
1812 
1813  if (ContainsPalette(pNewInfo) == FALSE) {
1814  if (ContainsPalette(pOldInfo) == FALSE) {
1815  return FALSE;
1816  }
1817  }
1818 
1819  // Compare the colours to see if they match
1820 
1821  DWORD VideoEntries = pNewInfo->bmiHeader.biClrUsed;
1822  if (ContainsPalette(pNewInfo) == TRUE)
1823  if (ContainsPalette(pOldInfo) == TRUE)
1824  if (pOldInfo->bmiHeader.biClrUsed == VideoEntries)
1825  if (pOldInfo->bmiHeader.biClrUsed > 0)
1826  if (memcmp((PVOID) GetBitmapPalette(pNewInfo),
1827  (PVOID) GetBitmapPalette(pOldInfo),
1828  VideoEntries * sizeof(RGBQUAD)) == 0) {
1829 
1830  return FALSE;
1831  }
1832  return TRUE;
1833 }
1834 
1835 
1836 // This is normally called when the input pin type is set to install a palette
1837 // We will typically be called from two different places. The first is when we
1838 // have negotiated a palettised media type after connection, the other is when
1839 // we receive a new type during processing with an updated palette in which
1840 // case we must remove and release the resources held by the current palette
1841 
1842 // We can be passed an optional device name if we wish to prepare a palette
1843 // for a specific monitor on a multi monitor system
1844 
1846  const CMediaType *pmtOld,
1847  __in LPSTR szDevice)
1848 {
1849  const VIDEOINFOHEADER *pNewInfo = (VIDEOINFOHEADER *) pmtNew->Format();
1850  const VIDEOINFOHEADER *pOldInfo = (VIDEOINFOHEADER *) pmtOld->Format();
1851  ASSERT(pNewInfo);
1852 
1853  // This is an performance optimisation, when we get a media type we check
1854  // to see if the format requires a palette change. If either we need one
1855  // when previously we didn't or vica versa then this returns TRUE, if we
1856  // previously needed a palette and we do now it compares their colours
1857 
1858  if (ShouldUpdate(pNewInfo,pOldInfo) == FALSE) {
1859  NOTE("No update needed");
1860  return S_FALSE;
1861  }
1862 
1863  // We must notify the filter graph that the application may have changed
1864  // the palette although in practice we don't bother checking to see if it
1865  // is really different. If it tries to get the palette either the window
1866  // or renderer lock will ensure it doesn't get in until we are finished
1867 
1868  RemovePalette();
1869  m_pFilter->NotifyEvent(EC_PALETTE_CHANGED,0,0);
1870 
1871  // Do we need a palette for the new format
1872 
1873  if (ContainsPalette(pNewInfo) == FALSE) {
1874  NOTE("New has no palette");
1875  return S_FALSE;
1876  }
1877 
1878  if (m_pBaseWindow) {
1880  }
1881 
1882  // If we're changing the palette on the fly then we increment our palette
1883  // cookie which is compared against the cookie also stored in all of our
1884  // DIBSECTION media samples. If they don't match when we come to draw it
1885  // then we know the sample is out of date and we'll update it's palette
1886 
1887  NOTE("Making new colour palette");
1888  m_hPalette = MakePalette(pNewInfo, szDevice);
1889  ASSERT(m_hPalette != NULL);
1890 
1891  if (m_pBaseWindow) {
1893  }
1894 
1895  // The window in which the new palette is to be realised may be a NULL
1896  // pointer to signal that no window is in use, if so we don't call it
1897  // Some filters just want to use this object to create/manage palettes
1898 
1900 
1901  // This is the only time where we need access to the draw object to say
1902  // to it that a new palette will be arriving on a sample real soon. The
1903  // constructor may take a NULL pointer in which case we don't call this
1904 
1906  return NOERROR;
1907 }
1908 
1909 
1910 // Helper function to copy a palette out of any kind of VIDEOINFO (ie it may
1911 // be YUV or true colour) into a palettised VIDEOINFO. We use this changing
1912 // palettes on DirectDraw samples as a source filter can attach a palette to
1913 // any buffer (eg YUV) and hand it back. We make a new palette out of that
1914 // format and then copy the palette colours into the current connection type
1915 
1916 HRESULT CImagePalette::CopyPalette(const CMediaType *pSrc,__out CMediaType *pDest)
1917 {
1918  // Reset the destination palette before starting
1919 
1920  VIDEOINFOHEADER *pDestInfo = (VIDEOINFOHEADER *) pDest->Format();
1921  pDestInfo->bmiHeader.biClrUsed = 0;
1922  pDestInfo->bmiHeader.biClrImportant = 0;
1923 
1924  // Does the destination have a palette
1925 
1926  if (PALETTISED(pDestInfo) == FALSE) {
1927  NOTE("No destination palette");
1928  return S_FALSE;
1929  }
1930 
1931  // Does the source contain a palette
1932 
1933  const VIDEOINFOHEADER *pSrcInfo = (VIDEOINFOHEADER *) pSrc->Format();
1934  if (ContainsPalette(pSrcInfo) == FALSE) {
1935  NOTE("No source palette");
1936  return S_FALSE;
1937  }
1938 
1939  // The number of colours may be zero filled
1940 
1941  DWORD PaletteEntries = pSrcInfo->bmiHeader.biClrUsed;
1942  if (PaletteEntries == 0) {
1943  DWORD Maximum = (1 << pSrcInfo->bmiHeader.biBitCount);
1944  NOTE1("Setting maximum colours (%d)",Maximum);
1945  PaletteEntries = Maximum;
1946  }
1947 
1948  // Make sure the destination has enough room for the palette
1949 
1950  ASSERT(pSrcInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS);
1951  ASSERT(pSrcInfo->bmiHeader.biClrImportant <= PaletteEntries);
1952  ASSERT(COLORS(pDestInfo) == GetBitmapPalette(pDestInfo));
1953  pDestInfo->bmiHeader.biClrUsed = PaletteEntries;
1954  pDestInfo->bmiHeader.biClrImportant = pSrcInfo->bmiHeader.biClrImportant;
1955  ULONG BitmapSize = GetBitmapFormatSize(HEADER(pSrcInfo));
1956 
1957  if (pDest->FormatLength() < BitmapSize) {
1958  NOTE("Reallocating destination");
1959  pDest->ReallocFormatBuffer(BitmapSize);
1960  }
1961 
1962  // Now copy the palette colours across
1963 
1964  CopyMemory((PVOID) COLORS(pDestInfo),
1965  (PVOID) GetBitmapPalette(pSrcInfo),
1966  PaletteEntries * sizeof(RGBQUAD));
1967 
1968  return NOERROR;
1969 }
1970 
1971 
1972 // This is normally called when the palette is changed (typically during a
1973 // dynamic format change) to remove any palette we previously installed. We
1974 // replace it (if necessary) in the video window with a standard VGA palette
1975 // that should always be available even if this is a true colour display
1976 
1978 {
1979  if (m_pBaseWindow) {
1981  }
1982 
1983  // Do we have a palette to remove
1984 
1985  if (m_hPalette != NULL) {
1986 
1987  if (m_pBaseWindow) {
1988  // Make sure that the window's palette handle matches
1989  // our palette handle.
1990  ASSERT(m_hPalette == m_pBaseWindow->GetPalette());
1991 
1993  }
1994 
1995  EXECUTE_ASSERT(DeleteObject(m_hPalette));
1996  m_hPalette = NULL;
1997  }
1998 
1999  if (m_pBaseWindow) {
2001  }
2002 
2003  return NOERROR;
2004 }
2005 
2006 
2007 // Called to create a palette for the object, the data structure used by GDI
2008 // to describe a palette is a LOGPALETTE, this includes a variable number of
2009 // PALETTEENTRY fields which are the colours, we have to convert the RGBQUAD
2010 // colour fields we are handed in a BITMAPINFO from the media type into these
2011 // This handles extraction of palettes from true colour and YUV media formats
2012 
2013 // We can be passed an optional device name if we wish to prepare a palette
2014 // for a specific monitor on a multi monitor system
2015 
2016 HPALETTE CImagePalette::MakePalette(const VIDEOINFOHEADER *pVideoInfo, __in LPSTR szDevice)
2017 {
2018  ASSERT(ContainsPalette(pVideoInfo) == TRUE);
2019  ASSERT(pVideoInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS);
2020  BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo);
2021 
2022  const RGBQUAD *pColours; // Pointer to the palette
2023  LOGPALETTE *lp; // Used to create a palette
2024  HPALETTE hPalette; // Logical palette object
2025 
2026  lp = (LOGPALETTE *) new BYTE[sizeof(LOGPALETTE) + SIZE_PALETTE];
2027  if (lp == NULL) {
2028  return NULL;
2029  }
2030 
2031  // Unfortunately for some hare brained reason a GDI palette entry (a
2032  // PALETTEENTRY structure) is different to a palette entry from a DIB
2033  // format (a RGBQUAD structure) so we have to do the field conversion
2034  // The VIDEOINFO containing the palette may be a true colour type so
2035  // we use GetBitmapPalette to skip over any bit fields if they exist
2036 
2037  lp->palVersion = PALVERSION;
2038  lp->palNumEntries = (USHORT) pHeader->biClrUsed;
2039  if (lp->palNumEntries == 0) lp->palNumEntries = (1 << pHeader->biBitCount);
2040  pColours = GetBitmapPalette(pVideoInfo);
2041 
2042  for (DWORD dwCount = 0;dwCount < lp->palNumEntries;dwCount++) {
2043  lp->palPalEntry[dwCount].peRed = pColours[dwCount].rgbRed;
2044  lp->palPalEntry[dwCount].peGreen = pColours[dwCount].rgbGreen;
2045  lp->palPalEntry[dwCount].peBlue = pColours[dwCount].rgbBlue;
2046  lp->palPalEntry[dwCount].peFlags = 0;
2047  }
2048 
2049  MakeIdentityPalette(lp->palPalEntry, lp->palNumEntries, szDevice);
2050 
2051  // Create a logical palette
2052 
2053  hPalette = CreatePalette(lp);
2054  ASSERT(hPalette != NULL);
2055  delete[] lp;
2056  return hPalette;
2057 }
2058 
2059 
2060 // GDI does a fair job of compressing the palette entries you give it, so for
2061 // example if you have five entries with an RGB colour (0,0,0) it will remove
2062 // all but one of them. When you subsequently draw an image it will map from
2063 // your logical palette to the compressed device palette. This function looks
2064 // to see if it is trying to be an identity palette and if so sets the flags
2065 // field in the PALETTEENTRYs so they remain expanded to boost performance
2066 
2067 // We can be passed an optional device name if we wish to prepare a palette
2068 // for a specific monitor on a multi monitor system
2069 
2070 HRESULT CImagePalette::MakeIdentityPalette(__inout_ecount_full(iColours) PALETTEENTRY *pEntry,INT iColours, __in LPSTR szDevice)
2071 {
2072  PALETTEENTRY SystemEntries[10]; // System palette entries
2073  BOOL bIdentityPalette = TRUE; // Is an identity palette
2074  ASSERT(iColours <= iPALETTE_COLORS); // Should have a palette
2075  const int PalLoCount = 10; // First ten reserved colours
2076  const int PalHiStart = 246; // Last VGA palette entries
2077 
2078  // Does this have the full colour range
2079 
2080  if (iColours < 10) {
2081  return S_FALSE;
2082  }
2083 
2084  // Apparently some displays have odd numbers of system colours
2085 
2086  // Get a DC on the right monitor - it's ugly, but this is the way you have
2087  // to do it
2088  HDC hdc;
2089  if (szDevice == NULL || lstrcmpiLocaleIndependentA(szDevice, "DISPLAY") == 0)
2090  hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
2091  else
2092  hdc = CreateDCA(NULL, szDevice, NULL, NULL);
2093  if (NULL == hdc) {
2094  return E_OUTOFMEMORY;
2095  }
2096  INT Reserved = GetDeviceCaps(hdc,NUMRESERVED);
2097  if (Reserved != 20) {
2098  DeleteDC(hdc);
2099  return S_FALSE;
2100  }
2101 
2102  // Compare our palette against the first ten system entries. The reason I
2103  // don't do a memory compare between our two arrays of colours is because
2104  // I am not sure what will be in the flags fields for the system entries
2105 
2106  UINT Result = GetSystemPaletteEntries(hdc,0,PalLoCount,SystemEntries);
2107  for (UINT Count = 0;Count < Result;Count++) {
2108  if (SystemEntries[Count].peRed != pEntry[Count].peRed ||
2109  SystemEntries[Count].peGreen != pEntry[Count].peGreen ||
2110  SystemEntries[Count].peBlue != pEntry[Count].peBlue) {
2111  bIdentityPalette = FALSE;
2112  }
2113  }
2114 
2115  // And likewise compare against the last ten entries
2116 
2117  Result = GetSystemPaletteEntries(hdc,PalHiStart,PalLoCount,SystemEntries);
2118  for (UINT Count = 0;Count < Result;Count++) {
2119  if (INT(Count) + PalHiStart < iColours) {
2120  if (SystemEntries[Count].peRed != pEntry[PalHiStart + Count].peRed ||
2121  SystemEntries[Count].peGreen != pEntry[PalHiStart + Count].peGreen ||
2122  SystemEntries[Count].peBlue != pEntry[PalHiStart + Count].peBlue) {
2123  bIdentityPalette = FALSE;
2124  }
2125  }
2126  }
2127 
2128  // If not an identity palette then return S_FALSE
2129 
2130  DeleteDC(hdc);
2131  if (bIdentityPalette == FALSE) {
2132  return S_FALSE;
2133  }
2134 
2135  // Set the non VGA entries so that GDI doesn't map them
2136 
2137  for (UINT Count = PalLoCount;INT(Count) < min(PalHiStart,iColours);Count++) {
2138  pEntry[Count].peFlags = PC_NOCOLLAPSE;
2139  }
2140  return NOERROR;
2141 }
2142 
2143 
2144 // Constructor initialises the VIDEOINFO we keep storing the current display
2145 // format. The format can be changed at any time, to reset the format held
2146 // by us call the RefreshDisplayType directly (it's a public method). Since
2147 // more than one thread will typically call us (ie window threads resetting
2148 // the type and source threads in the type checking methods) we have a lock
2149 
2151 {
2153 }
2154 
2155 
2156 
2157 // This initialises the format we hold which contains the display device type
2158 // We do a conversion on the display device type in here so that when we start
2159 // type checking input formats we can assume that certain fields have been set
2160 // correctly, an example is when we make the 16 bit mask fields explicit. This
2161 // is normally called when we receive WM_DEVMODECHANGED device change messages
2162 
2163 // The optional szDeviceName parameter tells us which monitor we are interested
2164 // in for a multi monitor system
2165 
2166 HRESULT CImageDisplay::RefreshDisplayType(__in_opt LPSTR szDeviceName)
2167 {
2168  CAutoLock cDisplayLock(this);
2169 
2170  // Set the preferred format type
2171 
2172  ZeroMemory((PVOID)&m_Display,sizeof(VIDEOINFOHEADER)+sizeof(TRUECOLORINFO));
2173  m_Display.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2174  m_Display.bmiHeader.biBitCount = FALSE;
2175 
2176  // Get the bit depth of a device compatible bitmap
2177 
2178  // get caps of whichever monitor they are interested in (multi monitor)
2179  HDC hdcDisplay;
2180  // it's ugly, but this is the way you have to do it
2181  if (szDeviceName == NULL || lstrcmpiLocaleIndependentA(szDeviceName, "DISPLAY") == 0)
2182  hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
2183  else
2184  hdcDisplay = CreateDCA(NULL, szDeviceName, NULL, NULL);
2185  if (hdcDisplay == NULL) {
2186  ASSERT(FALSE);
2187  DbgLog((LOG_ERROR,1,TEXT("ACK! Can't get a DC for %hs"),
2188  szDeviceName ? szDeviceName : "<NULL>"));
2189  return E_FAIL;
2190  } else {
2191  DbgLog((LOG_TRACE,3,TEXT("Created a DC for %s"),
2192  szDeviceName ? szDeviceName : "<NULL>"));
2193  }
2194  HBITMAP hbm = CreateCompatibleBitmap(hdcDisplay,1,1);
2195  if ( hbm )
2196  {
2197  GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS);
2198 
2199  // This call will get the colour table or the proper bitfields
2200  GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS);
2201  DeleteObject(hbm);
2202  }
2203  DeleteDC(hdcDisplay);
2204 
2205  // Complete the display type initialisation
2206 
2209  DbgLog((LOG_TRACE,3,TEXT("New DISPLAY bit depth =%d"),
2210  m_Display.bmiHeader.biBitCount));
2211  return NOERROR;
2212 }
2213 
2214 
2215 // We assume throughout this code that any bitfields masks are allowed no
2216 // more than eight bits to store a colour component. This checks that the
2217 // bit count assumption is enforced and also makes sure that all the bits
2218 // set are contiguous. We return a boolean TRUE if the field checks out ok
2219 
2220 BOOL CImageDisplay::CheckBitFields(const VIDEOINFO *pInput)
2221 {
2222  DWORD *pBitFields = (DWORD *) BITMASKS(pInput);
2223 
2224  for (INT iColour = iRED;iColour <= iBLUE;iColour++) {
2225 
2226  // First of all work out how many bits are set
2227 
2228  DWORD SetBits = CountSetBits(pBitFields[iColour]);
2229  if (SetBits > iMAXBITS || SetBits == 0) {
2230  NOTE1("Bit fields for component %d invalid",iColour);
2231  return FALSE;
2232  }
2233 
2234  // Next work out the number of zero bits prefix
2235  DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]);
2236 
2237  // This is going to see if all the bits set are contiguous (as they
2238  // should be). We know how much to shift them right by from the
2239  // count of prefix bits. The number of bits set defines a mask, we
2240  // invert this (ones complement) and AND it with the shifted bit
2241  // fields. If the result is NON zero then there are bit(s) sticking
2242  // out the left hand end which means they are not contiguous
2243 
2244  DWORD TestField = pBitFields[iColour] >> PrefixBits;
2245  DWORD Mask = ULONG_MAX << SetBits;
2246  if (TestField & Mask) {
2247  NOTE1("Bit fields for component %d not contiguous",iColour);
2248  return FALSE;
2249  }
2250  }
2251  return TRUE;
2252 }
2253 
2254 
2255 // This counts the number of bits set in the input field
2256 
2258 {
2259  // This is a relatively well known bit counting algorithm
2260 
2261  DWORD Count = 0;
2262  DWORD init = Field;
2263 
2264  // Until the input is exhausted, count the number of bits
2265 
2266  while (init) {
2267  init = init & (init - 1); // Turn off the bottommost bit
2268  Count++;
2269  }
2270  return Count;
2271 }
2272 
2273 
2274 // This counts the number of zero bits upto the first one set NOTE the input
2275 // field should have been previously checked to ensure there is at least one
2276 // set although if we don't find one set we return the impossible value 32
2277 
2279 {
2280  DWORD Mask = 1;
2281  DWORD Count = 0;
2282 
2283  while (TRUE) {
2284  if (Field & Mask) {
2285  return Count;
2286  }
2287  Count++;
2288 
2289  ASSERT(Mask != 0x80000000);
2290  if (Mask == 0x80000000) {
2291  return Count;
2292  }
2293  Mask <<= 1;
2294  }
2295 }
2296 
2297 
2298 // This is called to check the BITMAPINFOHEADER for the input type. There are
2299 // many implicit dependancies between the fields in a header structure which
2300 // if we validate now make for easier manipulation in subsequent handling. We
2301 // also check that the BITMAPINFOHEADER matches it's specification such that
2302 // fields likes the number of planes is one, that it's structure size is set
2303 // correctly and that the bitmap dimensions have not been set as negative
2304 
2305 BOOL CImageDisplay::CheckHeaderValidity(const VIDEOINFO *pInput)
2306 {
2307  // Check the bitmap width and height are not negative.
2308 
2309  if (pInput->bmiHeader.biWidth <= 0 ||
2310  pInput->bmiHeader.biHeight <= 0) {
2311  NOTE("Invalid bitmap dimensions");
2312  return FALSE;
2313  }
2314 
2315  // Check the compression is either BI_RGB or BI_BITFIELDS
2316 
2317  if (pInput->bmiHeader.biCompression != BI_RGB) {
2318  if (pInput->bmiHeader.biCompression != BI_BITFIELDS) {
2319  NOTE("Invalid compression format");
2320  return FALSE;
2321  }
2322  }
2323 
2324  // If BI_BITFIELDS compression format check the colour depth
2325 
2326  if (pInput->bmiHeader.biCompression == BI_BITFIELDS) {
2327  if (pInput->bmiHeader.biBitCount != 16) {
2328  if (pInput->bmiHeader.biBitCount != 32) {
2329  NOTE("BI_BITFIELDS not 16/32 bit depth");
2330  return FALSE;
2331  }
2332  }
2333  }
2334 
2335  // Check the assumptions about the layout of the bit fields
2336 
2337  if (pInput->bmiHeader.biCompression == BI_BITFIELDS) {
2338  if (CheckBitFields(pInput) == FALSE) {
2339  NOTE("Bit fields are not valid");
2340  return FALSE;
2341  }
2342  }
2343 
2344  // Are the number of planes equal to one
2345 
2346  if (pInput->bmiHeader.biPlanes != 1) {
2347  NOTE("Number of planes not one");
2348  return FALSE;
2349  }
2350 
2351  // Check the image size is consistent (it can be zero)
2352 
2353  if (pInput->bmiHeader.biSizeImage != GetBitmapSize(&pInput->bmiHeader)) {
2354  if (pInput->bmiHeader.biSizeImage) {
2355  NOTE("Image size incorrectly set");
2356  return FALSE;
2357  }
2358  }
2359 
2360  // Check the size of the structure
2361 
2362  if (pInput->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) {
2363  NOTE("Size of BITMAPINFOHEADER wrong");
2364  return FALSE;
2365  }
2366  return CheckPaletteHeader(pInput);
2367 }
2368 
2369 
2370 // This runs a few simple tests against the palette fields in the input to
2371 // see if it looks vaguely correct. The tests look at the number of palette
2372 // colours present, the number considered important and the biCompression
2373 // field which should always be BI_RGB as no other formats are meaningful
2374 
2375 BOOL CImageDisplay::CheckPaletteHeader(const VIDEOINFO *pInput)
2376 {
2377  // The checks here are for palettised videos only
2378 
2379  if (PALETTISED(pInput) == FALSE) {
2380  if (pInput->bmiHeader.biClrUsed) {
2381  NOTE("Invalid palette entries");
2382  return FALSE;
2383  }
2384  return TRUE;
2385  }
2386 
2387  // Compression type of BI_BITFIELDS is meaningless for palette video
2388 
2389  if (pInput->bmiHeader.biCompression != BI_RGB) {
2390  NOTE("Palettised video must be BI_RGB");
2391  return FALSE;
2392  }
2393 
2394  // Check the number of palette colours is correct
2395 
2396  if (pInput->bmiHeader.biClrUsed > PALETTE_ENTRIES(pInput)) {
2397  NOTE("Too many colours in palette");
2398  return FALSE;
2399  }
2400 
2401  // The number of important colours shouldn't exceed the number used
2402 
2403  if (pInput->bmiHeader.biClrImportant > pInput->bmiHeader.biClrUsed) {
2404  NOTE("Too many important colours");
2405  return FALSE;
2406  }
2407  return TRUE;
2408 }
2409 
2410 
2411 // Return the format of the video display
2412 
2414 {
2415  return &m_Display;
2416 }
2417 
2418 
2419 // Return TRUE if the display uses a palette
2420 
2422 {
2423  return PALETTISED(&m_Display);
2424 }
2425 
2426 
2427 // Return the bit depth of the current display setting
2428 
2430 {
2431  return m_Display.bmiHeader.biBitCount;
2432 }
2433 
2434 
2435 // Initialise the optional fields in a VIDEOINFO. These are mainly to do with
2436 // the source and destination rectangles and palette information such as the
2437 // number of colours present. It simplifies our code just a little if we don't
2438 // have to keep checking for all the different valid permutations in a header
2439 // every time we want to do anything with it (an example would be creating a
2440 // palette). We set the base class media type before calling this function so
2441 // that the media types between the pins match after a connection is made
2442 
2443 HRESULT CImageDisplay::UpdateFormat(__inout VIDEOINFO *pVideoInfo)
2444 {
2445  ASSERT(pVideoInfo);
2446 
2447  BITMAPINFOHEADER *pbmi = HEADER(pVideoInfo);
2448  SetRectEmpty(&pVideoInfo->rcSource);
2449  SetRectEmpty(&pVideoInfo->rcTarget);
2450 
2451  // Set the number of colours explicitly
2452 
2453  if (PALETTISED(pVideoInfo)) {
2454  if (pVideoInfo->bmiHeader.biClrUsed == 0) {
2455  pVideoInfo->bmiHeader.biClrUsed = PALETTE_ENTRIES(pVideoInfo);
2456  }
2457  }
2458 
2459  // The number of important colours shouldn't exceed the number used, on
2460  // some displays the number of important colours is not initialised when
2461  // retrieving the display type so we set the colours used correctly
2462 
2463  if (pVideoInfo->bmiHeader.biClrImportant > pVideoInfo->bmiHeader.biClrUsed) {
2464  pVideoInfo->bmiHeader.biClrImportant = PALETTE_ENTRIES(pVideoInfo);
2465  }
2466 
2467  // Change the image size field to be explicit
2468 
2469  if (pVideoInfo->bmiHeader.biSizeImage == 0) {
2470  pVideoInfo->bmiHeader.biSizeImage = GetBitmapSize(&pVideoInfo->bmiHeader);
2471  }
2472  return NOERROR;
2473 }
2474 
2475 
2476 // Lots of video rendering filters want code to check proposed formats are ok
2477 // This checks the VIDEOINFO we are passed as a media type. If the media type
2478 // is a valid media type then we return NOERROR otherwise E_INVALIDARG. Note
2479 // however we only accept formats that can be easily displayed in the display
2480 // so if we are on a 16 bit device we will not accept 24 bit images. The one
2481 // complexity is that most displays draw 8 bit palettised images efficiently
2482 // Also if the input format is less colour bits per pixel then we also accept
2483 
2484 HRESULT CImageDisplay::CheckVideoType(const VIDEOINFO *pInput)
2485 {
2486  // First of all check the VIDEOINFOHEADER looks correct
2487 
2488  if (CheckHeaderValidity(pInput) == FALSE) {
2489  return E_INVALIDARG;
2490  }
2491 
2492  // Virtually all devices support palettised images efficiently
2493 
2494  if (m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount) {
2495  if (PALETTISED(pInput) == TRUE) {
2496  ASSERT(PALETTISED(&m_Display) == TRUE);
2497  NOTE("(Video) Type connection ACCEPTED");
2498  return NOERROR;
2499  }
2500  }
2501 
2502 
2503  // Is the display depth greater than the input format
2504 
2505  if (m_Display.bmiHeader.biBitCount > pInput->bmiHeader.biBitCount) {
2506  NOTE("(Video) Mismatch agreed");
2507  return NOERROR;
2508  }
2509 
2510  // Is the display depth less than the input format
2511 
2512  if (m_Display.bmiHeader.biBitCount < pInput->bmiHeader.biBitCount) {
2513  NOTE("(Video) Format mismatch");
2514  return E_INVALIDARG;
2515  }
2516 
2517 
2518  // Both input and display formats are either BI_RGB or BI_BITFIELDS
2519 
2520  ASSERT(m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount);
2521  ASSERT(PALETTISED(pInput) == FALSE);
2522  ASSERT(PALETTISED(&m_Display) == FALSE);
2523 
2524  // BI_RGB 16 bit representation is implicitly RGB555, and likewise BI_RGB
2525  // 24 bit representation is RGB888. So we initialise a pointer to the bit
2526  // fields they really mean and check against the display device format
2527  // This is only going to be called when both formats are equal bits pixel
2528 
2529  const DWORD *pInputMask = GetBitMasks(pInput);
2530  const DWORD *pDisplayMask = GetBitMasks((VIDEOINFO *)&m_Display);
2531 
2532  if (pInputMask[iRED] != pDisplayMask[iRED] ||
2533  pInputMask[iGREEN] != pDisplayMask[iGREEN] ||
2534  pInputMask[iBLUE] != pDisplayMask[iBLUE]) {
2535 
2536  NOTE("(Video) Bit field mismatch");
2537  return E_INVALIDARG;
2538  }
2539 
2540  NOTE("(Video) Type connection ACCEPTED");
2541  return NOERROR;
2542 }
2543 
2544 
2545 // Return the bit masks for the true colour VIDEOINFO provided
2546 
2547 const DWORD *CImageDisplay::GetBitMasks(const VIDEOINFO *pVideoInfo)
2548 {
2549  static const DWORD FailMasks[] = {0,0,0};
2550 
2551  if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) {
2552  return BITMASKS(pVideoInfo);
2553  }
2554 
2555  ASSERT(pVideoInfo->bmiHeader.biCompression == BI_RGB);
2556 
2557  switch (pVideoInfo->bmiHeader.biBitCount) {
2558  case 16: return bits555;
2559  case 24: return bits888;
2560  case 32: return bits888;
2561  default: return FailMasks;
2562  }
2563 }
2564 
2565 
2566 // Check to see if we can support media type pmtIn as proposed by the output
2567 // pin - We first check that the major media type is video and also identify
2568 // the media sub type. Then we thoroughly check the VIDEOINFO type provided
2569 // As well as the contained VIDEOINFO being correct the major type must be
2570 // video, the subtype a recognised video format and the type GUID correct
2571 
2573 {
2574  // Does this have a VIDEOINFOHEADER format block
2575 
2576  const GUID *pFormatType = pmtIn->FormatType();
2577  if (*pFormatType != FORMAT_VideoInfo) {
2578  NOTE("Format GUID not a VIDEOINFOHEADER");
2579  return E_INVALIDARG;
2580  }
2581  ASSERT(pmtIn->Format());
2582 
2583  // Check the format looks reasonably ok
2584 
2585  ULONG Length = pmtIn->FormatLength();
2586  if (Length < SIZE_VIDEOHEADER) {
2587  NOTE("Format smaller than a VIDEOHEADER");
2588  return E_FAIL;
2589  }
2590 
2591  VIDEOINFO *pInput = (VIDEOINFO *) pmtIn->Format();
2592 
2593  // Check the major type is MEDIATYPE_Video
2594 
2595  const GUID *pMajorType = pmtIn->Type();
2596  if (*pMajorType != MEDIATYPE_Video) {
2597  NOTE("Major type not MEDIATYPE_Video");
2598  return E_INVALIDARG;
2599  }
2600 
2601  // Check we can identify the media subtype
2602 
2603  const GUID *pSubType = pmtIn->Subtype();
2604  if (GetBitCount(pSubType) == USHRT_MAX) {
2605  NOTE("Invalid video media subtype");
2606  return E_INVALIDARG;
2607  }
2608  return CheckVideoType(pInput);
2609 }
2610 
2611 
2612 // Given a video format described by a VIDEOINFO structure we return the mask
2613 // that is used to obtain the range of acceptable colours for this type, for
2614 // example, the mask for a 24 bit true colour format is 0xFF in all cases. A
2615 // 16 bit 5:6:5 display format uses 0xF8, 0xFC and 0xF8, therefore given any
2616 // RGB triplets we can AND them with these fields to find one that is valid
2617 
2618 BOOL CImageDisplay::GetColourMask(__out DWORD *pMaskRed,
2619  __out DWORD *pMaskGreen,
2620  __out DWORD *pMaskBlue)
2621 {
2622  CAutoLock cDisplayLock(this);
2623  *pMaskRed = 0xFF;
2624  *pMaskGreen = 0xFF;
2625  *pMaskBlue = 0xFF;
2626 
2627  // If this format is palettised then it doesn't have bit fields
2628 
2629  if (m_Display.bmiHeader.biBitCount < 16) {
2630  return FALSE;
2631  }
2632 
2633  // If this is a 24 bit true colour display then it can handle all the
2634  // possible colour component ranges described by a byte. It is never
2635  // allowed for a 24 bit colour depth image to have BI_BITFIELDS set
2636 
2637  if (m_Display.bmiHeader.biBitCount == 24) {
2638  ASSERT(m_Display.bmiHeader.biCompression == BI_RGB);
2639  return TRUE;
2640  }
2641 
2642  // Calculate the mask based on the format's bit fields
2643 
2644  const DWORD *pBitFields = (DWORD *) GetBitMasks((VIDEOINFO *)&m_Display);
2645  DWORD *pOutputMask[] = { pMaskRed, pMaskGreen, pMaskBlue };
2646 
2647  // We know from earlier testing that there are no more than iMAXBITS
2648  // bits set in the mask and that they are all contiguous. All that
2649  // therefore remains is to shift them into the correct position
2650 
2651  for (INT iColour = iRED;iColour <= iBLUE;iColour++) {
2652 
2653  // This works out how many bits there are and where they live
2654 
2655  DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]);
2656  DWORD SetBits = CountSetBits(pBitFields[iColour]);
2657 
2658  // The first shift moves the bit field so that it is right justified
2659  // in the DWORD, after which we then shift it back left which then
2660  // puts the leading bit in the bytes most significant bit position
2661 
2662  *(pOutputMask[iColour]) = pBitFields[iColour] >> PrefixBits;
2663  *(pOutputMask[iColour]) <<= (iMAXBITS - SetBits);
2664  }
2665  return TRUE;
2666 }
2667 
2668 
2669 /* Helper to convert to VIDEOINFOHEADER2
2670 */
2671 STDAPI ConvertVideoInfoToVideoInfo2(__inout AM_MEDIA_TYPE *pmt)
2672 {
2673  if (pmt->formattype != FORMAT_VideoInfo) {
2674  return E_INVALIDARG;
2675  }
2676  if (NULL == pmt->pbFormat || pmt->cbFormat < sizeof(VIDEOINFOHEADER)) {
2677  return E_INVALIDARG;
2678  }
2679  VIDEOINFO *pVideoInfo = (VIDEOINFO *)pmt->pbFormat;
2680  DWORD dwNewSize;
2681  HRESULT hr = DWordAdd(pmt->cbFormat, sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER), &dwNewSize);
2682  if (FAILED(hr)) {
2683  return hr;
2684  }
2685  PVOID pvNew = CoTaskMemAlloc(dwNewSize);
2686  if (pvNew == NULL) {
2687  return E_OUTOFMEMORY;
2688  }
2689  CopyMemory(pvNew, pmt->pbFormat, FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader));
2690  ZeroMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader),
2691  sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER));
2692  CopyMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader),
2693  pmt->pbFormat + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader),
2694  pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader));
2695  VIDEOINFOHEADER2 *pVideoInfo2 = (VIDEOINFOHEADER2 *)pvNew;
2696  pVideoInfo2->dwPictAspectRatioX = (DWORD)pVideoInfo2->bmiHeader.biWidth;
2697  pVideoInfo2->dwPictAspectRatioY = (DWORD)abs(pVideoInfo2->bmiHeader.biHeight);
2698  pmt->formattype = FORMAT_VideoInfo2;
2699  CoTaskMemFree(pmt->pbFormat);
2700  pmt->pbFormat = (PBYTE)pvNew;
2701  pmt->cbFormat += sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER);
2702  return S_OK;
2703 }
2704 
2705 
2706 // Check a media type containing VIDEOINFOHEADER
2707 STDAPI CheckVideoInfoType(const AM_MEDIA_TYPE *pmt)
2708 {
2709  if (NULL == pmt || NULL == pmt->pbFormat) {
2710  return E_POINTER;
2711  }
2712  if (pmt->majortype != MEDIATYPE_Video ||
2713  pmt->formattype != FORMAT_VideoInfo ||
2714  pmt->cbFormat < sizeof(VIDEOINFOHEADER)) {
2715  return VFW_E_TYPE_NOT_ACCEPTED;
2716  }
2717  const VIDEOINFOHEADER *pHeader = (const VIDEOINFOHEADER *)pmt->pbFormat;
2718  if (!ValidateBitmapInfoHeader(
2719  &pHeader->bmiHeader,
2720  pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader))) {
2721  return VFW_E_TYPE_NOT_ACCEPTED;
2722  }
2723 
2724  return S_OK;
2725 }
2726 
2727 // Check a media type containing VIDEOINFOHEADER2
2728 STDAPI CheckVideoInfo2Type(const AM_MEDIA_TYPE *pmt)
2729 {
2730  if (NULL == pmt || NULL == pmt->pbFormat) {
2731  return E_POINTER;
2732  }
2733  if (pmt->majortype != MEDIATYPE_Video ||
2734  pmt->formattype != FORMAT_VideoInfo2 ||
2735  pmt->cbFormat < sizeof(VIDEOINFOHEADER2)) {
2736  return VFW_E_TYPE_NOT_ACCEPTED;
2737  }
2738  const VIDEOINFOHEADER2 *pHeader = (const VIDEOINFOHEADER2 *)pmt->pbFormat;
2739  if (!ValidateBitmapInfoHeader(
2740  &pHeader->bmiHeader,
2741  pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader))) {
2742  return VFW_E_TYPE_NOT_ACCEPTED;
2743  }
2744 
2745  return S_OK;
2746 }
CDrawImage::GetTargetRect
void GetTargetRect(__out RECT *pTargetRect)
Definition: winutil.cpp:1328
checkbmi.h
CBaseWindow::m_ClassStyles
DWORD m_ClassStyles
Definition: winutil.h:47
CImageDisplay::GetDisplayDepth
WORD GetDisplayDepth()
Definition: winutil.cpp:2429
CBaseWindow::WndProc
friend LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: winutil.cpp:416
CDrawImage::ScaleSourceRect
virtual RECT ScaleSourceRect(const RECT *pSource)
Definition: winutil.cpp:1009
CBaseWindow::m_ShowStageTop
UINT m_ShowStageTop
Definition: winutil.h:51
CBaseFilter::NotifyEvent
HRESULT NotifyEvent(long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
Definition: amfilter.cpp:811
CImageAllocator::Alloc
HRESULT Alloc()
Definition: winutil.cpp:1560
CMediaType::Format
BYTE * Format() const
Definition: mtype.h:55
CBaseAllocator::m_lCount
long m_lCount
Definition: amfilter.h:1430
CritCheckIn
#define CritCheckIn(x)
Definition: wxutil.h:75
CImageAllocator::Free
void Free()
Definition: winutil.cpp:1476
HANDLE
short HANDLE
Definition: ajatypes.h:338
CBaseWindow::DoneWithWindow
virtual HRESULT DoneWithWindow()
Definition: winutil.cpp:113
CImageAllocator::CreateDIB
HRESULT CreateDIB(LONG InSize, DIBDATA &DibData)
Definition: winutil.cpp:1636
STDMETHODIMP_
STDMETHODIMP_(ULONG) CImageAllocator
Definition: winutil.cpp:1701
CImageAllocator::CreateImageSample
virtual CImageSample * CreateImageSample(__in_bcount(Length) LPBYTE pData, LONG Length)
Definition: winutil.cpp:1611
CBaseAllocator::m_lAllocated
long m_lAllocated
Definition: amfilter.h:1431
tagDIBDATA::DibSection
DIBSECTION DibSection
Definition: winutil.h:234
ConvertVideoInfoToVideoInfo2
STDAPI ConvertVideoInfoToVideoInfo2(__inout AM_MEDIA_TYPE *pmt)
Definition: winutil.cpp:2671
DEFWIDTH
const int DEFWIDTH
Definition: winutil.h:20
CBaseWindow::DoRealisePalette
virtual HRESULT DoRealisePalette(BOOL bForceBackground=FALSE)
Definition: winutil.cpp:376
CMediaType::Type
const GUID * Type() const
Definition: mtype.h:39
streams.h
NULL
#define NULL
Definition: ntv2caption608types.h:19
CDrawImage::NotifyStartDraw
void NotifyStartDraw()
Definition: winutil.h:215
CBaseWindow::GetWindowHWND
HWND GetWindowHWND()
Definition: winutil.cpp:844
CBaseWindow::m_hdc
HDC m_hdc
Definition: winutil.h:42
NUMELMS
#define NUMELMS(aa)
Definition: types.h:430
lstrcmpiLocaleIndependentA
__inline int lstrcmpiLocaleIndependentA(LPCSTR lpsz1, LPCSTR lpsz2)
Definition: wxutil.h:527
CDrawImage::NotifyEndDraw
void NotifyEndDraw()
Definition: winutil.h:221
CDrawImage::IncrementPaletteVersion
void IncrementPaletteVersion()
Definition: winutil.cpp:1433
LOG_TRACE
@ LOG_TRACE
Definition: wxdebug.h:45
CCritSec::Unlock
void Unlock()
Definition: wxutil.h:52
CBaseWindow::GetWindowWidth
LONG GetWindowWidth()
Definition: winutil.cpp:824
DbgBreak
#define DbgBreak(_x_)
Definition: wxdebug.h:201
NAME
#define NAME(_x_)
Definition: wxdebug.h:179
CImageDisplay::CheckVideoType
HRESULT CheckVideoType(const VIDEOINFO *pInput)
Definition: winutil.cpp:2484
MsgDestroy
static UINT MsgDestroy
Definition: winutil.cpp:16
CImageDisplay::GetBitMasks
const DWORD * GetBitMasks(const VIDEOINFO *pVideoInfo)
Definition: winutil.cpp:2547
CBaseWindow::PerformanceAlignWindow
HRESULT PerformanceAlignWindow()
Definition: winutil.cpp:276
CBaseWindow::WindowExists
bool WindowExists()
Definition: winutil.cpp:805
CImageSample
Definition: winutil.h:248
CBaseWindow::m_hPalette
HPALETTE m_hPalette
Definition: winutil.h:54
CBaseWindow::DoSetWindowForeground
void DoSetWindowForeground(BOOL bFocus)
Definition: winutil.cpp:908
CAutoLock
Definition: wxutil.h:83
CBaseWindow::UnlockPaletteLock
void UnlockPaletteLock()
Definition: winutil.cpp:368
CBaseWindow::DoShowWindow
HRESULT DoShowWindow(LONG ShowCmd)
Definition: winutil.cpp:887
CBaseWindow::m_bActivated
BOOL m_bActivated
Definition: winutil.h:45
CImageAllocator::SetProperties
STDMETHODIMP SetProperties(__in ALLOCATOR_PROPERTIES *pRequest, __out ALLOCATOR_PROPERTIES *pActual)
Definition: winutil.cpp:1536
CImagePalette::MakePalette
static HPALETTE MakePalette(const VIDEOINFOHEADER *pVideoInfo, __in LPSTR szDevice)
Definition: winutil.cpp:2016
CBaseWindow
Definition: winutil.h:36
CImagePalette::CImagePalette
CImagePalette(__inout CBaseFilter *pBaseFilter, __inout CBaseWindow *pBaseWindow, __inout CDrawImage *pDrawImage)
Definition: winutil.cpp:1772
AmGetLastErrorToHResult
HRESULT AmGetLastErrorToHResult()
Definition: wxutil.cpp:688
CImageDisplay::CImageDisplay
CImageDisplay()
Definition: winutil.cpp:2150
CBaseWindow::LockPaletteLock
void LockPaletteLock()
Definition: winutil.cpp:362
CImagePalette::m_pFilter
CBaseFilter * m_pFilter
Definition: winutil.h:332
g_hInst
HINSTANCE g_hInst
Definition: dllentry.cpp:28
SHOWSTAGETOP
#define SHOWSTAGETOP
Definition: winutil.h:33
CMediaType
Definition: mtype.h:18
CDrawImage::GetSourceRect
void GetSourceRect(__out RECT *pSourceRect)
Definition: winutil.cpp:1350
CImageAllocator::m_pMediaType
CMediaType * m_pMediaType
Definition: winutil.h:284
CBaseWindow::m_bDoGetDC
BOOL m_bDoGetDC
Definition: winutil.h:59
NOTE
#define NOTE(_x_)
Definition: wxdebug.h:211
nlohmann::json_abiNLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON_v3_11_NLOHMANN_JSON_VERSION_PATCH::detail::void
j template void())
Definition: json.hpp:4893
CBaseWindow::m_PaletteLock
CCritSec m_PaletteLock
Definition: winutil.h:61
CImageDisplay::GetDisplayFormat
const VIDEOINFO * GetDisplayFormat()
Definition: winutil.cpp:2413
CBaseWindow::m_bBackground
BYTE m_bBackground
Definition: winutil.h:56
CImageDisplay::GetColourMask
BOOL GetColourMask(__out DWORD *pMaskRed, __out DWORD *pMaskGreen, __out DWORD *pMaskBlue)
Definition: winutil.cpp:2618
CBaseAllocator::SetProperties
STDMETHODIMP SetProperties(__in ALLOCATOR_PROPERTIES *pRequest, __out ALLOCATOR_PROPERTIES *pActual)
Definition: amfilter.cpp:4663
CImageSample::GetDIBData
__out DIBDATA * GetDIBData()
Definition: winutil.cpp:1756
_SetWindowLongPtr
LONG_PTR _SetWindowLongPtr(HWND hwnd, int nIndex, T p)
Definition: streams.h:141
CImageDisplay::m_Display
VIDEOINFO m_Display
Definition: winutil.h:376
CImageSample::m_bInit
BOOL m_bInit
Definition: winutil.h:253
CImagePalette::CopyPalette
HRESULT CopyPalette(const CMediaType *pSrc, __out CMediaType *pDest)
Definition: winutil.cpp:1916
CImageDisplay::RefreshDisplayType
HRESULT RefreshDisplayType(__in_opt LPSTR szDeviceName)
Definition: winutil.cpp:2166
CBaseWindow::GetWindowHeight
LONG GetWindowHeight()
Definition: winutil.cpp:834
CDrawImage::SetSourceRect
void SetSourceRect(__in RECT *pSourceRect)
Definition: winutil.cpp:1340
CBaseWindow::PaintWindow
void PaintWindow(BOOL bErase)
Definition: winutil.cpp:896
tagDIBDATA::PaletteVersion
LONG PaletteVersion
Definition: winutil.h:233
CBaseWindow::SetPalette
virtual HRESULT SetPalette(HPALETTE hPalette)
Definition: winutil.cpp:313
CBaseAllocator::m_lSize
long m_lSize
Definition: amfilter.h:1432
DbgCheckModuleLevel
#define DbgCheckModuleLevel(Type, Level)
Definition: wxdebug.h:191
CDrawImage::m_PaletteVersion
LONG m_PaletteVersion
Definition: winutil.h:176
CDrawImage::m_SourceRect
RECT m_SourceRect
Definition: winutil.h:171
CImageDisplay::CountSetBits
static DWORD CountSetBits(const DWORD Field)
Definition: winutil.cpp:2257
tagDIBDATA::hMapping
HANDLE hMapping
Definition: winutil.h:236
CDrawImage::m_perfidRenderTime
int m_perfidRenderTime
Definition: winutil.h:175
LOG_ERROR
@ LOG_ERROR
Definition: wxdebug.h:48
CImagePalette::ShouldUpdate
BOOL ShouldUpdate(const VIDEOINFOHEADER *pNewInfo, const VIDEOINFOHEADER *pOldInfo)
Definition: winutil.cpp:1802
pName
CHAR * pName
Definition: amvideo.cpp:26
CMediaType::FormatType
const GUID * FormatType() const
Definition: mtype.h:59
CBaseWindow::OnPaletteChange
virtual LRESULT OnPaletteChange(HWND hwnd, UINT Message)
Definition: winutil.cpp:763
CImagePalette::m_pDrawImage
CDrawImage * m_pDrawImage
Definition: winutil.h:333
CBaseWindow::GetDefaultRect
virtual RECT GetDefaultRect()
Definition: winutil.cpp:813
WndProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: winutil.cpp:416
DbgLog
#define DbgLog(_x_)
Definition: wxdebug.h:183
CBaseWindow::m_Height
LONG m_Height
Definition: winutil.h:44
CDrawImage::DrawVideoImageHere
BOOL DrawVideoImageHere(HDC hdc, IMediaSample *pMediaSample, __in LPRECT lprcSrc, __in LPRECT lprcDst)
Definition: winutil.cpp:1244
CDrawImage::m_bStretch
BOOL m_bStretch
Definition: winutil.h:172
CBaseWindow::OnSize
virtual BOOL OnSize(LONG Width, LONG Height)
Definition: winutil.cpp:487
CDrawImage::CDrawImage
CDrawImage(__inout CBaseWindow *pBaseWindow)
Definition: winutil.cpp:919
CImageDisplay::CheckPaletteHeader
static BOOL CheckPaletteHeader(const VIDEOINFO *pInput)
Definition: winutil.cpp:2375
CBaseWindow::InitialiseWindow
virtual HRESULT InitialiseWindow(HWND hwnd)
Definition: winutil.cpp:550
CBaseWindow::InactivateWindow
virtual HRESULT InactivateWindow()
Definition: winutil.cpp:206
CDrawImage::SetStretchMode
void SetStretchMode()
Definition: winutil.cpp:1362
TIMELENGTH
const int TIMELENGTH
Definition: winutil.h:23
CAMEvent
Definition: wxutil.h:108
PVOID
void * PVOID
Definition: ajatypes.h:339
CDrawImage::m_hdc
HDC m_hdc
Definition: winutil.h:168
CDrawImage::m_pMediaType
CMediaType * m_pMediaType
Definition: winutil.h:174
WaitDispatchingMessages
DWORD WINAPI WaitDispatchingMessages(HANDLE hObject, DWORD dwWait, HWND hwnd, UINT uMsg, HANDLE hEvent)
Definition: wxutil.cpp:594
tagDIBDATA::hBitmap
HBITMAP hBitmap
Definition: winutil.h:235
CDrawImage::m_StartSample
CRefTime m_StartSample
Definition: winutil.h:166
CMediaSample
Definition: amfilter.h:1185
CRefTime::Millisecs
LONG Millisecs(void)
Definition: reftime.h:102
CopyMemory
#define CopyMemory(a, b, c)
Definition: ntv2baremetaldriverinterface.h:16
CBaseAllocator::m_bCommitted
BOOL m_bCommitted
Definition: amfilter.h:1438
CImagePalette::PreparePalette
HRESULT PreparePalette(const CMediaType *pmtNew, const CMediaType *pmtOld, __in LPSTR szDevice)
Definition: winutil.cpp:1845
CBaseWindow::GetClassWindowStyles
virtual LPTSTR GetClassWindowStyles(__out DWORD *pClassStyles, __out DWORD *pWindowStyles, __out DWORD *pWindowStylesEx) PURE
CImageDisplay::CheckMediaType
HRESULT CheckMediaType(const CMediaType *pmtIn)
Definition: winutil.cpp:2572
CDrawImage
Definition: winutil.h:161
MSR_REGISTER
#define MSR_REGISTER(a)
Definition: measure.h:134
CImageDisplay::CheckBitFields
static BOOL CheckBitFields(const VIDEOINFO *pInput)
Definition: winutil.cpp:2220
CBaseAllocator::Alloc
virtual HRESULT Alloc(void)
Definition: amfilter.cpp:4973
CBaseWindow::m_bRealizing
BYTE m_bRealizing
Definition: winutil.h:57
CDrawImage::SetDrawContext
void SetDrawContext()
Definition: winutil.cpp:1307
PALVERSION
const WORD PALVERSION
Definition: winutil.h:25
EXECUTE_ASSERT
#define EXECUTE_ASSERT(_x_)
Definition: wxdebug.h:207
CBaseWindow::PossiblyEatMessage
virtual BOOL PossiblyEatMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: winutil.h:112
CBaseWindow::m_WindowStylesEx
DWORD m_WindowStylesEx
Definition: winutil.h:49
CBaseWindow::SetPalette
HRESULT SetPalette()
Definition: winutil.cpp:326
tagDIBDATA::pBase
BYTE * pBase
Definition: winutil.h:237
CImageAllocator::CImageAllocator
CImageAllocator(__inout CBaseFilter *pFilter, __in_opt LPCTSTR pName, __inout HRESULT *phr)
Definition: winutil.cpp:1450
CDrawImage::m_pBaseWindow
CBaseWindow * m_pBaseWindow
Definition: winutil.h:165
CBaseWindow::m_WindowLock
CCritSec m_WindowLock
Definition: winutil.h:58
bits888
const DWORD bits888[]
Definition: amvideo.cpp:18
CImageSample::SetDIBData
void SetDIBData(__in DIBDATA *pDibData)
Definition: winutil.cpp:1746
CImageAllocator::NotifyMediaType
void NotifyMediaType(__in CMediaType *pMediaType)
Definition: winutil.cpp:1693
CDrawImage::UpdateColourTable
void UpdateColourTable(HDC hdc, __in BITMAPINFOHEADER *pbmi)
Definition: winutil.cpp:991
CImageAllocator::m_pFilter
CBaseFilter * m_pFilter
Definition: winutil.h:283
GetWindowLongPtr
#define GetWindowLongPtr
Definition: streams.h:88
CBaseWindow::DoCreateWindow
HRESULT DoCreateWindow()
Definition: winutil.cpp:569
NOTE1
#define NOTE1(_x_, a)
Definition: wxdebug.h:212
CImageDisplay::UpdateFormat
HRESULT UpdateFormat(__inout VIDEOINFO *pVideoInfo)
Definition: winutil.cpp:2443
CBaseWindow::UninitialiseWindow
virtual HRESULT UninitialiseWindow()
Definition: winutil.cpp:510
CBaseWindow::GetWindowHDC
HDC GetWindowHDC()
Definition: winutil.cpp:854
CBaseFilter
Definition: amfilter.h:148
CDrawImage::ResetPaletteVersion
void ResetPaletteVersion()
Definition: winutil.cpp:1425
CDrawImage::DisplaySampleTimes
void DisplaySampleTimes(IMediaSample *pSample)
Definition: winutil.cpp:941
ULONG
ULONG(__stdcall *_RegisterTraceGuids)(__in IN WMIDPREQUEST RequestAddress
CBaseWindow::PrepareWindow
virtual HRESULT PrepareWindow()
Definition: winutil.cpp:51
CBaseWindow::m_RealizePalette
UINT m_RealizePalette
Definition: winutil.h:52
CBaseWindow::m_bDoPostToDestroy
bool m_bDoPostToDestroy
Definition: winutil.h:60
CImagePalette::MakeIdentityPalette
static HRESULT MakeIdentityPalette(__inout_ecount_full(iColours) PALETTEENTRY *pEntry, INT iColours, __in LPSTR szDevice)
Definition: winutil.cpp:2070
CImagePalette::RemovePalette
HRESULT RemovePalette()
Definition: winutil.cpp:1977
bits555
const DWORD bits555[]
Definition: amvideo.cpp:16
CBaseWindow::m_hwnd
HWND m_hwnd
Definition: winutil.h:41
CImagePalette::m_hPalette
HPALETTE m_hPalette
Definition: winutil.h:334
CBaseWindow::GetMemoryHDC
HDC GetMemoryHDC()
Definition: winutil.cpp:864
CImageAllocator::CheckSizes
STDMETHODIMP CheckSizes(__in ALLOCATOR_PROPERTIES *pRequest)
Definition: winutil.cpp:1497
CBaseWindow::CBaseWindow
CBaseWindow(BOOL bDoGetDC=TRUE, bool bPostToDestroy=false)
Definition: winutil.cpp:20
CMediaType::Subtype
const GUID * Subtype() const
Definition: mtype.h:41
CDrawImage::m_TargetRect
RECT m_TargetRect
Definition: winutil.h:170
CBaseWindow::m_pClassName
LPTSTR m_pClassName
Definition: winutil.h:46
CImageDisplay::CheckHeaderValidity
static BOOL CheckHeaderValidity(const VIDEOINFO *pInput)
Definition: winutil.cpp:2305
CCritSec::Lock
void Lock()
Definition: wxutil.h:48
CDrawImage::m_bUsingImageAllocator
BOOL m_bUsingImageAllocator
Definition: winutil.h:173
CBaseWindow::m_ShowStageMessage
UINT m_ShowStageMessage
Definition: winutil.h:50
CDrawImage::NotifyAllocator
void NotifyAllocator(BOOL bUsingImageAllocator)
Definition: winutil.cpp:1387
CBaseWindow::ActivateWindow
virtual HRESULT ActivateWindow()
Definition: winutil.cpp:232
CBaseWindow::CompleteConnect
HRESULT CompleteConnect()
Definition: winutil.cpp:219
CBaseAllocator
Definition: amfilter.h:1339
CritCheckOut
#define CritCheckOut(x)
Definition: wxutil.h:76
CDrawImage::SetTargetRect
void SetTargetRect(__in RECT *pTargetRect)
Definition: winutil.cpp:1318
CDrawImage::DrawImage
BOOL DrawImage(IMediaSample *pMediaSample)
Definition: winutil.cpp:1217
CDrawImage::GetPaletteVersion
LONG GetPaletteVersion()
Definition: winutil.cpp:1417
CImageSample::CImageSample
CImageSample(__inout CBaseAllocator *pAllocator, __in_opt LPCTSTR pName, __inout HRESULT *phr, __in_bcount(length) LPBYTE pBuffer, LONG length)
Definition: winutil.cpp:1731
PALETTE_VERSION
const LONG PALETTE_VERSION
Definition: winutil.h:26
AmHresultFromWin32
#define AmHresultFromWin32(x)
Definition: wxutil.h:472
CBaseWindow::m_hInstance
HINSTANCE m_hInstance
Definition: winutil.h:40
CDrawImage::NotifyMediaType
void NotifyMediaType(__in CMediaType *pMediaType)
Definition: winutil.cpp:1405
CImageDisplay::CountPrefixBits
static DWORD CountPrefixBits(const DWORD Field)
Definition: winutil.cpp:2278
DEFHEIGHT
const int DEFHEIGHT
Definition: winutil.h:21
CMediaType::FormatLength
ULONG FormatLength() const
Definition: mtype.h:56
CheckVideoInfoType
STDAPI CheckVideoInfoType(const AM_MEDIA_TYPE *pmt)
Definition: winutil.cpp:2707
CImageSample::m_DibData
DIBDATA m_DibData
Definition: winutil.h:252
CDrawImage::m_MemoryDC
HDC m_MemoryDC
Definition: winutil.h:169
SHOWSTAGE
#define SHOWSTAGE
Definition: winutil.h:32
REALIZEPALETTE
#define REALIZEPALETTE
Definition: winutil.h:34
CBaseWindow::UnsetPalette
void UnsetPalette(void)
Definition: winutil.cpp:345
CDrawImage::FastRender
void FastRender(IMediaSample *pMediaSample)
Definition: winutil.cpp:1023
CBaseWindow::m_WindowStyles
DWORD m_WindowStyles
Definition: winutil.h:48
CBaseWindow::OnReceiveMessage
virtual LRESULT OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: winutil.cpp:653
HEIGHT
#define HEIGHT(x)
Definition: winutil.h:31
CDrawImage::SlowRender
void SlowRender(IMediaSample *pMediaSample)
Definition: winutil.cpp:1126
CheckVideoInfo2Type
STDAPI CheckVideoInfo2Type(const AM_MEDIA_TYPE *pmt)
Definition: winutil.cpp:2728
CImagePalette::m_pBaseWindow
CBaseWindow * m_pBaseWindow
Definition: winutil.h:331
tagDIBDATA
Definition: winutil.h:231
CImageDisplay::IsPalettised
BOOL IsPalettised()
Definition: winutil.cpp:2421
CDrawImage::m_EndSample
CRefTime m_EndSample
Definition: winutil.h:167
CBaseWindow::OnClose
virtual BOOL OnClose()
Definition: winutil.cpp:497
ASSERT
#define ASSERT(_x_)
Definition: wxdebug.h:205
CBaseAllocator::m_lFree
CSampleList m_lFree
Definition: amfilter.h:1390
CBaseWindow::m_MemoryDC
HDC m_MemoryDC
Definition: winutil.h:53
hr
__out HRESULT & hr
Definition: pstream.cpp:145
CDrawImage::UsingImageAllocator
BOOL UsingImageAllocator()
Definition: winutil.cpp:1395
CBaseWindow::m_bNoRealize
BYTE m_bNoRealize
Definition: winutil.h:55
WIDTH
#define WIDTH(x)
Definition: winutil.h:30
CBaseWindow::m_Width
LONG m_Width
Definition: winutil.h:43
hMEMORY
const HANDLE hMEMORY
Definition: winutil.h:28
if
if(!(riid==IID_IUnknown) &&!(riid==IID_IClassFactory))
Definition: dllentry.cpp:196