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

📄 tvstreamsink.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 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));
}

⌨️ 快捷键说明

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