www.pudn.com > mysee.zip > TVStreamSink.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 "uuids.h" 
#include "TVstreamsink.h" 
#include "TVstreamsinkpins.h" 
#include "CaptureServer.h" 
 
// filter info 
const AMOVIESETUP_MEDIATYPE sudPinTypes = 
{ 
    &MEDIATYPE_NULL,            // Major type 
    &MEDIASUBTYPE_NULL          // Minor type 
}; 
 
const AMOVIESETUP_PIN sudPins = 
{ 
    L"Input",                   // Pin string name 
    FALSE,                      // Is it rendered 
    FALSE,                      // Is it an output 
    FALSE,                      // Allowed none 
    FALSE,                      // Likewise many 
    &CLSID_NULL,                // Connects to filter 
    NULL,                       // Connects to pin 
    1,                          // Number of types 
    &sudPinTypes                // Pin information 
}; 
 
const AMOVIESETUP_FILTER sudTVStreamSink = 
{ 
    &CLSID_TVStreamSink,       // clsID 
    L"TV Stream Sink(fix mms)",// strName 
    MERIT_DO_NOT_USE,          // dwMerit 
    1,                         // nPins 
    &sudPins                   // lpPin 
}; 
 
// class factory info 
CFactoryTemplate g_Templates[]=  
{ 
    {L"TV Stream Sink(fix mms)", &CLSID_TVStreamSink, CTVStreamSink::CreateInstance, NULL, &sudTVStreamSink}, 
}; 
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); 
 
////////////////////////////////////////////////////////////////////////////// 
///////// 
CCritSec CTVStreamSink::m_Lock; 
 
CTVStreamSink::CTVStreamSink(LPUNKNOWN pUnk, CCritSec *pLock, HRESULT *phr) :  
	CBaseFilter(NAME("TVStreamSink filter"), pUnk, pLock, CLSID_TVStreamSink),  
	m_pFileName(0), m_pVideoPin(0), m_pAudioPin(0) { 
 
	if(!cs.Init()) { 
		*phr = E_OUTOFMEMORY; 
		return; 
	} 
 
	m_pVideoPin = new CTVStreamSinkInputPin(this, 
									   &m_Lock, 
									   phr, 
									   L"Video",  
									   FALSE); 
    if (m_pVideoPin == NULL)  
	{ 
        *phr = E_OUTOFMEMORY; 
        return; 
    } 
 
	m_pAudioPin = new CTVStreamSinkInputPin(this, 
									   &m_Lock, 
									   phr, 
									   L"Audio",  
									   TRUE); 
    if (m_pAudioPin == NULL)  
	{ 
        *phr = E_OUTOFMEMORY; 
        return; 
    } 
 
	m_iIsStop = 0; 
	m_iState = 1;//0为运行,1为停止。-1为发生意外错误停止 
	TRACE1("CTVStreamSink::CTVStreamSink因为bytethesamecounter非正常退出\n"); 
	*phr = S_OK; 
} 
 
CTVStreamSink::~CTVStreamSink() 
{ 
	m_iIsStop = 0; 
	SAFE_ARRAYDELETE(m_pFileName); 
	 
    SAFE_DELETE(m_pVideoPin); 
	SAFE_DELETE(m_pAudioPin); 
} 
 
CUnknown * WINAPI CTVStreamSink::CreateInstance(LPUNKNOWN pUnk, HRESULT * phr) 
{    
	CTVStreamSink* pSink = new CTVStreamSink(pUnk, &m_Lock, phr); 
	if(pSink == NULL) 
		*phr = E_OUTOFMEMORY; 
	 
	pSink->CreateDebugInfo(); 
	//TraceLog1("begin\n"); 
	return pSink; 
} 
 
int CTVStreamSink::GetPinCount() 
{ 
	return 2; 
} 
 
CBasePin* CTVStreamSink::GetPin(int n) 
{ 
	if(n == 0) // sink only support one input pin 
        return m_pVideoPin; 
	else if(n == 1) 
		return m_pAudioPin; 
	else 
        return NULL; 
} 
 
STDMETHODIMP CTVStreamSink::NonDelegatingQueryInterface(REFIID riid, void ** ppv) 
{ 
	CheckPointer(ppv,E_POINTER); 
    CAutoLock lock(&m_Lock); 
 
    // Do we have this interface 
    if (riid == IID_IFileSinkFilter)  
        return GetInterface((IFileSinkFilter *) this, ppv); 
	else if(IID_ITVSouceConfig == riid) 
		return GetInterface((ITVSourceConfig *) this, ppv); 
	else 
		return CBaseFilter::NonDelegatingQueryInterface(riid, ppv); 
} 
 
STDMETHODIMP CTVStreamSink::Run(REFERENCE_TIME tStart) 
{ 
	HRESULT hr; 
	CAutoLock cObjectLock(m_pLock); 
 
	CAutoLock lolock(&m_Lock); 
 
	hr = CBaseFilter::Run(tStart); 
	if(SUCCEEDED(hr)) 
	{ 
		m_iIsStop = 0; 
		TRACE1("CTVStreamSink::Run开始运行\n"); 
		m_iState = 0;//0为运行,1为停止。-1为发生意外错误停止 
		BOOL ii = m_pVideoPin->IsConnected(); 
		ii = m_pAudioPin->IsConnected(); 
		if (FALSE == cs.m_bIsOnlyOnePin && (FALSE == m_pVideoPin->IsConnected()  
			||FALSE == m_pAudioPin->IsConnected())) 
		{ 
			//MessageBox(NULL, "很抱歉,配置错误,此时是您转化的是单音频","错误", MB_OK|MB_ICONSTOP); 
			TraceLog1("很抱歉,配置错误,此时是您转化的是单音频"); 
			return E_FAIL; 
		} 
	} 
    return hr; 
} 
 
 
//创建调试信息日志 
bool CTVStreamSink::CreateDebugInfo() 
{ 
    char strPath[255]; 
	char strLogFileName[255]; 
	 
	//首先设置日志打印选项 
	CDebugTrace::SetTraceLevel(6); 
	 
	CDebugTrace::SetTraceOptions(CDebugTrace::GetTraceOptions() \ 
		| CDebugTrace::Timestamp & ~CDebugTrace::LogLevel \ 
		& ~CDebugTrace::FileAndLine | CDebugTrace::AppendToFile\ 
		& ~CDebugTrace::PrintToConsole); 
	 
	if (!GetModuleFileName(NULL,strPath, 255)) 
	{ 
		TRACE1("CMediaCenter::CreateDebugInfo:GetModuleFileName()函数返回失败!\n"); 
		return false; 
	} 
	 
	//从strPath中去掉文件名,从而取得可执行文件的路径; 
	int nPosition = 0; 
	nPosition = (int)(strrchr(strPath,'\\') - strPath); 
	strPath[nPosition+1] = '\0'; 
	 
	//生成日志目录 
	strcat(strPath, "日志文件\\");	 
	if(TRUE != CreateDirectory(strPath, NULL)) 
	{ 
		int i = GetLastError(); 
		if (ERROR_ACCESS_DENIED != i && ERROR_ALREADY_EXISTS != i) 
		{ 
			MessageBox(NULL, "创建文件夹失败", "错误", MB_OK|MB_ICONSTOP); 
		} 
	} 
 
	//生成TRACE文件名 
	SYSTEMTIME loSystemTime; 
	GetLocalTime(&loSystemTime); 
	 
	sprintf(strLogFileName, "%sGetZZLDisplay%4d%02d%02d%s", strPath,loSystemTime.wYear,\ 
		loSystemTime.wMonth,loSystemTime.wDay,".log"); 
	//sprintf(strLogFileName, "%sUTMedia%4d%02d%02d%s", strPath,loSystemTime.wYear,\ 
	//	loSystemTime.wMonth,loSystemTime.wDay,".log"); 
	//strcat(strPath, "GetZZLDisplay.log"); 
	CDebugTrace::SetLogFileName(strLogFileName);		 
	return true; 
} 
 
STDMETHODIMP CTVStreamSink::Pause() 
{ 
	CAutoLock cObjectLock(m_pLock); 
	 
    return CBaseFilter::Pause(); 
} 
 
STDMETHODIMP CTVStreamSink::Stop() 
{ 
	CAutoLock cObjectLock(m_pLock); 
	m_iState = -1;//0为运行,1为停止(全部文件转化完成为停止)。-1为发生意外错误停止(用户点击Stop为意外停止) 
	//cs.Stop(); 
	TRACE5("CTVStreamSink::Stop非正常退出m_iState = -1\n"); 
 
    return CBaseFilter::Stop(); 
} 
 
STDMETHODIMP CTVStreamSink::SetFileName(LPCOLESTR pszFileName,const AM_MEDIA_TYPE *pmt) 
{ 
	// Is this a valid filename supplied 
    CheckPointer(pszFileName,E_POINTER); 
 
	if(wcslen(pszFileName) > MAX_PATH) 
        return ERROR_FILENAME_EXCED_RANGE; 
 
    // Take a copy of the filename 
    m_pFileName = new WCHAR[1+lstrlenW(pszFileName)]; 
    if (m_pFileName == 0) 
        return E_OUTOFMEMORY; 
 
    wcscpy(m_pFileName,pszFileName); 
	 
	return S_OK; 
} 
 
STDMETHODIMP CTVStreamSink::GetCurFile(LPOLESTR * ppszFileName,AM_MEDIA_TYPE *pmt) 
{ 
	CheckPointer(ppszFileName, E_POINTER); 
 
	*ppszFileName = NULL; 
 
    if (m_pFileName != NULL)  
    { 
        *ppszFileName = (LPOLESTR) 
        QzTaskMemAlloc(sizeof(WCHAR) * (1+lstrlenW(m_pFileName))); 
 
        if (*ppszFileName != NULL)  
        { 
            wcscpy(*ppszFileName, m_pFileName); 
        } 
    } 
 
    if(pmt)  
    { 
        ZeroMemory(pmt, sizeof(*pmt)); 
        pmt->majortype = MEDIATYPE_NULL; 
        pmt->subtype = MEDIASUBTYPE_NULL; 
    } 
	 
    return S_OK; 
} 
 
HRESULT CTVStreamSink::WriteFormatTypeHeader(CMediaType *pmt, BOOL isAudio) 
{ 
    CAutoLock lock(&m_Lock); 
 
    if(isAudio) { 
        if(pmt->formattype != FORMAT_WaveFormatEx) { 
            return E_FAIL; 
        } 
    } 
    else { 
        if(pmt->formattype != FORMAT_VideoInfo && pmt->formattype != FORMAT_MPEGVideo) { 
            return E_FAIL; 
        } 
    } 
 
	 
	//ISampleSize: 如果这个字段非零,表示这是每个sample的尺寸, 
	//             如果是零,则表示sample的尺寸会改变。 
    //bFixdSizeSamples: 如果这个布尔类型的标记是TRUE,表示ISampleSize有效, 
	//                  否则,你可以忽略ISampleSize。 
	//bTemporalCompression: 如果这个布尔类型的标记是FALSE,表示所有帧都是关键帧。 
 
	TVMEDIATYPESECTION tms; 
	memset(&tms, 0, sizeof(tms)); 
	tms.majortype = pmt->majortype; 
	tms.subtype = pmt->subtype; 
	tms.formattype = pmt->formattype; 
	tms.lSampleSize = pmt->lSampleSize; 
	tms.bFixedSizeSamples = pmt->bFixedSizeSamples; 
	tms.bTemporalCompression = pmt->bTemporalCompression; 
	tms.bThisPinOnly = false; 
	tms.cbFormat = pmt->cbFormat; 
 
	/* 
	if(isAudio) { 
		DeleteFile("c:\\audio.xxx"); 
		char temp[64]; 
		sprintf(temp, "cbFormat: %d. \r\n", pmt->cbFormat); 
		HANDLE hFile = CreateFile("c:\\audio.xxx", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
		if(hFile == INVALID_HANDLE_VALUE) { 
			MessageBox(0, "c:\\audio.xxx", _T("无法写入GTV文件"), MB_OK|MB_ICONERROR); 
			return VFW_E_CANNOT_RENDER; 
		} 
		DWORD TTT = 0; 
		if(!WriteFile(hFile, temp, strlen(temp), &TTT, NULL) || TTT == 0) { 
			MessageBox(0, "c:\\audio.xxx", _T("无法写入GTV文件"), MB_OK|MB_ICONERROR); 
			return VFW_E_CANNOT_RENDER; 
		} 
		TTT = 0; 
		if(!WriteFile(hFile, pmt->pbFormat, pmt->cbFormat, &TTT, NULL) || TTT == 0) { 
			MessageBox(0, "c:\\audio.xxx", _T("无法写入GTV文件"), MB_OK|MB_ICONERROR); 
			return VFW_E_CANNOT_RENDER; 
		} 
		CloseHandle(hFile); 
	} 
	*/ 
 
	BOOL bRet = cs.SetFormatData(tms, pmt->pbFormat, isAudio); 
	return (TRUE == bRet) ? S_OK : S_FALSE; 
} 
 
 
STDMETHODIMP_(float) CTVStreamSink::GetCompressedSpeed() 
{ 
	return cs.GetSpeedInKBPS(); 
} 
 
STDMETHODIMP_(BOOL) CTVStreamSink::Login(int userID, char* pass) { 
	if(!pass) 
		return FALSE; 
 
	cs.cfgData.userID = userID; 
	cs.cfgData.password = pass; 
	cs.cfgData.canLogin = TRUE; 
	 
	return TRUE; 
} 
 
STDMETHODIMP_(int) CTVStreamSink::CheckPassword() 
{ 
	return cs.passwordStatus; 
} 
 
 
STDMETHODIMP_(LONGLONG) CTVStreamSink::GetTotalBytes() 
{ 
    return cs.GetTotalBytes(); 
} 
 
STDMETHODIMP_(void) CTVStreamSink::SetAudioOrVideoOnly(BOOL isAudio) 
{ 
	cs.SetAudioOrVideoOnly(isAudio); 
} 
 
STDMETHODIMP_(void) CTVStreamSink::SetParentWindow(HWND handle) 
{ 
	cs.parentWindow = handle; 
} 
 
STDMETHODIMP_(void) CTVStreamSink::SetProgramStorePath(LPCTSTR path) 
{ 
	if(path) 
		cs.cfgData.savePath = path; 
} 
 
STDMETHODIMP_(void) CTVStreamSink::SetChannelName(LPCTSTR astrChannelName) 
{ 
	if (astrChannelName) 
	{ 
		cs.cfgData.chnlStr = astrChannelName; 
	} 
} 
 
STDMETHODIMP_(void) CTVStreamSink::GetZZLState(int* apiState) 
{ 
	 *apiState = m_iState; 
} 
 
STDMETHODIMP_(bool) CTVStreamSink::EndOfStream() 
{ 
	return (cs.m_bIsOnlyOnePin? (m_iIsStop >= 1):(m_iIsStop >= 2)); 
}