MatroskaMuxer.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:38k
- /*
- * Copyright (C) 2003-2005 Gabest
- * http://www.gabest.org
- *
- * 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, 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 GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- */
- #include "StdAfx.h"
- #include <mmreg.h>
- #include "MatroskaMuxer.h"
- #include "......DSUtilDSUtil.h"
- #include <initguid.h>
- #include "........includematroskamatroska.h"
- #include "........includeoggOggDS.h"
- #include "........includemoreuuids.h"
- using namespace MatroskaWriter;
- #ifdef REGISTER_FILTER
- const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
- {
- {&MEDIATYPE_Stream, &MEDIASUBTYPE_Matroska}
- };
- const AMOVIESETUP_PIN sudpPins[] =
- {
- {L"Input", FALSE, FALSE, FALSE, TRUE, &CLSID_NULL, NULL, 0, NULL},
- {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
- };
- const AMOVIESETUP_FILTER sudFilter[] =
- {
- {&__uuidof(CMatroskaMuxerFilter), L"Matroska Muxer", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
- };
- CFactoryTemplate g_Templates[] =
- {
- {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CMatroskaMuxerFilter>, NULL, &sudFilter[0]}
- };
- int g_cTemplates = countof(g_Templates);
- STDAPI DllRegisterServer()
- {
- return AMovieDllRegisterServer2(TRUE);
- }
- STDAPI DllUnregisterServer()
- {
- return AMovieDllRegisterServer2(FALSE);
- }
- extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
- BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
- {
- return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
- }
- #endif
- //
- // CMatroskaMuxerFilter
- //
- CMatroskaMuxerFilter::CMatroskaMuxerFilter(LPUNKNOWN pUnk, HRESULT* phr)
- : CBaseFilter(NAME("CMatroskaMuxerFilter"), pUnk, this, __uuidof(this))
- , m_rtCurrent(0)
- , m_fNegative(true), m_fPositive(false)
- {
- if(phr) *phr = S_OK;
- m_pOutput.Attach(new CMatroskaMuxerOutputPin(NAME("CMatroskaMuxerOutputPin"), this, this, phr));
- AddInput();
- srand(clock());
- }
- CMatroskaMuxerFilter::~CMatroskaMuxerFilter()
- {
- CAutoLock cAutoLock(this);
- }
- STDMETHODIMP CMatroskaMuxerFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
- {
- CheckPointer(ppv, E_POINTER);
- *ppv = NULL;
- return
- // QI(IAMFilterMiscFlags)
- QI(IMediaSeeking)
- QI(IMatroskaMuxer)
- __super::NonDelegatingQueryInterface(riid, ppv);
- }
- UINT CMatroskaMuxerFilter::GetTrackNumber(CBasePin* pPin)
- {
- UINT nTrackNumber = 0;
- POSITION pos = m_pInputs.GetHeadPosition();
- while(pos)
- {
- nTrackNumber++;
- if(m_pInputs.GetNext(pos) == pPin)
- return nTrackNumber;
- }
- return 0;
- }
- void CMatroskaMuxerFilter::AddInput()
- {
- POSITION pos = m_pInputs.GetHeadPosition();
- while(pos)
- {
- CBasePin* pPin = m_pInputs.GetNext(pos);
- if(!pPin->IsConnected()) return;
- }
- CStringW name;
- name.Format(L"Track %d", m_pInputs.GetCount()+1);
-
- HRESULT hr;
- CAutoPtr<CMatroskaMuxerInputPin> pPin(new CMatroskaMuxerInputPin(name, this, this, &hr));
- m_pInputs.AddTail(pPin);
- }
- int CMatroskaMuxerFilter::GetPinCount()
- {
- return m_pInputs.GetCount() + (m_pOutput ? 1 : 0);
- }
- CBasePin* CMatroskaMuxerFilter::GetPin(int n)
- {
- CAutoLock cAutoLock(this);
- if(n >= 0 && n < (int)m_pInputs.GetCount())
- {
- if(POSITION pos = m_pInputs.FindIndex(n))
- return m_pInputs.GetAt(pos);
- }
- if(n == m_pInputs.GetCount() && m_pOutput)
- {
- return m_pOutput;
- }
- return NULL;
- }
- STDMETHODIMP CMatroskaMuxerFilter::Stop()
- {
- CAutoLock cAutoLock(this);
- HRESULT hr;
-
- if(FAILED(hr = __super::Stop()))
- return hr;
- CallWorker(CMD_EXIT);
- return hr;
- }
- STDMETHODIMP CMatroskaMuxerFilter::Pause()
- {
- CAutoLock cAutoLock(this);
- FILTER_STATE fs = m_State;
- HRESULT hr;
- if(FAILED(hr = __super::Pause()))
- return hr;
- if(fs == State_Stopped && m_pOutput)
- {
- CAMThread::Create();
- CallWorker(CMD_RUN);
- }
- return hr;
- }
- STDMETHODIMP CMatroskaMuxerFilter::Run(REFERENCE_TIME tStart)
- {
- CAutoLock cAutoLock(this);
- HRESULT hr;
- if(FAILED(hr = __super::Run(tStart)))
- return hr;
- return hr;
- }
- // IAMFilterMiscFlags
- STDMETHODIMP_(ULONG) CMatroskaMuxerFilter::GetMiscFlags()
- {
- return AM_FILTER_MISC_FLAGS_IS_RENDERER;
- }
- // IMediaSeeking
- STDMETHODIMP CMatroskaMuxerFilter::GetCapabilities(DWORD* pCapabilities)
- {
- return pCapabilities ? *pCapabilities =
- AM_SEEKING_CanGetDuration|
- AM_SEEKING_CanGetCurrentPos, S_OK : E_POINTER;
- }
- STDMETHODIMP CMatroskaMuxerFilter::CheckCapabilities(DWORD* pCapabilities)
- {
- CheckPointer(pCapabilities, E_POINTER);
- if(*pCapabilities == 0) return S_OK;
- DWORD caps;
- GetCapabilities(&caps);
- caps &= *pCapabilities;
- return caps == 0 ? E_FAIL : caps == *pCapabilities ? S_OK : S_FALSE;
- }
- STDMETHODIMP CMatroskaMuxerFilter::IsFormatSupported(const GUID* pFormat) {return !pFormat ? E_POINTER : *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;}
- STDMETHODIMP CMatroskaMuxerFilter::QueryPreferredFormat(GUID* pFormat) {return GetTimeFormat(pFormat);}
- STDMETHODIMP CMatroskaMuxerFilter::GetTimeFormat(GUID* pFormat) {return pFormat ? *pFormat = TIME_FORMAT_MEDIA_TIME, S_OK : E_POINTER;}
- STDMETHODIMP CMatroskaMuxerFilter::IsUsingTimeFormat(const GUID* pFormat) {return IsFormatSupported(pFormat);}
- STDMETHODIMP CMatroskaMuxerFilter::SetTimeFormat(const GUID* pFormat) {return S_OK == IsFormatSupported(pFormat) ? S_OK : E_INVALIDARG;}
- STDMETHODIMP CMatroskaMuxerFilter::GetDuration(LONGLONG* pDuration)
- {
- CheckPointer(pDuration, E_POINTER);
- *pDuration = 0;
- POSITION pos = m_pInputs.GetHeadPosition();
- while(pos) {REFERENCE_TIME rt = m_pInputs.GetNext(pos)->m_rtDur; if(rt > *pDuration) *pDuration = rt;}
- return S_OK;
- }
- STDMETHODIMP CMatroskaMuxerFilter::GetStopPosition(LONGLONG* pStop) {return E_NOTIMPL;}
- STDMETHODIMP CMatroskaMuxerFilter::GetCurrentPosition(LONGLONG* pCurrent)
- {
- CheckPointer(pCurrent, E_POINTER);
- *pCurrent = m_rtCurrent;
- return S_OK;
- }
- STDMETHODIMP CMatroskaMuxerFilter::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat) {return E_NOTIMPL;}
- STDMETHODIMP CMatroskaMuxerFilter::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags) {return E_NOTIMPL;}
- STDMETHODIMP CMatroskaMuxerFilter::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop) {return E_NOTIMPL;}
- STDMETHODIMP CMatroskaMuxerFilter::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest) {return E_NOTIMPL;}
- STDMETHODIMP CMatroskaMuxerFilter::SetRate(double dRate) {return E_NOTIMPL;}
- STDMETHODIMP CMatroskaMuxerFilter::GetRate(double* pdRate) {return E_NOTIMPL;}
- STDMETHODIMP CMatroskaMuxerFilter::GetPreroll(LONGLONG* pllPreroll) {return E_NOTIMPL;}
- // IMatroskaMuxer
- STDMETHODIMP CMatroskaMuxerFilter::CorrectTimeOffset(bool fNegative, bool fPositive)
- {
- m_fNegative = fNegative;
- m_fPositive = fPositive;
- return S_OK;
- }
- //
- ULONGLONG GetStreamPosition(IStream* pStream)
- {
- ULARGE_INTEGER pos = {0, 0};
- pStream->Seek(*(LARGE_INTEGER*)&pos, STREAM_SEEK_CUR, &pos);
- return pos.QuadPart;
- }
- ULONGLONG SetStreamPosition(IStream* pStream, ULONGLONG seekpos)
- {
- LARGE_INTEGER pos;
- pos.QuadPart = seekpos;
- ULARGE_INTEGER posnew;
- posnew.QuadPart = GetStreamPosition(pStream);
- pStream->Seek(pos, STREAM_SEEK_SET, &posnew);
- return posnew.QuadPart;
- }
- DWORD CMatroskaMuxerFilter::ThreadProc()
- {
- CComQIPtr<IStream> pStream;
-
- if(!m_pOutput || !(pStream = m_pOutput->GetConnected()))
- {
- while(1)
- {
- DWORD cmd = GetRequest();
- if(cmd == CMD_EXIT) CAMThread::m_hThread = NULL;
- Reply(S_OK);
- if(cmd == CMD_EXIT) return 0;
- }
- }
- REFERENCE_TIME rtDur = 0;
- GetDuration(&rtDur);
- SetStreamPosition(pStream, 0);
- ULARGE_INTEGER uli = {0};
- pStream->SetSize(uli);
- EBML hdr;
- hdr.DocType.Set("matroska");
- hdr.DocTypeVersion.Set(1);
- hdr.DocTypeReadVersion.Set(1);
- hdr.Write(pStream);
- Segment().Write(pStream);
- ULONGLONG segpos = GetStreamPosition(pStream);
- // TODO
- QWORD voidlen = 100;
- if(rtDur > 0) voidlen += int(1.0 * rtDur / MAXCLUSTERTIME / 10000 + 0.5) * 20;
- else voidlen += int(1.0 * 1000*60*60*24 / MAXCLUSTERTIME + 0.5) * 20; // when no duration is known, allocate for 24 hours (~340k)
- ULONGLONG voidpos = GetStreamPosition(pStream);
- {
- Void v(voidlen);
- voidlen = v.Size();
- v.Write(pStream);
- }
- // Meta Seek
- Seek seek;
- CAutoPtr<SeekHead> sh;
- // Segment Info
- sh.Attach(new SeekHead());
- sh->ID.Set(0x1549A966);
- sh->Position.Set(GetStreamPosition(pStream) - segpos);
- seek.SeekHeads.AddTail(sh);
- ULONGLONG infopos = GetStreamPosition(pStream);
- Info info;
- info.MuxingApp.Set(L"DirectShow Matroska Muxer");
- info.TimeCodeScale.Set(1000000);
- info.Duration.Set((float)rtDur / 10000);
- struct tm _2001 = {0, 0, 0, 1, 0, 101, 0, 0, 1};
- info.DateUTC.Set((_time64(NULL) - _mktime64(&_2001)) * 1000000000);
- info.Write(pStream);
- // Tracks
- sh.Attach(new SeekHead());
- sh->ID.Set(0x1654AE6B);
- sh->Position.Set(GetStreamPosition(pStream) - segpos);
- seek.SeekHeads.AddTail(sh);
- UINT64 TrackNumber = 0;
- /*
- CNode<Track> Tracks;
- CAutoPtr<Track> pT(new Track());
- POSITION pos = m_pInputs.GetHeadPosition();
- for(int i = 1; pos; i++)
- {
- CMatroskaMuxerInputPin* pPin = m_pInputs.GetNext(pos);
- if(!pPin->IsConnected()) continue;
- CAutoPtr<TrackEntry> pTE(new TrackEntry());
- *pTE = *pPin->GetTrackEntry();
- if(TrackNumber == 0 && pTE->TrackType == TrackEntry::TypeVideo)
- TrackNumber = pTE->TrackNumber;
- pT->TrackEntries.AddTail(pTE);
- }
- Tracks.AddTail(pT);
- Tracks.Write(pStream);
- if(TrackNumber == 0) TrackNumber = 1;
- */
- bool fTracksWritten = false;
- //
- Cluster c;
- c.TimeCode.Set(0);
- bool fFirstBlock = true;
- INT64 firstTimeCode = 0;
- CList<CMatroskaMuxerInputPin*> pActivePins;
- POSITION pos = m_pInputs.GetHeadPosition();
- while(pos)
- {
- CMatroskaMuxerInputPin* pPin = m_pInputs.GetNext(pos);
- if(pPin->IsConnected()) pActivePins.AddTail(pPin);
- }
- while(1)
- {
- DWORD cmd = GetRequest();
- switch(cmd)
- {
- default:
- case CMD_EXIT:
- CAMThread::m_hThread = NULL;
- Reply(S_OK);
- return 0;
- case CMD_RUN:
- Reply(S_OK);
- Cue cue;
- ULONGLONG lastcueclusterpos = -1;
- INT64 lastcuetimecode = -1;
- UINT64 nBlocksInCueTrack = 0;
- while(!CheckRequest(NULL))
- {
- if(m_State == State_Paused)
- {
- Sleep(10);
- continue;
- }
- int nPinsGotSomething = 0, nPinsNeeded = 0;
- CMatroskaMuxerInputPin* pPin = NULL;
- REFERENCE_TIME rtMin = _I64_MAX;
- pos = pActivePins.GetHeadPosition();
- while(pos)
- {
- CMatroskaMuxerInputPin* pTmp = pActivePins.GetNext(pos);
- CAutoLock cAutoLock(&pTmp->m_csQueue);
- if(pTmp->m_blocks.GetCount() == 0 && pTmp->m_fEndOfStreamReceived)
- {
- pActivePins.RemoveAt(pActivePins.Find(pTmp));
- continue;
- }
- if(pTmp->GetTrackEntry()->TrackType != TrackEntry::TypeSubtitle)
- nPinsNeeded++;
- if(pTmp->m_blocks.GetCount() > 0)
- {
- if(pTmp->GetTrackEntry()->TrackType != TrackEntry::TypeSubtitle)
- nPinsGotSomething++;
- if(pTmp->m_blocks.GetCount() > 0)
- {
- REFERENCE_TIME rt = pTmp->m_blocks.GetHead()->Block.TimeCode;
- if(rt < rtMin) {rtMin = rt; pPin = pTmp;}
- }
- }
- }
- if(pActivePins.GetCount() == 0)
- {
- break;
- }
- if(!pPin || nPinsNeeded > nPinsGotSomething || !pPin && nPinsGotSomething == 0)
- {
- Sleep(1);
- continue;
- }
- if(!fTracksWritten)
- {
- CNode<Track> Tracks;
- CAutoPtr<Track> pT(new Track());
- POSITION pos = pActivePins.GetHeadPosition();
- for(int i = 1; pos; i++)
- {
- CMatroskaMuxerInputPin* pPin = pActivePins.GetNext(pos);
- CAutoPtr<TrackEntry> pTE(new TrackEntry());
- *pTE = *pPin->GetTrackEntry();
- if(TrackNumber == 0 && pTE->TrackType == TrackEntry::TypeVideo)
- TrackNumber = pTE->TrackNumber;
- pT->TrackEntries.AddTail(pTE);
- }
- Tracks.AddTail(pT);
- Tracks.Write(pStream);
- if(TrackNumber == 0) TrackNumber = 1;
- fTracksWritten = true;
- }
- ASSERT(pPin);
- CAutoPtr<BlockGroup> b;
- {
- CAutoLock cAutoLock(&pPin->m_csQueue);
- b = pPin->m_blocks.RemoveHead();
- }
- if(b)
- {
- if(fFirstBlock)
- {
- if(b->Block.TimeCode < 0 && m_fNegative || b->Block.TimeCode > 0 && m_fPositive)
- firstTimeCode = b->Block.TimeCode;
- fFirstBlock = false;
- }
- b->Block.TimeCode -= firstTimeCode;
- b->Block.TimeCodeStop -= firstTimeCode;
- /*
- TRACE(_T("Muxing (%d): %I64d-%I64d dur=%I64d (c=%d, co=%dms), cnt=%d, ref=%dn"),
- GetTrackNumber(pPin),
- (INT64)b->Block.TimeCode, (INT64)b->Block.TimeCodeStop, (UINT64)b->BlockDuration,
- (int)((b->Block.TimeCode)/MAXCLUSTERTIME), (int)(b->Block.TimeCode%MAXCLUSTERTIME),
- b->Block.BlockData.GetCount(), (int)b->ReferenceBlock);
- */
- if(b->Block.TimeCode < SHRT_MIN /*0*/) {ASSERT(0); continue;}
- while((INT64)(c.TimeCode + MAXCLUSTERTIME) < b->Block.TimeCode)
- {
- if(!c.BlockGroups.IsEmpty())
- {
- sh.Attach(new SeekHead());
- sh->ID.Set(c.GetID()/*0x1F43B675*/);
- sh->Position.Set(GetStreamPosition(pStream) - segpos);
- seek.SeekHeads.AddTail(sh);
- c.Write(pStream); // TODO: write blocks
- }
- c.TimeCode.Set(c.TimeCode + MAXCLUSTERTIME);
- c.BlockGroups.RemoveAll();
- nBlocksInCueTrack = 0;
- }
- if(b->Block.TrackNumber == TrackNumber)
- {
- nBlocksInCueTrack++;
- }
- if(b->ReferenceBlock == 0 && b->Block.TrackNumber == TrackNumber)
- {
- ULONGLONG clusterpos = GetStreamPosition(pStream) - segpos;
- if(lastcueclusterpos != clusterpos || lastcuetimecode + 1000 < b->Block.TimeCode)
- {
- CAutoPtr<CueTrackPosition> ctp(new CueTrackPosition());
- ctp->CueTrack.Set(b->Block.TrackNumber);
- ctp->CueClusterPosition.Set(clusterpos);
- if(c.BlockGroups.GetCount() > 0) ctp->CueBlockNumber.Set(nBlocksInCueTrack);
- CAutoPtr<CuePoint> cp(new CuePoint());
- cp->CueTime.Set(b->Block.TimeCode);
- cp->CueTrackPositions.AddTail(ctp);
- cue.CuePoints.AddTail(cp);
- lastcueclusterpos = clusterpos;
- lastcuetimecode = b->Block.TimeCode;
- }
- }
- info.Duration.Set(max(info.Duration, (float)b->Block.TimeCodeStop));
- m_rtCurrent = b->Block.TimeCode*10000;
- b->Block.TimeCode -= c.TimeCode;
- c.BlockGroups.AddTail(b);
- }
- }
- if(!c.BlockGroups.IsEmpty())
- {
- sh.Attach(new SeekHead());
- sh->ID.Set(c.GetID()/*0x1F43B675*/);
- sh->Position.Set(GetStreamPosition(pStream) - segpos);
- seek.SeekHeads.AddTail(sh);
- c.Write(pStream);
- }
- ULONGLONG cuepos = 0;
- if(!cue.CuePoints.IsEmpty())
- {
- sh.Attach(new SeekHead());
- sh->ID.Set(cue.GetID()/*0x1C53BB6B*/);
- sh->Position.Set(GetStreamPosition(pStream) - segpos);
- seek.SeekHeads.AddTail(sh);
- cue.Write(pStream);
- }
- {
- Tags tags;
- sh.Attach(new SeekHead());
- sh->ID.Set(tags.GetID());
- sh->Position.Set(GetStreamPosition(pStream) - segpos);
- seek.SeekHeads.AddTail(sh);
- tags.Write(pStream);
- }
- SetStreamPosition(pStream, voidpos);
- int len = (int)(voidlen - seek.Size());
- ASSERT(len >= 0 && len != 1);
- seek.Write(pStream);
- if(len == 0)
- {
- // nothing to do
- }
- else if(len >= 2)
- {
- for(int i = 0; i < 8; i++)
- {
- if(len >= (1<<i*7)-2 && len <= (1<<(i+1)*7)-2)
- {
- Void(len-2-i).Write(pStream);
- break;
- }
- }
- }
- if(abs(m_rtCurrent - (REFERENCE_TIME)info.Duration*10000) > 10000000i64)
- {
- info.Duration.Set(m_rtCurrent / 10000 + 1);
- }
- SetStreamPosition(pStream, infopos);
- info.Write(pStream);
- // TODO: write some tags
- m_pOutput->DeliverEndOfStream();
- break;
- }
- }
- ASSERT(0); // we should only exit via CMD_EXIT
- CAMThread::m_hThread = NULL;
- return 0;
- }
- //
- // CMatroskaMuxerInputPin
- //
- CMatroskaMuxerInputPin::CMatroskaMuxerInputPin(LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
- : CBaseInputPin(NAME("CMatroskaMuxerInputPin"), pFilter, pLock, phr, pName)
- , m_fActive(false)
- , m_fEndOfStreamReceived(false)
- , m_rtDur(0)
- {
- }
- CMatroskaMuxerInputPin::~CMatroskaMuxerInputPin()
- {
- }
- STDMETHODIMP CMatroskaMuxerInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
- {
- CheckPointer(ppv, E_POINTER);
- return
- __super::NonDelegatingQueryInterface(riid, ppv);
- }
- HRESULT CMatroskaMuxerInputPin::CheckMediaType(const CMediaType* pmt)
- {
- return pmt->majortype == MEDIATYPE_Video && (pmt->formattype == FORMAT_VideoInfo
- || pmt->formattype == FORMAT_VideoInfo2)
- // || pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_MPEG1Payload && pmt->formattype == FORMAT_MPEGVideo
- // || pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_MPEG2_VIDEO && pmt->formattype == FORMAT_MPEG2_VIDEO
- || pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_DiracVideo && pmt->formattype == FORMAT_DiracVideoInfo
- || pmt->majortype == MEDIATYPE_Audio && pmt->formattype == FORMAT_WaveFormatEx && pmt->subtype == FOURCCMap(((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag)
- || pmt->majortype == MEDIATYPE_Audio && pmt->subtype == MEDIASUBTYPE_Vorbis && pmt->formattype == FORMAT_VorbisFormat
- || pmt->majortype == MEDIATYPE_Audio && pmt->subtype == MEDIASUBTYPE_Vorbis2 && pmt->formattype == FORMAT_VorbisFormat2
- || pmt->majortype == MEDIATYPE_Audio && (pmt->subtype == MEDIASUBTYPE_14_4
- || pmt->subtype == MEDIASUBTYPE_28_8
- || pmt->subtype == MEDIASUBTYPE_ATRC
- || pmt->subtype == MEDIASUBTYPE_COOK
- || pmt->subtype == MEDIASUBTYPE_DNET
- || pmt->subtype == MEDIASUBTYPE_SIPR) && pmt->formattype == FORMAT_WaveFormatEx
- || pmt->majortype == MEDIATYPE_Text && pmt->subtype == MEDIASUBTYPE_NULL && pmt->formattype == FORMAT_None
- || pmt->majortype == MEDIATYPE_Subtitle && pmt->formattype == FORMAT_SubtitleInfo
- ? S_OK
- : E_INVALIDARG;
- }
- HRESULT CMatroskaMuxerInputPin::BreakConnect()
- {
- HRESULT hr;
- if(FAILED(hr = __super::BreakConnect()))
- return hr;
- m_pTE.Free();
- return hr;
- }
- HRESULT CMatroskaMuxerInputPin::CompleteConnect(IPin* pPin)
- {
- HRESULT hr;
- if(FAILED(hr = __super::CompleteConnect(pPin)))
- return hr;
- m_rtDur = 0;
- CComQIPtr<IMediaSeeking> pMS;
- if((pMS = GetFilterFromPin(pPin)) || (pMS = pPin))
- pMS->GetDuration(&m_rtDur);
- m_pTE.Free();
- m_pTE.Attach(new TrackEntry());
- m_pTE->TrackUID.Set(rand());
- m_pTE->MinCache.Set(1);
- m_pTE->MaxCache.Set(1);
- m_pTE->TrackNumber.Set(((CMatroskaMuxerFilter*)m_pFilter)->GetTrackNumber(this));
- hr = E_FAIL;
- if(m_mt.majortype == MEDIATYPE_Video)
- {
- m_pTE->TrackType.Set(TrackEntry::TypeVideo);
- if(m_mt.formattype == FORMAT_VideoInfo
- && m_mt.subtype == MEDIASUBTYPE_RV10 || m_mt.subtype == MEDIASUBTYPE_RV20
- || m_mt.subtype == MEDIASUBTYPE_RV30 || m_mt.subtype == MEDIASUBTYPE_RV40)
- {
- m_pTE->CodecID.Set("V_REAL/RV00");
- m_pTE->CodecID[9] = (CHAR)(m_mt.subtype.Data1>>16);
- if(m_mt.formattype == FORMAT_VideoInfo)
- {
- VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_mt.pbFormat;
- if(m_mt.cbFormat > sizeof(VIDEOINFOHEADER))
- {
- m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - sizeof(VIDEOINFOHEADER));
- memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + sizeof(VIDEOINFOHEADER), m_pTE->CodecPrivate.GetSize());
- }
- m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100);
- m_pTE->DescType = TrackEntry::DescVideo;
- m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
- m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
- if(vih->AvgTimePerFrame > 0)
- m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame));
- }
- else if(m_mt.formattype == FORMAT_VideoInfo2)
- {
- VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)m_mt.pbFormat;
- if(m_mt.cbFormat > sizeof(VIDEOINFOHEADER2))
- {
- m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - sizeof(VIDEOINFOHEADER2));
- memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + sizeof(VIDEOINFOHEADER2), m_pTE->CodecPrivate.GetSize());
- }
- m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100);
- m_pTE->DescType = TrackEntry::DescVideo;
- m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
- m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
- if(vih->AvgTimePerFrame > 0)
- m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame));
- m_pTE->v.DisplayWidth.Set(vih->dwPictAspectRatioX);
- m_pTE->v.DisplayHeight.Set(vih->dwPictAspectRatioY);
- }
- else
- {
- ASSERT(0);
- return hr;
- }
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_VideoInfo)
- {
- m_pTE->CodecID.Set("V_MS/VFW/FOURCC");
- VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_mt.pbFormat;
- m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader));
- memcpy(m_pTE->CodecPrivate, &vih->bmiHeader, m_pTE->CodecPrivate.GetSize());
- m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100);
- m_pTE->DescType = TrackEntry::DescVideo;
- m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
- m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
- if(vih->AvgTimePerFrame > 0)
- m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame));
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_VideoInfo2)
- {
- m_pTE->CodecID.Set("V_MS/VFW/FOURCC");
- VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)m_mt.pbFormat;
- m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader));
- memcpy(m_pTE->CodecPrivate, &vih->bmiHeader, m_pTE->CodecPrivate.GetSize());
- m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100);
- m_pTE->DescType = TrackEntry::DescVideo;
- m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
- m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
- m_pTE->v.DisplayWidth.Set(vih->dwPictAspectRatioX);
- m_pTE->v.DisplayHeight.Set(vih->dwPictAspectRatioY);
- if(vih->AvgTimePerFrame > 0)
- m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame));
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_DiracVideoInfo)
- {
- m_pTE->CodecID.Set("V_DIRAC");
- DIRACINFOHEADER* vih = (DIRACINFOHEADER*)m_mt.pbFormat;
- m_pTE->CodecPrivate.SetSize(vih->cbSequenceHeader);
- memcpy(m_pTE->CodecPrivate, (BYTE*)&vih->dwSequenceHeader[0], m_pTE->CodecPrivate.GetSize());
- m_pTE->DefaultDuration.Set(vih->hdr.AvgTimePerFrame*100);
- m_pTE->DescType = TrackEntry::DescVideo;
- m_pTE->v.PixelWidth.Set(vih->hdr.bmiHeader.biWidth);
- m_pTE->v.PixelHeight.Set(abs(vih->hdr.bmiHeader.biHeight));
- // m_pTE->v.DisplayWidth.Set(vih->dwPictAspectRatioX);
- // m_pTE->v.DisplayHeight.Set(vih->dwPictAspectRatioY);
- if(vih->hdr.AvgTimePerFrame > 0)
- m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->hdr.AvgTimePerFrame));
- hr = S_OK;
- }
- /*
- else if(m_mt.formattype == FORMAT_MPEGVideo)
- {
- m_pTE->CodecID.Set("V_DSHOW/MPEG1VIDEO"); // V_MPEG1
- MPEG1VIDEOINFO* pm1vi = (MPEG1VIDEOINFO*)m_mt.pbFormat;
- m_pTE->CodecPrivate.SetSize(m_mt.FormatLength());
- memcpy(m_pTE->CodecPrivate, m_mt.pbFormat, m_pTE->CodecPrivate.GetSize());
- m_pTE->DefaultDuration.Set(pm1vi->hdr.AvgTimePerFrame*100);
- m_pTE->DescType = TrackEntry::DescVideo;
- m_pTE->v.PixelWidth.Set(pm1vi->hdr.bmiHeader.biWidth);
- m_pTE->v.PixelHeight.Set(abs(pm1vi->hdr.bmiHeader.biHeight));
- if(pm1vi->hdr.AvgTimePerFrame > 0)
- m_pTE->v.FramePerSec.Set((float)(10000000.0 / pm1vi->hdr.AvgTimePerFrame));
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_MPEG2_VIDEO)
- {
- m_pTE->CodecID.Set("V_DSHOW/MPEG2VIDEO"); // V_MPEG2
- MPEG2VIDEOINFO* pm2vi = (MPEG2VIDEOINFO*)m_mt.pbFormat;
- m_pTE->CodecPrivate.SetSize(m_mt.FormatLength());
- memcpy(m_pTE->CodecPrivate, m_mt.pbFormat, m_pTE->CodecPrivate.GetSize());
- m_pTE->DefaultDuration.Set(pm2vi->hdr.AvgTimePerFrame*100);
- m_pTE->DescType = TrackEntry::DescVideo;
- m_pTE->v.PixelWidth.Set(pm2vi->hdr.bmiHeader.biWidth);
- m_pTE->v.PixelHeight.Set(abs(pm2vi->hdr.bmiHeader.biHeight));
- if(pm2vi->hdr.AvgTimePerFrame > 0)
- m_pTE->v.FramePerSec.Set((float)(10000000.0 / pm2vi->hdr.AvgTimePerFrame));
- hr = S_OK;
- }
- */
- }
- else if(m_mt.majortype == MEDIATYPE_Audio)
- {
- m_pTE->TrackType.Set(TrackEntry::TypeAudio);
- if(m_mt.formattype == FORMAT_WaveFormatEx
- && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_AAC
- && m_mt.cbFormat >= sizeof(WAVEFORMATEX)+2)
- {
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
- BYTE* p = (BYTE*)(wfe+1);
- DWORD nSamplesPerSec = wfe->nSamplesPerSec;
- int profile = (p[0]>>3)-1;
- int rate1 = ((p[0]&7)<<1)|(p[1]>>7);
- int channels = ((p[1]>>3)&15);
- int exttype = 0;
- int rate2 = rate1;
- if(wfe->cbSize >= 5)
- {
- profile = 4;
- exttype = (p[2]<<3)|(p[3]>>5);
- ASSERT(exttype == 0x2B7);
- ASSERT((p[3]&31) == 5);
- ASSERT((p[4]>>7) == 1);
- rate2 = ((p[4]>>3)&15);
- if(rate2 < rate1)
- {
- m_pTE->a.OutputSamplingFrequency.Set((float)nSamplesPerSec);
- nSamplesPerSec /= 2;
- }
- }
- switch(profile)
- {
- default:
- case 0: m_pTE->CodecID.Set("A_AAC/MPEG2/MAIN"); break;
- case 1: m_pTE->CodecID.Set("A_AAC/MPEG2/LC"); break;
- case 2: m_pTE->CodecID.Set("A_AAC/MPEG2/SSR"); break;
- case 3: m_pTE->CodecID.Set("A_AAC/MPEG4/LTP"); break;
- case 4: m_pTE->CodecID.Set("A_AAC/MPEG4/LC/SBR"); break;
- }
- ASSERT(channels == wfe->nChannels);
- m_pTE->DescType = TrackEntry::DescAudio;
- m_pTE->a.SamplingFrequency.Set((float)nSamplesPerSec);
- m_pTE->a.Channels.Set(channels);
- m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_WaveFormatEx
- && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_DOLBY_AC3)
- {
- m_pTE->CodecID.Set("A_AC3");
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
- m_pTE->DescType = TrackEntry::DescAudio;
- m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
- m_pTE->a.Channels.Set(wfe->nChannels);
- m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_WaveFormatEx
- && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_DVD_DTS)
- {
- m_pTE->CodecID.Set("A_DTS");
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
- m_pTE->DescType = TrackEntry::DescAudio;
- m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
- m_pTE->a.Channels.Set(wfe->nChannels);
- m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_WaveFormatEx
- && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_FLAC)
- {
- m_pTE->CodecID.Set("A_FLAC");
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
- m_pTE->DescType = TrackEntry::DescAudio;
- m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
- m_pTE->a.Channels.Set(wfe->nChannels);
- m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
- if(wfe->cbSize)
- {
- m_pTE->CodecPrivate.SetSize(wfe->cbSize);
- memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + sizeof(WAVEFORMATEX), wfe->cbSize);
- }
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_WaveFormatEx
- && (m_mt.subtype == MEDIASUBTYPE_14_4
- || m_mt.subtype == MEDIASUBTYPE_28_8
- || m_mt.subtype == MEDIASUBTYPE_ATRC
- || m_mt.subtype == MEDIASUBTYPE_COOK
- || m_mt.subtype == MEDIASUBTYPE_DNET
- || m_mt.subtype == MEDIASUBTYPE_SIPR))
- {
- CStringA id;
- id.Format("A_REAL/%c%c%c%c",
- (char)((m_mt.subtype.Data1>>0)&0xff),
- (char)((m_mt.subtype.Data1>>8)&0xff),
- (char)((m_mt.subtype.Data1>>16)&0xff),
- (char)((m_mt.subtype.Data1>>24)&0xff));
- m_pTE->CodecID.Set(id);
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
- DWORD cbSize = sizeof(WAVEFORMATEX) + wfe->cbSize;
- if(m_mt.cbFormat > cbSize)
- {
- m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - cbSize);
- memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + cbSize, m_pTE->CodecPrivate.GetSize());
- }
- m_pTE->DescType = TrackEntry::DescAudio;
- m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
- m_pTE->a.Channels.Set(wfe->nChannels);
- m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_WaveFormatEx
- && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_PCM)
- {
- m_pTE->CodecID.Set("A_PCM/INT/LIT");
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
- m_pTE->DescType = TrackEntry::DescAudio;
- m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
- m_pTE->a.Channels.Set(wfe->nChannels);
- m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_WaveFormatEx)
- {
- m_pTE->CodecID.Set("A_MS/ACM");
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
- m_pTE->CodecPrivate.SetSize(m_mt.cbFormat);
- memcpy(m_pTE->CodecPrivate, wfe, m_pTE->CodecPrivate.GetSize());
- m_pTE->DescType = TrackEntry::DescAudio;
- m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
- m_pTE->a.Channels.Set(wfe->nChannels);
- m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_VorbisFormat)
- {
- m_pTE->CodecID.Set("A_VORBIS");
- VORBISFORMAT* pvf = (VORBISFORMAT*)m_mt.pbFormat;
- m_pTE->DescType = TrackEntry::DescAudio;
- m_pTE->a.SamplingFrequency.Set((float)pvf->nSamplesPerSec);
- m_pTE->a.Channels.Set(pvf->nChannels);
- // m_pTE->CodecPrivate will be filled later
- hr = S_OK;
- }
- else if(m_mt.formattype == FORMAT_VorbisFormat2)
- {
- m_pTE->CodecID.Set("A_VORBIS");
- VORBISFORMAT2* pvf2 = (VORBISFORMAT2*)m_mt.pbFormat;
- m_pTE->DescType = TrackEntry::DescAudio;
- m_pTE->a.SamplingFrequency.Set((float)pvf2->SamplesPerSec);
- m_pTE->a.Channels.Set(pvf2->Channels);
- m_pTE->a.BitDepth.Set(pvf2->BitsPerSample);
- int len = 1;
- for(int i = 0; i < 2; i++) len += pvf2->HeaderSize[i]/255 + 1;
- for(int i = 0; i < 3; i++) len += pvf2->HeaderSize[i];
- m_pTE->CodecPrivate.SetSize(len);
- BYTE* src = (BYTE*)m_mt.pbFormat + sizeof(VORBISFORMAT2);
- BYTE* dst = m_pTE->CodecPrivate.GetData();
- *dst++ = 2;
- for(int i = 0; i < 2; i++)
- for(int len = pvf2->HeaderSize[i]; len >= 0; len -= 255)
- *dst++ = min(len, 255);
- memcpy(dst, src, pvf2->HeaderSize[0]);
- dst += pvf2->HeaderSize[0];
- src += pvf2->HeaderSize[0];
- memcpy(dst, src, pvf2->HeaderSize[1]);
- dst += pvf2->HeaderSize[1];
- src += pvf2->HeaderSize[1];
- memcpy(dst, src, pvf2->HeaderSize[2]);
- dst += pvf2->HeaderSize[2];
- src += pvf2->HeaderSize[2];
- ASSERT(src <= m_mt.pbFormat + m_mt.cbFormat);
- ASSERT(dst <= m_pTE->CodecPrivate.GetData() + m_pTE->CodecPrivate.GetSize());
- hr = S_OK;
- }
- }
- else if(m_mt.majortype == MEDIATYPE_Text)
- {
- m_pTE->TrackType.Set(TrackEntry::TypeSubtitle);
- if(m_mt.formattype == FORMAT_None)
- {
- m_pTE->CodecID.Set("S_TEXT/ASCII");
- hr = S_OK;
- }
- }
- else if(m_mt.majortype == MEDIATYPE_Subtitle)
- {
- m_pTE->TrackType.Set(TrackEntry::TypeSubtitle);
- m_pTE->CodecID.Set(
- m_mt.subtype == MEDIASUBTYPE_UTF8 ? "S_TEXT/UTF8" :
- m_mt.subtype == MEDIASUBTYPE_SSA ? "S_TEXT/SSA" :
- m_mt.subtype == MEDIASUBTYPE_ASS ? "S_TEXT/ASS" :
- m_mt.subtype == MEDIASUBTYPE_USF ? "S_TEXT/USF" :
- m_mt.subtype == MEDIASUBTYPE_VOBSUB ? "S_VOBSUB" :
- "");
- if(!m_pTE->CodecID.IsEmpty())
- {
- hr = S_OK;
- SUBTITLEINFO* psi = (SUBTITLEINFO*)m_mt.pbFormat;
- if(psi->dwOffset)
- {
- m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - psi->dwOffset);
- memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + psi->dwOffset, m_pTE->CodecPrivate.GetSize());
- }
- }
- }
- if(S_OK == hr)
- {
- ((CMatroskaMuxerFilter*)m_pFilter)->AddInput();
- }
- return hr;
- }
- HRESULT CMatroskaMuxerInputPin::Active()
- {
- m_fActive = true;
- m_rtLastStart = m_rtLastStop = -1;
- m_fEndOfStreamReceived = false;
- return __super::Active();
- }
- HRESULT CMatroskaMuxerInputPin::Inactive()
- {
- m_fActive = false;
- CAutoLock cAutoLock(&m_csQueue);
- m_blocks.RemoveAll();
- m_pVorbisHdrs.RemoveAll();
- return __super::Inactive();
- }
- STDMETHODIMP CMatroskaMuxerInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
- {
- CAutoLock cAutoLock(&m_csReceive);
- return __super::NewSegment(tStart, tStop, dRate);
- }
- STDMETHODIMP CMatroskaMuxerInputPin::BeginFlush()
- {
- return __super::BeginFlush();
- }
- STDMETHODIMP CMatroskaMuxerInputPin::EndFlush()
- {
- return __super::EndFlush();
- }
- STDMETHODIMP CMatroskaMuxerInputPin::Receive(IMediaSample* pSample)
- {
- if(m_fEndOfStreamReceived) {/*ASSERT(0);*/ return S_FALSE;}
- CAutoLock cAutoLock(&m_csReceive);
- while(m_fActive)
- {
- {
- CAutoLock cAutoLock2(&m_csQueue);
- if(m_blocks.GetCount() < MAXBLOCKS)
- break;
- }
- Sleep(1);
- }
- if(!m_fActive) return S_FALSE;
- HRESULT hr;
- if(FAILED(hr = __super::Receive(pSample)))
- return hr;
- BYTE* pData = NULL;
- pSample->GetPointer(&pData);
- long len = pSample->GetActualDataLength();
- REFERENCE_TIME rtStart = -1, rtStop = -1;
- hr = pSample->GetTime(&rtStart, &rtStop);
- if(FAILED(hr) || rtStart == -1 || rtStop == -1)
- {
- TRACE(_T("No timestamp was set on the sample!!!"));
- m_pFilter->NotifyEvent(EC_ERRORABORT, VFW_E_SAMPLE_TIME_NOT_SET, 0);
- return VFW_E_SAMPLE_TIME_NOT_SET;
- }
- // rtStart += m_tStart;
- // rtStop += m_tStart;
- /**/
- TRACE(_T("Received (%d): %I64d-%I64d (c=%d, co=%dms), len=%d, d%d p%d s%dn"),
- ((CMatroskaMuxerFilter*)m_pFilter)->GetTrackNumber(this),
- rtStart, rtStop, (int)((rtStart/10000)/MAXCLUSTERTIME), (int)((rtStart/10000)%MAXCLUSTERTIME),
- len,
- pSample->IsDiscontinuity() == S_OK ? 1 : 0,
- pSample->IsPreroll() == S_OK ? 1 : 0,
- pSample->IsSyncPoint() == S_OK ? 1 : 0);
- if(m_mt.subtype == MEDIASUBTYPE_Vorbis && m_pVorbisHdrs.GetCount() < 3)
- {
- CAutoPtr<CBinary> data(new CBinary(0));
- data->SetSize(len);
- memcpy(data->GetData(), pData, len);
- m_pVorbisHdrs.Add(data);
- if(m_pVorbisHdrs.GetCount() == 3)
- {
- int len = 1;
- for(int i = 0; i < 2; i++) len += m_pVorbisHdrs[i]->GetSize()/255 + 1;
- for(int i = 0; i < 3; i++) len += m_pVorbisHdrs[i]->GetSize();
- m_pTE->CodecPrivate.SetSize(len);
- BYTE* dst = m_pTE->CodecPrivate.GetData();
- *dst++ = 2;
- for(int i = 0; i < 2; i++)
- for(int len = m_pVorbisHdrs[i]->GetSize(); len >= 0; len -= 255)
- *dst++ = min(len, 255);
- for(int i = 0; i < 3; i++)
- {
- memcpy(dst, m_pVorbisHdrs[i]->GetData(), m_pVorbisHdrs[i]->GetSize());
- dst += m_pVorbisHdrs[i]->GetSize();
- }
- }
- return S_OK;
- }
- if(m_mt.formattype == FORMAT_WaveFormatEx
- && (((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_PCM
- || ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_MPEGLAYER3))
- pSample->SetSyncPoint(TRUE); // HACK: some capture filters don't set this
- CAutoPtr<BlockGroup> b(new BlockGroup());
- /*
- // TODO: test this with a longer capture (pcm, mp3)
- if(S_OK == pSample->IsSyncPoint() && rtStart < m_rtLastStart)
- {
- TRACE(_T("!!! timestamp went backwards, dropping this frame !!! rtStart (%I64) < m_rtLastStart (%I64)"), rtStart, m_rtLastStart);
- return S_OK;
- }
- */
- if((S_OK != pSample->IsSyncPoint() || m_rtLastStart == rtStart) && m_rtLastStart >= 0 /*&& m_rtLastStart < rtStart*/)
- {
- ASSERT(m_rtLastStart - rtStart <= 0);
- REFERENCE_TIME rtDiff = m_rtLastStart - rtStart;
- b->ReferenceBlock.Set((rtDiff + (rtDiff >= 0 ? 5000 : -5000)) / 10000);
- }
- b->Block.TrackNumber = ((CMatroskaMuxerFilter*)m_pFilter)->GetTrackNumber(this);
- b->Block.TimeCode = (rtStart + 5000) / 10000;
- b->Block.TimeCodeStop = (rtStop + 5000) / 10000;
- if(m_pTE->TrackType == TrackEntry::TypeSubtitle)
- {
- b->BlockDuration.Set((rtStop - rtStart + 5000) / 10000);
- }
- CAutoPtr<CBinary> data(new CBinary(0));
- data->SetSize(len);
- memcpy(data->GetData(), pData, len);
- b->Block.BlockData.AddTail(data);
- CAutoLock cAutoLock2(&m_csQueue);
- m_blocks.AddTail(b); // TODO: lacing for audio
- m_rtLastStart = rtStart;
- m_rtLastStop = rtStop;
- return S_OK;
- }
- STDMETHODIMP CMatroskaMuxerInputPin::EndOfStream()
- {
- HRESULT hr;
- if(FAILED(hr = __super::EndOfStream()))
- return hr;
- CAutoLock cAutoLock(&m_csQueue);
- m_fEndOfStreamReceived = true;
- return hr;
- }
- //
- // CMatroskaMuxerOutputPin
- //
- CMatroskaMuxerOutputPin::CMatroskaMuxerOutputPin(TCHAR* pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
- : CBaseOutputPin(pName, pFilter, pLock, phr, L"Output")
- {
- }
- CMatroskaMuxerOutputPin::~CMatroskaMuxerOutputPin()
- {
- }
- STDMETHODIMP CMatroskaMuxerOutputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
- {
- CheckPointer(ppv, E_POINTER);
- return
- __super::NonDelegatingQueryInterface(riid, ppv);
- }
- HRESULT CMatroskaMuxerOutputPin::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
- {
- ASSERT(pAlloc);
- ASSERT(pProperties);
- HRESULT hr = NOERROR;
- pProperties->cBuffers = 1;
- pProperties->cbBuffer = 1;
- ALLOCATOR_PROPERTIES Actual;
- if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
- if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
- ASSERT(Actual.cBuffers == pProperties->cBuffers);
- return NOERROR;
- }
- HRESULT CMatroskaMuxerOutputPin::CheckMediaType(const CMediaType* pmt)
- {
- return pmt->majortype == MEDIATYPE_Stream && pmt->subtype == MEDIASUBTYPE_Matroska
- ? S_OK
- : E_INVALIDARG;
- }
- HRESULT CMatroskaMuxerOutputPin::GetMediaType(int iPosition, CMediaType* pmt)
- {
- CAutoLock cAutoLock(m_pLock);
- if(iPosition < 0) return E_INVALIDARG;
- if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
- pmt->ResetFormatBuffer();
- pmt->InitMediaType();
- pmt->majortype = MEDIATYPE_Stream;
- pmt->subtype = MEDIASUBTYPE_Matroska;
- pmt->formattype = FORMAT_None;
- return S_OK;
- }
- STDMETHODIMP CMatroskaMuxerOutputPin::Notify(IBaseFilter* pSender, Quality q)
- {
- return E_NOTIMPL;
- }