Esempio n. 1
0
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;
    }
}
Esempio n. 3
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;
}
Esempio n. 4
0
/* 设置捕获图像帧的格式,遍历所有格式是否有预定格式,若没有则以默认格式捕获 */
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
 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;
 }
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 11
0
//
// 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
Esempio n. 12
0
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;
}
Esempio n. 13
0
// 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;
    }
}
Esempio n. 14
0
//
// 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
Esempio n. 15
0
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;
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
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;
}