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

多媒体编程

开发平台:

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 <Shlwapi.h>
  23. #include <atlpath.h>
  24. #include <mmreg.h>
  25. #include <ks.h>
  26. #include <ksmedia.h>
  27. #include "......DSUtilDSUtil.h"
  28. #include "......DSUtilMediaTypes.h"
  29. #include "RealMediaSplitter.h"
  30. #include "......subtitlesSubtitleInputPin.h"
  31. //
  32. #include <initguid.h>
  33. #include "........includemoreuuids.h"
  34. template<typename T>
  35. static void bswap(T& var)
  36. {
  37. BYTE* s = (BYTE*)&var;
  38. for(BYTE* d = s + sizeof(var)-1; s < d; s++, d--)
  39. *s ^= *d, *d ^= *s, *s ^= *d;
  40. }
  41. void rvinfo::bswap()
  42. {
  43. ::bswap(dwSize);
  44. ::bswap(w); ::bswap(h); ::bswap(bpp);
  45. ::bswap(unk1); ::bswap(fps); 
  46. ::bswap(type1); ::bswap(type2);
  47. }
  48. void rainfo::bswap()
  49. {
  50. ::bswap(version1);
  51. ::bswap(version2);
  52. ::bswap(header_size);
  53. ::bswap(flavor);
  54. ::bswap(coded_frame_size);
  55. ::bswap(sub_packet_h);
  56. ::bswap(frame_size);
  57. ::bswap(sub_packet_size);
  58. }
  59. void rainfo4::bswap()
  60. {
  61. __super::bswap();
  62. ::bswap(sample_rate);
  63. ::bswap(sample_size);
  64. ::bswap(channels);
  65. }
  66. void rainfo5::bswap()
  67. {
  68. __super::bswap();
  69. ::bswap(sample_rate);
  70. ::bswap(sample_size);
  71. ::bswap(channels);
  72. }
  73. using namespace RMFF;
  74. #ifdef REGISTER_FILTER
  75. const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
  76. {
  77. {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL},
  78. };
  79. const AMOVIESETUP_PIN sudpPins[] =
  80. {
  81.     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
  82.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
  83. };
  84. const AMOVIESETUP_MEDIATYPE sudPinTypesIn2[] =
  85. {
  86. {&MEDIATYPE_Video, &MEDIASUBTYPE_RV20},
  87. {&MEDIATYPE_Video, &MEDIASUBTYPE_RV30},
  88. {&MEDIATYPE_Video, &MEDIASUBTYPE_RV40},
  89. {&MEDIATYPE_Video, &MEDIASUBTYPE_RV41},
  90. };
  91. const AMOVIESETUP_MEDIATYPE sudPinTypesOut2[] =
  92. {
  93. {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
  94. };
  95. const AMOVIESETUP_PIN sudpPins2[] =
  96. {
  97.     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn2), sudPinTypesIn2},
  98.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut2), sudPinTypesOut2}
  99. };
  100. const AMOVIESETUP_MEDIATYPE sudPinTypesIn3[] =
  101. {
  102. {&MEDIATYPE_Audio, &MEDIASUBTYPE_14_4},
  103. {&MEDIATYPE_Audio, &MEDIASUBTYPE_28_8},
  104. {&MEDIATYPE_Audio, &MEDIASUBTYPE_ATRC},
  105. {&MEDIATYPE_Audio, &MEDIASUBTYPE_COOK},
  106. {&MEDIATYPE_Audio, &MEDIASUBTYPE_DNET},
  107. {&MEDIATYPE_Audio, &MEDIASUBTYPE_SIPR},
  108. {&MEDIATYPE_Audio, &MEDIASUBTYPE_AAC},
  109. {&MEDIATYPE_Audio, &MEDIASUBTYPE_RAAC},
  110. {&MEDIATYPE_Audio, &MEDIASUBTYPE_RACP},
  111. };
  112. const AMOVIESETUP_MEDIATYPE sudPinTypesOut3[] =
  113. {
  114. {&MEDIATYPE_Audio, &MEDIASUBTYPE_PCM},
  115. };
  116. const AMOVIESETUP_PIN sudpPins3[] =
  117. {
  118.     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn3), sudPinTypesIn3},
  119.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut3), sudPinTypesOut3}
  120. };
  121. const AMOVIESETUP_FILTER sudFilter[] =
  122. {
  123. {&__uuidof(CRealMediaSplitterFilter), L"RealMedia Splitter", MERIT_NORMAL, countof(sudpPins), sudpPins},
  124. {&__uuidof(CRealMediaSourceFilter), L"RealMedia Source", MERIT_NORMAL, 0, NULL},
  125. {&__uuidof(CRealVideoDecoder), L"RealVideo Decoder", MERIT_UNLIKELY, countof(sudpPins2), sudpPins2},
  126. {&__uuidof(CRealAudioDecoder), L"RealAudio Decoder", MERIT_UNLIKELY, countof(sudpPins3), sudpPins3},
  127. };
  128. CFactoryTemplate g_Templates[] =
  129. {
  130. {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CRealMediaSplitterFilter>, NULL, &sudFilter[0]},
  131. {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CRealMediaSourceFilter>, NULL, &sudFilter[1]},
  132.     {sudFilter[2].strName, sudFilter[2].clsID, CreateInstance<CRealVideoDecoder>, NULL, &sudFilter[2]},
  133.     {sudFilter[3].strName, sudFilter[3].clsID, CreateInstance<CRealAudioDecoder>, NULL, &sudFilter[3]},
  134. };
  135. int g_cTemplates = countof(g_Templates);
  136. STDAPI DllRegisterServer()
  137. {
  138. RegisterSourceFilter(
  139. CLSID_AsyncReader, 
  140. MEDIASUBTYPE_RealMedia, 
  141. _T("0,4,,2E524D46"), 
  142. _T(".rm"), _T(".rmvb"), _T(".ram"), NULL);
  143. return AMovieDllRegisterServer2(TRUE);
  144. }
  145. STDAPI DllUnregisterServer()
  146. {
  147. UnRegisterSourceFilter(MEDIASUBTYPE_RealMedia);
  148. return AMovieDllRegisterServer2(FALSE);
  149. }
  150. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  151. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
  152. {
  153.     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
  154. }
  155. #endif
  156. //
  157. // CRealMediaSplitterFilter
  158. //
  159. CRealMediaSplitterFilter::CRealMediaSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
  160. : CBaseSplitterFilter(NAME("CRealMediaSplitterFilter"), pUnk, phr, __uuidof(this))
  161. {
  162. }
  163. CRealMediaSplitterFilter::~CRealMediaSplitterFilter()
  164. {
  165. }
  166. HRESULT CRealMediaSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
  167. {
  168. CheckPointer(pAsyncReader, E_POINTER);
  169. {
  170. DWORD dw;
  171. if(FAILED(pAsyncReader->SyncRead(0, 4, (BYTE*)&dw)) || dw != 'FMR.')
  172. return E_FAIL;
  173. }
  174. HRESULT hr = E_FAIL;
  175. m_pFile.Free();
  176. m_pFile.Attach(new CRMFile(pAsyncReader, hr));
  177. if(!m_pFile) return E_OUTOFMEMORY;
  178. if(FAILED(hr)) {m_pFile.Free(); return hr;}
  179. m_rtNewStart = m_rtCurrent = 0;
  180. m_rtNewStop = m_rtStop = 0;
  181. m_rtStop = 10000i64*m_pFile->m_p.tDuration;
  182. POSITION pos = m_pFile->m_mps.GetHeadPosition();
  183. while(pos)
  184. {
  185. MediaProperies* pmp = m_pFile->m_mps.GetNext(pos);
  186. CStringW name;
  187. name.Format(L"Output %02d", pmp->stream);
  188. if(!pmp->name.IsEmpty()) name += L" (" + CStringW(pmp->name) + L")";
  189. CArray<CMediaType> mts;
  190. CMediaType mt;
  191. mt.SetSampleSize(max(pmp->maxPacketSize*16/**/, 1));
  192. if(pmp->mime == "video/x-pn-realvideo")
  193. {
  194. mt.majortype = MEDIATYPE_Video;
  195. mt.formattype = FORMAT_VideoInfo;
  196. VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER) + pmp->typeSpecData.GetCount());
  197. memset(mt.Format(), 0, mt.FormatLength());
  198. memcpy(pvih + 1, pmp->typeSpecData.GetData(), pmp->typeSpecData.GetCount());
  199. rvinfo rvi = *(rvinfo*)pmp->typeSpecData.GetData();
  200. rvi.bswap();
  201. ASSERT(rvi.dwSize >= FIELD_OFFSET(rvinfo, morewh));
  202. ASSERT(rvi.fcc1 == 'ODIV');
  203. mt.subtype = FOURCCMap(rvi.fcc2);
  204. if(rvi.fps > 0x10000) pvih->AvgTimePerFrame = REFERENCE_TIME(10000000i64 / ((float)rvi.fps/0x10000)); 
  205. pvih->dwBitRate = pmp->avgBitRate; 
  206. pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
  207. pvih->bmiHeader.biWidth = rvi.w;
  208. pvih->bmiHeader.biHeight = rvi.h;
  209. pvih->bmiHeader.biPlanes = 3;
  210. pvih->bmiHeader.biBitCount = rvi.bpp;
  211. pvih->bmiHeader.biCompression = rvi.fcc2;
  212. pvih->bmiHeader.biSizeImage = rvi.w*rvi.h*3/2;
  213. mts.Add(mt);
  214. if(pmp->width > 0 && pmp->height > 0)
  215. {
  216. BITMAPINFOHEADER bmi = pvih->bmiHeader;
  217. mt.formattype = FORMAT_VideoInfo2;
  218. VIDEOINFOHEADER2* pvih2 = (VIDEOINFOHEADER2*)mt.ReallocFormatBuffer(sizeof(VIDEOINFOHEADER2) + pmp->typeSpecData.GetCount());
  219. memset(mt.Format() + FIELD_OFFSET(VIDEOINFOHEADER2, dwInterlaceFlags), 0, mt.FormatLength() - FIELD_OFFSET(VIDEOINFOHEADER2, dwInterlaceFlags));
  220. memcpy(pvih2 + 1, pmp->typeSpecData.GetData(), pmp->typeSpecData.GetCount());
  221. pvih2->bmiHeader = bmi;
  222. pvih2->bmiHeader.biWidth = (DWORD)pmp->width;
  223. pvih2->bmiHeader.biHeight = (DWORD)pmp->height;
  224. pvih2->dwPictAspectRatioX = rvi.w;
  225. pvih2->dwPictAspectRatioY = rvi.h;
  226. mts.InsertAt(0, mt);
  227. }
  228. }
  229. else if(pmp->mime == "audio/x-pn-realaudio")
  230. {
  231. mt.majortype = MEDIATYPE_Audio;
  232. mt.formattype = FORMAT_WaveFormatEx;
  233. mt.bTemporalCompression = 1;
  234. WAVEFORMATEX* pwfe = (WAVEFORMATEX*)mt.AllocFormatBuffer(sizeof(WAVEFORMATEX) + pmp->typeSpecData.GetCount());
  235. memset(mt.Format(), 0, mt.FormatLength());
  236. memcpy(pwfe + 1, pmp->typeSpecData.GetData(), pmp->typeSpecData.GetCount());
  237. union {
  238. DWORD fcc;
  239. char fccstr[5];
  240. };
  241. fcc = 0;
  242. fccstr[4] = 0;
  243. BYTE* fmt = pmp->typeSpecData.GetData();
  244. for(int i = 0; i < pmp->typeSpecData.GetSize()-4; i++, fmt++)
  245. {
  246. if(fmt[0] == '.' || fmt[1] == 'r' || fmt[2] == 'a')
  247. break;
  248. }
  249. rainfo rai = *(rainfo*)fmt;
  250. rai.bswap();
  251. BYTE* extra = NULL;
  252. if(rai.version2 == 4)
  253. {
  254. rainfo4 rai4 = *(rainfo4*)fmt;
  255. rai4.bswap();
  256. pwfe->nChannels = rai4.channels;
  257. pwfe->wBitsPerSample = rai4.sample_size;
  258. pwfe->nSamplesPerSec = rai4.sample_rate;
  259. pwfe->nBlockAlign = rai4.frame_size;
  260. BYTE* p = (BYTE*)((rainfo4*)fmt+1);
  261. int len = *p++; p += len; len = *p++; ASSERT(len == 4);
  262. if(len == 4)
  263. fcc = MAKEFOURCC(p[0],p[1],p[2],p[3]);
  264. extra = p + len + 3;
  265. }
  266. else if(rai.version2 == 5)
  267. {
  268. rainfo5 rai5 = *(rainfo5*)fmt;
  269. rai5.bswap();
  270. pwfe->nChannels = rai5.channels;
  271. pwfe->wBitsPerSample = rai5.sample_size;
  272. pwfe->nSamplesPerSec = rai5.sample_rate;
  273. pwfe->nBlockAlign = rai5.frame_size;
  274. fcc = rai5.fourcc3;
  275. extra = fmt + sizeof(rainfo5) + 4;
  276. }
  277. else
  278. {
  279. continue;
  280. }
  281. _strupr(fccstr);
  282. mt.subtype = FOURCCMap(fcc);
  283. bswap(fcc);
  284. switch(fcc)
  285. {
  286. case '14_4': pwfe->wFormatTag = WAVE_FORMAT_14_4; break;
  287. case '28_8': pwfe->wFormatTag = WAVE_FORMAT_28_8; break;
  288. case 'ATRC': pwfe->wFormatTag = WAVE_FORMAT_ATRC; break;
  289. case 'COOK': pwfe->wFormatTag = WAVE_FORMAT_COOK; break;
  290. case 'DNET': pwfe->wFormatTag = WAVE_FORMAT_DNET; break;
  291. case 'SIPR': pwfe->wFormatTag = WAVE_FORMAT_SIPR; break;
  292. case 'RAAC': pwfe->wFormatTag = WAVE_FORMAT_RAAC; break;
  293. case 'RACP': pwfe->wFormatTag = WAVE_FORMAT_RACP; break;
  294. }
  295. if(pwfe->wFormatTag)
  296. {
  297. mts.Add(mt);
  298. if(fcc == 'DNET')
  299. {
  300. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_DOLBY_AC3); 
  301. mts.InsertAt(0, mt);
  302. }
  303. else if(fcc == 'RAAC' || fcc == 'RACP')
  304. {
  305. mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_AAC); 
  306. int extralen = *(DWORD*)extra; extra += 4;
  307. ::bswap(extralen);
  308. ASSERT(*extra == 2); // always 2? why? what does it mean?
  309. if(*extra == 2)
  310. {
  311. extra++; extralen--;
  312. WAVEFORMATEX* pwfe = (WAVEFORMATEX*)mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + extralen);
  313. pwfe->cbSize = extralen;
  314. memcpy(pwfe + 1, extra, extralen);
  315. }
  316. else
  317. {
  318. WAVEFORMATEX* pwfe = (WAVEFORMATEX*)mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + 5);
  319. pwfe->cbSize = MakeAACInitData((BYTE*)(pwfe+1), 0, pwfe->nSamplesPerSec, pwfe->nChannels);
  320. }
  321. mts.InsertAt(0, mt);
  322. }
  323. }
  324. }
  325. else if(pmp->mime == "logical-fileinfo")
  326. {
  327. CMap<CStringA,LPCSTR,CStringA,LPCSTR> lfi;
  328. CStringA key, value;
  329. BYTE* p = pmp->typeSpecData.GetData();
  330. BYTE* end = p + pmp->typeSpecData.GetCount();
  331. p += 8;
  332. DWORD cnt = p <= end-4 ? *(DWORD*)p : 0; bswap(cnt); p += 4;
  333. if(cnt > 0xffff) // different format?
  334. {
  335. p += 2;
  336. cnt = p <= end-4 ? *(DWORD*)p : 0; bswap(cnt); p += 4;
  337. }
  338. while(p < end-4 && cnt-- > 0)
  339. {
  340. BYTE* base = p;
  341. DWORD len = *(DWORD*)p; bswap(len); p += 4;
  342. if(base + len > end) break;
  343. p++;
  344. WORD keylen = *(WORD*)p; bswap(keylen); p += 2;
  345. memcpy(key.GetBufferSetLength(keylen), p, keylen);
  346. p += keylen;
  347. p+=4;
  348. WORD valuelen = *(WORD*)p; bswap(valuelen); p += 2;
  349. memcpy(value.GetBufferSetLength(valuelen), p, valuelen);
  350. p += valuelen;
  351. ASSERT(p == base + len);
  352. p = base + len;
  353. lfi[key] = value;
  354. }
  355. POSITION pos = lfi.GetStartPosition();
  356. while(pos)
  357. {
  358. lfi.GetNextAssoc(pos, key, value);
  359. int n;
  360. if(key.Find("CHAPTER") == 0 && key.Find("TIME") == key.GetLength()-4
  361. && (n = strtol(key.Mid(7), NULL, 10)) > 0)
  362. {
  363. int h, m, s, ms;
  364. char c;
  365. if(7 != sscanf(value, "%d%c%d%c%d%c%d", &h, &c, &m, &c, &s, &c, &ms))
  366. continue;
  367. key.Format("CHAPTER%02dNAME", n);
  368. if(!lfi.Lookup(key, value) || value.IsEmpty())
  369. value.Format("Chapter %d", n);
  370. ChapAppend(
  371. ((((REFERENCE_TIME)h*60+m)*60+s)*1000+ms)*10000, 
  372. CStringW(CString(value)));
  373. }
  374. }
  375. }
  376. if(mts.IsEmpty())
  377. {
  378. TRACE(_T("Unsupported RealMedia stream (%d): %sn"), pmp->stream, CString(pmp->mime));
  379. continue;
  380. }
  381. HRESULT hr;
  382. CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CRealMediaSplitterOutputPin(mts, name, this, this, &hr));
  383. if(SUCCEEDED(AddOutputPin((DWORD)pmp->stream, pPinOut)))
  384. {
  385. if(!m_rtStop)
  386. m_pFile->m_p.tDuration = max(m_pFile->m_p.tDuration, pmp->tDuration);
  387. }
  388. }
  389. pos = m_pFile->m_subs.GetHeadPosition();
  390. for(DWORD stream = 0; pos; stream++)
  391. {
  392. CRMFile::subtitle& s = m_pFile->m_subs.GetNext(pos);
  393. CStringW name;
  394. name.Format(L"Subtitle %02d", stream);
  395. if(!s.name.IsEmpty()) name += L" (" + CStringW(CString(s.name)) + L")";
  396. CMediaType mt;
  397. mt.SetSampleSize(1);
  398. mt.majortype = MEDIATYPE_Text;
  399. CArray<CMediaType> mts;
  400. mts.Add(mt);
  401. HRESULT hr;
  402. CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CRealMediaSplitterOutputPin(mts, name, this, this, &hr));
  403. AddOutputPin((DWORD)~stream, pPinOut);
  404. }
  405. m_rtDuration = m_rtNewStop = m_rtStop = 10000i64*m_pFile->m_p.tDuration;
  406. SetProperty(L"TITL", CStringW(m_pFile->m_cd.title));
  407. SetProperty(L"AUTH", CStringW(m_pFile->m_cd.author));
  408. SetProperty(L"CPYR", CStringW(m_pFile->m_cd.copyright));
  409. SetProperty(L"DESC", CStringW(m_pFile->m_cd.comment));
  410. return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
  411. }
  412. bool CRealMediaSplitterFilter::DemuxInit()
  413. {
  414. if(!m_pFile) return(false);
  415. // reindex if needed
  416. if(m_pFile->m_irs.GetCount() == 0)
  417. {
  418. m_nOpenProgress = 0;
  419. m_rtDuration = 0;
  420. int stream = m_pFile->GetMasterStream();
  421. UINT32 tLastStart = -1;
  422. UINT32 nPacket = 0;
  423. POSITION pos = m_pFile->m_dcs.GetHeadPosition(); 
  424. while(pos && !m_fAbort)
  425. {
  426. DataChunk* pdc = m_pFile->m_dcs.GetNext(pos);
  427. m_pFile->Seek(pdc->pos);
  428. for(UINT32 i = 0; i < pdc->nPackets && !m_fAbort; i++, nPacket++)
  429. {
  430. UINT64 filepos = m_pFile->GetPos();
  431. HRESULT hr;
  432. MediaPacketHeader mph;
  433. if(S_OK != (hr = m_pFile->Read(mph, false)))
  434. break;
  435. if(mph.stream == stream && (mph.flags&MediaPacketHeader::PN_KEYFRAME_FLAG) && tLastStart != mph.tStart)
  436. {
  437. m_rtDuration = max((__int64)(10000i64*mph.tStart), m_rtDuration);
  438. CAutoPtr<IndexRecord> pir(new IndexRecord());
  439. pir->tStart = mph.tStart;
  440. pir->ptrFilePos = (UINT32)filepos;
  441. pir->packet = nPacket;
  442. m_pFile->m_irs.AddTail(pir);
  443. tLastStart = mph.tStart;
  444. }
  445. m_nOpenProgress = m_pFile->GetPos()*100/m_pFile->GetLength();
  446. DWORD cmd;
  447. if(CheckRequest(&cmd))
  448. {
  449. if(cmd == CMD_EXIT) m_fAbort = true;
  450. else Reply(S_OK);
  451. }
  452. }
  453. }
  454. m_nOpenProgress = 100;
  455. if(m_fAbort) m_pFile->m_irs.RemoveAll();
  456. m_fAbort = false;
  457. }
  458. m_seekpos = NULL;
  459. m_seekpacket = 0;
  460. m_seekfilepos = 0;
  461. return(true);
  462. }
  463. void CRealMediaSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
  464. {
  465. if(rt <= 0)
  466. {
  467. m_seekpos = m_pFile->m_dcs.GetHeadPosition(); 
  468. m_seekpacket = 0;
  469. m_seekfilepos = m_pFile->m_dcs.GetHead()->pos;
  470. }
  471. else
  472. {
  473. m_seekpos = NULL; 
  474. POSITION pos = m_pFile->m_irs.GetTailPosition();
  475. while(pos && !m_seekpos)
  476. {
  477. IndexRecord* pir = m_pFile->m_irs.GetPrev(pos);
  478. if(pir->tStart <= rt/10000)
  479. {
  480. m_seekpacket = pir->packet;
  481. pos = m_pFile->m_dcs.GetTailPosition();
  482. while(pos && !m_seekpos)
  483. {
  484. POSITION tmp = pos;
  485. DataChunk* pdc = m_pFile->m_dcs.GetPrev(pos);
  486. if(pdc->pos <= pir->ptrFilePos)
  487. {
  488. m_seekpos = tmp;
  489. m_seekfilepos = pir->ptrFilePos;
  490. POSITION pos = m_pFile->m_dcs.GetHeadPosition();
  491. while(pos != m_seekpos)
  492. {
  493. m_seekpacket -= m_pFile->m_dcs.GetNext(pos)->nPackets;
  494. }
  495. }
  496. }
  497. // search the closest keyframe to the seek time (commented out 'cause rm seems to index all of its keyframes...)
  498. /*
  499. if(m_seekpos)
  500. {
  501. DataChunk* pdc = m_pFile->m_dcs.GetAt(m_seekpos);
  502. m_pFile->Seek(m_seekfilepos);
  503. REFERENCE_TIME seektime = -1;
  504. UINT32 seekstream = -1;
  505. for(UINT32 i = m_seekpacket; i < pdc->nPackets; i++)
  506. {
  507. UINT64 filepos = m_pFile->GetPos();
  508. MediaPacketHeader mph;
  509. if(S_OK != m_pFile->Read(mph, false))
  510. break;
  511. if(seekstream == -1) seekstream = mph.stream;
  512. if(seekstream != mph.stream) continue;
  513. if(seektime == 10000i64*mph.tStart) continue;
  514. if(rt < 10000i64*mph.tStart) break;
  515. if((mph.flags&MediaPacketHeader::PN_KEYFRAME_FLAG))
  516. {
  517. m_seekpacket = i;
  518. m_seekfilepos = filepos;
  519. seektime = 10000i64*mph.tStart;
  520. }
  521. }
  522. }
  523. */
  524. }
  525. }
  526. if(!m_seekpos)
  527. {
  528. m_seekpos = m_pFile->m_dcs.GetHeadPosition(); 
  529. m_seekpacket = 0;
  530. m_seekfilepos = m_pFile->m_dcs.GetAt(m_seekpos)->pos;
  531. }
  532. }
  533. }
  534. bool CRealMediaSplitterFilter::DemuxLoop()
  535. {
  536. HRESULT hr = S_OK;
  537. POSITION pos;
  538. pos = m_pFile->m_subs.GetHeadPosition();
  539. for(DWORD stream = 0; pos && SUCCEEDED(hr) && !CheckRequest(NULL); stream++)
  540. {
  541. CRMFile::subtitle& s = m_pFile->m_subs.GetNext(pos);
  542. CAutoPtr<Packet> p(new Packet);
  543. p->TrackNumber = ~stream;
  544. p->bSyncPoint = TRUE;
  545. p->rtStart = 0;
  546. p->rtStop = 1;
  547. p->pData.SetSize((4+1) + (2+4+(s.name.GetLength()+1)*2) + (2+4+s.data.GetLength()));
  548. BYTE* ptr = p->pData.GetData();
  549. strcpy((char*)ptr, "GAB2"); ptr += 4+1;
  550. *(WORD*)ptr = 2; ptr += 2;
  551. *(DWORD*)ptr = (s.name.GetLength()+1)*2; ptr += 4;
  552. wcscpy((WCHAR*)ptr, CStringW(s.name)); ptr += (s.name.GetLength()+1)*2;
  553. *(WORD*)ptr = 4; ptr += 2;
  554. *(DWORD*)ptr = s.data.GetLength(); ptr += 4;
  555. memcpy((char*)ptr, s.data, s.data.GetLength()); ptr += s.name.GetLength();
  556. hr = DeliverPacket(p);
  557. }
  558. pos = m_seekpos; 
  559. while(pos && SUCCEEDED(hr) && !CheckRequest(NULL))
  560. {
  561. DataChunk* pdc = m_pFile->m_dcs.GetNext(pos);
  562. m_pFile->Seek(m_seekfilepos > 0 ? m_seekfilepos : pdc->pos);
  563. for(UINT32 i = m_seekpacket; i < pdc->nPackets && SUCCEEDED(hr) && !CheckRequest(NULL); i++)
  564. {
  565. MediaPacketHeader mph;
  566. if(S_OK != (hr = m_pFile->Read(mph)))
  567. break;
  568. CAutoPtr<Packet> p(new Packet);
  569. p->TrackNumber = mph.stream;
  570. p->bSyncPoint = !!(mph.flags&MediaPacketHeader::PN_KEYFRAME_FLAG);
  571. p->rtStart = 10000i64*(mph.tStart);
  572. p->rtStop = p->rtStart+1;
  573. p->pData.Copy(mph.pData);
  574. hr = DeliverPacket(p);
  575. }
  576. m_seekpacket = 0;
  577. m_seekfilepos = 0;
  578. }
  579. return(true);
  580. }
  581. // IKeyFrameInfo
  582. STDMETHODIMP CRealMediaSplitterFilter::GetKeyFrameCount(UINT& nKFs)
  583. {
  584. if(!m_pFile) return E_UNEXPECTED;
  585. nKFs = m_pFile->m_irs.GetCount();
  586. return S_OK;
  587. }
  588. STDMETHODIMP CRealMediaSplitterFilter::GetKeyFrames(const GUID* pFormat, REFERENCE_TIME* pKFs, UINT& nKFs)
  589. {
  590. CheckPointer(pFormat, E_POINTER);
  591. CheckPointer(pKFs, E_POINTER);
  592. if(!m_pFile) return E_UNEXPECTED;
  593. if(*pFormat != TIME_FORMAT_MEDIA_TIME) return E_INVALIDARG;
  594. UINT nKFsTmp = 0;
  595. POSITION pos = m_pFile->m_irs.GetHeadPosition();
  596. for(int i = 0; pos && nKFsTmp < nKFs; i++)
  597. pKFs[nKFsTmp++] = 10000i64*m_pFile->m_irs.GetNext(pos)->tStart;
  598. nKFs = nKFsTmp;
  599. return S_OK;
  600. }
  601. //
  602. // CRealMediaSplitterOutputPin
  603. //
  604. CRealMediaSplitterOutputPin::CRealMediaSplitterOutputPin(CArray<CMediaType>& mts, LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
  605. : CBaseSplitterOutputPin(mts, pName, pFilter, pLock, phr)
  606. {
  607. }
  608. CRealMediaSplitterOutputPin::~CRealMediaSplitterOutputPin()
  609. {
  610. }
  611. HRESULT CRealMediaSplitterOutputPin::DeliverEndFlush()
  612. {
  613. {
  614. CAutoLock cAutoLock(&m_csQueue);
  615. m_segments.Clear();
  616. }
  617. return __super::DeliverEndFlush();
  618. }
  619. HRESULT CRealMediaSplitterOutputPin::DeliverSegments()
  620. {
  621. HRESULT hr;
  622. if(m_segments.GetCount() == 0)
  623. {
  624. m_segments.Clear();
  625. return S_OK;
  626. }
  627. CAutoPtr<Packet> p(new Packet());
  628. p->TrackNumber = -1;
  629. p->bDiscontinuity = m_segments.fDiscontinuity;
  630. p->bSyncPoint = m_segments.fSyncPoint;
  631. p->rtStart = m_segments.rtStart;
  632. p->rtStop = m_segments.rtStart+1;
  633. DWORD len = 0, total = 0;
  634. POSITION pos = m_segments.GetHeadPosition();
  635. while(pos)
  636. {
  637. segment* s = m_segments.GetNext(pos);
  638. len = max(len, s->offset + s->data.GetCount());
  639. total += s->data.GetCount();
  640. }
  641. ASSERT(len == total);
  642. len += 1 + 2*4*(!m_segments.fMerged ? m_segments.GetCount() : 1);
  643. p->pData.SetSize(len);
  644. BYTE* pData = p->pData.GetData();
  645. *pData++ = m_segments.fMerged ? 0 : m_segments.GetCount()-1;
  646. if(m_segments.fMerged)
  647. {
  648. *((DWORD*)pData) = 1; pData += 4;
  649. *((DWORD*)pData) = 0; pData += 4;
  650. }
  651. else
  652. {
  653. pos = m_segments.GetHeadPosition();
  654. while(pos)
  655. {
  656. *((DWORD*)pData) = 1; pData += 4;
  657. *((DWORD*)pData) = m_segments.GetNext(pos)->offset; pData += 4;
  658. }
  659. }
  660. pos = m_segments.GetHeadPosition();
  661. while(pos)
  662. {
  663. segment* s = m_segments.GetNext(pos);
  664. memcpy(pData + s->offset, s->data.GetData(), s->data.GetCount());
  665. }
  666. hr = __super::DeliverPacket(p);
  667. m_segments.Clear();
  668. return hr;
  669. }
  670. HRESULT CRealMediaSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p)
  671. {
  672. HRESULT hr = S_OK;
  673. ASSERT(p->rtStart < p->rtStop);
  674. if(m_mt.subtype == MEDIASUBTYPE_WAVE_DOLBY_AC3)
  675. {
  676. WORD* s = (WORD*)p->pData.GetData();
  677. WORD* e = s + p->pData.GetSize()/2;
  678. while(s < e) bswap(*s++);
  679. }
  680. if(m_mt.subtype == MEDIASUBTYPE_RV10 || m_mt.subtype == MEDIASUBTYPE_RV20
  681. || m_mt.subtype == MEDIASUBTYPE_RV30 || m_mt.subtype == MEDIASUBTYPE_RV40
  682. || m_mt.subtype == MEDIASUBTYPE_RV41)
  683. {
  684. CAutoLock cAutoLock(&m_csQueue);
  685. int len = p->pData.GetCount();
  686. BYTE* pIn = p->pData.GetData();
  687. BYTE* pInOrg = pIn;
  688. if(m_segments.rtStart != p->rtStart)
  689. {
  690. if(S_OK != (hr = DeliverSegments()))
  691. return hr;
  692. }
  693. if(!m_segments.fDiscontinuity && p->bDiscontinuity)
  694. m_segments.fDiscontinuity = true;
  695. m_segments.fSyncPoint = !!p->bSyncPoint;
  696. m_segments.rtStart = p->rtStart;
  697. while(pIn - pInOrg < len)
  698. {
  699. BYTE hdr = *pIn++, subseq = 0, seqnum = 0;
  700. DWORD packetlen = 0, packetoffset = 0;
  701. if((hdr&0xc0) == 0x40)
  702. {
  703. pIn++;
  704. packetlen = len - (pIn - pInOrg);
  705. }
  706. else
  707. {
  708. if((hdr&0x40) == 0)
  709. subseq = (*pIn++)&0x7f;
  710. #define GetWORD(var) 
  711. var = (var<<8)|(*pIn++); 
  712. var = (var<<8)|(*pIn++); 
  713. GetWORD(packetlen);
  714. if(packetlen&0x8000) m_segments.fMerged = true;
  715. if((packetlen&0x4000) == 0) {GetWORD(packetlen); packetlen &= 0x3fffffff;}
  716. else packetlen &= 0x3fff;
  717. GetWORD(packetoffset);
  718. if((packetoffset&0x4000) == 0) {GetWORD(packetoffset); packetoffset &= 0x3fffffff;}
  719. else packetoffset &= 0x3fff;
  720. #undef GetWORD
  721. if((hdr&0xc0) == 0xc0)
  722. m_segments.rtStart = 10000i64*packetoffset - m_rtStart, packetoffset = 0;
  723. else if((hdr&0xc0) == 0x80)
  724. packetoffset = packetlen - packetoffset;
  725. seqnum = *pIn++;
  726. }
  727.             int len2 = min(len - (pIn - pInOrg), packetlen - packetoffset);
  728. CAutoPtr<segment> s(new segment);
  729. s->offset = packetoffset;
  730. s->data.SetSize(len2);
  731. memcpy(s->data.GetData(), pIn, len2);
  732. m_segments.AddTail(s);
  733. pIn += len2;
  734. if((hdr&0x80) || packetoffset+len2 >= packetlen)
  735. {
  736.     if(S_OK != (hr = DeliverSegments()))
  737. return hr;
  738. }
  739. }
  740. }
  741. else if(m_mt.subtype == MEDIASUBTYPE_RAAC || m_mt.subtype == MEDIASUBTYPE_RACP
  742.  || m_mt.subtype == MEDIASUBTYPE_AAC)
  743. {
  744. BYTE* ptr = p->pData.GetData()+2;
  745. CList<WORD> sizes;
  746. int total = 0;
  747. int remaining = p->pData.GetSize()-2;
  748. int expected = *(ptr-1)>>4;
  749. while(total < remaining)
  750. {
  751. int size = (ptr[0]<<8)|(ptr[1]);
  752. sizes.AddTail(size);
  753. total += size;
  754. ptr += 2;
  755. remaining -= 2;
  756. expected--;
  757. }
  758. ASSERT(total == remaining);
  759. ASSERT(expected == 0);
  760. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
  761. REFERENCE_TIME rtDur = 10240000000i64/wfe->nSamplesPerSec * (wfe->cbSize>2?2:1);
  762. REFERENCE_TIME rtStart = p->rtStart;
  763. BOOL bDiscontinuity = p->bDiscontinuity;
  764. POSITION pos = sizes.GetHeadPosition();
  765. while(pos)
  766. {
  767. CAutoPtr<Packet> p(new Packet);
  768. p->bDiscontinuity = bDiscontinuity;
  769. p->bSyncPoint = true;
  770. p->rtStart = rtStart;
  771. p->rtStop = rtStart + rtDur;
  772. p->pData.SetSize(sizes.GetNext(pos));
  773. memcpy(p->pData.GetData(), ptr, p->pData.GetSize());
  774. ptr += p->pData.GetSize();
  775. rtStart = p->rtStop;
  776. bDiscontinuity = false;
  777. if(S_OK != (hr = __super::DeliverPacket(p)))
  778. break;
  779. }
  780. }
  781. else
  782. {
  783. hr = __super::DeliverPacket(p);
  784. }
  785. return hr;
  786. }
  787. //
  788. // CRealMediaSourceFilter
  789. //
  790. CRealMediaSourceFilter::CRealMediaSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
  791. : CRealMediaSplitterFilter(pUnk, phr)
  792. {
  793. m_clsid = __uuidof(this);
  794. m_pInput.Free();
  795. }
  796. //
  797. // CRMFile
  798. //
  799. CRMFile::CRMFile(IAsyncReader* pAsyncReader, HRESULT& hr)
  800. : CBaseSplitterFile(pAsyncReader, hr)
  801. {
  802. if(FAILED(hr)) return;
  803. hr = Init();
  804. }
  805. template<typename T> 
  806. HRESULT CRMFile::Read(T& var)
  807. {
  808. HRESULT hr = Read((BYTE*)&var, sizeof(var));
  809. bswap(var);
  810. return hr;
  811. }
  812. HRESULT CRMFile::Read(ChunkHdr& hdr)
  813. {
  814. memset(&hdr, 0, sizeof(hdr));
  815. HRESULT hr;
  816. if(S_OK != (hr = Read(hdr.object_id))
  817. || S_OK != (hr = Read(hdr.size))
  818. || S_OK != (hr = Read(hdr.object_version)))
  819. return hr;
  820. return S_OK;
  821. }
  822. HRESULT CRMFile::Read(MediaPacketHeader& mph, bool fFull)
  823. {
  824. memset(&mph, 0, FIELD_OFFSET(MediaPacketHeader, pData));
  825. mph.stream = -1;
  826. HRESULT hr;
  827. UINT16 object_version;
  828. if(S_OK != (hr = Read(object_version))) return hr;
  829. if(object_version != 0 && object_version != 1) return S_OK;
  830. UINT8 flags;
  831. if(S_OK != (hr = Read(mph.len))
  832. || S_OK != (hr = Read(mph.stream))
  833. || S_OK != (hr = Read(mph.tStart))
  834. || S_OK != (hr = Read(mph.reserved))
  835. || S_OK != (hr = Read(flags)))
  836. return hr;
  837. mph.flags = (MediaPacketHeader::flag_t)flags;
  838. LONG len = mph.len;
  839. len -= sizeof(object_version);
  840. len -= FIELD_OFFSET(MediaPacketHeader, flags);
  841. len -= sizeof(flags);
  842. ASSERT(len >= 0);
  843. len = max(len, 0);
  844. if(fFull)
  845. {
  846. mph.pData.SetSize(len);
  847. if(mph.len > 0 && S_OK != (hr = Read(mph.pData.GetData(), len)))
  848. return hr;
  849. }
  850. else
  851. {
  852. Seek(GetPos() + len);
  853. }
  854. return S_OK;
  855. }
  856. HRESULT CRMFile::Init()
  857. {
  858. Seek(0);
  859. bool fFirstChunk = true;
  860. HRESULT hr;
  861. ChunkHdr hdr;
  862. while(GetPos() < GetLength() && S_OK == (hr = Read(hdr)))
  863. {
  864. __int64 pos = GetPos() - sizeof(hdr);
  865. if(fFirstChunk && hdr.object_id != '.RMF')
  866. return E_FAIL;
  867. fFirstChunk = false;
  868. if(pos + hdr.size > GetLength() && hdr.object_id != 'DATA') // truncated?
  869. break;
  870. if(hdr.object_id == 0x2E7261FD) // '.ra+0xFD'
  871. return E_FAIL;
  872. if(hdr.object_version == 0)
  873. {
  874. switch(hdr.object_id)
  875. {
  876. case '.RMF':
  877. if(S_OK != (hr = Read(m_fh.version))) return hr;
  878. if(hdr.size == 0x10) {WORD w = 0; if(S_OK != (hr = Read(w))) return hr; m_fh.nHeaders = w;}
  879. else if(S_OK != (hr = Read(m_fh.nHeaders))) return hr;
  880. break;
  881. case 'CONT':
  882. UINT16 slen;
  883. if(S_OK != (hr = Read(slen))) return hr;
  884. if(slen > 0 && S_OK != (hr = Read((BYTE*)m_cd.title.GetBufferSetLength(slen), slen))) return hr;
  885. if(S_OK != (hr = Read(slen))) return hr;
  886. if(slen > 0 && S_OK != (hr = Read((BYTE*)m_cd.author.GetBufferSetLength(slen), slen))) return hr;
  887. if(S_OK != (hr = Read(slen))) return hr;
  888. if(slen > 0 && S_OK != (hr = Read((BYTE*)m_cd.copyright.GetBufferSetLength(slen), slen))) return hr;
  889. if(S_OK != (hr = Read(slen))) return hr;
  890. if(slen > 0 && S_OK != (hr = Read((BYTE*)m_cd.comment.GetBufferSetLength(slen), slen))) return hr;
  891. break;
  892. case 'PROP':
  893. if(S_OK != (hr = Read(m_p.maxBitRate))) return hr;
  894. if(S_OK != (hr = Read(m_p.avgBitRate))) return hr;
  895. if(S_OK != (hr = Read(m_p.maxPacketSize))) return hr;
  896. if(S_OK != (hr = Read(m_p.avgPacketSize))) return hr;
  897. if(S_OK != (hr = Read(m_p.nPackets))) return hr;
  898. if(S_OK != (hr = Read(m_p.tDuration))) return hr;
  899. if(S_OK != (hr = Read(m_p.tPreroll))) return hr;
  900. if(S_OK != (hr = Read(m_p.ptrIndex))) return hr;
  901. if(S_OK != (hr = Read(m_p.ptrData))) return hr;
  902. if(S_OK != (hr = Read(m_p.nStreams))) return hr;
  903. UINT16 flags;
  904. if(S_OK != (hr = Read(flags))) return hr;
  905. m_p.flags = (Properies::flags_t)flags;
  906. break;
  907. case 'MDPR':
  908. {
  909. CAutoPtr<MediaProperies> mp(new MediaProperies);
  910. if(S_OK != (hr = Read(mp->stream))) return hr;
  911. if(S_OK != (hr = Read(mp->maxBitRate))) return hr;
  912. if(S_OK != (hr = Read(mp->avgBitRate))) return hr;
  913. if(S_OK != (hr = Read(mp->maxPacketSize))) return hr;
  914. if(S_OK != (hr = Read(mp->avgPacketSize))) return hr;
  915. if(S_OK != (hr = Read(mp->tStart))) return hr;
  916. if(S_OK != (hr = Read(mp->tPreroll))) return hr;
  917. if(S_OK != (hr = Read(mp->tDuration))) return hr;
  918. UINT8 slen;
  919. if(S_OK != (hr = Read(slen))) return hr;
  920. if(slen > 0 && S_OK != (hr = Read((BYTE*)mp->name.GetBufferSetLength(slen), slen))) return hr;
  921. if(S_OK != (hr = Read(slen))) return hr;
  922. if(slen > 0 && S_OK != (hr = Read((BYTE*)mp->mime.GetBufferSetLength(slen), slen))) return hr;
  923. UINT32 tsdlen;
  924. if(S_OK != (hr = Read(tsdlen))) return hr;
  925. mp->typeSpecData.SetSize(tsdlen);
  926. if(tsdlen > 0 && S_OK != (hr = Read(mp->typeSpecData.GetData(), tsdlen))) return hr;
  927. mp->width = mp->height = 0;
  928. mp->interlaced = mp->top_field_first = false;
  929. m_mps.AddTail(mp);
  930. break;
  931. }
  932. case 'DATA':
  933. {
  934. CAutoPtr<DataChunk> dc(new DataChunk);
  935. if(S_OK != (hr = Read(dc->nPackets))) return hr;
  936. if(S_OK != (hr = Read(dc->ptrNext))) return hr;
  937. dc->pos = GetPos();
  938. m_dcs.AddTail(dc);
  939.                 GetDimensions();
  940. break;
  941. }
  942. case 'INDX':
  943. {
  944. IndexChunkHeader ich;
  945. if(S_OK != (hr = Read(ich.nIndices))) return hr;
  946. if(S_OK != (hr = Read(ich.stream))) return hr;
  947. if(S_OK != (hr = Read(ich.ptrNext))) return hr;
  948. int stream = GetMasterStream();
  949. while(ich.nIndices-- > 0)
  950. {
  951. UINT16 object_version;
  952. if(S_OK != (hr = Read(object_version))) return hr;
  953. if(object_version == 0)
  954. {
  955. CAutoPtr<IndexRecord> ir(new IndexRecord);
  956. if(S_OK != (hr = Read(ir->tStart))) return hr;
  957. if(S_OK != (hr = Read(ir->ptrFilePos))) return hr;
  958. if(S_OK != (hr = Read(ir->packet))) return hr;
  959. if(ich.stream == stream) m_irs.AddTail(ir);
  960. }
  961. }
  962. break;
  963. }
  964. case '.SUB':
  965. if(hdr.size > sizeof(hdr))
  966. {
  967. int size = hdr.size - sizeof(hdr);
  968. CAutoVectorPtr<char> buff;
  969. if(!buff.Allocate(size)) return E_OUTOFMEMORY;
  970. char* p = buff;
  971. if(S_OK != (hr = Read((BYTE*)p, size))) return hr;
  972. for(char* end = p + size; p < end; )
  973. {
  974. subtitle s;
  975. s.name = p; p += s.name.GetLength()+1;
  976. CStringA len(p); p += len.GetLength()+1;
  977. s.data = CStringA(p, strtol(len, NULL, 10)); p += s.data.GetLength();
  978. m_subs.AddTail(s);
  979. }
  980. }
  981. break;
  982. }
  983. }
  984. ASSERT(hdr.object_id == 'DATA' 
  985. || GetPos() == pos + hdr.size 
  986. || GetPos() == pos + sizeof(hdr));
  987. pos += hdr.size;
  988. if(pos > GetPos()) 
  989. Seek(pos);
  990. }
  991. return S_OK;
  992. }
  993. #define GetBits(n) GetBits2(n, p, bit_offset, bit_buffer)
  994. unsigned int GetBits2(int n, unsigned char*& p, unsigned int& bit_offset, unsigned int& bit_buffer)
  995. {
  996. unsigned int ret = ((unsigned int)bit_buffer >> (32-(n)));
  997. bit_offset += n;
  998. bit_buffer <<= n;
  999. if(bit_offset > (32-16))
  1000. {
  1001. p += bit_offset >> 3;
  1002. bit_offset &= 7;
  1003. bit_buffer = (unsigned int)p[0] << 24;
  1004. bit_buffer |= (unsigned int)p[1] << 16;
  1005. bit_buffer |= (unsigned int)p[2] << 8;
  1006. bit_buffer |= (unsigned int)p[3];
  1007. bit_buffer <<= bit_offset;
  1008. }
  1009.     return ret;
  1010. }
  1011. void GetDimensions(unsigned char* p, unsigned int* wi, unsigned int* hi)
  1012. {
  1013. unsigned int w, h, c;
  1014. const unsigned int cw[8] = {160, 176, 240, 320, 352, 640, 704, 0};
  1015. const unsigned int ch1[8] = {120, 132, 144, 240, 288, 480, 0, 0};
  1016. const unsigned int ch2[4] = {180, 360, 576, 0};
  1017. unsigned int bit_offset = 0;
  1018. unsigned int bit_buffer = *(unsigned int*)p;
  1019. bswap(bit_buffer);
  1020.     GetBits(13);
  1021. GetBits(13);
  1022. w = cw[GetBits(3)];
  1023. if(w == 0)
  1024. {
  1025. do
  1026. {
  1027. c = GetBits(8);
  1028. w += (c << 2);
  1029. }
  1030. while(c == 255);
  1031. }
  1032. c = GetBits(3);
  1033. h = ch1[c];
  1034. if(h == 0)
  1035. {
  1036. c = ((c << 1) | GetBits(1)) & 3;
  1037. h = ch2[c];
  1038. if(h == 0)
  1039. {
  1040. do
  1041. {
  1042. c = GetBits(8);
  1043. h += (c << 2);
  1044. }
  1045. while(c == 255);
  1046. }
  1047. }
  1048. *wi = w;
  1049. *hi = h;    
  1050. }
  1051. void GetDimensions_X10(unsigned char* p, unsigned int* wi, unsigned int* hi, 
  1052.    bool *interlaced, bool *top_field_first, bool *repeat_field)
  1053. {
  1054. unsigned int w, h, c;
  1055. const unsigned int cw[8] = {160, 176, 240, 320, 352, 640, 704, 0};
  1056. const unsigned int ch1[8] = {120, 132, 144, 240, 288, 480, 0, 0};
  1057. const unsigned int ch2[4] = {180, 360, 576, 0};
  1058. unsigned int bit_offset = 0;
  1059. unsigned int bit_buffer = *(unsigned int*)p;
  1060. bswap(bit_buffer);
  1061.     GetBits(9);
  1062. *interlaced = false;
  1063. *top_field_first = false;
  1064. *repeat_field = false;
  1065. c = GetBits(1);
  1066. if (c)
  1067. {
  1068. c = GetBits(1);
  1069. if (c)
  1070. *interlaced = true;
  1071. c = GetBits(1);
  1072. if (c)
  1073. *top_field_first = true;
  1074. c = GetBits(1); 
  1075. if (c)
  1076. *repeat_field = true; 
  1077. c = GetBits(1);
  1078. c = GetBits(1);
  1079. if (c)
  1080. GetBits(2);
  1081. }
  1082. GetBits(16);
  1083. w = cw[GetBits(3)];
  1084. if(w == 0)
  1085. {
  1086. do
  1087. {
  1088. c = GetBits(8);
  1089. w += (c << 2);
  1090. }
  1091. while(c == 255);
  1092. }
  1093. c = GetBits(3);
  1094. h = ch1[c];
  1095. if(h == 0)
  1096. {
  1097. c = ((c << 1) | GetBits(1)) & 3;
  1098. h = ch2[c];
  1099. if(h == 0)
  1100. {
  1101. do
  1102. {
  1103. c = GetBits(8);
  1104. h += (c << 2);
  1105. }
  1106. while(c == 255);
  1107. }
  1108. }
  1109. *wi = w;
  1110. *hi = h;    
  1111. }
  1112. void CRMFile::GetDimensions()
  1113. {
  1114. POSITION pos = m_mps.GetHeadPosition();
  1115. while(pos)
  1116. {
  1117. UINT64 filepos = GetPos();
  1118. MediaProperies* pmp = m_mps.GetNext(pos);
  1119. if(pmp->mime == "video/x-pn-realvideo")
  1120. {
  1121. pmp->width = pmp->height = 0;
  1122. rvinfo rvi = *(rvinfo*)pmp->typeSpecData.GetData();
  1123. rvi.bswap();
  1124. if(rvi.fcc2 != '04VR' && rvi.fcc2 != '14VR')
  1125. continue;
  1126. MediaPacketHeader mph;
  1127. while(S_OK == Read(mph))
  1128. {
  1129. if(mph.stream != pmp->stream || mph.len == 0
  1130. || !(mph.flags&MediaPacketHeader::PN_KEYFRAME_FLAG))
  1131. continue;
  1132. BYTE* p = mph.pData.GetData();
  1133. BYTE* p0 = p;
  1134. int len = mph.pData.GetCount();
  1135. BYTE hdr = *p++;
  1136. DWORD packetlen = 0, packetoffset = 0;
  1137. if((hdr&0xc0) == 0x40)
  1138. {
  1139. packetlen = len - (++p - p0);
  1140. }
  1141. else
  1142. {
  1143. if((hdr&0x40) == 0) p++;
  1144. #define GetWORD(var) 
  1145. var = (var<<8)|(*p++); 
  1146. var = (var<<8)|(*p++); 
  1147. GetWORD(packetlen);
  1148. if((packetlen&0x4000) == 0) {GetWORD(packetlen); packetlen &= 0x3fffffff;}
  1149. else packetlen &= 0x3fff;
  1150. GetWORD(packetoffset);
  1151. if((packetoffset&0x4000) == 0) {GetWORD(packetoffset); packetoffset &= 0x3fffffff;}
  1152. else packetoffset &= 0x3fff;
  1153. #undef GetWORD
  1154. if((hdr&0xc0) == 0xc0) packetoffset = 0;
  1155. else if((hdr&0xc0) == 0x80) packetoffset = packetlen - packetoffset;
  1156. p++;
  1157. }
  1158. len = min(len - (p - p0), packetlen - packetoffset);
  1159. if(len > 0)
  1160. {
  1161. bool repeat_field;
  1162. if(rvi.fcc2 == '14VR') ::GetDimensions_X10(p, &pmp->width, &pmp->height, &pmp->interlaced, &pmp->top_field_first, &repeat_field);
  1163. else ::GetDimensions(p, &pmp->width, &pmp->height);
  1164. if(rvi.w == pmp->width && rvi.h == pmp->height)
  1165. pmp->width = pmp->height = 0;
  1166. break;
  1167. }
  1168. }
  1169. }
  1170. Seek(filepos);
  1171. }
  1172. }
  1173. int CRMFile::GetMasterStream()
  1174. {
  1175. int s1 = -1, s2 = -1;
  1176. POSITION pos = m_mps.GetHeadPosition();
  1177. while(pos)
  1178. {
  1179. MediaProperies* pmp = m_mps.GetNext(pos);
  1180. if(pmp->mime == "video/x-pn-realvideo") {s1 = pmp->stream; break;}
  1181. else if(pmp->mime == "audio/x-pn-realaudio" && s2 == -1) s2 = pmp->stream;
  1182. }
  1183. if(s1 == -1)
  1184. s1 = s2;
  1185. return s1;
  1186. }
  1187. ////////////////////////////
  1188. //
  1189. // CRealVideoDecoder
  1190. //
  1191. CRealVideoDecoder::CRealVideoDecoder(LPUNKNOWN lpunk, HRESULT* phr)
  1192. : CBaseVideoFilter(NAME("CRealVideoDecoder"), lpunk, phr, __uuidof(this))
  1193. , m_hDrvDll(NULL)
  1194. , m_dwCookie(0)
  1195. {
  1196. }
  1197. CRealVideoDecoder::~CRealVideoDecoder()
  1198. {
  1199. if(m_hDrvDll) FreeLibrary(m_hDrvDll);
  1200. }
  1201. HRESULT CRealVideoDecoder::InitRV(const CMediaType* pmt)
  1202. {
  1203. FreeRV();
  1204. HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
  1205. rvinfo rvi = *(rvinfo*)(pmt->Format() + (pmt->formattype == FORMAT_VideoInfo ? sizeof(VIDEOINFOHEADER) : sizeof(VIDEOINFOHEADER2)));
  1206. rvi.bswap();
  1207. #pragma pack(push, 1)
  1208. struct {WORD unk1, w, h, unk3; DWORD unk2, subformat, unk5, format;} i =
  1209. {11, rvi.w, rvi.h, 0, 0, rvi.type1, 1, rvi.type2};
  1210. #pragma pack(pop)
  1211. if(FAILED(hr = RVInit(&i, &m_dwCookie)))
  1212. return hr;
  1213. if(rvi.fcc2 <= '03VR' && rvi.type2 >= 0x20200002)
  1214. {
  1215. int nWidthHeight = (1+((rvi.type1>>16)&7));
  1216. UINT32* pWH = new UINT32[nWidthHeight*2];
  1217. pWH[0] = rvi.w; pWH[1] = rvi.h;
  1218. for(int i = 2; i < nWidthHeight*2; i++)
  1219. pWH[i] = rvi.morewh[i-2]*4;
  1220. #pragma pack(push, 1)
  1221. struct {UINT32 data1; UINT32 data2; UINT32* dimensions;} cmsg_data = 
  1222. {0x24, nWidthHeight, pWH};
  1223. #pragma pack(pop)
  1224. hr = RVCustomMessage(&cmsg_data, m_dwCookie);
  1225. delete [] pWH;
  1226. }
  1227. return hr;
  1228. }
  1229. void CRealVideoDecoder::FreeRV()
  1230. {
  1231. if(m_dwCookie)
  1232. {
  1233. RVFree(m_dwCookie);
  1234. m_dwCookie = 0;
  1235. }
  1236. }
  1237. HRESULT CRealVideoDecoder::Transform(IMediaSample* pIn)
  1238. {
  1239. CAutoLock cAutoLock(&m_csReceive);
  1240. HRESULT hr;
  1241. BYTE* pDataIn = NULL;
  1242. if(FAILED(hr = pIn->GetPointer(&pDataIn)))
  1243. return hr;
  1244. long len = pIn->GetActualDataLength();
  1245. if(len <= 0) return S_OK; // nothing to do
  1246. REFERENCE_TIME rtStart, rtStop;
  1247. pIn->GetTime(&rtStart, &rtStop);
  1248. rtStart += m_tStart;
  1249. int offset = 1+((*pDataIn)+1)*8;
  1250. #pragma pack(push, 1)
  1251. struct {DWORD len, unk1, chunks; DWORD* extra; DWORD unk2, timestamp;} transform_in = 
  1252. {len - offset, 0, *pDataIn, (DWORD*)(pDataIn+1), 0, (DWORD)(rtStart/10000)};
  1253. struct {DWORD unk1, unk2, timestamp, w, h;} transform_out = 
  1254. {0,0,0,0,0};
  1255. #pragma pack(pop)
  1256. pDataIn += offset;
  1257. if(m_fDropFrames && m_timestamp+1 == transform_in.timestamp)
  1258. {
  1259. m_timestamp = transform_in.timestamp;
  1260. return S_OK;
  1261. }
  1262. hr = RVTransform(pDataIn, (BYTE*)m_pI420, &transform_in, &transform_out, m_dwCookie);
  1263. unsigned int tmp1, tmp2;
  1264. bool interlaced = false, tmp3, tmp4;
  1265. ::GetDimensions_X10(pDataIn, &tmp1, &tmp2, &interlaced, &tmp3, &tmp4);
  1266. m_timestamp = transform_in.timestamp;
  1267. if(FAILED(hr))
  1268. {
  1269. TRACE(_T("RV returned an error code!!!n"));
  1270. ASSERT(!(transform_out.unk1&1)); // error allowed when the "render" flag is not set
  1271. // return hr;
  1272. }
  1273. if(pIn->IsPreroll() == S_OK || rtStart < 0 || !(transform_out.unk1&1))
  1274. return S_OK;
  1275. CComPtr<IMediaSample> pOut;
  1276. BYTE* pDataOut = NULL;
  1277. if(/*FAILED(hr = GetDeliveryBuffer(transform_out.w, transform_out.h, &pOut)) // TODO
  1278. && */ FAILED(hr = GetDeliveryBuffer(m_w, m_h, &pOut))
  1279. || FAILED(hr = pOut->GetPointer(&pDataOut)))
  1280. return hr;
  1281. BYTE* pI420[3] = {m_pI420, m_pI420Tmp, NULL};
  1282. if(interlaced)
  1283. {
  1284. int size = m_w*m_h;
  1285. DeinterlaceBlend(pI420[1], pI420[0], m_w, m_h, m_w, m_w);
  1286. DeinterlaceBlend(pI420[1]+size, pI420[0]+size, m_w/2, m_h/2, m_w/2, m_w/2);
  1287. DeinterlaceBlend(pI420[1]+size*5/4, pI420[0]+size*5/4, m_w/2, m_h/2, m_w/2, m_w/2);
  1288. pI420[2] = pI420[1], pI420[1] = pI420[0], pI420[0] = pI420[2];
  1289. }
  1290. if(transform_out.w != m_w || transform_out.h != m_h)
  1291. {
  1292. Resize(pI420[0], transform_out.w, transform_out.h, pI420[1], m_w, m_h);
  1293. // only one of these can be true, and when it happens the result image must be in the tmp buffer
  1294. if(transform_out.w == m_w || transform_out.h == m_h)
  1295. pI420[2] = pI420[1], pI420[1] = pI420[0], pI420[0] = pI420[2];
  1296. }
  1297. rtStart = 10000i64*transform_out.timestamp - m_tStart;
  1298. rtStop = rtStart + 1;
  1299. pOut->SetTime(&rtStart, /*NULL*/&rtStop);
  1300. pOut->SetDiscontinuity(pIn->IsDiscontinuity() == S_OK);
  1301. CopyBuffer(pDataOut, pI420[0], m_w, m_h, m_w, MEDIASUBTYPE_I420);
  1302. DbgLog((LOG_TRACE, 0, _T("V: rtStart=%I64d, rtStop=%I64d, disc=%d, sync=%d"), 
  1303.    rtStart, rtStop, pOut->IsDiscontinuity() == S_OK, pOut->IsSyncPoint() == S_OK));
  1304. return m_pOutput->Deliver(pOut);
  1305. }
  1306. void CRealVideoDecoder::Resize(BYTE* pIn, DWORD wi, DWORD hi, BYTE* pOut, DWORD wo, DWORD ho)
  1307. {
  1308. int si = wi*hi, so = wo*ho;
  1309. ASSERT(((si*so)&3) == 0);
  1310. if(wi < wo)
  1311. {
  1312. ResizeWidth(pIn, wi, hi, pOut, wo, ho);
  1313. ResizeWidth(pIn + si, wi/2, hi/2, pOut + so, wo/2, ho/2);
  1314. ResizeWidth(pIn + si + si/4, wi/2, hi/2, pOut + so + so/4, wo/2, ho/2);
  1315. if(hi == ho) return; 
  1316. ResizeHeight(pOut, wo, hi, pIn, wo, ho);
  1317. ResizeHeight(pOut + so, wo/2, hi/2, pIn + so, wo/2, ho/2);
  1318. ResizeHeight(pOut + so + so/4, wo/2, hi/2, pIn + so + so/4, wo/2, ho/2);
  1319. }
  1320. else if(hi < ho)
  1321. {
  1322. ResizeHeight(pIn, wi, hi, pOut, wo, ho);
  1323. ResizeHeight(pIn + si, wi/2, hi/2, pOut + so, wo/2, ho/2);
  1324. ResizeHeight(pIn + si + si/4, wi/2, hi/2, pOut + so + so/4, wo/2, ho/2);
  1325. if(wi == wo) return;
  1326. ASSERT(0); // this is uncreachable code, but anyway... looks nice being so symmetric
  1327. ResizeWidth(pOut, wi, ho, pIn, wo, ho);
  1328. ResizeWidth(pOut + so, wi/2, ho/2, pIn + so, wo/2, ho/2);
  1329. ResizeWidth(pOut + so + so/4, wi/2, ho/2, pIn + so + so/4, wo/2, ho/2);
  1330. }
  1331. }
  1332. void CRealVideoDecoder::ResizeWidth(BYTE* pIn, DWORD wi, DWORD hi, BYTE* pOut, DWORD wo, DWORD ho)
  1333. {
  1334. for(DWORD y = 0; y < hi; y++, pIn += wi, pOut += wo)
  1335. {
  1336. if(wi == wo) memcpy_accel(pOut, pIn, wo);
  1337. else ResizeRow(pIn, wi, 1, pOut, wo, 1);
  1338. }
  1339. }
  1340. void CRealVideoDecoder::ResizeHeight(BYTE* pIn, DWORD wi, DWORD hi, BYTE* pOut, DWORD wo, DWORD ho)
  1341. {
  1342. if(hi == ho) 
  1343. {
  1344. memcpy_accel(pOut, pIn, wo*ho);
  1345. }
  1346. else
  1347. {
  1348. for(DWORD x = 0; x < wo; x++, pIn++, pOut++)
  1349. ResizeRow(pIn, hi, wo, pOut, ho, wo);
  1350. }
  1351. }
  1352. void CRealVideoDecoder::ResizeRow(BYTE* pIn, DWORD wi, DWORD dpi, BYTE* pOut, DWORD wo, DWORD dpo)
  1353. {
  1354. ASSERT(wi < wo);
  1355.     if(dpo == 1)
  1356. {
  1357. for(DWORD i = 0, j = 0, dj = (wi<<16)/wo; i < wo-1; i++, pOut++, j += dj)
  1358. // pOut[i] = pIn[j>>16];
  1359. {
  1360. BYTE* p = &pIn[j>>16];
  1361. DWORD jf = j&0xffff;
  1362. *pOut = ((p[0]*(0xffff-jf) + p[1]*jf) + 0x7fff) >> 16;
  1363. }
  1364. *pOut = pIn[wi-1];
  1365. }
  1366. else
  1367. {
  1368. for(DWORD i = 0, j = 0, dj = (wi<<16)/wo; i < wo-1; i++, pOut += dpo, j += dj)
  1369. // *pOut = pIn[dpi*(j>>16)];
  1370. {
  1371. BYTE* p = &pIn[dpi*(j>>16)];
  1372. DWORD jf = j&0xffff;
  1373. *pOut = ((p[0]*(0xffff-jf) + p[dpi]*jf) + 0x7fff) >> 16;
  1374. }
  1375. *pOut = pIn[dpi*(wi-1)];
  1376. }
  1377. }
  1378. HRESULT CRealVideoDecoder::CheckInputType(const CMediaType* mtIn)
  1379. {
  1380. if(mtIn->majortype != MEDIATYPE_Video 
  1381. || mtIn->subtype != MEDIASUBTYPE_RV20
  1382. && mtIn->subtype != MEDIASUBTYPE_RV30 
  1383. && mtIn->subtype != MEDIASUBTYPE_RV40
  1384. && mtIn->subtype != MEDIASUBTYPE_RV41)
  1385. return VFW_E_TYPE_NOT_ACCEPTED;
  1386. if(mtIn->formattype == FORMAT_VideoInfo2)
  1387. {
  1388. VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)mtIn->Format();
  1389. if(vih2->dwPictAspectRatioX < vih2->bmiHeader.biWidth
  1390. || vih2->dwPictAspectRatioY < vih2->bmiHeader.biHeight)
  1391. return VFW_E_TYPE_NOT_ACCEPTED;
  1392. }
  1393. if(!m_pInput->IsConnected())
  1394. {
  1395. if(m_hDrvDll) {FreeLibrary(m_hDrvDll); m_hDrvDll = NULL;}
  1396. CList<CString> paths;
  1397. CString olddll, newdll, oldpath, newpath;
  1398. olddll.Format(_T("drv%c3260.dll"), (TCHAR)((mtIn->subtype.Data1>>16)&0xff));
  1399. newdll = 
  1400. mtIn->subtype == FOURCCMap('14VR') ? _T("drvi.dll") :
  1401. mtIn->subtype == FOURCCMap('02VR') ? _T("drv2.dll") :
  1402. _T("drvc.dll");
  1403. CRegKey key;
  1404. TCHAR buff[MAX_PATH];
  1405. ULONG len = sizeof(buff);
  1406. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Software\RealNetworks\Preferences\DT_Codecs"), KEY_READ)
  1407. && ERROR_SUCCESS == key.QueryStringValue(NULL, buff, &len) && _tcslen(buff) > 0)
  1408. {
  1409. oldpath = buff;
  1410. TCHAR c = oldpath[oldpath.GetLength()-1];
  1411. if(c != '\' && c != '/') oldpath += '\';
  1412. key.Close();
  1413. }
  1414. len = sizeof(buff);
  1415. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Helix\HelixSDK\10.0\Preferences\DT_Codecs"), KEY_READ)
  1416. && ERROR_SUCCESS == key.QueryStringValue(NULL, buff, &len) && _tcslen(buff) > 0)
  1417. {
  1418. newpath = buff;
  1419. TCHAR c = newpath[newpath.GetLength()-1];
  1420. if(c != '\' && c != '/') newpath += '\';
  1421. key.Close();
  1422. }
  1423. if(!newpath.IsEmpty()) paths.AddTail(newpath + newdll);
  1424. if(!oldpath.IsEmpty()) paths.AddTail(oldpath + newdll);
  1425. paths.AddTail(newdll); // default dll paths
  1426. if(!newpath.IsEmpty()) paths.AddTail(newpath + olddll);
  1427. if(!oldpath.IsEmpty()) paths.AddTail(oldpath + olddll);
  1428. paths.AddTail(olddll); // default dll paths
  1429. POSITION pos = paths.GetHeadPosition();
  1430. while(pos && !(m_hDrvDll = LoadLibrary(paths.GetNext(pos))));
  1431. if(m_hDrvDll)
  1432. {
  1433. RVCustomMessage = (PRVCustomMessage)GetProcAddress(m_hDrvDll, "RV20toYUV420CustomMessage");
  1434. RVFree = (PRVFree)GetProcAddress(m_hDrvDll, "RV20toYUV420Free");
  1435. RVHiveMessage = (PRVHiveMessage)GetProcAddress(m_hDrvDll, "RV20toYUV420HiveMessage");
  1436. RVInit = (PRVInit)GetProcAddress(m_hDrvDll, "RV20toYUV420Init");
  1437. RVTransform = (PRVTransform)GetProcAddress(m_hDrvDll, "RV20toYUV420Transform");
  1438. if(!RVCustomMessage) RVCustomMessage = (PRVCustomMessage)GetProcAddress(m_hDrvDll, "RV40toYUV420CustomMessage");
  1439. if(!RVFree) RVFree = (PRVFree)GetProcAddress(m_hDrvDll, "RV40toYUV420Free");
  1440. if(!RVHiveMessage) RVHiveMessage = (PRVHiveMessage)GetProcAddress(m_hDrvDll, "RV40toYUV420HiveMessage");
  1441. if(!RVInit) RVInit = (PRVInit)GetProcAddress(m_hDrvDll, "RV40toYUV420Init");
  1442. if(!RVTransform) RVTransform = (PRVTransform)GetProcAddress(m_hDrvDll, "RV40toYUV420Transform");
  1443. }
  1444. if(!m_hDrvDll || !RVCustomMessage 
  1445. || !RVFree || !RVHiveMessage
  1446. || !RVInit || !RVTransform)
  1447. return VFW_E_TYPE_NOT_ACCEPTED;
  1448. if(FAILED(InitRV(mtIn)))
  1449. return VFW_E_TYPE_NOT_ACCEPTED;
  1450. }
  1451. return S_OK;
  1452. }
  1453. HRESULT CRealVideoDecoder::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  1454. {
  1455. if(m_pOutput && m_pOutput->IsConnected())
  1456. {
  1457. BITMAPINFOHEADER bih1, bih2;
  1458. if(ExtractBIH(mtOut, &bih1) && ExtractBIH(&m_pOutput->CurrentMediaType(), &bih2)
  1459. && abs(bih1.biHeight) != abs(bih2.biHeight))
  1460. return VFW_E_TYPE_NOT_ACCEPTED;
  1461. }
  1462. return __super::CheckTransform(mtIn, mtOut);
  1463. }
  1464. HRESULT CRealVideoDecoder::StartStreaming()
  1465. {
  1466. const CMediaType& mt = m_pInput->CurrentMediaType();
  1467. if(FAILED(InitRV(&mt)))
  1468. return E_FAIL;
  1469. int size = m_w*m_h;
  1470. m_pI420.Allocate(size*3/2);
  1471. memset(m_pI420, 0, size);
  1472. memset(m_pI420 + size, 0x80, size/2);
  1473. m_pI420Tmp.Allocate(size*3/2);
  1474. memset(m_pI420Tmp, 0, size);
  1475. memset(m_pI420Tmp + size, 0x80, size/2);
  1476. return __super::StartStreaming();
  1477. }
  1478. HRESULT CRealVideoDecoder::StopStreaming()
  1479. {
  1480. m_pI420.Free();
  1481. m_pI420Tmp.Free();
  1482. FreeRV();
  1483. return __super::StopStreaming();
  1484. }
  1485. HRESULT CRealVideoDecoder::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  1486. {
  1487. CAutoLock cAutoLock(&m_csReceive);
  1488. m_timestamp = ~0;
  1489. m_fDropFrames = false;
  1490. DWORD tmp[2] = {20, 0};
  1491. RVHiveMessage(tmp, m_dwCookie);
  1492. m_tStart = tStart;
  1493. return __super::NewSegment(tStart, tStop, dRate);
  1494. }
  1495. HRESULT CRealVideoDecoder::AlterQuality(Quality q)
  1496. {
  1497. if(q.Late > 500*10000i64) m_fDropFrames = true;
  1498. if(q.Late <= 0) m_fDropFrames = false;
  1499. // TRACE(_T("CRealVideoDecoder::AlterQuality: Type=%d, Proportion=%d, Late=%I64d, TimeStamp=%I64dn"), q.Type, q.Proportion, q.Late, q.TimeStamp);
  1500. return E_NOTIMPL;
  1501. }
  1502. /////////////////////////
  1503. //
  1504. // CRealAudioDecoder
  1505. //
  1506. CRealAudioDecoder::CRealAudioDecoder(LPUNKNOWN lpunk, HRESULT* phr)
  1507. : CTransformFilter(NAME("CRealAudioDecoder"), lpunk, __uuidof(this))
  1508. , m_hDrvDll(NULL)
  1509. , m_dwCookie(0)
  1510. {
  1511. if(phr) *phr = S_OK;
  1512. }
  1513. CRealAudioDecoder::~CRealAudioDecoder()
  1514. {
  1515. // FreeRA();
  1516. if(m_hDrvDll) FreeLibrary(m_hDrvDll);
  1517. }
  1518. HRESULT CRealAudioDecoder::InitRA(const CMediaType* pmt)
  1519. {
  1520. FreeRA();
  1521. HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
  1522. if(RAOpenCodec2 && FAILED(hr = RAOpenCodec2(&m_dwCookie, m_dllpath))
  1523. || RAOpenCodec && FAILED(hr = RAOpenCodec(&m_dwCookie)))
  1524. return hr;
  1525. WAVEFORMATEX* pwfe = (WAVEFORMATEX*)pmt->Format();
  1526. // someone might be doing cbSize = sizeof(WAVEFORMATEX), chances of 
  1527. // cbSize being really sizeof(WAVEFORMATEX) is less than this, 
  1528. // especially with our rm splitter ;)
  1529. DWORD cbSize = pwfe->cbSize;
  1530. if(cbSize == sizeof(WAVEFORMATEX)) {ASSERT(0); cbSize = 0;}
  1531. WORD wBitsPerSample = pwfe->wBitsPerSample;
  1532. if(!wBitsPerSample) wBitsPerSample = 16;
  1533. #pragma pack(push, 1)
  1534. struct {DWORD freq; WORD bpsample, channels, quality; DWORD bpframe, packetsize, extralen; void* extra;} initdata =
  1535. {pwfe->nSamplesPerSec, wBitsPerSample, pwfe->nChannels, 100, 
  1536. 0, 0, 0, NULL};
  1537. #pragma pack(pop)
  1538. CAutoVectorPtr<BYTE> pBuff;
  1539. if(pmt->subtype == MEDIASUBTYPE_AAC)
  1540. {
  1541. pBuff.Allocate(cbSize+1);
  1542. pBuff[0] = 0x02;
  1543. memcpy(pBuff+1, pwfe+1, cbSize);
  1544. initdata.extralen = cbSize+1;
  1545. initdata.extra = pBuff;
  1546. }
  1547. else
  1548. {
  1549. if(pmt->FormatLength() <= sizeof(WAVEFORMATEX) + cbSize) // must have type_specific_data appended
  1550. return hr;
  1551. BYTE* fmt = pmt->Format() + sizeof(WAVEFORMATEX) + cbSize;
  1552. for(int i = 0, len = pmt->FormatLength() - (sizeof(WAVEFORMATEX) + cbSize); i < len-4; i++, fmt++)
  1553. {
  1554. if(fmt[0] == '.' || fmt[1] == 'r' || fmt[2] == 'a')
  1555. break;
  1556. }
  1557. m_rai = *(rainfo*)fmt;
  1558. m_rai.bswap();
  1559. BYTE* p;
  1560. if(m_rai.version2 == 4)
  1561. {
  1562. p = (BYTE*)((rainfo4*)fmt+1);
  1563. int len = *p++; p += len; len = *p++; p += len; 
  1564. ASSERT(len == 4);
  1565. }
  1566. else if(m_rai.version2 == 5)
  1567. {
  1568. p = (BYTE*)((rainfo5*)fmt+1);
  1569. }
  1570. else
  1571. {
  1572. return hr;
  1573. }
  1574. p += 3;
  1575. if(m_rai.version2 == 5) p++;
  1576. initdata.bpframe = m_rai.sub_packet_size;
  1577. initdata.packetsize = m_rai.coded_frame_size;
  1578. initdata.extralen = *(DWORD*)p;
  1579. initdata.extra = p + 4;
  1580. }
  1581. if(FAILED(hr = RAInitDecoder(m_dwCookie, &initdata)))
  1582. return hr;
  1583. if(RASetPwd)
  1584. RASetPwd(m_dwCookie, "Ardubancel Quazanga");
  1585. if(RASetFlavor && FAILED(hr = RASetFlavor(m_dwCookie, m_rai.flavor)))
  1586. return hr;
  1587. return hr;
  1588. }
  1589. void CRealAudioDecoder::FreeRA()
  1590. {
  1591. if(m_dwCookie)
  1592. {
  1593. RAFreeDecoder(m_dwCookie);
  1594. RACloseCodec(m_dwCookie);
  1595. m_dwCookie = 0;
  1596. }
  1597. }
  1598. HRESULT CRealAudioDecoder::Receive(IMediaSample* pIn)
  1599. {
  1600. CAutoLock cAutoLock(&m_csReceive);
  1601. HRESULT hr;
  1602.     AM_SAMPLE2_PROPERTIES* const pProps = m_pInput->SampleProps();
  1603.     if(pProps->dwStreamId != AM_STREAM_MEDIA)
  1604. return m_pOutput->Deliver(pIn);
  1605. BYTE* pDataIn = NULL;
  1606. if(FAILED(hr = pIn->GetPointer(&pDataIn))) return hr;
  1607. BYTE* pDataInOrg = pDataIn;
  1608. long len = pIn->GetActualDataLength();
  1609. if(len <= 0) return S_OK;
  1610. REFERENCE_TIME rtStart, rtStop;
  1611. pIn->GetTime(&rtStart, &rtStop);
  1612. /*
  1613. if(pIn->IsPreroll() == S_OK || rtStart < 0)
  1614. return S_OK;
  1615. */
  1616. //
  1617. if(S_OK == pIn->IsSyncPoint())
  1618. {
  1619. m_bufflen = 0;
  1620. m_rtBuffStart = rtStart;
  1621. m_fBuffDiscontinuity = pIn->IsDiscontinuity() == S_OK;
  1622. }
  1623. BYTE* src = NULL;
  1624. BYTE* dst = NULL;
  1625. int w = m_rai.coded_frame_size;
  1626. int h = m_rai.sub_packet_h;
  1627. int sps = m_rai.sub_packet_size;
  1628. if(m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_RAAC
  1629. || m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_RACP
  1630. || m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_AAC)
  1631. {
  1632. src = pDataIn;
  1633. dst = pDataIn + len;
  1634. w = len;
  1635. }
  1636. else
  1637. {
  1638. memcpy(&m_buff[m_bufflen], pDataIn, len);
  1639. m_bufflen += len;
  1640. len = w*h;
  1641. if(m_bufflen >= len)
  1642. {
  1643. ASSERT(m_bufflen == len);
  1644. src = m_buff;
  1645. dst = m_buff + len;
  1646. if(sps > 0
  1647. && (m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_COOK
  1648. || m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_ATRC))
  1649. {
  1650. for(int y = 0; y < h; y++)
  1651. {
  1652. for(int x = 0, w2 = w / sps; x < w2; x++)
  1653. {
  1654. // TRACE(_T("--- %d, %dn"), (h*x+((h+1)/2)*(y&1)+(y>>1)), sps*(h*x+((h+1)/2)*(y&1)+(y>>1)));
  1655. memcpy(dst + sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), src, sps);
  1656. src += sps;
  1657. }
  1658. }
  1659. src = m_buff + len;
  1660. dst = m_buff + len*2;
  1661. }
  1662. else if(m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_SIPR)
  1663. {
  1664. // http://mplayerhq.hu/pipermail/mplayer-dev-eng/2002-August/010569.html
  1665. static BYTE sipr_swaps[38][2]={
  1666. {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68},
  1667. {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46},
  1668. {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56},
  1669. {42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83},
  1670. {77,80} };
  1671. int bs=h*w*2/96; // nibbles per subpacket
  1672. for(int n=0;n<38;n++){
  1673. int i=bs*sipr_swaps[n][0];
  1674. int o=bs*sipr_swaps[n][1];
  1675. // swap nibbles of block 'i' with 'o'      TODO: optimize
  1676. for(int j=0;j<bs;j++){
  1677. int x=(i&1) ? (src[(i>>1)]>>4) : (src[(i>>1)]&15);
  1678. int y=(o&1) ? (src[(o>>1)]>>4) : (src[(o>>1)]&15);
  1679. if(o&1) src[(o>>1)]=(src[(o>>1)]&0x0F)|(x<<4);
  1680. else  src[(o>>1)]=(src[(o>>1)]&0xF0)|x;
  1681. if(i&1) src[(i>>1)]=(src[(i>>1)]&0x0F)|(y<<4);
  1682. else  src[(i>>1)]=(src[(i>>1)]&0xF0)|y;
  1683. ++i;++o;
  1684. }
  1685. }
  1686. }
  1687. m_bufflen = 0;
  1688. }
  1689. }
  1690. rtStart = m_rtBuffStart;
  1691. for(; src < dst; src += w)
  1692. {
  1693. CComPtr<IMediaSample> pOut;
  1694. BYTE* pDataOut = NULL;
  1695. if(FAILED(hr = m_pOutput->GetDeliveryBuffer(&pOut, NULL, NULL, 0))
  1696. || FAILED(hr = pOut->GetPointer(&pDataOut)))
  1697. return hr;
  1698. AM_MEDIA_TYPE* pmt;
  1699. if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
  1700. {
  1701. CMediaType mt(*pmt);
  1702. m_pOutput->SetMediaType(&mt);
  1703. DeleteMediaType(pmt);
  1704. }
  1705. hr = RADecode(m_dwCookie, src, w, pDataOut, &len, -1);
  1706. if(FAILED(hr))
  1707. {
  1708. TRACE(_T("RA returned an error code!!!n"));
  1709. continue;
  1710. // return hr;
  1711. }
  1712. WAVEFORMATEX* pwfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
  1713. rtStop = rtStart + 1000i64*len/pwfe->nAvgBytesPerSec*10000;
  1714. pOut->SetTime(&rtStart, &rtStop);
  1715. pOut->SetMediaTime(NULL, NULL);
  1716. pOut->SetDiscontinuity(m_fBuffDiscontinuity); m_fBuffDiscontinuity = false;
  1717. pOut->SetSyncPoint(TRUE);
  1718. pOut->SetActualDataLength(len);
  1719. DbgLog((LOG_TRACE, 0, _T("A: rtStart=%I64d, rtStop=%I64d, disc=%d, sync=%d"), 
  1720. rtStart, rtStop, pOut->IsDiscontinuity() == S_OK, pOut->IsSyncPoint() == S_OK));
  1721. if(rtStart >= 0 && S_OK != (hr = m_pOutput->Deliver(pOut)))
  1722. return hr;
  1723. rtStart = rtStop;
  1724. }
  1725. m_rtBuffStart = rtStart;
  1726. return S_OK;
  1727. }
  1728. HRESULT CRealAudioDecoder::CheckInputType(const CMediaType* mtIn)
  1729. {
  1730. if(mtIn->majortype != MEDIATYPE_Audio 
  1731. || mtIn->subtype != MEDIASUBTYPE_14_4
  1732. && mtIn->subtype != MEDIASUBTYPE_28_8
  1733. && mtIn->subtype != MEDIASUBTYPE_ATRC
  1734. && mtIn->subtype != MEDIASUBTYPE_COOK
  1735. && mtIn->subtype != MEDIASUBTYPE_DNET
  1736. && mtIn->subtype != MEDIASUBTYPE_SIPR
  1737. && mtIn->subtype != MEDIASUBTYPE_RAAC
  1738. && mtIn->subtype != MEDIASUBTYPE_RACP
  1739. && mtIn->subtype != MEDIASUBTYPE_AAC)
  1740. return VFW_E_TYPE_NOT_ACCEPTED;
  1741. if(!m_pInput->IsConnected())
  1742. {
  1743. if(m_hDrvDll) {FreeLibrary(m_hDrvDll); m_hDrvDll = NULL;}
  1744. CList<CString> paths;
  1745. CString olddll, newdll, oldpath, newpath;
  1746. TCHAR fourcc[5] = 
  1747. {
  1748. (TCHAR)((mtIn->subtype.Data1>>0)&0xff),
  1749. (TCHAR)((mtIn->subtype.Data1>>8)&0xff),
  1750. (TCHAR)((mtIn->subtype.Data1>>16)&0xff),
  1751. (TCHAR)((mtIn->subtype.Data1>>24)&0xff),
  1752. 0
  1753. };
  1754. if(!_tcscmp(_T("RACP"), fourcc) || !_tcscmp(_T("xff"), fourcc))
  1755. _tcscpy(fourcc, _T("RAAC"));
  1756. olddll.Format(_T("%s3260.dll"), fourcc);
  1757. newdll.Format(_T("%s.dll"), fourcc);
  1758. CRegKey key;
  1759. TCHAR buff[MAX_PATH];
  1760. ULONG len = sizeof(buff);
  1761. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Software\RealNetworks\Preferences\DT_Codecs"), KEY_READ)
  1762. && ERROR_SUCCESS == key.QueryStringValue(NULL, buff, &len) && _tcslen(buff) > 0)
  1763. {
  1764. oldpath = buff;
  1765. TCHAR c = oldpath[oldpath.GetLength()-1];
  1766. if(c != '\' && c != '/') oldpath += '\';
  1767. key.Close();
  1768. }
  1769. len = sizeof(buff);
  1770. if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Helix\HelixSDK\10.0\Preferences\DT_Codecs"), KEY_READ)
  1771. && ERROR_SUCCESS == key.QueryStringValue(NULL, buff, &len) && _tcslen(buff) > 0)
  1772. {
  1773. newpath = buff;
  1774. TCHAR c = newpath[newpath.GetLength()-1];
  1775. if(c != '\' && c != '/') newpath += '\';
  1776. key.Close();
  1777. }
  1778. if(!newpath.IsEmpty()) paths.AddTail(newpath + newdll);
  1779. if(!oldpath.IsEmpty()) paths.AddTail(oldpath + newdll);
  1780. paths.AddTail(newdll); // default dll paths
  1781. if(!newpath.IsEmpty()) paths.AddTail(newpath + olddll);
  1782. if(!oldpath.IsEmpty()) paths.AddTail(oldpath + olddll);
  1783. paths.AddTail(olddll); // default dll paths
  1784. POSITION pos = paths.GetHeadPosition();
  1785. while(pos && !(m_hDrvDll = LoadLibrary(paths.GetNext(pos))));
  1786. if(m_hDrvDll)
  1787. {
  1788. RACloseCodec = (PCloseCodec)GetProcAddress(m_hDrvDll, "RACloseCodec");
  1789. RADecode = (PDecode)GetProcAddress(m_hDrvDll, "RADecode");
  1790. RAFlush = (PFlush)GetProcAddress(m_hDrvDll, "RAFlush");
  1791. RAFreeDecoder = (PFreeDecoder)GetProcAddress(m_hDrvDll, "RAFreeDecoder");
  1792. RAGetFlavorProperty = (PGetFlavorProperty)GetProcAddress(m_hDrvDll, "RAGetFlavorProperty");
  1793. RAInitDecoder = (PInitDecoder)GetProcAddress(m_hDrvDll, "RAInitDecoder");
  1794. RAOpenCodec = (POpenCodec)GetProcAddress(m_hDrvDll, "RAOpenCodec");
  1795. RAOpenCodec2 = (POpenCodec2)GetProcAddress(m_hDrvDll, "RAOpenCodec2");
  1796. RASetFlavor = (PSetFlavor)GetProcAddress(m_hDrvDll, "RASetFlavor");
  1797. RASetDLLAccessPath = (PSetDLLAccessPath)GetProcAddress(m_hDrvDll, "RASetDLLAccessPath");
  1798. RASetPwd = (PSetPwd)GetProcAddress(m_hDrvDll, "RASetPwd");
  1799. }
  1800. if(!m_hDrvDll || !RACloseCodec || !RADecode /*|| !RAFlush*/
  1801. || !RAFreeDecoder || !RAGetFlavorProperty || !RAInitDecoder 
  1802. || !(RAOpenCodec || RAOpenCodec2) /*|| !RASetFlavor*/)
  1803. return VFW_E_TYPE_NOT_ACCEPTED;
  1804. if(m_hDrvDll)
  1805. {
  1806. char buff[MAX_PATH];
  1807. GetModuleFileNameA(m_hDrvDll, buff, MAX_PATH);
  1808. CPathA p(buff);
  1809. p.RemoveFileSpec();
  1810. p.AddBackslash();
  1811. m_dllpath = p.m_strPath;
  1812. if(RASetDLLAccessPath)
  1813. RASetDLLAccessPath("DT_Codecs=" + m_dllpath);
  1814. }
  1815. if(FAILED(InitRA(mtIn)))
  1816. return VFW_E_TYPE_NOT_ACCEPTED;
  1817. }
  1818. return S_OK;
  1819. }
  1820. HRESULT CRealAudioDecoder::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  1821. {
  1822. return mtIn->majortype == MEDIATYPE_Audio && (mtIn->subtype == MEDIASUBTYPE_14_4
  1823. || mtIn->subtype == MEDIASUBTYPE_28_8
  1824. || mtIn->subtype == MEDIASUBTYPE_ATRC
  1825. || mtIn->subtype == MEDIASUBTYPE_COOK
  1826. || mtIn->subtype == MEDIASUBTYPE_DNET
  1827. || mtIn->subtype == MEDIASUBTYPE_SIPR
  1828. || mtIn->subtype == MEDIASUBTYPE_RAAC
  1829. || mtIn->subtype == MEDIASUBTYPE_RACP
  1830. || mtIn->subtype == MEDIASUBTYPE_AAC)
  1831. && mtOut->majortype == MEDIATYPE_Audio && mtOut->subtype == MEDIASUBTYPE_PCM
  1832. ? S_OK
  1833. : VFW_E_TYPE_NOT_ACCEPTED;
  1834. }
  1835. HRESULT CRealAudioDecoder::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
  1836. {
  1837. if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  1838. CComPtr<IMemAllocator> pAllocatorIn;
  1839. m_pInput->GetAllocator(&pAllocatorIn);
  1840. if(!pAllocatorIn) return E_UNEXPECTED;
  1841. WAVEFORMATEX* pwfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
  1842. WORD wBitsPerSample = pwfe->wBitsPerSample;
  1843. if(!wBitsPerSample) wBitsPerSample = 16;
  1844. // ok, maybe this is too much...
  1845. pProperties->cBuffers = 8;
  1846. pProperties->cbBuffer = pwfe->nChannels*pwfe->nSamplesPerSec*wBitsPerSample>>3; // nAvgBytesPerSec;
  1847. pProperties->cbAlign = 1;
  1848. pProperties->cbPrefix = 0;
  1849. HRESULT hr;
  1850. ALLOCATOR_PROPERTIES Actual;
  1851.     if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) 
  1852. return hr;
  1853.     return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
  1854. ? E_FAIL
  1855. : NOERROR);
  1856. }
  1857. HRESULT CRealAudioDecoder::GetMediaType(int iPosition, CMediaType* pmt)
  1858. {
  1859.     if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  1860. *pmt = m_pInput->CurrentMediaType();
  1861. pmt->subtype = MEDIASUBTYPE_PCM;
  1862. WAVEFORMATEX* pwfe = (WAVEFORMATEX*)pmt->ReallocFormatBuffer(sizeof(WAVEFORMATEX));
  1863. if(iPosition < 0) return E_INVALIDARG;
  1864. if(iPosition > (pwfe->nChannels > 2 && pwfe->nChannels <= 6 ? 1 : 0)) return VFW_S_NO_MORE_ITEMS;
  1865. if(!pwfe->wBitsPerSample) pwfe->wBitsPerSample = 16;
  1866. pwfe->cbSize = 0;
  1867. pwfe->wFormatTag = WAVE_FORMAT_PCM;
  1868. pwfe->nBlockAlign = pwfe->nChannels*pwfe->wBitsPerSample>>3;
  1869. pwfe->nAvgBytesPerSec = pwfe->nSamplesPerSec*pwfe->nBlockAlign;
  1870. if(iPosition == 0 && pwfe->nChannels > 2 && pwfe->nChannels <= 6)
  1871. {
  1872. static DWORD chmask[] = 
  1873. {
  1874. KSAUDIO_SPEAKER_DIRECTOUT,
  1875. KSAUDIO_SPEAKER_MONO,
  1876. KSAUDIO_SPEAKER_STEREO,
  1877. KSAUDIO_SPEAKER_STEREO|SPEAKER_FRONT_CENTER,
  1878. KSAUDIO_SPEAKER_QUAD,
  1879. KSAUDIO_SPEAKER_QUAD|SPEAKER_FRONT_CENTER,
  1880. KSAUDIO_SPEAKER_5POINT1
  1881. };
  1882. WAVEFORMATEXTENSIBLE* pwfex = (WAVEFORMATEXTENSIBLE*)pmt->ReallocFormatBuffer(sizeof(WAVEFORMATEXTENSIBLE));
  1883. pwfex->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
  1884. pwfex->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
  1885. pwfex->dwChannelMask = chmask[pwfex->Format.nChannels];
  1886. pwfex->Samples.wValidBitsPerSample = pwfex->Format.wBitsPerSample;
  1887. pwfex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  1888. }
  1889. return S_OK;
  1890. }
  1891. HRESULT CRealAudioDecoder::StartStreaming()
  1892. {
  1893. int w = m_rai.coded_frame_size;
  1894. int h = m_rai.sub_packet_h;
  1895. int sps = m_rai.sub_packet_size;
  1896. int len = w*h;
  1897. m_buff.Allocate(len*2);
  1898. m_bufflen = 0;
  1899. m_rtBuffStart = 0;
  1900. return __super::StartStreaming();
  1901. }
  1902. HRESULT CRealAudioDecoder::StopStreaming()
  1903. {
  1904. m_buff.Free();
  1905. m_bufflen = 0;
  1906. return __super::StopStreaming();
  1907. }
  1908. HRESULT CRealAudioDecoder::EndOfStream()
  1909. {
  1910. return __super::EndOfStream();
  1911. }
  1912. HRESULT CRealAudioDecoder::BeginFlush()
  1913. {
  1914. return __super::BeginFlush();
  1915. }
  1916. HRESULT CRealAudioDecoder::EndFlush()
  1917. {
  1918. return __super::EndFlush();
  1919. }
  1920. HRESULT CRealAudioDecoder::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  1921. {
  1922. CAutoLock cAutoLock(&m_csReceive);
  1923. m_tStart = tStart;
  1924. m_bufflen = 0;
  1925. m_rtBuffStart = 0;
  1926. return __super::NewSegment(tStart, tStop, dRate);
  1927. }