📄 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));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -