MatroskaMuxer.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
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); // "DllMain" of the dshow baseclasses;
00074 }
00075 
00076 #endif
00077 
00078 //
00079 // CMatroskaMuxerFilter
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 //              QI(IAMFilterMiscFlags)
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 // IAMFilterMiscFlags
00216 
00217 STDMETHODIMP_(ULONG) CMatroskaMuxerFilter::GetMiscFlags()
00218 {
00219         return AM_FILTER_MISC_FLAGS_IS_RENDERER;
00220 }
00221 
00222 // IMediaSeeking
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 // IMatroskaMuxer 
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         // TODO
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; // when no duration is known, allocate for 24 hours (~340k)
00331         ULONGLONG voidpos = GetStreamPosition(pStream);
00332         {
00333                 Void v(voidlen);
00334                 voidlen = v.Size();
00335                 v.Write(pStream);
00336         }
00337 
00338         // Meta Seek
00339 
00340         Seek seek;
00341         CAutoPtr<SeekHead> sh;
00342 
00343         // Segment Info
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         // Tracks
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         CNode<Track> Tracks;
00369         CAutoPtr<Track> pT(new Track());
00370         POSITION pos = m_pInputs.GetHeadPosition();
00371         for(int i = 1; pos; i++)
00372         {
00373                 CMatroskaMuxerInputPin* pPin = m_pInputs.GetNext(pos);
00374                 if(!pPin->IsConnected()) continue;
00375 
00376                 CAutoPtr<TrackEntry> pTE(new TrackEntry());
00377                 *pTE = *pPin->GetTrackEntry();
00378                 if(TrackNumber == 0 && pTE->TrackType == TrackEntry::TypeVideo) 
00379                         TrackNumber = pTE->TrackNumber;
00380                 pT->TrackEntries.AddTail(pTE);
00381         }
00382         Tracks.AddTail(pT);
00383         Tracks.Write(pStream);
00384 
00385         if(TrackNumber == 0) TrackNumber = 1;
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 TRACE(_T("Muxing (%d): %I64d-%I64d dur=%I64d (c=%d, co=%dms), cnt=%d, ref=%d\n"), 
00524         GetTrackNumber(pPin), 
00525         (INT64)b->Block.TimeCode, (INT64)b->Block.TimeCodeStop, (UINT64)b->BlockDuration,
00526         (int)((b->Block.TimeCode)/MAXCLUSTERTIME), (int)(b->Block.TimeCode%MAXCLUSTERTIME),
00527         b->Block.BlockData.GetCount(), (int)b->ReferenceBlock);
00528 */
00529                                         if(b->Block.TimeCode < SHRT_MIN /*0*/) {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()/*0x1F43B675*/);
00537                                                         sh->Position.Set(GetStreamPosition(pStream) - segpos);
00538                                                         seek.SeekHeads.AddTail(sh);
00539 
00540                                                         c.Write(pStream); // TODO: write blocks
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()/*0x1F43B675*/);
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()/*0x1C53BB6B*/);
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                                 // nothing to do
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                         // TODO: write some tags
00642 
00643                         m_pOutput->DeliverEndOfStream();
00644 
00645                         break;
00646                 }
00647         }
00648 
00649         ASSERT(0); // we should only exit via CMD_EXIT
00650 
00651         CAMThread::m_hThread = NULL;
00652         return 0;
00653 }
00654 
00655 //
00656 // CMatroskaMuxerInputPin
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 //              || pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_MPEG1Payload && pmt->formattype == FORMAT_MPEGVideo
00684 //              || pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_MPEG2_VIDEO && pmt->formattype == FORMAT_MPEG2_VIDEO
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                         // m_pTE->v.DisplayWidth.Set(vih->dwPictAspectRatioX);
00832                         // m_pTE->v.DisplayHeight.Set(vih->dwPictAspectRatioY);
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                 else if(m_mt.formattype == FORMAT_MPEGVideo)
00840                 {
00841                         m_pTE->CodecID.Set("V_DSHOW/MPEG1VIDEO"); // V_MPEG1
00842 
00843                         MPEG1VIDEOINFO* pm1vi = (MPEG1VIDEOINFO*)m_mt.pbFormat;
00844                         m_pTE->CodecPrivate.SetSize(m_mt.FormatLength());
00845                         memcpy(m_pTE->CodecPrivate, m_mt.pbFormat, m_pTE->CodecPrivate.GetSize());
00846                         m_pTE->DefaultDuration.Set(pm1vi->hdr.AvgTimePerFrame*100);
00847                         m_pTE->DescType = TrackEntry::DescVideo;
00848                         m_pTE->v.PixelWidth.Set(pm1vi->hdr.bmiHeader.biWidth);
00849                         m_pTE->v.PixelHeight.Set(abs(pm1vi->hdr.bmiHeader.biHeight));
00850                         if(pm1vi->hdr.AvgTimePerFrame > 0)
00851                                 m_pTE->v.FramePerSec.Set((float)(10000000.0 / pm1vi->hdr.AvgTimePerFrame)); 
00852 
00853                         hr = S_OK;
00854                 }
00855                 else if(m_mt.formattype == FORMAT_MPEG2_VIDEO)
00856                 {
00857                         m_pTE->CodecID.Set("V_DSHOW/MPEG2VIDEO"); // V_MPEG2
00858 
00859                         MPEG2VIDEOINFO* pm2vi = (MPEG2VIDEOINFO*)m_mt.pbFormat;
00860                         m_pTE->CodecPrivate.SetSize(m_mt.FormatLength());
00861                         memcpy(m_pTE->CodecPrivate, m_mt.pbFormat, m_pTE->CodecPrivate.GetSize());
00862                         m_pTE->DefaultDuration.Set(pm2vi->hdr.AvgTimePerFrame*100);
00863                         m_pTE->DescType = TrackEntry::DescVideo;
00864                         m_pTE->v.PixelWidth.Set(pm2vi->hdr.bmiHeader.biWidth);
00865                         m_pTE->v.PixelHeight.Set(abs(pm2vi->hdr.bmiHeader.biHeight));
00866                         if(pm2vi->hdr.AvgTimePerFrame > 0)
00867                                 m_pTE->v.FramePerSec.Set((float)(10000000.0 / pm2vi->hdr.AvgTimePerFrame)); 
00868 
00869                         hr = S_OK;
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                         // m_pTE->CodecPrivate will be filled later
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) {/*ASSERT(0);*/ 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 //      rtStart += m_tStart;
01199 //      rtStop += m_tStart;
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); // HACK: some capture filters don't set this
01245 
01246         CAutoPtr<BlockGroup> b(new BlockGroup());
01247 /*
01248         // TODO: test this with a longer capture (pcm, mp3)
01249         if(S_OK == pSample->IsSyncPoint() && rtStart < m_rtLastStart)
01250         {
01251                 TRACE(_T("!!! timestamp went backwards, dropping this frame !!! rtStart (%I64) < m_rtLastStart (%I64)"), rtStart, m_rtLastStart);
01252                 return S_OK;
01253         }
01254 */
01255         if((S_OK != pSample->IsSyncPoint() || m_rtLastStart == rtStart) && m_rtLastStart >= 0 /*&& m_rtLastStart < rtStart*/)
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); // TODO: lacing for audio
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 // CMatroskaMuxerOutputPin
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 

Generated on Tue Dec 13 14:47:10 2005 for guliverkli by  doxygen 1.4.5