/*
* $Id$
*
* (C) 2003-2006 Gabest
* (C) 2006-2012 see Authors.txt
*
* This file is part of MPC-HC.
*
* MPC-HC 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 3 of the License, or
* (at your option) any later version.
*
* MPC-HC 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, see .
*
*/
#include "stdafx.h"
#include
#include
#include "MpaSplitter.h"
#include
#ifdef REGISTER_FILTER
const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] = {
{&MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Audio},
{&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL}
};
const AMOVIESETUP_PIN sudpPins[] = {
{L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
{L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
};
const AMOVIESETUP_FILTER sudFilter[] = {
{&__uuidof(CMpaSplitterFilter), MpaSplitterName, MERIT_NORMAL+1, countof(sudpPins), sudpPins, CLSID_LegacyAmFilterCategory},
{&__uuidof(CMpaSourceFilter), MpaSourceName, MERIT_NORMAL+1, 0, NULL, CLSID_LegacyAmFilterCategory},
};
CFactoryTemplate g_Templates[] = {
{sudFilter[0].strName, sudFilter[0].clsID, CreateInstance, NULL, &sudFilter[0]},
{sudFilter[1].strName, sudFilter[1].clsID, CreateInstance, NULL, &sudFilter[1]},
};
int g_cTemplates = countof(g_Templates);
STDAPI DllRegisterServer()
{
CAtlList chkbytes;
chkbytes.AddTail(_T("0,2,FFE0,FFE0"));
chkbytes.AddTail(_T("0,10,FFFFFF00000080808080,49443300000000000000"));
RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_MPEG1Audio, chkbytes, NULL);
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
#include "../../FilterApp.h"
CFilterApp theApp;
#endif
//
// CMpaSplitterFilter
//
CMpaSplitterFilter::CMpaSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
: CBaseSplitterFilter(NAME("CMpaSplitterFilter"), pUnk, phr, __uuidof(this))
{
}
STDMETHODIMP CMpaSplitterFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
{
CheckPointer(ppv, E_POINTER);
return
__super::NonDelegatingQueryInterface(riid, ppv);
}
STDMETHODIMP CMpaSplitterFilter::QueryFilterInfo(FILTER_INFO* pInfo)
{
CheckPointer(pInfo, E_POINTER);
ValidateReadWritePtr(pInfo, sizeof(FILTER_INFO));
if (m_pName && m_pName[0]==L'M' && m_pName[1]==L'P' && m_pName[2]==L'C') {
(void)StringCchCopyW(pInfo->achName, NUMELMS(pInfo->achName), m_pName);
} else {
wcscpy(pInfo->achName, MpaSourceName);
}
pInfo->pGraph = m_pGraph;
if (m_pGraph) {
m_pGraph->AddRef();
}
return S_OK;
}
HRESULT CMpaSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
{
CheckPointer(pAsyncReader, E_POINTER);
HRESULT hr = E_FAIL;
m_pFile.Free();
m_pFile.Attach(DNew CMpaSplitterFile(pAsyncReader, hr));
if (!m_pFile) {
return E_OUTOFMEMORY;
}
if (FAILED(hr)) {
m_pFile.Free();
return hr;
}
CAtlArray mts;
mts.Add(m_pFile->GetMediaType());
CAutoPtr pPinOut(DNew CBaseSplitterOutputPin(mts, L"Audio", this, this, &hr));
AddOutputPin(0, pPinOut);
m_rtNewStart = m_rtCurrent = 0;
m_rtNewStop = m_rtStop = m_rtDuration = m_pFile->GetDuration();
CStringW str, title;
if (m_pFile->m_tags.Lookup('TIT2', str)) {
title = str;
}
if (m_pFile->m_tags.Lookup('TYER', str) && !title.IsEmpty() && !str.IsEmpty()) {
title += L" (" + str + L")";
}
if (!title.IsEmpty()) {
SetProperty(L"TITL", title);
}
if (m_pFile->m_tags.Lookup('TPE1', str)) {
SetProperty(L"AUTH", str);
}
if (m_pFile->m_tags.Lookup('TCOP', str)) {
SetProperty(L"CPYR", str);
}
if (m_pFile->m_tags.Lookup('COMM', str)) {
SetProperty(L"DESC", str);
}
return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
}
STDMETHODIMP CMpaSplitterFilter::GetDuration(LONGLONG* pDuration)
{
CheckPointer(pDuration, E_POINTER);
CheckPointer(m_pFile, VFW_E_NOT_CONNECTED);
*pDuration = m_pFile->GetDuration();
return S_OK;
}
bool CMpaSplitterFilter::DemuxInit()
{
SetThreadName((DWORD)-1, "CMpaSplitterFilter");
if (!m_pFile) {
return false;
}
// TODO
return true;
}
void CMpaSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
{
__int64 startpos = m_pFile->GetStartPos();
__int64 endpos = m_pFile->GetEndPos();
if (rt <= 0 || m_pFile->GetDuration() <= 0) {
m_pFile->Seek(startpos);
m_rtStart = 0;
} else {
m_pFile->Seek(startpos + (__int64)((1.0 * rt / m_pFile->GetDuration()) * (endpos - startpos)));
m_rtStart = rt;
}
}
bool CMpaSplitterFilter::DemuxLoop()
{
HRESULT hr = S_OK;
int FrameSize;
REFERENCE_TIME rtDuration;
while (SUCCEEDED(hr) && !CheckRequest(NULL) && m_pFile->GetPos() < m_pFile->GetEndPos() - 9) {
if (!m_pFile->Sync(FrameSize, rtDuration)) {
Sleep(1);
continue;
}
CAutoPtr p(DNew Packet());
p->SetCount(FrameSize);
m_pFile->ByteRead(p->GetData(), FrameSize);
p->TrackNumber = 0;
p->rtStart = m_rtStart;
p->rtStop = m_rtStart + rtDuration;
p->bSyncPoint = TRUE;
hr = DeliverPacket(p);
m_rtStart += rtDuration;
}
return true;
}
//
// CMpaSourceFilter
//
CMpaSourceFilter::CMpaSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
: CMpaSplitterFilter(pUnk, phr)
{
m_clsid = __uuidof(this);
m_pInput.Free();
}