home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / videotxt.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-16  |  15.9 KB  |  466 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11.  
  12. // Sample ActiveMovie video renderer
  13.  
  14. #include <streams.h>
  15. #include <sampvid.h>
  16. #include <vidprop.h>
  17. #include <tchar.h>
  18.  
  19. // This is a sample renderer that displays video in a window. What is special
  20. // about that is that the window is non rectangular, the region it has is a
  21. // word (whatever VideoString is defined to be as shown below). Using various
  22. // GDI methods we create a region from the word and select it into our window
  23. // Windows will then look after clipping and mouse interactions, all we have
  24. // to do is handle the painting and drawing. This sample can work if it uses
  25. // either its own allocator (the preferred approach) or a source filter's
  26. // (like when it connects to the tee filter). It has separate code paths to
  27. // handle the drawing depending whose allocator it's using on this connection
  28.  
  29. TCHAR VideoString[] = TEXT("ActiveX");
  30.  
  31.  
  32. // Constructor
  33.  
  34. CVideoText::CVideoText(TCHAR *pName,                 // Object description
  35.                        LPUNKNOWN pUnk,               // Normal COM ownership
  36.                        HRESULT *phr,                 // OLE failure code
  37.                        CCritSec *pInterfaceLock,     // Main critical section
  38.                        CVideoRenderer *pRenderer) :  // Delegates locking to
  39.  
  40.     CBaseControlVideo(pRenderer,pInterfaceLock,pName,pUnk,phr),
  41.     CBaseControlWindow(pRenderer,pInterfaceLock,pName,pUnk,phr),
  42.     m_pRenderer(pRenderer)
  43. {
  44.     PrepareWindow();
  45.     InitWindowRegion(VideoString);
  46. }
  47.  
  48.  
  49. // Destructor
  50.  
  51. CVideoText::~CVideoText()
  52. {
  53.     InactivateWindow();
  54.     DoneWithWindow();
  55. }
  56.  
  57.  
  58. // Overriden to say what interfaces we support and where
  59.  
  60. STDMETHODIMP CVideoText::NonDelegatingQueryInterface(REFIID riid,void **ppv)
  61. {
  62.     CheckPointer(ppv,E_POINTER);
  63.     if (riid == IID_IVideoWindow) {
  64.         return CBaseVideoWindow::NonDelegatingQueryInterface(riid,ppv);
  65.     } else {
  66.         ASSERT(riid == IID_IBasicVideo);
  67.         return CBaseBasicVideo::NonDelegatingQueryInterface(riid,ppv);
  68.     }
  69. }
  70.  
  71.  
  72. // This is called when we initialise the mask bitmap used when drawing. We
  73. // create and install a larger font into the device context. The font used
  74. // is 72 point Arial. It doesn't matter that the width of the letters are
  75. // bigger than the video as we can stretch the video during the draw. This
  76. // makes us go slower but it looks good and the quality management in the
  77. // base renderer class should take care of reducing the source frame rate
  78.  
  79. HFONT CVideoText::CreateVideoFont()
  80. {
  81.     LOGFONT lf;
  82.  
  83.     int iLogPelsY = GetDeviceCaps(m_hdc,LOGPIXELSY);
  84.     ZeroMemory(&lf,sizeof(LOGFONT));
  85.  
  86.     lf.lfHeight = (-72 * iLogPelsY) / 72;
  87.     lf.lfWeight = 700;
  88.     lf.lfCharSet = ANSI_CHARSET;
  89.     lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  90.     lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  91.     lf.lfQuality = PROOF_QUALITY;
  92.     lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
  93.     _tcscpy(lf.lfFaceName,TEXT("Arial"));
  94.  
  95.     return CreateFontIndirect(&lf);
  96. }
  97.  
  98.  
  99. // We display the video in a window that has a region selected into it that
  100. // matches the word we are passed in. By doing this we let Windows manage
  101. // all the clipping and mouse technology. The trick is in creating a region
  102. // that matches the word, this is done by using paths. We create a path for
  103. // a temporary HDC, draw the word and then end the path. After which we can
  104. // then ask Windows for a region that describes that path. That gives us a
  105. // region for the outside of the word so we not it to get the word region
  106.  
  107. HRESULT CVideoText::InitWindowRegion(TCHAR *pStringName)
  108. {
  109.     OSVERSIONINFO VersionInfo;
  110.     VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  111.     EXECUTE_ASSERT(GetVersionEx(&VersionInfo));
  112.  
  113.     // Set a window region according to the OS capabilities
  114.  
  115.     if ((VersionInfo.dwPlatformId & VER_PLATFORM_WIN32_NT) == 0) {
  116.         m_Size.cx = 320;
  117.         m_Size.cy = 240;
  118.         return NOERROR;
  119.     }
  120.  
  121.     // Get the text extents the word passed in will require based on the
  122.     // font and bitmap selected in the current device context. For it to
  123.     // be displayed in a different font it must be selected into the HDC
  124.  
  125.     HDC hdc = CreateCompatibleDC(m_hdc);
  126.     HFONT hFont = CreateVideoFont();
  127.     SelectObject(hdc,hFont);
  128.  
  129.     GetTextExtentPoint32((HDC) hdc,             // The output device context
  130.                          pStringName,           // The string we'll be using
  131.                          lstrlen(pStringName),  // Number of characters in it
  132.                          (LPSIZE) &m_Size);     // Filled in with the extents
  133.  
  134.     // Create a bitmap that matches the current format
  135.  
  136.     HBITMAP hMaskBitmap = CreateCompatibleBitmap(hdc,m_Size.cx,m_Size.cy);
  137.     if (hMaskBitmap == NULL) {
  138.         ASSERT(hMaskBitmap);
  139.         return E_UNEXPECTED;
  140.     }
  141.  
  142.     // Select the monochrome bitmap into the device context
  143.  
  144.     HBITMAP hBitmap = (HBITMAP) SelectObject(hdc,hMaskBitmap);
  145.     EXECUTE_ASSERT(BeginPath(hdc));
  146.  
  147.     // Draw the string into the monochrome bitmap
  148.  
  149.     ExtTextOut((HDC) hdc,               // Target device context
  150.                (int) 0,                 // x coordinate reference
  151.                (int) 0,                 // Likewise y coordinate
  152.                (DWORD) 0,               // No special flags to set
  153.                NULL,                    // No clipping rectangle
  154.                pStringName,             // Pointer to text words
  155.                lstrlen(pStringName),    // Number of characters
  156.                NULL);                   // Intercharacter spacing
  157.  
  158.     EXECUTE_ASSERT(EndPath(hdc));
  159.     HRGN hOutside = PathToRegion(hdc);
  160.     HRGN hFullWindow = CreateRectRgn(0,0,m_Size.cx,m_Size.cy);
  161.     HRGN hWordRegion = CreateRectRgn(0,0,1,1);
  162.     CombineRgn(hWordRegion,hFullWindow,hOutside,RGN_DIFF);
  163.     SetWindowRgn(m_hwnd,hWordRegion,TRUE);
  164.  
  165.     // Clear up the regions we created
  166.  
  167.     DeleteObject(hWordRegion);
  168.     DeleteObject(hOutside);
  169.     DeleteObject(hFullWindow);
  170.  
  171.     // Delete the HDC and text bitmap
  172.  
  173.     SelectObject(hdc,hBitmap);
  174.     HFONT hDefault = (HFONT) GetStockObject(SYSTEM_FONT);
  175.     SelectObject(hdc,hDefault);
  176.     DeleteObject(hFont);
  177.     DeleteObject(hMaskBitmap);
  178.     DeleteDC(hdc);
  179.  
  180.     return NOERROR;
  181. }
  182.  
  183.  
  184. // When we call PrepareWindow in our constructor it will call this method as
  185. // it is going to create the window to get our window and class styles. The
  186. // return code is the class name and must be allocated in static storage. We
  187. // specify a normal window during creation although the window styles as well
  188. // as the extended styles may be changed by the application via IVideoWindow
  189.  
  190. LPTSTR CVideoText::GetClassWindowStyles(DWORD *pClassStyles,
  191.                                         DWORD *pWindowStyles,
  192.                                         DWORD *pWindowStylesEx)
  193. {
  194.     OSVERSIONINFO VersionInfo;
  195.     VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  196.     EXECUTE_ASSERT(GetVersionEx(&VersionInfo));
  197.  
  198.     // Default styles for Windows NT systems
  199.  
  200.     *pClassStyles = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT;
  201.     *pWindowStyles = WS_POPUP | WS_CLIPCHILDREN;
  202.     *pWindowStylesEx = (DWORD) 0;
  203.  
  204.     // Make a normal window on Win95 systems
  205.  
  206.     if ((VersionInfo.dwPlatformId & VER_PLATFORM_WIN32_NT) == 0) {
  207.         *pWindowStyles = WS_POPUP | WS_CAPTION | WS_CLIPCHILDREN;
  208.     }
  209.     return TEXT("VideoTextRenderer");
  210. }
  211.  
  212.  
  213. // Return the default window rectangle
  214.  
  215. RECT CVideoText::GetDefaultRect()
  216. {
  217.     RECT DefaultRect = {0,0,m_Size.cx,m_Size.cy};
  218.     ASSERT(m_hwnd);
  219.     ASSERT(m_hdc);
  220.     return DefaultRect;
  221. }
  222.  
  223.  
  224. // This is the derived class window message handler methods
  225.  
  226. LRESULT CVideoText::OnReceiveMessage(HWND hwnd,          // Window handle
  227.                                      UINT uMsg,          // Message ID
  228.                                      WPARAM wParam,      // First parameter
  229.                                      LPARAM lParam)      // Other parameter
  230. {
  231.     IFilter *pFilter = NULL;
  232.     RECT ClientRect;
  233.  
  234.     // Blank out the window background
  235.  
  236.     if (uMsg == WM_ERASEBKGND) {
  237.         EXECUTE_ASSERT(GetClientRect(m_hwnd,&ClientRect));
  238.         HBRUSH hBrush = CreateSolidBrush(RGB(0,0,0));
  239.         EXECUTE_ASSERT(FillRect(m_hdc,&ClientRect,hBrush));
  240.         EXECUTE_ASSERT(DeleteObject(hBrush));
  241.         return (LRESULT) 0;
  242.     }
  243.  
  244.     // Handle WM_CLOSE by aborting the playback
  245.  
  246.     if (uMsg == WM_CLOSE) {
  247.         m_pRenderer->NotifyEvent(EC_USERABORT,0,0);
  248.         DoShowWindow(SW_HIDE);
  249.         return CBaseWindow::OnClose();
  250.     }
  251.  
  252.     // We pass on WM_ACTIVATEAPP messages to the filtergraph so that the
  253.     // IVideoWindow plug in distributor can switch us out of fullscreen
  254.     // mode where appropriate. These messages may also be used by the
  255.     // resource manager to keep track of which renderer has the focus
  256.  
  257.     if (uMsg == WM_ACTIVATEAPP) {
  258.         NOTE1("Notification of EC_ACTIVATE (%d)",(BOOL) wParam);
  259.         m_pRenderer->QueryInterface(IID_IFilter,(void **) &pFilter);
  260.         m_pRenderer->NotifyEvent(EC_ACTIVATE,wParam,(LPARAM) pFilter);
  261.         pFilter->Release();
  262.         return (LRESULT) 0;
  263.     }
  264.  
  265.     // Treat clicks on text as requests to move window
  266.  
  267.     if (uMsg == WM_NCHITTEST) {
  268.         LRESULT Result = DefWindowProc(hwnd,uMsg,wParam,lParam);
  269.         if (Result == HTCLIENT) {
  270.             Result = HTCAPTION;
  271.         }
  272.         return Result;
  273.     }
  274.  
  275.     // The base class that implements IVideoWindow looks after a flag
  276.     // that says whether or not the cursor should be hidden. If so we
  277.     // hide the cursor and return (LRESULT) 1. Otherwise we pass to
  278.     // the DefWindowProc to show the cursor as normal. This is used
  279.     // when our window is made fullscreen to imitate the Modex filter
  280.  
  281.     if (uMsg == WM_SETCURSOR) {
  282.         if (IsCursorHidden() == TRUE) {
  283.             SetCursor(NULL);
  284.             return (LRESULT) 1;
  285.         }
  286.     }
  287.  
  288.     // When we detect a display change we send an EC_DISPLAY_CHANGED
  289.     // message along with our input pin. The filtergraph will stop
  290.     // everyone and reconnect our input pin. When being reconnected
  291.     // we can then accept the media type that matches the new display
  292.     // mode since we may no longer be able to draw the current format
  293.  
  294.     if (uMsg == WM_DISPLAYCHANGE) {
  295.         m_pRenderer->m_Display.RefreshDisplayType();
  296.         m_pRenderer->OnDisplayChange();
  297.         NOTE("Sent EC_DISPLAY_CHANGED event");
  298.         return (LRESULT) 0;
  299.     }
  300.     return CBaseWindow::OnReceiveMessage(hwnd,uMsg,wParam,lParam);
  301. }
  302.  
  303.  
  304. // This is called when we reset the default target rectangle
  305.  
  306. HRESULT CVideoText::SetDefaultTargetRect()
  307. {
  308.     VIDEOINFO *pVideoInfo = (VIDEOINFO *) m_pRenderer->m_mtIn.Format();
  309.     BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo);
  310.     RECT TargetRect = {0,0,m_Size.cx,m_Size.cy};
  311.     m_pRenderer->m_DrawImage.SetTargetRect(&TargetRect);
  312.     return NOERROR;
  313. }
  314.  
  315.  
  316. // Return S_OK if using the default target otherwise S_FALSE
  317.  
  318. HRESULT CVideoText::IsDefaultTargetRect()
  319. {
  320.     RECT TargetRect;
  321.  
  322.     VIDEOINFO *pVideoInfo = (VIDEOINFO *) m_pRenderer->m_mtIn.Format();
  323.     BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo);
  324.     m_pRenderer->m_DrawImage.GetTargetRect(&TargetRect);
  325.  
  326.     // Check the destination matches the initial client area
  327.  
  328.     if (TargetRect.left != 0 || TargetRect.top != 0 ||
  329.             TargetRect.right != m_Size.cx ||
  330.                 TargetRect.bottom != m_Size.cy) {
  331.                     return S_FALSE;
  332.     }
  333.     return S_OK;
  334. }
  335.  
  336.  
  337. // This is called to set the target rectangle in the video window, it will be
  338. // called whenever a WM_SIZE message is retrieved from the message queue. We
  339. // simply store the rectangle and use it later when we do the drawing calls
  340.  
  341. HRESULT CVideoText::SetTargetRect(RECT *pTargetRect)
  342. {
  343.     m_pRenderer->m_DrawImage.SetTargetRect(pTargetRect);
  344.     return NOERROR;
  345. }
  346.  
  347.  
  348. // Return the current destination rectangle
  349.  
  350. HRESULT CVideoText::GetTargetRect(RECT *pTargetRect)
  351. {
  352.     ASSERT(pTargetRect);
  353.     m_pRenderer->m_DrawImage.GetTargetRect(pTargetRect);
  354.     return NOERROR;
  355. }
  356.  
  357.  
  358. // This is called when we reset the default source rectangle
  359.  
  360. HRESULT CVideoText::SetDefaultSourceRect()
  361. {
  362.     SIZE VideoSize = m_pRenderer->m_VideoSize;
  363.     RECT SourceRect = {0,0,VideoSize.cx,VideoSize.cy};
  364.     m_pRenderer->m_DrawImage.SetSourceRect(&SourceRect);
  365.     return NOERROR;
  366. }
  367.  
  368.  
  369. // Return S_OK if using the default source otherwise S_FALSE
  370.  
  371. HRESULT CVideoText::IsDefaultSourceRect()
  372. {
  373.     RECT SourceRect;
  374.  
  375.     // Does the source match the native video size
  376.  
  377.     SIZE VideoSize = m_pRenderer->m_VideoSize;
  378.     CAutoLock cWindowLock(&m_WindowLock);
  379.     m_pRenderer->m_DrawImage.GetSourceRect(&SourceRect);
  380.  
  381.     // Check the coordinates match the video dimensions
  382.  
  383.     if (SourceRect.right == VideoSize.cx) {
  384.         if (SourceRect.bottom == VideoSize.cy) {
  385.             if (SourceRect.left == 0) {
  386.                 if (SourceRect.top == 0) {
  387.                     return S_OK;
  388.                 }
  389.             }
  390.         }
  391.     }
  392.     return S_FALSE;
  393. }
  394.  
  395.  
  396. // This is called when we want to change the section of the image to draw. We
  397. // use this information in the drawing operation calls later on. We must also
  398. // see if the source and destination rectangles have the same dimensions. If
  399. // not we must stretch during the rendering rather than a direct pixel copy
  400.  
  401. HRESULT CVideoText::SetSourceRect(RECT *pSourceRect)
  402. {
  403.     m_pRenderer->m_DrawImage.SetSourceRect(pSourceRect);
  404.     return NOERROR;
  405. }
  406.  
  407.  
  408. // Return the current source rectangle
  409.  
  410. HRESULT CVideoText::GetSourceRect(RECT *pSourceRect)
  411. {
  412.     ASSERT(pSourceRect);
  413.     m_pRenderer->m_DrawImage.GetSourceRect(pSourceRect);
  414.     return NOERROR;
  415. }
  416.  
  417.  
  418. // Return a copy of the current image in the video renderer
  419.  
  420. HRESULT CVideoText::GetStaticImage(long *pBufferSize,long *pDIBImage)
  421. {
  422.     NOTE("Entering GetStaticImage");
  423.     IMediaSample *pMediaSample;
  424.     pMediaSample = m_pRenderer->GetCurrentSample();
  425.     RECT SourceRect;
  426.  
  427.     // Is there an image available
  428.  
  429.     if (pMediaSample == NULL) {
  430.         return E_UNEXPECTED;
  431.     }
  432.  
  433.     // Find a scaled source rectangle for the current bitmap
  434.  
  435.     m_pRenderer->m_DrawImage.GetSourceRect(&SourceRect);
  436.     SourceRect = m_pRenderer->m_DrawImage.ScaleSourceRect(&SourceRect);
  437.     VIDEOINFO *pVideoInfo = (VIDEOINFO *) m_pRenderer->m_mtIn.Format();
  438.  
  439.     // Call the base class helper method to do the work
  440.  
  441.     HRESULT hr = CopyImage(pMediaSample,        // Buffer containing image
  442.                            pVideoInfo,          // Type representing bitmap
  443.                            pBufferSize,         // Size of buffer for DIB
  444.                            (BYTE*) pDIBImage,   // Data buffer for output
  445.                            &SourceRect);        // Current source position
  446.  
  447.     pMediaSample->Release();
  448.     return hr;
  449. }
  450.  
  451.  
  452. // Derived classes must override this to return a VIDEOINFO representing
  453. // the video format. We cannot call IPin ConnectionMediaType to get this
  454. // format because various filters dynamically change the type when using
  455. // DirectDraw such that the format shows the position of the logical
  456. // bitmap in a frame buffer surface, so the size might be returned as
  457. // 1024x768 pixels instead of 320x240 which are the real video dimensions
  458.  
  459. void CVideoText::GetVideoFormat(VIDEOINFO *pVideoInfo)
  460. {
  461.     ZeroMemory((PVOID) pVideoInfo, sizeof(VIDEOINFO));
  462.     CopyMemory((PVOID) pVideoInfo, (PVOID) m_pRenderer->m_mtIn.Format(),
  463.                min(sizeof(VIDEOINFO), m_pRenderer->m_mtIn.FormatLength()));
  464. }
  465.  
  466.