home *** CD-ROM | disk | FTP | other *** search
- //==========================================================================;
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- // PURPOSE.
- //
- // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
- //
- //--------------------------------------------------------------------------;
-
- // Sample ActiveMovie video renderer
-
- #include <streams.h>
- #include <sampvid.h>
- #include <vidprop.h>
- #include <tchar.h>
-
- // This is a sample renderer that displays video in a window. What is special
- // about that is that the window is non rectangular, the region it has is a
- // word (whatever VideoString is defined to be as shown below). Using various
- // GDI methods we create a region from the word and select it into our window
- // Windows will then look after clipping and mouse interactions, all we have
- // to do is handle the painting and drawing. This sample can work if it uses
- // either its own allocator (the preferred approach) or a source filter's
- // (like when it connects to the tee filter). It has separate code paths to
- // handle the drawing depending whose allocator it's using on this connection
-
- TCHAR VideoString[] = TEXT("ActiveX");
-
-
- // Constructor
-
- CVideoText::CVideoText(TCHAR *pName, // Object description
- LPUNKNOWN pUnk, // Normal COM ownership
- HRESULT *phr, // OLE failure code
- CCritSec *pInterfaceLock, // Main critical section
- CVideoRenderer *pRenderer) : // Delegates locking to
-
- CBaseControlVideo(pRenderer,pInterfaceLock,pName,pUnk,phr),
- CBaseControlWindow(pRenderer,pInterfaceLock,pName,pUnk,phr),
- m_pRenderer(pRenderer)
- {
- PrepareWindow();
- InitWindowRegion(VideoString);
- }
-
-
- // Destructor
-
- CVideoText::~CVideoText()
- {
- InactivateWindow();
- DoneWithWindow();
- }
-
-
- // Overriden to say what interfaces we support and where
-
- STDMETHODIMP CVideoText::NonDelegatingQueryInterface(REFIID riid,void **ppv)
- {
- CheckPointer(ppv,E_POINTER);
- if (riid == IID_IVideoWindow) {
- return CBaseVideoWindow::NonDelegatingQueryInterface(riid,ppv);
- } else {
- ASSERT(riid == IID_IBasicVideo);
- return CBaseBasicVideo::NonDelegatingQueryInterface(riid,ppv);
- }
- }
-
-
- // This is called when we initialise the mask bitmap used when drawing. We
- // create and install a larger font into the device context. The font used
- // is 72 point Arial. It doesn't matter that the width of the letters are
- // bigger than the video as we can stretch the video during the draw. This
- // makes us go slower but it looks good and the quality management in the
- // base renderer class should take care of reducing the source frame rate
-
- HFONT CVideoText::CreateVideoFont()
- {
- LOGFONT lf;
-
- int iLogPelsY = GetDeviceCaps(m_hdc,LOGPIXELSY);
- ZeroMemory(&lf,sizeof(LOGFONT));
-
- lf.lfHeight = (-72 * iLogPelsY) / 72;
- lf.lfWeight = 700;
- lf.lfCharSet = ANSI_CHARSET;
- lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
- lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lf.lfQuality = PROOF_QUALITY;
- lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
- _tcscpy(lf.lfFaceName,TEXT("Arial"));
-
- return CreateFontIndirect(&lf);
- }
-
-
- // We display the video in a window that has a region selected into it that
- // matches the word we are passed in. By doing this we let Windows manage
- // all the clipping and mouse technology. The trick is in creating a region
- // that matches the word, this is done by using paths. We create a path for
- // a temporary HDC, draw the word and then end the path. After which we can
- // then ask Windows for a region that describes that path. That gives us a
- // region for the outside of the word so we not it to get the word region
-
- HRESULT CVideoText::InitWindowRegion(TCHAR *pStringName)
- {
- OSVERSIONINFO VersionInfo;
- VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- EXECUTE_ASSERT(GetVersionEx(&VersionInfo));
-
- // Set a window region according to the OS capabilities
-
- if ((VersionInfo.dwPlatformId & VER_PLATFORM_WIN32_NT) == 0) {
- m_Size.cx = 320;
- m_Size.cy = 240;
- return NOERROR;
- }
-
- // Get the text extents the word passed in will require based on the
- // font and bitmap selected in the current device context. For it to
- // be displayed in a different font it must be selected into the HDC
-
- HDC hdc = CreateCompatibleDC(m_hdc);
- HFONT hFont = CreateVideoFont();
- SelectObject(hdc,hFont);
-
- GetTextExtentPoint32((HDC) hdc, // The output device context
- pStringName, // The string we'll be using
- lstrlen(pStringName), // Number of characters in it
- (LPSIZE) &m_Size); // Filled in with the extents
-
- // Create a bitmap that matches the current format
-
- HBITMAP hMaskBitmap = CreateCompatibleBitmap(hdc,m_Size.cx,m_Size.cy);
- if (hMaskBitmap == NULL) {
- ASSERT(hMaskBitmap);
- return E_UNEXPECTED;
- }
-
- // Select the monochrome bitmap into the device context
-
- HBITMAP hBitmap = (HBITMAP) SelectObject(hdc,hMaskBitmap);
- EXECUTE_ASSERT(BeginPath(hdc));
-
- // Draw the string into the monochrome bitmap
-
- ExtTextOut((HDC) hdc, // Target device context
- (int) 0, // x coordinate reference
- (int) 0, // Likewise y coordinate
- (DWORD) 0, // No special flags to set
- NULL, // No clipping rectangle
- pStringName, // Pointer to text words
- lstrlen(pStringName), // Number of characters
- NULL); // Intercharacter spacing
-
- EXECUTE_ASSERT(EndPath(hdc));
- HRGN hOutside = PathToRegion(hdc);
- HRGN hFullWindow = CreateRectRgn(0,0,m_Size.cx,m_Size.cy);
- HRGN hWordRegion = CreateRectRgn(0,0,1,1);
- CombineRgn(hWordRegion,hFullWindow,hOutside,RGN_DIFF);
- SetWindowRgn(m_hwnd,hWordRegion,TRUE);
-
- // Clear up the regions we created
-
- DeleteObject(hWordRegion);
- DeleteObject(hOutside);
- DeleteObject(hFullWindow);
-
- // Delete the HDC and text bitmap
-
- SelectObject(hdc,hBitmap);
- HFONT hDefault = (HFONT) GetStockObject(SYSTEM_FONT);
- SelectObject(hdc,hDefault);
- DeleteObject(hFont);
- DeleteObject(hMaskBitmap);
- DeleteDC(hdc);
-
- return NOERROR;
- }
-
-
- // When we call PrepareWindow in our constructor it will call this method as
- // it is going to create the window to get our window and class styles. The
- // return code is the class name and must be allocated in static storage. We
- // specify a normal window during creation although the window styles as well
- // as the extended styles may be changed by the application via IVideoWindow
-
- LPTSTR CVideoText::GetClassWindowStyles(DWORD *pClassStyles,
- DWORD *pWindowStyles,
- DWORD *pWindowStylesEx)
- {
- OSVERSIONINFO VersionInfo;
- VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- EXECUTE_ASSERT(GetVersionEx(&VersionInfo));
-
- // Default styles for Windows NT systems
-
- *pClassStyles = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT;
- *pWindowStyles = WS_POPUP | WS_CLIPCHILDREN;
- *pWindowStylesEx = (DWORD) 0;
-
- // Make a normal window on Win95 systems
-
- if ((VersionInfo.dwPlatformId & VER_PLATFORM_WIN32_NT) == 0) {
- *pWindowStyles = WS_POPUP | WS_CAPTION | WS_CLIPCHILDREN;
- }
- return TEXT("VideoTextRenderer");
- }
-
-
- // Return the default window rectangle
-
- RECT CVideoText::GetDefaultRect()
- {
- RECT DefaultRect = {0,0,m_Size.cx,m_Size.cy};
- ASSERT(m_hwnd);
- ASSERT(m_hdc);
- return DefaultRect;
- }
-
-
- // This is the derived class window message handler methods
-
- LRESULT CVideoText::OnReceiveMessage(HWND hwnd, // Window handle
- UINT uMsg, // Message ID
- WPARAM wParam, // First parameter
- LPARAM lParam) // Other parameter
- {
- IFilter *pFilter = NULL;
- RECT ClientRect;
-
- // Blank out the window background
-
- if (uMsg == WM_ERASEBKGND) {
- EXECUTE_ASSERT(GetClientRect(m_hwnd,&ClientRect));
- HBRUSH hBrush = CreateSolidBrush(RGB(0,0,0));
- EXECUTE_ASSERT(FillRect(m_hdc,&ClientRect,hBrush));
- EXECUTE_ASSERT(DeleteObject(hBrush));
- return (LRESULT) 0;
- }
-
- // Handle WM_CLOSE by aborting the playback
-
- if (uMsg == WM_CLOSE) {
- m_pRenderer->NotifyEvent(EC_USERABORT,0,0);
- DoShowWindow(SW_HIDE);
- return CBaseWindow::OnClose();
- }
-
- // We pass on WM_ACTIVATEAPP messages to the filtergraph so that the
- // IVideoWindow plug in distributor can switch us out of fullscreen
- // mode where appropriate. These messages may also be used by the
- // resource manager to keep track of which renderer has the focus
-
- if (uMsg == WM_ACTIVATEAPP) {
- NOTE1("Notification of EC_ACTIVATE (%d)",(BOOL) wParam);
- m_pRenderer->QueryInterface(IID_IFilter,(void **) &pFilter);
- m_pRenderer->NotifyEvent(EC_ACTIVATE,wParam,(LPARAM) pFilter);
- pFilter->Release();
- return (LRESULT) 0;
- }
-
- // Treat clicks on text as requests to move window
-
- if (uMsg == WM_NCHITTEST) {
- LRESULT Result = DefWindowProc(hwnd,uMsg,wParam,lParam);
- if (Result == HTCLIENT) {
- Result = HTCAPTION;
- }
- return Result;
- }
-
- // The base class that implements IVideoWindow looks after a flag
- // that says whether or not the cursor should be hidden. If so we
- // hide the cursor and return (LRESULT) 1. Otherwise we pass to
- // the DefWindowProc to show the cursor as normal. This is used
- // when our window is made fullscreen to imitate the Modex filter
-
- if (uMsg == WM_SETCURSOR) {
- if (IsCursorHidden() == TRUE) {
- SetCursor(NULL);
- return (LRESULT) 1;
- }
- }
-
- // When we detect a display change we send an EC_DISPLAY_CHANGED
- // message along with our input pin. The filtergraph will stop
- // everyone and reconnect our input pin. When being reconnected
- // we can then accept the media type that matches the new display
- // mode since we may no longer be able to draw the current format
-
- if (uMsg == WM_DISPLAYCHANGE) {
- m_pRenderer->m_Display.RefreshDisplayType();
- m_pRenderer->OnDisplayChange();
- NOTE("Sent EC_DISPLAY_CHANGED event");
- return (LRESULT) 0;
- }
- return CBaseWindow::OnReceiveMessage(hwnd,uMsg,wParam,lParam);
- }
-
-
- // This is called when we reset the default target rectangle
-
- HRESULT CVideoText::SetDefaultTargetRect()
- {
- VIDEOINFO *pVideoInfo = (VIDEOINFO *) m_pRenderer->m_mtIn.Format();
- BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo);
- RECT TargetRect = {0,0,m_Size.cx,m_Size.cy};
- m_pRenderer->m_DrawImage.SetTargetRect(&TargetRect);
- return NOERROR;
- }
-
-
- // Return S_OK if using the default target otherwise S_FALSE
-
- HRESULT CVideoText::IsDefaultTargetRect()
- {
- RECT TargetRect;
-
- VIDEOINFO *pVideoInfo = (VIDEOINFO *) m_pRenderer->m_mtIn.Format();
- BITMAPINFOHEADER *pHeader = HEADER(pVideoInfo);
- m_pRenderer->m_DrawImage.GetTargetRect(&TargetRect);
-
- // Check the destination matches the initial client area
-
- if (TargetRect.left != 0 || TargetRect.top != 0 ||
- TargetRect.right != m_Size.cx ||
- TargetRect.bottom != m_Size.cy) {
- return S_FALSE;
- }
- return S_OK;
- }
-
-
- // This is called to set the target rectangle in the video window, it will be
- // called whenever a WM_SIZE message is retrieved from the message queue. We
- // simply store the rectangle and use it later when we do the drawing calls
-
- HRESULT CVideoText::SetTargetRect(RECT *pTargetRect)
- {
- m_pRenderer->m_DrawImage.SetTargetRect(pTargetRect);
- return NOERROR;
- }
-
-
- // Return the current destination rectangle
-
- HRESULT CVideoText::GetTargetRect(RECT *pTargetRect)
- {
- ASSERT(pTargetRect);
- m_pRenderer->m_DrawImage.GetTargetRect(pTargetRect);
- return NOERROR;
- }
-
-
- // This is called when we reset the default source rectangle
-
- HRESULT CVideoText::SetDefaultSourceRect()
- {
- SIZE VideoSize = m_pRenderer->m_VideoSize;
- RECT SourceRect = {0,0,VideoSize.cx,VideoSize.cy};
- m_pRenderer->m_DrawImage.SetSourceRect(&SourceRect);
- return NOERROR;
- }
-
-
- // Return S_OK if using the default source otherwise S_FALSE
-
- HRESULT CVideoText::IsDefaultSourceRect()
- {
- RECT SourceRect;
-
- // Does the source match the native video size
-
- SIZE VideoSize = m_pRenderer->m_VideoSize;
- CAutoLock cWindowLock(&m_WindowLock);
- m_pRenderer->m_DrawImage.GetSourceRect(&SourceRect);
-
- // Check the coordinates match the video dimensions
-
- if (SourceRect.right == VideoSize.cx) {
- if (SourceRect.bottom == VideoSize.cy) {
- if (SourceRect.left == 0) {
- if (SourceRect.top == 0) {
- return S_OK;
- }
- }
- }
- }
- return S_FALSE;
- }
-
-
- // This is called when we want to change the section of the image to draw. We
- // use this information in the drawing operation calls later on. We must also
- // see if the source and destination rectangles have the same dimensions. If
- // not we must stretch during the rendering rather than a direct pixel copy
-
- HRESULT CVideoText::SetSourceRect(RECT *pSourceRect)
- {
- m_pRenderer->m_DrawImage.SetSourceRect(pSourceRect);
- return NOERROR;
- }
-
-
- // Return the current source rectangle
-
- HRESULT CVideoText::GetSourceRect(RECT *pSourceRect)
- {
- ASSERT(pSourceRect);
- m_pRenderer->m_DrawImage.GetSourceRect(pSourceRect);
- return NOERROR;
- }
-
-
- // Return a copy of the current image in the video renderer
-
- HRESULT CVideoText::GetStaticImage(long *pBufferSize,long *pDIBImage)
- {
- NOTE("Entering GetStaticImage");
- IMediaSample *pMediaSample;
- pMediaSample = m_pRenderer->GetCurrentSample();
- RECT SourceRect;
-
- // Is there an image available
-
- if (pMediaSample == NULL) {
- return E_UNEXPECTED;
- }
-
- // Find a scaled source rectangle for the current bitmap
-
- m_pRenderer->m_DrawImage.GetSourceRect(&SourceRect);
- SourceRect = m_pRenderer->m_DrawImage.ScaleSourceRect(&SourceRect);
- VIDEOINFO *pVideoInfo = (VIDEOINFO *) m_pRenderer->m_mtIn.Format();
-
- // Call the base class helper method to do the work
-
- HRESULT hr = CopyImage(pMediaSample, // Buffer containing image
- pVideoInfo, // Type representing bitmap
- pBufferSize, // Size of buffer for DIB
- (BYTE*) pDIBImage, // Data buffer for output
- &SourceRect); // Current source position
-
- pMediaSample->Release();
- return hr;
- }
-
-
- // Derived classes must override this to return a VIDEOINFO representing
- // the video format. We cannot call IPin ConnectionMediaType to get this
- // format because various filters dynamically change the type when using
- // DirectDraw such that the format shows the position of the logical
- // bitmap in a frame buffer surface, so the size might be returned as
- // 1024x768 pixels instead of 320x240 which are the real video dimensions
-
- void CVideoText::GetVideoFormat(VIDEOINFO *pVideoInfo)
- {
- ZeroMemory((PVOID) pVideoInfo, sizeof(VIDEOINFO));
- CopyMemory((PVOID) pVideoInfo, (PVOID) m_pRenderer->m_mtIn.Format(),
- min(sizeof(VIDEOINFO), m_pRenderer->m_mtIn.FormatLength()));
- }
-
-