00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include <mmreg.h>
00024 #include "MatroskaMuxer.h"
00025 #include "..\..\..\DSUtil\DSUtil.h"
00026
00027 #include <initguid.h>
00028 #include "..\..\..\..\include\matroska\matroska.h"
00029 #include "..\..\..\..\include\ogg\OggDS.h"
00030 #include "..\..\..\..\include\moreuuids.h"
00031
00032 using namespace MatroskaWriter;
00033
00034 #ifdef REGISTER_FILTER
00035
00036 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00037 {
00038 {&MEDIATYPE_Stream, &MEDIASUBTYPE_Matroska}
00039 };
00040
00041 const AMOVIESETUP_PIN sudpPins[] =
00042 {
00043 {L"Input", FALSE, FALSE, FALSE, TRUE, &CLSID_NULL, NULL, 0, NULL},
00044 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
00045 };
00046
00047 const AMOVIESETUP_FILTER sudFilter[] =
00048 {
00049 {&__uuidof(CMatroskaMuxerFilter), L"Matroska Muxer", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
00050 };
00051
00052 CFactoryTemplate g_Templates[] =
00053 {
00054 {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CMatroskaMuxerFilter>, NULL, &sudFilter[0]}
00055 };
00056
00057 int g_cTemplates = countof(g_Templates);
00058
00059 STDAPI DllRegisterServer()
00060 {
00061 return AMovieDllRegisterServer2(TRUE);
00062 }
00063
00064 STDAPI DllUnregisterServer()
00065 {
00066 return AMovieDllRegisterServer2(FALSE);
00067 }
00068
00069 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00070
00071 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00072 {
00073 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00074 }
00075
00076 #endif
00077
00078
00079
00080
00081
00082 CMatroskaMuxerFilter::CMatroskaMuxerFilter(LPUNKNOWN pUnk, HRESULT* phr)
00083 : CBaseFilter(NAME("CMatroskaMuxerFilter"), pUnk, this, __uuidof(this))
00084 , m_rtCurrent(0)
00085 , m_fNegative(true), m_fPositive(false)
00086 {
00087 if(phr) *phr = S_OK;
00088
00089 m_pOutput.Attach(new CMatroskaMuxerOutputPin(NAME("CMatroskaMuxerOutputPin"), this, this, phr));
00090
00091 AddInput();
00092
00093 srand(clock());
00094 }
00095
00096 CMatroskaMuxerFilter::~CMatroskaMuxerFilter()
00097 {
00098 CAutoLock cAutoLock(this);
00099 }
00100
00101 STDMETHODIMP CMatroskaMuxerFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00102 {
00103 CheckPointer(ppv, E_POINTER);
00104
00105 *ppv = NULL;
00106
00107 return
00108
00109 QI(IMediaSeeking)
00110 QI(IMatroskaMuxer)
00111 __super::NonDelegatingQueryInterface(riid, ppv);
00112 }
00113
00114 UINT CMatroskaMuxerFilter::GetTrackNumber(CBasePin* pPin)
00115 {
00116 UINT nTrackNumber = 0;
00117
00118 POSITION pos = m_pInputs.GetHeadPosition();
00119 while(pos)
00120 {
00121 nTrackNumber++;
00122 if(m_pInputs.GetNext(pos) == pPin)
00123 return nTrackNumber;
00124 }
00125
00126 return 0;
00127 }
00128
00129 void CMatroskaMuxerFilter::AddInput()
00130 {
00131 POSITION pos = m_pInputs.GetHeadPosition();
00132 while(pos)
00133 {
00134 CBasePin* pPin = m_pInputs.GetNext(pos);
00135 if(!pPin->IsConnected()) return;
00136 }
00137
00138 CStringW name;
00139 name.Format(L"Track %d", m_pInputs.GetCount()+1);
00140
00141 HRESULT hr;
00142 CAutoPtr<CMatroskaMuxerInputPin> pPin(new CMatroskaMuxerInputPin(name, this, this, &hr));
00143 m_pInputs.AddTail(pPin);
00144 }
00145
00146 int CMatroskaMuxerFilter::GetPinCount()
00147 {
00148 return m_pInputs.GetCount() + (m_pOutput ? 1 : 0);
00149 }
00150
00151 CBasePin* CMatroskaMuxerFilter::GetPin(int n)
00152 {
00153 CAutoLock cAutoLock(this);
00154
00155 if(n >= 0 && n < (int)m_pInputs.GetCount())
00156 {
00157 if(POSITION pos = m_pInputs.FindIndex(n))
00158 return m_pInputs.GetAt(pos);
00159 }
00160
00161 if(n == m_pInputs.GetCount() && m_pOutput)
00162 {
00163 return m_pOutput;
00164 }
00165
00166 return NULL;
00167 }
00168
00169 STDMETHODIMP CMatroskaMuxerFilter::Stop()
00170 {
00171 CAutoLock cAutoLock(this);
00172
00173 HRESULT hr;
00174
00175 if(FAILED(hr = __super::Stop()))
00176 return hr;
00177
00178 CallWorker(CMD_EXIT);
00179
00180 return hr;
00181 }
00182
00183 STDMETHODIMP CMatroskaMuxerFilter::Pause()
00184 {
00185 CAutoLock cAutoLock(this);
00186
00187 FILTER_STATE fs = m_State;
00188
00189 HRESULT hr;
00190
00191 if(FAILED(hr = __super::Pause()))
00192 return hr;
00193
00194 if(fs == State_Stopped && m_pOutput)
00195 {
00196 CAMThread::Create();
00197 CallWorker(CMD_RUN);
00198 }
00199
00200 return hr;
00201 }
00202
00203 STDMETHODIMP CMatroskaMuxerFilter::Run(REFERENCE_TIME tStart)
00204 {
00205 CAutoLock cAutoLock(this);
00206
00207 HRESULT hr;
00208
00209 if(FAILED(hr = __super::Run(tStart)))
00210 return hr;
00211
00212 return hr;
00213 }
00214
00215
00216
00217 STDMETHODIMP_(ULONG) CMatroskaMuxerFilter::GetMiscFlags()
00218 {
00219 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
00220 }
00221
00222
00223
00224 STDMETHODIMP CMatroskaMuxerFilter::GetCapabilities(DWORD* pCapabilities)
00225 {
00226 return pCapabilities ? *pCapabilities =
00227 AM_SEEKING_CanGetDuration|
00228 AM_SEEKING_CanGetCurrentPos, S_OK : E_POINTER;
00229 }
00230 STDMETHODIMP CMatroskaMuxerFilter::CheckCapabilities(DWORD* pCapabilities)
00231 {
00232 CheckPointer(pCapabilities, E_POINTER);
00233 if(*pCapabilities == 0) return S_OK;
00234 DWORD caps;
00235 GetCapabilities(&caps);
00236 caps &= *pCapabilities;
00237 return caps == 0 ? E_FAIL : caps == *pCapabilities ? S_OK : S_FALSE;
00238 }
00239 STDMETHODIMP CMatroskaMuxerFilter::IsFormatSupported(const GUID* pFormat) {return !pFormat ? E_POINTER : *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;}
00240 STDMETHODIMP CMatroskaMuxerFilter::QueryPreferredFormat(GUID* pFormat) {return GetTimeFormat(pFormat);}
00241 STDMETHODIMP CMatroskaMuxerFilter::GetTimeFormat(GUID* pFormat) {return pFormat ? *pFormat = TIME_FORMAT_MEDIA_TIME, S_OK : E_POINTER;}
00242 STDMETHODIMP CMatroskaMuxerFilter::IsUsingTimeFormat(const GUID* pFormat) {return IsFormatSupported(pFormat);}
00243 STDMETHODIMP CMatroskaMuxerFilter::SetTimeFormat(const GUID* pFormat) {return S_OK == IsFormatSupported(pFormat) ? S_OK : E_INVALIDARG;}
00244 STDMETHODIMP CMatroskaMuxerFilter::GetDuration(LONGLONG* pDuration)
00245 {
00246 CheckPointer(pDuration, E_POINTER);
00247 *pDuration = 0;
00248 POSITION pos = m_pInputs.GetHeadPosition();
00249 while(pos) {REFERENCE_TIME rt = m_pInputs.GetNext(pos)->m_rtDur; if(rt > *pDuration) *pDuration = rt;}
00250 return S_OK;
00251 }
00252 STDMETHODIMP CMatroskaMuxerFilter::GetStopPosition(LONGLONG* pStop) {return E_NOTIMPL;}
00253 STDMETHODIMP CMatroskaMuxerFilter::GetCurrentPosition(LONGLONG* pCurrent)
00254 {
00255 CheckPointer(pCurrent, E_POINTER);
00256 *pCurrent = m_rtCurrent;
00257 return S_OK;
00258 }
00259 STDMETHODIMP CMatroskaMuxerFilter::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat) {return E_NOTIMPL;}
00260 STDMETHODIMP CMatroskaMuxerFilter::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags) {return E_NOTIMPL;}
00261 STDMETHODIMP CMatroskaMuxerFilter::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop) {return E_NOTIMPL;}
00262 STDMETHODIMP CMatroskaMuxerFilter::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest) {return E_NOTIMPL;}
00263 STDMETHODIMP CMatroskaMuxerFilter::SetRate(double dRate) {return E_NOTIMPL;}
00264 STDMETHODIMP CMatroskaMuxerFilter::GetRate(double* pdRate) {return E_NOTIMPL;}
00265 STDMETHODIMP CMatroskaMuxerFilter::GetPreroll(LONGLONG* pllPreroll) {return E_NOTIMPL;}
00266
00267
00268
00269 STDMETHODIMP CMatroskaMuxerFilter::CorrectTimeOffset(bool fNegative, bool fPositive)
00270 {
00271 m_fNegative = fNegative;
00272 m_fPositive = fPositive;
00273 return S_OK;
00274 }
00275
00276
00277
00278 ULONGLONG GetStreamPosition(IStream* pStream)
00279 {
00280 ULARGE_INTEGER pos = {0, 0};
00281 pStream->Seek(*(LARGE_INTEGER*)&pos, STREAM_SEEK_CUR, &pos);
00282 return pos.QuadPart;
00283 }
00284
00285 ULONGLONG SetStreamPosition(IStream* pStream, ULONGLONG seekpos)
00286 {
00287 LARGE_INTEGER pos;
00288 pos.QuadPart = seekpos;
00289 ULARGE_INTEGER posnew;
00290 posnew.QuadPart = GetStreamPosition(pStream);
00291 pStream->Seek(pos, STREAM_SEEK_SET, &posnew);
00292 return posnew.QuadPart;
00293 }
00294
00295 DWORD CMatroskaMuxerFilter::ThreadProc()
00296 {
00297 CComQIPtr<IStream> pStream;
00298
00299 if(!m_pOutput || !(pStream = m_pOutput->GetConnected()))
00300 {
00301 while(1)
00302 {
00303 DWORD cmd = GetRequest();
00304 if(cmd == CMD_EXIT) CAMThread::m_hThread = NULL;
00305 Reply(S_OK);
00306 if(cmd == CMD_EXIT) return 0;
00307 }
00308 }
00309
00310 REFERENCE_TIME rtDur = 0;
00311 GetDuration(&rtDur);
00312
00313 SetStreamPosition(pStream, 0);
00314
00315 ULARGE_INTEGER uli = {0};
00316 pStream->SetSize(uli);
00317
00318 EBML hdr;
00319 hdr.DocType.Set("matroska");
00320 hdr.DocTypeVersion.Set(1);
00321 hdr.DocTypeReadVersion.Set(1);
00322 hdr.Write(pStream);
00323
00324 Segment().Write(pStream);
00325 ULONGLONG segpos = GetStreamPosition(pStream);
00326
00327
00328 QWORD voidlen = 100;
00329 if(rtDur > 0) voidlen += int(1.0 * rtDur / MAXCLUSTERTIME / 10000 + 0.5) * 20;
00330 else voidlen += int(1.0 * 1000*60*60*24 / MAXCLUSTERTIME + 0.5) * 20;
00331 ULONGLONG voidpos = GetStreamPosition(pStream);
00332 {
00333 Void v(voidlen);
00334 voidlen = v.Size();
00335 v.Write(pStream);
00336 }
00337
00338
00339
00340 Seek seek;
00341 CAutoPtr<SeekHead> sh;
00342
00343
00344
00345 sh.Attach(new SeekHead());
00346 sh->ID.Set(0x1549A966);
00347 sh->Position.Set(GetStreamPosition(pStream) - segpos);
00348 seek.SeekHeads.AddTail(sh);
00349
00350 ULONGLONG infopos = GetStreamPosition(pStream);
00351 Info info;
00352 info.MuxingApp.Set(L"DirectShow Matroska Muxer");
00353 info.TimeCodeScale.Set(1000000);
00354 info.Duration.Set((float)rtDur / 10000);
00355 struct tm _2001 = {0, 0, 0, 1, 0, 101, 0, 0, 1};
00356 info.DateUTC.Set((_time64(NULL) - _mktime64(&_2001)) * 1000000000);
00357 info.Write(pStream);
00358
00359
00360
00361 sh.Attach(new SeekHead());
00362 sh->ID.Set(0x1654AE6B);
00363 sh->Position.Set(GetStreamPosition(pStream) - segpos);
00364 seek.SeekHeads.AddTail(sh);
00365
00366 UINT64 TrackNumber = 0;
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 bool fTracksWritten = false;
00388
00389
00390
00391 Cluster c;
00392 c.TimeCode.Set(0);
00393
00394 bool fFirstBlock = true;
00395 INT64 firstTimeCode = 0;
00396
00397 CList<CMatroskaMuxerInputPin*> pActivePins;
00398
00399 POSITION pos = m_pInputs.GetHeadPosition();
00400 while(pos)
00401 {
00402 CMatroskaMuxerInputPin* pPin = m_pInputs.GetNext(pos);
00403 if(pPin->IsConnected()) pActivePins.AddTail(pPin);
00404 }
00405
00406 while(1)
00407 {
00408 DWORD cmd = GetRequest();
00409
00410 switch(cmd)
00411 {
00412 default:
00413 case CMD_EXIT:
00414 CAMThread::m_hThread = NULL;
00415 Reply(S_OK);
00416 return 0;
00417
00418 case CMD_RUN:
00419 Reply(S_OK);
00420
00421 Cue cue;
00422 ULONGLONG lastcueclusterpos = -1;
00423 INT64 lastcuetimecode = -1;
00424 UINT64 nBlocksInCueTrack = 0;
00425
00426 while(!CheckRequest(NULL))
00427 {
00428 if(m_State == State_Paused)
00429 {
00430 Sleep(10);
00431 continue;
00432 }
00433
00434 int nPinsGotSomething = 0, nPinsNeeded = 0;
00435 CMatroskaMuxerInputPin* pPin = NULL;
00436 REFERENCE_TIME rtMin = _I64_MAX;
00437
00438 pos = pActivePins.GetHeadPosition();
00439 while(pos)
00440 {
00441 CMatroskaMuxerInputPin* pTmp = pActivePins.GetNext(pos);
00442
00443 CAutoLock cAutoLock(&pTmp->m_csQueue);
00444
00445 if(pTmp->m_blocks.GetCount() == 0 && pTmp->m_fEndOfStreamReceived)
00446 {
00447 pActivePins.RemoveAt(pActivePins.Find(pTmp));
00448 continue;
00449 }
00450
00451 if(pTmp->GetTrackEntry()->TrackType != TrackEntry::TypeSubtitle)
00452 nPinsNeeded++;
00453
00454 if(pTmp->m_blocks.GetCount() > 0)
00455 {
00456 if(pTmp->GetTrackEntry()->TrackType != TrackEntry::TypeSubtitle)
00457 nPinsGotSomething++;
00458
00459 if(pTmp->m_blocks.GetCount() > 0)
00460 {
00461 REFERENCE_TIME rt = pTmp->m_blocks.GetHead()->Block.TimeCode;
00462 if(rt < rtMin) {rtMin = rt; pPin = pTmp;}
00463 }
00464 }
00465 }
00466
00467 if(pActivePins.GetCount() == 0)
00468 {
00469 break;
00470 }
00471
00472 if(!pPin || nPinsNeeded > nPinsGotSomething || !pPin && nPinsGotSomething == 0)
00473 {
00474 Sleep(1);
00475 continue;
00476 }
00477
00478 if(!fTracksWritten)
00479 {
00480 CNode<Track> Tracks;
00481 CAutoPtr<Track> pT(new Track());
00482 POSITION pos = pActivePins.GetHeadPosition();
00483 for(int i = 1; pos; i++)
00484 {
00485 CMatroskaMuxerInputPin* pPin = pActivePins.GetNext(pos);
00486
00487 CAutoPtr<TrackEntry> pTE(new TrackEntry());
00488 *pTE = *pPin->GetTrackEntry();
00489 if(TrackNumber == 0 && pTE->TrackType == TrackEntry::TypeVideo)
00490 TrackNumber = pTE->TrackNumber;
00491 pT->TrackEntries.AddTail(pTE);
00492 }
00493 Tracks.AddTail(pT);
00494 Tracks.Write(pStream);
00495
00496 if(TrackNumber == 0) TrackNumber = 1;
00497
00498 fTracksWritten = true;
00499 }
00500
00501 ASSERT(pPin);
00502
00503 CAutoPtr<BlockGroup> b;
00504
00505 {
00506 CAutoLock cAutoLock(&pPin->m_csQueue);
00507 b = pPin->m_blocks.RemoveHead();
00508 }
00509
00510 if(b)
00511 {
00512 if(fFirstBlock)
00513 {
00514 if(b->Block.TimeCode < 0 && m_fNegative || b->Block.TimeCode > 0 && m_fPositive)
00515 firstTimeCode = b->Block.TimeCode;
00516 fFirstBlock = false;
00517 }
00518
00519 b->Block.TimeCode -= firstTimeCode;
00520 b->Block.TimeCodeStop -= firstTimeCode;
00521
00522
00523
00524
00525
00526
00527
00528
00529 if(b->Block.TimeCode < SHRT_MIN ) {ASSERT(0); continue;}
00530
00531 while((INT64)(c.TimeCode + MAXCLUSTERTIME) < b->Block.TimeCode)
00532 {
00533 if(!c.BlockGroups.IsEmpty())
00534 {
00535 sh.Attach(new SeekHead());
00536 sh->ID.Set(c.GetID());
00537 sh->Position.Set(GetStreamPosition(pStream) - segpos);
00538 seek.SeekHeads.AddTail(sh);
00539
00540 c.Write(pStream);
00541 }
00542
00543 c.TimeCode.Set(c.TimeCode + MAXCLUSTERTIME);
00544 c.BlockGroups.RemoveAll();
00545 nBlocksInCueTrack = 0;
00546 }
00547
00548 if(b->Block.TrackNumber == TrackNumber)
00549 {
00550 nBlocksInCueTrack++;
00551 }
00552
00553 if(b->ReferenceBlock == 0 && b->Block.TrackNumber == TrackNumber)
00554 {
00555 ULONGLONG clusterpos = GetStreamPosition(pStream) - segpos;
00556 if(lastcueclusterpos != clusterpos || lastcuetimecode + 1000 < b->Block.TimeCode)
00557 {
00558 CAutoPtr<CueTrackPosition> ctp(new CueTrackPosition());
00559 ctp->CueTrack.Set(b->Block.TrackNumber);
00560 ctp->CueClusterPosition.Set(clusterpos);
00561 if(c.BlockGroups.GetCount() > 0) ctp->CueBlockNumber.Set(nBlocksInCueTrack);
00562 CAutoPtr<CuePoint> cp(new CuePoint());
00563 cp->CueTime.Set(b->Block.TimeCode);
00564 cp->CueTrackPositions.AddTail(ctp);
00565 cue.CuePoints.AddTail(cp);
00566 lastcueclusterpos = clusterpos;
00567 lastcuetimecode = b->Block.TimeCode;
00568 }
00569 }
00570
00571 info.Duration.Set(max(info.Duration, (float)b->Block.TimeCodeStop));
00572
00573 m_rtCurrent = b->Block.TimeCode*10000;
00574
00575 b->Block.TimeCode -= c.TimeCode;
00576 c.BlockGroups.AddTail(b);
00577 }
00578 }
00579
00580 if(!c.BlockGroups.IsEmpty())
00581 {
00582 sh.Attach(new SeekHead());
00583 sh->ID.Set(c.GetID());
00584 sh->Position.Set(GetStreamPosition(pStream) - segpos);
00585 seek.SeekHeads.AddTail(sh);
00586
00587 c.Write(pStream);
00588 }
00589
00590 ULONGLONG cuepos = 0;
00591 if(!cue.CuePoints.IsEmpty())
00592 {
00593 sh.Attach(new SeekHead());
00594 sh->ID.Set(cue.GetID());
00595 sh->Position.Set(GetStreamPosition(pStream) - segpos);
00596 seek.SeekHeads.AddTail(sh);
00597
00598 cue.Write(pStream);
00599 }
00600
00601 {
00602 Tags tags;
00603
00604 sh.Attach(new SeekHead());
00605 sh->ID.Set(tags.GetID());
00606 sh->Position.Set(GetStreamPosition(pStream) - segpos);
00607 seek.SeekHeads.AddTail(sh);
00608
00609 tags.Write(pStream);
00610 }
00611
00612 SetStreamPosition(pStream, voidpos);
00613 int len = (int)(voidlen - seek.Size());
00614 ASSERT(len >= 0 && len != 1);
00615 seek.Write(pStream);
00616
00617 if(len == 0)
00618 {
00619
00620 }
00621 else if(len >= 2)
00622 {
00623 for(int i = 0; i < 8; i++)
00624 {
00625 if(len >= (1<<i*7)-2 && len <= (1<<(i+1)*7)-2)
00626 {
00627 Void(len-2-i).Write(pStream);
00628 break;
00629 }
00630 }
00631 }
00632
00633 if(abs(m_rtCurrent - (REFERENCE_TIME)info.Duration*10000) > 10000000i64)
00634 {
00635 info.Duration.Set(m_rtCurrent / 10000 + 1);
00636 }
00637
00638 SetStreamPosition(pStream, infopos);
00639 info.Write(pStream);
00640
00641
00642
00643 m_pOutput->DeliverEndOfStream();
00644
00645 break;
00646 }
00647 }
00648
00649 ASSERT(0);
00650
00651 CAMThread::m_hThread = NULL;
00652 return 0;
00653 }
00654
00655
00656
00657
00658
00659 CMatroskaMuxerInputPin::CMatroskaMuxerInputPin(LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
00660 : CBaseInputPin(NAME("CMatroskaMuxerInputPin"), pFilter, pLock, phr, pName)
00661 , m_fActive(false)
00662 , m_fEndOfStreamReceived(false)
00663 , m_rtDur(0)
00664 {
00665 }
00666
00667 CMatroskaMuxerInputPin::~CMatroskaMuxerInputPin()
00668 {
00669 }
00670
00671 STDMETHODIMP CMatroskaMuxerInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00672 {
00673 CheckPointer(ppv, E_POINTER);
00674
00675 return
00676 __super::NonDelegatingQueryInterface(riid, ppv);
00677 }
00678
00679 HRESULT CMatroskaMuxerInputPin::CheckMediaType(const CMediaType* pmt)
00680 {
00681 return pmt->majortype == MEDIATYPE_Video && (pmt->formattype == FORMAT_VideoInfo
00682 || pmt->formattype == FORMAT_VideoInfo2)
00683
00684
00685 || pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_DiracVideo && pmt->formattype == FORMAT_DiracVideoInfo
00686 || pmt->majortype == MEDIATYPE_Audio && pmt->formattype == FORMAT_WaveFormatEx && pmt->subtype == FOURCCMap(((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag)
00687 || pmt->majortype == MEDIATYPE_Audio && pmt->subtype == MEDIASUBTYPE_Vorbis && pmt->formattype == FORMAT_VorbisFormat
00688 || pmt->majortype == MEDIATYPE_Audio && pmt->subtype == MEDIASUBTYPE_Vorbis2 && pmt->formattype == FORMAT_VorbisFormat2
00689 || pmt->majortype == MEDIATYPE_Audio && (pmt->subtype == MEDIASUBTYPE_14_4
00690 || pmt->subtype == MEDIASUBTYPE_28_8
00691 || pmt->subtype == MEDIASUBTYPE_ATRC
00692 || pmt->subtype == MEDIASUBTYPE_COOK
00693 || pmt->subtype == MEDIASUBTYPE_DNET
00694 || pmt->subtype == MEDIASUBTYPE_SIPR) && pmt->formattype == FORMAT_WaveFormatEx
00695 || pmt->majortype == MEDIATYPE_Text && pmt->subtype == MEDIASUBTYPE_NULL && pmt->formattype == FORMAT_None
00696 || pmt->majortype == MEDIATYPE_Subtitle && pmt->formattype == FORMAT_SubtitleInfo
00697 ? S_OK
00698 : E_INVALIDARG;
00699 }
00700
00701 HRESULT CMatroskaMuxerInputPin::BreakConnect()
00702 {
00703 HRESULT hr;
00704
00705 if(FAILED(hr = __super::BreakConnect()))
00706 return hr;
00707
00708 m_pTE.Free();
00709
00710 return hr;
00711 }
00712
00713 HRESULT CMatroskaMuxerInputPin::CompleteConnect(IPin* pPin)
00714 {
00715 HRESULT hr;
00716
00717 if(FAILED(hr = __super::CompleteConnect(pPin)))
00718 return hr;
00719
00720 m_rtDur = 0;
00721 CComQIPtr<IMediaSeeking> pMS;
00722 if((pMS = GetFilterFromPin(pPin)) || (pMS = pPin))
00723 pMS->GetDuration(&m_rtDur);
00724
00725 m_pTE.Free();
00726 m_pTE.Attach(new TrackEntry());
00727
00728 m_pTE->TrackUID.Set(rand());
00729 m_pTE->MinCache.Set(1);
00730 m_pTE->MaxCache.Set(1);
00731 m_pTE->TrackNumber.Set(((CMatroskaMuxerFilter*)m_pFilter)->GetTrackNumber(this));
00732
00733 hr = E_FAIL;
00734
00735 if(m_mt.majortype == MEDIATYPE_Video)
00736 {
00737 m_pTE->TrackType.Set(TrackEntry::TypeVideo);
00738
00739 if(m_mt.formattype == FORMAT_VideoInfo
00740 && m_mt.subtype == MEDIASUBTYPE_RV10 || m_mt.subtype == MEDIASUBTYPE_RV20
00741 || m_mt.subtype == MEDIASUBTYPE_RV30 || m_mt.subtype == MEDIASUBTYPE_RV40)
00742 {
00743 m_pTE->CodecID.Set("V_REAL/RV00");
00744 m_pTE->CodecID[9] = (CHAR)(m_mt.subtype.Data1>>16);
00745
00746 if(m_mt.formattype == FORMAT_VideoInfo)
00747 {
00748 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_mt.pbFormat;
00749 if(m_mt.cbFormat > sizeof(VIDEOINFOHEADER))
00750 {
00751 m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - sizeof(VIDEOINFOHEADER));
00752 memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + sizeof(VIDEOINFOHEADER), m_pTE->CodecPrivate.GetSize());
00753 }
00754 m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100);
00755 m_pTE->DescType = TrackEntry::DescVideo;
00756 m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
00757 m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
00758 if(vih->AvgTimePerFrame > 0)
00759 m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame));
00760 }
00761 else if(m_mt.formattype == FORMAT_VideoInfo2)
00762 {
00763 VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)m_mt.pbFormat;
00764 if(m_mt.cbFormat > sizeof(VIDEOINFOHEADER2))
00765 {
00766 m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - sizeof(VIDEOINFOHEADER2));
00767 memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + sizeof(VIDEOINFOHEADER2), m_pTE->CodecPrivate.GetSize());
00768 }
00769 m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100);
00770 m_pTE->DescType = TrackEntry::DescVideo;
00771 m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
00772 m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
00773 if(vih->AvgTimePerFrame > 0)
00774 m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame));
00775 m_pTE->v.DisplayWidth.Set(vih->dwPictAspectRatioX);
00776 m_pTE->v.DisplayHeight.Set(vih->dwPictAspectRatioY);
00777 }
00778 else
00779 {
00780 ASSERT(0);
00781 return hr;
00782 }
00783
00784 hr = S_OK;
00785 }
00786 else if(m_mt.formattype == FORMAT_VideoInfo)
00787 {
00788 m_pTE->CodecID.Set("V_MS/VFW/FOURCC");
00789
00790 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_mt.pbFormat;
00791 m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader));
00792 memcpy(m_pTE->CodecPrivate, &vih->bmiHeader, m_pTE->CodecPrivate.GetSize());
00793 m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100);
00794 m_pTE->DescType = TrackEntry::DescVideo;
00795 m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
00796 m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
00797 if(vih->AvgTimePerFrame > 0)
00798 m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame));
00799
00800 hr = S_OK;
00801 }
00802 else if(m_mt.formattype == FORMAT_VideoInfo2)
00803 {
00804 m_pTE->CodecID.Set("V_MS/VFW/FOURCC");
00805
00806 VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)m_mt.pbFormat;
00807 m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader));
00808 memcpy(m_pTE->CodecPrivate, &vih->bmiHeader, m_pTE->CodecPrivate.GetSize());
00809 m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100);
00810 m_pTE->DescType = TrackEntry::DescVideo;
00811 m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
00812 m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
00813 m_pTE->v.DisplayWidth.Set(vih->dwPictAspectRatioX);
00814 m_pTE->v.DisplayHeight.Set(vih->dwPictAspectRatioY);
00815 if(vih->AvgTimePerFrame > 0)
00816 m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame));
00817
00818 hr = S_OK;
00819 }
00820 else if(m_mt.formattype == FORMAT_DiracVideoInfo)
00821 {
00822 m_pTE->CodecID.Set("V_DIRAC");
00823
00824 DIRACINFOHEADER* vih = (DIRACINFOHEADER*)m_mt.pbFormat;
00825 m_pTE->CodecPrivate.SetSize(vih->cbSequenceHeader);
00826 memcpy(m_pTE->CodecPrivate, (BYTE*)&vih->dwSequenceHeader[0], m_pTE->CodecPrivate.GetSize());
00827 m_pTE->DefaultDuration.Set(vih->hdr.AvgTimePerFrame*100);
00828 m_pTE->DescType = TrackEntry::DescVideo;
00829 m_pTE->v.PixelWidth.Set(vih->hdr.bmiHeader.biWidth);
00830 m_pTE->v.PixelHeight.Set(abs(vih->hdr.bmiHeader.biHeight));
00831
00832
00833 if(vih->hdr.AvgTimePerFrame > 0)
00834 m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->hdr.AvgTimePerFrame));
00835
00836 hr = S_OK;
00837 }
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 }
00873 else if(m_mt.majortype == MEDIATYPE_Audio)
00874 {
00875 m_pTE->TrackType.Set(TrackEntry::TypeAudio);
00876
00877 if(m_mt.formattype == FORMAT_WaveFormatEx
00878 && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_AAC
00879 && m_mt.cbFormat >= sizeof(WAVEFORMATEX)+2)
00880 {
00881 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
00882 BYTE* p = (BYTE*)(wfe+1);
00883
00884 DWORD nSamplesPerSec = wfe->nSamplesPerSec;
00885
00886 int profile = (p[0]>>3)-1;
00887 int rate1 = ((p[0]&7)<<1)|(p[1]>>7);
00888 int channels = ((p[1]>>3)&15);
00889 int exttype = 0;
00890 int rate2 = rate1;
00891
00892 if(wfe->cbSize >= 5)
00893 {
00894 profile = 4;
00895
00896 exttype = (p[2]<<3)|(p[3]>>5);
00897 ASSERT(exttype == 0x2B7);
00898 ASSERT((p[3]&31) == 5);
00899 ASSERT((p[4]>>7) == 1);
00900 rate2 = ((p[4]>>3)&15);
00901
00902 if(rate2 < rate1)
00903 {
00904 m_pTE->a.OutputSamplingFrequency.Set((float)nSamplesPerSec);
00905 nSamplesPerSec /= 2;
00906 }
00907 }
00908
00909 switch(profile)
00910 {
00911 default:
00912 case 0: m_pTE->CodecID.Set("A_AAC/MPEG2/MAIN"); break;
00913 case 1: m_pTE->CodecID.Set("A_AAC/MPEG2/LC"); break;
00914 case 2: m_pTE->CodecID.Set("A_AAC/MPEG2/SSR"); break;
00915 case 3: m_pTE->CodecID.Set("A_AAC/MPEG4/LTP"); break;
00916 case 4: m_pTE->CodecID.Set("A_AAC/MPEG4/LC/SBR"); break;
00917 }
00918
00919 ASSERT(channels == wfe->nChannels);
00920
00921 m_pTE->DescType = TrackEntry::DescAudio;
00922 m_pTE->a.SamplingFrequency.Set((float)nSamplesPerSec);
00923 m_pTE->a.Channels.Set(channels);
00924 m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
00925
00926 hr = S_OK;
00927 }
00928 else if(m_mt.formattype == FORMAT_WaveFormatEx
00929 && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_DOLBY_AC3)
00930 {
00931 m_pTE->CodecID.Set("A_AC3");
00932
00933 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
00934 m_pTE->DescType = TrackEntry::DescAudio;
00935 m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
00936 m_pTE->a.Channels.Set(wfe->nChannels);
00937 m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
00938
00939 hr = S_OK;
00940 }
00941 else if(m_mt.formattype == FORMAT_WaveFormatEx
00942 && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_DVD_DTS)
00943 {
00944 m_pTE->CodecID.Set("A_DTS");
00945
00946 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
00947 m_pTE->DescType = TrackEntry::DescAudio;
00948 m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
00949 m_pTE->a.Channels.Set(wfe->nChannels);
00950 m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
00951
00952 hr = S_OK;
00953 }
00954 else if(m_mt.formattype == FORMAT_WaveFormatEx
00955 && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_FLAC)
00956 {
00957 m_pTE->CodecID.Set("A_FLAC");
00958
00959 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
00960 m_pTE->DescType = TrackEntry::DescAudio;
00961 m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
00962 m_pTE->a.Channels.Set(wfe->nChannels);
00963 m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
00964
00965 if(wfe->cbSize)
00966 {
00967 m_pTE->CodecPrivate.SetSize(wfe->cbSize);
00968 memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + sizeof(WAVEFORMATEX), wfe->cbSize);
00969 }
00970
00971 hr = S_OK;
00972 }
00973 else if(m_mt.formattype == FORMAT_WaveFormatEx
00974 && (m_mt.subtype == MEDIASUBTYPE_14_4
00975 || m_mt.subtype == MEDIASUBTYPE_28_8
00976 || m_mt.subtype == MEDIASUBTYPE_ATRC
00977 || m_mt.subtype == MEDIASUBTYPE_COOK
00978 || m_mt.subtype == MEDIASUBTYPE_DNET
00979 || m_mt.subtype == MEDIASUBTYPE_SIPR))
00980 {
00981 CStringA id;
00982 id.Format("A_REAL/%c%c%c%c",
00983 (char)((m_mt.subtype.Data1>>0)&0xff),
00984 (char)((m_mt.subtype.Data1>>8)&0xff),
00985 (char)((m_mt.subtype.Data1>>16)&0xff),
00986 (char)((m_mt.subtype.Data1>>24)&0xff));
00987
00988 m_pTE->CodecID.Set(id);
00989
00990 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
00991 DWORD cbSize = sizeof(WAVEFORMATEX) + wfe->cbSize;
00992 if(m_mt.cbFormat > cbSize)
00993 {
00994 m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - cbSize);
00995 memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + cbSize, m_pTE->CodecPrivate.GetSize());
00996 }
00997 m_pTE->DescType = TrackEntry::DescAudio;
00998 m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
00999 m_pTE->a.Channels.Set(wfe->nChannels);
01000 m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
01001
01002 hr = S_OK;
01003 }
01004 else if(m_mt.formattype == FORMAT_WaveFormatEx
01005 && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_PCM)
01006 {
01007 m_pTE->CodecID.Set("A_PCM/INT/LIT");
01008
01009 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
01010 m_pTE->DescType = TrackEntry::DescAudio;
01011 m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
01012 m_pTE->a.Channels.Set(wfe->nChannels);
01013 m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
01014
01015 hr = S_OK;
01016 }
01017 else if(m_mt.formattype == FORMAT_WaveFormatEx)
01018 {
01019 m_pTE->CodecID.Set("A_MS/ACM");
01020
01021 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
01022 m_pTE->CodecPrivate.SetSize(m_mt.cbFormat);
01023 memcpy(m_pTE->CodecPrivate, wfe, m_pTE->CodecPrivate.GetSize());
01024 m_pTE->DescType = TrackEntry::DescAudio;
01025 m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
01026 m_pTE->a.Channels.Set(wfe->nChannels);
01027 m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
01028
01029 hr = S_OK;
01030 }
01031 else if(m_mt.formattype == FORMAT_VorbisFormat)
01032 {
01033 m_pTE->CodecID.Set("A_VORBIS");
01034
01035 VORBISFORMAT* pvf = (VORBISFORMAT*)m_mt.pbFormat;
01036 m_pTE->DescType = TrackEntry::DescAudio;
01037 m_pTE->a.SamplingFrequency.Set((float)pvf->nSamplesPerSec);
01038 m_pTE->a.Channels.Set(pvf->nChannels);
01039
01040
01041
01042 hr = S_OK;
01043 }
01044 else if(m_mt.formattype == FORMAT_VorbisFormat2)
01045 {
01046 m_pTE->CodecID.Set("A_VORBIS");
01047
01048 VORBISFORMAT2* pvf2 = (VORBISFORMAT2*)m_mt.pbFormat;
01049 m_pTE->DescType = TrackEntry::DescAudio;
01050 m_pTE->a.SamplingFrequency.Set((float)pvf2->SamplesPerSec);
01051 m_pTE->a.Channels.Set(pvf2->Channels);
01052 m_pTE->a.BitDepth.Set(pvf2->BitsPerSample);
01053
01054 int len = 1;
01055 for(int i = 0; i < 2; i++) len += pvf2->HeaderSize[i]/255 + 1;
01056 for(int i = 0; i < 3; i++) len += pvf2->HeaderSize[i];
01057 m_pTE->CodecPrivate.SetSize(len);
01058
01059 BYTE* src = (BYTE*)m_mt.pbFormat + sizeof(VORBISFORMAT2);
01060 BYTE* dst = m_pTE->CodecPrivate.GetData();
01061
01062 *dst++ = 2;
01063 for(int i = 0; i < 2; i++)
01064 for(int len = pvf2->HeaderSize[i]; len >= 0; len -= 255)
01065 *dst++ = min(len, 255);
01066
01067 memcpy(dst, src, pvf2->HeaderSize[0]);
01068 dst += pvf2->HeaderSize[0];
01069 src += pvf2->HeaderSize[0];
01070 memcpy(dst, src, pvf2->HeaderSize[1]);
01071 dst += pvf2->HeaderSize[1];
01072 src += pvf2->HeaderSize[1];
01073 memcpy(dst, src, pvf2->HeaderSize[2]);
01074 dst += pvf2->HeaderSize[2];
01075 src += pvf2->HeaderSize[2];
01076
01077 ASSERT(src <= m_mt.pbFormat + m_mt.cbFormat);
01078 ASSERT(dst <= m_pTE->CodecPrivate.GetData() + m_pTE->CodecPrivate.GetSize());
01079
01080 hr = S_OK;
01081 }
01082 }
01083 else if(m_mt.majortype == MEDIATYPE_Text)
01084 {
01085 m_pTE->TrackType.Set(TrackEntry::TypeSubtitle);
01086
01087 if(m_mt.formattype == FORMAT_None)
01088 {
01089 m_pTE->CodecID.Set("S_TEXT/ASCII");
01090 hr = S_OK;
01091 }
01092 }
01093 else if(m_mt.majortype == MEDIATYPE_Subtitle)
01094 {
01095 m_pTE->TrackType.Set(TrackEntry::TypeSubtitle);
01096
01097 m_pTE->CodecID.Set(
01098 m_mt.subtype == MEDIASUBTYPE_UTF8 ? "S_TEXT/UTF8" :
01099 m_mt.subtype == MEDIASUBTYPE_SSA ? "S_TEXT/SSA" :
01100 m_mt.subtype == MEDIASUBTYPE_ASS ? "S_TEXT/ASS" :
01101 m_mt.subtype == MEDIASUBTYPE_USF ? "S_TEXT/USF" :
01102 m_mt.subtype == MEDIASUBTYPE_VOBSUB ? "S_VOBSUB" :
01103 "");
01104
01105 if(!m_pTE->CodecID.IsEmpty())
01106 {
01107 hr = S_OK;
01108
01109 SUBTITLEINFO* psi = (SUBTITLEINFO*)m_mt.pbFormat;
01110 if(psi->dwOffset)
01111 {
01112 m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - psi->dwOffset);
01113 memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + psi->dwOffset, m_pTE->CodecPrivate.GetSize());
01114 }
01115 }
01116 }
01117
01118 if(S_OK == hr)
01119 {
01120 ((CMatroskaMuxerFilter*)m_pFilter)->AddInput();
01121 }
01122
01123 return hr;
01124 }
01125
01126 HRESULT CMatroskaMuxerInputPin::Active()
01127 {
01128 m_fActive = true;
01129 m_rtLastStart = m_rtLastStop = -1;
01130 m_fEndOfStreamReceived = false;
01131 return __super::Active();
01132 }
01133
01134 HRESULT CMatroskaMuxerInputPin::Inactive()
01135 {
01136 m_fActive = false;
01137 CAutoLock cAutoLock(&m_csQueue);
01138 m_blocks.RemoveAll();
01139 m_pVorbisHdrs.RemoveAll();
01140 return __super::Inactive();
01141 }
01142
01143 STDMETHODIMP CMatroskaMuxerInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
01144 {
01145 CAutoLock cAutoLock(&m_csReceive);
01146 return __super::NewSegment(tStart, tStop, dRate);
01147 }
01148
01149 STDMETHODIMP CMatroskaMuxerInputPin::BeginFlush()
01150 {
01151 return __super::BeginFlush();
01152 }
01153
01154 STDMETHODIMP CMatroskaMuxerInputPin::EndFlush()
01155 {
01156 return __super::EndFlush();
01157 }
01158
01159 STDMETHODIMP CMatroskaMuxerInputPin::Receive(IMediaSample* pSample)
01160 {
01161 if(m_fEndOfStreamReceived) { return S_FALSE;}
01162
01163 CAutoLock cAutoLock(&m_csReceive);
01164
01165 while(m_fActive)
01166 {
01167 {
01168 CAutoLock cAutoLock2(&m_csQueue);
01169 if(m_blocks.GetCount() < MAXBLOCKS)
01170 break;
01171 }
01172
01173 Sleep(1);
01174 }
01175
01176 if(!m_fActive) return S_FALSE;
01177
01178 HRESULT hr;
01179
01180 if(FAILED(hr = __super::Receive(pSample)))
01181 return hr;
01182
01183 BYTE* pData = NULL;
01184 pSample->GetPointer(&pData);
01185
01186 long len = pSample->GetActualDataLength();
01187
01188 REFERENCE_TIME rtStart = -1, rtStop = -1;
01189 hr = pSample->GetTime(&rtStart, &rtStop);
01190
01191 if(FAILED(hr) || rtStart == -1 || rtStop == -1)
01192 {
01193 TRACE(_T("No timestamp was set on the sample!!!"));
01194 m_pFilter->NotifyEvent(EC_ERRORABORT, VFW_E_SAMPLE_TIME_NOT_SET, 0);
01195 return VFW_E_SAMPLE_TIME_NOT_SET;
01196 }
01197
01198
01199
01200
01201
01202 TRACE(_T("Received (%d): %I64d-%I64d (c=%d, co=%dms), len=%d, d%d p%d s%d\n"),
01203 ((CMatroskaMuxerFilter*)m_pFilter)->GetTrackNumber(this),
01204 rtStart, rtStop, (int)((rtStart/10000)/MAXCLUSTERTIME), (int)((rtStart/10000)%MAXCLUSTERTIME),
01205 len,
01206 pSample->IsDiscontinuity() == S_OK ? 1 : 0,
01207 pSample->IsPreroll() == S_OK ? 1 : 0,
01208 pSample->IsSyncPoint() == S_OK ? 1 : 0);
01209
01210 if(m_mt.subtype == MEDIASUBTYPE_Vorbis && m_pVorbisHdrs.GetCount() < 3)
01211 {
01212 CAutoPtr<CBinary> data(new CBinary(0));
01213 data->SetSize(len);
01214 memcpy(data->GetData(), pData, len);
01215 m_pVorbisHdrs.Add(data);
01216
01217 if(m_pVorbisHdrs.GetCount() == 3)
01218 {
01219 int len = 1;
01220 for(int i = 0; i < 2; i++) len += m_pVorbisHdrs[i]->GetSize()/255 + 1;
01221 for(int i = 0; i < 3; i++) len += m_pVorbisHdrs[i]->GetSize();
01222 m_pTE->CodecPrivate.SetSize(len);
01223
01224 BYTE* dst = m_pTE->CodecPrivate.GetData();
01225
01226 *dst++ = 2;
01227 for(int i = 0; i < 2; i++)
01228 for(int len = m_pVorbisHdrs[i]->GetSize(); len >= 0; len -= 255)
01229 *dst++ = min(len, 255);
01230
01231 for(int i = 0; i < 3; i++)
01232 {
01233 memcpy(dst, m_pVorbisHdrs[i]->GetData(), m_pVorbisHdrs[i]->GetSize());
01234 dst += m_pVorbisHdrs[i]->GetSize();
01235 }
01236 }
01237
01238 return S_OK;
01239 }
01240
01241 if(m_mt.formattype == FORMAT_WaveFormatEx
01242 && (((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_PCM
01243 || ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_MPEGLAYER3))
01244 pSample->SetSyncPoint(TRUE);
01245
01246 CAutoPtr<BlockGroup> b(new BlockGroup());
01247
01248
01249
01250
01251
01252
01253
01254
01255 if((S_OK != pSample->IsSyncPoint() || m_rtLastStart == rtStart) && m_rtLastStart >= 0 )
01256 {
01257 ASSERT(m_rtLastStart - rtStart <= 0);
01258 REFERENCE_TIME rtDiff = m_rtLastStart - rtStart;
01259 b->ReferenceBlock.Set((rtDiff + (rtDiff >= 0 ? 5000 : -5000)) / 10000);
01260 }
01261
01262 b->Block.TrackNumber = ((CMatroskaMuxerFilter*)m_pFilter)->GetTrackNumber(this);
01263
01264 b->Block.TimeCode = (rtStart + 5000) / 10000;
01265 b->Block.TimeCodeStop = (rtStop + 5000) / 10000;
01266
01267 if(m_pTE->TrackType == TrackEntry::TypeSubtitle)
01268 {
01269 b->BlockDuration.Set((rtStop - rtStart + 5000) / 10000);
01270 }
01271
01272 CAutoPtr<CBinary> data(new CBinary(0));
01273 data->SetSize(len);
01274 memcpy(data->GetData(), pData, len);
01275 b->Block.BlockData.AddTail(data);
01276
01277 CAutoLock cAutoLock2(&m_csQueue);
01278 m_blocks.AddTail(b);
01279
01280 m_rtLastStart = rtStart;
01281 m_rtLastStop = rtStop;
01282
01283 return S_OK;
01284 }
01285
01286 STDMETHODIMP CMatroskaMuxerInputPin::EndOfStream()
01287 {
01288 HRESULT hr;
01289
01290 if(FAILED(hr = __super::EndOfStream()))
01291 return hr;
01292
01293 CAutoLock cAutoLock(&m_csQueue);
01294
01295 m_fEndOfStreamReceived = true;
01296
01297 return hr;
01298 }
01299
01300
01301
01302
01303
01304 CMatroskaMuxerOutputPin::CMatroskaMuxerOutputPin(TCHAR* pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
01305 : CBaseOutputPin(pName, pFilter, pLock, phr, L"Output")
01306 {
01307 }
01308
01309 CMatroskaMuxerOutputPin::~CMatroskaMuxerOutputPin()
01310 {
01311 }
01312
01313 STDMETHODIMP CMatroskaMuxerOutputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
01314 {
01315 CheckPointer(ppv, E_POINTER);
01316
01317 return
01318 __super::NonDelegatingQueryInterface(riid, ppv);
01319 }
01320
01321 HRESULT CMatroskaMuxerOutputPin::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
01322 {
01323 ASSERT(pAlloc);
01324 ASSERT(pProperties);
01325
01326 HRESULT hr = NOERROR;
01327
01328 pProperties->cBuffers = 1;
01329 pProperties->cbBuffer = 1;
01330
01331 ALLOCATOR_PROPERTIES Actual;
01332 if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
01333
01334 if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
01335 ASSERT(Actual.cBuffers == pProperties->cBuffers);
01336
01337 return NOERROR;
01338 }
01339
01340 HRESULT CMatroskaMuxerOutputPin::CheckMediaType(const CMediaType* pmt)
01341 {
01342 return pmt->majortype == MEDIATYPE_Stream && pmt->subtype == MEDIASUBTYPE_Matroska
01343 ? S_OK
01344 : E_INVALIDARG;
01345 }
01346
01347 HRESULT CMatroskaMuxerOutputPin::GetMediaType(int iPosition, CMediaType* pmt)
01348 {
01349 CAutoLock cAutoLock(m_pLock);
01350
01351 if(iPosition < 0) return E_INVALIDARG;
01352 if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
01353
01354 pmt->ResetFormatBuffer();
01355 pmt->InitMediaType();
01356 pmt->majortype = MEDIATYPE_Stream;
01357 pmt->subtype = MEDIASUBTYPE_Matroska;
01358 pmt->formattype = FORMAT_None;
01359
01360 return S_OK;
01361 }
01362
01363 STDMETHODIMP CMatroskaMuxerOutputPin::Notify(IBaseFilter* pSender, Quality q)
01364 {
01365 return E_NOTIMPL;
01366 }
01367
01368