int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const { QVarLengthArray<IBaseFilter *, 16> filters; source->AddRef(); filters.append(source); int streamTypes = 0; while (!filters.isEmpty()) { IEnumPins *pins = 0; IBaseFilter *filter = filters[filters.size() - 1]; filters.removeLast(); if (SUCCEEDED(filter->EnumPins(&pins))) { for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { PIN_DIRECTION direction; if (pin->QueryDirection(&direction) == S_OK && direction == PINDIR_OUTPUT) { AM_MEDIA_TYPE connectionType; if (SUCCEEDED(pin->ConnectionMediaType(&connectionType))) { IPin *peer = 0; if (connectionType.majortype == MEDIATYPE_Audio) { streamTypes |= AudioStream; } else if (connectionType.majortype == MEDIATYPE_Video) { streamTypes |= VideoStream; } else if (SUCCEEDED(pin->ConnectedTo(&peer))) { PIN_INFO peerInfo; if (SUCCEEDED(peer->QueryPinInfo(&peerInfo))) filters.append(peerInfo.pFilter); peer->Release(); } } else { streamTypes |= findStreamType(pin); } } } } filter->Release(); } return streamTypes; }
void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel) { if( !pGraph ) { return; } IEnumFilters *pFilters; DbgLog((LOG_TRACE,dwLevel,TEXT("DumpGraph [%x]"), pGraph)); if (FAILED(pGraph->EnumFilters(&pFilters))) { DbgLog((LOG_TRACE,dwLevel,TEXT("EnumFilters failed!"))); } IBaseFilter *pFilter; ULONG n; while (pFilters->Next(1, &pFilter, &n) == S_OK) { FILTER_INFO info; if (FAILED(pFilter->QueryFilterInfo(&info))) { DbgLog((LOG_TRACE,dwLevel,TEXT(" Filter [%x] -- failed QueryFilterInfo"), pFilter)); } else { QueryFilterInfoReleaseGraph(info); // !!! should QueryVendorInfo here! DbgLog((LOG_TRACE,dwLevel,TEXT(" Filter [%x] '%ls'"), pFilter, info.achName)); IEnumPins *pins; if (FAILED(pFilter->EnumPins(&pins))) { DbgLog((LOG_TRACE,dwLevel,TEXT("EnumPins failed!"))); } else { IPin *pPin; while (pins->Next(1, &pPin, &n) == S_OK) { PIN_INFO info; if (FAILED(pPin->QueryPinInfo(&info))) { DbgLog((LOG_TRACE,dwLevel,TEXT(" Pin [%x] -- failed QueryPinInfo"), pPin)); } else { QueryPinInfoReleaseFilter(info); IPin *pPinConnected = NULL; HRESULT hr = pPin->ConnectedTo(&pPinConnected); if (pPinConnected) { DbgLog((LOG_TRACE,dwLevel,TEXT(" Pin [%x] '%ls' [%sput]") TEXT(" Connected to pin [%x]"), pPin, info.achName, info.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out"), pPinConnected)); pPinConnected->Release(); // perhaps we should really dump the type both ways as a sanity // check? if (info.dir == PINDIR_OUTPUT) { AM_MEDIA_TYPE mt; hr = pPin->ConnectionMediaType(&mt); if (SUCCEEDED(hr)) { DisplayType(TEXT("Connection type"), &mt); FreeMediaType(mt); } } } else { DbgLog((LOG_TRACE,dwLevel, TEXT(" Pin [%x] '%ls' [%sput]"), pPin, info.achName, info.dir == PINDIR_INPUT ? TEXT("In") : TEXT("Out"))); } } pPin->Release(); } pins->Release(); } } pFilter->Release(); } pFilters->Release(); }
void gui::dx::audio_playerX::initialize_speedup_filter() { if (speedup_filter_available_valid && !speedup_filter_available) { // We don't seem to have the filter. Too bad. return; } // Either the filter exists or we haven't tried yet. Let's try to create // it and remember whether it worked. IBaseFilter *pNewFilter = NULL; HRESULT res; res = CoCreateInstance(CLSID_TPBVupp69, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pNewFilter); if (res != S_OK) { traceX("dx_audio_player: Speedup filter not available, error 0x%x", res); speedup_filter_available = false; speedup_filter_available_valid = true; return; } res = m_graph_builder->AddFilter(pNewFilter, NULL); if (res != S_OK) { traceX("dx_audio_player: AddFilter(Speedup filter): error 0x%x", res); pNewFilter->Release(); return; } speedup_filter_available = true; speedup_filter_available_valid = true; // AM_DBG lib::debugX("dx_audio_player: added speedup filter to graph"); // Next step: find out where we want to add the filter to the graph. // We iterate over the filter graph, then for each item in the graph // we iterate over the connected output pins util we find one we like. IPin *pOutputPin = NULL; IPin *pInputPin = NULL; IEnumFilters *pEnumFilters = NULL; res = m_graph_builder->EnumFilters(&pEnumFilters); if (res != S_OK) { traceX("dx_audio_filter: EnumFilters: error 0x%x", res); return; } IBaseFilter *pCurFilter; while (pOutputPin == NULL && (res=pEnumFilters->Next(1, &pCurFilter, NULL)) == S_OK) { AM_DBG { FILTER_INFO info; LPWSTR vendorInfo; res = pCurFilter->QueryFilterInfo(&info); if (res != S_OK) info.achName[0] = 0; res = pCurFilter->QueryVendorInfo(&vendorInfo); if (res != S_OK) vendorInfo = L""; //ambulant::lib::textptr tInfo(info.achName); //ambulant::lib::textptr tVendorInfo(vendorInfo); //lib::debugX("dx_audio_filter: filter found: '%s' vendor '%s'", tInfo.c_str(), tVendorInfo.c_str()); } IEnumPins *pEnumPins; res = pCurFilter->EnumPins(&pEnumPins); IPin *pCurPin; while (pOutputPin == NULL && (res=pEnumPins->Next(1, &pCurPin, NULL)) == S_OK) { AM_MEDIA_TYPE mediaType; PIN_DIRECTION curPinDir; res = pCurPin->QueryDirection(&curPinDir); HRESULT res2 = pCurPin->ConnectionMediaType(&mediaType); if (res == S_OK && res2 == S_OK && curPinDir == PINDIR_OUTPUT && mediaType.majortype == MEDIATYPE_Audio&& mediaType.subtype == MEDIASUBTYPE_PCM){ pOutputPin = pCurPin; res = pOutputPin->ConnectedTo(&pInputPin); if (res != S_OK) { // This output pin was the correct type, but not connected. // So it cannot be the one we're looking for. pOutputPin = pInputPin = NULL; } else { // Found it! pOutputPin->AddRef(); pInputPin->AddRef(); } } if (res2 == S_OK) { if (mediaType.cbFormat != 0) { CoTaskMemFree((PVOID)mediaType.pbFormat); } } pCurPin->Release(); } if (res != S_FALSE && res != S_OK) traceX("dx_audio_filter: enumerating pins: error 0x%x", res); pEnumPins->Release(); pCurFilter->Release(); } if (res != S_FALSE && res != S_OK) traceX("dx_audio_filter: enumerating filters: error 0x%x", res); pEnumFilters->Release(); // We have the correct pins now. if (pOutputPin) { traceX("dx_audio_filter: found the right pins!"); } else { traceX("dx_audio_filter: could not find a good pin"); pOutputPin->Release(); pInputPin->Release(); return; } // Now we need to find the pins on our speedup filter. IPin *pFilterInputPin = NULL; IPin *pFilterOutputPin = NULL; IEnumPins *pEnumPins; res = pNewFilter->EnumPins(&pEnumPins); IPin *pCurPin; while (res=pEnumPins->Next(1, &pCurPin, NULL) == S_OK) { PIN_DIRECTION pinDir; res = pCurPin->QueryDirection(&pinDir); //assert(res == S_OK); if (pinDir == PINDIR_INPUT) { if (pFilterInputPin) { traceX("dx_audio_filter: multiple input pins on filter"); goto bad; } pFilterInputPin = pCurPin; pFilterInputPin->AddRef(); } else { if (pFilterOutputPin) { traceX("dx_audio_filter: multiple output pins on filter"); goto bad; } pFilterOutputPin = pCurPin; pFilterOutputPin->AddRef(); } } if (!pFilterInputPin) { traceX("dx_audio_filter: no input pin on filter"); goto bad; } if (!pFilterOutputPin) { traceX("dx_audio_filter: no output pin on filter"); goto bad; } // We have everything. Sever the old connection and insert the filter. res = m_graph_builder->Disconnect(pOutputPin); if (res) { traceX("dx_audio_filter: Severing old connection: error 0x%x", res); goto bad; } res = m_graph_builder->Disconnect(pInputPin); if (res) { traceX("dx_audio_filter: Severing old connection: error 0x%x", res); goto bad; } res = m_graph_builder->Connect(pOutputPin, pFilterInputPin); if (res) { traceX("dx_audio_filter: Creating filter input connection: error 0x%x", res); goto bad; } res = m_graph_builder->Connect(pFilterOutputPin, pInputPin); if (res) { traceX("dx_audio_filter: Creating filter output connection: error 0x%x", res); goto bad; } // Finally remember the interface to set speedup/slowdown, and register ourselves // in the global pool (so Amis can change our speed). res = pNewFilter->QueryInterface(IID_IVuppInterface, (void**) &m_audio_speedup); if (res != S_OK) { traceX("dx_audio_filter: filter does not provide IVuppInterface"); goto bad; } set_rate(s_current_playback_rate); bad: if (pOutputPin) pOutputPin->Release(); if (pInputPin) pInputPin->Release(); if (pFilterOutputPin) pFilterOutputPin->Release(); if (pFilterInputPin) pFilterInputPin->Release(); return; }
HRESULT FindRenderer(IGraphBuilder *pGB, const GUID *mediatype, IBaseFilter **ppFilter) { HRESULT hr; IEnumFilters *pEnum = NULL; IBaseFilter *pFilter = NULL; IPin *pPin; ULONG ulFetched, ulInPins, ulOutPins; BOOL bFound=FALSE; // Verify graph builder interface if (!pGB) return E_NOINTERFACE; // Verify that a media type was passed if (!mediatype) return E_POINTER; // Clear the filter pointer in case there is no match if (ppFilter) *ppFilter = NULL; // Get filter enumerator hr = pGB->EnumFilters(&pEnum); if (FAILED(hr)) return hr; pEnum->Reset(); // Enumerate all filters in the graph while(!bFound && (pEnum->Next(1, &pFilter, &ulFetched) == S_OK)) { #ifdef DEBUG // Read filter name for debugging purposes FILTER_INFO FilterInfo; TCHAR szName[256]; hr = pFilter->QueryFilterInfo(&FilterInfo); if (SUCCEEDED(hr)) { // Show filter name in debugger #ifdef UNICODE lstrcpy(szName, FilterInfo.achName); #else WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName, -1, szName, 256, 0, 0); #endif FilterInfo.pGraph->Release(); } #endif // Find a filter with one input and no output pins hr = CountFilterPins(pFilter, &ulInPins, &ulOutPins); if (FAILED(hr)) break; if ((ulInPins == 1) && (ulOutPins == 0)) { // Get the first pin on the filter pPin=0; pPin = GetInPin(pFilter, 0); // Read this pin's major media type AM_MEDIA_TYPE type= {0}; hr = pPin->ConnectionMediaType(&type); if (FAILED(hr)) break; // Is this pin's media type the requested type? // If so, then this is the renderer for which we are searching. // Copy the interface pointer and return. if (type.majortype == *mediatype) { // Found our filter *ppFilter = pFilter; bFound = TRUE;; } // This is not the renderer, so release the interface. else pFilter->Release(); // Delete memory allocated by ConnectionMediaType() FreeMediaType(type); } else { // No match, so release the interface pFilter->Release(); } } pEnum->Release(); return hr; }