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

📄 capture.cpp

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

⌨️ 快捷键说明

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