HRESULT CDelay::InternalGetInputType(DWORD dwInputStreamIndex, 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 (OutputTypeSet(0)) // If the input type is set, we prefer that one { return MoCopyMediaType(pmt, OutputType(0)); } else { // if output type is not set, propose something we like return GetPcmType(pmt); } }
///////////////////////////////// // // IMediaObjectImpl::InternalGetInputType // // *** Called by GetInputType, description below *** // // The GetInputType method retrieves a preferred media type for a specified // input stream. // // Parameters // // dwInputStreamIndex // Zero-based index of an input 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 input 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 SetInputType 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 // SetInputType 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 SetInputType with the DMO_SET_TYPEF_TEST_ONLY flag. // HRESULT CHXAudioDeviceHookBase::InternalGetInputType(DWORD dwInputStreamIndex, DWORD dwTypeIndex, DMO_MEDIA_TYPE *pmt) { // This function resembles InternalGetOutputType() 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 output type is set, we prefer to use that one if (OutputTypeSet(0)) { return MoCopyMediaType(pmt, OutputType(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; }
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. }
HRESULT CDelay::InternalGetOutputSizeInfo(DWORD dwOutputStreamIndex, DWORD *pcbSize, DWORD *pcbAlignment) { // IMediaObjectImpl validates this for us... _ASSERTE(OutputTypeSet(dwOutputStreamIndex)); // And we expect only PCM audio types. _ASSERTE(OutputType(dwOutputStreamIndex)->formattype == FORMAT_WaveFormatEx); WAVEFORMATEX *pWave = (WAVEFORMATEX*)OutputType(dwOutputStreamIndex)->pbFormat; *pcbSize = pWave->nBlockAlign; *pcbAlignment = 1; return S_OK; }
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::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); } }
//////////////////////////////////// // // IMediaObjectImpl::InternalCheckInputType // // Queries whether an input stream can accept a given media type. // The derived class must declare and implement this method. // // Parameters // // dwInputStreamIndex // Index of an input 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::SetInputType // HRESULT CHXAudioDeviceHookBase::InternalCheckInputType(DWORD dwInputStreamIndex, const DMO_MEDIA_TYPE *pmt) { WAVEFORMATEX* pWave = (WAVEFORMATEX*)pmt->pbFormat; HRESULT hr = S_OK; // Check that we're PCM or float 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 (OutputTypeSet(0)) { const DMO_MEDIA_TYPE* pmtOutput; pmtOutput = OutputType(0); if (memcmp(pmt->pbFormat, pmtOutput->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; } } } if (SUCCEEDED(hr)) { // We will remember the number of channels, bps, and sample rate of the input type m_nChannels = pWave->nChannels; m_wBitsPerSample = pWave->wBitsPerSample; m_nSamplesPerSec = pWave->nSamplesPerSec; } return hr; }