MatroskaMuxer.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:38k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "StdAfx.h"
  22. #include <mmreg.h>
  23. #include "MatroskaMuxer.h"
  24. #include "......DSUtilDSUtil.h"
  25. #include <initguid.h>
  26. #include "........includematroskamatroska.h"
  27. #include "........includeoggOggDS.h"
  28. #include "........includemoreuuids.h"
  29. using namespace MatroskaWriter;
  30. #ifdef REGISTER_FILTER
  31. const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
  32. {
  33. {&MEDIATYPE_Stream, &MEDIASUBTYPE_Matroska}
  34. };
  35. const AMOVIESETUP_PIN sudpPins[] =
  36. {
  37.     {L"Input", FALSE, FALSE, FALSE, TRUE, &CLSID_NULL, NULL, 0, NULL},
  38.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
  39. };
  40. const AMOVIESETUP_FILTER sudFilter[] =
  41. {
  42. {&__uuidof(CMatroskaMuxerFilter), L"Matroska Muxer", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
  43. };
  44. CFactoryTemplate g_Templates[] =
  45. {
  46. {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CMatroskaMuxerFilter>, NULL, &sudFilter[0]}
  47. };
  48. int g_cTemplates = countof(g_Templates);
  49. STDAPI DllRegisterServer()
  50. {
  51. return AMovieDllRegisterServer2(TRUE);
  52. }
  53. STDAPI DllUnregisterServer()
  54. {
  55. return AMovieDllRegisterServer2(FALSE);
  56. }
  57. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  58. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
  59. {
  60.     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
  61. }
  62. #endif
  63. //
  64. // CMatroskaMuxerFilter
  65. //
  66. CMatroskaMuxerFilter::CMatroskaMuxerFilter(LPUNKNOWN pUnk, HRESULT* phr)
  67. : CBaseFilter(NAME("CMatroskaMuxerFilter"), pUnk, this, __uuidof(this))
  68. , m_rtCurrent(0)
  69. , m_fNegative(true), m_fPositive(false)
  70. {
  71. if(phr) *phr = S_OK;
  72. m_pOutput.Attach(new CMatroskaMuxerOutputPin(NAME("CMatroskaMuxerOutputPin"), this, this, phr));
  73. AddInput();
  74. srand(clock());
  75. }
  76. CMatroskaMuxerFilter::~CMatroskaMuxerFilter()
  77. {
  78. CAutoLock cAutoLock(this);
  79. }
  80. STDMETHODIMP CMatroskaMuxerFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  81. {
  82. CheckPointer(ppv, E_POINTER);
  83. *ppv = NULL;
  84. return 
  85. // QI(IAMFilterMiscFlags)
  86. QI(IMediaSeeking)
  87. QI(IMatroskaMuxer)
  88. __super::NonDelegatingQueryInterface(riid, ppv);
  89. }
  90. UINT CMatroskaMuxerFilter::GetTrackNumber(CBasePin* pPin)
  91. {
  92. UINT nTrackNumber = 0;
  93. POSITION pos = m_pInputs.GetHeadPosition();
  94. while(pos)
  95. {
  96. nTrackNumber++;
  97. if(m_pInputs.GetNext(pos) == pPin)
  98. return nTrackNumber;
  99. }
  100. return 0;
  101. }
  102. void CMatroskaMuxerFilter::AddInput()
  103. {
  104. POSITION pos = m_pInputs.GetHeadPosition();
  105. while(pos)
  106. {
  107. CBasePin* pPin = m_pInputs.GetNext(pos);
  108. if(!pPin->IsConnected()) return;
  109. }
  110. CStringW name;
  111. name.Format(L"Track %d", m_pInputs.GetCount()+1);
  112. HRESULT hr;
  113. CAutoPtr<CMatroskaMuxerInputPin> pPin(new CMatroskaMuxerInputPin(name, this, this, &hr));
  114. m_pInputs.AddTail(pPin);
  115. }
  116. int CMatroskaMuxerFilter::GetPinCount()
  117. {
  118. return m_pInputs.GetCount() + (m_pOutput ? 1 : 0);
  119. }
  120. CBasePin* CMatroskaMuxerFilter::GetPin(int n)
  121. {
  122.     CAutoLock cAutoLock(this);
  123. if(n >= 0 && n < (int)m_pInputs.GetCount())
  124. {
  125. if(POSITION pos = m_pInputs.FindIndex(n))
  126. return m_pInputs.GetAt(pos);
  127. }
  128. if(n == m_pInputs.GetCount() && m_pOutput)
  129. {
  130. return m_pOutput;
  131. }
  132. return NULL;
  133. }
  134. STDMETHODIMP CMatroskaMuxerFilter::Stop()
  135. {
  136. CAutoLock cAutoLock(this);
  137. HRESULT hr;
  138. if(FAILED(hr = __super::Stop()))
  139. return hr;
  140. CallWorker(CMD_EXIT);
  141. return hr;
  142. }
  143. STDMETHODIMP CMatroskaMuxerFilter::Pause()
  144. {
  145. CAutoLock cAutoLock(this);
  146. FILTER_STATE fs = m_State;
  147. HRESULT hr;
  148. if(FAILED(hr = __super::Pause()))
  149. return hr;
  150. if(fs == State_Stopped && m_pOutput)
  151. {
  152. CAMThread::Create();
  153. CallWorker(CMD_RUN);
  154. }
  155. return hr;
  156. }
  157. STDMETHODIMP CMatroskaMuxerFilter::Run(REFERENCE_TIME tStart)
  158. {
  159. CAutoLock cAutoLock(this);
  160. HRESULT hr;
  161. if(FAILED(hr = __super::Run(tStart)))
  162. return hr;
  163. return hr;
  164. }
  165. // IAMFilterMiscFlags
  166. STDMETHODIMP_(ULONG) CMatroskaMuxerFilter::GetMiscFlags()
  167. {
  168. return AM_FILTER_MISC_FLAGS_IS_RENDERER;
  169. }
  170. // IMediaSeeking
  171. STDMETHODIMP CMatroskaMuxerFilter::GetCapabilities(DWORD* pCapabilities)
  172. {
  173. return pCapabilities ? *pCapabilities = 
  174. AM_SEEKING_CanGetDuration|
  175. AM_SEEKING_CanGetCurrentPos, S_OK : E_POINTER;
  176. }
  177. STDMETHODIMP CMatroskaMuxerFilter::CheckCapabilities(DWORD* pCapabilities)
  178. {
  179. CheckPointer(pCapabilities, E_POINTER);
  180. if(*pCapabilities == 0) return S_OK;
  181. DWORD caps;
  182. GetCapabilities(&caps);
  183. caps &= *pCapabilities;
  184. return caps == 0 ? E_FAIL : caps == *pCapabilities ? S_OK : S_FALSE;
  185. }
  186. STDMETHODIMP CMatroskaMuxerFilter::IsFormatSupported(const GUID* pFormat) {return !pFormat ? E_POINTER : *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;}
  187. STDMETHODIMP CMatroskaMuxerFilter::QueryPreferredFormat(GUID* pFormat) {return GetTimeFormat(pFormat);}
  188. STDMETHODIMP CMatroskaMuxerFilter::GetTimeFormat(GUID* pFormat) {return pFormat ? *pFormat = TIME_FORMAT_MEDIA_TIME, S_OK : E_POINTER;}
  189. STDMETHODIMP CMatroskaMuxerFilter::IsUsingTimeFormat(const GUID* pFormat) {return IsFormatSupported(pFormat);}
  190. STDMETHODIMP CMatroskaMuxerFilter::SetTimeFormat(const GUID* pFormat) {return S_OK == IsFormatSupported(pFormat) ? S_OK : E_INVALIDARG;}
  191. STDMETHODIMP CMatroskaMuxerFilter::GetDuration(LONGLONG* pDuration)
  192. {
  193. CheckPointer(pDuration, E_POINTER);
  194. *pDuration = 0;
  195. POSITION pos = m_pInputs.GetHeadPosition();
  196. while(pos) {REFERENCE_TIME rt = m_pInputs.GetNext(pos)->m_rtDur; if(rt > *pDuration) *pDuration = rt;}
  197. return S_OK;
  198. }
  199. STDMETHODIMP CMatroskaMuxerFilter::GetStopPosition(LONGLONG* pStop) {return E_NOTIMPL;}
  200. STDMETHODIMP CMatroskaMuxerFilter::GetCurrentPosition(LONGLONG* pCurrent)
  201. {
  202. CheckPointer(pCurrent, E_POINTER);
  203. *pCurrent = m_rtCurrent;
  204. return S_OK;
  205. }
  206. STDMETHODIMP CMatroskaMuxerFilter::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat) {return E_NOTIMPL;}
  207. STDMETHODIMP CMatroskaMuxerFilter::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags) {return E_NOTIMPL;}
  208. STDMETHODIMP CMatroskaMuxerFilter::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop) {return E_NOTIMPL;}
  209. STDMETHODIMP CMatroskaMuxerFilter::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest) {return E_NOTIMPL;}
  210. STDMETHODIMP CMatroskaMuxerFilter::SetRate(double dRate) {return E_NOTIMPL;}
  211. STDMETHODIMP CMatroskaMuxerFilter::GetRate(double* pdRate) {return E_NOTIMPL;}
  212. STDMETHODIMP CMatroskaMuxerFilter::GetPreroll(LONGLONG* pllPreroll) {return E_NOTIMPL;}
  213. // IMatroskaMuxer 
  214. STDMETHODIMP CMatroskaMuxerFilter::CorrectTimeOffset(bool fNegative, bool fPositive)
  215. {
  216. m_fNegative = fNegative;
  217. m_fPositive = fPositive;
  218. return S_OK;
  219. }
  220. //
  221. ULONGLONG GetStreamPosition(IStream* pStream)
  222. {
  223. ULARGE_INTEGER pos = {0, 0};
  224. pStream->Seek(*(LARGE_INTEGER*)&pos, STREAM_SEEK_CUR, &pos);
  225. return pos.QuadPart;
  226. }
  227. ULONGLONG SetStreamPosition(IStream* pStream, ULONGLONG seekpos)
  228. {
  229. LARGE_INTEGER pos;
  230. pos.QuadPart = seekpos;
  231. ULARGE_INTEGER posnew;
  232. posnew.QuadPart = GetStreamPosition(pStream);
  233. pStream->Seek(pos, STREAM_SEEK_SET, &posnew);
  234. return posnew.QuadPart;
  235. }
  236. DWORD CMatroskaMuxerFilter::ThreadProc()
  237. {
  238. CComQIPtr<IStream> pStream;
  239. if(!m_pOutput || !(pStream = m_pOutput->GetConnected()))
  240. {
  241. while(1)
  242. {
  243. DWORD cmd = GetRequest();
  244. if(cmd == CMD_EXIT) CAMThread::m_hThread = NULL;
  245. Reply(S_OK);
  246. if(cmd == CMD_EXIT) return 0;
  247. }
  248. }
  249. REFERENCE_TIME rtDur = 0;
  250. GetDuration(&rtDur);
  251. SetStreamPosition(pStream, 0);
  252. ULARGE_INTEGER uli = {0};
  253. pStream->SetSize(uli);
  254. EBML hdr;
  255. hdr.DocType.Set("matroska");
  256. hdr.DocTypeVersion.Set(1);
  257. hdr.DocTypeReadVersion.Set(1);
  258. hdr.Write(pStream);
  259. Segment().Write(pStream);
  260. ULONGLONG segpos = GetStreamPosition(pStream);
  261. // TODO
  262. QWORD voidlen = 100;
  263. if(rtDur > 0) voidlen += int(1.0 * rtDur / MAXCLUSTERTIME / 10000 + 0.5) * 20;
  264. else voidlen += int(1.0 * 1000*60*60*24 / MAXCLUSTERTIME + 0.5) * 20; // when no duration is known, allocate for 24 hours (~340k)
  265. ULONGLONG voidpos = GetStreamPosition(pStream);
  266. {
  267. Void v(voidlen);
  268. voidlen = v.Size();
  269. v.Write(pStream);
  270. }
  271. // Meta Seek
  272. Seek seek;
  273. CAutoPtr<SeekHead> sh;
  274. // Segment Info
  275. sh.Attach(new SeekHead());
  276. sh->ID.Set(0x1549A966);
  277. sh->Position.Set(GetStreamPosition(pStream) - segpos);
  278. seek.SeekHeads.AddTail(sh);
  279. ULONGLONG infopos = GetStreamPosition(pStream);
  280. Info info;
  281. info.MuxingApp.Set(L"DirectShow Matroska Muxer");
  282. info.TimeCodeScale.Set(1000000);
  283. info.Duration.Set((float)rtDur / 10000);
  284. struct tm _2001 = {0, 0, 0, 1, 0, 101, 0, 0, 1};
  285. info.DateUTC.Set((_time64(NULL) - _mktime64(&_2001)) * 1000000000);
  286. info.Write(pStream);
  287. // Tracks
  288. sh.Attach(new SeekHead());
  289. sh->ID.Set(0x1654AE6B);
  290. sh->Position.Set(GetStreamPosition(pStream) - segpos);
  291. seek.SeekHeads.AddTail(sh);
  292. UINT64 TrackNumber = 0;
  293. /*
  294. CNode<Track> Tracks;
  295. CAutoPtr<Track> pT(new Track());
  296. POSITION pos = m_pInputs.GetHeadPosition();
  297. for(int i = 1; pos; i++)
  298. {
  299. CMatroskaMuxerInputPin* pPin = m_pInputs.GetNext(pos);
  300. if(!pPin->IsConnected()) continue;
  301. CAutoPtr<TrackEntry> pTE(new TrackEntry());
  302. *pTE = *pPin->GetTrackEntry();
  303. if(TrackNumber == 0 && pTE->TrackType == TrackEntry::TypeVideo) 
  304. TrackNumber = pTE->TrackNumber;
  305. pT->TrackEntries.AddTail(pTE);
  306. }
  307. Tracks.AddTail(pT);
  308. Tracks.Write(pStream);
  309. if(TrackNumber == 0) TrackNumber = 1;
  310. */
  311. bool fTracksWritten = false;
  312. //
  313. Cluster c;
  314. c.TimeCode.Set(0);
  315. bool fFirstBlock = true;
  316. INT64 firstTimeCode = 0;
  317. CList<CMatroskaMuxerInputPin*> pActivePins;
  318. POSITION pos = m_pInputs.GetHeadPosition();
  319. while(pos)
  320. {
  321. CMatroskaMuxerInputPin* pPin = m_pInputs.GetNext(pos);
  322. if(pPin->IsConnected()) pActivePins.AddTail(pPin);
  323. }
  324. while(1)
  325. {
  326. DWORD cmd = GetRequest();
  327. switch(cmd)
  328. {
  329. default:
  330. case CMD_EXIT:
  331. CAMThread::m_hThread = NULL;
  332. Reply(S_OK);
  333. return 0;
  334. case CMD_RUN:
  335. Reply(S_OK);
  336. Cue cue;
  337. ULONGLONG lastcueclusterpos = -1;
  338. INT64 lastcuetimecode = -1;
  339. UINT64 nBlocksInCueTrack = 0;
  340. while(!CheckRequest(NULL))
  341. {
  342. if(m_State == State_Paused)
  343. {
  344. Sleep(10);
  345. continue;
  346. }
  347. int nPinsGotSomething = 0, nPinsNeeded = 0;
  348. CMatroskaMuxerInputPin* pPin = NULL;
  349. REFERENCE_TIME rtMin = _I64_MAX;
  350. pos = pActivePins.GetHeadPosition();
  351. while(pos)
  352. {
  353. CMatroskaMuxerInputPin* pTmp = pActivePins.GetNext(pos);
  354. CAutoLock cAutoLock(&pTmp->m_csQueue);
  355. if(pTmp->m_blocks.GetCount() == 0 && pTmp->m_fEndOfStreamReceived)
  356. {
  357. pActivePins.RemoveAt(pActivePins.Find(pTmp));
  358. continue;
  359. }
  360. if(pTmp->GetTrackEntry()->TrackType != TrackEntry::TypeSubtitle)
  361. nPinsNeeded++;
  362. if(pTmp->m_blocks.GetCount() > 0)
  363. {
  364. if(pTmp->GetTrackEntry()->TrackType != TrackEntry::TypeSubtitle)
  365. nPinsGotSomething++;
  366. if(pTmp->m_blocks.GetCount() > 0)
  367. {
  368. REFERENCE_TIME rt = pTmp->m_blocks.GetHead()->Block.TimeCode;
  369. if(rt < rtMin) {rtMin = rt; pPin = pTmp;}
  370. }
  371. }
  372. }
  373. if(pActivePins.GetCount() == 0)
  374. {
  375. break;
  376. }
  377. if(!pPin || nPinsNeeded > nPinsGotSomething || !pPin && nPinsGotSomething == 0)
  378. {
  379. Sleep(1);
  380. continue;
  381. }
  382. if(!fTracksWritten)
  383. {
  384. CNode<Track> Tracks;
  385. CAutoPtr<Track> pT(new Track());
  386. POSITION pos = pActivePins.GetHeadPosition();
  387. for(int i = 1; pos; i++)
  388. {
  389. CMatroskaMuxerInputPin* pPin = pActivePins.GetNext(pos);
  390. CAutoPtr<TrackEntry> pTE(new TrackEntry());
  391. *pTE = *pPin->GetTrackEntry();
  392. if(TrackNumber == 0 && pTE->TrackType == TrackEntry::TypeVideo) 
  393. TrackNumber = pTE->TrackNumber;
  394. pT->TrackEntries.AddTail(pTE);
  395. }
  396. Tracks.AddTail(pT);
  397. Tracks.Write(pStream);
  398. if(TrackNumber == 0) TrackNumber = 1;
  399. fTracksWritten = true;
  400. }
  401. ASSERT(pPin);
  402. CAutoPtr<BlockGroup> b;
  403. {
  404. CAutoLock cAutoLock(&pPin->m_csQueue);
  405. b = pPin->m_blocks.RemoveHead();
  406. }
  407. if(b)
  408. {
  409. if(fFirstBlock)
  410. {
  411. if(b->Block.TimeCode < 0 && m_fNegative || b->Block.TimeCode > 0 && m_fPositive)
  412. firstTimeCode = b->Block.TimeCode;
  413. fFirstBlock = false;
  414. }
  415. b->Block.TimeCode -= firstTimeCode;
  416. b->Block.TimeCodeStop -= firstTimeCode;
  417. /*
  418. TRACE(_T("Muxing (%d): %I64d-%I64d dur=%I64d (c=%d, co=%dms), cnt=%d, ref=%dn"), 
  419. GetTrackNumber(pPin), 
  420. (INT64)b->Block.TimeCode, (INT64)b->Block.TimeCodeStop, (UINT64)b->BlockDuration,
  421. (int)((b->Block.TimeCode)/MAXCLUSTERTIME), (int)(b->Block.TimeCode%MAXCLUSTERTIME),
  422. b->Block.BlockData.GetCount(), (int)b->ReferenceBlock);
  423. */
  424. if(b->Block.TimeCode < SHRT_MIN /*0*/) {ASSERT(0); continue;}
  425. while((INT64)(c.TimeCode + MAXCLUSTERTIME) < b->Block.TimeCode)
  426. {
  427. if(!c.BlockGroups.IsEmpty())
  428. {
  429. sh.Attach(new SeekHead());
  430. sh->ID.Set(c.GetID()/*0x1F43B675*/);
  431. sh->Position.Set(GetStreamPosition(pStream) - segpos);
  432. seek.SeekHeads.AddTail(sh);
  433. c.Write(pStream); // TODO: write blocks
  434. }
  435. c.TimeCode.Set(c.TimeCode + MAXCLUSTERTIME);
  436. c.BlockGroups.RemoveAll();
  437. nBlocksInCueTrack = 0;
  438. }
  439. if(b->Block.TrackNumber == TrackNumber)
  440. {
  441. nBlocksInCueTrack++;
  442. }
  443. if(b->ReferenceBlock == 0 && b->Block.TrackNumber == TrackNumber)
  444. {
  445. ULONGLONG clusterpos = GetStreamPosition(pStream) - segpos;
  446. if(lastcueclusterpos != clusterpos || lastcuetimecode + 1000 < b->Block.TimeCode)
  447. {
  448. CAutoPtr<CueTrackPosition> ctp(new CueTrackPosition());
  449. ctp->CueTrack.Set(b->Block.TrackNumber);
  450. ctp->CueClusterPosition.Set(clusterpos);
  451. if(c.BlockGroups.GetCount() > 0) ctp->CueBlockNumber.Set(nBlocksInCueTrack);
  452. CAutoPtr<CuePoint> cp(new CuePoint());
  453. cp->CueTime.Set(b->Block.TimeCode);
  454. cp->CueTrackPositions.AddTail(ctp);
  455. cue.CuePoints.AddTail(cp);
  456. lastcueclusterpos = clusterpos;
  457. lastcuetimecode = b->Block.TimeCode;
  458. }
  459. }
  460. info.Duration.Set(max(info.Duration, (float)b->Block.TimeCodeStop));
  461. m_rtCurrent = b->Block.TimeCode*10000;
  462. b->Block.TimeCode -= c.TimeCode;
  463. c.BlockGroups.AddTail(b);
  464. }
  465. }
  466. if(!c.BlockGroups.IsEmpty())
  467. {
  468. sh.Attach(new SeekHead());
  469. sh->ID.Set(c.GetID()/*0x1F43B675*/);
  470. sh->Position.Set(GetStreamPosition(pStream) - segpos);
  471. seek.SeekHeads.AddTail(sh);
  472. c.Write(pStream);
  473. }
  474. ULONGLONG cuepos = 0;
  475. if(!cue.CuePoints.IsEmpty())
  476. {
  477. sh.Attach(new SeekHead());
  478. sh->ID.Set(cue.GetID()/*0x1C53BB6B*/);
  479. sh->Position.Set(GetStreamPosition(pStream) - segpos);
  480. seek.SeekHeads.AddTail(sh);
  481. cue.Write(pStream);
  482. }
  483. {
  484. Tags tags;
  485. sh.Attach(new SeekHead());
  486. sh->ID.Set(tags.GetID());
  487. sh->Position.Set(GetStreamPosition(pStream) - segpos);
  488. seek.SeekHeads.AddTail(sh);
  489. tags.Write(pStream);
  490. }
  491. SetStreamPosition(pStream, voidpos);
  492. int len = (int)(voidlen - seek.Size());
  493. ASSERT(len >= 0 && len != 1);
  494. seek.Write(pStream);
  495. if(len == 0)
  496. {
  497. // nothing to do
  498. }
  499. else if(len >= 2)
  500. {
  501. for(int i = 0; i < 8; i++)
  502. {
  503. if(len >= (1<<i*7)-2 && len <= (1<<(i+1)*7)-2)
  504. {
  505. Void(len-2-i).Write(pStream);
  506. break;
  507. }
  508. }
  509. }
  510. if(abs(m_rtCurrent - (REFERENCE_TIME)info.Duration*10000) > 10000000i64)
  511. {
  512. info.Duration.Set(m_rtCurrent / 10000 + 1);
  513. }
  514. SetStreamPosition(pStream, infopos);
  515. info.Write(pStream);
  516. // TODO: write some tags
  517. m_pOutput->DeliverEndOfStream();
  518. break;
  519. }
  520. }
  521. ASSERT(0); // we should only exit via CMD_EXIT
  522. CAMThread::m_hThread = NULL;
  523. return 0;
  524. }
  525. //
  526. // CMatroskaMuxerInputPin
  527. //
  528. CMatroskaMuxerInputPin::CMatroskaMuxerInputPin(LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
  529. : CBaseInputPin(NAME("CMatroskaMuxerInputPin"), pFilter, pLock, phr, pName)
  530. , m_fActive(false)
  531. , m_fEndOfStreamReceived(false)
  532. , m_rtDur(0)
  533. {
  534. }
  535. CMatroskaMuxerInputPin::~CMatroskaMuxerInputPin()
  536. {
  537. }
  538. STDMETHODIMP CMatroskaMuxerInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  539. {
  540. CheckPointer(ppv, E_POINTER);
  541. return 
  542. __super::NonDelegatingQueryInterface(riid, ppv);
  543. }
  544. HRESULT CMatroskaMuxerInputPin::CheckMediaType(const CMediaType* pmt)
  545. {
  546. return pmt->majortype == MEDIATYPE_Video && (pmt->formattype == FORMAT_VideoInfo 
  547. || pmt->formattype == FORMAT_VideoInfo2)
  548. // || pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_MPEG1Payload && pmt->formattype == FORMAT_MPEGVideo
  549. // || pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_MPEG2_VIDEO && pmt->formattype == FORMAT_MPEG2_VIDEO
  550. || pmt->majortype == MEDIATYPE_Video && pmt->subtype == MEDIASUBTYPE_DiracVideo && pmt->formattype == FORMAT_DiracVideoInfo
  551. || pmt->majortype == MEDIATYPE_Audio && pmt->formattype == FORMAT_WaveFormatEx && pmt->subtype == FOURCCMap(((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag)
  552. || pmt->majortype == MEDIATYPE_Audio && pmt->subtype == MEDIASUBTYPE_Vorbis && pmt->formattype == FORMAT_VorbisFormat
  553. || pmt->majortype == MEDIATYPE_Audio && pmt->subtype == MEDIASUBTYPE_Vorbis2 && pmt->formattype == FORMAT_VorbisFormat2
  554. || pmt->majortype == MEDIATYPE_Audio && (pmt->subtype == MEDIASUBTYPE_14_4 
  555. || pmt->subtype == MEDIASUBTYPE_28_8
  556. || pmt->subtype == MEDIASUBTYPE_ATRC
  557. || pmt->subtype == MEDIASUBTYPE_COOK
  558. || pmt->subtype == MEDIASUBTYPE_DNET
  559. || pmt->subtype == MEDIASUBTYPE_SIPR) && pmt->formattype == FORMAT_WaveFormatEx
  560. || pmt->majortype == MEDIATYPE_Text && pmt->subtype == MEDIASUBTYPE_NULL && pmt->formattype == FORMAT_None
  561. || pmt->majortype == MEDIATYPE_Subtitle && pmt->formattype == FORMAT_SubtitleInfo
  562. ? S_OK
  563. : E_INVALIDARG;
  564. }
  565. HRESULT CMatroskaMuxerInputPin::BreakConnect()
  566. {
  567. HRESULT hr;
  568. if(FAILED(hr = __super::BreakConnect()))
  569. return hr;
  570. m_pTE.Free();
  571. return hr;
  572. }
  573. HRESULT CMatroskaMuxerInputPin::CompleteConnect(IPin* pPin)
  574. {
  575. HRESULT hr;
  576. if(FAILED(hr = __super::CompleteConnect(pPin)))
  577. return hr;
  578. m_rtDur = 0;
  579. CComQIPtr<IMediaSeeking> pMS;
  580. if((pMS = GetFilterFromPin(pPin)) || (pMS = pPin))
  581. pMS->GetDuration(&m_rtDur);
  582. m_pTE.Free();
  583. m_pTE.Attach(new TrackEntry());
  584. m_pTE->TrackUID.Set(rand());
  585. m_pTE->MinCache.Set(1);
  586. m_pTE->MaxCache.Set(1);
  587. m_pTE->TrackNumber.Set(((CMatroskaMuxerFilter*)m_pFilter)->GetTrackNumber(this));
  588. hr = E_FAIL;
  589. if(m_mt.majortype == MEDIATYPE_Video)
  590. {
  591. m_pTE->TrackType.Set(TrackEntry::TypeVideo);
  592. if(m_mt.formattype == FORMAT_VideoInfo 
  593. && m_mt.subtype == MEDIASUBTYPE_RV10 || m_mt.subtype == MEDIASUBTYPE_RV20
  594. || m_mt.subtype == MEDIASUBTYPE_RV30 || m_mt.subtype == MEDIASUBTYPE_RV40)
  595. {
  596. m_pTE->CodecID.Set("V_REAL/RV00");
  597. m_pTE->CodecID[9] = (CHAR)(m_mt.subtype.Data1>>16);
  598. if(m_mt.formattype == FORMAT_VideoInfo)
  599. {
  600. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_mt.pbFormat;
  601. if(m_mt.cbFormat > sizeof(VIDEOINFOHEADER))
  602. {
  603. m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - sizeof(VIDEOINFOHEADER));
  604. memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + sizeof(VIDEOINFOHEADER), m_pTE->CodecPrivate.GetSize());
  605. }
  606. m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100); 
  607. m_pTE->DescType = TrackEntry::DescVideo;
  608. m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
  609. m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
  610. if(vih->AvgTimePerFrame > 0)
  611. m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame)); 
  612. }
  613. else if(m_mt.formattype == FORMAT_VideoInfo2)
  614. {
  615. VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)m_mt.pbFormat;
  616. if(m_mt.cbFormat > sizeof(VIDEOINFOHEADER2))
  617. {
  618. m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - sizeof(VIDEOINFOHEADER2));
  619. memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + sizeof(VIDEOINFOHEADER2), m_pTE->CodecPrivate.GetSize());
  620. }
  621. m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100); 
  622. m_pTE->DescType = TrackEntry::DescVideo;
  623. m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
  624. m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
  625. if(vih->AvgTimePerFrame > 0)
  626. m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame)); 
  627. m_pTE->v.DisplayWidth.Set(vih->dwPictAspectRatioX);
  628. m_pTE->v.DisplayHeight.Set(vih->dwPictAspectRatioY);
  629. }
  630. else
  631. {
  632. ASSERT(0);
  633. return hr;
  634. }
  635. hr = S_OK;
  636. }
  637. else if(m_mt.formattype == FORMAT_VideoInfo)
  638. {
  639. m_pTE->CodecID.Set("V_MS/VFW/FOURCC");
  640. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)m_mt.pbFormat;
  641. m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader));
  642. memcpy(m_pTE->CodecPrivate, &vih->bmiHeader, m_pTE->CodecPrivate.GetSize());
  643. m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100); 
  644. m_pTE->DescType = TrackEntry::DescVideo;
  645. m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
  646. m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
  647. if(vih->AvgTimePerFrame > 0)
  648. m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame)); 
  649. hr = S_OK;
  650. }
  651. else if(m_mt.formattype == FORMAT_VideoInfo2)
  652. {
  653. m_pTE->CodecID.Set("V_MS/VFW/FOURCC");
  654. VIDEOINFOHEADER2* vih = (VIDEOINFOHEADER2*)m_mt.pbFormat;
  655. m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader));
  656. memcpy(m_pTE->CodecPrivate, &vih->bmiHeader, m_pTE->CodecPrivate.GetSize());
  657. m_pTE->DefaultDuration.Set(vih->AvgTimePerFrame*100);
  658. m_pTE->DescType = TrackEntry::DescVideo;
  659. m_pTE->v.PixelWidth.Set(vih->bmiHeader.biWidth);
  660. m_pTE->v.PixelHeight.Set(abs(vih->bmiHeader.biHeight));
  661. m_pTE->v.DisplayWidth.Set(vih->dwPictAspectRatioX);
  662. m_pTE->v.DisplayHeight.Set(vih->dwPictAspectRatioY);
  663. if(vih->AvgTimePerFrame > 0)
  664. m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->AvgTimePerFrame)); 
  665. hr = S_OK;
  666. }
  667. else if(m_mt.formattype == FORMAT_DiracVideoInfo)
  668. {
  669. m_pTE->CodecID.Set("V_DIRAC");
  670. DIRACINFOHEADER* vih = (DIRACINFOHEADER*)m_mt.pbFormat;
  671. m_pTE->CodecPrivate.SetSize(vih->cbSequenceHeader);
  672. memcpy(m_pTE->CodecPrivate, (BYTE*)&vih->dwSequenceHeader[0], m_pTE->CodecPrivate.GetSize());
  673. m_pTE->DefaultDuration.Set(vih->hdr.AvgTimePerFrame*100);
  674. m_pTE->DescType = TrackEntry::DescVideo;
  675. m_pTE->v.PixelWidth.Set(vih->hdr.bmiHeader.biWidth);
  676. m_pTE->v.PixelHeight.Set(abs(vih->hdr.bmiHeader.biHeight));
  677. // m_pTE->v.DisplayWidth.Set(vih->dwPictAspectRatioX);
  678. // m_pTE->v.DisplayHeight.Set(vih->dwPictAspectRatioY);
  679. if(vih->hdr.AvgTimePerFrame > 0)
  680. m_pTE->v.FramePerSec.Set((float)(10000000.0 / vih->hdr.AvgTimePerFrame)); 
  681. hr = S_OK;
  682. }
  683. /*
  684. else if(m_mt.formattype == FORMAT_MPEGVideo)
  685. {
  686. m_pTE->CodecID.Set("V_DSHOW/MPEG1VIDEO"); // V_MPEG1
  687. MPEG1VIDEOINFO* pm1vi = (MPEG1VIDEOINFO*)m_mt.pbFormat;
  688. m_pTE->CodecPrivate.SetSize(m_mt.FormatLength());
  689. memcpy(m_pTE->CodecPrivate, m_mt.pbFormat, m_pTE->CodecPrivate.GetSize());
  690. m_pTE->DefaultDuration.Set(pm1vi->hdr.AvgTimePerFrame*100);
  691. m_pTE->DescType = TrackEntry::DescVideo;
  692. m_pTE->v.PixelWidth.Set(pm1vi->hdr.bmiHeader.biWidth);
  693. m_pTE->v.PixelHeight.Set(abs(pm1vi->hdr.bmiHeader.biHeight));
  694. if(pm1vi->hdr.AvgTimePerFrame > 0)
  695. m_pTE->v.FramePerSec.Set((float)(10000000.0 / pm1vi->hdr.AvgTimePerFrame)); 
  696. hr = S_OK;
  697. }
  698. else if(m_mt.formattype == FORMAT_MPEG2_VIDEO)
  699. {
  700. m_pTE->CodecID.Set("V_DSHOW/MPEG2VIDEO"); // V_MPEG2
  701. MPEG2VIDEOINFO* pm2vi = (MPEG2VIDEOINFO*)m_mt.pbFormat;
  702. m_pTE->CodecPrivate.SetSize(m_mt.FormatLength());
  703. memcpy(m_pTE->CodecPrivate, m_mt.pbFormat, m_pTE->CodecPrivate.GetSize());
  704. m_pTE->DefaultDuration.Set(pm2vi->hdr.AvgTimePerFrame*100);
  705. m_pTE->DescType = TrackEntry::DescVideo;
  706. m_pTE->v.PixelWidth.Set(pm2vi->hdr.bmiHeader.biWidth);
  707. m_pTE->v.PixelHeight.Set(abs(pm2vi->hdr.bmiHeader.biHeight));
  708. if(pm2vi->hdr.AvgTimePerFrame > 0)
  709. m_pTE->v.FramePerSec.Set((float)(10000000.0 / pm2vi->hdr.AvgTimePerFrame)); 
  710. hr = S_OK;
  711. }
  712. */
  713. }
  714. else if(m_mt.majortype == MEDIATYPE_Audio)
  715. {
  716. m_pTE->TrackType.Set(TrackEntry::TypeAudio);
  717. if(m_mt.formattype == FORMAT_WaveFormatEx 
  718. && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_AAC
  719. && m_mt.cbFormat >= sizeof(WAVEFORMATEX)+2)
  720. {
  721. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
  722. BYTE* p = (BYTE*)(wfe+1);
  723. DWORD nSamplesPerSec = wfe->nSamplesPerSec;
  724. int profile = (p[0]>>3)-1;
  725. int rate1 = ((p[0]&7)<<1)|(p[1]>>7);
  726. int channels = ((p[1]>>3)&15);
  727. int exttype = 0;
  728. int rate2 = rate1;
  729. if(wfe->cbSize >= 5)
  730. {
  731. profile = 4;
  732. exttype = (p[2]<<3)|(p[3]>>5);
  733. ASSERT(exttype == 0x2B7);
  734. ASSERT((p[3]&31) == 5);
  735. ASSERT((p[4]>>7) == 1);
  736. rate2 = ((p[4]>>3)&15);
  737. if(rate2 < rate1)
  738. {
  739. m_pTE->a.OutputSamplingFrequency.Set((float)nSamplesPerSec);
  740. nSamplesPerSec /= 2;
  741. }
  742. }
  743. switch(profile)
  744. {
  745. default:
  746. case 0: m_pTE->CodecID.Set("A_AAC/MPEG2/MAIN"); break;
  747. case 1: m_pTE->CodecID.Set("A_AAC/MPEG2/LC"); break;
  748. case 2: m_pTE->CodecID.Set("A_AAC/MPEG2/SSR"); break;
  749. case 3: m_pTE->CodecID.Set("A_AAC/MPEG4/LTP"); break;
  750. case 4: m_pTE->CodecID.Set("A_AAC/MPEG4/LC/SBR"); break;
  751. }
  752. ASSERT(channels == wfe->nChannels);
  753. m_pTE->DescType = TrackEntry::DescAudio;
  754. m_pTE->a.SamplingFrequency.Set((float)nSamplesPerSec);
  755. m_pTE->a.Channels.Set(channels);
  756. m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
  757. hr = S_OK;
  758. }
  759. else if(m_mt.formattype == FORMAT_WaveFormatEx 
  760. && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_DOLBY_AC3)
  761. {
  762. m_pTE->CodecID.Set("A_AC3");
  763. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
  764. m_pTE->DescType = TrackEntry::DescAudio;
  765. m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
  766. m_pTE->a.Channels.Set(wfe->nChannels);
  767. m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
  768. hr = S_OK;
  769. }
  770. else if(m_mt.formattype == FORMAT_WaveFormatEx 
  771. && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_DVD_DTS)
  772. {
  773. m_pTE->CodecID.Set("A_DTS");
  774. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
  775. m_pTE->DescType = TrackEntry::DescAudio;
  776. m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
  777. m_pTE->a.Channels.Set(wfe->nChannels);
  778. m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
  779. hr = S_OK;
  780. }
  781. else if(m_mt.formattype == FORMAT_WaveFormatEx
  782. && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_FLAC)
  783. {
  784. m_pTE->CodecID.Set("A_FLAC");
  785. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
  786. m_pTE->DescType = TrackEntry::DescAudio;
  787. m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
  788. m_pTE->a.Channels.Set(wfe->nChannels);
  789. m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
  790. if(wfe->cbSize)
  791. {
  792. m_pTE->CodecPrivate.SetSize(wfe->cbSize);
  793. memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + sizeof(WAVEFORMATEX), wfe->cbSize);
  794. }
  795. hr = S_OK;
  796. }
  797. else if(m_mt.formattype == FORMAT_WaveFormatEx 
  798. && (m_mt.subtype == MEDIASUBTYPE_14_4
  799. || m_mt.subtype == MEDIASUBTYPE_28_8
  800. || m_mt.subtype == MEDIASUBTYPE_ATRC
  801. || m_mt.subtype == MEDIASUBTYPE_COOK
  802. || m_mt.subtype == MEDIASUBTYPE_DNET
  803. || m_mt.subtype == MEDIASUBTYPE_SIPR))
  804. {
  805. CStringA id;
  806. id.Format("A_REAL/%c%c%c%c", 
  807. (char)((m_mt.subtype.Data1>>0)&0xff),
  808. (char)((m_mt.subtype.Data1>>8)&0xff),
  809. (char)((m_mt.subtype.Data1>>16)&0xff),
  810. (char)((m_mt.subtype.Data1>>24)&0xff));
  811. m_pTE->CodecID.Set(id);
  812. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
  813. DWORD cbSize = sizeof(WAVEFORMATEX) + wfe->cbSize;
  814. if(m_mt.cbFormat > cbSize)
  815. {
  816. m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - cbSize);
  817. memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + cbSize, m_pTE->CodecPrivate.GetSize());
  818. }
  819. m_pTE->DescType = TrackEntry::DescAudio;
  820. m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
  821. m_pTE->a.Channels.Set(wfe->nChannels);
  822. m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
  823. hr = S_OK;
  824. }
  825. else if(m_mt.formattype == FORMAT_WaveFormatEx
  826. && ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_PCM)
  827. {
  828. m_pTE->CodecID.Set("A_PCM/INT/LIT");
  829. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
  830. m_pTE->DescType = TrackEntry::DescAudio;
  831. m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
  832. m_pTE->a.Channels.Set(wfe->nChannels);
  833. m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
  834. hr = S_OK;
  835. }
  836. else if(m_mt.formattype == FORMAT_WaveFormatEx)
  837. {
  838. m_pTE->CodecID.Set("A_MS/ACM");
  839. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
  840. m_pTE->CodecPrivate.SetSize(m_mt.cbFormat);
  841. memcpy(m_pTE->CodecPrivate, wfe, m_pTE->CodecPrivate.GetSize());
  842. m_pTE->DescType = TrackEntry::DescAudio;
  843. m_pTE->a.SamplingFrequency.Set((float)wfe->nSamplesPerSec);
  844. m_pTE->a.Channels.Set(wfe->nChannels);
  845. m_pTE->a.BitDepth.Set(wfe->wBitsPerSample);
  846. hr = S_OK;
  847. }
  848. else if(m_mt.formattype == FORMAT_VorbisFormat)
  849. {
  850. m_pTE->CodecID.Set("A_VORBIS");
  851. VORBISFORMAT* pvf = (VORBISFORMAT*)m_mt.pbFormat;
  852. m_pTE->DescType = TrackEntry::DescAudio;
  853. m_pTE->a.SamplingFrequency.Set((float)pvf->nSamplesPerSec);
  854. m_pTE->a.Channels.Set(pvf->nChannels);
  855. // m_pTE->CodecPrivate will be filled later
  856. hr = S_OK;
  857. }
  858. else if(m_mt.formattype == FORMAT_VorbisFormat2)
  859. {
  860. m_pTE->CodecID.Set("A_VORBIS");
  861. VORBISFORMAT2* pvf2 = (VORBISFORMAT2*)m_mt.pbFormat;
  862. m_pTE->DescType = TrackEntry::DescAudio;
  863. m_pTE->a.SamplingFrequency.Set((float)pvf2->SamplesPerSec);
  864. m_pTE->a.Channels.Set(pvf2->Channels);
  865. m_pTE->a.BitDepth.Set(pvf2->BitsPerSample);
  866. int len = 1;
  867. for(int i = 0; i < 2; i++) len += pvf2->HeaderSize[i]/255 + 1;
  868. for(int i = 0; i < 3; i++) len += pvf2->HeaderSize[i];
  869. m_pTE->CodecPrivate.SetSize(len);
  870. BYTE* src = (BYTE*)m_mt.pbFormat + sizeof(VORBISFORMAT2);
  871. BYTE* dst = m_pTE->CodecPrivate.GetData();
  872. *dst++ = 2;
  873. for(int i = 0; i < 2; i++)
  874. for(int len = pvf2->HeaderSize[i]; len >= 0; len -= 255)
  875. *dst++ = min(len, 255);
  876. memcpy(dst, src, pvf2->HeaderSize[0]); 
  877. dst += pvf2->HeaderSize[0]; 
  878. src += pvf2->HeaderSize[0];
  879. memcpy(dst, src, pvf2->HeaderSize[1]); 
  880. dst += pvf2->HeaderSize[1]; 
  881. src += pvf2->HeaderSize[1];
  882. memcpy(dst, src, pvf2->HeaderSize[2]); 
  883. dst += pvf2->HeaderSize[2]; 
  884. src += pvf2->HeaderSize[2];
  885. ASSERT(src <= m_mt.pbFormat + m_mt.cbFormat);
  886. ASSERT(dst <= m_pTE->CodecPrivate.GetData() + m_pTE->CodecPrivate.GetSize());
  887. hr = S_OK;
  888. }
  889. }
  890. else if(m_mt.majortype == MEDIATYPE_Text)
  891. {
  892. m_pTE->TrackType.Set(TrackEntry::TypeSubtitle);
  893. if(m_mt.formattype == FORMAT_None)
  894. {
  895. m_pTE->CodecID.Set("S_TEXT/ASCII");
  896. hr = S_OK;
  897. }
  898. }
  899. else if(m_mt.majortype == MEDIATYPE_Subtitle)
  900. {
  901. m_pTE->TrackType.Set(TrackEntry::TypeSubtitle);
  902. m_pTE->CodecID.Set(
  903. m_mt.subtype == MEDIASUBTYPE_UTF8 ? "S_TEXT/UTF8" :
  904. m_mt.subtype == MEDIASUBTYPE_SSA ? "S_TEXT/SSA" :
  905. m_mt.subtype == MEDIASUBTYPE_ASS ? "S_TEXT/ASS" :
  906. m_mt.subtype == MEDIASUBTYPE_USF ? "S_TEXT/USF" :
  907. m_mt.subtype == MEDIASUBTYPE_VOBSUB ? "S_VOBSUB" :
  908. "");
  909. if(!m_pTE->CodecID.IsEmpty())
  910. {
  911. hr = S_OK;
  912. SUBTITLEINFO* psi = (SUBTITLEINFO*)m_mt.pbFormat;
  913. if(psi->dwOffset)
  914. {
  915. m_pTE->CodecPrivate.SetSize(m_mt.cbFormat - psi->dwOffset);
  916. memcpy(m_pTE->CodecPrivate, m_mt.pbFormat + psi->dwOffset, m_pTE->CodecPrivate.GetSize());
  917. }
  918. }
  919. }
  920. if(S_OK == hr)
  921. {
  922. ((CMatroskaMuxerFilter*)m_pFilter)->AddInput();
  923. }
  924. return hr;
  925. }
  926. HRESULT CMatroskaMuxerInputPin::Active()
  927. {
  928. m_fActive = true;
  929. m_rtLastStart = m_rtLastStop = -1;
  930. m_fEndOfStreamReceived = false;
  931. return __super::Active();
  932. }
  933. HRESULT CMatroskaMuxerInputPin::Inactive()
  934. {
  935. m_fActive = false;
  936. CAutoLock cAutoLock(&m_csQueue);
  937. m_blocks.RemoveAll();
  938. m_pVorbisHdrs.RemoveAll();
  939. return __super::Inactive();
  940. }
  941. STDMETHODIMP CMatroskaMuxerInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  942. {
  943. CAutoLock cAutoLock(&m_csReceive);
  944. return __super::NewSegment(tStart, tStop, dRate);
  945. }
  946. STDMETHODIMP CMatroskaMuxerInputPin::BeginFlush()
  947. {
  948. return __super::BeginFlush();
  949. }
  950. STDMETHODIMP CMatroskaMuxerInputPin::EndFlush()
  951. {
  952. return __super::EndFlush();
  953. }
  954. STDMETHODIMP CMatroskaMuxerInputPin::Receive(IMediaSample* pSample)
  955. {
  956. if(m_fEndOfStreamReceived) {/*ASSERT(0);*/ return S_FALSE;}
  957. CAutoLock cAutoLock(&m_csReceive);
  958. while(m_fActive)
  959. {
  960. {
  961. CAutoLock cAutoLock2(&m_csQueue);
  962. if(m_blocks.GetCount() < MAXBLOCKS)
  963. break;
  964. }
  965. Sleep(1);
  966. }
  967. if(!m_fActive) return S_FALSE;
  968. HRESULT hr;
  969. if(FAILED(hr = __super::Receive(pSample)))
  970. return hr;
  971. BYTE* pData = NULL;
  972. pSample->GetPointer(&pData);
  973. long len = pSample->GetActualDataLength();
  974. REFERENCE_TIME rtStart = -1, rtStop = -1;
  975. hr = pSample->GetTime(&rtStart, &rtStop);
  976. if(FAILED(hr) || rtStart == -1 || rtStop == -1)
  977. {
  978. TRACE(_T("No timestamp was set on the sample!!!"));
  979. m_pFilter->NotifyEvent(EC_ERRORABORT, VFW_E_SAMPLE_TIME_NOT_SET, 0);
  980. return VFW_E_SAMPLE_TIME_NOT_SET;
  981. }
  982. // rtStart += m_tStart;
  983. // rtStop += m_tStart;
  984. /**/
  985. TRACE(_T("Received (%d): %I64d-%I64d (c=%d, co=%dms), len=%d, d%d p%d s%dn"), 
  986. ((CMatroskaMuxerFilter*)m_pFilter)->GetTrackNumber(this), 
  987. rtStart, rtStop, (int)((rtStart/10000)/MAXCLUSTERTIME), (int)((rtStart/10000)%MAXCLUSTERTIME),
  988. len,
  989. pSample->IsDiscontinuity() == S_OK ? 1 : 0,
  990. pSample->IsPreroll() == S_OK ? 1 : 0,
  991. pSample->IsSyncPoint() == S_OK ? 1 : 0);
  992. if(m_mt.subtype == MEDIASUBTYPE_Vorbis && m_pVorbisHdrs.GetCount() < 3)
  993. {
  994. CAutoPtr<CBinary> data(new CBinary(0));
  995. data->SetSize(len);
  996. memcpy(data->GetData(), pData, len);
  997. m_pVorbisHdrs.Add(data);
  998. if(m_pVorbisHdrs.GetCount() == 3)
  999. {
  1000. int len = 1;
  1001. for(int i = 0; i < 2; i++) len += m_pVorbisHdrs[i]->GetSize()/255 + 1;
  1002. for(int i = 0; i < 3; i++) len += m_pVorbisHdrs[i]->GetSize();
  1003. m_pTE->CodecPrivate.SetSize(len);
  1004. BYTE* dst = m_pTE->CodecPrivate.GetData();
  1005. *dst++ = 2;
  1006. for(int i = 0; i < 2; i++)
  1007. for(int len = m_pVorbisHdrs[i]->GetSize(); len >= 0; len -= 255)
  1008. *dst++ = min(len, 255);
  1009. for(int i = 0; i < 3; i++)
  1010. {
  1011. memcpy(dst, m_pVorbisHdrs[i]->GetData(), m_pVorbisHdrs[i]->GetSize());
  1012. dst += m_pVorbisHdrs[i]->GetSize(); 
  1013. }
  1014. }
  1015. return S_OK;
  1016. }
  1017. if(m_mt.formattype == FORMAT_WaveFormatEx 
  1018. && (((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_PCM
  1019. || ((WAVEFORMATEX*)m_mt.pbFormat)->wFormatTag == WAVE_FORMAT_MPEGLAYER3))
  1020. pSample->SetSyncPoint(TRUE); // HACK: some capture filters don't set this
  1021. CAutoPtr<BlockGroup> b(new BlockGroup());
  1022. /*
  1023. // TODO: test this with a longer capture (pcm, mp3)
  1024. if(S_OK == pSample->IsSyncPoint() && rtStart < m_rtLastStart)
  1025. {
  1026. TRACE(_T("!!! timestamp went backwards, dropping this frame !!! rtStart (%I64) < m_rtLastStart (%I64)"), rtStart, m_rtLastStart);
  1027. return S_OK;
  1028. }
  1029. */
  1030. if((S_OK != pSample->IsSyncPoint() || m_rtLastStart == rtStart) && m_rtLastStart >= 0 /*&& m_rtLastStart < rtStart*/)
  1031. {
  1032. ASSERT(m_rtLastStart - rtStart <= 0);
  1033. REFERENCE_TIME rtDiff = m_rtLastStart - rtStart;
  1034. b->ReferenceBlock.Set((rtDiff + (rtDiff >= 0 ? 5000 : -5000)) / 10000);
  1035. }
  1036. b->Block.TrackNumber = ((CMatroskaMuxerFilter*)m_pFilter)->GetTrackNumber(this);
  1037. b->Block.TimeCode = (rtStart + 5000) / 10000;
  1038. b->Block.TimeCodeStop = (rtStop + 5000) / 10000;
  1039. if(m_pTE->TrackType == TrackEntry::TypeSubtitle)
  1040. {
  1041. b->BlockDuration.Set((rtStop - rtStart + 5000) / 10000);
  1042. }
  1043. CAutoPtr<CBinary> data(new CBinary(0));
  1044. data->SetSize(len);
  1045. memcpy(data->GetData(), pData, len);
  1046. b->Block.BlockData.AddTail(data);
  1047. CAutoLock cAutoLock2(&m_csQueue);
  1048. m_blocks.AddTail(b); // TODO: lacing for audio
  1049. m_rtLastStart = rtStart;
  1050. m_rtLastStop = rtStop;
  1051. return S_OK;
  1052. }
  1053. STDMETHODIMP CMatroskaMuxerInputPin::EndOfStream()
  1054. {
  1055. HRESULT hr;
  1056. if(FAILED(hr = __super::EndOfStream()))
  1057. return hr;
  1058. CAutoLock cAutoLock(&m_csQueue);
  1059. m_fEndOfStreamReceived = true;
  1060. return hr;
  1061. }
  1062. //
  1063. // CMatroskaMuxerOutputPin
  1064. //
  1065. CMatroskaMuxerOutputPin::CMatroskaMuxerOutputPin(TCHAR* pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
  1066. : CBaseOutputPin(pName, pFilter, pLock, phr, L"Output")
  1067. {
  1068. }
  1069. CMatroskaMuxerOutputPin::~CMatroskaMuxerOutputPin()
  1070. {
  1071. }
  1072. STDMETHODIMP CMatroskaMuxerOutputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  1073. {
  1074. CheckPointer(ppv, E_POINTER);
  1075. return 
  1076. __super::NonDelegatingQueryInterface(riid, ppv);
  1077. }
  1078. HRESULT CMatroskaMuxerOutputPin::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
  1079. {
  1080.     ASSERT(pAlloc);
  1081.     ASSERT(pProperties);
  1082.     HRESULT hr = NOERROR;
  1083. pProperties->cBuffers = 1;
  1084. pProperties->cbBuffer = 1;
  1085.     ALLOCATOR_PROPERTIES Actual;
  1086.     if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
  1087.     if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
  1088.     ASSERT(Actual.cBuffers == pProperties->cBuffers);
  1089.     return NOERROR;
  1090. }
  1091. HRESULT CMatroskaMuxerOutputPin::CheckMediaType(const CMediaType* pmt)
  1092. {
  1093. return pmt->majortype == MEDIATYPE_Stream && pmt->subtype == MEDIASUBTYPE_Matroska
  1094. ? S_OK
  1095. : E_INVALIDARG;
  1096. }
  1097. HRESULT CMatroskaMuxerOutputPin::GetMediaType(int iPosition, CMediaType* pmt)
  1098. {
  1099.     CAutoLock cAutoLock(m_pLock);
  1100. if(iPosition < 0) return E_INVALIDARG;
  1101. if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
  1102. pmt->ResetFormatBuffer();
  1103. pmt->InitMediaType();
  1104. pmt->majortype = MEDIATYPE_Stream;
  1105. pmt->subtype = MEDIASUBTYPE_Matroska;
  1106. pmt->formattype = FORMAT_None;
  1107. return S_OK;
  1108. }
  1109. STDMETHODIMP CMatroskaMuxerOutputPin::Notify(IBaseFilter* pSender, Quality q)
  1110. {
  1111. return E_NOTIMPL;
  1112. }