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

📄 capture.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			{
				int cch = lstrlenW(varName.bstrVal) + 1;
				CHAR* lpszFilterName = new char[cch * 2];
				if (!lpszFilterName) 
					return E_OUTOFMEMORY;
				WideCharToMultiByte(GetACP(), 0, varName.bstrVal, -1,
					lpszFilterName, cch, NULL, NULL);
				VariantClear(&varName);
				if(strcmp(lpszFilterName, strName) == 0)
				{
					hr = pMoniker->BindToObject(NULL, NULL, 
						IID_IBaseFilter,
						(VOID**)ppFilter);

					delete [] lpszFilterName;
					pPropBag->Release();
					pMoniker->Release();
					break;
				}

				delete [] lpszFilterName;
			}

			pPropBag->Release();
		}
		pMoniker->Release();
	}

	pClassEnum->Release();
	pDevEnum->Release();

	return S_OK;
}

// used to get audio capture device 
HRESULT CCaptureGraph::GetAudioCaptureDevice()
{
	HRESULT hr;
	IMoniker *pMoniker =NULL;
	ULONG cFetched;

	// Create the system device enumerator
	ICreateDevEnum* pDevEnum = NULL;

	hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
		IID_ICreateDevEnum, (void **) &pDevEnum);
	if (FAILED(hr))
	{		
		TRACE1(TEXT("Couldn't create system enumerator!  hr=0x%x"), hr);
		return hr;
	}

	IEnumMoniker *pClassEnum = NULL;
	hr = pDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pClassEnum, 0);
	if (FAILED(hr))
	{
		pDevEnum->Release();
		TRACE1(TEXT("Couldn't create class enumerator!  hr=0x%x"), hr);
		return hr;
	}
	if (pClassEnum == NULL)
	{
		pDevEnum->Release();
		return S_OK;
	}
	pDevEnum->Release();
	hr = pClassEnum->Reset();
	if(S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
	{
		hr = pMoniker->BindToObject(NULL, NULL, 
			IID_IBaseFilter,
			(VOID**)&m_pAudioCapture);
		if(FAILED(hr))
		{
			pMoniker->Release();
			pClassEnum->Release();
			TRACE("Cant find Audio Capture");
			return hr;
		}
	}
	pMoniker->Release();
	pClassEnum->Release();
	return hr;
}

// used for filling the m_arryOtherFilter, diff from our 
// refrenced filters
BOOL CCaptureGraph::IsFilterInStdFilters(IBaseFilter *pFilter)
{
	if(m_pVideoCapture == pFilter ||
		m_pAudioCapture == pFilter ||
		m_pVideoEncoder == pFilter ||
		m_pAudioEncoder == pFilter ||
		m_pTVStreamSink == pFilter ||
		m_pVideoSmartTee == pFilter)
		return TRUE;
	else
		return FALSE;
}

//得到媒体类型
bool CCaptureGraph::GetCurMediaType(AM_MEDIA_TYPE** aMTMediaType)
{
	//Arthur:把当前的媒体类型交出去。重新拷一下,不能直接只拷指针。只拷指针不能访问
	if(m_pCurAudioAMT)
	{

		if (!*aMTMediaType)
		{
			*aMTMediaType = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(), 
				HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, 
				sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat);
			if (!*aMTMediaType)
			{
				return false;
			}
		}
		memcpy(*aMTMediaType, m_pCurAudioAMT, sizeof(AM_MEDIA_TYPE));
		(*aMTMediaType)->pbFormat = (LPBYTE)(*aMTMediaType+ 1);//指针加1。则相当于空出一个AM_MEDIA_TYPE。在这
		//赋给pbFormat
		memcpy((*aMTMediaType)->pbFormat, m_pCurAudioAMT->pbFormat, m_pCurAudioAMT->cbFormat);
		int ii = sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat;
		return true;
	}
	return false;
}

//设置媒体类型
bool CCaptureGraph::SetCurMediaType(AM_MEDIA_TYPE *aMTMediaType)
{
	//设置当前媒体类型的一个指针。
	if(aMTMediaType)
	{
		//如果此时已经有媒体类型则将之释放掉
		if (!m_pCurAudioAMT)
		{
			m_pCurAudioAMT = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(), 
				HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, 
				sizeof(AM_MEDIA_TYPE) + aMTMediaType->cbFormat);
			if (!m_pCurAudioAMT)
			{
				return false;
			}
		}
		ZeroMemory(m_pCurAudioAMT, sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat);

		memcpy(m_pCurAudioAMT, aMTMediaType, sizeof(AM_MEDIA_TYPE));
		BYTE* ii = (LPBYTE)(m_pCurAudioAMT+1);
		int iii = sizeof(AM_MEDIA_TYPE);
		m_pCurAudioAMT->pbFormat = (LPBYTE)(m_pCurAudioAMT+1);//arthur:指针加1。则相当于空出一个AM_MEDIA_TYPE。在这
		//赋给pbFormat
		if (m_pCurAudioAMT->pbFormat && aMTMediaType->pbFormat)
		{
			memcpy(m_pCurAudioAMT->pbFormat, aMTMediaType->pbFormat, aMTMediaType->cbFormat);
		}
		return true;
	}
	return false;
}

//=========================================
// Writed by zhuwei 2005-8-12 
//Show Pin Setting
void CCaptureGraph::ShowPinSetting(HWND hParent)
{
	if (NULL == m_pVideoCapture)
	{
		AfxMessageBox("视频采集设备未找到");
		return;
	}
	/*
	* SECOND: prompt user to configure output pin configuration
	*/
	HRESULT hr;
	ISpecifyPropertyPages *pSpec;	
	WCHAR wstrCaption[256];

	CAUUID cauuid;
	// must be added in the graph this time
	m_pGB->AddFilter(m_pVideoCapture, NULL);

	IAMStreamConfig *pSC;
	IPin *pOutPin = FindPinOnFilter(m_pVideoCapture, NULL);
	hr = pOutPin->QueryInterface(IID_IAMStreamConfig, (void**)(&pSC));
	pOutPin->Release();
	if(FAILED(hr))
		return;
	hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void**)(&pSpec));
	if(FAILED(hr))
	{
		pSC->Release();
		return;
	}

	// Popup page
	CString str = CString(_T("Video Capture Configuration 2"));	// dlg caption
	pSpec->GetPages(&cauuid);
	if(cauuid.cElems >= 1)
	{
		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_USEGLYPHCHARS,
			str.GetBuffer(str.GetLength()), -1, 
			wstrCaption, sizeof(wstrCaption) / sizeof(WCHAR));

		hr = OleCreatePropertyFrame(hParent, 30, 30, wstrCaption, 1,
			(IUnknown **)&pSC, cauuid.cElems,
			(GUID *)cauuid.pElems, 0, 0, NULL);
		if(FAILED(hr))
		{
			CoTaskMemFree(cauuid.pElems);
			pSpec->Release();
			pSC->Release();
			return;
		}
	}

	// Destructor
	CoTaskMemFree(cauuid.pElems);
	pSpec->Release();
	pSC->Release();

	return;
}
//Set AVI Filename
void CCaptureGraph::SetAVIFile( char* szFile )
{
	if ( szFile[0] )
	{
		this->m_bSave = true;
		strncpy( this->m_szAVIFile, szFile, MAX_PATH);
	}
}

HRESULT CCaptureGraph::DVSplitter()
{
	HRESULT hr;
	if(!m_pVideoCapture)
	{
		AfxMessageBox("No Video Capture Device!");
		return E_FAIL;
	}
	hr = m_pGB->AddFilter(m_pVideoCapture, NULL);
	if(FAILED(hr))
	{
		TRACE("cant add video capture filter to graph");
		return hr;
	}
	hr = AddFilter(CLSID_DVSplitter, &m_pftrDVSpliter);
	//Add DV Splitter Filter				
	if(FAILED(hr))
	{
		AfxMessageBox("cant add DV Splitter Filter to graph");
		return hr;
	}
	hr = ConnectAutoPins(m_pVideoCapture, "DV A/V Out", m_pftrDVSpliter, NULL);
	if (FAILED(hr))
	{
		AfxMessageBox("cant ConnectDirect DV Splitter Filter to graph");
		return hr;
	}
	return hr;
}

HRESULT CCaptureGraph::BuildDVAudio()
{
	//DV加音频
	HRESULT hr;
	//Add Audio Encoder
	if(!m_pAudioEncoder)
	{
		AfxMessageBox("No Aduio Compressor available!");
		return E_FAIL;	
	}
	hr = m_pGB->AddFilter(m_pAudioEncoder, NULL);
	if(FAILED(hr))
	{
		TRACE("cant add audio encoder filter to graph");
		return hr;
	}

	//[DVSplitter] --> [AudioEncoder]
	hr = ConnectAutoPins(m_pftrDVSpliter,"AudOut00", m_pAudioEncoder, NULL);
	if(FAILED(hr))
	{
		AfxMessageBox("不能进行播放,请重新选择音频编码器。");
		return hr;
	}

	//Add AudioSmartTee
	hr = AddFilter(CLSID_InfTee, &m_pAudioSmartTee);
	if(FAILED(hr))
	{
		TRACE("cant add smarttee filter to graph");
		return hr;
	}
	//[AudioEncoder] --> [AudioSmartTee]
	hr = ConnectPins(m_pAudioEncoder, __T("Output"), m_pAudioSmartTee, __T("Input"));
	if(FAILED(hr))
	{
		AfxMessageBox("不能进行播放,请重新选择音频编码器。");
		return E_FAIL;
	}
	//[AudioSmartTee] -> [TVSink]
	hr = ConnectPins(m_pAudioSmartTee, __T("Output1"), m_pTVStreamSink, __T("Audio"), m_pCurAudioAMT);
	if(FAILED(hr))
	{
		AfxMessageBox("不能进行播放,请重新选择音频编码器。");
		return hr;
	}
	return hr;
}
HRESULT CCaptureGraph::AddDVVideoOverlay()
{
	HRESULT hr;
	hr = m_pGB->AddFilter(m_pVideoOverlay, NULL);
	if(FAILED(hr))
	{
		TRACE("cant add Video Overlay to graph");
		return E_FAIL;
	}
	//[DVEncoder] --> [VideoOverlay]
	hr = ConnectPins(m_pDVDecoder, NULL, m_pVideoOverlay, NULL);
	if(FAILED(hr))
	{
		AfxMessageBox("与字幕Filter连接失败");
		return E_FAIL;
	}

	//将字幕Filter和视频编码filter相连
	//Add Video Encoder 
	if(!m_pVideoEncoder)
	{
		AfxMessageBox("No Video Compressor available!");
		return E_FAIL;	
	}
	hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
	if(FAILED(hr))
	{
		TRACE("cant add video encoder filter to graph");
		return E_FAIL;
	}

	//如果是DMO组件
	if (IsDMOFilter())
	{
		hr = BuildVideoDMOEncoder();						
		if (FAILED(hr))
		{
			return hr;
		}
	}
	else
	{
		//[VideoOverlay] --> [VideoEncoder]
		hr = ConnectPins(m_pVideoOverlay, NULL, m_pVideoEncoder, NULL);
		if(FAILED(hr))
		{
			AfxMessageBox("不能进行播放,请重新选择视频编码器。");
			return hr;
		}
	}
	return hr;
}

//DV视频预览
HRESULT CCaptureGraph::BuildDVVideoPrview()
{
	//Get VideoSmartTee's Sencond Output Pin
	IPin *pPreview;
	if(FAILED(pPreview = FindPinOnFilter(m_pVideoSmartTee, __T("Output2"))))
	{
		TRACE("cant get preview outpin of smart tee!");
		return E_FAIL;
	}
	//Render pin
	HRESULT hr;
	hr = m_pGB->Render(pPreview);
	if(FAILED(hr))
	{
		AfxMessageBox("不能进行播放,请重新选择视频编码器。");
		return hr;
	}
	pPreview->Release();
	if ( NULL == m_pVW )
	{
		hr = m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW);
		if (FAILED(hr))
		{
			TRACE0("ERROR - Could not Get IVideoWindow.");
			return hr;
		}
	}
	m_pVW->put_Owner((OAHWND)m_hWndOwner);	
	m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
	CRect rc;
	GetClientRect(m_hWndOwner, &rc);
	m_pVW->put_Top(0);
	m_pVW->put_Left(0);
	m_pVW->put_Width(rc.Width());
	m_pVW->put_Height(rc.Height());
	m_pVW->put_Visible(-1);
	m_pVW->put_AutoShow(-1);
	return hr;
}

//构建DV视频链路
HRESULT CCaptureGraph::BuildDVVideo()
{
	HRESULT hr;
	hr = AddFilter(CLSID_DVVideoCodec, &m_pDVDecoder);
	if (FAILED(hr))
	{
		TRACE("加载m_pDVDecoder失败");
		return hr;
	}

	//为了解决CPU消耗过高,只减小输出画面
	IIPDVDec* lpDVDec = NULL;
	hr = m_pDVDecoder->QueryInterface(IID_IIPDVDec, (void**)&lpDVDec);
	if (FAILED(hr))
	{
		TRACE("获取IIPDVDec接口失败");
		return hr;
	}
	else
	{
		lpDVDec->put_IPDisplay(DVRESOLUTION_HALF);
		lpDVDec->Release();
	}

	//[DVSpliter] --> [DVVideoCodec]
	hr = ConnectPins(m_pftrDVSpliter, "DVVidOut0", m_pDVDecoder, NULL);
	if(FAILED(hr))
	{
		AfxMessageBox("与m_pDVDecoderFilter连接失败");
		return E_FAIL;
	}

	if (m_pVideoOverlay)//如果字幕filter有则需连字幕filter
	{
		hr = AddDVVideoOverlay();
	}
	else//不需要字幕的情况
	{
		//Add Video Encoder 
		if(!m_pVideoEncoder)
		{
			AfxMessageBox("No Video Compressor available!");
			return E_FAIL;	
		}
		hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
		if(FAILED(hr))
		{
			AfxMessageBox("cant add video encoder filter to graph");
			return hr;
		}

		//如果是DMO组件
		if (IsDMOFilter())
		{
			hr = BuildVideoDMOEncoder();						
			if (FAILED(hr))
			{
				return hr;
			}
		}
		else
		{
			//[DV Splitter] --> [VideoEncoder]
			hr = ConnectPins(m_pDVDecoder, NULL, m_pVideoEncoder, NULL);
			if(FAILED(hr))
			{
				AfxMessageBox("不能进行自动连接在m_pftrDVSpliter和m_pVideoEncoder之间");
				return E_FAIL;
			}
		}
	}

	//Add VideoSmartTee
	hr = AddFilter(CLSID_InfTee, &m_pVideoSmartTee);
	if(FAILED(hr))
	{
		TRACE("cant add smarttee filter to graph");
		return hr;
	}
	//[VideoEncoder] --> [VideoSmartTee]
	hr = ConnectPins(m_pVideoEncoder, NULL, m_pVideoSmartTee, __T("Input"));
	if(FAILED(hr))
	{
		TRACE("cant connect video encoder and Smart Tee!");
		return E_FAIL;
	}
	//[Video SmartTee] --> [TVSink]
	hr = ConnectPins(m_pVideoSmartTee, __T("Output1"), m_pTVStreamSink, __T("Video"));
	if(FAILED(hr))
	{
		AfxMessageBox("不能进行播放,请重新选择视频编码器。");
		return hr;
	}

	//==================================================================================================
	//预览
	if(m_bIsPreview)
	{
		hr = BuildDVVideoPrview();
		if (FAILED(hr))
		{
			return hr;
		}
	}
	return hr;
}

//采集DV
HRESULT CCaptureGraph::DisplayDV()
{	
	HRESULT hr;
	//分离DV的信号
	hr = DVSplitter();
	if (FAILED(hr))
	{
		return hr;
	}

	//构建DV音频
	hr = BuildDVAudio();
	if (FAILED(hr))
	{
		return hr;
	}

	if (FALSE == m_bIsOnlyAudio)
	{
		hr = BuildDVVideo();
		if (FAILED(hr))
		{
			return hr;
		}
	}

	if (m_bSave)
	{
		hr = BuildSaveGraph();
		if (FAILED(hr))
		{
			return hr;
		}
	}
	return hr;
}

⌨️ 快捷键说明

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