📄 mmsgraph.cpp
字号:
/*
* 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 "mmsgraph.h"
#include "configFile.h"
#include "string.h"
// {6B6D0800-9ADA-11d0-A520-00A0D10129C0}
DEFINE_GUID(CLSID_NetShowSource,
0x6b6d0800, 0x9ada, 0x11d0, 0xa5, 0x20, 0x0, 0xa0, 0xd1, 0x1, 0x29, 0xc0);
//////////////////////////////////////////////
// Only for Debug
static DWORD g_dwRegister;
static HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
{
#ifdef _DEBUG
IMoniker * pMoniker;
IRunningObjectTable *pROT;
HRESULT hr;
hr = GetRunningObjectTable(0, &pROT);
if (FAILED(hr)) return hr;
WCHAR wsz[128];
wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
hr = CreateItemMoniker(L"!", wsz, &pMoniker);
if (SUCCEEDED(hr))
{
hr = pROT->Register(0, pUnkGraph, pMoniker, pdwRegister);
pMoniker->Release();
}
pROT->Release();
return hr;
#endif
return S_OK;
}
static void RemoveGraphFromRot(DWORD pdwRegister)
{
#ifdef _DEBUG
IRunningObjectTable *pROT;
if (SUCCEEDED(GetRunningObjectTable(0, &pROT)))
{
pROT->Revoke(pdwRegister);
pROT->Release();
}
#endif
}
/////////////////////////////////////////////////////////////////
// CMMSGraph
CMMSGraph::CMMSGraph(string strChannel, string strMMSAddr, HRESULT *hr)
{
m_pGB = NULL;
m_pMC = NULL;
m_pMMSSource = NULL;
m_pSink = NULL;
m_pAsfAcmHandler = NULL;
m_pAsfIcmHandler = NULL;
m_pAudioSmartTee = NULL;
m_pTVConfig = NULL;
m_pMMSInfo = new MMSGRAPHINFO;
m_pMMSInfo->fDataRate = 0.0;
m_pMMSInfo->fTotalBytes=0;
m_pMMSInfo->m_oldtotalbyte=0;
m_pMMSInfo->mmsState = INIT;
m_pMMSInfo->llTimeEscaped = 0;
m_pMMSInfo->strChannelName = strChannel;
m_pMMSInfo->strMMSAddr = strMMSAddr;
m_pMMSInfo->llTimeEscaped = 0;
m_pMMSInfo->m_time=0;
m_bReconnecting = false;
*hr = Initialize();
}
CMMSGraph::~CMMSGraph()
{
m_bReconnecting = false;
SAFE_RELEASE(m_pSink);
SAFE_RELEASE(m_pTVConfig);
Uninitialize();
if(m_pMMSInfo)
{
delete m_pMMSInfo;
m_pMMSInfo = NULL;
}
}
STDMETHODIMP CMMSGraph::Run()
{
if(m_pMC)
return m_pMC->Run();
return E_FAIL;
}
STDMETHODIMP CMMSGraph::Stop()
{
if(m_pMC)
return m_pMC->Stop();
return E_FAIL;
}
STDMETHODIMP CMMSGraph::Pause()
{
if(m_pMC)
return m_pMC->Pause();
return E_FAIL;
}
STDMETHODIMP CMMSGraph::Uninitialize()
{
RemoveGraphFromRot(g_dwRegister);
DisassembleGraph();
// release all objects
SAFE_RELEASE(m_pGB);
SAFE_RELEASE(m_pMC);
// release COM lib
CoUninitialize();
return S_OK;
}
STDMETHODIMP CMMSGraph::BuildGraph(bool bAssumeAudioFirst)
{
// add/config source filter
if(FAILED(CreateAddFilter(CLSID_NetShowSource, &m_pMMSSource)))
{
AfxMessageBox("can not create & add mms source filter!");
return E_FAIL;
}
IFileSourceFilter *pSF;
if(FAILED(m_pMMSSource->QueryInterface(IID_IFileSourceFilter, (VOID**)&pSF)))
{
AfxMessageBox("can not query interface of mms source filter!");
return E_FAIL;
}
WCHAR wstrAddr[1024];
MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED | MB_USEGLYPHCHARS,
m_pMMSInfo->strMMSAddr.data(),
-1,
wstrAddr,
sizeof(wstrAddr) / sizeof(WCHAR));
HRESULT hr;
hr = pSF->Load(wstrAddr, NULL);
if(FAILED(hr))
{
string strError;
char s[100];
wsprintf(s, "无法读取mms流:%s,请检查这个流是否可用。", m_pMMSInfo->strMMSAddr.data());
strError.append(s);
//AfxMessageBox(strError.data());
return FALSE;
}
pSF->Release();
/*
IEnumPins* enumPin = NULL;
hr = m_pMMSSource->EnumPins(&enumPin);
IPin* pins = NULL
hr = enumPin->Next(1, &pins, NULL);
AM_MEDIA_TYPE type;
hr = pins->ConnectionMediaType(&type);
if(type.formattype == FORMAT_VideoInfo) {
pins->ConnectedTo(
}
*/
if(m_pSink == NULL) {
// add our sink filter
if(FAILED(CreateAddFilter(CLSID_TVStreamSink, &m_pSink)))
{
AfxMessageBox("can not create & add capture filter!");
return E_FAIL;
}
if(FAILED(m_pSink->QueryInterface(IID_ITVSouceConfig, (VOID**)&m_pTVConfig)))
{
AfxMessageBox("can not query interface of captureserver!");
return E_FAIL;
}
}
else {
// No filter name specified, cannot convert
// try to add it to the filter graph
hr = m_pGB->AddFilter(m_pSink, NULL);
if(hr != S_OK)
{
AfxMessageBox("can not add capture filter!");
return E_FAIL;
}
}
// connect graph
// audio channel
BOOL bHasAudio = TRUE;
BOOL bHasVideo = TRUE;
if(SUCCEEDED(FindASFHandler("ASF ACM Handler")))
{
VERIFY(SUCCEEDED(m_pGB->AddFilter(m_pAsfAcmHandler, NULL)));
hr = ConnectPins(m_pMMSSource, bAssumeAudioFirst?__T("Stream 1"):__T("Stream 2"), m_pAsfAcmHandler,NULL);
if(hr != S_OK) {
DisassembleGraph();
hr = BuildGraph(false);
return hr;
}
hr = ConnectPins(m_pAsfAcmHandler, NULL, m_pSink, __T("Audio"));
if(hr != S_OK) {
ASSERT(0);
bHasAudio = FALSE;
RemoveFilter(m_pAsfAcmHandler);
SAFE_RELEASE(m_pAsfAcmHandler);
}
/*
if((FAILED(ConnectPins(m_pMMSSource, __T("Stream 1"), m_pAsfAcmHandler,NULL) &&
FAILED(ConnectPins(m_pMMSSource, __T("Stream 2"), m_pAsfAcmHandler,NULL)) ||
FAILED(ConnectPins(m_pAsfAcmHandler, NULL, m_pSink, __T("Audio"))))))
{
ASSERT(0);
bHasAudio = FALSE;
RemoveFilter(m_pAsfAcmHandler);
SAFE_RELEASE(m_pAsfAcmHandler);
}
*/
}
else
bHasAudio = FALSE;
// video channel
if(SUCCEEDED(FindASFHandler("ASF ICM Handler")))
{
VERIFY(SUCCEEDED(m_pGB->AddFilter(m_pAsfIcmHandler, NULL)));
hr = ConnectPins(m_pMMSSource, bAssumeAudioFirst?__T("Stream 2"):__T("Stream 1"), m_pAsfIcmHandler,NULL);
if(hr != S_OK) {
DisassembleGraph();
hr = BuildGraph(false);
return hr;
}
hr = ConnectPins(m_pAsfIcmHandler, NULL, m_pSink, __T("Video"));
if(hr != S_OK) {
ASSERT(0);
bHasVideo = FALSE;
RemoveFilter(m_pAsfIcmHandler);
SAFE_RELEASE(m_pAsfIcmHandler);
}
/*
if((FAILED(ConnectPins(m_pMMSSource, __T("Stream 2"), m_pAsfIcmHandler,NULL) &&
FAILED(ConnectPins(m_pMMSSource, __T("Stream 1"), m_pAsfIcmHandler,NULL)) ||
FAILED(ConnectPins(m_pAsfIcmHandler, NULL, m_pSink, __T("Video"))))))
{
ASSERT(0);
bHasVideo = FALSE;
RemoveFilter(m_pAsfIcmHandler);
SAFE_RELEASE(m_pAsfIcmHandler);
}
*/
#ifdef TIME_EXPIRE
/// 如果过了2006-03-21日,就返回错误
tm expire_tm;
memset(&expire_tm, 0, sizeof(expire_tm));
expire_tm.tm_year = 106;
expire_tm.tm_mon = 2;
expire_tm.tm_mday = 21;
time_t expire_seconds = mktime(&expire_tm);
time_t now;
time( &now ); /* Get time as long integer. */
if(now > expire_seconds)
return E_FAIL;
#endif
}
else
bHasVideo = FALSE;
if(!bHasVideo && !bHasAudio)
{
AfxMessageBox("Sorry, MMS Server cant get media. plz check mms address is right!");
return E_FAIL;
}
if(!bHasVideo)
{
// AfxMessageBox("warning:no video captured!");
//return S_FALSE;
m_pTVConfig->SetAudioOrVideoOnly(TRUE); // set audio only
}
if(!bHasAudio)
{
AfxMessageBox("warning:no audio captured!");
return S_FALSE;
}
return 1 ;
}
STDMETHODIMP CMMSGraph::DisassembleGraph()
{
Stop();
// remove all filters from graph
RemoveFilter(m_pMMSSource);
RemoveFilter(m_pSink);
if(m_pAsfAcmHandler)
RemoveFilter(m_pAsfAcmHandler);
if(m_pAsfAcmHandler)
RemoveFilter(m_pAsfIcmHandler);
if(m_pAudioSmartTee)
RemoveFilter(m_pAudioSmartTee);
SAFE_RELEASE(m_pMMSSource);
SAFE_RELEASE(m_pAsfIcmHandler);
SAFE_RELEASE(m_pAsfAcmHandler);
SAFE_RELEASE(m_pAudioSmartTee);
return S_OK;
}
MMSGRAPHINFO *CMMSGraph::GetMMSGraphInfo()
{
////////////Get the value of the ResStartTime
CString str_path;
GetModuleFileName(NULL,str_path.GetBuffer(MAX_PATH),MAX_PATH);
str_path.ReleaseBuffer();
int index = str_path.ReverseFind('\\');
str_path= str_path.Left(index+1);
int ResStartTime = 10;
static bool reconnecting = false;
// speed
m_pMMSInfo->fDataRate = m_pTVConfig->GetCompressedSpeed();
m_pMMSInfo->fTotalBytes=m_pTVConfig->GetTotalBytes(); //get current totalbytes
if(m_pMMSInfo->fTotalBytes>m_pMMSInfo->m_oldtotalbyte) //if we got new data
{
if (m_pMMSInfo->mmsState==RUNNING)
m_pMMSInfo->llTimeEscaped++;
m_pMMSInfo->m_time=0; //recount
}
else if(m_pMMSInfo->mmsState != STOPPED )//if data stopped
{
m_pMMSInfo->m_time++;
if(m_pTVConfig->EndOfStream() || m_pMMSInfo->m_time >= ResStartTime) {
if(!m_bReconnecting) {
m_bReconnecting = true;
HRESULT ret = this->DisassembleGraph();
ret = this->BuildGraph();
ret = this->Run();
m_bReconnecting = false;
}
m_pMMSInfo->m_time=0; //recount
}
}
if (m_pMMSInfo->m_time==0)
m_pMMSInfo->m_oldtotalbyte=m_pMMSInfo->fTotalBytes;
// state
OAFilterState os;
m_pMC->GetState(100, &os);
if(os == State_Running)
m_pMMSInfo->mmsState = RUNNING;
else if(os == State_Stopped) {
m_pMMSInfo->mmsState = STOPPED;
if(m_bReconnecting)
m_pMMSInfo->mmsState = RECONNECTING;
}
else if(os == State_Paused)
m_pMMSInfo->mmsState = PAUSED;
else
m_pMMSInfo->mmsState = INIT;
// time escaped
return m_pMMSInfo;
}
STDMETHODIMP CMMSGraph::CreateAddFilter(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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -