home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / sampvid.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-21  |  13.3 KB  |  402 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. #include <streams.h>
  13. #include <sampvid.h>
  14. #include <vidprop.h>
  15. #include <initguid.h>
  16. #include <olectlid.h>
  17.  
  18.  
  19. // setup data
  20.  
  21. AMOVIESETUP_MEDIATYPE sudPinTypes =     { &MEDIATYPE_Video                 // clsMajorType
  22.                                            , &MEDIASUBTYPE_NULL }  ;       // clsMinorType
  23.  
  24. AMOVIESETUP_PIN sudPins   =    { L"Input"            // strName
  25.                                , FALSE               // bRendered
  26.                                , FALSE               // bOutput
  27.                                , FALSE               // bZero
  28.                                , FALSE               // bMany
  29.                                , &CLSID_NULL         // clsConnectsToFilter
  30.                                , L"Output"           // strConnectsToPin
  31.                                , 1                   // nTypes
  32.                                , &sudPinTypes } ;    // lpTypes
  33.  
  34.  
  35. AMOVIESETUP_FILTER sudSampVid   = { &CLSID_SampleRenderer            // clsID
  36.                                   , L"Sample Video Renderer"        // strName
  37.                                   , MERIT_DO_NOT_USE                // dwMerit
  38.                                   , 1                               // nPins
  39.                                   , &sudPins };                     // lpPin
  40.  
  41. // We have a precompiled header file which is included in all the source code
  42. // files in this directory. The precompiled header includes a definition of
  43. // these CLSIDs but because it does not include initguid it does not allocate
  44. // the memory for the GUID. We therefore actually declare the GUID in here
  45.  
  46. DEFINE_GUID(CLSID_SampleRenderer,
  47. 0x4d4b1600, 0x33ac, 0x11cf, 0xbf, 0x30, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a);
  48.  
  49. DEFINE_GUID(CLSID_SampleQuality,
  50. 0xdb76d7f0, 0x97cc, 0x11cf, 0xa0, 0x96, 0x00, 0x80, 0x5f, 0x6c, 0xab, 0x82);
  51.  
  52. // List of class IDs and creator functions for the class factory. This
  53. // provides the link between the OLE entry point in the DLL and an object
  54. // being created. The class factory will call the static CreateInstance
  55.  
  56. CFactoryTemplate g_Templates[] = {
  57.     {L"Sample Video Renderer", &CLSID_SampleRenderer,CVideoRenderer::CreateInstance},
  58.     {L"Quality Property Page", &CLSID_SampleQuality,CQualityProperties::CreateInstance}
  59. };
  60. int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
  61.  
  62.  
  63. // This goes in the factory template table to create new filter instances
  64.  
  65. CUnknown *CVideoRenderer::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
  66. {
  67.     return new CVideoRenderer(NAME("Sample Video Renderer"),pUnk,phr);
  68. }
  69.  
  70.  
  71. #pragma warning(disable:4355)
  72.  
  73. CVideoRenderer::CVideoRenderer(TCHAR *pName,
  74.                                LPUNKNOWN pUnk,
  75.                                HRESULT *phr) :
  76.  
  77.     CBaseVideoRenderer(CLSID_SampleRenderer,pName,pUnk,phr),
  78.     m_InputPin(NAME("Video Pin"),this,&m_InterfaceLock,phr,L"Input"),
  79.     m_ImageAllocator(this,NAME("Sample video allocator"),phr),
  80.     m_VideoText(NAME("Video properties"),GetOwner(),phr,&m_InterfaceLock,this),
  81.     m_ImagePalette(this,&m_VideoText,&m_DrawImage),
  82.     m_DrawImage(&m_VideoText)
  83. {
  84.     // Reset the current video size
  85.  
  86.     m_VideoSize.cx = 0;
  87.     m_VideoSize.cy = 0;
  88.  
  89.     // Initialise the window and control interfaces
  90.  
  91.     m_VideoText.SetControlVideoPin(&m_InputPin);
  92.     m_VideoText.SetControlWindowPin(&m_InputPin);
  93. }
  94.  
  95.  
  96. // Destructor
  97.  
  98. CVideoRenderer::~CVideoRenderer()
  99. {
  100.     m_pInputPin = NULL;
  101. }
  102.  
  103. //
  104. // GetSetupData
  105. //
  106. LPAMOVIESETUP_FILTER CVideoRenderer::GetSetupData()
  107. {
  108.   return &sudSampVid;
  109. }
  110.  
  111. // Check the proposed video media type
  112.  
  113. HRESULT CVideoRenderer::CheckMediaType(const CMediaType *pmtIn)
  114. {
  115.     return m_Display.CheckMediaType(pmtIn);
  116. }
  117.  
  118.  
  119. // We only support one input pin and it is numbered zero
  120.  
  121. CBasePin *CVideoRenderer::GetPin(int n)
  122. {
  123.     ASSERT(n == 0);
  124.     if (n != 0) {
  125.         return NULL;
  126.     }
  127.  
  128.     // Assign the input pin if not already done so
  129.  
  130.     if (m_pInputPin == NULL) {
  131.         m_pInputPin = &m_InputPin;
  132.     }
  133.     return m_pInputPin;
  134. }
  135.  
  136.  
  137. // Overriden to say what interfaces we support and where
  138.  
  139. STDMETHODIMP CVideoRenderer::NonDelegatingQueryInterface(REFIID riid,void **ppv)
  140. {
  141.     CheckPointer(ppv,E_POINTER);
  142.     if (riid == IID_ISpecifyPropertyPages) {
  143.         return GetInterface((ISpecifyPropertyPages *)this, ppv);
  144.     } else if (riid == IID_IVideoWindow) {
  145.         return m_VideoText.NonDelegatingQueryInterface(riid,ppv);
  146.     } else if (riid == IID_IBasicVideo) {
  147.         return m_VideoText.NonDelegatingQueryInterface(riid,ppv);
  148.     }
  149.     return CBaseVideoRenderer::NonDelegatingQueryInterface(riid,ppv);
  150. }
  151.  
  152.  
  153. // Return the CLSIDs for the property pages we support
  154.  
  155. STDMETHODIMP CVideoRenderer::GetPages(CAUUID *pPages)
  156. {
  157.     CheckPointer(pPages,E_POINTER);
  158.  
  159.     pPages->cElems = 1;
  160.     pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
  161.     if (pPages->pElems == NULL) {
  162.         return E_OUTOFMEMORY;
  163.     }
  164.  
  165.     pPages->pElems[0] = CLSID_SampleQuality;
  166.     return NOERROR;
  167. }
  168.  
  169.  
  170. // Have the drawing object render the current image
  171.  
  172. HRESULT CVideoRenderer::DoRenderSample(IMediaSample *pMediaSample)
  173. {
  174.     return m_DrawImage.DrawImage(pMediaSample);
  175. }
  176.  
  177.  
  178. // Overriden to realise the palette before drawing
  179.  
  180. void CVideoRenderer::PrepareRender()
  181. {
  182.     HWND hwnd = m_VideoText.GetWindowHWND();
  183.     SendMessage(hwnd,WM_QUERYNEWPALETTE,0,0);
  184.     NOTE("Sent WM_QUERYNEWPALETTE to window");
  185. }
  186.  
  187.  
  188. // The auto show flag is used to have the window shown automatically when we
  189. // change state. We do this only when moving to paused or running, when there
  190. // is no outstanding EC_USERABORT set and when the window is not already up
  191. // This can be changed through the IVideoWindow interface AutoShow property.
  192. // If the window is not currently visible then we are showing it because of
  193. // a state change to paused or running, in which case there is no point in
  194. // the video window sending an EC_REPAINT as we're getting an image anyway
  195.  
  196. HRESULT CVideoRenderer::Active()
  197. {
  198.     HWND hwnd = m_VideoText.GetWindowHWND();
  199.     NOTE("AutoShowWindow");
  200.  
  201.     if (m_VideoText.IsAutoShowEnabled() == TRUE) {
  202.         if (m_bAbort == FALSE) {
  203.             if (IsWindowVisible(hwnd) == FALSE) {
  204.                 NOTE("Executing AutoShowWindow");
  205.                 SetRepaintStatus(FALSE);
  206.                 m_VideoText.PerformanceAlignWindow();
  207.                 m_VideoText.DoShowWindow(SW_SHOWNORMAL);
  208.                 m_VideoText.DoSetWindowForeground(TRUE);
  209.             }
  210.         }
  211.     }
  212.     return CBaseVideoRenderer::Active();
  213. }
  214.  
  215.  
  216. // We store a copy of the media type used for the connection in the renderer
  217. // because it is required by many different parts of the running renderer
  218. // This can be called when we come to draw a media sample that has a format
  219. // change with it. We normally delay type changes until they are really due
  220. // for rendering otherwise we will change types too early if the source has
  221. // allocated a queue of samples. In our case this isn't a problem because we
  222. // only ever receive one sample at a time so it's safe to change immediately
  223.  
  224. HRESULT CVideoRenderer::SetMediaType(const CMediaType *pmt)
  225. {
  226.     CAutoLock cInterfaceLock(&m_InterfaceLock);
  227.     CMediaType StoreFormat(m_mtIn);
  228.     HRESULT hr = NOERROR;
  229.  
  230.     // Fill out the optional fields in the VIDEOINFO
  231.  
  232.     m_mtIn = *pmt;
  233.     VIDEOINFO *pVideoInfo = (VIDEOINFO *) m_mtIn.Format();
  234.     m_Display.UpdateFormat(pVideoInfo);
  235.  
  236.     // We set the new palette before completing so that the method can look
  237.     // at the old RGB colours we used and compare them with the new set, if
  238.     // they're all identical colours we don't need to change the palette
  239.  
  240.     hr = m_ImagePalette.PreparePalette(&m_mtIn,&StoreFormat);
  241.     if (FAILED(hr)) {
  242.         return hr;
  243.     }
  244.  
  245.     // Complete the initialisation
  246.  
  247.     m_DrawImage.NotifyMediaType(&m_mtIn);
  248.     m_ImageAllocator.NotifyMediaType(&m_mtIn);
  249.     return NOERROR;
  250. }
  251.  
  252.  
  253. // This is called when a connection or an attempted connection is terminated
  254. // and lets us to reset the connection flag held by the base class renderer
  255. // The filter object may be hanging onto an image to use for refreshing the
  256. // video window so that must be freed (the allocator decommit may be waiting
  257. // for that image to return before completing) then we must also uninstall
  258. // any palette we were using, reset anything set with the control interfaces
  259. // then set our overall state back to disconnected ready for the next time
  260.  
  261. HRESULT CVideoRenderer::BreakConnect()
  262. {
  263.     CAutoLock cInterfaceLock(&m_InterfaceLock);
  264.  
  265.     // Check we are in a valid state
  266.  
  267.     HRESULT hr = CBaseVideoRenderer::BreakConnect();
  268.     if (FAILED(hr)) {
  269.         return hr;
  270.     }
  271.  
  272.     // The base class break connect disables us from sending any EC_REPAINT
  273.     // events which is important otherwise when we come down here to remove
  274.     // our palette we end up painting the window again - which in turn sees
  275.     // there is no image to draw and would otherwise send a redundant event
  276.  
  277.     m_ImagePalette.RemovePalette();
  278.     m_mtIn.ResetFormatBuffer();
  279.     return NOERROR;
  280. }
  281.  
  282.  
  283. // When we complete connection we need to see if the video has changed sizes
  284. // If it has then we activate the window and reset the source and destination
  285. // rectangles. If the video is the same size then we bomb out early. By doing
  286. // this we make sure that temporary disocnnections such as when we go into a
  287. // fullscreen mode do not cause unnecessary property changes. The basic ethos
  288. // is that all properties should be persistent across connections if possible
  289.  
  290. HRESULT CVideoRenderer::CompleteConnect(IPin *pReceivePin)
  291. {
  292.     CAutoLock cInterfaceLock(&m_InterfaceLock);
  293.     CBaseVideoRenderer::CompleteConnect(pReceivePin);
  294.     m_DrawImage.ResetPaletteVersion();
  295.  
  296.     // Has the video size changed between connections
  297.  
  298.     VIDEOINFO *pVideoInfo = (VIDEOINFO *) m_mtIn.Format();
  299.     if (pVideoInfo->bmiHeader.biWidth == m_VideoSize.cx) {
  300.         if (pVideoInfo->bmiHeader.biHeight == m_VideoSize.cy) {
  301.             return NOERROR;
  302.         }
  303.     }
  304.  
  305.     // Set them for the current video dimensions
  306.  
  307.     m_DrawImage.SetDrawContext();
  308.     m_VideoSize.cx = pVideoInfo->bmiHeader.biWidth;
  309.     m_VideoSize.cy = pVideoInfo->bmiHeader.biHeight;
  310.     m_VideoText.SetDefaultSourceRect();
  311.     m_VideoText.SetDefaultTargetRect();
  312.     m_VideoText.OnVideoSizeChange();
  313.     m_VideoText.ActivateWindow();
  314.  
  315.     return NOERROR;
  316. }
  317.  
  318.  
  319. // Constructor
  320.  
  321. CVideoInputPin::CVideoInputPin(TCHAR *pObjectName,
  322.                                CVideoRenderer *pRenderer,
  323.                                CCritSec *pInterfaceLock,
  324.                                HRESULT *phr,
  325.                                LPCWSTR pPinName) :
  326.  
  327.     CRendererInputPin(pRenderer,phr,pPinName),
  328.     m_pRenderer(pRenderer),
  329.     m_pInterfaceLock(pInterfaceLock)
  330. {
  331.     ASSERT(m_pRenderer);
  332.     ASSERT(pInterfaceLock);
  333. }
  334.  
  335.  
  336. // This overrides the CBaseInputPin virtual method to return our allocator
  337. // we create to pass shared memory DIB buffers that GDI can directly access
  338. // When NotifyAllocator is called it sets the current allocator in the base
  339. // input pin class (m_pAllocator), this is what GetAllocator should return
  340. // unless it is NULL in which case we return the allocator we would like
  341.  
  342. STDMETHODIMP CVideoInputPin::GetAllocator(IMemAllocator **ppAllocator)
  343. {
  344.     CAutoLock cInterfaceLock(m_pInterfaceLock);
  345.     CheckPointer(ppAllocator,E_POINTER);
  346.  
  347.     // Has an allocator been set yet in the base class
  348.  
  349.     if (m_pAllocator == NULL) {
  350.         m_pAllocator = &m_pRenderer->m_ImageAllocator;
  351.         m_pAllocator->AddRef();
  352.     }
  353.  
  354.     m_pAllocator->AddRef();
  355.     *ppAllocator = m_pAllocator;
  356.     return NOERROR;
  357. }
  358.  
  359.  
  360. // The COM specification says any two IUnknown pointers to the same object
  361. // should always match which provides a way for us to see if they are using
  362. // our DIB allocator or not. Since we are only really interested in equality
  363. // and our object always hands out the same IMemAllocator interface we can
  364. // just see if the pointers match. If they are we set a flag in the main
  365. // renderer as the window needs to know whether it can do fast rendering
  366.  
  367. STDMETHODIMP
  368. CVideoInputPin::NotifyAllocator(IMemAllocator *pAllocator,BOOL bReadOnly)
  369. {
  370.     CAutoLock cInterfaceLock(m_pInterfaceLock);
  371.  
  372.     // Make sure the base class gets a look
  373.  
  374.     HRESULT hr = CBaseInputPin::NotifyAllocator(pAllocator,bReadOnly);
  375.     if (FAILED(hr)) {
  376.         return hr;
  377.     }
  378.  
  379.     // Whose allocator is the source going to use
  380.  
  381.     m_pRenderer->m_DrawImage.NotifyAllocator(FALSE);
  382.     if (pAllocator == &m_pRenderer->m_ImageAllocator) {
  383.         m_pRenderer->m_DrawImage.NotifyAllocator(TRUE);
  384.     }
  385.     return NOERROR;
  386. }
  387.  
  388.  
  389. // Handle the registration of this filter
  390.  
  391. HRESULT DllRegisterServer()
  392. {
  393.     return AMovieDllRegisterServer();
  394. }
  395.  
  396.  
  397. HRESULT DllUnregisterServer()
  398. {
  399.     return AMovieDllUnregisterServer();
  400. }
  401.  
  402.