⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 capture.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	if(FAILED(pIPinOutput->Disconnect()))
	{
		ASSERT(FALSE);
		return E_FAIL;
	}

	if(FAILED(pIPinInput->Disconnect()))
	{
		ASSERT(FALSE);
		return E_FAIL;
	}

	// Now just connect the two pins
	hr = m_pGB->ConnectDirect(pIPinOutput, pIPinInput, pmt);
	ASSERT(SUCCEEDED(hr));
	if(FAILED(hr))
		TRACE("Could not connect pins!");

	// Release the two pins and return the result
	pIPinOutput->Release();
	pIPinInput->Release();

	return hr;
}

//自动连接Filter
STDMETHODIMP CCaptureGraph::ConnectAutoPins(IBaseFilter* pIFilterOutput, 
											LPCTSTR pstrPinNameOutput,
											IBaseFilter* pIFilterInput, 
											LPCTSTR pstrPinNameInput)
{
	HRESULT hr;
	ASSERT(m_pGB);

	// Parameters...
	if((!pIFilterOutput) || (!pIFilterInput))
	{
		ASSERT(pIFilterOutput && pIFilterInput);
		TRACE("ConnectPins called with NULL parameter\n");
		return E_INVALIDARG;
	}

	// Find the first pin
	IPin* pIPinOutput = FindPinOnFilter(pIFilterOutput, 
		pstrPinNameOutput,
		PINDIR_OUTPUT);
	if(!pIPinOutput)
	{
		ASSERT(pIPinOutput);
		return E_FAIL;
	}

	// Find the second pin
	IPin* pIPinInput = FindPinOnFilter(pIFilterInput,
		pstrPinNameInput,
		PINDIR_INPUT);
	if(!pIPinInput)
	{
		ASSERT(pIPinInput);
		// release the other pin
		pIPinOutput->Release();
		return E_FAIL;
	}

	if(FAILED(pIPinOutput->Disconnect()))
	{
		ASSERT(FALSE);
		return E_FAIL;
	}

	if(FAILED(pIPinInput->Disconnect()))
	{
		ASSERT(FALSE);
		return E_FAIL;
	}

	// Now just connect the two pins
	hr = m_pGB->Connect(pIPinOutput, pIPinInput);
	ASSERT(SUCCEEDED(hr));
	if(FAILED(hr))
		TRACE("Could not connect pins!");

	// Release the two pins and return the result
	pIPinOutput->Release();
	pIPinInput->Release();

	return hr;
}

STDMETHODIMP_(BOOL) CCaptureGraph::IsConnected(IBaseFilter *pFilter,
											   LPCTSTR pstrPinName, 
											   PIN_DIRECTION pd)
{
	ASSERT(m_pGB);

	// Parameters...
	if((!pFilter))
	{
		ASSERT(pFilter);
		TRACE("ConnectPins called with NULL parameter\n");
		return FALSE;
	}

	// Find the pin
	IPin* pIPin = FindPinOnFilter(pFilter, 
		pstrPinName,
		pd);
	if(!pIPin)
	{
		ASSERT(pIPin);
		return FALSE;
	}

	IPin  *pNextPin = NULL;

	pIPin->ConnectedTo(&pNextPin);
	if(!pNextPin)
	{
		return FALSE;
	}

	pIPin->Release();
	pNextPin->Release();

	//That's it...
	return TRUE;
}

STDMETHODIMP CCaptureGraph::DisconnectPin(IBaseFilter *pIFilter, 
										  LPCTSTR pstrPinName,
										  PIN_DIRECTION dir)
{
	HRESULT hr;
	ASSERT(m_pGB);

	// Parameters...
	if(!pIFilter)
		// DON'T fail on this, it is expected
		return NOERROR;

	// Find the pin
	IPin* pIPin = FindPinOnFilter(pIFilter, pstrPinName, dir);
	if(!pIPin)
	{
		TRACE("Could not find specified filter pin\n");
		return E_FAIL;
	}

	// Find the pin it's connected to
	IPin* pIPinConnected;
	hr = pIPin->ConnectedTo(&pIPinConnected);
	if((FAILED(hr)) || (!pIPinConnected))
	{
		// Function call failed, pin not connected, nothing to do!
		pIPin->Release();
		return NOERROR;
	}

	// Try to disconnect the input pin first
	if (dir == PINDIR_INPUT)
	{
		// ok now disconnect both of them
		hr = m_pGB->Disconnect(pIPin);
		if(FAILED(hr))
		{
			// just forget everything
			ASSERT(SUCCEEDED(hr));
			pIPin->Release();
			pIPinConnected->Release();
			TRACE("Disconnect failed on input pin\n");
			return hr;
		}
		hr = m_pGB->Disconnect(pIPinConnected);
		if(FAILED(hr))
		{
			ASSERT(SUCCEEDED(hr));
			TRACE("Disconnect failed on output pin\n");
		}
	}
	else
	{
		// ok now disconnect both of them
		hr = m_pGB->Disconnect(pIPinConnected);
		if(FAILED(hr))
		{
			ASSERT(SUCCEEDED(hr));
			// just forget everything
			pIPin->Release();
			pIPinConnected->Release();
			TRACE("Disconnect failed on input pin\n");
			return hr;
		}
		hr = m_pGB->Disconnect(pIPin);
		if(FAILED(hr))
		{
			ASSERT(SUCCEEDED(hr));
			TRACE("Disconnect failed on output pin\n");
		}
	}

	// Just release the two pins and return last result
	pIPin->Release();
	pIPinConnected->Release();

	return hr;
}

STDMETHODIMP_(IPin*) CCaptureGraph::FindPinOnFilter(IBaseFilter* pIFilter, 
													LPCTSTR pstrPinName,
													PIN_DIRECTION dir)
{
	HRESULT     hr;
	IEnumPins*  pIEnumPins;
	IPin*       pIPin;
	PIN_INFO    pi;
	ASSERT(m_pGB);

	// Parameters...
	if(!pIFilter)
		return NULL;

	// Enumerate pins on the filter
	hr = pIFilter->EnumPins(&pIEnumPins);
	if(FAILED(hr))
		// pin was not found!
		return NULL;

	// Loop till we find no more pins
	IPin* pIPinFound = NULL;
	while( (!pIPinFound) && (pIEnumPins->Next(1, &pIPin, NULL)==S_OK) )
	{
		// Is this the pin?
		hr = pIPin->QueryPinInfo(&pi);
		if(!FAILED(hr))
		{
			// check if it is the right direction
			if(pi.dir == dir)
			{
				// Let the graph builder find the right filter
				TCHAR strFoundPinName[256];
#ifndef _UNICODE
				// not unicode, we need to de-unicodify the returned pin name
				WideCharToMultiByte(CP_ACP, NULL,
					pi.achName, -1,
					strFoundPinName, sizeof(strFoundPinName),
					NULL, NULL);
#else
				// just make a copy of the string
				lstrcpyn(strFoundPinName, pi.achName, sizeof(strFoundPinName));
#endif

				// check if there is a pin name specified	
				if(!pstrPinName)
				{
					// no name specified, take the first pin found
					pIPinFound = pIPin;
					pIPinFound->AddRef();
				}
				// check if we have the right pin name
				else if(lstrcmp(strFoundPinName, pstrPinName)==0)
				{
					// yes we have!
					pIPinFound = pIPin;
					pIPinFound->AddRef();
				}
			}

			// release the PIN_INFO data
			pi.pFilter->Release();
		}

		// release the IPin pointer
		pIPin->Release();
	}

	// Finished with the enumerator, let it go (be free)
	pIEnumPins->Release();

	// Return whatever we have found
	return pIPinFound;
}

STDMETHODIMP CCaptureGraph::BuildGraph()
{
	HRESULT hr;	

	//添加TV Sink Filter
	hr = AddFilter(CLSID_TVStreamSink, &m_pTVStreamSink);
	if (FAILED(hr))
	{
		return hr;
	}

	hr = m_pTVStreamSink->Release();

	//添加IID_ITVSouceConfig接口
	hr = m_pTVStreamSink->QueryInterface(IID_ITVSouceConfig, (VOID**)&m_pTVConfig);
	if(FAILED(hr))
	{
		TRACE("cant Get the ITVConfig interface!!");
		return hr;
	}
	//判断是否为DV设备将判断结果置为mbISDV的值若是DV则走DV的流程
	JudgeDV();

	//若为只有音频设备,则调TV Sink接口
	if(m_bIsOnlyAudio)
	{
		m_pTVConfig->SetAudioOrVideoOnly(m_bIsOnlyAudio);
	}
	m_pTVConfig->Release();

	//若为DV则调用DV的Graph
	if (TRUE == mbIsDV)
	{
		hr = DisplayDV();//DisplayDV();
		if (SUCCEEDED(hr))
		{
			m_bGraphBuiled = TRUE;
			return hr;
		}
		return hr;
	}

	//若不是DV则调用一般的Graph
	hr = BuildGeneralGraph();
	if (SUCCEEDED(hr))
	{
		m_bGraphBuiled = TRUE;
		return hr;
	}
	return hr;
	// that's ok, we can run it!
	//m_bGraphBuiled = TRUE;
	//return S_OK;
}

STDMETHODIMP CCaptureGraph::DisassembleGraph()
{
	HRESULT hr;
	/*
	// first must stop
	if(m_hWndOwner != NULL)
	{
	CWnd wd;
	wd.Attach(m_hWndOwner);
	//((CGVCaptureDlg*)wd.GetParent())->OnNotifyStop();
	wd.Detach();
	}
	*/

	RemoveFilter(m_pVideoCapture);
	RemoveFilter(m_pVideoEncoder);
	RemoveFilter(m_pAudioCapture);
	RemoveFilter(m_pAudioEncoder);
	RemoveFilter(m_pTVStreamSink);
	RemoveFilter(m_pVideoSmartTee);
	RemoveFilter(m_pftrDVSpliter);
	RemoveFilter(m_pDVDecoder);

	for(int i = 0; i < m_arrayOtherFilter.GetSize(); i++)
	{
		IBaseFilter *pFilter = (IBaseFilter*)(m_arrayOtherFilter.GetAt(i));
		RemoveFilter(pFilter);
	}
	// added by zk for saving 2004-04-16
	if(m_pVideoSmartTee)
		RemoveFilter(m_pVideoSmartTee);
	if(m_pAudioSmartTee)
		RemoveFilter(m_pAudioSmartTee);
	if(m_pAVIMuxer)
		RemoveFilter(m_pAVIMuxer);
	if(m_pFileWriter)
		RemoveFilter(m_pFileWriter);
	// release All filter in the graph except for 
	// videocapture and videoencoder.these two filters will be
	// deleted in create CreateCapDeviceFilterByName and 
	// CreateEncoderFilterByNamer
	SAFE_RELEASE(m_pAudioCapture);
	//	SAFE_RELEASE(m_pTVStreamSink);
	SAFE_RELEASE(m_pVideoSmartTee);
	SAFE_RELEASE(m_pAudioSmartTee);
	//	SAFE_RELEASE(m_pTVConfig);
	SAFE_RELEASE(m_pftrDVSpliter);
	SAFE_RELEASE(m_pDVDecoder);

	for(i=0; i<m_arrayOtherFilter.GetSize(); i++)
	{
		IBaseFilter *pFilter = (IBaseFilter*)(m_arrayOtherFilter.GetAt(i));
		SAFE_RELEASE(pFilter);
	}
	m_arrayOtherFilter.RemoveAll();

	m_bGraphBuiled = FALSE;


	CComPtr <IVideoWindow> lpVideoWindow;
	hr = m_pGB->QueryInterface(IID_IVideoWindow, (void**)&lpVideoWindow);
	if (FAILED(hr))
	{					
		return hr;
	}	
	hr = lpVideoWindow->put_Visible(OAFALSE);

	return S_OK;
}

//  [10/6/2005] xiezhouwei 
void CCaptureGraph::JudgeDV()
{
	HRESULT hr;

	CComPtr<ICaptureGraphBuilder2> lpgraphBuilder2;
	//获得graphBuilder2_
	hr = lpgraphBuilder2.CoCreateInstance(CLSID_CaptureGraphBuilder2); 
	if (FAILED(hr))
	{
		return ;
	}

	hr = lpgraphBuilder2->SetFiltergraph(m_pGB);
	if (FAILED(hr))
	{
		return ;
	}

	//判断是否为DV设备,如果不是就照正常的进行采集,否则链路将要变。
	IAMStreamConfig *pSC;
	mbIsDV =FALSE;			//首先假设不是DV设备
	hr = lpgraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,
		&MEDIATYPE_Interleaved, m_pVideoCapture,
		IID_IAMStreamConfig, (void **)&pSC);

	if(hr != NOERROR)
		hr = lpgraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,
		&MEDIATYPE_Video, m_pVideoCapture,
		IID_IAMStreamConfig, (void **)&pSC);
	if (!FAILED(hr))
	{
		AM_MEDIA_TYPE *pmt;
		if(pSC && pSC->GetFormat(&pmt) == S_OK)
		{
			if(pmt->formattype == FORMAT_DvInfo)
			{						
				mbIsDV = TRUE;
			}
		}
		pSC->Release();
	}
}

HRESULT CCaptureGraph::BuildGeneralAudio()
{
	HRESULT hr;
	hr = GetAudioCaptureDevice();
	if (FAILED(hr))
	{
		return hr;
	}
	hr = m_pGB->AddFilter(m_pAudioCapture, NULL);
	if (FAILED(hr))
	{
		return hr;
	}	
	if (NULL == m_pAudioEncoder)
	{
		AfxMessageBox("请选择正确的音频解码器");
		return E_FAIL;
	}
	hr = m_pGB->AddFilter(m_pAudioEncoder, NULL);
	if (FAILED(hr))
	{
		return hr;
	}
	hr = ConnectPins(m_pAudioCapture, NULL, m_pAudioEncoder, NULL);
	if (FAILED(hr))
	{
		AfxMessageBox("请选择正确的音频解码器");
		return hr;
	}
	hr = AddFilter(CLSID_InfTee, &m_pAudioSmartTee);
	if (FAILED(hr))
	{		
		return hr;
	}
	hr = ConnectPins(m_pAudioEncoder, NULL, m_pAudioSmartTee,NULL);
	if (FAILED(hr))
	{
		AfxMessageBox("音频部分构建出错");
		return hr;
	}
	//[AudioSmartTee] -> [TVSink]
	hr = ConnectPins(m_pAudioSmartTee, __T("Output1"), m_pTVStreamSink, __T("Audio"), m_pCurAudioAMT);
	if(FAILED(hr))
	{
		AfxMessageBox("不能进行播放,请重新选择音频编码器。");
		return hr;
	}
	return hr;
}

//在VideoGraph中加入字幕Filter
HRESULT CCaptureGraph::AddVideoOverlayFilter()
{
	HRESULT hr;
	hr = m_pGB->AddFilter(m_pVideoOverlay, NULL);
	if (FAILED(hr))
	{
		return hr;
	}
	hr = ConnectPins(m_pVideoCapture, NULL, m_pVideoOverlay, NULL);
	if (FAILED(hr))
	{
		AfxMessageBox("连接字幕Filter出错");
		return hr;
	}

	if (NULL == m_pVideoEncoder)
	{
		AfxMessageBox("视频编码器出错");
		return E_FAIL;
	}
	hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
	if (FAILED(hr))
	{
		return hr;
	}

	//如果是DMO组件
	if (IsDMOFilter())
	{
		hr = BuildVideoDMOEncoder();						
		if (FAILED(hr))
		{
			return hr;
		}
	}
	else
	{
		hr = ConnectPins(m_pVideoOverlay, NULL, m_pVideoEncoder, NULL);
		if (FAILED(hr))
		{
			AfxMessageBox("视频编码器出错。请重新选择视频编码器");
			return hr;
		}
	}	
	return hr;
}

//视频部分预览

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -