STDMETHODIMP CDelay::Process(ULONG ulSize, BYTE *pData, REFERENCE_TIME refTimeStart, DWORD dwFlags) { if (dwFlags &= ~DMO_INPLACE_ZERO) return E_INVALIDARG; if (!pData) { return E_POINTER; } ATLTRACE2(atlTraceGeneral, 3, "Process: %d bytes. Time stamp: %f\n", ulSize, RefTime2Double(refTimeStart)); LockIt lock(this); if (!InputTypeSet(0) || !OutputTypeSet(0)) { return DMO_E_TYPE_NOT_SET; } // Make sure all streams have media types set and resources are allocated HRESULT hr = AllocateStreamingResources(); if (SUCCEEDED(hr)) hr = DoProcessOutput(pData, pData, ulSize / m_pWave->nBlockAlign); return hr; // If this DMO supported an effect tail, it would return S_FALSE until // the tail was processed. See IMediaObjectInPlace::Process documentation. }
/////////////////////////////////// // // IMediaObjectImpl::InternalGetOutputType // // *** Called by GetOutputType, description below *** // // The GetOutputType method retrieves a preferred media type for a specified // output stream. // // Parameters // // dwOutputStreamIndex // Zero-based index of an output stream on the DMO. // // dwTypeIndex // Zero-based index on the set of acceptable media types. // // pmt // [out] Pointer to a DMO_MEDIA_TYPE structure allocated by the // caller. The method fills the structure with the media type. The // format block might be NULL, in which case the format type GUID is GUID_NULL. // // Return Value // S_OK Success // DMO_E_INVALIDSTREAMINDEX Invalid stream index // DMO_E_NO_MORE_ITEMS Type index is out of range // E_OUTOFMEMORY Insufficient memory // E_POINTER NULL pointer argument // // Call this method to enumerate an output stream's preferred media types. The // DMO assigns each media type an index value, in order of preference. The // most preferred type has an index of zero. To enumerate all the types, make // successive calls while incrementing the type index, until the method returns // DMO_E_NO_MORE_ITEMS. // // If the method succeeds, call MoFreeMediaType to free the format block. // // To set the media type, call the SetOutputType method. Setting the media type // on one stream can change another stream's preferred types. In fact, a stream // might not have a preferred type until the type is set on another stream. For // example, a decoder might not have a preferred output type until the input // type is set. However, the DMO is not required to update its preferred types // dynamically in this fashion. Thus, the types returned by this method are not // guaranteed to be valid; they might fail when used in the SetOutputType method. // Conversely, the DMO is not guaranteed to enumerate every media type that it // supports. To test whether a particular media type is acceptable, call // SetOutputType with the DMO_SET_TYPEF_TEST_ONLY flag. // // HRESULT CHXAudioDeviceHookBase::InternalGetOutputType(DWORD dwOutputStreamIndex, DWORD dwTypeIndex, DMO_MEDIA_TYPE *pmt) { // This function resembles InternalGetInputType() since the input and output types must // be consistent for DirectSound HRESULT hr = S_OK; if (dwTypeIndex > 0) { return DMO_E_NO_MORE_ITEMS; } // If pmt is NULL, and the type index is in range, we return S_OK if (pmt == NULL) { return S_OK; } // If the input type is set, we prefer to use that one if (InputTypeSet(0)) { return MoCopyMediaType(pmt, InputType(0)); } hr = MoInitMediaType(pmt, sizeof(WAVEFORMATEX)); if (SUCCEEDED(hr)) { pmt->majortype = MEDIATYPE_Audio; pmt->subtype = MEDIASUBTYPE_PCM; // We take PCM format! pmt->formattype = FORMAT_None; } return hr; }
HRESULT CDelay::InternalGetOutputType(DWORD dwOutputStreamIndex, DWORD dwTypeIndex, DMO_MEDIA_TYPE *pmt) { if (dwTypeIndex != 0) { return DMO_E_NO_MORE_ITEMS; } // if pmt is NULL, we just return S_OK if the type index is in range if (pmt == NULL) { return S_OK; } if (InputTypeSet(0)) // If the input type is set, we prefer that one { return MoCopyMediaType(pmt, InputType(0)); } else { // input type is not set, propose something we like return GetPcmType(pmt); } }
//////////////////////////////////////////// // // IMediaObjectImpl::InternalCheckOutputType // // Queries whether an output stream can accept a given media type. The derived // class must declare and implement this method. // // Parameters // // dwOutputStreamIndex // Index of an output stream. // // pmt // Pointer to a DMO_MEDIA_TYPE structure that describes the media type. // // Return Value // // Returns S_OK if the media type is valid, or DMO_E_INVALIDTYPE otherwise. // // Note: // // Called by IMediaObject::SetOutputType // HRESULT CHXAudioDeviceHookBase::InternalCheckOutputType(DWORD dwOutputStreamIndex,const DMO_MEDIA_TYPE *pmt) { // Check that we're PCM or float HRESULT hr = S_OK; if ((NULL == pmt) || (MEDIATYPE_Audio != pmt->majortype) || (MEDIASUBTYPE_PCM != pmt->subtype) || (FORMAT_WaveFormatEx != pmt->formattype && FORMAT_None != pmt->formattype) || (pmt->cbFormat < sizeof(WAVEFORMATEX)) || (NULL == pmt->pbFormat)) { hr = DMO_E_INVALIDTYPE; } // If other type set, accept only if identical to that. Otherwise accept // any standard PCM/float audio. if (SUCCEEDED(hr)) { if (InputTypeSet(0)) { const DMO_MEDIA_TYPE* pmtInput; pmtInput = InputType(0); if (memcmp(pmt->pbFormat, pmtInput->pbFormat, sizeof(WAVEFORMATEX))) { hr = DMO_E_INVALIDTYPE; } } else { WAVEFORMATEX* pWave = (WAVEFORMATEX*)pmt->pbFormat; if ((WAVE_FORMAT_PCM != pWave->wFormatTag) || ((8 != pWave->wBitsPerSample) && (16 != pWave->wBitsPerSample)) || ((1 != pWave->nChannels) && (2 != pWave->nChannels)) || ( // Supported sample rates: (96000 != pWave->nSamplesPerSec) && (48000 != pWave->nSamplesPerSec) && (44100 != pWave->nSamplesPerSec) && (32000 != pWave->nSamplesPerSec) && (22050 != pWave->nSamplesPerSec) && (16000 != pWave->nSamplesPerSec) && (11025 != pWave->nSamplesPerSec) && (8000 != pWave->nSamplesPerSec) && TRUE // You may delete && TRUE ) || (pWave->nBlockAlign != pWave->nChannels * pWave->wBitsPerSample / 8) || (pWave->nAvgBytesPerSec != pWave->nSamplesPerSec * pWave->nBlockAlign)) { hr = DMO_E_INVALIDTYPE; } } } return hr; }
STDMETHODIMP CDelay::Clone(IMediaObjectInPlace **ppMediaObject) { HRESULT hr; if (!ppMediaObject) { return E_POINTER; } *ppMediaObject = NULL; // Make a new one CDelay *pTemp = new CComObject<CDelay>; if (!pTemp) { return E_OUTOFMEMORY; } // Set the media types CComQIPtr<IMediaObject, &IID_IMediaObject> pMediaObj(pTemp); _ASSERTE(pMediaObj != NULL); if (InputTypeSet(0)) { hr = pMediaObj->SetInputType(0, InputType(0), 0); if (FAILED(hr)) { return hr; } } if (OutputTypeSet(0)) { hr = pMediaObj->SetOutputType(0, OutputType(0), 0); if (FAILED(hr)) { return hr; } } // Everything is OK, return the AddRef'd pointer. return pTemp->QueryInterface(IID_IMediaObjectInPlace, (void**)ppMediaObject); }
HRESULT CDelay::InternalGetInputSizeInfo(DWORD dwInputStreamIndex, DWORD *pcbSize, DWORD *pcbMaxLookahead, DWORD *pcbAlignment) { // IMediaObjectImpl validates this for us... _ASSERTE(InputTypeSet(dwInputStreamIndex)); // And we expect only PCM audio types. _ASSERTE(InputType(dwInputStreamIndex)->formattype == FORMAT_WaveFormatEx); WAVEFORMATEX *pWave = (WAVEFORMATEX*)InputType(dwInputStreamIndex)->pbFormat; *pcbSize = pWave->nBlockAlign; *pcbMaxLookahead = 0; *pcbAlignment = 1; return S_OK; }
HRESULT CDelay::InternalCheckOutputType(DWORD dwOutputStreamIndex, const DMO_MEDIA_TYPE *pmt) { // If our output type is already set, reject format changes if (OutputTypeSet(dwOutputStreamIndex) && !TypesMatch(pmt, OutputType(dwOutputStreamIndex))) { return DMO_E_INVALIDTYPE; } // If our input type is already set, the output type must match else if (InputTypeSet(dwOutputStreamIndex) && !TypesMatch(pmt, InputType(dwOutputStreamIndex))) { return DMO_E_INVALIDTYPE; } // If no types are set yet, validate the format else { return CheckPcmFormat(pmt); } }