MediaTypesList CaptureDShow::listMediaTypes(IBaseFilter *filter) const { PinList pins = this->enumPins(filter, PINDIR_OUTPUT); MediaTypesList mediaTypes; for (const PinPtr &pin: pins) { IEnumMediaTypes *pEnum = NULL; pin->EnumMediaTypes(&pEnum); AM_MEDIA_TYPE *mediaType = NULL; while (pEnum->Next(1, &mediaType, NULL) == S_OK) if (mediaType->formattype == FORMAT_VideoInfo && mediaType->cbFormat >= sizeof(VIDEOINFOHEADER) && mediaType->pbFormat != NULL && guidToStr->contains(mediaType->subtype)) { mediaTypes << MediaTypePtr(mediaType, this->deleteMediaType); } else { this->deleteMediaType(mediaType); } pEnum->Release(); } return mediaTypes; }
int DirectShowPlayerService::findStreamType(IPin *pin) const { IEnumMediaTypes *types; if (SUCCEEDED(pin->EnumMediaTypes(&types))) { bool video = false; bool audio = false; bool other = false; for (AM_MEDIA_TYPE *type = 0; types->Next(1, &type, 0) == S_OK; DirectShowMediaType::deleteType(type)) { if (type->majortype == MEDIATYPE_Audio) audio = true; else if (type->majortype == MEDIATYPE_Video) video = true; else other = true; } types->Release(); if (other) return 0; else if (audio && !video) return AudioStream; else if (!audio && video) return VideoStream; else return 0; } else { return 0; } }
HRESULT Captura::IniciarVentanaVideo(HWND hWnd,int width, int height) { HRESULT hr; RECT rcDest; // CComPtr<IAMStreamConfig> pConfig; IAMStreamConfig * pConfig; IEnumMediaTypes *pMedia; AM_MEDIA_TYPE *pmt = NULL, *pfnt = NULL; hr = m_pCamOutPin->EnumMediaTypes( &pMedia ); if(SUCCEEDED(hr)) { while(pMedia->Next(1, &pmt, 0) == S_OK) { if( pmt->formattype == FORMAT_VideoInfo ) { VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pmt->pbFormat; if( vih->bmiHeader.biWidth == width && vih->bmiHeader.biHeight == height ) { pfnt = pmt; break; } BorrarTipoMedio( pmt ); } } pMedia->Release(); } hr = m_pCamOutPin->QueryInterface( IID_IAMStreamConfig, (void **) &pConfig ); if(SUCCEEDED(hr)) { if( pfnt != NULL ) { hr=pConfig->SetFormat( pfnt ); BorrarTipoMedio( pfnt ); } hr = pConfig->GetFormat( &pfnt ); if(SUCCEEDED(hr)) { m_nAncho = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biWidth; m_nAlto = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biHeight; BorrarTipoMedio( pfnt ); } } ::GetClientRect (hWnd,&rcDest); hr = m_pWC->SetVideoPosition(NULL, &rcDest); return hr; }
/* 设置捕获图像帧的格式,遍历所有格式是否有预定格式,若没有则以默认格式捕获 */ HRESULT CVMR_Capture::InitVideoWindow(HWND hWnd,int width, int height) { HRESULT hr; RECT rcDest; IAMStreamConfig *pConfig; IEnumMediaTypes *pMedia; AM_MEDIA_TYPE *pmt = NULL, *pfnt = NULL; hr = m_pCamOutPin->EnumMediaTypes( &pMedia ); if(SUCCEEDED(hr)) { //把所有视频的所有格式遍历一遍,看是否有预定的格式 while(pMedia->Next(1, &pmt, 0) == S_OK) { if( pmt->formattype == FORMAT_VideoInfo ) { VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pmt->pbFormat; // 当前的格式是否与预定格式相同,即宽和高相同 if( vih->bmiHeader.biWidth == width && vih->bmiHeader.biHeight == height ) { pfnt = pmt; break; } DeleteMediaType( pmt ); } } pMedia->Release(); } hr = m_pCamOutPin->QueryInterface( IID_IAMStreamConfig, (void **) &pConfig ); if(SUCCEEDED(hr)) { // 有预定的格式 if( pfnt != NULL ) { hr=pConfig->SetFormat( pfnt ); DeleteMediaType( pfnt ); } // 没有预定的格式,读取缺省媒体格式 hr = pConfig->GetFormat( &pfnt ); if(SUCCEEDED(hr)) { m_nWidth = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biWidth; //读取高 m_nHeight = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biHeight; //读取宽 DeleteMediaType( pfnt ); } } // 获取传入窗口的区域,以设置显示窗口 ::GetClientRect (hWnd,&rcDest); hr = m_pWC->SetVideoPosition(NULL, &rcDest); return hr; }
HRESULT CBasePin::AgreeMediaType( IPin *pReceivePin, const CMediaType *pmt) { ASSERT(pReceivePin); IEnumMediaTypes *pEnumMediaTypes = NULL; // if the media type is fully specified then use that if ( (pmt != NULL) && (!pmt->IsPartiallySpecified())) { // if this media type fails, then we must fail the connection // since if pmt is nonnull we are only allowed to connect // using a type that matches it. return AttemptConnection(pReceivePin, pmt); } /* Try the other pin's enumerator */ HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES; for (int i = 0; i < 2; i++) { HRESULT hr; if (i == (int)m_bTryMyTypesFirst) { hr = pReceivePin->EnumMediaTypes(&pEnumMediaTypes); } else { hr = EnumMediaTypes(&pEnumMediaTypes); } if (SUCCEEDED(hr)) { ASSERT(pEnumMediaTypes); hr = TryMediaTypes(pReceivePin,pmt,pEnumMediaTypes); pEnumMediaTypes->Release(); if (SUCCEEDED(hr)) { return NOERROR; } else { // try to remember specific error codes if there are any if ((hr != E_FAIL) && (hr != E_INVALIDARG) && (hr != VFW_E_TYPE_NOT_ACCEPTED)) { hrFailure = hr; } } } } return hrFailure; }
BOOL CheckMediaTypes(IPin *pin) { IEnumMediaTypes *pMedia; AM_MEDIA_TYPE *pmt = NULL, *pfnt = NULL; HRESULT m_res = pin->EnumMediaTypes(&pMedia); pMedia->Reset(); while((m_res = pMedia->Next(1, &pmt, NULL)) == S_OK) { if (pmt->formattype == FORMAT_VideoInfo) { VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *) pmt->pbFormat; DeleteMediaType(pmt); } } pMedia->Release(); return TRUE; }
HRESULT MiniPlayer::findPin(IBaseFilter *pFilter, int dir, const GUID &mediaMajorType, IPin **pOutPin) { IEnumPins *pEnumPins = NULL; IEnumMediaTypes *pEnumMediaTypes = NULL; IPin *pPin = NULL; PIN_INFO pinInfo; //FILTER_INFO filterInfo; AM_MEDIA_TYPE *pMediaType = NULL; //HRESULT hr = pFilter->QueryFilterInfo(&filterInfo); //if(hr == S_OK) //{ // ctrace(L"%s Pins:\n", filterInfo.achName); //} HRESULT hr = pFilter->EnumPins(&pEnumPins); if(FAILED(hr)) return hr; while(pEnumPins->Next(1, &pPin, NULL) == S_OK) { hr = pPin->QueryPinInfo(&pinInfo); if(FAILED(hr)) continue; if(pinInfo.dir == dir) { hr = pPin->EnumMediaTypes(&pEnumMediaTypes); if(FAILED(hr))continue; while(pEnumMediaTypes->Next(1, &pMediaType, NULL) == S_OK) { if(pMediaType->majortype == mediaMajorType) { *pOutPin = pPin; return S_OK; } } pEnumMediaTypes->Release(); } } pEnumPins->Release(); return -1; }
HRESULT RecordGraph::GetUnconnectedPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin, GUID MediaType) { *ppPin = 0; IEnumPins *pEnum = 0; IPin *pPin = 0; HRESULT hr = pFilter->EnumPins(&pEnum); if(FAILED(hr)) return hr; while (pEnum->Next(1, &pPin, NULL) == S_OK) { PIN_DIRECTION ThisPinDir; pPin->QueryDirection(&ThisPinDir); if (ThisPinDir == PinDir) { IPin *pTmp = 0; hr = pPin->ConnectedTo(&pTmp); if (SUCCEEDED(hr)) pTmp->Release(); else { IEnumMediaTypes *pEnumMediaType = NULL; hr = pPin->EnumMediaTypes(&pEnumMediaType); if (MediaType == MEDIATYPE_NULL) { pEnum->Release(); *ppPin = pPin; pPin->Release(); return S_OK; }else if(SUCCEEDED(this->CheckMediaType(pEnumMediaType, MediaType))) { pEnum->Release(); *ppPin = pPin; pPin->Release(); return S_OK; } pEnumMediaType->Release(); } } pPin->Release(); } pEnum->Release(); return E_FAIL; }
void MiniPlayer::listAllPins(IBaseFilter *pFilter) { IEnumPins *pEnumPins = NULL; IEnumMediaTypes *pEnumMediaTypes = NULL; IPin *pPin = NULL; PIN_INFO pinInfo; FILTER_INFO filterInfo; AM_MEDIA_TYPE *pMediaType = NULL; HRESULT hr = pFilter->QueryFilterInfo(&filterInfo); if(hr == S_OK) { ctrace(L"%s Pins:\n", filterInfo.achName); } hr = pFilter->EnumPins(&pEnumPins); if(FAILED(hr)) return; while(pEnumPins->Next(1, &pPin, NULL) == S_OK) { hr = pPin->QueryPinInfo(&pinInfo); if(FAILED(hr)) continue; ctrace(L"\t [%s] %s: ", (pinInfo.dir == PINDIR_INPUT)? L"INPUT": L"OUTPUT", pinInfo.achName); hr = pPin->EnumMediaTypes(&pEnumMediaTypes); if(FAILED(hr))continue; while(pEnumMediaTypes->Next(1, &pMediaType, NULL) == S_OK) { if(pMediaType->majortype == MEDIATYPE_Video) ctrace("Video "); if(pMediaType->majortype == MEDIATYPE_Audio) ctrace("Audio "); } ctrace("\n"); pEnumMediaTypes->Release(); } pEnumPins->Release(); }
HRESULT CVMR_Capture::InitVideoWindow(HWND hWnd,int width, int height) { // Set the grabbing size // First we iterate through the available media types and // store the first one that fits the requested size. // If we have found one, we set it. // In any case we query the size of the current media type // to have this information for clients of this class. // Gerhard Reitmayr <reitmayr@i ...............> HRESULT hr; RECT rcDest; CComPtr<IAMStreamConfig> pConfig; IEnumMediaTypes *pMedia; AM_MEDIA_TYPE *pmt = NULL, *pfnt = NULL; hr = m_pCamOutPin->EnumMediaTypes( &pMedia ); if(SUCCEEDED(hr)) { while(pMedia->Next(1, &pmt, 0) == S_OK) { if( pmt->formattype == FORMAT_VideoInfo ) { VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)pmt->pbFormat; // printf("Size %i %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight ); if( vih->bmiHeader.biWidth == width && vih->bmiHeader.biHeight == height ) { pfnt = pmt; // printf("found mediatype with %i %i\n", vih->bmiHeader.biWidth, vih->bmiHeader.biHeight ); //char test[100]; //sprintf(test,"Width=%d\nHeight=%d",vih->bmiHeader.biWidth, vih->bmiHeader.biHeight); //MessageBox(test); break; } DeleteMediaType( pmt ); } } pMedia->Release(); } hr = m_pCamOutPin->QueryInterface( IID_IAMStreamConfig, (void **) &pConfig ); if(SUCCEEDED(hr)) { if( pfnt != NULL ) { hr=pConfig->SetFormat( pfnt ); //if(SUCCEEDED(hr)) //MessageBox("OK"); DeleteMediaType( pfnt ); } hr = pConfig->GetFormat( &pfnt ); if(SUCCEEDED(hr)) { m_nWidth = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biWidth; m_nHeight = ((VIDEOINFOHEADER *)pfnt->pbFormat)->bmiHeader.biHeight; DeleteMediaType( pfnt ); } } ::GetClientRect (hWnd,&rcDest); hr = m_pWC->SetVideoPosition(NULL, &rcDest); return hr; }
// // FillListBox // // Fill the list box with an enumeration of the media type that our // void NullIPProperties::FillListBox() { IEnumMediaTypes * pMTEnum; AM_MEDIA_TYPE *pMediaType; ULONG count; TCHAR szBuffer[200]; int Loop = 0, wextent = 0 ; SIZE extent ; FILTER_STATE state ; CMediaType *pmtCurrent ; // // get the current media type // ASSERT(m_pINullIPP); m_pINullIPP->get_MediaType (&pmtCurrent); m_nIndex = 0 ; // // Fill the first entry of the list box with a choice to select any media. // LoadString(g_hInst, IDS_ANYTYPE, szBuffer, 200); SendMessage (m_hwndLB, LB_ADDSTRING, 0, (LPARAM)szBuffer) ; // // if the filter is not connected on the input, nothing more to fill // also return if we haven't gotten any pin interface // if (m_pPin == NULL) return ; // // get a dc for the control. need this to get the extent of the strings // that we put in the list box (so that we can get a horiz scroll bar). // HDC hdc = GetDC (m_hwndLB) ; // // now enumerate the media types from our pin. // HRESULT hr = m_pPin->EnumMediaTypes(&pMTEnum); if (SUCCEEDED(hr)) { ASSERT(pMTEnum); pMTEnum->Next(1, &pMediaType, &count); while (count == 1) // While a media type retrieved OK { // // Count it - used to set m_nIndex. // Loop++; // // convert the media type to string. // CTextMediaType(*pMediaType).AsText(szBuffer, 200, TEXT(" - "), TEXT(" - "), TEXT("\0")); // // if the mediatype matches the current one, set m_nIndex to cur index // if (*pmtCurrent == *pMediaType) { m_nIndex = Loop; } // // get the extent of the string and save the max extent // GetTextExtentPoint (hdc, szBuffer, lstrlen(szBuffer), &extent) ; if (extent.cx > wextent) wextent = extent.cx ; // // add the string to the list box. // SendMessage (m_hwndLB, LB_ADDSTRING, 0, (LPARAM)szBuffer) ; // // enumerate the next media type and loop. // DeleteMediaType(pMediaType); pMTEnum->Next(1, &pMediaType, &count); } pMTEnum->Release(); SendMessage (m_hwndLB, LB_SETHORIZONTALEXTENT, wextent, 0) ; SendMessage (m_hwndLB, LB_SETCURSEL, m_nIndex, 0) ; } ASSERT(m_pINullIPP); // // if the filter is in a running state, disable the list box and allow // no input. // m_pINullIPP->get_State(&state); EnableWindow (m_hwndLB, state != State_Running) ; } // FillListBox
bool DeviceSource::LoadFilters() { if(bCapturing || bFiltersLoaded) return false; bool bSucceeded = false; List<MediaOutputInfo> outputList; IAMStreamConfig *config = NULL; bool bAddedVideoCapture = false, bAddedAudioCapture = false, bAddedDevice = false; GUID expectedMediaType; IPin *devicePin = NULL, *audioPin = NULL; HRESULT err; String strShader; bUseThreadedConversion = API->UseMultithreadedOptimizations() && (OSGetTotalCores() > 1); //------------------------------------------------ // basic initialization vars bool bCheckForceAudio = data->GetInt(TEXT("forceCustomAudioDevice")) != 0; bUseCustomResolution = data->GetInt(TEXT("customResolution")); strDevice = data->GetString(TEXT("device")); strDeviceName = data->GetString(TEXT("deviceName")); strDeviceID = data->GetString(TEXT("deviceID")); strAudioDevice = data->GetString(TEXT("audioDevice")); strAudioName = data->GetString(TEXT("audioDeviceName")); strAudioID = data->GetString(TEXT("audioDeviceID")); strAudioGUID = data->GetString(TEXT("audioDeviceCLSID")); if(strAudioGUID.Compare(TEXT("CLSID_AudioInputDeviceCategory"))) matchGUID = CLSID_AudioInputDeviceCategory; if(strAudioGUID.Compare(TEXT("CLSID_VideoInputDeviceCategory"))) matchGUID = CLSID_VideoInputDeviceCategory; if(strAudioGUID.Compare(TEXT("CLSID_AudioRendererCategory"))) { //Log(TEXT("Dese are spekers.\n")); matchGUID = CLSID_AudioRendererCategory; } bFlipVertical = data->GetInt(TEXT("flipImage")) != 0; bFlipHorizontal = data->GetInt(TEXT("flipImageHorizontal")) != 0; opacity = data->GetInt(TEXT("opacity"), 100); float volume = data->GetFloat(TEXT("volume"), 1.0f); //------------------------------------------------ // chrom key stuff bUseChromaKey = data->GetInt(TEXT("useChromaKey")) != 0; keyColor = data->GetInt(TEXT("keyColor"), 0xFFFFFFFF); keySimilarity = data->GetInt(TEXT("keySimilarity")); keyBlend = data->GetInt(TEXT("keyBlend"), 80); keySpillReduction = data->GetInt(TEXT("keySpillReduction"), 50); if(keyBaseColor.x < keyBaseColor.y && keyBaseColor.x < keyBaseColor.z) keyBaseColor -= keyBaseColor.x; else if(keyBaseColor.y < keyBaseColor.x && keyBaseColor.y < keyBaseColor.z) keyBaseColor -= keyBaseColor.y; else if(keyBaseColor.z < keyBaseColor.x && keyBaseColor.z < keyBaseColor.y) keyBaseColor -= keyBaseColor.z; //------------------------------------------------ // get the device filter and pins if(strAudioDevice.IsValid()) { audioDeviceFilter = GetDeviceByValue(matchGUID, L"FriendlyName", strAudioName, L"DevicePath", strAudioID); if(!audioDeviceFilter) { AppWarning(TEXT("DShowAudioPlugin: Invalid audio device: name '%s', path '%s'"), strAudioName.Array(), strAudioID.Array()); } } soundOutputType = data->GetInt(TEXT("soundOutputType")); if(soundOutputType != 0) { if(matchGUID == CLSID_AudioRendererCategory) { err = capture->FindPin(audioDeviceFilter, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FALSE, 0, &audioPin); } else { err = capture->FindPin(audioDeviceFilter, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FALSE, 0, &audioPin); } if(FAILED(err)) { Log(TEXT("DShowAudioPlugin: No audio pin, result = %lX"), err); soundOutputType = 0; } } int soundTimeOffset = data->GetInt(TEXT("soundTimeOffset")); //GetOutputList(devicePin, outputList); //------------------------------------------------ // initialize the basic video variables and data //------------------------------------------------ // log audio info { String strTest; strTest = FormattedString(TEXT(" audio device: %s,\r\n audio device id %s,\r\n"), strAudioDevice.Array(), strAudioID.Array()); Log(TEXT("------------------------------------------")); Log(strTest.Array()); } //------------------------------------------------ // get audio pin configuration, optionally configure audio pin to 44100 GUID expectedAudioType; if(soundOutputType == 1) { IAMStreamConfig *audioConfig; if(SUCCEEDED(audioPin->QueryInterface(IID_IAMStreamConfig, (void**)&audioConfig))) { AM_MEDIA_TYPE *audioMediaType; if(SUCCEEDED(err = audioConfig->GetFormat(&audioMediaType))) { SetAudioInfo(audioMediaType, expectedAudioType); //Log(TEXT("Fixed size samples: %s\r\n"), (audioMediaType->bFixedSizeSamples) ? "Yes" : "No"); //Log(TEXT("Temporal Compression: %s\r\n"), (audioMediaType->bTemporalCompression) ? "Yes" : "No"); //Log(TEXT("cbFormat: %.16X\r\n"), audioMediaType->cbFormat); //Log(TEXT("Sample size: %u\r\n"), audioMediaType->lSampleSize); } else if(err == E_NOTIMPL) //elgato probably { IEnumMediaTypes *audioMediaTypes; if(SUCCEEDED(err = audioPin->EnumMediaTypes(&audioMediaTypes))) { ULONG i = 0; if((err = audioMediaTypes->Next(1, &audioMediaType, &i)) == S_OK) SetAudioInfo(audioMediaType, expectedAudioType); else { AppWarning(TEXT("DShowAudioPlugin: audioMediaTypes->Next failed, result = %08lX"), err); soundOutputType = 0; } audioMediaTypes->Release(); } else { AppWarning(TEXT("DShowAudioPlugin: audioMediaTypes->Next failed, result = %08lX"), err); soundOutputType = 0; } } else { AppWarning(TEXT("DShowAudioPlugin: Could not get audio format, result = %08lX"), err); soundOutputType = 0; } audioConfig->Release(); } else { soundOutputType = 0; } } //------------------------------------------------ // add video capture filter if any captureFilter = new CaptureFilter(this, MEDIATYPE_Video, expectedMediaType); if(FAILED(err = graph->AddFilter(captureFilter, NULL))) { AppWarning(TEXT("DShowAudioPlugin: Failed to add video capture filter to graph, result = %08lX"), err); goto cleanFinish; } bAddedVideoCapture = true; //------------------------------------------------ // add audio capture filter if any if(soundOutputType == 1) { audioFilter = new CaptureFilter(this, MEDIATYPE_Audio, expectedAudioType); if(!audioFilter) { AppWarning(TEXT("Failed to create audio capture filter")); soundOutputType = 0; } } else if(soundOutputType == 2) { if(FAILED(err = CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&audioFilter))) { AppWarning(TEXT("DShowPlugin: failed to create audio renderer, result = %08lX"), err); soundOutputType = 0; } IBasicAudio *basicAudio; if(SUCCEEDED(audioFilter->QueryInterface(IID_IBasicAudio, (void**)&basicAudio))) { long lVol = long((double(volume)*NEAR_SILENTf)-NEAR_SILENTf); if(lVol <= -NEAR_SILENT) lVol = -10000; basicAudio->put_Volume(lVol); basicAudio->Release(); } } if(soundOutputType != 0) { if(FAILED(err = graph->AddFilter(audioFilter, NULL))) { AppWarning(TEXT("DShowAudioPlugin: Failed to add audio capture filter to graph, result = %08lX"), err); goto cleanFinish; } bAddedAudioCapture = true; } //------------------------------------------------ // add primary device filter if(FAILED(err = graph->AddFilter(audioDeviceFilter, NULL))) { AppWarning(TEXT("DShowAudioPlugin: Failed to add audio device filter to graph, result = %08lX"), err); goto cleanFinish; } bAddedDevice = true; //------------------------------------------------ // connect all pins and set up the whole capture thing bool bConnected; if(soundOutputType != 0) { bConnected = SUCCEEDED(err = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, audioDeviceFilter, NULL, audioFilter)); if(!bConnected) { AppWarning(TEXT("DShowAudioPlugin: Failed to connect the audio device pin to the audio capture pin, result = %08lX"), err); soundOutputType = 0; } } if(FAILED(err = graph->QueryInterface(IID_IMediaControl, (void**)&control))) { AppWarning(TEXT("DShowAudioPlugin: Failed to get IMediaControl, result = %08lX"), err); goto cleanFinish; } if(soundOutputType == 1) { audioOut = new DeviceAudioSource; audioOut->Initialize(this); API->AddAudioSource(audioOut); audioOut->SetAudioOffset(soundTimeOffset); audioOut->SetVolume(volume); } bSucceeded = true; cleanFinish: SafeRelease(config); SafeRelease(devicePin); SafeRelease(audioPin); for(UINT i=0; i<outputList.Num(); i++) outputList[i].FreeData(); if(!bSucceeded) { bCapturing = false; if(bAddedVideoCapture) graph->RemoveFilter(captureFilter); if(bAddedAudioCapture) graph->RemoveFilter(audioFilter); if(bAddedDevice) { graph->RemoveFilter(audioDeviceFilter); graph->RemoveFilter(deviceFilter); } SafeRelease(audioDeviceFilter); SafeRelease(deviceFilter); SafeRelease(captureFilter); SafeRelease(audioFilter); SafeRelease(control); if(colorConvertShader) { delete colorConvertShader; colorConvertShader = NULL; } if(audioOut) { delete audioOut; audioOut = NULL; } if(lpImageBuffer) { Free(lpImageBuffer); lpImageBuffer = NULL; } bReadyToDraw = true; } else bReadyToDraw = false; if(!renderCX) renderCX = 32; if(!renderCY) renderCY = 32; //----------------------------------------------------- // create the texture regardless, will just show up as red to indicate failure BYTE *textureData = (BYTE*)Allocate(renderCX*renderCY*4); if(colorType == DeviceOutputType_RGB) //you may be confused, but when directshow outputs RGB, it's actually outputting BGR { msetd(textureData, 0xFFFF0000, renderCX*renderCY*4); texture = CreateTexture(renderCX, renderCY, GS_BGR, textureData, FALSE, FALSE); } else //if we're working with planar YUV, we can just use regular RGB textures instead { msetd(textureData, 0xFF0000FF, renderCX*renderCY*4); texture = CreateTexture(renderCX, renderCY, GS_RGB, textureData, FALSE, FALSE); } if(bSucceeded && bUseThreadedConversion) { if(colorType == DeviceOutputType_I420 || colorType == DeviceOutputType_YV12) { LPBYTE lpData; if(texture->Map(lpData, texturePitch)) texture->Unmap(); else texturePitch = renderCX*4; lpImageBuffer = (LPBYTE)Allocate(texturePitch*renderCY); } } Free(textureData); bFiltersLoaded = bSucceeded; return bSucceeded; }
// IPin HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) { QMutexLocker locker(&m_mutex); if (!pReceivePin) { return E_POINTER; } else if (m_state != State_Stopped) { return VFW_E_NOT_STOPPED; } else if (m_peerPin) { return VFW_E_ALREADY_CONNECTED; } else { HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED; m_peerPin = pReceivePin; m_peerPin->AddRef(); if (!pmt) { IEnumMediaTypes *mediaTypes = 0; if (pReceivePin->EnumMediaTypes(&mediaTypes) == S_OK) { for (AM_MEDIA_TYPE *type = 0; mediaTypes->Next(1, &type, 0) == S_OK; DirectShowMediaType::deleteType(type)) { switch (tryConnect(pReceivePin, type)) { case S_OK: DirectShowMediaType::freeData(type); mediaTypes->Release(); return S_OK; case VFW_E_NO_TRANSPORT: hr = VFW_E_NO_TRANSPORT; break; default: break; } } mediaTypes->Release(); } AM_MEDIA_TYPE type = { MEDIATYPE_Stream, // majortype MEDIASUBTYPE_NULL, // subtype TRUE, // bFixedSizeSamples FALSE, // bTemporalCompression 1, // lSampleSize GUID_NULL, // formattype 0, // pUnk 0, // cbFormat 0, // pbFormat }; static const int count = sizeof(directshow_subtypes) / sizeof(GUID); for (int i = 0; i < count; ++i) { type.subtype = directshow_subtypes[i]; switch (tryConnect(pReceivePin, &type)) { case S_OK: return S_OK; case VFW_E_NO_TRANSPORT: hr = VFW_E_NO_TRANSPORT; break; default: break; } } } else if (pmt->majortype == MEDIATYPE_Stream && (hr = tryConnect(pReceivePin, pmt))) { return S_OK; } m_peerPin->Release(); m_peerPin = 0; m_mediaType.clear(); return hr; } }
// // OnApplyChanges // // Changes made should be kept. // HRESULT NullIPProperties::OnApplyChanges() { ASSERT(m_pINullIPP); // // get the current selection of the media type // int iIndex = SendMessage (m_hwndLB, LB_GETCURSEL, 0, 0) ; if (iIndex <= 0) iIndex = 0 ; m_bDirty = FALSE; // the page is now clean if (iIndex == 0) { m_pINullIPP->put_MediaType (NULL) ; m_nIndex = 0; return NOERROR; } IEnumMediaTypes * pMTEnum; AM_MEDIA_TYPE *pMediaType=0; ULONG count=0; // // get the type enumerator from the pin again // HRESULT hr = m_pPin->EnumMediaTypes(&pMTEnum); if (FAILED(hr)) { return hr; } // // skip to the appropriate type and read it // pMTEnum->Skip(iIndex - 1); pMTEnum->Next(1, &pMediaType, &count); if (count != 1) { pMTEnum->Release(); return E_UNEXPECTED; } // // change the type by calling the filter // ASSERT(pMediaType); CMediaType cmt(*pMediaType); DeleteMediaType(pMediaType); hr = m_pINullIPP->put_MediaType(&cmt) ; if (FAILED(hr)) { pMTEnum->Release(); return NOERROR; } // // update the current selection and release the enumerator // m_nIndex = iIndex; pMTEnum->Release(); return NOERROR; } // OnApplyChanges
HRESULT recChannel_t::map(void) { __CONTEXT("recChannel_t::map"); int hr = 0; IBaseFilter * pFilter = NULL; IBaseFilter * pFilter2 = NULL; IPin * pVideoInputPin = NULL; pControl->StopWhenReady(); mapping = true; pOutput = camInfo->output; if (remaped){ //refresh Codec BW before creation pSender->sampleGrabber->BWController->refreshBW(); pSender->rebind(); hr = pGraph->Render(pOutput); { // Enumerate the filters in the graph. IEnumFilters *pEnum = NULL; int hr = pGraph->EnumFilters(&pEnum); if (SUCCEEDED(hr)) { IBaseFilter *pFilter = NULL; pEnum->Reset(); while (S_OK == pEnum->Next(1, &pFilter, NULL)) { CLSID filterId; pFilter->GetClassID(&filterId); if(filterId == CLSID_AviSplitter) { IEnumPins * pEnumpin = NULL; hr = pFilter->EnumPins(&pEnumpin); if (!hr) { IPin * pPin = NULL; pEnumpin->Reset(); while (pEnumpin->Next(1, &pPin, 0) == S_OK) { bool break_loop = false; AM_MEDIA_TYPE * mediaType; IEnumMediaTypes * enumMedia = NULL; hr = pPin->EnumMediaTypes(&enumMedia); if(!hr) { enumMedia->Reset(); while(enumMedia->Next(1,&mediaType , NULL) == S_OK) { if (mediaType->majortype == MEDIATYPE_Audio) { pPin->Disconnect(); pGraph->Render(pPin); pPin->Release(); break_loop = true; break; } } enumMedia->Release(); if (break_loop) break; } } pEnumpin->Release(); } } pFilter->Release(); } pEnum->Release(); } } pipeCreated = true; if (hr) { errorCheck(hr); NOTIFY("[recChannel_t::map]WARNING :: Can't render actual format, restoring default settings...\r\n"); capInfo.heigth = DEFAULT_CAPTURE_HEIGTH; capInfo.width = DEFAULT_CAPTURE_WIDTH; ql_t<AM_MEDIA_TYPE *> auxFormats = camInfo->getFormatList(); pSender->SetActualCodec(DEFAULT_CODEC_STR); } } if (fullScreen){ set_full_screen(true); }else{ hr = setWindowGeometry(windowInfo); errorCheck(hr); } // IVideoWindow *pWindowInfo = NULL; // hr = pGraph->QueryInterface(IID_IVideoWindow, (void **)&pWindowInfo); // if (!hr) // { // wchar_t wtext[100]; // long windowStyle,windowStyleEx; // lText(wtext,title); // pWindowInfo->get_WindowStyle(&windowStyle); // pWindowInfo->get_WindowStyleEx(&windowStyleEx); // windowStyle = windowStyle + DEFAULT_WINDOW_PROPS - DEFAULT_WINDOW_NON_PROPS; // windowStyleEx = windowStyleEx - WS_EX_APPWINDOW; // pWindowInfo->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS); // pWindowInfo->put_WindowStyleEx(WS_EX_TOOLWINDOW); // pWindowInfo->put_Caption(wtext); // //#ifdef _WINDOWS // if (camInfo->getKind() == MEDIA) // { // fControl->setGeometry(windowInfo); // // } //#endif ////Ares daemon don't show local windows on ////recChannels //#ifndef __ARES // if (camInfo->getKind() != SHARED) // { // pWindowInfo->put_Visible(OATRUE); // pWindowInfo->put_AutoShow(OATRUE); // } // else // { //#endif // pWindowInfo->put_Visible(OAFALSE); // pWindowInfo->put_AutoShow(OAFALSE); //#ifndef __ARES // } //#endif // // pWindowInfo->Release(); // setOwner(); // } IMediaSeeking * pSeek = NULL; pGraph->QueryInterface(IID_IMediaSeeking,(void **)&pSeek); if (pSeek)pSeek->SetRate(1); pControl->Run(); if (camInfo->getKind() == SHARED) { camInfo->RunSource(); } if (camInfo->getKind() == TEST) { if (pSeek) pSeek->SetRate(0.5); looper->Run(); } remaped = false; return hr; }
HRESULT CDXGraph::RenderAVIFile(CString mSourceFile) { if(pGraph != NULL) { //Add Grabber Filter IBaseFilter *pGrabberF = NULL; this->AddGrabber(&pGrabberF); //Add src filter IBaseFilter *pSrc; HRESULT hr = pGraph->AddSourceFilter(mSourceFile, L"Source", &pSrc); if(FAILED(hr)) return hr; //Add Avi splitter filter IBaseFilter *pAviSplitter = NULL; hr = CoCreateInstance(CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pAviSplitter); hr = pGraph->AddFilter(pAviSplitter, L"AVI Splitter"); //Add Mpeg4s decoder dmo filter IBaseFilter *pMp4Decoder = NULL; hr = CoCreateInstance(CLSID_MPEG4SDecoder, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pMp4Decoder); hr = pGraph->AddFilter(pMp4Decoder, L"Mp4 Decoder"); //Audio //add mp3 decoder IBaseFilter *pMP3Decoder = NULL; hr = CoCreateInstance(CLSID_MP3Decoder, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pMP3Decoder); hr = pGraph->AddFilter(pMP3Decoder, L"MP3 Decoder"); //add direct sound device IBaseFilter *pDSoundDevice = NULL; hr = CoCreateInstance(CLSID_DSoundRender,NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pDSoundDevice); hr = pGraph->AddFilter(pDSoundDevice, L"Sound Renderer"); //connect filters via pins hr = ConnectFilters(pGraph, pSrc, pAviSplitter, MEDIATYPE_NULL); //Split to audio and video IEnumPins *pEnum = 0; IPin *pPin = 0; IEnumMediaTypes *pEnumMediaType = 0; hr = pAviSplitter->EnumPins(&pEnum); bool audio_connected = false, video_connected = false; while(pEnum->Next(1, &pPin, NULL) == S_OK) { hr = pPin->EnumMediaTypes(&pEnumMediaType); //if this is video output pin if(SUCCEEDED(this->CheckMediaType(pEnumMediaType, MEDIATYPE_Video))) { IPin *pMP4DecoderInput = NULL; hr = this->GetUnconnectedPin(pMp4Decoder, PINDIR_INPUT, &pMP4DecoderInput, MEDIATYPE_NULL); hr = pGraph->Connect(pPin, pMP4DecoderInput); PIN_INFO pInfo; pPin->QueryPinInfo(&pInfo); pMP4DecoderInput->QueryPinInfo(&pInfo); pMP4DecoderInput->Release(); video_connected = true; } //if this is audio output pin else if (SUCCEEDED(this->CheckMediaType(pEnumMediaType, MEDIATYPE_Audio))) { IPin *pMP3DecoderInput = NULL; hr = this->GetUnconnectedPin(pMP3Decoder, PINDIR_INPUT, &pMP3DecoderInput, MEDIATYPE_NULL); hr = pGraph->Connect(pPin, pMP3DecoderInput); pMP3DecoderInput->Release(); audio_connected = true; } pPin->Release(); pEnumMediaType->Release(); if (audio_connected && video_connected) break; } pEnum->Release(); //Connect Audio Renderer hr = this->ConnectFilters(pGraph, pMP3Decoder, pDSoundDevice, MEDIATYPE_Audio); //Connect the Mp4Decoder to Sample Grabber hr = this->ConnectFilters(pGraph, pMp4Decoder, pGrabberF, MEDIATYPE_NULL); //get the output pin of grabber, then render pin IPin *pOutPin = NULL; this->GetUnconnectedPin(pGrabberF, PINDIR_OUTPUT, &pOutPin, MEDIATYPE_NULL); hr = pGraph->Render(pOutPin); pGrabberF->Release(); pSrc->Release(); pAviSplitter->Release(); pMp4Decoder->Release(); pMP3Decoder->Release(); pDSoundDevice->Release(); IEnumFilters *pEnumFilter; IBaseFilter *pRenderFilter; hr = pGraph->EnumFilters(&pEnumFilter); //test the graph SaveGraphFile(pGraph, L"D:\\SliderPlayer_264.grf"); return S_OK; } return E_FAIL; }
bool DeviceSource::LoadFilters() { if(bCapturing || bFiltersLoaded) return false; bool bSucceeded = false; List<MediaOutputInfo> outputList; IAMStreamConfig *config = NULL; bool bAddedVideoCapture = false, bAddedAudioCapture = false, bAddedDevice = false; GUID expectedMediaType; IPin *devicePin = NULL, *audioPin = NULL; HRESULT err; String strShader; bUseThreadedConversion = API->UseMultithreadedOptimizations() && (OSGetTotalCores() > 1); //------------------------------------------------ // basic initialization vars bool bForceCustomAudio = data->GetInt(TEXT("forceCustomAudioDevice")) != 0; bUseCustomResolution = data->GetInt(TEXT("customResolution")); strDevice = data->GetString(TEXT("device")); strDeviceName = data->GetString(TEXT("deviceName")); strDeviceID = data->GetString(TEXT("deviceID")); strAudioDevice = data->GetString(TEXT("audioDevice")); strAudioName = data->GetString(TEXT("audioDeviceName")); strAudioID = data->GetString(TEXT("audioDeviceID")); bFlipVertical = data->GetInt(TEXT("flipImage")) != 0; bFlipHorizontal = data->GetInt(TEXT("flipImageHorizontal")) != 0; bUsePointFiltering = data->GetInt(TEXT("usePointFiltering")) != 0; opacity = data->GetInt(TEXT("opacity"), 100); float volume = data->GetFloat(TEXT("volume"), 1.0f); bUseBuffering = data->GetInt(TEXT("useBuffering")) != 0; bufferTime = data->GetInt(TEXT("bufferTime"))*10000; //------------------------------------------------ // chrom key stuff bUseChromaKey = data->GetInt(TEXT("useChromaKey")) != 0; keyColor = data->GetInt(TEXT("keyColor"), 0xFFFFFFFF); keySimilarity = data->GetInt(TEXT("keySimilarity")); keyBlend = data->GetInt(TEXT("keyBlend"), 80); keySpillReduction = data->GetInt(TEXT("keySpillReduction"), 50); if(keyBaseColor.x < keyBaseColor.y && keyBaseColor.x < keyBaseColor.z) keyBaseColor -= keyBaseColor.x; else if(keyBaseColor.y < keyBaseColor.x && keyBaseColor.y < keyBaseColor.z) keyBaseColor -= keyBaseColor.y; else if(keyBaseColor.z < keyBaseColor.x && keyBaseColor.z < keyBaseColor.y) keyBaseColor -= keyBaseColor.z; //------------------------------------------------ // get the device filter and pins if(strDeviceName.IsValid()) deviceFilter = GetDeviceByValue(CLSID_VideoInputDeviceCategory, L"FriendlyName", strDeviceName, L"DevicePath", strDeviceID); else { if(!strDevice.IsValid()) { AppWarning(TEXT("DShowPlugin: Invalid device specified")); goto cleanFinish; } deviceFilter = GetDeviceByValue(CLSID_VideoInputDeviceCategory, L"FriendlyName", strDevice); } if(!deviceFilter) { AppWarning(TEXT("DShowPlugin: Could not create device filter")); goto cleanFinish; } devicePin = GetOutputPin(deviceFilter, &MEDIATYPE_Video); if(!devicePin) { AppWarning(TEXT("DShowPlugin: Could not get device video pin")); goto cleanFinish; } soundOutputType = data->GetInt(TEXT("soundOutputType")); //0 is for backward-compatibility if (strAudioID.CompareI(TEXT("Disabled"))) soundOutputType = 0; if(soundOutputType != 0) { if(!bForceCustomAudio) { err = capture->FindPin(deviceFilter, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FALSE, 0, &audioPin); bDeviceHasAudio = SUCCEEDED(err); } else bDeviceHasAudio = false; if(!bDeviceHasAudio) { if(strDeviceName.IsValid()) { audioDeviceFilter = GetDeviceByValue(CLSID_AudioInputDeviceCategory, L"FriendlyName", strAudioName, L"DevicePath", strAudioID); if(!audioDeviceFilter) AppWarning(TEXT("DShowPlugin: Invalid audio device: name '%s', path '%s'"), strAudioName.Array(), strAudioID.Array()); } else if(strAudioDevice.IsValid()) { audioDeviceFilter = GetDeviceByValue(CLSID_AudioInputDeviceCategory, L"FriendlyName", strAudioDevice); if(!audioDeviceFilter) AppWarning(TEXT("DShowPlugin: Could not create audio device filter")); } if(audioDeviceFilter) err = capture->FindPin(audioDeviceFilter, PINDIR_OUTPUT, &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, FALSE, 0, &audioPin); else err = E_FAIL; } if(FAILED(err) || !audioPin) { Log(TEXT("DShowPlugin: No audio pin, result = %lX"), err); soundOutputType = 0; } } else bDeviceHasAudio = bForceCustomAudio = false; int soundTimeOffset = data->GetInt(TEXT("soundTimeOffset")); GetOutputList(devicePin, outputList); //------------------------------------------------ // initialize the basic video variables and data renderCX = renderCY = 0; frameInterval = 0; if(bUseCustomResolution) { renderCX = data->GetInt(TEXT("resolutionWidth")); renderCY = data->GetInt(TEXT("resolutionHeight")); frameInterval = data->GetInt(TEXT("frameInterval")); } else { SIZE size; if (!GetClosestResolution(outputList, size, frameInterval)) { AppWarning(TEXT("DShowPlugin: Unable to find appropriate resolution")); renderCX = renderCY = 64; goto cleanFinish; } renderCX = size.cx; renderCY = size.cy; } if(!renderCX || !renderCY || !frameInterval) { AppWarning(TEXT("DShowPlugin: Invalid size/fps specified")); goto cleanFinish; } preferredOutputType = (data->GetInt(TEXT("usePreferredType")) != 0) ? data->GetInt(TEXT("preferredType")) : -1; int numThreads = MAX(OSGetTotalCores()-2, 1); for(int i=0; i<numThreads; i++) { convertData[i].width = renderCX; convertData[i].height = renderCY; convertData[i].sample = NULL; convertData[i].hSignalConvert = CreateEvent(NULL, FALSE, FALSE, NULL); convertData[i].hSignalComplete = CreateEvent(NULL, FALSE, FALSE, NULL); if(i == 0) convertData[i].startY = 0; else convertData[i].startY = convertData[i-1].endY; if(i == (numThreads-1)) convertData[i].endY = renderCY; else convertData[i].endY = ((renderCY/numThreads)*(i+1)) & 0xFFFFFFFE; } bFirstFrame = true; //------------------------------------------------ // get the closest media output for the settings used MediaOutputInfo *bestOutput = GetBestMediaOutput(outputList, renderCX, renderCY, preferredOutputType, frameInterval); if(!bestOutput) { AppWarning(TEXT("DShowPlugin: Could not find appropriate resolution to create device image source")); goto cleanFinish; } //------------------------------------------------ // log video info { String strTest = FormattedString(TEXT(" device: %s,\r\n device id %s,\r\n chosen type: %s, usingFourCC: %s, res: %ux%u - %ux%u, frameIntervals: %llu-%llu"), strDevice.Array(), strDeviceID.Array(), EnumToName[(int)bestOutput->videoType], bestOutput->bUsingFourCC ? TEXT("true") : TEXT("false"), bestOutput->minCX, bestOutput->minCY, bestOutput->maxCX, bestOutput->maxCY, bestOutput->minFrameInterval, bestOutput->maxFrameInterval); BITMAPINFOHEADER *bmiHeader = GetVideoBMIHeader(bestOutput->mediaType); char fourcc[5]; mcpy(fourcc, &bmiHeader->biCompression, 4); fourcc[4] = 0; if(bmiHeader->biCompression > 1000) strTest << FormattedString(TEXT(", fourCC: '%S'\r\n"), fourcc); else strTest << FormattedString(TEXT(", fourCC: %08lX\r\n"), bmiHeader->biCompression); if(!bDeviceHasAudio) strTest << FormattedString(TEXT(" audio device: %s,\r\n audio device id %s,\r\n"), strAudioDevice.Array(), strAudioID.Array()); Log(TEXT("------------------------------------------")); Log(strTest.Array()); } //------------------------------------------------ // set up shaders and video output data expectedMediaType = bestOutput->mediaType->subtype; colorType = DeviceOutputType_RGB; if(bestOutput->videoType == VideoOutputType_I420) colorType = DeviceOutputType_I420; else if(bestOutput->videoType == VideoOutputType_YV12) colorType = DeviceOutputType_YV12; else if(bestOutput->videoType == VideoOutputType_YVYU) colorType = DeviceOutputType_YVYU; else if(bestOutput->videoType == VideoOutputType_YUY2) colorType = DeviceOutputType_YUY2; else if(bestOutput->videoType == VideoOutputType_UYVY) colorType = DeviceOutputType_UYVY; else if(bestOutput->videoType == VideoOutputType_HDYC) colorType = DeviceOutputType_HDYC; else { colorType = DeviceOutputType_RGB; expectedMediaType = MEDIASUBTYPE_RGB32; } strShader = ChooseShader(); if(strShader.IsValid()) colorConvertShader = CreatePixelShaderFromFile(strShader); if(colorType != DeviceOutputType_RGB && !colorConvertShader) { AppWarning(TEXT("DShowPlugin: Could not create color space conversion pixel shader")); goto cleanFinish; } if(colorType == DeviceOutputType_YV12 || colorType == DeviceOutputType_I420) { for(int i=0; i<numThreads; i++) hConvertThreads[i] = OSCreateThread((XTHREAD)PackPlanarThread, convertData+i); } //------------------------------------------------ // set chroma details keyBaseColor = Color4().MakeFromRGBA(keyColor); Matrix4x4TransformVect(keyChroma, (colorType == DeviceOutputType_HDYC) ? (float*)yuv709Mat : (float*)yuvMat, keyBaseColor); keyChroma *= 2.0f; //------------------------------------------------ // configure video pin if(FAILED(err = devicePin->QueryInterface(IID_IAMStreamConfig, (void**)&config))) { AppWarning(TEXT("DShowPlugin: Could not get IAMStreamConfig for device pin, result = %08lX"), err); goto cleanFinish; } AM_MEDIA_TYPE outputMediaType; CopyMediaType(&outputMediaType, bestOutput->mediaType); VIDEOINFOHEADER *vih = reinterpret_cast<VIDEOINFOHEADER*>(outputMediaType.pbFormat); BITMAPINFOHEADER *bmi = GetVideoBMIHeader(&outputMediaType); vih->AvgTimePerFrame = frameInterval; bmi->biWidth = renderCX; bmi->biHeight = renderCY; bmi->biSizeImage = renderCX*renderCY*(bmi->biBitCount>>3); if(FAILED(err = config->SetFormat(&outputMediaType))) { if(err != E_NOTIMPL) { AppWarning(TEXT("DShowPlugin: SetFormat on device pin failed, result = %08lX"), err); goto cleanFinish; } } FreeMediaType(outputMediaType); //------------------------------------------------ // get audio pin configuration, optionally configure audio pin to 44100 GUID expectedAudioType; if(soundOutputType == 1) { IAMStreamConfig *audioConfig; if(SUCCEEDED(audioPin->QueryInterface(IID_IAMStreamConfig, (void**)&audioConfig))) { AM_MEDIA_TYPE *audioMediaType; if(SUCCEEDED(err = audioConfig->GetFormat(&audioMediaType))) { SetAudioInfo(audioMediaType, expectedAudioType); } else if(err == E_NOTIMPL) //elgato probably { IEnumMediaTypes *audioMediaTypes; if(SUCCEEDED(err = audioPin->EnumMediaTypes(&audioMediaTypes))) { ULONG i = 0; if((err = audioMediaTypes->Next(1, &audioMediaType, &i)) == S_OK) SetAudioInfo(audioMediaType, expectedAudioType); else { AppWarning(TEXT("DShowPlugin: audioMediaTypes->Next failed, result = %08lX"), err); soundOutputType = 0; } audioMediaTypes->Release(); } else { AppWarning(TEXT("DShowPlugin: audioMediaTypes->Next failed, result = %08lX"), err); soundOutputType = 0; } } else { AppWarning(TEXT("DShowPlugin: Could not get audio format, result = %08lX"), err); soundOutputType = 0; } audioConfig->Release(); } else { soundOutputType = 0; } } //------------------------------------------------ // add video capture filter if any captureFilter = new CaptureFilter(this, MEDIATYPE_Video, expectedMediaType); if(FAILED(err = graph->AddFilter(captureFilter, NULL))) { AppWarning(TEXT("DShowPlugin: Failed to add video capture filter to graph, result = %08lX"), err); goto cleanFinish; } bAddedVideoCapture = true; //------------------------------------------------ // add audio capture filter if any if(soundOutputType == 1) { audioFilter = new CaptureFilter(this, MEDIATYPE_Audio, expectedAudioType); if(!audioFilter) { AppWarning(TEXT("Failed to create audio capture filter")); soundOutputType = 0; } } else if(soundOutputType == 2) { if(FAILED(err = CoCreateInstance(CLSID_AudioRender, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&audioFilter))) { AppWarning(TEXT("DShowPlugin: failed to create audio renderer, result = %08lX"), err); soundOutputType = 0; } IBasicAudio *basicAudio; if(SUCCEEDED(audioFilter->QueryInterface(IID_IBasicAudio, (void**)&basicAudio))) { long lVol = long((double(volume)*NEAR_SILENTf)-NEAR_SILENTf); if(lVol <= -NEAR_SILENT) lVol = -10000; basicAudio->put_Volume(lVol); basicAudio->Release(); } } if(soundOutputType != 0) { if(FAILED(err = graph->AddFilter(audioFilter, NULL))) AppWarning(TEXT("DShowPlugin: Failed to add audio capture filter to graph, result = %08lX"), err); bAddedAudioCapture = true; } //------------------------------------------------ // add primary device filter if(FAILED(err = graph->AddFilter(deviceFilter, NULL))) { AppWarning(TEXT("DShowPlugin: Failed to add device filter to graph, result = %08lX"), err); goto cleanFinish; } if(soundOutputType != 0 && !bDeviceHasAudio) { if(FAILED(err = graph->AddFilter(audioDeviceFilter, NULL))) AppWarning(TEXT("DShowPlugin: Failed to add audio device filter to graph, result = %08lX"), err); } bAddedDevice = true; //------------------------------------------------ // connect all pins and set up the whole capture thing //THANK THE NINE DIVINES I FINALLY GOT IT WORKING bool bConnected = SUCCEEDED(err = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, deviceFilter, NULL, captureFilter)); if(!bConnected) { if(FAILED(err = graph->Connect(devicePin, captureFilter->GetCapturePin()))) { AppWarning(TEXT("DShowPlugin: Failed to connect the video device pin to the video capture pin, result = %08lX"), err); goto cleanFinish; } } if(soundOutputType != 0) { if(!bDeviceHasAudio) bConnected = SUCCEEDED(err = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, audioDeviceFilter, NULL, audioFilter)); else bConnected = SUCCEEDED(err = capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, deviceFilter, NULL, audioFilter)); if(!bConnected) { AppWarning(TEXT("DShowPlugin: Failed to connect the audio device pin to the audio capture pin, result = %08lX"), err); soundOutputType = 0; } } if(FAILED(err = graph->QueryInterface(IID_IMediaControl, (void**)&control))) { AppWarning(TEXT("DShowPlugin: Failed to get IMediaControl, result = %08lX"), err); goto cleanFinish; } if (bUseBuffering) { if (!(hStopSampleEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) { AppWarning(TEXT("DShowPlugin: Failed to create stop event"), err); goto cleanFinish; } if (!(hSampleThread = OSCreateThread((XTHREAD)SampleThread, this))) { AppWarning(TEXT("DShowPlugin: Failed to create sample thread"), err); goto cleanFinish; } } if(soundOutputType == 1) { audioOut = new DeviceAudioSource; audioOut->Initialize(this); API->AddAudioSource(audioOut); audioOut->SetAudioOffset(soundTimeOffset); audioOut->SetVolume(volume); } bSucceeded = true; cleanFinish: SafeRelease(config); SafeRelease(devicePin); SafeRelease(audioPin); for(UINT i=0; i<outputList.Num(); i++) outputList[i].FreeData(); if(!bSucceeded) { bCapturing = false; if(bAddedVideoCapture) graph->RemoveFilter(captureFilter); if(bAddedAudioCapture) graph->RemoveFilter(audioFilter); if(bAddedDevice) { if(!bDeviceHasAudio && audioDeviceFilter) graph->RemoveFilter(audioDeviceFilter); graph->RemoveFilter(deviceFilter); } SafeRelease(audioDeviceFilter); SafeRelease(deviceFilter); SafeRelease(captureFilter); SafeRelease(audioFilter); SafeRelease(control); if (hSampleThread) { SetEvent(hStopSampleEvent); WaitForSingleObject(hSampleThread, INFINITE); CloseHandle(hSampleThread); hSampleThread = NULL; } if (hStopSampleEvent) { CloseHandle(hStopSampleEvent); hStopSampleEvent = NULL; } if(colorConvertShader) { delete colorConvertShader; colorConvertShader = NULL; } if(audioOut) { delete audioOut; audioOut = NULL; } if(lpImageBuffer) { Free(lpImageBuffer); lpImageBuffer = NULL; } bReadyToDraw = true; } else bReadyToDraw = false; if(!renderCX) renderCX = 32; if(!renderCY) renderCY = 32; //----------------------------------------------------- // create the texture regardless, will just show up as red to indicate failure BYTE *textureData = (BYTE*)Allocate(renderCX*renderCY*4); if(colorType == DeviceOutputType_RGB) //you may be confused, but when directshow outputs RGB, it's actually outputting BGR { msetd(textureData, 0xFFFF0000, renderCX*renderCY*4); texture = CreateTexture(renderCX, renderCY, GS_BGR, textureData, FALSE, FALSE); } else //if we're working with planar YUV, we can just use regular RGB textures instead { msetd(textureData, 0xFF0000FF, renderCX*renderCY*4); texture = CreateTexture(renderCX, renderCY, GS_RGB, textureData, FALSE, FALSE); } if(bSucceeded && bUseThreadedConversion) { if(colorType == DeviceOutputType_I420 || colorType == DeviceOutputType_YV12) { LPBYTE lpData; if(texture->Map(lpData, texturePitch)) texture->Unmap(); else texturePitch = renderCX*4; lpImageBuffer = (LPBYTE)Allocate(texturePitch*renderCY); } } Free(textureData); bFiltersLoaded = bSucceeded; return bSucceeded; }