Capture.cpp
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:61k
源码类别:
P2P编程
开发平台:
Visual C++
- /*
- * Openmysee
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
- #include "stdafx.h"
- #include <atlbase.h>
- #include <dmodshow.h>
- #include <qedit.h>
- #include "capture.h"
- #include "utilities.h"
- #include "audiocompressselectordlg.h"
- #include "GVCaptureDlg.h"
- #include "audiochangeddlg.h"
- #include "videochanged.h"
- #include "SysConfig.h"
- #include "wmcodecconst.h"
- #include "VideoEncParams.h"
- #include "macros.h"
- #include "videoenc.h"
- #include "streams.h"
- #pragma comment(lib,"Dmoguids")
- #pragma comment(lib,"Winmm")
- //static const GUID CLSID_TVStreamSink =
- //{ 0x1860c8d5, 0x370b, 0x4334, { 0x99, 0xf1, 0xb7, 0xc, 0x37, 0x9f, 0xac, 0x67 } };
- // {C2B146BB-C61D-4673-AF41-5079E6855401}
- static const GUID CLSID_TVStreamSink =
- { 0xc2b146bb, 0xc61d, 0x4673, { 0xaf, 0x41, 0x50, 0x79, 0xe6, 0x85, 0x54, 0x1 } };
- static const GUID CLSID_FVideoOverlay =
- {0xae1c4226, 0xb8ec, 0x4204, { 0xbf, 0x15, 0x92, 0x56, 0x63, 0xde, 0x51, 0x68} };
- //用于WM9的外部变量
- extern CVideoEncParams g_VideoEncodingParams;
- //////////////////////////////////////////////////////////////////////////
- //以下是构造和析构函数
- //////////////////////////////////////////////////////////////////////////
- CCaptureGraph::CCaptureGraph()
- {
- m_config = FALSE;
- state = NULL;
- sstate = 0;
- m_RefCount = 0;
- m_pGB = NULL; // capture graph
- m_pVW = NULL; // video window
- m_pMC = NULL; // media control
- m_pTVConfig = NULL; // tv sink config
- // filters in graph
- m_pVideoCapture = NULL;
- m_pVideoEncoder = NULL;
- m_pAudioEncoder = NULL;
- m_pAudioCapture = NULL;
- m_pTVStreamSink = NULL;
- m_pVideoSmartTee = NULL;
- m_pAudioSmartTee = NULL;
- m_pAVIMuxer = NULL;
- m_pFileWriter = NULL;
- m_pftrDVSpliter = NULL;
- m_pDVDecoder = NULL;
- //xiezhouwei 05-08-17添加
- m_pVideoOverlay = NULL;
- m_arrayOtherFilter.RemoveAll();
- m_bGraphBuiled = FALSE;
- m_bIsPreview = TRUE;
- m_bIsOnlyAudio = FALSE;
- m_bSave = FALSE; // added by zk for saving 2004-04-16
- m_bNeedOverlay = TRUE;
- mbIsDV = FALSE; //added by xiezhouwei 2005-09-01
- m_bISCrossBar = FALSE; //默认不选择CrossBar
- m_strCurVideoEncoder.Empty();
- m_pCurAudioAMT = NULL;
- m_hWndOwner = NULL;
- ZeroMemory(m_szAVIFile,sizeof(m_szAVIFile));
- }
- CCaptureGraph::~CCaptureGraph()
- {
- Uninitialize();
- }
- STDMETHODIMP_(ULONG) CCaptureGraph::AddRef()
- {
- return ++m_RefCount;
- }
- STDMETHODIMP_(ULONG) CCaptureGraph::Release()
- {
- m_RefCount--;
- if(m_RefCount == 0)
- delete this;
- return m_RefCount;
- }
- STDMETHODIMP CCaptureGraph::QueryInterface(REFIID iid, void** ppInter)
- {
- // we need not to implement this now
- // it only for late_use
- return E_NOTIMPL;
- }
- STDMETHODIMP CCaptureGraph::Initialize()
- {
- HRESULT hr = CoInitialize(NULL);
- if (FAILED(hr))
- {
- TRACE0("ERROR - Could not initialize COM library");
- return hr;
- }
- // Create the filter graph manager and query for interfaces.
- hr = CoCreateInstance(CLSID_FilterGraph,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_IGraphBuilder,
- (void **)&m_pGB);
- if (FAILED(hr))
- {
- TRACE0("ERROR - Could not create the Filter Graph Manager.");
- return hr;
- }
- hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
- if (FAILED(hr))
- {
- TRACE0("ERROR - Could not Get IMediaControl");
- return hr;
- }
- // for DEBUG
- #ifdef _DEBUG
- AddGraphToRot(m_pGB, &g_dwRegister);
- #endif //_DEBUG
- return S_OK;
- }
- STDMETHODIMP CCaptureGraph::Uninitialize()
- {
- // first unDEBUG
- #ifdef _DEBUG
- RemoveGraphFromRot(g_dwRegister);
- #endif //_DEBUG
- RemoveFilter(m_pVideoCapture);
- RemoveFilter(m_pAudioCapture);
- RemoveFilter(m_pVideoEncoder);
- RemoveFilter(m_pAudioEncoder);
- RemoveFilter(m_pVideoSmartTee);
- RemoveFilter(m_pAudioSmartTee);
- RemoveFilter(m_pTVStreamSink);
- RemoveFilter(m_pVideoOverlay);
- RemoveFilter(m_pAVIMuxer);
- RemoveFilter(m_pFileWriter);
- RemoveFilter(m_pDVDecoder);
- state = NULL;
- SAFE_RELEASE(m_pGB);
- SAFE_RELEASE(m_pVW);
- SAFE_RELEASE(m_pMC);
- // SAFE_RELEASE(m_pTVConfig);
- // filters in graph
- SAFE_RELEASE(m_pVideoCapture);
- SAFE_RELEASE(m_pVideoEncoder);
- SAFE_RELEASE(m_pAudioEncoder);
- SAFE_RELEASE(m_pAudioCapture);
- // SAFE_RELEASE(m_pTVStreamSink);
- SAFE_RELEASE(m_pVideoSmartTee);
- SAFE_RELEASE(m_pAudioSmartTee);
- SAFE_RELEASE(m_pAVIMuxer);
- SAFE_RELEASE(m_pFileWriter);
- SAFE_RELEASE(m_pVideoOverlay);
- SAFE_RELEASE(m_pDVDecoder);
- m_hWndOwner = NULL;
- CoUninitialize();
- return S_OK;
- }
- // controls
- STDMETHODIMP CCaptureGraph::Run()
- {
- HRESULT hr;
- if(!m_bGraphBuiled)
- {
- if(FAILED(BuildGraph()))
- {
- DisassembleGraph();
- return E_FAIL;
- }
- }
- CComPtr <IVideoWindow> lpVideoWindow;
- hr = m_pGB->QueryInterface(IID_IVideoWindow, (void**)&lpVideoWindow);
- if (FAILED(hr))
- {
- return hr;
- }
- hr = lpVideoWindow->put_Visible(OATRUE);
- ASSERT(m_pMC);
- return m_pMC->Run();
- }
- STDMETHODIMP CCaptureGraph::Stop()
- {
- HRESULT hr;
- ASSERT(m_pMC);
- CComPtr <IVideoWindow> lpVideoWindow;
- hr = m_pGB->QueryInterface(IID_IVideoWindow, (void**)&lpVideoWindow);
- if (FAILED(hr))
- {
- return hr;
- }
- hr = lpVideoWindow->put_AutoShow(OAFALSE);
- hr = lpVideoWindow->put_Visible(OAFALSE);
- return m_pMC->Stop();
- }
- STDMETHODIMP CCaptureGraph::Pause()
- {
- ASSERT(m_pMC);
- return m_pMC->Pause();
- }
- // enums,it respectively call EnumSpeciFilters
- // with diffrent specification
- STDMETHODIMP CCaptureGraph::EnumVideoCapDevices(CStringArray &strArrayType)
- {
- return EnumSpeciFilters(VIDEO_CAP, strArrayType);
- }
- STDMETHODIMP CCaptureGraph::EnumAudioCapDevices(CStringArray &strArrayType)
- {
- return EnumSpeciFilters(AUDIO_CAP, strArrayType);
- }
- STDMETHODIMP CCaptureGraph::EnumVideoEncoders(CStringArray &strArrayType)
- {
- return EnumSpeciFilters(VIDEO_COMPRESS, strArrayType);
- }
- STDMETHODIMP CCaptureGraph::EnumAudioEncoders(CStringArray &strArrayType)
- {
- return EnumSpeciFilters(AUDIO_COMPRESS, strArrayType);
- }
- // configs
- STDMETHODIMP CCaptureGraph::ConfigVideoCapDeviceByName(HWND hParent)
- {
- if (NULL == m_pVideoCapture)
- {
- AfxMessageBox("视频采集设备未找到");
- return S_OK;
- }
- // must be added in the graph this time
- m_pGB->AddFilter(m_pVideoCapture, NULL);
- /*
- * FIRST: prompt user to set filter configuration
- */
- // Get property page interface
- HRESULT hr;
- IAMVfwCaptureDialogs* pDlg;
- hr = m_pVideoCapture->QueryInterface(IID_IAMVfwCaptureDialogs, (void**)(&pDlg));
- if(!FAILED(hr))
- {
- if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Format)))
- {
- hr = pDlg->ShowDialog(VfwCaptureDialog_Format, hParent);
- }
- if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Source)))
- {
- hr = pDlg->ShowDialog(VfwCaptureDialog_Source, hParent);
- }
- if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Display)))
- {
- hr = pDlg->ShowDialog(VfwCaptureDialog_Display, hParent);
- }
- return hr;
- }
- ISpecifyPropertyPages *pSpec;
- hr = m_pVideoCapture->QueryInterface(IID_ISpecifyPropertyPages, (void**)(&pSpec));
- if(FAILED(hr))
- {
- return E_FAIL;
- }
- // Popup page
- CString str(_T("Video Capture Configuration 1")); // dlg caption
- WCHAR wstrCaption[256];
- CAUUID cauuid;
- pSpec->GetPages(&cauuid);
- pSpec->Release();
- 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 **)&m_pVideoCapture, cauuid.cElems,
- (GUID *)cauuid.pElems, 0, 0, NULL);
- if(FAILED(hr))
- {
- CoTaskMemFree(cauuid.pElems);
- pSpec->Release();
- return E_FAIL;
- }
- }
- // Destructor
- CoTaskMemFree(cauuid.pElems);
- return S_OK;
- }
- // configs
- STDMETHODIMP CCaptureGraph::ConfigAudioCapDeviceByName(HWND hParent)
- {
- if (NULL == m_pAudioCapture)
- {
- AfxMessageBox("视频采集设备未找到");
- return S_OK;
- }
- // must be added in the graph this time
- m_pGB->AddFilter(m_pAudioCapture, NULL);
- /*
- * FIRST: prompt user to set filter configuration
- */
- // Get property page interface
- HRESULT hr;
- IAMVfwCaptureDialogs* pDlg;
- hr = m_pAudioCapture->QueryInterface(IID_IAMVfwCaptureDialogs, (void**)(&pDlg));
- if(!FAILED(hr))
- {
- if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Format)))
- {
- hr = pDlg->ShowDialog(VfwCaptureDialog_Format, hParent);
- }
- if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Source)))
- {
- hr = pDlg->ShowDialog(VfwCaptureDialog_Source, hParent);
- }
- if ( !FAILED(pDlg->HasDialog(VfwCaptureDialog_Display)))
- {
- hr = pDlg->ShowDialog(VfwCaptureDialog_Display, hParent);
- }
- return hr;
- }
- ISpecifyPropertyPages *pSpec;
- hr = m_pAudioCapture->QueryInterface(IID_ISpecifyPropertyPages, (void**)(&pSpec));
- if(FAILED(hr))
- {
- return E_FAIL;
- }
- // Popup page
- CString str(_T("Audio Capture Configuration 1")); // dlg caption
- WCHAR wstrCaption[256];
- CAUUID cauuid;
- pSpec->GetPages(&cauuid);
- pSpec->Release();
- 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 **)&m_pAudioCapture, cauuid.cElems,
- (GUID *)cauuid.pElems, 0, 0, NULL);
- if(FAILED(hr))
- {
- CoTaskMemFree(cauuid.pElems);
- pSpec->Release();
- return E_FAIL;
- }
- }
- // Destructor
- CoTaskMemFree(cauuid.pElems);
- return S_OK;
- }
- //Arthur?
- bool isEqualFOURCC(FOURCC fccA, FOURCC fccB) {
- int i;
- for(i=0; i<4; i++) {
- if (tolower((unsigned char)fccA) != tolower((unsigned char)fccB))
- return false;
- fccA>>=8;
- fccB>>=8;
- }
- return true;
- }
- ////////////////
- HIC hic=0;
- BYTE *pState = NULL;
- int size = 0;
- ICINFO in;
- STDMETHODIMP CCaptureGraph::ConfigVideoEncoderByName(HWND hParent)
- {
- HRESULT hr;
- if (NULL == m_pVideoEncoder)
- {
- return E_FAIL;
- }
- if (NULL == hParent)
- {
- AfxMessageBox("hParent不能为空");
- }
- hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
- if (FAILED(hr))
- {
- return E_FAIL;
- }
- if (TRUE == IsDMOFilter())
- {
- return S_OK;
- }
- //ASSERT(m_pVideoEncoder);
- if(hic)
- {
- ICClose(hic);
- TRACE("hic值为:%d",hic);
- }
- //Arthur:?将压缩信息中ICTYPE_VIDEO进行枚举。若能打开则取出他的信息。
- //判断它的描述信息是否和当前的m_strCurVideoEncoder一致。一致则显示配置
- //配置信息框。(若pState中有可设置的值。则将之,设入。?是否会将上次的
- //pState设置到这次的hic中去。)再用ICGetState得到信息。再将之设回去??
- //何必呢?并将之保存在state变量中。
- //一切连接好后,若用户选择马上中断则会,将全部filter移出。若不是则将之
- //移出后再立刻接上会不会有问题,是否执行了重定位操作。
- ICINFO info;
- for(int i=0; ICInfo(ICTYPE_VIDEO, i, &info); i++)//Arthur:该函数的用法逐步取出i个ICINFO结构。
- {
- hic = ICOpen(info.fccType, info.fccHandler, ICMODE_COMPRESS);//Arthur:打开该压缩器。
- if(hic == NULL)
- continue;
- ICINFO ici = { sizeof(ICINFO) };
- CHAR* lpszDes;
- if (ICGetInfo(hic, &ici, sizeof(ICINFO)))//Arthur:得到该压缩器。并将描述信息放入
- //lpszDes中
- {
- int cch = lstrlenW(ici.szDescription) + 1;
- lpszDes = new char[cch * 2];
- if (!lpszDes)
- {
- AfxMessageBox("开辟描述名buf失败");
- return E_OUTOFMEMORY;
- }
- WideCharToMultiByte(GetACP(), 0, ici.szDescription,
- -1,lpszDes, cch, NULL, NULL);
- }
- if(CString(lpszDes) == m_strCurVideoEncoder)//若取出的,是自己要的
- {
- if(ICQueryConfigure(hic))
- {
- if (state)
- ICSetState(hic, state, sstate);
- if (NULL == hParent || 0 == hic)
- {
- AfxMessageBox("父窗口指针为空,无法显示");
- return E_FAIL;
- }
- ICConfigure(hic, hParent);//Arthur:显示该压缩码的对话框。
- if(pState)
- delete [] pState;
- size = ICGetStateSize(hic);
- pState = new BYTE[size];
- if (0 == hic || NULL == pState)
- {
- AfxMessageBox("pState为零");
- return E_FAIL;
- }
- int nt = ICGetState(hic, pState, size);//Arthur:得到hic此时的状态信息
- if(nt > 0)
- {
- m_config = TRUE;
- if (NULL == state)
- {
- state=new BYTE[size + 1];
- if (NULL == state)
- {
- AfxMessageBox("State为零");
- return E_FAIL;
- }
- }
- ICSetState(hic, pState, size);//为什么要重新设置一次,此时pState的信息已经是完善了的。
- memcpy(state,pState,size);
- sstate=size;
- }
- }
- if (lpszDes)
- {
- delete [] lpszDes;
- }
- break;
- }
- ICClose(hic);
- hic = 0;
- if (lpszDes)
- {
- delete [] lpszDes;
- }
- }
- OAFilterState ofs;
- m_pMC->GetState(1000, &ofs);
- if(ofs == State_Running)
- {
- CVideoChanged vc;
- if(vc.DoModal() == IDOK)
- {
- CWnd wd;
- wd.Attach(m_hWndOwner);
- ((CGVCaptureDlg*)wd.GetParent())->OnNotifyStop();
- DisassembleGraph();
- ((CGVCaptureDlg*)wd.GetParent())->OnNotifyPlay();
- wd.Detach();
- }
- }
- else
- {
- if(m_bGraphBuiled)
- {
- DisassembleGraph();
- if(FAILED(BuildGraph()))
- {
- DisassembleGraph();
- return E_FAIL;
- }
- }
- }
- return S_OK;
- }
- STDMETHODIMP CCaptureGraph::ConfigAudioEncoderByName(HWND hParent)
- {
- if (NULL == m_pAudioEncoder)
- {
- return E_FAIL;
- }
- if (NULL == m_hWndOwner)
- {
- AfxMessageBox("m_hWndOwner不能为空");
- }
- CWnd wnd;
- wnd.Attach(m_hWndOwner);
- CAudioCompressSelectorDlg afs(this, &wnd);
- if(afs.DoModal()== IDOK)
- {
- OAFilterState ofs;
- m_pMC->GetState(1000, &ofs);
- if(ofs == State_Running)
- {
- CAudioChangedDlg vc;
- if(vc.DoModal() == IDOK)
- {
- AfxMessageBox("不可能执行的代码");
- ((CGVCaptureDlg*)wnd.GetParent())->OnNotifyStop();
- DisassembleGraph();
- ((CGVCaptureDlg*)wnd.GetParent())->OnNotifyPlay();
- }
- }
- else
- {
- if(m_bGraphBuiled)
- {
- DisassembleGraph();
- if(FAILED(BuildGraph()))
- {
- wnd.Detach();
- DisassembleGraph();
- return E_FAIL;
- }
- }
- }
- }
- wnd.Detach();
- return S_OK;
- }
- //系统设置框
- STDMETHODIMP CCaptureGraph::ConfigSysCfg(HWND hParent)
- {
- CSysConfig afs;
- afs.DoModal();
- return S_OK;
- }
- // some filter creations must be implemented by enumulator
- // implemented with FindFilterByName auxily function
- HRESULT CCaptureGraph::CreateVideoCapDeviceFilterByName(LPTSTR strName)
- {
- // here we disassamble the graph
- if (m_bGraphBuiled)
- {
- DisassembleGraph();
- }
- RemoveFilter(m_pVideoCapture);
- SAFE_RELEASE(m_pVideoCapture);
- FindFilterByName(strName, &m_pVideoCapture, VIDEO_CAP);
- if(m_pVideoCapture == NULL)
- {
- TRACE0("no this filte in system");
- return S_FALSE;
- }
- return NOERROR;
- }
- // some filter creations must be implemented by enumulator
- // implemented with FindFilterByName auxily function
- HRESULT CCaptureGraph::CreateAudioCapDeviceFilterByName(LPTSTR strName)
- {
- // here we disassamble the graph
- if (m_bGraphBuiled)
- {
- DisassembleGraph();
- }
- RemoveFilter(m_pAudioCapture);
- SAFE_RELEASE(m_pAudioCapture);
- FindFilterByName(strName, &m_pAudioCapture, AUDIO_CAP);
- if(m_pAudioCapture == NULL)
- {
- TRACE0("no this filte in system");
- return S_FALSE;
- }
- return NOERROR;
- }
- BOOL CCaptureGraph::IsDMOFilter()
- {
- HRESULT hr;
- IDMOWrapperFilter *pDmoWrapper;
- hr = m_pVideoEncoder->QueryInterface(IID_IDMOWrapperFilter, (void**)&pDmoWrapper);
- if (SUCCEEDED(hr))
- {
- return TRUE;
- }
- return FALSE;
- }
- STDMETHODIMP CCaptureGraph::BuildVideoDMOEncoder()
- {
- AM_MEDIA_TYPE mtIn, mtOut;
- mtIn.majortype = MEDIATYPE_Video; //set this for the call to "Connect Filters"
- mtIn.cbFormat = 0;
- GetInputMediaType(m_pVideoCapture, mtIn); //S_FALSE is ok here
- // now connect these filters and render them
- if (NULL == m_pVideoOverlay)
- {
- if(FAILED(ConnectPins(m_pVideoCapture, NULL, m_pVideoEncoder, NULL, &mtIn)))
- {
- AfxMessageBox("不能进行播放,请重新选择视频编码器。");
- return E_FAIL;
- }
- }
- else
- {
- if(FAILED(ConnectPins(m_pVideoOverlay, NULL, m_pVideoEncoder, NULL, &mtIn)))
- {
- AfxMessageBox("不能进行播放,请重新选择视频编码器。");
- return E_FAIL;
- }
- }
- CComQIPtr<IMediaObject, &IID_IMediaObject> pDMO(m_pVideoEncoder);
- ConfigureDMO(pDMO, &mtIn, &mtOut);
- // Get Wrapper's output pin
- IPin* pOutPin = FindPinOnFilter( m_pVideoEncoder, NULL, PINDIR_OUTPUT );
- if(pOutPin == NULL)
- {
- TRACE("Failed to get wrapper's output pin!");
- return E_FAIL;
- }
- // Set the output media type
- CComQIPtr<IAMStreamConfig, &IID_IAMStreamConfig> pIAMStreamConfig( pOutPin );
- ON_QI_FAIL("Failed to QI for IAMStreamConfig!", pIAMStreamConfig)
- // Set the media type
- HRESULT hr = pIAMStreamConfig->SetFormat( &mtOut );
- ON_FAIL("Failed to set wrapper's output type!", hr)
- FreeMediaType(mtIn);
- FreeMediaType(mtOut);
- return S_OK;
- }
- HRESULT CCaptureGraph::CreateV9EncoderFilter()
- {
- // here we disassamble the graph
- // DisassembleGraph();
- HRESULT hr = CoCreateInstance(CLSID_DMOWrapperFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&m_pVideoEncoder);
- if (SUCCEEDED(hr))
- {
- // Query for IDMOWrapperFilter.
- IDMOWrapperFilter *pDmoWrapper;
- hr = m_pVideoEncoder->QueryInterface(IID_IDMOWrapperFilter, (void**)&pDmoWrapper);
- if (SUCCEEDED(hr))
- {
- // Initialize the filter.
- hr = pDmoWrapper->Init(CLSID_CWMVEncMediaObject2, CLSID_VideoCompressorCategory);
- pDmoWrapper->Release();
- if (SUCCEEDED(hr))
- {
- // Add the filter to the graph.
- hr = m_pGB->AddFilter(m_pVideoEncoder, L"My DMO");
- }
- }
- }
- return hr;
- }
- HRESULT CCaptureGraph::CreateVideoEncoderFilterByName(LPTSTR strName)
- {
- // here we disassamble the graph
- if (NULL == strName)
- {
- AfxMessageBox("Filter名称为空");
- return E_FAIL;
- }
- if (m_bGraphBuiled)
- {
- DisassembleGraph();
- }
- RemoveFilter(m_pVideoEncoder);
- SAFE_RELEASE(m_pVideoEncoder);
- if (0 == strcmp(strName, "MicroSoft Media 9 DMO"))
- {
- CreateV9EncoderFilter();
- }
- else
- {
- FindFilterByName(strName, &m_pVideoEncoder, VIDEO_COMPRESS);
- }
- if(m_pVideoEncoder == NULL)
- {
- TRACE0("no this filte in system");
- return S_FALSE;
- }
- m_strCurVideoEncoder = strName;
- return NOERROR;
- }
- HRESULT CCaptureGraph::CreateAudioEncoderFilterByName(LPTSTR strName)
- {
- // here we disassamble the graph
- if (NULL == strName)
- {
- AfxMessageBox("Filter名称为空");
- return E_FAIL;
- }
- if (m_bGraphBuiled)
- {
- DisassembleGraph();
- }
- RemoveFilter(m_pAudioEncoder);
- SAFE_RELEASE(m_pAudioEncoder);
- FindFilterByName(strName, &m_pAudioEncoder, AUDIO_COMPRESS);
- if (m_pAudioEncoder == NULL)
- {
- TRACE0("no this filte in system");
- return S_FALSE;
- }
- if(m_pCurAudioAMT)
- {
- HeapFree(GetProcessHeap(), 0, m_pCurAudioAMT);
- m_pCurAudioAMT = NULL;
- }
- return NOERROR;
- }
- //xiezhouwei 05-08-17 添加
- /*
- // 设置是否需要字幕的
- void CCaptureGraph::SetNeedOverlay(bool abNeedOverlay)
- {
- m_bNeedOverlay = abNeedOverlay;
- }
- */
- //初始化字幕Filter
- HRESULT CCaptureGraph::CreateUideoOverlay()
- {
- HRESULT hr;
- hr = CoCreateInstance(CLSID_FVideoOverlay,
- NULL,
- CLSCTX_INPROC,
- IID_IBaseFilter,
- (void **)&m_pVideoOverlay);
- if(FAILED(hr))
- {
- TRACE("Could not instantiate VideoOverlay filter");
- }
- return hr;
- }
- //配置字幕property。
- HRESULT CCaptureGraph::ConfigVideoOverlay(HWND hParent)
- {
- ASSERT(m_pVideoOverlay);
- HRESULT hr;
- ISpecifyPropertyPages *pSpec;
- hr = m_pVideoOverlay->QueryInterface(IID_ISpecifyPropertyPages, (void**)(&pSpec));
- if(FAILED(hr))
- {
- return E_FAIL;
- }
- // Popup page
- CAUUID cauuid;
- pSpec->GetPages(&cauuid);
- if(cauuid.cElems >= 1)
- {
- hr = OleCreatePropertyFrame(NULL, 30, 30, /*wstrCaption*/NULL, 1,
- (IUnknown **)&pSpec, cauuid.cElems,
- (GUID *)cauuid.pElems, 0, 0, NULL);
- if(FAILED(hr))
- {
- CoTaskMemFree(cauuid.pElems);
- pSpec->Release();
- return hr;
- }
- }
- // Destructor
- CoTaskMemFree(cauuid.pElems);
- pSpec->Release();
- return hr;
- }
- //释放掉字幕filter
- void CCaptureGraph::ReleaseUideoOverlay()
- {
- //DisassembleGraph();
- if (TRUE == m_bGraphBuiled)
- {
- DisassembleGraph();
- }
- RemoveFilter(m_pVideoOverlay);
- SAFE_RELEASE(m_pVideoOverlay);
- }
- // preview
- VOID CCaptureGraph::SetPreview(BOOL bIsPreview)
- {
- if(m_bGraphBuiled)
- {
- if(bIsPreview)
- {
- m_pVW->put_Owner((OAHWND)m_hWndOwner);
- m_pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
- 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);
- }
- else
- {
- m_pVW->put_Visible(0);
- m_pVW->put_AutoShow(0);
- m_pVW->put_Owner(NULL);
- }
- }
- m_bIsPreview = bIsPreview;
- }
- void CCaptureGraph::SetOnlyAudio( BOOL bIsOnlyAudio )
- {
- OAFilterState ofs;
- m_pMC->GetState(1000, &ofs);
- m_bIsOnlyAudio = bIsOnlyAudio;
- if(ofs == State_Running)
- {
- //将对wd的操作解除。因为在DisassembleGraph中会会做的,
- //如果不解除,因为attach操作不允许同时做两遍,会导致断言。
- CWnd wd;
- wd.Attach(m_hWndOwner);
- ((CGVCaptureDlg*)wd.GetParent())->OnNotifyStop();
- DisassembleGraph();
- ((CGVCaptureDlg*)wd.GetParent())->OnNotifyPlay();
- wd.Detach();
- }
- else
- {
- if(m_bGraphBuiled)
- {
- DisassembleGraph();
- if(FAILED(BuildGraph()))
- DisassembleGraph();
- }
- }
- }
- STDMETHODIMP CCaptureGraph::AddFilter(CLSID clsidFilter,
- IBaseFilter** ppIFilter,
- LPCTSTR pstrFilterName)
- {
- HRESULT hr;
- ASSERT(m_pGB);
- ASSERT(ppIFilter);
- (*ppIFilter) = NULL;
- // try to instantiate the filter
- hr = CoCreateInstance(clsidFilter,
- NULL,
- CLSCTX_INPROC,
- IID_IBaseFilter,
- (LPVOID*)(ppIFilter));
- if(FAILED(hr))
- {
- TRACE("Could not instantiate filter");
- return hr;
- }
- // Check for unicode or not
- #ifndef _UNICODE
- if(pstrFilterName)
- {
- // not unicode, we need to unicodify the string
- WCHAR wstrFilterName[256];
- MultiByteToWideChar(CP_ACP,
- MB_PRECOMPOSED | MB_USEGLYPHCHARS,
- pstrFilterName,
- -1,
- wstrFilterName,
- sizeof(wstrFilterName) / sizeof(WCHAR));
- // try to add it to the filter graph
- hr = m_pGB->AddFilter(*ppIFilter, wstrFilterName);
- }
- else
- {
- // No filter name specified, cannot convert
- // try to add it to the filter graph
- hr = m_pGB->AddFilter(*ppIFilter, NULL);
- }
- #else
- // already unicode, no need to change anything
- // try to add it to the filter graph
- hr = m_pGB->AddFilter(*ppIFilter, pstrFilterName);
- #endif
- // check the result of the operation
- if(FAILED(hr))
- {
- TRACE("Could not add filter to filter graphn");
- // free the filter definitely
- (*ppIFilter)->Release();
- (*ppIFilter) = NULL;
- return hr;
- }
- // that's it
- return hr;
- }
- STDMETHODIMP CCaptureGraph::RemoveFilter(IBaseFilter* pIFilter)
- {
- HRESULT hr;
- // Parameters...
- if(!pIFilter)
- // DON'T return an error, this is expected
- return NOERROR;
- ASSERT(m_pGB);
- // Just remove it from the graph
- hr = m_pGB->RemoveFilter(pIFilter);
- // Check the result
- if(FAILED(hr))
- TRACE("Could not remove filter from filter graphn");
- return hr;
- }
- STDMETHODIMP CCaptureGraph::ConnectPins(IBaseFilter* pIFilterOutput,
- LPCTSTR pstrPinNameOutput,
- IBaseFilter* pIFilterInput,
- LPCTSTR pstrPinNameInput,
- AM_MEDIA_TYPE* pmt)
- {
- HRESULT hr;
- ASSERT(m_pGB);
- // Parameters...
- if((!pIFilterOutput) || (!pIFilterInput))
- {
- ASSERT(pIFilterOutput && pIFilterInput);
- TRACE("ConnectPins called with NULL parametern");
- 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->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 parametern");
- 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 parametern");
- 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 pinn");
- 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 pinn");
- return hr;
- }
- hr = m_pGB->Disconnect(pIPinConnected);
- if(FAILED(hr))
- {
- ASSERT(SUCCEEDED(hr));
- TRACE("Disconnect failed on output pinn");
- }
- }
- 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 pinn");
- return hr;
- }
- hr = m_pGB->Disconnect(pIPin);
- if(FAILED(hr))
- {
- ASSERT(SUCCEEDED(hr));
- TRACE("Disconnect failed on output pinn");
- }
- }
- // 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;
- }
- //视频部分预览
- 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))
- {
- 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;
- }