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

📄 capture.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
📖 第 1 页 / 共 5 页
字号:
HRESULT CCaptureGraph::BuildVideoPreview()
{
	HRESULT hr;
	CComPtr <IPin> lpPin = NULL; 
	//pPreview = FindPinOnFilter(m_pVideoSmartTee, __T("Output2"))
	lpPin = FindPinOnFilter(m_pVideoSmartTee, __T("Output2"));				
	if (lpPin == NULL)
	{
		AfxMessageBox("预览pin出错");
		return E_FAIL;
	}			
	hr = m_pGB->Render(lpPin);	

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

	hr = lpVideoWindow->put_Owner((OAHWND)m_hWndOwner);
	lpVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
	CRect rc;
	GetClientRect(m_hWndOwner, &rc);
	lpVideoWindow->put_Top(0);
	lpVideoWindow->put_Left(0);
	lpVideoWindow->put_Width(rc.Width());
	lpVideoWindow->put_Height(rc.Height());
	lpVideoWindow->put_Visible(-1);
	lpVideoWindow->put_AutoShow(-1);	
	return hr;
}


HRESULT CCaptureGraph::OpenCrossBar()
{
	HRESULT hr;
	CComPtr<IBaseFilter> pNULL;
	hr = AddFilter(CLSID_NullRenderer, &pNULL);
	if(FAILED(hr))
	{
		TRACE("cant add smarttee filter to graph");
		return hr;
	}

	//获得lpgraphBuilder2_
	CComPtr<ICaptureGraphBuilder2> lpgraphBuilder2_;
	hr = lpgraphBuilder2_.CoCreateInstance(CLSID_CaptureGraphBuilder2);	
	if (FAILED(hr))
	{
		return hr;		
	}
	hr = lpgraphBuilder2_->SetFiltergraph(m_pGB);

	hr = lpgraphBuilder2_->RenderStream( &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, m_pVideoCapture, 0, pNULL );	

	hr = lpgraphBuilder2_->RenderStream( &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCapture, 0, pNULL );

	if (SUCCEEDED(hr))
	{
		IAMCrossbar *pX;

		hr = lpgraphBuilder2_->FindInterface(&PIN_CATEGORY_CAPTURE,
			&MEDIATYPE_Interleaved, m_pVideoCapture,
			IID_IAMCrossbar, (void **)&pX);

		if(FAILED(hr))
		{
			hr = lpgraphBuilder2_->FindInterface(&PIN_CATEGORY_CAPTURE,
				&MEDIATYPE_Video, m_pVideoCapture,
				IID_IAMCrossbar, (void **)&pX);
		}
		if (SUCCEEDED(hr))
		{
			ISpecifyPropertyPages *pSpec;
			CAUUID cauuid;

			hr = pX->QueryInterface(IID_ISpecifyPropertyPages,
				(void **)&pSpec);			
			if(S_OK == hr)
			{
				hr = pSpec->GetPages(&cauuid);

				hr = OleCreatePropertyFrame(m_hWndOwner, 30, 30, NULL, 1,
					(IUnknown **)&pX, cauuid.cElems,
					(GUID *)cauuid.pElems, 0, 0, NULL); 
				CoTaskMemFree(cauuid.pElems);
				pSpec->Release(); 
			}
			pX->Release();	               
		}
	}
	return hr;
}

//构建并预览一般的Graph的视频部分
HRESULT CCaptureGraph::BuildGeneralVideo()
{
	HRESULT hr;
	if (NULL == m_pVideoCapture)
	{
		AfxMessageBox("视频采集设备出错");
		return E_FAIL;
	}
	hr = m_pGB->AddFilter(m_pVideoCapture, NULL);
	if (FAILED(hr))
	{
		return hr;
	}

	if (TRUE == m_bISCrossBar)
	{
		hr = OpenCrossBar();
	}	

	//如果有字幕的Filter
	if (NULL != m_pVideoOverlay)
	{
		hr = AddVideoOverlayFilter();
		if (FAILED(hr))
		{
			return hr;
		}
	}
	else
	{
		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_pVideoCapture, NULL, m_pVideoEncoder, NULL);
			if (FAILED(hr))
			{
				AfxMessageBox("视频编码器出错。请重新选择视频编码器");
				return hr;
			}
		}		
	}

	hr = AddFilter(CLSID_InfTee, &m_pVideoSmartTee);
	if (FAILED(hr))
	{			
		return hr;
	}
	hr = ConnectPins(m_pVideoEncoder, NULL, m_pVideoSmartTee, NULL);
	if (FAILED(hr))
	{
		AfxMessageBox("视频编码器出错,请重新选择视频编码器");
		return hr;
	}		
	//[VideoSmartTee] -> [TVSink]
	hr = ConnectPins(m_pVideoSmartTee, __T("Output1"), m_pTVStreamSink, __T("Video"));
	if(FAILED(hr))
	{
		AfxMessageBox("不能进行播放,请重新选择音频编码器。");
		return hr;
	}

	if (m_bIsPreview)
	{
		hr = BuildVideoPreview();
	}
	return hr;
}

HRESULT CCaptureGraph::BuildSaveGraph()
{
	HRESULT hr;
	//Add AVI Muxer and Filewriter
	if(FAILED(AddFilter(CLSID_AviDest, &m_pAVIMuxer)))
	{
		TRACE("cant add Avi mux filter to graph");
		return E_FAIL;
	}
	if(FAILED(AddFilter(CLSID_FileWriter, &m_pFileWriter)))
	{
		TRACE("cant add Filewriter filter to graph");
		return E_FAIL;
	}

	IConfigAviMux*	lpAviMux = NULL;
	hr = m_pAVIMuxer->QueryInterface(IID_IConfigAviMux, (void**)&lpAviMux); 

	if (FAILED(hr))
	{
		AfxMessageBox("AVI 设置失败");
		lpAviMux->Release();
		return E_FAIL;
	}

	hr = lpAviMux->SetOutputCompatibilityIndex(TRUE);

	if (FAILED(hr))
	{
		AfxMessageBox("AVI 设置失败");
		lpAviMux->Release();
		return E_FAIL;
	}

	hr = lpAviMux->SetMasterStream(0);//为音频输入PIN序号 

	if (FAILED(hr))
	{
		AfxMessageBox("AVI 设置失败");
		lpAviMux->Release();
		return E_FAIL;
	}
	lpAviMux->Release();

	//[AudioSmartTee] --> [AVIMux]
	if(FAILED(ConnectPins(m_pAudioSmartTee, __T("Output2"), m_pAVIMuxer, __T("Input 01"))))
	{
		AfxMessageBox("不能保存音频。");
		return E_FAIL;
	}

	if (!m_bIsOnlyAudio)//如果不是只采音频的情况
	{
		if ( m_bIsPreview )
		{
			//[VideoSmartTee] --> [AVIMux]
			if(FAILED(ConnectPins(m_pVideoSmartTee, __T("Output3"), m_pAVIMuxer, __T("Input 02"))))
			{
				AfxMessageBox("不能保存视频。");
				return E_FAIL;
			}
		}
		else
		{
			//[VideoSmartTee] --> [AVIMux]
			if(FAILED(ConnectPins(m_pVideoSmartTee, __T("Output2"), m_pAVIMuxer, __T("Input 02"))))
			{
				AfxMessageBox("不能保存视频。");
				return E_FAIL;
			}
		}
	}
	//Set Output FileName
	IFileSinkFilter *pFileSink = NULL;
	m_pFileWriter->QueryInterface(IID_IFileSinkFilter, (VOID**)(&pFileSink));
	if (NULL == pFileSink)
	{
		return E_FAIL;
	}

	WCHAR wstrFilename[MAX_PATH];
	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_USEGLYPHCHARS,
		m_szAVIFile, -1, 
		wstrFilename, sizeof(wstrFilename) / sizeof(WCHAR));

	pFileSink->SetFileName(wstrFilename, NULL);
	pFileSink->Release();

	hr = ConnectPins(m_pAVIMuxer, NULL, m_pFileWriter, NULL);
	if(FAILED(hr))
	{
		AfxMessageBox("不能保存成文件。");
		return E_FAIL;
	}
	return hr;
}

HRESULT CCaptureGraph::BuildGeneralGraph()
{
	HRESULT hr;
	hr = BuildGeneralAudio();
	if (FAILED(hr))
	{
		return hr;
	}

	//构建视频部分
	if (FALSE == m_bIsOnlyAudio)
	{
		hr = BuildGeneralVideo();
	}

	if (FAILED(hr))
	{
		return hr;
	}

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

// audio compression format
HRESULT CCaptureGraph::EnumAudioWaveFormat(CListBox* pLB)// called by main dlg
{
	IPin *pOutPin;

	//ASSERT(m_pCurAudioAMT);

	if(FAILED(pOutPin = FindPinOnFilter(m_pAudioEncoder, NULL)))
	{
		TRACE("cant get outpin of Audio encoder!");
		return E_FAIL;
	}

	IEnumMediaTypes *pEmt;
	if(FAILED(pOutPin->EnumMediaTypes(&pEmt)))
	{
		pOutPin->Release();
		return E_FAIL;
	}

	for(int i = 0; i < pLB->GetCount(); i++)
		HeapFree(GetProcessHeap(), 0, pLB->GetItemDataPtr(i));

	pLB->ResetContent();

	ULONG uFetch;
	AM_MEDIA_TYPE *pamt;
	CString strTemp;
	CString strFormat;
	int liResult = 0;//保存两个当前媒体类型和枚举媒题类型的比较结果
	while(pEmt->Next(1, &pamt, &uFetch) == S_OK)
	{
		if(pamt->formattype == FORMAT_WaveFormatEx)
		{
			WAVEFORMATEX *pw = (WAVEFORMATEX *)(pamt->pbFormat);


			strTemp.Format("%.3fKbits/s, %dHz", (pw->nAvgBytesPerSec*8)/1024.0, pw->nSamplesPerSec);
			if(pw->nChannels == 1)
				strFormat.Format("%s, mono", strTemp);
			else
				strFormat.Format("%s, stereo", strTemp);

			AM_MEDIA_TYPE *pwfe = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(), 
				HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, 
				sizeof(AM_MEDIA_TYPE) + pamt->cbFormat);
			memcpy(pwfe, pamt, sizeof(AM_MEDIA_TYPE));
			pwfe->pbFormat = (LPBYTE)(pwfe+1);
			memcpy(pwfe->pbFormat, pw, pamt->cbFormat);
			int idx = pLB->AddString(strFormat);
			pLB->SetItemDataPtr(idx, pwfe);
			//Arthur:0806Add
			//当前媒体类型不动,这里只是负责选择,如果当前类型在枚举的时候已经不存在,则依然不动。
			//如果用户选择了新的则改变,否则继续不动。
			if (!m_pCurAudioAMT)
			{
				continue;
			}
			if (m_pCurAudioAMT->cbFormat == pwfe->cbFormat)
			{
				liResult = memcmp(m_pCurAudioAMT, pwfe,sizeof(AM_MEDIA_TYPE) - 4);
				if (!liResult)
				{//如果两者一样就将这项选择
					liResult = memcmp(m_pCurAudioAMT->pbFormat, pwfe->pbFormat,m_pCurAudioAMT->cbFormat);
					if (!liResult)
					{
						pLB->SetCurSel(idx);
					}
				}
			}
		}
	}

	pEmt->Release();
	pOutPin->Release();

	return S_OK;
}

void CCaptureGraph::SetAudioWaveformat(AM_MEDIA_TYPE* pamt)// called by selector dlg
{
	if(pamt)
	{
		//Arthur:0806Modify
		WAVEFORMATEX *pwfe = (WAVEFORMATEX *)pamt;//Arthur:Bug.该指针根本就没用
		//

		if (!m_pCurAudioAMT)
		{
			m_pCurAudioAMT = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(), 
				HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, 
				sizeof(AM_MEDIA_TYPE) + pamt->cbFormat);
		}
		ZeroMemory(m_pCurAudioAMT, sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat);

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

// used to enum fiters in specified catagory
HRESULT CCaptureGraph::EnumSpeciFilters(IID iidEnumType, CStringArray &strArrayType)
{
	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(iidEnumType, &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;
	}

	while (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
	{
		IPropertyBag *pPropBag;
		hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
			(void **)&pPropBag);
		if (SUCCEEDED(hr))
		{
			VARIANT varName;
			VariantInit(&varName);
			hr = pPropBag->Read(L"FriendlyName", &varName, 0);
			if (SUCCEEDED(hr))
			{
				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);

				if(iidEnumType == VIDEO_CAP)
                    strArrayType.Add(lpszFilterName);
                else if(iidEnumType == AUDIO_CAP)
                    strArrayType.Add(lpszFilterName);
				else if(iidEnumType == VIDEO_COMPRESS)
				{
					if(strcmp(lpszFilterName, "Microsoft H.261 Video Codec") != 0 &&
						strcmp(lpszFilterName, "Microsoft H.263 Video Codec") != 0 &&
						strcmp(lpszFilterName, "Microsoft RLE") != 0 && 
						strcmp(lpszFilterName, "ffdshow video encoder") != 0)
						strArrayType.Add(lpszFilterName);
				}
				else if(iidEnumType == AUDIO_COMPRESS)
				{
					if(strcmp(lpszFilterName, "WM Speech Encoder DMO") != 0 &&
						strcmp(lpszFilterName, "ACELP.net") != 0)
						strArrayType.Add(lpszFilterName);
				}
				else
					ASSERT(FALSE);

				delete [] lpszFilterName;
			}
			VariantClear(&varName);

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

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

	return S_OK;
}

// used to create filter 
HRESULT CCaptureGraph::FindFilterByName(LPTSTR strName, IBaseFilter **ppFilter, IID iidEnumType)
{
	if(ppFilter == NULL)
		return E_INVALIDARG;

	*ppFilter = NULL;

	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(iidEnumType, &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;
	}

	while (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
	{
		IPropertyBag *pPropBag;
		hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
			(void **)&pPropBag);
		if (SUCCEEDED(hr))
		{
			VARIANT varName;
			VariantInit(&varName);
			hr = pPropBag->Read(L"FriendlyName", &varName, 0);
			if (SUCCEEDED(hr))

⌨️ 快捷键说明

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