00001
00002
00003
00004
00005
00006 #include <streams.h>
00007 #include <limits.h>
00008 #include <dvdmedia.h>
00009
00010 static UINT MsgDestroy;
00011
00012 CBaseWindow::CBaseWindow(BOOL bDoGetDC, bool bDoPostToDestroy) :
00013 m_hInstance(g_hInst),
00014 m_hwnd(NULL),
00015 m_hdc(NULL),
00016 m_bActivated(FALSE),
00017 m_pClassName(NULL),
00018 m_ClassStyles(0),
00019 m_WindowStyles(0),
00020 m_WindowStylesEx(0),
00021 m_ShowStageMessage(0),
00022 m_ShowStageTop(0),
00023 m_MemoryDC(NULL),
00024 m_hPalette(NULL),
00025 m_bBackground(FALSE),
00026 #ifdef DEBUG
00027 m_bRealizing(FALSE),
00028 #endif
00029 m_bNoRealize(FALSE),
00030 m_bDoPostToDestroy(bDoPostToDestroy)
00031 {
00032 m_bDoGetDC = bDoGetDC;
00033 }
00034
00035 HRESULT CBaseWindow::PrepareWindow()
00036 {
00037 if (m_hwnd) return NOERROR;
00038 ASSERT(m_hwnd == NULL);
00039 ASSERT(m_hdc == NULL);
00040
00041
00042
00043 m_pClassName = GetClassWindowStyles(&m_ClassStyles,
00044 &m_WindowStyles,
00045 &m_WindowStylesEx);
00046 if (m_pClassName == NULL) {
00047 return E_FAIL;
00048 }
00049
00050
00051 m_ShowStageMessage = RegisterWindowMessage(SHOWSTAGE);
00052 m_ShowStageTop = RegisterWindowMessage(SHOWSTAGETOP);
00053 m_RealizePalette = RegisterWindowMessage(REALIZEPALETTE);
00054
00055 return DoCreateWindow();
00056 }
00057
00058 #ifdef DEBUG
00059 CBaseWindow::~CBaseWindow()
00060 {
00061 ASSERT(m_hwnd == NULL);
00062 ASSERT(m_hdc == NULL);
00063 }
00064 #endif
00065
00066 HRESULT CBaseWindow::DoneWithWindow()
00067 {
00068
00069
00070
00071
00072
00073
00074
00075 if (!IsWindow(m_hwnd)) {
00076
00077
00078
00079
00080
00081
00082 m_hdc = NULL;
00083
00084
00085
00086
00087
00088 if (m_MemoryDC)
00089 {
00090 EXECUTE_ASSERT(DeleteDC(m_MemoryDC));
00091 m_MemoryDC = NULL;
00092 }
00093
00094
00095 m_hwnd = NULL;
00096 return NOERROR;
00097 }
00098
00099 if (GetWindowThreadProcessId(m_hwnd, NULL) != GetCurrentThreadId()) {
00100 CAMEvent m_evDone;
00101
00102
00103
00104
00105
00106 MsgDestroy = RegisterWindowMessage(TEXT("AM_DESTROY"));
00107 if (m_bDoPostToDestroy) {
00108 PostMessage(m_hwnd, MsgDestroy, (WPARAM)(HANDLE)m_evDone, 0);
00109 WaitDispatchingMessages(m_evDone, INFINITE);
00110 } else {
00111 SendMessage(m_hwnd, MsgDestroy, 0, 0);
00112 }
00113 return NOERROR;
00114 }
00115 const HWND hwnd = m_hwnd;
00116 if (hwnd == NULL) {
00117 return NOERROR;
00118 }
00119
00120 InactivateWindow();
00121 NOTE("Inactivated");
00122
00123
00124
00125 SetWindowLong(hwnd,GWL_STYLE,m_WindowStyles);
00126 ASSERT(GetParent(hwnd) == NULL);
00127 NOTE1("Reset window styles %d",m_WindowStyles);
00128
00129
00130 UninitialiseWindow();
00131 DbgLog((LOG_TRACE, 2, TEXT("Destroying 0x%8.8X"), hwnd));
00132 if (!DestroyWindow(hwnd)) {
00133 DbgLog((LOG_TRACE, 0, TEXT("DestroyWindow %8.8X failed code %d"),
00134 hwnd, GetLastError()));
00135 DbgBreak("");
00136 }
00137
00138
00139
00140 m_pClassName = NULL;
00141 m_ClassStyles = 0;
00142 m_WindowStyles = 0;
00143 m_WindowStylesEx = 0;
00144 m_ShowStageMessage = 0;
00145 m_ShowStageTop = 0;
00146
00147 return NOERROR;
00148 }
00149
00150 HRESULT CBaseWindow::InactivateWindow()
00151 {
00152
00153 if (m_bActivated == FALSE) {
00154 return S_FALSE;
00155 }
00156
00157 m_bActivated = FALSE;
00158 ShowWindow(m_hwnd,SW_HIDE);
00159 return NOERROR;
00160 }
00161
00162 HRESULT CBaseWindow::CompleteConnect()
00163 {
00164 m_bActivated = FALSE;
00165 return NOERROR;
00166 }
00167
00168 HRESULT CBaseWindow::ActivateWindow()
00169 {
00170
00171
00172 if (m_bActivated == TRUE || GetParent(m_hwnd) != NULL) {
00173
00174 SetWindowPos(m_hwnd,
00175 HWND_TOP,
00176 0, 0, 0, 0,
00177 SWP_NOMOVE |
00178 SWP_NOSIZE);
00179
00180 m_bActivated = TRUE;
00181 return S_FALSE;
00182 }
00183
00184
00185
00186 RECT WindowRect, ClientRect = GetDefaultRect();
00187 GetWindowRect(m_hwnd,&WindowRect);
00188 AdjustWindowRectEx(&ClientRect,GetWindowLong(m_hwnd,GWL_STYLE),
00189 FALSE,GetWindowLong(m_hwnd,GWL_EXSTYLE));
00190
00191
00192
00193 UINT WindowFlags = (SWP_NOACTIVATE | SWP_FRAMECHANGED);
00194 WindowRect.left -= (WindowRect.left & 3);
00195 WindowRect.top -= (WindowRect.top & 3);
00196
00197 SetWindowPos(m_hwnd,
00198 HWND_TOP,
00199 WindowRect.left,
00200 WindowRect.top,
00201 WIDTH(&ClientRect),
00202 HEIGHT(&ClientRect),
00203 WindowFlags);
00204
00205 m_bActivated = TRUE;
00206 return NOERROR;
00207 }
00208
00209 HRESULT CBaseWindow::PerformanceAlignWindow()
00210 {
00211 RECT ClientRect,WindowRect;
00212 GetWindowRect(m_hwnd,&WindowRect);
00213 ASSERT(m_bActivated == TRUE);
00214
00215
00216
00217 if (GetParent(m_hwnd)) {
00218 return NOERROR;
00219 }
00220
00221
00222
00223 GetClientRect(m_hwnd, &ClientRect);
00224 MapWindowPoints(m_hwnd, HWND_DESKTOP, (LPPOINT) &ClientRect, 2);
00225 WindowRect.left -= (ClientRect.left & 3);
00226 WindowRect.top -= (ClientRect.top & 3);
00227 UINT WindowFlags = (SWP_NOACTIVATE | SWP_NOSIZE);
00228
00229 SetWindowPos(m_hwnd,
00230 HWND_TOP,
00231 WindowRect.left,
00232 WindowRect.top,
00233 (int) 0,(int) 0,
00234 WindowFlags);
00235
00236 return NOERROR;
00237 }
00238
00239 HRESULT CBaseWindow::SetPalette(HPALETTE hPalette)
00240 {
00241
00242 {
00243 CAutoLock cWindowLock(&m_WindowLock);
00244 ASSERT(hPalette);
00245 m_hPalette = hPalette;
00246 }
00247 return SetPalette();
00248 }
00249
00250 HRESULT CBaseWindow::SetPalette()
00251 {
00252 if (!m_bNoRealize) {
00253 SendMessage(m_hwnd, m_RealizePalette, 0, 0);
00254
00255 return (GdiFlush() == FALSE ? S_FALSE : S_OK);
00256 } else {
00257
00258 ASSERT(m_hdc);
00259 ASSERT(m_MemoryDC);
00260 SelectPalette(m_hdc,m_hPalette,m_bBackground);
00261 SelectPalette(m_MemoryDC,m_hPalette,m_bBackground);
00262 return S_OK;
00263 }
00264 }
00265
00266 HRESULT CBaseWindow::DoRealisePalette(BOOL bForceBackground)
00267 {
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 if (m_hPalette == NULL) {
00280
00281 return NOERROR;
00282 }
00283
00284
00285 ASSERT(m_hdc);
00286 ASSERT(m_MemoryDC);
00287 SelectPalette(m_hdc,m_hPalette,m_bBackground || bForceBackground);
00288 EXECUTE_ASSERT(RealizePalette(m_hdc) != GDI_ERROR);
00289 SelectPalette(m_MemoryDC,m_hPalette,m_bBackground);
00290 EXECUTE_ASSERT(RealizePalette(m_MemoryDC) != GDI_ERROR);
00291
00292 return (GdiFlush() == FALSE ? S_FALSE : S_OK);
00293 }
00294
00295 LRESULT CALLBACK WndProc(HWND hwnd,
00296 UINT uMsg,
00297 WPARAM wParam,
00298 LPARAM lParam)
00299 {
00300
00301
00302
00303
00304
00305
00306
00307 CBaseWindow *pBaseWindow = (CBaseWindow *)GetWindowLongPtr(hwnd,0);
00308 if (pBaseWindow == NULL) {
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 if (uMsg == WM_NCCREATE) {
00320 SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~0x400000);
00321 }
00322
00323 if ((uMsg != WM_NCCREATE)
00324 || (NULL == (pBaseWindow = *(CBaseWindow**) ((LPCREATESTRUCT)lParam)->lpCreateParams)))
00325 {
00326 return(DefWindowProc(hwnd, uMsg, wParam, lParam));
00327 }
00328
00329
00330 #ifdef DEBUG
00331 SetLastError(0);
00332 #endif
00333 LONG_PTR rc = SetWindowLongPtr(hwnd, (DWORD) 0, (LONG_PTR) pBaseWindow);
00334 #ifdef DEBUG
00335 if (0 == rc) {
00336
00337
00338 LONG lasterror = GetLastError();
00339 ASSERT(0 == lasterror);
00340
00341
00342 }
00343 #endif
00344
00345 }
00346
00347 if (uMsg == MsgDestroy && uMsg != 0) {
00348 pBaseWindow->DoneWithWindow();
00349 if (pBaseWindow->m_bDoPostToDestroy) {
00350 EXECUTE_ASSERT(SetEvent((HANDLE)wParam));
00351 }
00352 return 0;
00353 }
00354 return pBaseWindow->OnReceiveMessage(hwnd,uMsg,wParam,lParam);
00355 }
00356
00357 BOOL CBaseWindow::OnSize(LONG Width, LONG Height)
00358 {
00359 m_Width = Width;
00360 m_Height = Height;
00361 return TRUE;
00362 }
00363
00364 BOOL CBaseWindow::OnClose()
00365 {
00366 ShowWindow(m_hwnd,SW_HIDE);
00367 return TRUE;
00368 }
00369
00370 HRESULT CBaseWindow::UninitialiseWindow()
00371 {
00372
00373
00374 if (m_hwnd == NULL) {
00375 ASSERT(m_hdc == NULL);
00376 ASSERT(m_MemoryDC == NULL);
00377 return NOERROR;
00378 }
00379
00380
00381
00382 EXECUTE_ASSERT(GdiFlush());
00383
00384 if (m_hdc)
00385 {
00386 EXECUTE_ASSERT(ReleaseDC(m_hwnd,m_hdc));
00387 m_hdc = NULL;
00388 }
00389
00390 if (m_MemoryDC)
00391 {
00392 EXECUTE_ASSERT(DeleteDC(m_MemoryDC));
00393 m_MemoryDC = NULL;
00394 }
00395
00396
00397 m_hwnd = NULL;
00398
00399 return NOERROR;
00400 }
00401
00402 HRESULT CBaseWindow::InitialiseWindow(HWND hwnd)
00403 {
00404
00405
00406 ASSERT(IsWindow(hwnd));
00407 m_hwnd = hwnd;
00408
00409 if (m_bDoGetDC)
00410 {
00411 EXECUTE_ASSERT(m_hdc = GetDC(hwnd));
00412 EXECUTE_ASSERT(m_MemoryDC = CreateCompatibleDC(m_hdc));
00413
00414 EXECUTE_ASSERT(SetStretchBltMode(m_hdc,COLORONCOLOR));
00415 EXECUTE_ASSERT(SetStretchBltMode(m_MemoryDC,COLORONCOLOR));
00416 }
00417
00418 return NOERROR;
00419 }
00420
00421 HRESULT CBaseWindow::DoCreateWindow()
00422 {
00423 WNDCLASS wndclass;
00424 BOOL bRegistered;
00425 HWND hwnd;
00426
00427 bRegistered = GetClassInfo(m_hInstance,
00428 m_pClassName,
00429 &wndclass);
00430
00431
00432
00433
00434
00435 if (m_bDoGetDC)
00436 {
00437 m_ClassStyles |= CS_OWNDC;
00438 }
00439
00440 if (bRegistered == FALSE) {
00441
00442
00443
00444 wndclass.lpszClassName = m_pClassName;
00445 wndclass.style = m_ClassStyles;
00446 wndclass.lpfnWndProc = WndProc;
00447 wndclass.cbClsExtra = 0;
00448 wndclass.cbWndExtra = sizeof(CBaseWindow *);
00449 wndclass.hInstance = m_hInstance;
00450 wndclass.hIcon = NULL;
00451 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
00452 wndclass.hbrBackground = (HBRUSH) NULL;
00453 wndclass.lpszMenuName = NULL;
00454
00455 RegisterClass(&wndclass);
00456 }
00457
00458
00459
00460
00461
00462 CBaseWindow *pBaseWindow = this;
00463 hwnd = CreateWindowEx(m_WindowStylesEx,
00464 m_pClassName,
00465 TEXT("ActiveMovie Window"),
00466 m_WindowStyles,
00467 CW_USEDEFAULT,
00468 CW_USEDEFAULT,
00469 DEFWIDTH,
00470 DEFHEIGHT,
00471 NULL,
00472 NULL,
00473 m_hInstance,
00474 &pBaseWindow);
00475
00476
00477
00478
00479
00480 if (hwnd == NULL) {
00481 DWORD Error = GetLastError();
00482 return AmHresultFromWin32(Error);
00483 }
00484
00485
00486 ASSERT(GetWindowLongPtr(hwnd, 0) == (LONG_PTR)this);
00487
00488
00489
00490
00491
00492
00493
00494 InitialiseWindow(hwnd);
00495
00496 DbgLog((LOG_TRACE, 2, TEXT("Created window class (%s) HWND(%8.8X)"),
00497 m_pClassName, hwnd));
00498
00499 return S_OK;
00500 }
00501
00502 LRESULT CBaseWindow::OnReceiveMessage(HWND hwnd,
00503 UINT uMsg,
00504 WPARAM wParam,
00505 LPARAM lParam)
00506 {
00507 ASSERT(IsWindow(hwnd));
00508
00509 if (PossiblyEatMessage(uMsg, wParam, lParam))
00510 return 0;
00511
00512
00513
00514
00515
00516
00517
00518 if (uMsg == m_ShowStageMessage) {
00519
00520 BOOL bVisible = IsWindowVisible(hwnd);
00521 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
00522 SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
00523 (bVisible ? SWP_NOACTIVATE : 0));
00524
00525
00526 if (wParam == TRUE) {
00527 SetForegroundWindow(hwnd);
00528 }
00529 return (LRESULT) 1;
00530 }
00531
00532
00533
00534
00535
00536
00537
00538 if (uMsg == m_ShowStageTop) {
00539 HWND HwndTop = (wParam == TRUE ? HWND_TOPMOST : HWND_NOTOPMOST);
00540 BOOL bVisible = IsWindowVisible(hwnd);
00541 SetWindowPos(hwnd, HwndTop, 0, 0, 0, 0,
00542 SWP_NOMOVE | SWP_NOSIZE |
00543 (wParam == TRUE ? SWP_SHOWWINDOW : 0) |
00544 (bVisible ? SWP_NOACTIVATE : 0));
00545 return (LRESULT) 1;
00546 }
00547
00548
00549 if (uMsg == m_RealizePalette) {
00550 ASSERT(m_hwnd == hwnd);
00551 return OnPaletteChange(m_hwnd,WM_QUERYNEWPALETTE);
00552 }
00553
00554 switch (uMsg) {
00555
00556
00557
00558 case WM_SYSCOLORCHANGE:
00559
00560 InvalidateRect(hwnd,NULL,FALSE);
00561 return (LRESULT) 1;
00562
00563
00564 case WM_PALETTECHANGED:
00565
00566 OnPaletteChange((HWND)wParam,uMsg);
00567 return (LRESULT) 0;
00568
00569
00570
00571
00572
00573 case WM_QUERYNEWPALETTE:
00574 ASSERT(m_hwnd == hwnd);
00575 return OnPaletteChange(m_hwnd,uMsg);
00576
00577
00578
00579
00580
00581 case WM_MOVE:
00582 if (IsWindowVisible(m_hwnd)) {
00583 PostMessage(m_hwnd,WM_PAINT,0,0);
00584 }
00585 break;
00586
00587
00588
00589 case WM_SIZE:
00590
00591 OnSize(LOWORD(lParam), HIWORD(lParam));
00592 return (LRESULT) 0;
00593
00594
00595
00596 case WM_CLOSE:
00597
00598 OnClose();
00599 return (LRESULT) 0;
00600 }
00601 return DefWindowProc(hwnd,uMsg,wParam,lParam);
00602 }
00603
00604 LRESULT CBaseWindow::OnPaletteChange(HWND hwnd,UINT Message)
00605 {
00606
00607
00608 if (m_hwnd == NULL || hwnd == NULL) {
00609 return (LRESULT) 0;
00610 }
00611 ASSERT(!m_bRealizing);
00612
00613
00614
00615 if ((Message == WM_QUERYNEWPALETTE || hwnd != m_hwnd)) {
00616
00617
00618
00619
00620 if (!IsWindowVisible(m_hwnd)) {
00621 DbgLog((LOG_TRACE, 1, TEXT("Realizing when invisible!")));
00622 return (LRESULT) 0;
00623 }
00624
00625
00626 #ifdef DEBUG
00627 m_bRealizing = TRUE;
00628 #endif
00629 DoRealisePalette(Message != WM_QUERYNEWPALETTE);
00630 #ifdef DEBUG
00631 m_bRealizing = FALSE;
00632 #endif
00633
00634
00635 if (Message == WM_PALETTECHANGED) {
00636 InvalidateRect(m_hwnd,NULL,FALSE);
00637 }
00638 }
00639
00640 return (LRESULT) 1;
00641 }
00642
00643 RECT CBaseWindow::GetDefaultRect()
00644 {
00645 RECT DefaultRect = {0,0,DEFWIDTH,DEFHEIGHT};
00646 ASSERT(m_hwnd);
00647
00648 return DefaultRect;
00649 }
00650
00651 LONG CBaseWindow::GetWindowWidth()
00652 {
00653 ASSERT(m_hwnd);
00654
00655 return m_Width;
00656 }
00657
00658 LONG CBaseWindow::GetWindowHeight()
00659 {
00660 ASSERT(m_hwnd);
00661
00662 return m_Height;
00663 }
00664
00665 HWND CBaseWindow::GetWindowHWND()
00666 {
00667 ASSERT(m_hwnd);
00668
00669 return m_hwnd;
00670 }
00671
00672 HDC CBaseWindow::GetWindowHDC()
00673 {
00674 ASSERT(m_hwnd);
00675 ASSERT(m_hdc);
00676 return m_hdc;
00677 }
00678
00679 HDC CBaseWindow::GetMemoryHDC()
00680 {
00681 ASSERT(m_hwnd);
00682 ASSERT(m_MemoryDC);
00683 return m_MemoryDC;
00684 }
00685
00686 HRESULT CBaseWindow::DoShowWindow(LONG ShowCmd)
00687 {
00688 ShowWindow(m_hwnd,ShowCmd);
00689 return NOERROR;
00690 }
00691
00692 void CBaseWindow::PaintWindow(BOOL bErase)
00693 {
00694 InvalidateRect(m_hwnd,NULL,bErase);
00695 }
00696
00697 void CBaseWindow::DoSetWindowForeground(BOOL bFocus)
00698 {
00699 SendMessage(m_hwnd,m_ShowStageMessage,(WPARAM) bFocus,(LPARAM) 0);
00700 }
00701
00702 CDrawImage::CDrawImage(CBaseWindow *pBaseWindow) :
00703 m_pBaseWindow(pBaseWindow),
00704 m_hdc(NULL),
00705 m_MemoryDC(NULL),
00706 m_bStretch(FALSE),
00707 m_pMediaType(NULL),
00708 m_bUsingImageAllocator(FALSE)
00709 {
00710 ASSERT(pBaseWindow);
00711 ResetPaletteVersion();
00712 SetRectEmpty(&m_TargetRect);
00713 SetRectEmpty(&m_SourceRect);
00714
00715 m_perfidRenderTime = MSR_REGISTER("Single Blt time");
00716 }
00717
00718 void CDrawImage::DisplaySampleTimes(IMediaSample *pSample)
00719 {
00720 TCHAR szTimes[TIMELENGTH];
00721 ASSERT(pSample);
00722 RECT ClientRect;
00723 SIZE Size;
00724
00725
00726
00727 pSample->GetTime((REFERENCE_TIME*)&m_StartSample, (REFERENCE_TIME*)&m_EndSample);
00728 HWND hwnd = m_pBaseWindow->GetWindowHWND();
00729 EXECUTE_ASSERT(GetClientRect(hwnd,&ClientRect));
00730
00731
00732
00733 wsprintf(szTimes,TEXT("%08d : %08d"),
00734 m_StartSample.Millisecs(),
00735 m_EndSample.Millisecs());
00736
00737 ASSERT(lstrlen(szTimes) < TIMELENGTH);
00738
00739
00740
00741 GetTextExtentPoint32(m_hdc,szTimes,lstrlen(szTimes),&Size);
00742 INT XPos = ((ClientRect.right - ClientRect.left) - Size.cx) / 2;
00743 INT YPos = ((ClientRect.bottom - ClientRect.top) - Size.cy) * 4 / 5;
00744
00745
00746
00747 if ((XPos > 0) && (YPos > 0)) {
00748 TextOut(m_hdc,XPos,YPos,szTimes,lstrlen(szTimes));
00749 }
00750 }
00751
00752 void CDrawImage::UpdateColourTable(HDC hdc,BITMAPINFOHEADER *pbmi)
00753 {
00754 ASSERT(pbmi->biClrUsed);
00755 RGBQUAD *pColourTable = (RGBQUAD *)(pbmi+1);
00756
00757
00758
00759 UINT uiReturn = SetDIBColorTable(hdc,(UINT) 0,
00760 pbmi->biClrUsed,
00761 pColourTable);
00762
00763
00764 ASSERT(uiReturn == pbmi->biClrUsed);
00765 }
00766
00767 RECT CDrawImage::ScaleSourceRect(const RECT *pSource)
00768 {
00769 ASSERT(pSource);
00770 return *pSource;
00771 }
00772
00773 void CDrawImage::FastRender(IMediaSample *pMediaSample)
00774 {
00775 BITMAPINFOHEADER *pbmi;
00776 DIBDATA *pDibData;
00777 BYTE *pImage;
00778 HBITMAP hOldBitmap;
00779 CImageSample *pSample;
00780
00781 ASSERT(m_pMediaType);
00782
00783
00784
00785
00786
00787 pbmi = HEADER(m_pMediaType->Format());
00788 pSample = (CImageSample *) pMediaSample;
00789 pDibData = pSample->GetDIBData();
00790 hOldBitmap = (HBITMAP) SelectObject(m_MemoryDC,pDibData->hBitmap);
00791
00792
00793
00794 HRESULT hr = pMediaSample->GetPointer(&pImage);
00795 if (FAILED(hr)) {
00796 return;
00797 }
00798
00799
00800
00801
00802
00803
00804
00805 if (pDibData->PaletteVersion < GetPaletteVersion()) {
00806 ASSERT(pbmi->biBitCount <= iPALETTE);
00807 UpdateColourTable(m_MemoryDC,pbmi);
00808 pDibData->PaletteVersion = GetPaletteVersion();
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818 RECT SourceRect = ScaleSourceRect(&m_SourceRect);
00819
00820
00821
00822 if (m_bStretch == FALSE) {
00823
00824
00825
00826 BitBlt(
00827 (HDC) m_hdc,
00828 m_TargetRect.left,
00829 m_TargetRect.top,
00830 m_TargetRect.right - m_TargetRect.left,
00831 m_TargetRect.bottom - m_TargetRect.top,
00832 m_MemoryDC,
00833 SourceRect.left,
00834 SourceRect.top,
00835 SRCCOPY);
00836
00837 } else {
00838
00839
00840
00841 StretchBlt(
00842 (HDC) m_hdc,
00843 m_TargetRect.left,
00844 m_TargetRect.top,
00845 m_TargetRect.right - m_TargetRect.left,
00846 m_TargetRect.bottom - m_TargetRect.top,
00847 m_MemoryDC,
00848 SourceRect.left,
00849 SourceRect.top,
00850 SourceRect.right - SourceRect.left,
00851 SourceRect.bottom - SourceRect.top,
00852 SRCCOPY);
00853 }
00854
00855
00856
00857
00858
00859 #ifdef DEBUG
00860 DisplaySampleTimes(pMediaSample);
00861 #endif
00862
00863
00864 SelectObject(m_MemoryDC,hOldBitmap);
00865 }
00866
00867 void CDrawImage::SlowRender(IMediaSample *pMediaSample)
00868 {
00869
00870
00871 ASSERT(m_pMediaType);
00872 BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format());
00873 BYTE *pImage;
00874
00875
00876
00877 HRESULT hr = pMediaSample->GetPointer(&pImage);
00878 if (FAILED(hr)) {
00879 return;
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889 RECT SourceRect = ScaleSourceRect(&m_SourceRect);
00890
00891 LONG lAdjustedSourceTop = SourceRect.top;
00892
00893
00894 if (pbmi->biHeight > 0) {
00895 lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom;
00896 }
00897
00898
00899 if (m_bStretch == FALSE) {
00900
00901
00902
00903 SetDIBitsToDevice(
00904 (HDC) m_hdc,
00905 m_TargetRect.left,
00906 m_TargetRect.top,
00907 m_TargetRect.right - m_TargetRect.left,
00908 m_TargetRect.bottom - m_TargetRect.top,
00909 SourceRect.left,
00910 lAdjustedSourceTop,
00911 (UINT) 0,
00912 pbmi->biHeight,
00913 pImage,
00914 (BITMAPINFO *) pbmi,
00915 DIB_RGB_COLORS);
00916
00917 } else {
00918
00919
00920
00921 StretchDIBits(
00922 (HDC) m_hdc,
00923 m_TargetRect.left,
00924 m_TargetRect.top,
00925 m_TargetRect.right - m_TargetRect.left,
00926 m_TargetRect.bottom - m_TargetRect.top,
00927 SourceRect.left,
00928 lAdjustedSourceTop,
00929 SourceRect.right - SourceRect.left,
00930 SourceRect.bottom - SourceRect.top,
00931 pImage,
00932 (BITMAPINFO *) pbmi,
00933 DIB_RGB_COLORS,
00934 SRCCOPY);
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 #ifdef DEBUG
00946 DisplaySampleTimes(pMediaSample);
00947 #endif
00948 }
00949
00950 BOOL CDrawImage::DrawImage(IMediaSample *pMediaSample)
00951 {
00952 ASSERT(m_hdc);
00953 ASSERT(m_MemoryDC);
00954 NotifyStartDraw();
00955
00956
00957
00958
00959
00960
00961 if (m_bUsingImageAllocator == FALSE) {
00962 SlowRender(pMediaSample);
00963 EXECUTE_ASSERT(GdiFlush());
00964 NotifyEndDraw();
00965 return TRUE;
00966 }
00967
00968
00969
00970 FastRender(pMediaSample);
00971 EXECUTE_ASSERT(GdiFlush());
00972 NotifyEndDraw();
00973 return TRUE;
00974 }
00975
00976 BOOL CDrawImage::DrawVideoImageHere(
00977 HDC hdc,
00978 IMediaSample *pMediaSample,
00979 LPRECT lprcSrc,
00980 LPRECT lprcDst
00981 )
00982 {
00983 ASSERT(m_pMediaType);
00984 BITMAPINFOHEADER *pbmi = HEADER(m_pMediaType->Format());
00985 BYTE *pImage;
00986
00987
00988
00989 HRESULT hr = pMediaSample->GetPointer(&pImage);
00990 if (FAILED(hr)) {
00991 return FALSE;
00992 }
00993
00994 RECT SourceRect;
00995 RECT TargetRect;
00996
00997 if (lprcSrc) {
00998 SourceRect = *lprcSrc;
00999 }
01000 else SourceRect = ScaleSourceRect(&m_SourceRect);
01001
01002 if (lprcDst) {
01003 TargetRect = *lprcDst;
01004 }
01005 else TargetRect = m_TargetRect;
01006
01007 LONG lAdjustedSourceTop = SourceRect.top;
01008
01009
01010 if (pbmi->biHeight > 0) {
01011 lAdjustedSourceTop = pbmi->biHeight - SourceRect.bottom;
01012 }
01013
01014
01015
01016 BOOL bRet = (0 != StretchDIBits(hdc,
01017 TargetRect.left,
01018 TargetRect.top,
01019 TargetRect.right - TargetRect.left,
01020 TargetRect.bottom - TargetRect.top,
01021 SourceRect.left,
01022 lAdjustedSourceTop,
01023 SourceRect.right - SourceRect.left,
01024 SourceRect.bottom - SourceRect.top,
01025 pImage,
01026 (BITMAPINFO *)pbmi,
01027 DIB_RGB_COLORS,
01028 SRCCOPY));
01029 return bRet;
01030 }
01031
01032 void CDrawImage::SetDrawContext()
01033 {
01034 m_MemoryDC = m_pBaseWindow->GetMemoryHDC();
01035 m_hdc = m_pBaseWindow->GetWindowHDC();
01036 }
01037
01038 void CDrawImage::SetTargetRect(RECT *pTargetRect)
01039 {
01040 ASSERT(pTargetRect);
01041 m_TargetRect = *pTargetRect;
01042 SetStretchMode();
01043 }
01044
01045 void CDrawImage::GetTargetRect(RECT *pTargetRect)
01046 {
01047 ASSERT(pTargetRect);
01048 *pTargetRect = m_TargetRect;
01049 }
01050
01051 void CDrawImage::SetSourceRect(RECT *pSourceRect)
01052 {
01053 ASSERT(pSourceRect);
01054 m_SourceRect = *pSourceRect;
01055 SetStretchMode();
01056 }
01057
01058 void CDrawImage::GetSourceRect(RECT *pSourceRect)
01059 {
01060 ASSERT(pSourceRect);
01061 *pSourceRect = m_SourceRect;
01062 }
01063
01064 void CDrawImage::SetStretchMode()
01065 {
01066
01067
01068 LONG SourceWidth = m_SourceRect.right - m_SourceRect.left;
01069 LONG SinkWidth = m_TargetRect.right - m_TargetRect.left;
01070 LONG SourceHeight = m_SourceRect.bottom - m_SourceRect.top;
01071 LONG SinkHeight = m_TargetRect.bottom - m_TargetRect.top;
01072
01073 m_bStretch = TRUE;
01074 if (SourceWidth == SinkWidth) {
01075 if (SourceHeight == SinkHeight) {
01076 m_bStretch = FALSE;
01077 }
01078 }
01079 }
01080
01081 void CDrawImage::NotifyAllocator(BOOL bUsingImageAllocator)
01082 {
01083 m_bUsingImageAllocator = bUsingImageAllocator;
01084 }
01085
01086 BOOL CDrawImage::UsingImageAllocator()
01087 {
01088 return m_bUsingImageAllocator;
01089 }
01090
01091 void CDrawImage::NotifyMediaType(CMediaType *pMediaType)
01092 {
01093 m_pMediaType = pMediaType;
01094 }
01095
01096 LONG CDrawImage::GetPaletteVersion()
01097 {
01098 return m_PaletteVersion;
01099 }
01100
01101 void CDrawImage::ResetPaletteVersion()
01102 {
01103 m_PaletteVersion = PALETTE_VERSION;
01104 }
01105
01106 void CDrawImage::IncrementPaletteVersion()
01107 {
01108 m_PaletteVersion++;
01109 }
01110
01111 CImageAllocator::CImageAllocator(CBaseFilter *pFilter,
01112 TCHAR *pName,
01113 HRESULT *phr) :
01114 CBaseAllocator(pName,NULL,phr,TRUE,TRUE),
01115 m_pFilter(pFilter)
01116 {
01117 ASSERT(phr);
01118 ASSERT(pFilter);
01119 }
01120
01121 #ifdef DEBUG
01122 CImageAllocator::~CImageAllocator()
01123 {
01124 ASSERT(m_bCommitted == FALSE);
01125 }
01126 #endif
01127
01128 void CImageAllocator::Free()
01129 {
01130 ASSERT(m_lAllocated == m_lFree.GetCount());
01131 EXECUTE_ASSERT(GdiFlush());
01132 CImageSample *pSample;
01133 DIBDATA *pDibData;
01134
01135 while (m_lFree.GetCount() != 0) {
01136 pSample = (CImageSample *) m_lFree.RemoveHead();
01137 pDibData = pSample->GetDIBData();
01138 EXECUTE_ASSERT(DeleteObject(pDibData->hBitmap));
01139 EXECUTE_ASSERT(CloseHandle(pDibData->hMapping));
01140 delete pSample;
01141 }
01142
01143 m_lAllocated = 0;
01144 }
01145
01146 STDMETHODIMP CImageAllocator::CheckSizes(ALLOCATOR_PROPERTIES *pRequest)
01147 {
01148
01149
01150 if (m_pMediaType == NULL) {
01151 return VFW_E_NOT_CONNECTED;
01152 }
01153
01154
01155
01156
01157
01158
01159 VIDEOINFOHEADER *pVideoInfo = (VIDEOINFOHEADER *) m_pMediaType->Format();
01160
01161
01162
01163
01164
01165
01166 if ((DWORD) pRequest->cbBuffer < pVideoInfo->bmiHeader.biSizeImage) {
01167 return E_INVALIDARG;
01168 }
01169
01170
01171
01172 if (pRequest->cbPrefix > 0) {
01173 return E_INVALIDARG;
01174 }
01175
01176 pRequest->cbBuffer = pVideoInfo->bmiHeader.biSizeImage;
01177 return NOERROR;
01178 }
01179
01180 STDMETHODIMP CImageAllocator::SetProperties(
01181 ALLOCATOR_PROPERTIES * pRequest,
01182 ALLOCATOR_PROPERTIES * pActual)
01183 {
01184 ALLOCATOR_PROPERTIES Adjusted = *pRequest;
01185
01186
01187
01188 HRESULT hr = CheckSizes(&Adjusted);
01189 if (FAILED(hr)) {
01190 return hr;
01191 }
01192 return CBaseAllocator::SetProperties(&Adjusted, pActual);
01193 }
01194
01195 HRESULT CImageAllocator::Alloc(void)
01196 {
01197 ASSERT(m_pMediaType);
01198 CImageSample *pSample;
01199 DIBDATA DibData;
01200
01201
01202
01203 HRESULT hr = CBaseAllocator::Alloc();
01204 if (FAILED(hr)) {
01205 return hr;
01206 }
01207
01208
01209
01210
01211
01212
01213 ASSERT(m_lAllocated == 0);
01214 while (m_lAllocated < m_lCount) {
01215
01216
01217
01218 HRESULT hr = CreateDIB(m_lSize,DibData);
01219 if (FAILED(hr)) {
01220 return hr;
01221 }
01222
01223
01224
01225 pSample = CreateImageSample(DibData.pBase,m_lSize);
01226 if (pSample == NULL) {
01227 EXECUTE_ASSERT(DeleteObject(DibData.hBitmap));
01228 EXECUTE_ASSERT(CloseHandle(DibData.hMapping));
01229 return E_OUTOFMEMORY;
01230 }
01231
01232
01233
01234 pSample->SetDIBData(&DibData);
01235 m_lFree.Add(pSample);
01236 m_lAllocated++;
01237 }
01238 return NOERROR;
01239 }
01240
01241 CImageSample *CImageAllocator::CreateImageSample(LPBYTE pData,LONG Length)
01242 {
01243 HRESULT hr = NOERROR;
01244 CImageSample *pSample;
01245
01246
01247
01248 pSample = new CImageSample((CBaseAllocator *) this,
01249 NAME("Video sample"),
01250 (HRESULT *) &hr,
01251 (LPBYTE) pData,
01252 (LONG) Length);
01253
01254 if (pSample == NULL || FAILED(hr)) {
01255 delete pSample;
01256 return NULL;
01257 }
01258 return pSample;
01259 }
01260
01261 HRESULT CImageAllocator::CreateDIB(LONG InSize,DIBDATA &DibData)
01262 {
01263 BITMAPINFO *pbmi;
01264 BYTE *pBase;
01265 HANDLE hMapping;
01266 HBITMAP hBitmap;
01267
01268
01269
01270 hMapping = CreateFileMapping(hMEMORY,
01271 NULL,
01272 PAGE_READWRITE,
01273 (DWORD) 0,
01274 InSize,
01275 NULL);
01276 if (hMapping == NULL) {
01277 DWORD Error = GetLastError();
01278 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error);
01279 }
01280
01281
01282
01283
01284
01285
01286 pbmi = (BITMAPINFO *) HEADER(m_pMediaType->Format());
01287 if (m_pMediaType == NULL) {
01288 DbgBreak("Invalid media type");
01289 }
01290
01291 hBitmap = CreateDIBSection((HDC) NULL,
01292 pbmi,
01293 DIB_RGB_COLORS,
01294 (VOID **) &pBase,
01295 hMapping,
01296 (DWORD) 0);
01297
01298 if (hBitmap == NULL || pBase == NULL) {
01299 EXECUTE_ASSERT(CloseHandle(hMapping));
01300 DWORD Error = GetLastError();
01301 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, Error);
01302 }
01303
01304
01305
01306 DibData.hBitmap = hBitmap;
01307 DibData.hMapping = hMapping;
01308 DibData.pBase = pBase;
01309 DibData.PaletteVersion = PALETTE_VERSION;
01310 GetObject(hBitmap,sizeof(DIBSECTION),(VOID *)&DibData.DibSection);
01311
01312 return NOERROR;
01313 }
01314
01315 void CImageAllocator::NotifyMediaType(CMediaType *pMediaType)
01316 {
01317 m_pMediaType = pMediaType;
01318 }
01319
01320 STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingAddRef()
01321 {
01322 return m_pFilter->AddRef();
01323 }
01324
01325 STDMETHODIMP_(ULONG) CImageAllocator::NonDelegatingRelease()
01326 {
01327 return m_pFilter->Release();
01328 }
01329
01330 CImageSample::CImageSample(CBaseAllocator *pAllocator,
01331 TCHAR *pName,
01332 HRESULT *phr,
01333 LPBYTE pBuffer,
01334 LONG length) :
01335 CMediaSample(pName,pAllocator,phr,pBuffer,length),
01336 m_bInit(FALSE)
01337 {
01338 ASSERT(pAllocator);
01339 ASSERT(pBuffer);
01340 }
01341
01342 void CImageSample::SetDIBData(DIBDATA *pDibData)
01343 {
01344 ASSERT(pDibData);
01345 m_DibData = *pDibData;
01346 m_bInit = TRUE;
01347 }
01348
01349 DIBDATA *CImageSample::GetDIBData()
01350 {
01351 ASSERT(m_bInit == TRUE);
01352 return &m_DibData;
01353 }
01354
01355 CImagePalette::CImagePalette(CBaseFilter *pBaseFilter,
01356 CBaseWindow *pBaseWindow,
01357 CDrawImage *pDrawImage) :
01358 m_pBaseWindow(pBaseWindow),
01359 m_pFilter(pBaseFilter),
01360 m_pDrawImage(pDrawImage),
01361 m_hPalette(NULL)
01362 {
01363 ASSERT(m_pFilter);
01364 }
01365
01366 #ifdef DEBUG
01367 CImagePalette::~CImagePalette()
01368 {
01369 ASSERT(m_hPalette == NULL);
01370 }
01371 #endif
01372
01373 BOOL CImagePalette::ShouldUpdate(const VIDEOINFOHEADER *pNewInfo,
01374 const VIDEOINFOHEADER *pOldInfo)
01375 {
01376
01377
01378 if (pOldInfo == NULL) {
01379 return TRUE;
01380 }
01381
01382
01383
01384 if (ContainsPalette(pNewInfo) == FALSE) {
01385 if (ContainsPalette(pOldInfo) == FALSE) {
01386 return FALSE;
01387 }
01388 }
01389
01390
01391
01392 DWORD VideoEntries = pNewInfo->bmiHeader.biClrUsed;
01393 if (ContainsPalette(pNewInfo) == TRUE)
01394 if (ContainsPalette(pOldInfo) == TRUE)
01395 if (pOldInfo->bmiHeader.biClrUsed == VideoEntries)
01396 if (pOldInfo->bmiHeader.biClrUsed > 0)
01397 if (memcmp((PVOID) GetBitmapPalette(pNewInfo),
01398 (PVOID) GetBitmapPalette(pOldInfo),
01399 VideoEntries * sizeof(RGBQUAD)) == 0) {
01400
01401 return FALSE;
01402 }
01403 return TRUE;
01404 }
01405
01406 HRESULT CImagePalette::PreparePalette(const CMediaType *pmtNew,
01407 const CMediaType *pmtOld,
01408 LPSTR szDevice)
01409 {
01410 const VIDEOINFOHEADER *pNewInfo = (VIDEOINFOHEADER *) pmtNew->Format();
01411 const VIDEOINFOHEADER *pOldInfo = (VIDEOINFOHEADER *) pmtOld->Format();
01412 ASSERT(pNewInfo);
01413
01414
01415
01416
01417
01418
01419 if (ShouldUpdate(pNewInfo,pOldInfo) == FALSE) {
01420 NOTE("No update needed");
01421 return S_FALSE;
01422 }
01423
01424
01425
01426
01427
01428
01429 RemovePalette();
01430 m_pFilter->NotifyEvent(EC_PALETTE_CHANGED,0,0);
01431
01432
01433
01434 if (ContainsPalette(pNewInfo) == FALSE) {
01435 NOTE("New has no palette");
01436 return S_FALSE;
01437 }
01438
01439
01440
01441
01442
01443
01444 NOTE("Making new colour palette");
01445 m_hPalette = MakePalette(pNewInfo, szDevice);
01446 ASSERT(m_hPalette != NULL);
01447
01448
01449
01450
01451
01452 if (m_pBaseWindow) m_pBaseWindow->SetPalette(m_hPalette);
01453
01454
01455
01456
01457
01458 if (m_pDrawImage) m_pDrawImage->IncrementPaletteVersion();
01459 return NOERROR;
01460 }
01461
01462 HRESULT CImagePalette::CopyPalette(const CMediaType *pSrc,CMediaType *pDest)
01463 {
01464
01465
01466 VIDEOINFOHEADER *pDestInfo = (VIDEOINFOHEADER *) pDest->Format();
01467 pDestInfo->bmiHeader.biClrUsed = 0;
01468 pDestInfo->bmiHeader.biClrImportant = 0;
01469
01470
01471
01472 if (PALETTISED(pDestInfo) == FALSE) {
01473 NOTE("No destination palette");
01474 return S_FALSE;
01475 }
01476
01477
01478
01479 const VIDEOINFOHEADER *pSrcInfo = (VIDEOINFOHEADER *) pSrc->Format();
01480 if (ContainsPalette(pSrcInfo) == FALSE) {
01481 NOTE("No source palette");
01482 return S_FALSE;
01483 }
01484
01485
01486
01487 DWORD PaletteEntries = pSrcInfo->bmiHeader.biClrUsed;
01488 if (PaletteEntries == 0) {
01489 DWORD Maximum = (1 << pSrcInfo->bmiHeader.biBitCount);
01490 NOTE1("Setting maximum colours (%d)",Maximum);
01491 PaletteEntries = Maximum;
01492 }
01493
01494
01495
01496 ASSERT(pSrcInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS);
01497 ASSERT(pSrcInfo->bmiHeader.biClrImportant <= PaletteEntries);
01498 ASSERT(COLORS(pDestInfo) == GetBitmapPalette(pDestInfo));
01499 pDestInfo->bmiHeader.biClrUsed = PaletteEntries;
01500 pDestInfo->bmiHeader.biClrImportant = pSrcInfo->bmiHeader.biClrImportant;
01501 ULONG BitmapSize = GetBitmapFormatSize(HEADER(pSrcInfo));
01502
01503 if (pDest->FormatLength() < BitmapSize) {
01504 NOTE("Reallocating destination");
01505 pDest->ReallocFormatBuffer(BitmapSize);
01506 }
01507
01508
01509
01510 CopyMemory((PVOID) COLORS(pDestInfo),
01511 (PVOID) GetBitmapPalette(pSrcInfo),
01512 PaletteEntries * sizeof(RGBQUAD));
01513
01514 return NOERROR;
01515 }
01516
01517 HRESULT CImagePalette::RemovePalette()
01518 {
01519
01520
01521 if (m_hPalette == NULL) {
01522 return NOERROR;
01523 }
01524
01525
01526
01527 HPALETTE hPalette = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
01528 ASSERT(hPalette);
01529 const HPALETTE hPalOurs = m_hPalette;
01530
01531
01532
01533
01534
01535
01536 if (m_pBaseWindow) {
01537 SelectPalette(m_pBaseWindow->GetWindowHDC(), hPalette, TRUE);
01538 SelectPalette(m_pBaseWindow->GetMemoryHDC(), hPalette, TRUE);
01539 }
01540
01541 EXECUTE_ASSERT(DeleteObject(hPalOurs));
01542 m_hPalette = NULL;
01543 return NOERROR;
01544 }
01545
01546 HPALETTE CImagePalette::MakePalette(const VIDEOINFOHEADER *pVideoInfo, LPSTR szDevice)
01547 {
01548 ASSERT(ContainsPalette(pVideoInfo) == TRUE);
01549 ASSERT(pVideoInfo->bmiHeader.biClrUsed <= iPALETTE_COLORS);
01550 BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo);
01551
01552 const RGBQUAD *pColours;
01553 LOGPALETTE *lp;
01554 HPALETTE hPalette;
01555
01556 lp = (LOGPALETTE *) new BYTE[sizeof(LOGPALETTE) + SIZE_PALETTE];
01557 if (lp == NULL) {
01558 return NULL;
01559 }
01560
01561
01562
01563
01564
01565
01566
01567 lp->palVersion = PALVERSION;
01568 lp->palNumEntries = (USHORT) pHeader->biClrUsed;
01569 if (lp->palNumEntries == 0) lp->palNumEntries = (1 << pHeader->biBitCount);
01570 pColours = GetBitmapPalette(pVideoInfo);
01571
01572 for (DWORD dwCount = 0;dwCount < lp->palNumEntries;dwCount++) {
01573 lp->palPalEntry[dwCount].peRed = pColours[dwCount].rgbRed;
01574 lp->palPalEntry[dwCount].peGreen = pColours[dwCount].rgbGreen;
01575 lp->palPalEntry[dwCount].peBlue = pColours[dwCount].rgbBlue;
01576 lp->palPalEntry[dwCount].peFlags = 0;
01577 }
01578
01579 MakeIdentityPalette(lp->palPalEntry, lp->palNumEntries, szDevice);
01580
01581
01582
01583 hPalette = CreatePalette(lp);
01584 ASSERT(hPalette != NULL);
01585 delete[] lp;
01586 return hPalette;
01587 }
01588
01589 HRESULT CImagePalette::MakeIdentityPalette(PALETTEENTRY *pEntry,INT iColours, LPSTR szDevice)
01590 {
01591 PALETTEENTRY SystemEntries[10];
01592 BOOL bIdentityPalette = TRUE;
01593 ASSERT(iColours <= iPALETTE_COLORS);
01594 const int PalLoCount = 10;
01595 const int PalHiStart = 246;
01596
01597
01598
01599 if (iColours < 10) {
01600 return S_FALSE;
01601 }
01602
01603
01604
01605
01606
01607 HDC hdc;
01608 if (szDevice == NULL || lstrcmpiA(szDevice, "DISPLAY") == 0)
01609 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
01610 else
01611 hdc = CreateDCA(NULL, szDevice, NULL, NULL);
01612 if (NULL == hdc) {
01613 return E_OUTOFMEMORY;
01614 }
01615 INT Reserved = GetDeviceCaps(hdc,NUMRESERVED);
01616 if (Reserved != 20) {
01617 DeleteDC(hdc);
01618 return S_FALSE;
01619 }
01620
01621
01622
01623
01624
01625 UINT Result = GetSystemPaletteEntries(hdc,0,PalLoCount,SystemEntries);
01626 for (UINT Count = 0;Count < Result;Count++) {
01627 if (SystemEntries[Count].peRed != pEntry[Count].peRed ||
01628 SystemEntries[Count].peGreen != pEntry[Count].peGreen ||
01629 SystemEntries[Count].peBlue != pEntry[Count].peBlue) {
01630 bIdentityPalette = FALSE;
01631 }
01632 }
01633
01634
01635
01636 Result = GetSystemPaletteEntries(hdc,PalHiStart,PalLoCount,SystemEntries);
01637 for (Count = 0;Count < Result;Count++) {
01638 if (INT(Count) + PalHiStart < iColours) {
01639 if (SystemEntries[Count].peRed != pEntry[PalHiStart + Count].peRed ||
01640 SystemEntries[Count].peGreen != pEntry[PalHiStart + Count].peGreen ||
01641 SystemEntries[Count].peBlue != pEntry[PalHiStart + Count].peBlue) {
01642 bIdentityPalette = FALSE;
01643 }
01644 }
01645 }
01646
01647
01648
01649 DeleteDC(hdc);
01650 if (bIdentityPalette == FALSE) {
01651 return S_FALSE;
01652 }
01653
01654
01655
01656 for (Count = PalLoCount;INT(Count) < min(PalHiStart,iColours);Count++) {
01657 pEntry[Count].peFlags = PC_NOCOLLAPSE;
01658 }
01659 return NOERROR;
01660 }
01661
01662 CImageDisplay::CImageDisplay()
01663 {
01664 RefreshDisplayType(NULL);
01665 }
01666
01667 HRESULT CImageDisplay::RefreshDisplayType(LPSTR szDeviceName)
01668 {
01669 CAutoLock cDisplayLock(this);
01670
01671
01672
01673 ZeroMemory((PVOID)&m_Display,sizeof(VIDEOINFOHEADER)+sizeof(TRUECOLORINFO));
01674 m_Display.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01675 m_Display.bmiHeader.biBitCount = FALSE;
01676
01677
01678
01679
01680 HDC hdcDisplay;
01681
01682 if (szDeviceName == NULL || lstrcmpiA(szDeviceName, "DISPLAY") == 0)
01683 hdcDisplay = CreateDCA("DISPLAY", NULL, NULL, NULL);
01684 else
01685 hdcDisplay = CreateDCA(NULL, szDeviceName, NULL, NULL);
01686 if (hdcDisplay == NULL) {
01687 ASSERT(FALSE);
01688 DbgLog((LOG_ERROR,1,TEXT("ACK! Can't get a DC for %hs"),
01689 szDeviceName ? szDeviceName : "<NULL>"));
01690 return E_FAIL;
01691 } else {
01692 DbgLog((LOG_TRACE,3,TEXT("Created a DC for %s"),
01693 szDeviceName ? szDeviceName : "<NULL>"));
01694 }
01695 HBITMAP hbm = CreateCompatibleBitmap(hdcDisplay,1,1);
01696 GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS);
01697
01698
01699 GetDIBits(hdcDisplay,hbm,0,1,NULL,(BITMAPINFO *)&m_Display.bmiHeader,DIB_RGB_COLORS);
01700 DeleteObject(hbm);
01701 DeleteDC(hdcDisplay);
01702
01703
01704
01705 ASSERT(CheckHeaderValidity(&m_Display));
01706 UpdateFormat(&m_Display);
01707 DbgLog((LOG_TRACE,3,TEXT("New DISPLAY bit depth =%d"),
01708 m_Display.bmiHeader.biBitCount));
01709 return NOERROR;
01710 }
01711
01712 BOOL CImageDisplay::CheckBitFields(const VIDEOINFO *pInput)
01713 {
01714 DWORD *pBitFields = (DWORD *) BITMASKS(pInput);
01715
01716 for (INT iColour = iRED;iColour <= iBLUE;iColour++) {
01717
01718
01719
01720 DWORD SetBits = CountSetBits(pBitFields[iColour]);
01721 if (SetBits > iMAXBITS || SetBits == 0) {
01722 NOTE1("Bit fields for component %d invalid",iColour);
01723 return FALSE;
01724 }
01725
01726
01727 DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]);
01728
01729
01730
01731
01732
01733
01734
01735
01736 DWORD TestField = pBitFields[iColour] >> PrefixBits;
01737 DWORD Mask = ULONG_MAX << SetBits;
01738 if (TestField & Mask) {
01739 NOTE1("Bit fields for component %d not contiguous",iColour);
01740 return FALSE;
01741 }
01742 }
01743 return TRUE;
01744 }
01745
01746 DWORD CImageDisplay::CountSetBits(DWORD Field)
01747 {
01748
01749
01750 DWORD Count = 0;
01751 DWORD init = Field;
01752
01753
01754
01755 while (init) {
01756 init = init & (init - 1);
01757 Count++;
01758 }
01759 return Count;
01760 }
01761
01762 DWORD CImageDisplay::CountPrefixBits(DWORD Field)
01763 {
01764 DWORD Mask = 1;
01765 DWORD Count = 0;
01766
01767 while (TRUE) {
01768 if (Field & Mask) {
01769 return Count;
01770 }
01771 Count++;
01772
01773 ASSERT(Mask != 0x80000000);
01774 if (Mask == 0x80000000) {
01775 return Count;
01776 }
01777 Mask <<= 1;
01778 }
01779 }
01780
01781 BOOL CImageDisplay::CheckHeaderValidity(const VIDEOINFO *pInput)
01782 {
01783
01784
01785 if (pInput->bmiHeader.biWidth <= 0 ||
01786 pInput->bmiHeader.biHeight <= 0) {
01787 NOTE("Invalid bitmap dimensions");
01788 return FALSE;
01789 }
01790
01791
01792
01793 if (pInput->bmiHeader.biCompression != BI_RGB) {
01794 if (pInput->bmiHeader.biCompression != BI_BITFIELDS) {
01795 NOTE("Invalid compression format");
01796 return FALSE;
01797 }
01798 }
01799
01800
01801
01802 if (pInput->bmiHeader.biCompression == BI_BITFIELDS) {
01803 if (pInput->bmiHeader.biBitCount != 16) {
01804 if (pInput->bmiHeader.biBitCount != 32) {
01805 NOTE("BI_BITFIELDS not 16/32 bit depth");
01806 return FALSE;
01807 }
01808 }
01809 }
01810
01811
01812
01813 if (pInput->bmiHeader.biCompression == BI_BITFIELDS) {
01814 if (CheckBitFields(pInput) == FALSE) {
01815 NOTE("Bit fields are not valid");
01816 return FALSE;
01817 }
01818 }
01819
01820
01821
01822 if (pInput->bmiHeader.biPlanes != 1) {
01823 NOTE("Number of planes not one");
01824 return FALSE;
01825 }
01826
01827
01828
01829 if (pInput->bmiHeader.biSizeImage != GetBitmapSize(&pInput->bmiHeader)) {
01830 if (pInput->bmiHeader.biSizeImage) {
01831 NOTE("Image size incorrectly set");
01832 return FALSE;
01833 }
01834 }
01835
01836
01837
01838 if (pInput->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) {
01839 NOTE("Size of BITMAPINFOHEADER wrong");
01840 return FALSE;
01841 }
01842 return CheckPaletteHeader(pInput);
01843 }
01844
01845 BOOL CImageDisplay::CheckPaletteHeader(const VIDEOINFO *pInput)
01846 {
01847
01848
01849 if (PALETTISED(pInput) == FALSE) {
01850 if (pInput->bmiHeader.biClrUsed) {
01851 NOTE("Invalid palette entries");
01852 return FALSE;
01853 }
01854 return TRUE;
01855 }
01856
01857
01858
01859 if (pInput->bmiHeader.biCompression != BI_RGB) {
01860 NOTE("Palettised video must be BI_RGB");
01861 return FALSE;
01862 }
01863
01864
01865
01866 if (pInput->bmiHeader.biClrUsed > PALETTE_ENTRIES(pInput)) {
01867 NOTE("Too many colours in palette");
01868 return FALSE;
01869 }
01870
01871
01872
01873 if (pInput->bmiHeader.biClrImportant > pInput->bmiHeader.biClrUsed) {
01874 NOTE("Too many important colours");
01875 return FALSE;
01876 }
01877 return TRUE;
01878 }
01879
01880 const VIDEOINFO *CImageDisplay::GetDisplayFormat()
01881 {
01882 return &m_Display;
01883 }
01884
01885 BOOL CImageDisplay::IsPalettised()
01886 {
01887 return PALETTISED(&m_Display);
01888 }
01889
01890 WORD CImageDisplay::GetDisplayDepth()
01891 {
01892 return m_Display.bmiHeader.biBitCount;
01893 }
01894
01895 HRESULT CImageDisplay::UpdateFormat(VIDEOINFO *pVideoInfo)
01896 {
01897 ASSERT(pVideoInfo);
01898
01899 BITMAPINFOHEADER *pbmi = HEADER(pVideoInfo);
01900 SetRectEmpty(&pVideoInfo->rcSource);
01901 SetRectEmpty(&pVideoInfo->rcTarget);
01902
01903
01904
01905 if (PALETTISED(pVideoInfo)) {
01906 if (pVideoInfo->bmiHeader.biClrUsed == 0) {
01907 pVideoInfo->bmiHeader.biClrUsed = PALETTE_ENTRIES(pVideoInfo);
01908 }
01909 }
01910
01911
01912
01913
01914
01915 if (pVideoInfo->bmiHeader.biClrImportant > pVideoInfo->bmiHeader.biClrUsed) {
01916 pVideoInfo->bmiHeader.biClrImportant = PALETTE_ENTRIES(pVideoInfo);
01917 }
01918
01919
01920
01921 if (pVideoInfo->bmiHeader.biSizeImage == 0) {
01922 pVideoInfo->bmiHeader.biSizeImage = GetBitmapSize(&pVideoInfo->bmiHeader);
01923 }
01924 return NOERROR;
01925 }
01926
01927 HRESULT CImageDisplay::CheckVideoType(const VIDEOINFO *pInput)
01928 {
01929
01930
01931 if (CheckHeaderValidity(pInput) == FALSE) {
01932 return E_INVALIDARG;
01933 }
01934
01935
01936
01937 if (m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount) {
01938 if (PALETTISED(pInput) == TRUE) {
01939 ASSERT(PALETTISED(&m_Display) == TRUE);
01940 NOTE("(Video) Type connection ACCEPTED");
01941 return NOERROR;
01942 }
01943 }
01944
01945
01946
01947 if (m_Display.bmiHeader.biBitCount > pInput->bmiHeader.biBitCount) {
01948 NOTE("(Video) Mismatch agreed");
01949 return NOERROR;
01950 }
01951
01952
01953
01954 if (m_Display.bmiHeader.biBitCount < pInput->bmiHeader.biBitCount) {
01955 NOTE("(Video) Format mismatch");
01956 return E_INVALIDARG;
01957 }
01958
01959
01960
01961 ASSERT(m_Display.bmiHeader.biBitCount == pInput->bmiHeader.biBitCount);
01962 ASSERT(PALETTISED(pInput) == FALSE);
01963 ASSERT(PALETTISED(&m_Display) == FALSE);
01964
01965
01966
01967
01968
01969
01970 const DWORD *pInputMask = GetBitMasks(pInput);
01971 const DWORD *pDisplayMask = GetBitMasks((VIDEOINFO *)&m_Display);
01972
01973 if (pInputMask[iRED] != pDisplayMask[iRED] ||
01974 pInputMask[iGREEN] != pDisplayMask[iGREEN] ||
01975 pInputMask[iBLUE] != pDisplayMask[iBLUE]) {
01976
01977 NOTE("(Video) Bit field mismatch");
01978 return E_INVALIDARG;
01979 }
01980
01981 NOTE("(Video) Type connection ACCEPTED");
01982 return NOERROR;
01983 }
01984
01985 const DWORD *CImageDisplay::GetBitMasks(const VIDEOINFO *pVideoInfo)
01986 {
01987 static const DWORD FailMasks[] = {0,0,0};
01988
01989 if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) {
01990 return BITMASKS(pVideoInfo);
01991 }
01992
01993 ASSERT(pVideoInfo->bmiHeader.biCompression == BI_RGB);
01994
01995 switch (pVideoInfo->bmiHeader.biBitCount) {
01996 case 16: return bits555;
01997 case 24: return bits888;
01998 case 32: return bits888;
01999 default: return FailMasks;
02000 }
02001 }
02002
02003 HRESULT CImageDisplay::CheckMediaType(const CMediaType *pmtIn)
02004 {
02005
02006
02007 const GUID *pFormatType = pmtIn->FormatType();
02008 if (*pFormatType != FORMAT_VideoInfo) {
02009 NOTE("Format GUID not a VIDEOINFOHEADER");
02010 return E_INVALIDARG;
02011 }
02012 ASSERT(pmtIn->Format());
02013
02014
02015
02016 ULONG Length = pmtIn->FormatLength();
02017 if (Length < SIZE_VIDEOHEADER) {
02018 NOTE("Format smaller than a VIDEOHEADER");
02019 return E_FAIL;
02020 }
02021
02022 VIDEOINFO *pInput = (VIDEOINFO *) pmtIn->Format();
02023
02024
02025
02026 const GUID *pMajorType = pmtIn->Type();
02027 if (*pMajorType != MEDIATYPE_Video) {
02028 NOTE("Major type not MEDIATYPE_Video");
02029 return E_INVALIDARG;
02030 }
02031
02032
02033
02034 const GUID *pSubType = pmtIn->Subtype();
02035 if (GetBitCount(pSubType) == USHRT_MAX) {
02036 NOTE("Invalid video media subtype");
02037 return E_INVALIDARG;
02038 }
02039 return CheckVideoType(pInput);
02040 }
02041
02042 BOOL CImageDisplay::GetColourMask(DWORD *pMaskRed,
02043 DWORD *pMaskGreen,
02044 DWORD *pMaskBlue)
02045 {
02046 CAutoLock cDisplayLock(this);
02047 *pMaskRed = 0xFF;
02048 *pMaskGreen = 0xFF;
02049 *pMaskBlue = 0xFF;
02050
02051
02052
02053 if (m_Display.bmiHeader.biBitCount < 16) {
02054 return FALSE;
02055 }
02056
02057
02058
02059
02060
02061 if (m_Display.bmiHeader.biBitCount == 24) {
02062 ASSERT(m_Display.bmiHeader.biCompression == BI_RGB);
02063 return TRUE;
02064 }
02065
02066
02067
02068 const DWORD *pBitFields = (DWORD *) GetBitMasks((VIDEOINFO *)&m_Display);
02069 DWORD *pOutputMask[] = { pMaskRed, pMaskGreen, pMaskBlue };
02070
02071
02072
02073
02074
02075 for (INT iColour = iRED;iColour <= iBLUE;iColour++) {
02076
02077
02078
02079 DWORD PrefixBits = CountPrefixBits(pBitFields[iColour]);
02080 DWORD SetBits = CountSetBits(pBitFields[iColour]);
02081
02082
02083
02084
02085
02086 *(pOutputMask[iColour]) = pBitFields[iColour] >> PrefixBits;
02087 *(pOutputMask[iColour]) <<= (iMAXBITS - SetBits);
02088 }
02089 return TRUE;
02090 }
02091
02092 STDAPI ConvertVideoInfoToVideoInfo2(AM_MEDIA_TYPE *pmt)
02093 {
02094 ASSERT(pmt->formattype == FORMAT_VideoInfo);
02095 VIDEOINFO *pVideoInfo = (VIDEOINFO *)pmt->pbFormat;
02096 PVOID pvNew = CoTaskMemAlloc(pmt->cbFormat + sizeof(VIDEOINFOHEADER2) -
02097 sizeof(VIDEOINFOHEADER));
02098 if (pvNew == NULL) {
02099 return E_OUTOFMEMORY;
02100 }
02101 CopyMemory(pvNew, pmt->pbFormat, FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader));
02102 ZeroMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader),
02103 sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER));
02104 CopyMemory((PBYTE)pvNew + FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader),
02105 pmt->pbFormat + FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader),
02106 pmt->cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader));
02107 VIDEOINFOHEADER2 *pVideoInfo2 = (VIDEOINFOHEADER2 *)pvNew;
02108 pVideoInfo2->dwPictAspectRatioX = (DWORD)pVideoInfo2->bmiHeader.biWidth;
02109 pVideoInfo2->dwPictAspectRatioY = (DWORD)pVideoInfo2->bmiHeader.biHeight;
02110 pmt->formattype = FORMAT_VideoInfo2;
02111 CoTaskMemFree(pmt->pbFormat);
02112 pmt->pbFormat = (PBYTE)pvNew;
02113 pmt->cbFormat += sizeof(VIDEOINFOHEADER2) - sizeof(VIDEOINFOHEADER);
02114 return S_OK;
02115 }