dmoimpl.h
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:21k
源码类别:

模拟服务器

开发平台:

C/C++

  1. //------------------------------------------------------------------------------
  2. // File: DMOImpl.h
  3. //
  4. // Desc: Classes to implement a DMO.
  5. //
  6. // Copyright (c) 2000, Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8. #ifndef _dmoimpl_h_
  9. #define _dmoimpl_h_
  10. #ifdef _DEBUG
  11. #include <crtdbg.h>
  12. #endif
  13. //  Class to implement a DMO
  14. //
  15. //
  16. //       Assumes the number of input and output streams is fixed
  17. //       (these are template parameters)
  18. //
  19. //       Provides following services:
  20. //
  21. //          Basic parameter checking and locking
  22. //          Fully implements :
  23. //                 GetStreamCount
  24. //                 SetInputType
  25. //                 SetOutputType
  26. //                 GetCurrentInputType
  27. //                 GetCurrentOutputType
  28. //
  29. //          Checks if all types are set before streaming
  30. //          Automatically calls AllocateStreamingResources before streaming
  31. //              if it's not been called already
  32. //          Prevents streaming until the types on all non-optional streams
  33. //              have been set
  34. //
  35. //
  36. //  Derived class implements the following methods :
  37. //
  38. /*
  39.    HRESULT InternalGetInputStreamInfo(DWORD dwInputStreamIndex, DWORD *pdwFlags);
  40.    HRESULT InternalGetOutputStreamInfo(DWORD dwOutputStreamIndex, DWORD *pdwFlags);
  41.    HRESULT InternalCheckInputType(DWORD dwInputStreamIndex, const DMO_MEDIA_TYPE *pmt);
  42.    HRESULT InternalCheckOutputType(DWORD dwOutputStreamIndex, const DMO_MEDIA_TYPE *pmt);
  43.    HRESULT InternalGetInputType(DWORD dwInputStreamIndex, DWORD dwTypeIndex,
  44.                             DMO_MEDIA_TYPE *pmt);
  45.    HRESULT InternalGetOutputType(DWORD dwOutputStreamIndex, DWORD dwTypeIndex,
  46.                             DMO_MEDIA_TYPE *pmt);
  47.    HRESULT InternalGetInputSizeInfo(DWORD dwInputStreamIndex, DWORD *pcbSize,
  48.                             DWORD *pcbMaxLookahead, DWORD *pcbAlignment);
  49.    HRESULT InternalGetOutputSizeInfo(DWORD dwOutputStreamIndex, DWORD *pcbSize,
  50.                              DWORD *pcbAlignment);
  51.    HRESULT InternalGetInputMaxLatency(DWORD dwInputStreamIndex, REFERENCE_TIME *prtMaxLatency);
  52.    HRESULT InternalSetInputMaxLatency(DWORD dwInputStreamIndex, REFERENCE_TIME rtMaxLatency);
  53.    HRESULT InternalFlush();
  54.    HRESULT InternalDiscontinuity(DWORD dwInputStreamIndex);
  55.    HRESULT InternalAllocateStreamingResources();
  56.    HRESULT InternalFreeStreamingResources();
  57.    HRESULT InternalProcessInput(DWORD dwInputStreamIndex, IMediaBuffer *pBuffer,
  58.                                DWORD dwFlags, REFERENCE_TIME rtTimestamp,
  59.                                REFERENCE_TIME rtTimelength);
  60.    HRESULT InternalProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount,
  61.                                DMO_OUTPUT_DATA_BUFFER *pOutputBuffers,
  62.                            DWORD *pdwStatus);
  63.    HRESULT InternalAcceptingInput(DWORD dwInputStreamIndex);
  64.    void Lock();
  65.    void Unlock();
  66.    Notes:
  67.        The derived class is meant to do most work to initialize streaming
  68.        in AllocateStreamingResources rather than when types are set.
  69.        This centralizes the work to one
  70.        clear place based on the types set for all streams.
  71.        The derived class implements locking.
  72.        The derived class implements the IUnknown methods
  73.    Usage example (1 input and 1 output) :
  74.    class CMyDMO : public IMediaObjectImpl<CMyDmo, 1, 1>,
  75.                   ...
  76. */
  77. #define INTERNAL_CALL(_T_, _X_) 
  78.     static_cast<_T_ *>(this)->Internal##_X_
  79. template <class _DERIVED_, int NUMBEROFINPUTS, int NUMBEROFOUTPUTS>
  80. class IMediaObjectImpl : public IMediaObject
  81. {
  82. private:
  83.     // Member variables
  84.     struct {
  85.         DWORD   fTypeSet:1;
  86.         DWORD   fIncomplete:1;
  87.         DMO_MEDIA_TYPE CurrentMediaType;
  88.     } m_InputInfo[NUMBEROFINPUTS], m_OutputInfo[NUMBEROFOUTPUTS];
  89.     bool m_fTypesSet;
  90.     bool m_fFlushed;
  91.     bool m_fResourcesAllocated;
  92. protected:
  93.     //  Helpers
  94.     bool InputTypeSet(DWORD ulInputStreamIndex) const
  95.     {
  96.         _ASSERTE(ulInputStreamIndex < NUMBEROFINPUTS);
  97.         return 0 != m_InputInfo[ulInputStreamIndex].fTypeSet;
  98.     }
  99.     bool OutputTypeSet(DWORD ulOutputStreamIndex) const
  100.     {
  101.         _ASSERTE(ulOutputStreamIndex < NUMBEROFOUTPUTS);
  102.         return 0 != m_OutputInfo[ulOutputStreamIndex].fTypeSet;
  103.     }
  104.     const DMO_MEDIA_TYPE *InputType(DWORD ulInputStreamIndex)
  105.     {
  106.         if (!InputTypeSet(ulInputStreamIndex)) {
  107.             return NULL;
  108.         }
  109.         return &m_InputInfo[ulInputStreamIndex].CurrentMediaType;
  110.     }
  111.     const DMO_MEDIA_TYPE *OutputType(DWORD ulOutputStreamIndex)
  112.     {
  113.         if (!OutputTypeSet(ulOutputStreamIndex)) {
  114.             return NULL;
  115.         }
  116.         return &m_OutputInfo[ulOutputStreamIndex].CurrentMediaType;
  117.     }
  118.     class LockIt
  119.     {
  120.     public:
  121.         LockIt(_DERIVED_ *p) : m_p(p)
  122.         {
  123.             static_cast<_DERIVED_ *>(m_p)->Lock();
  124.         }
  125.         ~LockIt()
  126.         {
  127.             static_cast<_DERIVED_ *>(m_p)->Unlock();
  128.         }
  129.         _DERIVED_ *const m_p;
  130.     };
  131.     bool CheckTypesSet()
  132.     {
  133.         m_fTypesSet = false;
  134.         DWORD dw;
  135.         for (dw = 0; dw < NUMBEROFINPUTS; dw++) {
  136.             if (!InputTypeSet(dw)) {
  137.                 return false;
  138.             }
  139.         }
  140.         for (dw = 0; dw < NUMBEROFOUTPUTS; dw++) {
  141.             if (!OutputTypeSet(dw)) {
  142.                 //  Check if it's optional
  143.                 DWORD dwFlags;
  144. #ifdef _DEBUG
  145.                 dwFlags = 0xFFFFFFFF;
  146. #endif
  147.                 INTERNAL_CALL(_DERIVED_, GetOutputStreamInfo)(dw, &dwFlags);
  148.                 _ASSERTE(0 == (dwFlags & ~(DMO_OUTPUT_STREAMF_WHOLE_SAMPLES |
  149.                                          DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER |
  150.                                          DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE |
  151.                                          DMO_OUTPUT_STREAMF_DISCARDABLE |
  152.                                          DMO_OUTPUT_STREAMF_OPTIONAL)));
  153.                 if (!(dwFlags & DMO_OUTPUT_STREAMF_OPTIONAL)) {
  154.                     return false;
  155.                 }
  156.             }
  157.         }
  158.         m_fTypesSet = true;
  159.         return true;
  160.     }
  161.     IMediaObjectImpl() :
  162.         m_fTypesSet(false),
  163.         m_fFlushed(true),
  164.         m_fResourcesAllocated(false)
  165.     {
  166.         ZeroMemory(&m_InputInfo, sizeof(m_InputInfo));
  167.         ZeroMemory(&m_OutputInfo, sizeof(m_OutputInfo));
  168.     }
  169.     virtual ~IMediaObjectImpl() {
  170.         DWORD dwCurrentType;
  171.         for (dwCurrentType = 0; dwCurrentType < NUMBEROFINPUTS; dwCurrentType++) {
  172.             if(InputTypeSet(dwCurrentType)) {
  173.                 MoFreeMediaType(&m_InputInfo[dwCurrentType].CurrentMediaType);
  174.             }
  175.         }
  176.         for (dwCurrentType = 0; dwCurrentType < NUMBEROFOUTPUTS; dwCurrentType++) {
  177.             if(OutputTypeSet(dwCurrentType)) {
  178.                 MoFreeMediaType(&m_OutputInfo[dwCurrentType].CurrentMediaType);
  179.             }
  180.         }
  181.     }
  182.     // IMediaObject methods
  183.     //
  184.     // IMediaObject methods
  185.     //
  186.     STDMETHODIMP GetStreamCount(unsigned long *pulNumberOfInputStreams, unsigned long *pulNumberOfOutputStreams)
  187.     {
  188.         LockIt lck(static_cast<_DERIVED_ *>(this));
  189.         if (pulNumberOfInputStreams == NULL ||
  190.             pulNumberOfOutputStreams == NULL) {
  191.             return E_POINTER;
  192.         }
  193.         *pulNumberOfInputStreams  = NUMBEROFINPUTS;
  194.         *pulNumberOfOutputStreams = NUMBEROFOUTPUTS;
  195.         return S_OK;
  196.     }
  197.     STDMETHODIMP GetInputStreamInfo(ULONG ulStreamIndex, DWORD *pdwFlags)
  198.     {
  199.         LockIt lck(static_cast<_DERIVED_ *>(this));
  200.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  201.             return DMO_E_INVALIDSTREAMINDEX;
  202.         }
  203.         if (pdwFlags == NULL) {
  204.             return E_POINTER;
  205.         }
  206.         HRESULT hr = INTERNAL_CALL(_DERIVED_, GetInputStreamInfo)(ulStreamIndex, pdwFlags);
  207.         _ASSERTE(0 == (*pdwFlags & ~(DMO_INPUT_STREAMF_WHOLE_SAMPLES |
  208.                                    DMO_INPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER |
  209.                                    DMO_INPUT_STREAMF_FIXED_SAMPLE_SIZE |
  210.                                    DMO_INPUT_STREAMF_HOLDS_BUFFERS)));
  211.         return hr;
  212.     }
  213.     STDMETHODIMP GetOutputStreamInfo(ULONG ulStreamIndex, DWORD *pdwFlags)
  214.     {
  215.         LockIt lck(static_cast<_DERIVED_ *>(this));
  216.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  217.             return DMO_E_INVALIDSTREAMINDEX;
  218.         }
  219.         if (pdwFlags == NULL) {
  220.             return E_POINTER;
  221.         }
  222.         HRESULT hr = INTERNAL_CALL(_DERIVED_, GetOutputStreamInfo)(ulStreamIndex, pdwFlags);
  223.         _ASSERTE(0 == (*pdwFlags & ~(DMO_OUTPUT_STREAMF_WHOLE_SAMPLES |
  224.                                    DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER |
  225.                                    DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE |
  226.                                    DMO_OUTPUT_STREAMF_DISCARDABLE |
  227.                                    DMO_OUTPUT_STREAMF_OPTIONAL)));
  228.         return hr;
  229.     }
  230.     STDMETHODIMP GetInputType(ULONG ulStreamIndex, ULONG ulTypeIndex, DMO_MEDIA_TYPE *pmt) {
  231.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  232.             return DMO_E_INVALIDSTREAMINDEX;
  233.         }
  234.         LockIt lck(static_cast<_DERIVED_ *>(this));
  235.         return INTERNAL_CALL(_DERIVED_, GetInputType)(ulStreamIndex, ulTypeIndex, pmt);
  236.     }
  237.     STDMETHODIMP GetOutputType(ULONG ulStreamIndex, ULONG ulTypeIndex, DMO_MEDIA_TYPE *pmt) {
  238.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  239.             return DMO_E_INVALIDSTREAMINDEX;
  240.         }
  241.         LockIt lck(static_cast<_DERIVED_ *>(this));
  242.         return INTERNAL_CALL(_DERIVED_, GetOutputType)(ulStreamIndex, ulTypeIndex, pmt);
  243.     }
  244.     STDMETHODIMP GetInputCurrentType(ULONG ulStreamIndex, DMO_MEDIA_TYPE *pmt) {
  245.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  246.             return DMO_E_INVALIDSTREAMINDEX;
  247.         }
  248.         if (NULL == pmt) {
  249.             return E_POINTER;
  250.         }
  251.         LockIt lck(static_cast<_DERIVED_ *>(this));
  252.         if (InputTypeSet(ulStreamIndex))
  253.             return MoCopyMediaType(pmt,
  254.                                    &m_InputInfo[ulStreamIndex].CurrentMediaType);
  255.         else
  256.            return DMO_E_TYPE_NOT_SET;
  257.     }
  258.     STDMETHODIMP GetOutputCurrentType(ULONG ulStreamIndex, DMO_MEDIA_TYPE *pmt) {
  259.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  260.             return DMO_E_INVALIDSTREAMINDEX;
  261.         }
  262.         if (NULL == pmt) {
  263.             return E_POINTER;
  264.         }
  265.         LockIt lck(static_cast<_DERIVED_ *>(this));
  266.         if (OutputTypeSet(ulStreamIndex))
  267.             return MoCopyMediaType(pmt,
  268.                                    &m_OutputInfo[ulStreamIndex].CurrentMediaType);
  269.         else
  270.            return DMO_E_TYPE_NOT_SET;
  271.     }
  272.     STDMETHODIMP GetInputSizeInfo(ULONG ulStreamIndex, ULONG *pulSize, ULONG *pcbMaxLookahead, ULONG *pulAlignment) {
  273.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  274.             return DMO_E_INVALIDSTREAMINDEX;
  275.         }
  276.         if (NULL == pulSize || NULL == pulAlignment ||
  277.             NULL == pcbMaxLookahead) {
  278.             return E_POINTER;
  279.         }
  280.         LockIt lck(static_cast<_DERIVED_ *>(this));
  281.         if (!InputTypeSet(ulStreamIndex)) {
  282.            return DMO_E_TYPE_NOT_SET;
  283.         }
  284.         return INTERNAL_CALL(_DERIVED_, GetInputSizeInfo)(ulStreamIndex, pulSize, pcbMaxLookahead, pulAlignment);
  285.     }
  286.     STDMETHODIMP GetOutputSizeInfo(ULONG ulStreamIndex, ULONG *pulSize, ULONG *pulAlignment) {
  287.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  288.             return DMO_E_INVALIDSTREAMINDEX;
  289.         }
  290.         if (NULL == pulSize || NULL == pulAlignment) {
  291.             return E_POINTER;
  292.         }
  293.         LockIt lck(static_cast<_DERIVED_ *>(this));
  294.         if (!m_fTypesSet || !OutputTypeSet(ulStreamIndex)) {
  295.            return DMO_E_TYPE_NOT_SET;
  296.         }
  297.         return INTERNAL_CALL(_DERIVED_, GetOutputSizeInfo)(ulStreamIndex, pulSize, pulAlignment);
  298.     }
  299.     STDMETHODIMP SetInputType(ULONG ulStreamIndex, const DMO_MEDIA_TYPE *pmt, DWORD dwFlags) {
  300.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  301.             return DMO_E_INVALIDSTREAMINDEX;
  302.         }
  303.         if (dwFlags & ~ (DMO_SET_TYPEF_CLEAR | DMO_SET_TYPEF_TEST_ONLY)) {
  304.             return E_INVALIDARG;
  305.         }
  306.         LockIt lck(static_cast<_DERIVED_ *>(this));
  307.         if (dwFlags & DMO_SET_TYPEF_CLEAR) {
  308.             MoFreeMediaType(&m_InputInfo[ulStreamIndex].CurrentMediaType);
  309.             m_InputInfo[ulStreamIndex].fTypeSet = FALSE;
  310.             if (!CheckTypesSet()) {
  311.                 Flush();
  312.                 FreeStreamingResources();
  313.             }
  314.             return NOERROR;
  315.         }
  316.         if (NULL == pmt) {
  317.             return E_POINTER;
  318.         }
  319.         HRESULT hr = INTERNAL_CALL(_DERIVED_, CheckInputType)(ulStreamIndex, pmt);
  320.         if (FAILED(hr))
  321.            return hr;
  322.         if (dwFlags & DMO_SET_TYPEF_TEST_ONLY) {
  323.            return NOERROR;
  324.         }
  325.         // actually set the type
  326.         DMO_MEDIA_TYPE mtTemp;
  327.         if (S_OK == MoCopyMediaType(&mtTemp, pmt)) {
  328.             // Free any previous mediatype
  329.             if (InputTypeSet(ulStreamIndex)) {
  330.                 MoFreeMediaType(&m_InputInfo[ulStreamIndex].CurrentMediaType);
  331.             }
  332.             m_InputInfo[ulStreamIndex].CurrentMediaType = mtTemp;
  333.             m_InputInfo[ulStreamIndex].fTypeSet = TRUE;
  334.             CheckTypesSet();
  335.         } else {
  336.             return E_OUTOFMEMORY;
  337.         }
  338.         return NOERROR;
  339.     }
  340.     STDMETHODIMP SetOutputType(ULONG ulStreamIndex, const DMO_MEDIA_TYPE *pmt, DWORD dwFlags) {
  341.         if (ulStreamIndex >= NUMBEROFOUTPUTS) {
  342.             return DMO_E_INVALIDSTREAMINDEX;
  343.         }
  344.         if (dwFlags & ~ (DMO_SET_TYPEF_CLEAR | DMO_SET_TYPEF_TEST_ONLY)) {
  345.             return E_INVALIDARG;
  346.         }
  347.         LockIt lck(static_cast<_DERIVED_ *>(this));
  348.         if (dwFlags & DMO_SET_TYPEF_CLEAR) {
  349.             MoFreeMediaType(&m_OutputInfo[ulStreamIndex].CurrentMediaType);
  350.             m_OutputInfo[ulStreamIndex].fTypeSet = FALSE;
  351.             if (!CheckTypesSet()) {
  352.                 Flush();
  353.                 FreeStreamingResources();
  354.             }
  355.             return NOERROR;
  356.         }
  357.         if (NULL == pmt) {
  358.             return E_POINTER;
  359.         }
  360.         HRESULT hr = INTERNAL_CALL(_DERIVED_, CheckOutputType)(ulStreamIndex, pmt);
  361.         if (FAILED(hr)) {
  362.            return hr;
  363.         }
  364.         if (dwFlags & DMO_SET_TYPEF_TEST_ONLY) {
  365.            return NOERROR;
  366.         }
  367.         // actually set the type
  368.         DMO_MEDIA_TYPE mtTemp;
  369.         if (S_OK == MoCopyMediaType(&mtTemp, pmt)) {
  370.             // Free any previous mediatype
  371.             if (OutputTypeSet(ulStreamIndex)) {
  372.                 MoFreeMediaType(&m_OutputInfo[ulStreamIndex].CurrentMediaType);
  373.             }
  374.             m_OutputInfo[ulStreamIndex].CurrentMediaType = mtTemp;
  375.             m_OutputInfo[ulStreamIndex].fTypeSet = TRUE;
  376.             CheckTypesSet();
  377.         } else {
  378.             return E_OUTOFMEMORY;
  379.         }
  380.         return NOERROR;
  381.     }
  382.     STDMETHODIMP GetInputStatus(
  383.         ULONG ulStreamIndex,
  384.         DWORD *pdwStatus
  385.     ) {
  386.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  387.             return DMO_E_INVALIDSTREAMINDEX;
  388.         }
  389.         if (NULL == pdwStatus) {
  390.             return E_POINTER;
  391.         }
  392.         *pdwStatus = 0;
  393.         LockIt lck(static_cast<_DERIVED_ *>(this));
  394.         if (!m_fTypesSet) {
  395.             return DMO_E_TYPE_NOT_SET;
  396.         }
  397.         if (INTERNAL_CALL(_DERIVED_, AcceptingInput)(ulStreamIndex) == S_OK) {
  398.            *pdwStatus |= DMO_INPUT_STATUSF_ACCEPT_DATA;
  399.         }
  400.         return NOERROR;
  401.     }
  402.     STDMETHODIMP GetInputMaxLatency(unsigned long ulStreamIndex, REFERENCE_TIME *prtLatency) {
  403.         if (prtLatency == NULL) {
  404.             return E_POINTER;
  405.         }
  406.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  407.             return DMO_E_INVALIDSTREAMINDEX;
  408.         }
  409.         LockIt lck(static_cast<_DERIVED_ *>(this));
  410.         return INTERNAL_CALL(_DERIVED_, GetInputMaxLatency)(ulStreamIndex, prtLatency);
  411.     }
  412.     STDMETHODIMP SetInputMaxLatency(unsigned long ulStreamIndex, REFERENCE_TIME rtLatency) {
  413.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  414.             return DMO_E_INVALIDSTREAMINDEX;
  415.         }
  416.         LockIt lck(static_cast<_DERIVED_ *>(this));
  417.         return INTERNAL_CALL(_DERIVED_, SetInputMaxLatency)(ulStreamIndex, rtLatency);
  418.     }
  419.     STDMETHODIMP Discontinuity(ULONG ulStreamIndex) {
  420.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  421.             return DMO_E_INVALIDSTREAMINDEX;
  422.         }
  423.         LockIt lck(static_cast<_DERIVED_ *>(this));
  424.         if (!m_fTypesSet) {
  425.             return DMO_E_TYPE_NOT_SET;
  426.         }
  427.         if (S_OK != INTERNAL_CALL(_DERIVED_, AcceptingInput)(ulStreamIndex)) {
  428.             return DMO_E_NOTACCEPTING;
  429.         }
  430.         return INTERNAL_CALL(_DERIVED_, Discontinuity)(ulStreamIndex);
  431.     }
  432.     STDMETHODIMP Flush()
  433.     {
  434.         LockIt lck(static_cast<_DERIVED_ *>(this));
  435.         if (!m_fTypesSet) {
  436.             return S_OK;
  437.         }
  438.         if (m_fFlushed) {
  439.             return S_OK;
  440.         }
  441.         HRESULT hr =  INTERNAL_CALL(_DERIVED_, Flush)();
  442.         m_fFlushed = true;
  443.         return hr;
  444.     }
  445.     STDMETHODIMP AllocateStreamingResources() {
  446.         LockIt lck(static_cast<_DERIVED_ *>(this));
  447.         if (!m_fTypesSet) {
  448.             return DMO_E_TYPE_NOT_SET;
  449.         }
  450.         if (m_fResourcesAllocated) {
  451.             return S_OK;
  452.         }
  453.         HRESULT hr = INTERNAL_CALL(_DERIVED_, AllocateStreamingResources)();
  454.         if (SUCCEEDED(hr)) {
  455.             m_fResourcesAllocated = true;
  456.         }
  457.         return hr;
  458.     }
  459.     STDMETHODIMP FreeStreamingResources()
  460.     {
  461.         LockIt lck(static_cast<_DERIVED_ *>(this));
  462.         if (m_fResourcesAllocated) {
  463.             m_fResourcesAllocated = false;
  464.             INTERNAL_CALL(_DERIVED_, Flush)();
  465.             return INTERNAL_CALL(_DERIVED_, FreeStreamingResources)();
  466.         }
  467.         return S_OK;
  468.     }
  469.     //
  470.     // Processing methods - public entry points
  471.     //
  472.     STDMETHODIMP ProcessInput(
  473.         DWORD ulStreamIndex,
  474.         IMediaBuffer *pBuffer, // [in], must not be NULL
  475.         DWORD dwFlags, // [in] - discontinuity, timestamp, etc.
  476.         REFERENCE_TIME rtTimestamp, // [in], valid if flag set
  477.         REFERENCE_TIME rtTimelength // [in], valid if flag set
  478.     ) {
  479.         if (!pBuffer) {
  480.             return E_POINTER;
  481.         }
  482.         if (ulStreamIndex >= NUMBEROFINPUTS) {
  483.             return DMO_E_INVALIDSTREAMINDEX;
  484.         }
  485.         if (dwFlags & ~(DMO_INPUT_DATA_BUFFERF_SYNCPOINT |
  486.                         DMO_INPUT_DATA_BUFFERF_TIME |
  487.                         DMO_INPUT_DATA_BUFFERF_TIMELENGTH)) {
  488.             return E_INVALIDARG;
  489.         }
  490.         LockIt lck(static_cast<_DERIVED_ *>(this));
  491.         //  Make sure all streams have media types set and resources are allocated
  492.         HRESULT hr = AllocateStreamingResources();
  493.         if (FAILED(hr)) {
  494.             return hr;
  495.         }
  496.         if (INTERNAL_CALL(_DERIVED_, AcceptingInput)(ulStreamIndex) != S_OK) {
  497.             return DMO_E_NOTACCEPTING;
  498.         }
  499.         m_fFlushed = false;
  500.         return INTERNAL_CALL(_DERIVED_, ProcessInput)(
  501.                                     ulStreamIndex,
  502.                                     pBuffer,
  503.                                     dwFlags,
  504.                                     rtTimestamp,
  505.                                     rtTimelength);
  506.     }
  507.     STDMETHODIMP ProcessOutput(
  508.                     DWORD dwFlags,
  509.                     DWORD ulOutputBufferCount,
  510.                     DMO_OUTPUT_DATA_BUFFER *pOutputBuffers,
  511.                     DWORD *pdwStatus)
  512.     {
  513.         if (pdwStatus == NULL) {
  514.             return E_POINTER;
  515.         }
  516.         if (ulOutputBufferCount != NUMBEROFOUTPUTS || (dwFlags & ~DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER)) {
  517.            return E_INVALIDARG;
  518.         }
  519.         if (NUMBEROFOUTPUTS != 0 && pOutputBuffers == NULL) {
  520.             return E_POINTER;
  521.         }
  522.         *pdwStatus = 0;
  523.         LockIt lck(static_cast<_DERIVED_ *>(this));
  524.         HRESULT hr = AllocateStreamingResources();
  525.         if (FAILED(hr)) {
  526.             return hr;
  527.         }
  528.         for (DWORD dw = 0; dw < NUMBEROFOUTPUTS; dw++) {
  529.             pOutputBuffers[dw].dwStatus = 0;
  530.         }
  531.         hr = INTERNAL_CALL(_DERIVED_, ProcessOutput)(
  532.                            dwFlags,
  533.                            ulOutputBufferCount,
  534.                            pOutputBuffers,
  535.                            pdwStatus);
  536.         // remember the DMO's incomplete status
  537.         for (dw = 0; dw < NUMBEROFOUTPUTS; dw++) {
  538.             if (pOutputBuffers[dw].dwStatus & DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE) {
  539.                 m_OutputInfo[dw].fIncomplete = TRUE;
  540.             } else {
  541.                 m_OutputInfo[dw].fIncomplete = FALSE;
  542.             }
  543.         }
  544.         return hr;
  545.     }
  546.     STDMETHODIMP DMOLock(LONG lLock)
  547.     {
  548.         if (lLock) {
  549.             static_cast<_DERIVED_ *>(this)->Lock();
  550.         } else {
  551.             static_cast<_DERIVED_ *>(this)->Unlock();
  552.         }
  553.         return S_OK;
  554.     }
  555. };
  556. #endif // _dmoimpl_h_