int InitMediaEnviront()
{

	
	JIF( CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
		IID_IGraphBuilder, (void **)&pGB));
	//add filter and connect them



	//hr=CoCreateInstance(INFINITEPINTEEFILTER, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVideorenderFilter);
	JIF(CoCreateInstance(
		CLSID_VideoRenderer, 
		NULL, 
		CLSCTX_INPROC_SERVER, 
		IID_IBaseFilter, 
		(void**)&pVMRFilter));
	//pGB->FindFilterByName(
	//hr = pGB->FindFilterByName(L"Video Renderer", &pVMRFilter) ;

	JIF(CoCreateInstance(
		CLSID_BouncingBall, 
		NULL, 
		CLSCTX_INPROC_SERVER, 
		IID_IBaseFilter, 
		(void**)&pSnowFilter));
	//GET PINS
	JIF(pGB->QueryInterface(IID_IVideoWindow,(void **)&pVW));
	JIF(pGB->AddFilter(pVMRFilter,L"RENDER"));
	JIF(pGB->AddFilter(pSnowFilter,L"SOURCE"));

//	EnumPins(pSnowFilter);
//	EnumPins(pVMRFilter);

	//hr = pSnowFilter->FindPin(L"Output" , &pPinOut);
	pPinOut=GetFirstPin(pSnowFilter);
	//pVMRFilter
	//JIF( pVMRFilter->FindPin(L"VMR Input0" , &pPinIn));

	pPinIn=GetFirstPin(pVMRFilter);
	//pGB->AddSourceFilter(

	JIF(pGB->Connect (pPinOut,pPinIn));
	
	JIF( pGB->QueryInterface(IID_IMediaControl, (void **)&pMC));
	JIF( pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME));

	return 0;	
}
Beispiel #2
0
bool CBaseSplitterOutputPin::IsActive()
{
    CComPtr<IPin> pPin = this;
    do {
        CComPtr<IPin> pPinTo;
        CComQIPtr<IStreamSwitcherInputPin> pSSIP;
        if (S_OK == pPin->ConnectedTo(&pPinTo) && (pSSIP = pPinTo) && !pSSIP->IsActive()) {
            return false;
        }
        pPin = GetFirstPin(GetFilterFromPin(pPinTo), PINDIR_OUTPUT);
    } while (pPin);

    return true;
}
Beispiel #3
0
void CBaseSplitterOutputPin::MakeISCRHappy()
{
    CComPtr<IPin> pPinTo = this, pTmp;
    while (pPinTo && SUCCEEDED(pPinTo->ConnectedTo(&pTmp)) && (pPinTo = pTmp)) {
        pTmp = nullptr;

        CComPtr<IBaseFilter> pBF = GetFilterFromPin(pPinTo);

        if (GetCLSID(pBF) == GUIDFromCString(_T("{48025243-2D39-11CE-875D-00608CB78066}"))) { // ISCR
            CAutoPtr<Packet> p(DEBUG_NEW Packet());
            p->TrackNumber = DWORD_ERROR;
            p->rtStart = -1;
            p->rtStop = 0;
            p->bSyncPoint = FALSE;
            p->SetData(" ", 2);
            QueuePacket(p);
            break;
        }

        pPinTo = GetFirstPin(pBF, PINDIR_OUTPUT);
    }
}
Beispiel #4
0
DWORD CBaseSplitterOutputPin::ThreadProc()
{
    SetThreadName(DWORD(-1), "CBaseSplitterOutputPin");
    m_hrDeliver = S_OK;
    m_fFlushing = m_fFlushed = false;
    m_eEndFlush.Set();

    // fix for Microsoft DTV-DVD Video Decoder - video freeze after STOP/PLAY
    bool iHaaliRenderConnect = false;
    CComPtr<IPin> pPinTo = this, pTmp;
    while (pPinTo && SUCCEEDED(pPinTo->ConnectedTo(&pTmp)) && (pPinTo = pTmp)) {
        pTmp = nullptr;
        CComPtr<IBaseFilter> pBF = GetFilterFromPin(pPinTo);
        if (GetCLSID(pBF) == CLSID_DXR) { // Haali Renderer
            iHaaliRenderConnect = true;
            break;
        }
        pPinTo = GetFirstPin(pBF, PINDIR_OUTPUT);
    }
    if (IsConnected() && !iHaaliRenderConnect) {
        GetConnected()->BeginFlush();
        GetConnected()->EndFlush();
    }

    for (;;) {
        Sleep(1);

        DWORD cmd;
        if (CheckRequest(&cmd)) {
            m_hThread = nullptr;
            cmd = GetRequest();
            Reply(S_OK);
            ASSERT(cmd == CMD_EXIT);
            return 0;
        }

        int cnt = 0;
        do {
            CAutoPtr<Packet> p;

            {
                CAutoLock cAutoLock(&m_queue);
                if ((cnt = m_queue.GetCount()) > 0) {
                    p = m_queue.Remove();
                }
            }

            if (S_OK == m_hrDeliver && cnt > 0) {
                ASSERT(!m_fFlushing);

                m_fFlushed = false;

                // flushing can still start here, to release a blocked deliver call

                HRESULT hr = p
                             ? DeliverPacket(p)
                             : DeliverEndOfStream();

                m_eEndFlush.Wait(); // .. so we have to wait until it is done

                if (hr != S_OK && !m_fFlushed) { // and only report the error in m_hrDeliver if we didn't flush the stream
                    // CAutoLock cAutoLock(&m_csQueueLock);
                    m_hrDeliver = hr;
                    break;
                }
            }
        } while (--cnt > 0);
    }
}
Beispiel #5
0
HRESULT CStreamSwitcherInputPin::CompleteConnect(IPin* pReceivePin)
{
    HRESULT hr = __super::CompleteConnect(pReceivePin);
    if (FAILED(hr)) {
        return hr;
    }

    (static_cast<CStreamSwitcherFilter*>(m_pFilter))->CompleteConnect(PINDIR_INPUT, this, pReceivePin);

    m_fCanBlock = false;
    bool fForkedSomewhere = false;

    CStringW fileName;
    CStringW pinName;

    IPin* pPin = (IPin*)this;
    IBaseFilter* pBF = (IBaseFilter*)m_pFilter;

    pPin = GetUpStreamPin(pBF, pPin);
    if (pPin) {
        pBF = GetFilterFromPin(pPin);
    }
    while (pPin && pBF) {
        if (IsSplitter(pBF)) {
            pinName = GetPinName(pPin);
        }

        CLSID clsid = GetCLSID(pBF);
        if (clsid == CLSID_AviSplitter || clsid == CLSID_OggSplitter) {
            m_fCanBlock = true;
        }

        int nIn, nOut, nInC, nOutC;
        CountPins(pBF, nIn, nOut, nInC, nOutC);
        fForkedSomewhere = fForkedSomewhere || nIn > 1 || nOut > 1;

        DWORD cStreams = 0;
        if (CComQIPtr<IAMStreamSelect> pSSF = pBF) {
            hr = pSSF->Count(&cStreams);
            if (SUCCEEDED(hr)) {
                for (int i = 0; i < (int)cStreams; i++) {
                    AM_MEDIA_TYPE* pmt = nullptr;
                    hr = pSSF->Info(i, &pmt, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
                    if (SUCCEEDED(hr) && pmt && pmt->majortype == MEDIATYPE_Audio) {
                        m_pSSF = pSSF;
                        DeleteMediaType(pmt);
                        break;
                    }
                    DeleteMediaType(pmt);
                }
            }
        }

        if (CComQIPtr<IFileSourceFilter> pFSF = pBF) {
            WCHAR* pszName = nullptr;
            AM_MEDIA_TYPE mt;
            if (SUCCEEDED(pFSF->GetCurFile(&pszName, &mt)) && pszName) {
                fileName = pszName;
                CoTaskMemFree(pszName);

                fileName.Replace('\\', '/');
                CStringW fn = fileName.Mid(fileName.ReverseFind('/') + 1);
                if (!fn.IsEmpty()) {
                    fileName = fn;
                }

                // Haali & LAVFSplitter return only one "Audio" pin name, cause CMainFrame::OnInitMenuPopup lookup find the wrong popmenu,
                // add space at the end to prevent this, internal filter never return "Audio" only.
                if (!pinName.IsEmpty()) {
                    fileName = pinName + L" ";
                }

                WCHAR* pName = DEBUG_NEW WCHAR[fileName.GetLength() + 1];
                if (pName) {
                    wcscpy_s(pName, fileName.GetLength() + 1, fileName);
                    if (m_pName) {
                        delete [] m_pName;
                    }
                    m_pName = pName;
                    if (cStreams == 1) { // Simple external track, no need to use the info from IAMStreamSelect
                        m_pSSF.Release();
                    }
                }
            }

            break;
        }

        pPin = GetFirstPin(pBF);

        pPin = GetUpStreamPin(pBF, pPin);
        if (pPin) {
            pBF = GetFilterFromPin(pPin);
        }
    }

    if (!fForkedSomewhere) {
        m_fCanBlock = true;
    }

    m_hNotifyEvent = nullptr;

    return S_OK;
}
HRESULT CStreamSwitcherInputPin::CompleteConnect(IPin* pReceivePin)
{
	HRESULT hr = __super::CompleteConnect(pReceivePin);
	if(FAILED(hr)) return hr;

    ((CStreamSwitcherFilter*)m_pFilter)->CompleteConnect(PINDIR_INPUT, this, pReceivePin);

	m_fCanBlock = false;
	bool fForkedSomewhere = false;

	CStringW fileName;
	CStringW pinName;

    IPin* pPin = (IPin*)this;
	IBaseFilter* pBF = (IBaseFilter*)m_pFilter;

	while((pPin = GetUpStreamPin(pBF, pPin)) && (pBF = GetFilterFromPin(pPin)))
	{
		if(IsSplitter(pBF))
		{
			pinName = GetPinName(pPin);
		}

		CLSID clsid = GetCLSID(pBF);
		if(clsid == CLSID_AviSplitter || clsid == CLSID_OggSplitter)
			m_fCanBlock = true;

		int nIn, nOut, nInC, nOutC;
		CountPins(pBF, nIn, nOut, nInC, nOutC);
		fForkedSomewhere = fForkedSomewhere || nIn > 1 || nOut > 1;

		if(CComQIPtr<IFileSourceFilter> pFSF = pBF)
		{
			WCHAR* pszName = NULL;
			AM_MEDIA_TYPE mt;
			if(SUCCEEDED(pFSF->GetCurFile(&pszName, &mt)) && pszName)
			{
				fileName = pszName;
				CoTaskMemFree(pszName);

				fileName.Replace('\\', '/');
				CStringW fn = fileName.Mid(fileName.ReverseFind('/')+1);
				if(!fn.IsEmpty()) fileName = fn;

				if(!pinName.IsEmpty()) fileName += L" / " + pinName;

				WCHAR* pName = new WCHAR[fileName.GetLength()+1];
				if(pName)
				{
					wcscpy(pName, fileName);
					if(m_pName) delete [] m_pName;
					m_pName = pName;
				}
			}

			break;
		}

		pPin = GetFirstPin(pBF);
	}

	if(!fForkedSomewhere)
		m_fCanBlock = true;

	m_hNotifyEvent = NULL;

	return S_OK;
}
Beispiel #7
0
bool CConvertDlg::ConvertFile(LPCTSTR fn, IPin* pPin)
{
	OAFilterState fs;
	if(!m_pMC || FAILED(m_pMC->GetState(0, &fs)) || fs != State_Stopped)
		return false;

	m_pGB->NukeDownstream(m_pMux);

	CComPtr<IBaseFilter> pFW;
	pFW.CoCreateInstance(CLSID_FileWriter);
	CComQIPtr<IFileSinkFilter2> pFSF = pFW;

	if(pPin)
	{
		CComQIPtr<IBaseMuxerRelatedPin> pRP = pPin;
		if(!pRP) return false;

		pPin = pRP->GetRelatedPin();
	}
	else
	{
		pPin = GetFirstPin(m_pMux, PINDIR_OUTPUT);
	}

	if(!pPin || !pFSF
		|| FAILED(m_pGB->AddFilter(pFW, NULL))
		|| FAILED(pFSF->SetFileName(CStringW(fn), NULL))
		|| FAILED(pFSF->SetMode(AM_FILE_OVERWRITE))
		|| FAILED(m_pGB->ConnectDirect(pPin, GetFirstPin(pFW), NULL)))
	{
		m_pGB->RemoveFilter(pFW);
		return false;
	}

	if(m_pMS)
	{
		LONGLONG pos = 0;
		m_pMS->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
	}

	if(CComQIPtr<IDSMPropertyBag> pPB = m_pMux)
	{
		pPB->SetProperty(L"APPL", L"Media Player Classic");
	}

	if(CComQIPtr<IDSMResourceBag> pRB = m_pMux)
	{
		pRB->ResRemoveAll(0);
		POSITION pos = m_pTIs.GetHeadPosition();
		while(pos)
		{
			if(CTreeItemResource* t2 = dynamic_cast<CTreeItemResource*>((CTreeItem*)m_pTIs.GetNext(pos)))
				pRB->ResAppend(
					t2->m_res.name, t2->m_res.desc, t2->m_res.mime,
					t2->m_res.data.GetData(), t2->m_res.data.GetCount(),
					NULL);
		}
	}

	if(CComQIPtr<IDSMChapterBag> pCB = m_pMux)
	{
		pCB->ChapRemoveAll();
		POSITION pos = m_pTIs.GetHeadPosition();
		while(pos)
		{
			if(CTreeItemChapter* t2 = dynamic_cast<CTreeItemChapter*>((CTreeItem*)m_pTIs.GetNext(pos)))
				pCB->ChapAppend(t2->m_chap.rt, t2->m_chap.name);
		}
	}

	if(FAILED(m_pMC->Run()))
		return false;

	m_tree.EnableWindow(FALSE);

	return true;
}
Beispiel #8
0
BOOL CSaveDlg::OnInitDialog()
{
	CCmdUIDialog::OnInitDialog();

	//m_anim.Open(IDR_AVI_FILECOPY);
	//m_anim.Play(0, -1, -1);

	CString str, in = m_in, out = m_out;
	if(in.GetLength() > 60) in = in.Left(17) + _T("..") + in.Right(43);
	if(out.GetLength() > 60) out = out.Left(17) + _T("..") + out.Right(43);
	str.Format(_T("%s\r\n%s"), in, out);
	m_fromto.SetWindowText(str);

	m_progress.SetRange(0, 100);

	if(FAILED(pGB.CoCreateInstance(CLSID_FilterGraph)) || !(pMC = pGB) || !(pME = pGB) || !(pMS = pGB)
	|| FAILED(pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)))
	{
		m_report.SetWindowText(_T("Error"));
		return FALSE;
	}

	HRESULT hr;

	CStringW fnw = m_in;
	CComPtr<IFileSourceFilter> pReader;

	if(!pReader && m_in.Mid(m_in.ReverseFind('.')+1).MakeLower() == _T("cda"))
	{
		hr = S_OK;
		CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)new CCDDAReader(NULL, &hr);
		if(FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL)))
			pReader.Release();
	}

	if(!pReader)
	{
		hr = S_OK;
		CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)new CCDXAReader(NULL, &hr);
		if(FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL)))
			pReader.Release();
	}

	if(!pReader /*&& ext == _T("ifo")*/)
	{
		hr = S_OK;
		CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)new CVTSReader(NULL, &hr);
		if(FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL)))
			pReader.Release();
		else
		{
			CPath pout(m_out);
			pout.RenameExtension(_T(".ifo"));
			CopyFile(m_in, pout, FALSE);
		}
	}

	if(!pReader)
	{
		hr = S_OK;
		CComPtr<IUnknown> pUnk;
		pUnk.CoCreateInstance(CLSID_AsyncReader);
		if(FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL)))
			pReader.Release();
	}

	if(!pReader)
	{
		hr = S_OK;
		CComPtr<IUnknown> pUnk;
		pUnk.CoCreateInstance(CLSID_URLReader);
		if(CComQIPtr<IBaseFilter> pSrc = pUnk) // url reader has to be in the graph to load the file
		{
			pGB->AddFilter(pSrc, fnw);
			if(FAILED(hr) || !(pReader = pUnk) || FAILED(hr = pReader->Load(fnw, NULL)))
			{
				pReader.Release();
				pGB->RemoveFilter(pSrc);
			}
		}
	}

	CComQIPtr<IBaseFilter> pSrc = pReader;
	if(FAILED(pGB->AddFilter(pSrc, fnw)))
	{
		m_report.SetWindowText(_T("Sorry, can't save this file, press cancel"));
		return FALSE;
	}

	CComQIPtr<IBaseFilter> pMid = new CStreamDriveThruFilter(NULL, &hr);
	if(FAILED(pGB->AddFilter(pMid, L"StreamDriveThru")))
	{
		m_report.SetWindowText(_T("Error"));
		return FALSE;
	}

	CComQIPtr<IBaseFilter> pDst;
	pDst.CoCreateInstance(CLSID_FileWriter);
	CComQIPtr<IFileSinkFilter2> pFSF = pDst;
	pFSF->SetFileName(CStringW(m_out), NULL);
	pFSF->SetMode(AM_FILE_OVERWRITE);
	if(FAILED(pGB->AddFilter(pDst, L"File Writer")))
	{
		m_report.SetWindowText(_T("Error"));
		return FALSE;
	}

	hr = pGB->Connect(
		GetFirstPin((pSrc), PINDIR_OUTPUT), 
		GetFirstPin((pMid), PINDIR_INPUT));

	hr = pGB->Connect(
		GetFirstPin((pMid), PINDIR_OUTPUT), 
		GetFirstPin((pDst), PINDIR_INPUT));

pMS = pMid;

	pMC->Run();

	m_nIDTimerEvent = SetTimer(1, 1000, NULL);

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}
BOOL CSaveDlg::OnInitDialog()
{
	CCmdUIDialog::OnInitDialog();

	AppSettings& s = AfxGetAppSettings();

	CString str, in = m_name, out = m_out;

	if (m_in.Find(_T("http://")) != -1 || m_in.Find(_T("ftp://")) != -1) {
		m_anim.SendMessage(ACM_OPEN, (WPARAM)AfxGetInstanceHandle(), (LPARAM)IDR_AVI_WEB_FILECOPY);
	} else {
		m_anim.SendMessage(ACM_OPEN, (WPARAM)AfxGetInstanceHandle(), (LPARAM)IDR_AVI_FILECOPY);
	}
	m_anim.Play(0, (UINT)-1, (UINT)-1);

	if (in.GetLength() > 60) {
		in = in.Left(17) + _T("..") + in.Right(43);
	}

	if (out.GetLength() > 60) {
		out = out.Left(17) + _T("..") + out.Right(43);
	}

	str.Format(_T("%s\r\n%s"), in, out);
	m_fromto.SetWindowText(str);

	m_progress.SetRange(0, 100);

	if (OpenImageCheck(m_in) && s.strSnapShotExt != _T(".*")) {
		OpenImageDIB(m_in, m_out, s.iThumbQuality, 0);
		EndDialog(IDOK);
		return TRUE;
	}

	if (FAILED(pGB.CoCreateInstance(CLSID_FilterGraph)) || !(pMC = pGB) || !(pME = pGB) || !(pMS = pGB)
			|| FAILED(pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0))) {
		m_report.SetWindowText(_T("Error"));
		return FALSE;
	}

	HRESULT hr;

	CStringW fnw = m_in;
	CComPtr<IFileSourceFilter> pReader;

	if (!pReader && m_in.Mid(m_in.ReverseFind('.')+1).MakeLower() == _T("cda")) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)DNew CCDDAReader(NULL, &hr);

		if (FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL))) {
			pReader.Release();
		}
	}

	if (!pReader) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)DNew CCDXAReader(NULL, &hr);

		if (FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL))) {
			pReader.Release();
		}
	}

	if (!pReader /*&& ext == _T("ifo")*/) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)DNew CVTSReader(NULL, &hr);

		if (FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL))) {
			pReader.Release();
		} else {
			CPath pout(m_out);
			pout.RenameExtension(_T(".ifo"));
			CopyFile(m_in, pout, FALSE);
		}
	}

	if (!pReader) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk;
		hr = pUnk.CoCreateInstance(CLSID_AsyncReader);

		if (FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL))) {
			pReader.Release();
		}
	}

	if (!pReader) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk;
		hr = pUnk.CoCreateInstance(CLSID_URLReader);

		if (CComQIPtr<IBaseFilter> pSrc = pUnk) {
			hr = pGB->AddFilter(pSrc, fnw);

			if (FAILED(hr) || !(pReader = pUnk) || FAILED(hr = pReader->Load(fnw, NULL))) {
				pReader.Release();
				pGB->RemoveFilter(pSrc);
			}
		}
	}

	CComQIPtr<IBaseFilter> pSrc = pReader;

	if (FAILED(pGB->AddFilter(pSrc, fnw))) {
		m_report.SetWindowText(_T("Sorry, can't save this file, press cancel"));

		return FALSE;
	}

	CComQIPtr<IBaseFilter> pMid = DNew CStreamDriveThruFilter(NULL, &hr);

	if (FAILED(pGB->AddFilter(pMid, L"StreamDriveThru"))) {
		m_report.SetWindowText(_T("Error"));

		return FALSE;
	}

	CComQIPtr<IBaseFilter> pDst;
	pDst.CoCreateInstance(CLSID_FileWriter);
	CComQIPtr<IFileSinkFilter2> pFSF = pDst;
	pFSF->SetFileName(CStringW(m_out), NULL);
	pFSF->SetMode(AM_FILE_OVERWRITE);

	if (FAILED(pGB->AddFilter(pDst, L"File Writer"))) {
		m_report.SetWindowText(_T("Error"));

		return FALSE;
	}

	hr = pGB->Connect(
			 GetFirstPin((pSrc), PINDIR_OUTPUT),
			 GetFirstPin((pMid), PINDIR_INPUT));

	if (FAILED(hr)) {
		m_report.SetWindowText(_T("Error Connect pSrc / pMid"));
		return FALSE;
	}

	hr = pGB->Connect(
			 GetFirstPin((pMid), PINDIR_OUTPUT),
			 GetFirstPin((pDst), PINDIR_INPUT));
	if (FAILED(hr)) {
		m_report.SetWindowText(_T("Error Connect pMid / pDst"));
		return FALSE;
	}

	pMS = pMid;

	pMC->Run();

	m_nIDTimerEvent = SetTimer(1, 500, NULL);

	return TRUE;
}
HRESULT CSaveTaskDlg::InitFileCopy()
{
	AppSettings& s = AfxGetAppSettings();

	if (OpenImageCheck(m_in) && s.strSnapShotExt != _T(".*")) {
		OpenImageDIB(m_in, m_out, s.iThumbQuality, 0);
		return S_OK;
	}

	if (FAILED(pGB.CoCreateInstance(CLSID_FilterGraph)) || !(pMC = pGB) || !(pME = pGB) || !(pMS = pGB)) {
		SetFooterIcon(MAKEINTRESOURCE(IDI_ERROR));
		SetFooterText(ResStr(IDS_AG_ERROR));
		return S_FALSE;
	}

	HRESULT hr;

	CStringW fnw = m_in;
	CComPtr<IFileSourceFilter> pReader;

	if (!pReader && m_in.Mid(m_in.ReverseFind('.')+1).MakeLower() == _T("cda")) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)DNew CCDDAReader(NULL, &hr);

		if (FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL))) {
			pReader.Release();
		}
	}

	if (!pReader) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)DNew CCDXAReader(NULL, &hr);

		if (FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL))) {
			pReader.Release();
		}
	}

	if (!pReader ) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)DNew CVTSReader(NULL, &hr);

		if (FAILED(hr) || !(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL))) {
			pReader.Release();
		} else {
			CPath pout(m_out);
			pout.RenameExtension(_T(".ifo"));
			CopyFile(m_in, pout, FALSE);
		}
	}

	if (!pReader) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk;
		pUnk.CoCreateInstance(CLSID_AsyncReader);

		if (!(pReader = pUnk) || FAILED(pReader->Load(fnw, NULL))) {
			pReader.Release();
		}
	}

	if (!pReader) {
		hr = S_OK;
		CComPtr<IUnknown> pUnk;
		pUnk.CoCreateInstance(CLSID_URLReader);

		if (CComQIPtr<IBaseFilter> pSrc = pUnk) {
			pGB->AddFilter(pSrc, fnw);

			if (!(pReader = pUnk) || FAILED(hr = pReader->Load(fnw, NULL))) {
				pReader.Release();
				pGB->RemoveFilter(pSrc);
			}
		}
	}

	CComQIPtr<IBaseFilter> pSrc = pReader;

	if (FAILED(pGB->AddFilter(pSrc, fnw))) {
		SetFooterIcon(MAKEINTRESOURCE(IDI_ERROR));
		SetFooterText(_T("Sorry, can't save this file, press Cancel"));
		return S_FALSE;
	}

	CComQIPtr<IBaseFilter> pMid = DNew CStreamDriveThruFilter(NULL, &hr);

	if (FAILED(pGB->AddFilter(pMid, L"StreamDriveThru"))) {
		SetFooterIcon(MAKEINTRESOURCE(IDI_ERROR));
		SetFooterText(ResStr(IDS_AG_ERROR));

		return S_FALSE;
	}

	CComQIPtr<IBaseFilter> pDst;
	pDst.CoCreateInstance(CLSID_FileWriter);
	CComQIPtr<IFileSinkFilter2> pFSF = pDst;
	pFSF->SetFileName(CStringW(m_out), NULL);
	pFSF->SetMode(AM_FILE_OVERWRITE);

	if (FAILED(pGB->AddFilter(pDst, L"File Writer"))) {
		SetFooterIcon(MAKEINTRESOURCE(IDI_ERROR));
		SetFooterText(ResStr(IDS_AG_ERROR));

		return S_FALSE;
	}

	hr = pGB->Connect(
			 GetFirstPin((pSrc), PINDIR_OUTPUT),
			 GetFirstPin((pMid), PINDIR_INPUT));

	if (FAILED(hr)) {
		SetFooterIcon(MAKEINTRESOURCE(IDI_ERROR));
		SetFooterText(_T("Error Connect pSrc / pMid"));

		return S_FALSE;
	}

	hr = pGB->Connect(
			 GetFirstPin((pMid), PINDIR_OUTPUT),
			 GetFirstPin((pDst), PINDIR_INPUT));
	if (FAILED(hr)) {
		SetFooterIcon(MAKEINTRESOURCE(IDI_ERROR));
		SetFooterText(_T("Error Connect pMid / pDst"));

		return S_FALSE;
	}

	pMS = pMid;

	pMC->Run();

	return S_OK;
}
HRESULT CStreamSwitcherInputPin::CompleteConnect(IPin* pReceivePin)
{
	HRESULT hr = __super::CompleteConnect(pReceivePin);
	if (FAILED(hr)) {
		return hr;
	}

	(static_cast<CStreamSwitcherFilter*>(m_pFilter))->CompleteConnect(PINDIR_INPUT, this, pReceivePin);

	m_fCanBlock = false;
	bool fForkedSomewhere = false;

	CStringW fileName;
	CStringW pinName;

	IPin* pPin = (IPin*)this;
	IBaseFilter* pBF = (IBaseFilter*)m_pFilter;

	pPin = GetUpStreamPin(pBF, pPin);
	if (pPin) {
		pBF = GetFilterFromPin(pPin);
	}
	while (pPin && pBF) {
		if (IsSplitter(pBF)) {
			pinName = GetPinName(pPin);
		}

		CLSID clsid = GetCLSID(pBF);
		if (clsid == CLSID_AviSplitter || clsid == CLSID_OggSplitter) {
			m_fCanBlock = true;
		}

		int nIn, nOut, nInC, nOutC;
		CountPins(pBF, nIn, nOut, nInC, nOutC);
		fForkedSomewhere = fForkedSomewhere || nIn > 1 || nOut > 1;

		if (CComQIPtr<IFileSourceFilter> pFSF = pBF) {
			WCHAR* pszName = NULL;
			AM_MEDIA_TYPE mt;
			if (SUCCEEDED(pFSF->GetCurFile(&pszName, &mt)) && pszName) {
				fileName = pszName;
				CoTaskMemFree(pszName);

				fileName.Replace('\\', '/');
				CStringW fn = fileName.Mid(fileName.ReverseFind('/')+1);
				if (!fn.IsEmpty()) {
					fileName = fn;
				}

				// Haali & LAVFSplitter return only one "Audio" pin name, cause CMainFrame::OnInitMenuPopup lookup find the wrong popmenu,
				// add space at the end to prevent this, internal filter never return "Audio" only.
				if (!pinName.IsEmpty()) {
					fileName = pinName + L" ";
				}

				WCHAR* pName = DNew WCHAR[fileName.GetLength()+1];
				if (pName) {
					wcscpy_s(pName, fileName.GetLength() + 1, fileName);
					if (m_pName) {
						delete [] m_pName;
					}
					m_pName = pName;
				}
			}

			break;
		}

		pPin = GetFirstPin(pBF);

		pPin = GetUpStreamPin(pBF, pPin);
		if (pPin) {
			pBF = GetFilterFromPin(pPin);
		}
	}

	if (!fForkedSomewhere) {
		m_fCanBlock = true;
	}

	m_hNotifyEvent = NULL;

	return S_OK;
}