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

多媒体编程

开发平台:

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 <initguid.h>
  23. #include "RoQSplitter.h"
  24. #include "........includemoreuuids.h"
  25. #ifdef REGISTER_FILTER
  26. const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
  27. {
  28. {&MEDIATYPE_Stream, &MEDIASUBTYPE_RoQ},
  29. {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL},
  30. };
  31. const AMOVIESETUP_PIN sudpPins[] =
  32. {
  33.     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
  34.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
  35. };
  36. const AMOVIESETUP_MEDIATYPE sudPinTypesIn2[] =
  37. {
  38. {&MEDIATYPE_Video, &MEDIASUBTYPE_RoQV},
  39. };
  40. const AMOVIESETUP_MEDIATYPE sudPinTypesOut2[] =
  41. {
  42. {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
  43. };
  44. const AMOVIESETUP_PIN sudpPins2[] =
  45. {
  46.     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn2), sudPinTypesIn2},
  47.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut2), sudPinTypesOut2}
  48. };
  49. const AMOVIESETUP_MEDIATYPE sudPinTypesIn3[] =
  50. {
  51. {&MEDIATYPE_Audio, &MEDIASUBTYPE_RoQA},
  52. };
  53. const AMOVIESETUP_MEDIATYPE sudPinTypesOut3[] =
  54. {
  55. {&MEDIATYPE_Audio, &MEDIASUBTYPE_PCM},
  56. };
  57. const AMOVIESETUP_PIN sudpPins3[] =
  58. {
  59.     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn3), sudPinTypesIn3},
  60.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut3), sudPinTypesOut3}
  61. };
  62. const AMOVIESETUP_FILTER sudFilter[] =
  63. {
  64. {&__uuidof(CRoQSplitterFilter), L"RoQ Splitter", MERIT_NORMAL+1, countof(sudpPins), sudpPins},
  65. {&__uuidof(CRoQSourceFilter), L"RoQ Source", MERIT_NORMAL+1, 0, NULL},
  66. {&__uuidof(CRoQVideoDecoder), L"RoQ Video Decoder", MERIT_UNLIKELY, countof(sudpPins2), sudpPins2},
  67. {&__uuidof(CRoQAudioDecoder), L"RoQ Audio Decoder", MERIT_UNLIKELY, countof(sudpPins3), sudpPins3},
  68. };
  69. CFactoryTemplate g_Templates[] =
  70. {
  71. {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CRoQSplitterFilter>, NULL, &sudFilter[0]},
  72. {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CRoQSourceFilter>, NULL, &sudFilter[1]},
  73.     {sudFilter[2].strName, sudFilter[2].clsID, CreateInstance<CRoQVideoDecoder>, NULL, &sudFilter[2]},
  74.     {sudFilter[3].strName, sudFilter[3].clsID, CreateInstance<CRoQAudioDecoder>, NULL, &sudFilter[3]},
  75. };
  76. int g_cTemplates = countof(g_Templates);
  77. STDAPI DllRegisterServer()
  78. {
  79. RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_RoQ, _T("0,8,,8410FFFFFFFF1E00"), _T(".roq"), NULL);
  80. return AMovieDllRegisterServer2(TRUE);
  81. }
  82. STDAPI DllUnregisterServer()
  83. {
  84. UnRegisterSourceFilter(MEDIASUBTYPE_RoQ);
  85. return AMovieDllRegisterServer2(FALSE);
  86. }
  87. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  88. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
  89. {
  90.     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
  91. }
  92. #endif
  93. //
  94. // CRoQSplitterFilter
  95. //
  96. CRoQSplitterFilter::CRoQSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
  97. : CBaseSplitterFilter(NAME("CRoQSplitterFilter"), pUnk, phr, __uuidof(this))
  98. {
  99. }
  100. HRESULT CRoQSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
  101. {
  102. CheckPointer(pAsyncReader, E_POINTER);
  103. HRESULT hr = E_FAIL;
  104. m_pAsyncReader = pAsyncReader;
  105. UINT64 hdr = 0, hdrchk = 0x001effffffff1084;
  106. m_pAsyncReader->SyncRead(0, 8, (BYTE*)&hdr);
  107. if(hdr != hdrchk) return E_FAIL;
  108. //
  109. m_rtNewStart = m_rtCurrent = 0;
  110. m_rtNewStop = m_rtStop = m_rtDuration = 0;
  111. // pins
  112. CMediaType mt;
  113. CArray<CMediaType> mts;
  114. int iHasVideo = 0;
  115. int iHasAudio = 0;
  116. m_index.RemoveAll();
  117. __int64 audiosamples = 0;
  118. roq_info ri;
  119. memset(&ri, 0, sizeof(ri));
  120. roq_chunk rc;
  121. UINT64 pos = 8;
  122. while(S_OK == m_pAsyncReader->SyncRead(pos, sizeof(rc), (BYTE*)&rc))
  123. {
  124. pos += sizeof(rc);
  125. if(rc.id == 0x1001)
  126. {
  127. if(S_OK != m_pAsyncReader->SyncRead(pos, sizeof(ri), (BYTE*)&ri) || ri.w == 0 || ri.h == 0)
  128. break;
  129. }
  130. else if(rc.id == 0x1002 || rc.id == 0x1011)
  131. {
  132. if(!iHasVideo && ri.w > 0 && ri.h > 0)
  133. {
  134. mts.RemoveAll();
  135. mt.InitMediaType();
  136. mt.majortype = MEDIATYPE_Video;
  137. mt.subtype = MEDIASUBTYPE_RoQV;
  138. mt.formattype = FORMAT_VideoInfo;
  139. VIDEOINFOHEADER vih;
  140. memset(&vih, 0, sizeof(vih));
  141. vih.AvgTimePerFrame = 10000000i64/30;
  142. vih.bmiHeader.biSize = sizeof(vih.bmiHeader.biSize);
  143. vih.bmiHeader.biWidth = ri.w;
  144. vih.bmiHeader.biHeight = ri.h;
  145. vih.bmiHeader.biCompression = MEDIASUBTYPE_RoQV.Data1;
  146. mt.SetFormat((BYTE*)&vih, sizeof(vih));
  147. mt.lSampleSize = 1;
  148. mts.Add(mt);
  149. CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CBaseSplitterOutputPin(mts, L"Video", this, this, &hr));
  150. AddOutputPin(0, pPinOut);
  151. }
  152. if(rc.id == 0x1002)
  153. {
  154. iHasVideo++;
  155. index i;
  156. i.rtv = 10000000i64*m_index.GetCount()/30;
  157. i.rta = 10000000i64*audiosamples/22050;
  158. i.fp = pos - sizeof(rc);
  159. m_index.AddTail(i);
  160. }
  161. }
  162. else if(rc.id == 0x1020 || rc.id == 0x1021)
  163. {
  164. if(!iHasAudio)
  165. {
  166. mts.RemoveAll();
  167. mt.InitMediaType();
  168. mt.majortype = MEDIATYPE_Audio;
  169. mt.subtype = MEDIASUBTYPE_RoQA;
  170. mt.formattype = FORMAT_WaveFormatEx;
  171. WAVEFORMATEX wfe;
  172. memset(&wfe, 0, sizeof(wfe));
  173. wfe.wFormatTag = (WORD)WAVE_FORMAT_RoQA; // cut into half, hehe, like anyone would care
  174. wfe.nChannels = (rc.id&1)+1;
  175. wfe.nSamplesPerSec = 22050;
  176. wfe.wBitsPerSample = 16;
  177. mt.SetFormat((BYTE*)&wfe, sizeof(wfe));
  178. mt.lSampleSize = 1;
  179. mts.Add(mt);
  180. CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CBaseSplitterOutputPin(mts, L"Audio", this, this, &hr));
  181. AddOutputPin(1, pPinOut);
  182. }
  183. iHasAudio++;
  184. audiosamples += rc.size / ((rc.id&1)+1);
  185. }
  186. pos += rc.size;
  187. }
  188. //
  189. m_rtNewStop = m_rtStop = m_rtDuration = 10000000i64*iHasVideo/30;
  190. return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
  191. }
  192. bool CRoQSplitterFilter::DemuxInit()
  193. {
  194. m_indexpos = m_index.GetHeadPosition();
  195. return(true);
  196. }
  197. void CRoQSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
  198. {
  199. if(rt <= 0)
  200. {
  201. m_indexpos = m_index.GetHeadPosition();
  202. }
  203. else
  204. {
  205. m_indexpos = m_index.GetTailPosition();
  206. while(m_indexpos && m_index.GetPrev(m_indexpos).rtv > rt);
  207. }
  208. }
  209. bool CRoQSplitterFilter::DemuxLoop()
  210. {
  211. if(!m_indexpos) return(true);
  212. index& i = m_index.GetAt(m_indexpos);
  213. REFERENCE_TIME rtVideo = i.rtv, rtAudio = i.rta;
  214. HRESULT hr = S_OK;
  215. UINT64 pos = i.fp;
  216. roq_chunk rc;
  217. while(S_OK == (hr = m_pAsyncReader->SyncRead(pos, sizeof(rc), (BYTE*)&rc))
  218. && !CheckRequest(NULL))
  219. {
  220. pos += sizeof(rc);
  221. CAutoPtr<Packet> p(new Packet());
  222. if(rc.id == 0x1002 || rc.id == 0x1011 || rc.id == 0x1020 || rc.id == 0x1021)
  223. {
  224. p->pData.SetSize(sizeof(rc) + rc.size);
  225. memcpy(p->pData.GetData(), &rc, sizeof(rc));
  226. if(S_OK != (hr = m_pAsyncReader->SyncRead(pos, rc.size, p->pData.GetData() + sizeof(rc))))
  227. break;
  228. }
  229. if(rc.id == 0x1002 || rc.id == 0x1011)
  230. {
  231. p->TrackNumber = 0;
  232. p->bSyncPoint = rtVideo == 0;
  233. p->rtStart = rtVideo;
  234. p->rtStop = rtVideo += (rc.id == 0x1011 ? 10000000i64/30 : 0);
  235. TRACE(_T("v: %I64d - %I64d (%d)n"), p->rtStart/10000, p->rtStop/10000, p->pData.GetSize());
  236. }
  237. else if(rc.id == 0x1020 || rc.id == 0x1021)
  238. {
  239. int nChannels = (rc.id&1)+1;
  240. p->TrackNumber = 1;
  241. p->bSyncPoint = TRUE;
  242. p->rtStart = rtAudio;
  243. p->rtStop = rtAudio += 10000000i64*rc.size/(nChannels*22050);
  244. TRACE(_T("a: %I64d - %I64d (%d)n"), p->rtStart/10000, p->rtStop/10000, p->pData.GetSize());
  245. }
  246. if(rc.id == 0x1002 || rc.id == 0x1011 || rc.id == 0x1020 || rc.id == 0x1021)
  247. {
  248. hr = DeliverPacket(p);
  249. }
  250. pos += rc.size;
  251. }
  252. return(true);
  253. }
  254. //
  255. // CRoQSourceFilter
  256. //
  257. CRoQSourceFilter::CRoQSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
  258. : CRoQSplitterFilter(pUnk, phr)
  259. {
  260. m_clsid = __uuidof(this);
  261. m_pInput.Free();
  262. }
  263. //
  264. // CRoQVideoDecoder
  265. //
  266. CRoQVideoDecoder::CRoQVideoDecoder(LPUNKNOWN lpunk, HRESULT* phr)
  267. : CTransformFilter(NAME("CRoQVideoDecoder"), lpunk, __uuidof(this))
  268. {
  269. if(phr) *phr = S_OK;
  270. }
  271. CRoQVideoDecoder::~CRoQVideoDecoder()
  272. {
  273. }
  274. void CRoQVideoDecoder::apply_vector_2x2(int x, int y, roq_cell* cell)
  275. {
  276. unsigned char* yptr;
  277. yptr = m_y[0] + (y * m_pitch) + x;
  278. *yptr++ = cell->y0;
  279. *yptr++ = cell->y1;
  280. yptr += (m_pitch - 2);
  281. *yptr++ = cell->y2;
  282. *yptr++ = cell->y3;
  283. m_u[0][(y/2) * (m_pitch/2) + x/2] = cell->u;
  284. m_v[0][(y/2) * (m_pitch/2) + x/2] = cell->v;
  285. }
  286. void CRoQVideoDecoder::apply_vector_4x4(int x, int y, roq_cell* cell)
  287. {
  288. unsigned long row_inc, c_row_inc;
  289. register unsigned char y0, y1, u, v;
  290. unsigned char *yptr, *uptr, *vptr;
  291. yptr = m_y[0] + (y * m_pitch) + x;
  292. uptr = m_u[0] + (y/2) * (m_pitch/2) + x/2;
  293. vptr = m_v[0] + (y/2) * (m_pitch/2) + x/2;
  294. row_inc = m_pitch - 4;
  295. c_row_inc = (m_pitch/2) - 2;
  296. *yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v;
  297. *yptr++ = y0;
  298. *yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
  299. *yptr++ = y1;
  300. yptr += row_inc;
  301. *yptr++ = y0;
  302. *yptr++ = y0;
  303. *yptr++ = y1;
  304. *yptr++ = y1;
  305. yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
  306. *yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
  307. *yptr++ = y0;
  308. *yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
  309. *yptr++ = y1;
  310. yptr += row_inc;
  311. *yptr++ = y0;
  312. *yptr++ = y0;
  313. *yptr++ = y1;
  314. *yptr++ = y1;
  315. }
  316. void CRoQVideoDecoder::apply_motion_4x4(int x, int y, unsigned char mv, char mean_x, char mean_y)
  317. {
  318. int i, mx, my;
  319. unsigned char *pa, *pb;
  320. mx = x + 8 - (mv >> 4) - mean_x;
  321. my = y + 8 - (mv & 0xf) - mean_y;
  322. pa = m_y[0] + (y * m_pitch) + x;
  323. pb = m_y[1] + (my * m_pitch) + mx;
  324. for(i = 0; i < 4; i++)
  325. {
  326. pa[0] = pb[0];
  327. pa[1] = pb[1];
  328. pa[2] = pb[2];
  329. pa[3] = pb[3];
  330. pa += m_pitch;
  331. pb += m_pitch;
  332. }
  333. pa = m_u[0] + (y/2) * (m_pitch/2) + x/2;
  334. pb = m_u[1] + (my/2) * (m_pitch/2) + (mx + 1)/2;
  335. for(i = 0; i < 2; i++)
  336. {
  337. pa[0] = pb[0];
  338. pa[1] = pb[1];
  339. pa += m_pitch/2;
  340. pb += m_pitch/2;
  341. }
  342. pa = m_v[0] + (y/2) * (m_pitch/2) + x/2;
  343. pb = m_v[1] + (my/2) * (m_pitch/2) + (mx + 1)/2;
  344. for(i = 0; i < 2; i++)
  345. {
  346. pa[0] = pb[0];
  347. pa[1] = pb[1];
  348. pa += m_pitch/2;
  349. pb += m_pitch/2;
  350. }
  351. }
  352. void CRoQVideoDecoder::apply_motion_8x8(int x, int y, unsigned char mv, char mean_x, char mean_y)
  353. {
  354. int mx, my, i;
  355. unsigned char *pa, *pb;
  356. mx = x + 8 - (mv >> 4) - mean_x;
  357. my = y + 8 - (mv & 0xf) - mean_y;
  358. pa = m_y[0] + (y * m_pitch) + x;
  359. pb = m_y[1] + (my * m_pitch) + mx;
  360. for(i = 0; i < 8; i++)
  361. {
  362. pa[0] = pb[0];
  363. pa[1] = pb[1];
  364. pa[2] = pb[2];
  365. pa[3] = pb[3];
  366. pa[4] = pb[4];
  367. pa[5] = pb[5];
  368. pa[6] = pb[6];
  369. pa[7] = pb[7];
  370. pa += m_pitch;
  371. pb += m_pitch;
  372. }
  373. pa = m_u[0] + (y/2) * (m_pitch/2) + x/2;
  374. pb = m_u[1] + (my/2) * (m_pitch/2) + (mx + 1)/2;
  375. for(i = 0; i < 4; i++)
  376. {
  377. pa[0] = pb[0];
  378. pa[1] = pb[1];
  379. pa[2] = pb[2];
  380. pa[3] = pb[3];
  381. pa += m_pitch/2;
  382. pb += m_pitch/2;
  383. }
  384. pa = m_v[0] + (y/2) * (m_pitch/2) + x/2;
  385. pb = m_v[1] + (my/2) * (m_pitch/2) + (mx + 1)/2;
  386. for(i = 0; i < 4; i++)
  387. {
  388. pa[0] = pb[0];
  389. pa[1] = pb[1];
  390. pa[2] = pb[2];
  391. pa[3] = pb[3];
  392. pa += m_pitch/2;
  393. pb += m_pitch/2;
  394. }
  395. }
  396. HRESULT CRoQVideoDecoder::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
  397. {
  398. CAutoLock cAutoLock(&m_csReceive);
  399. m_rtStart = tStart;
  400. BITMAPINFOHEADER bih;
  401. ExtractBIH(&m_pInput->CurrentMediaType(), &bih);
  402. int size = bih.biWidth*bih.biHeight;
  403. memset(m_y[0], 0, size);
  404. memset(m_u[0], 0x80, size/2);
  405. memset(m_y[1], 0, size);
  406. memset(m_u[1], 0x80, size/2);
  407. return __super::NewSegment(tStart, tStop, dRate);
  408. }
  409. HRESULT CRoQVideoDecoder::Transform(IMediaSample* pIn, IMediaSample* pOut)
  410. {
  411. CAutoLock cAutoLock(&m_csReceive);
  412. HRESULT hr;
  413. AM_MEDIA_TYPE* pmt;
  414. if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
  415. {
  416. CMediaType mt(*pmt);
  417. m_pOutput->SetMediaType(&mt);
  418. DeleteMediaType(pmt);
  419. }
  420. BYTE* pDataIn = NULL;
  421. if(FAILED(hr = pIn->GetPointer(&pDataIn))) return hr;
  422. long len = pIn->GetActualDataLength();
  423. if(len <= 0) return S_OK; // nothing to do
  424. REFERENCE_TIME rtStart = 0, rtStop = 0;
  425. pIn->GetTime(&rtStart, &rtStop);
  426. if(pIn->IsPreroll() == S_OK || rtStart < 0)
  427. return S_OK;
  428. BYTE* pDataOut = NULL;
  429. if(FAILED(hr = pOut->GetPointer(&pDataOut)))
  430. return hr;
  431. BITMAPINFOHEADER bih;
  432. ExtractBIH(&m_pInput->CurrentMediaType(), &bih);
  433. int w = bih.biWidth, h = bih.biHeight;
  434. // TODO: decode picture into m_pI420
  435. roq_chunk* rc = (roq_chunk*)pDataIn;
  436. pDataIn += sizeof(roq_chunk);
  437. if(rc->id == 0x1002)
  438. {
  439. DWORD nv1 = rc->arg>>8;
  440. if(nv1 == 0) nv1 = 256;
  441. DWORD nv2 = rc->arg&0xff;
  442. if(nv2 == 0 && nv1 * 6 < rc->size) nv2 = 256;
  443. memcpy(m_cells, pDataIn, sizeof(m_cells[0])*nv1);
  444. pDataIn += sizeof(m_cells[0])*nv1;
  445. for(int i = 0; i < (int)nv2; i++)
  446. for(int j = 0; j < 4; j++)
  447. m_qcells[i].idx[j] = &m_cells[*pDataIn++];
  448. return S_FALSE;
  449. }
  450. else if(rc->id == 0x1011)
  451. {
  452. int bpos = 0, xpos = 0, ypos = 0;
  453. int vqflg = 0, vqflg_pos = -1, vqid;
  454. roq_qcell* qcell = NULL;
  455. BYTE* buf = pDataIn;
  456. while(bpos < (int)rc->size && ypos < h)
  457. {
  458. for(int yp = ypos; yp < ypos + 16; yp += 8)
  459. {
  460. for(int xp = xpos; xp < xpos + 16; xp += 8)
  461. {
  462. if(vqflg_pos < 0)
  463. {
  464. vqflg = buf[bpos++];
  465. vqflg |= buf[bpos++]<<8;
  466. vqflg_pos = 7;
  467. }
  468. vqid = (vqflg >> (vqflg_pos * 2)) & 3;
  469. vqflg_pos--;
  470. switch(vqid)
  471. {
  472. case 0:
  473. break;
  474. case 1:
  475. apply_motion_8x8(xp, yp, buf[bpos++], rc->arg >> 8, rc->arg & 0xff);
  476. break;
  477. case 2:
  478. qcell = m_qcells + buf[bpos++];
  479. apply_vector_4x4(xp, yp, qcell->idx[0]);
  480. apply_vector_4x4(xp+4, yp, qcell->idx[1]);
  481. apply_vector_4x4(xp, yp+4, qcell->idx[2]);
  482. apply_vector_4x4(xp+4, yp+4, qcell->idx[3]);
  483. break;
  484. case 3:
  485. for(int k = 0; k < 4; k++)
  486. {
  487. int x = xp, y = yp;
  488. if(k&1) x += 4;
  489. if(k&2) y += 4;
  490. if(vqflg_pos < 0)
  491. {
  492. vqflg = buf[bpos++];
  493. vqflg |= buf[bpos++]<<8;
  494. vqflg_pos = 7;
  495. }
  496. vqid = (vqflg >> (vqflg_pos * 2)) & 3;
  497. vqflg_pos--;
  498. switch(vqid)
  499. {
  500. case 0:
  501. break;
  502. case 1:
  503. apply_motion_4x4(x, y, buf[bpos++], rc->arg >> 8, rc->arg & 0xff);
  504. break;
  505. case 2:
  506. qcell = m_qcells + buf[bpos++];
  507. apply_vector_2x2(x, y, qcell->idx[0]);
  508. apply_vector_2x2(x+2, y, qcell->idx[1]);
  509. apply_vector_2x2(x, y+2, qcell->idx[2]);
  510. apply_vector_2x2(x+2, y+2, qcell->idx[3]);
  511. break;
  512. case 3:
  513. apply_vector_2x2(x, y, &m_cells[buf[bpos++]]);
  514. apply_vector_2x2(x+2, y, &m_cells[buf[bpos++]]);
  515. apply_vector_2x2(x, y+2, &m_cells[buf[bpos++]]);
  516. apply_vector_2x2(x+2, y+2, &m_cells[buf[bpos++]]);
  517. break;
  518. }
  519. }
  520. break;
  521. }
  522. }
  523. }
  524. xpos += 16;
  525. if(xpos >= w) {xpos -= w; ypos += 16;}
  526. }
  527. if(m_rtStart+rtStart == 0)
  528. {
  529. memcpy(m_y[1], m_y[0], w*h*3/2);
  530. }
  531. else
  532. {
  533. BYTE* tmp;
  534. tmp = m_y[0]; m_y[0] = m_y[1]; m_y[1] = tmp;
  535. tmp = m_u[0]; m_u[0] = m_u[1]; m_u[1] = tmp;
  536. tmp = m_v[0]; m_v[0] = m_v[1]; m_v[1] = tmp;
  537. }
  538. }
  539. else
  540. {
  541. return E_UNEXPECTED;
  542. }
  543. if(rtStart < 0)
  544. return S_FALSE;
  545. Copy(pDataOut, m_y[1], w, h);
  546. pOut->SetTime(&rtStart, &rtStop);
  547. return S_OK;
  548. }
  549. void CRoQVideoDecoder::Copy(BYTE* pOut, BYTE* pIn, DWORD w, DWORD h)
  550. {
  551. BITMAPINFOHEADER bihOut;
  552. ExtractBIH(&m_pOutput->CurrentMediaType(), &bihOut);
  553. int pitchIn = w;
  554. int pitchInUV = pitchIn>>1;
  555. BYTE* pInU = pIn + pitchIn*h;
  556. BYTE* pInV = pInU + pitchInUV*h/2;
  557. if(bihOut.biCompression == '2YUY')
  558. {
  559. BitBltFromI420ToYUY2(w, h, pOut, bihOut.biWidth*2, pIn, pInU, pInV, pitchIn);
  560. }
  561. else if(bihOut.biCompression == 'I420' || bihOut.biCompression == 'VUYI')
  562. {
  563. BitBltFromI420ToI420(w, h, pOut, pOut + bihOut.biWidth*h, pOut + bihOut.biWidth*h*5/4, bihOut.biWidth, pIn, pInU, pInV, pitchIn);
  564. }
  565. else if(bihOut.biCompression == '21VY')
  566. {
  567. BitBltFromI420ToI420(w, h, pOut, pOut + bihOut.biWidth*h*5/4, pOut + bihOut.biWidth*h, bihOut.biWidth, pIn, pInU, pInV, pitchIn);
  568. }
  569. else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
  570. {
  571. int pitchOut = bihOut.biWidth*bihOut.biBitCount>>3;
  572. if(bihOut.biHeight > 0)
  573. {
  574. pOut += pitchOut*(h-1);
  575. pitchOut = -pitchOut;
  576. }
  577. if(!BitBltFromI420ToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, pIn, pInU, pInV, pitchIn))
  578. {
  579. for(DWORD y = 0; y < h; y++, pIn += pitchIn, pOut += pitchOut)
  580. memset(pOut, 0, pitchOut);
  581. }
  582. }
  583. }
  584. HRESULT CRoQVideoDecoder::CheckInputType(const CMediaType* mtIn)
  585. {
  586. return mtIn->majortype == MEDIATYPE_Video && mtIn->subtype == MEDIASUBTYPE_RoQV
  587. ? S_OK
  588. : VFW_E_TYPE_NOT_ACCEPTED;
  589. }
  590. HRESULT CRoQVideoDecoder::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  591. {
  592. if(m_pOutput && m_pOutput->IsConnected())
  593. {
  594. BITMAPINFOHEADER bih1, bih2;
  595. if(ExtractBIH(mtOut, &bih1) && ExtractBIH(&m_pOutput->CurrentMediaType(), &bih2)
  596. && abs(bih1.biHeight) != abs(bih2.biHeight))
  597. return VFW_E_TYPE_NOT_ACCEPTED;
  598. }
  599. return SUCCEEDED(CheckInputType(mtIn))
  600. && mtOut->majortype == MEDIATYPE_Video && (mtOut->subtype == MEDIASUBTYPE_YUY2
  601. || mtOut->subtype == MEDIASUBTYPE_YV12
  602. || mtOut->subtype == MEDIASUBTYPE_I420
  603. || mtOut->subtype == MEDIASUBTYPE_IYUV
  604. || mtOut->subtype == MEDIASUBTYPE_ARGB32
  605. || mtOut->subtype == MEDIASUBTYPE_RGB32
  606. || mtOut->subtype == MEDIASUBTYPE_RGB24
  607. || mtOut->subtype == MEDIASUBTYPE_RGB565
  608. || mtOut->subtype == MEDIASUBTYPE_RGB555)
  609. ? S_OK
  610. : VFW_E_TYPE_NOT_ACCEPTED;
  611. }
  612. HRESULT CRoQVideoDecoder::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
  613. {
  614. if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  615. BITMAPINFOHEADER bih;
  616. ExtractBIH(&m_pOutput->CurrentMediaType(), &bih);
  617. pProperties->cBuffers = 1;
  618. pProperties->cbBuffer = bih.biSizeImage;
  619. pProperties->cbAlign = 1;
  620. pProperties->cbPrefix = 0;
  621. HRESULT hr;
  622. ALLOCATOR_PROPERTIES Actual;
  623.     if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) 
  624. return hr;
  625.     return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
  626. ? E_FAIL
  627. : NOERROR);
  628. }
  629. HRESULT CRoQVideoDecoder::GetMediaType(int iPosition, CMediaType* pmt)
  630. {
  631.     if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  632. struct {const GUID* subtype; WORD biPlanes, biBitCount; DWORD biCompression;} fmts[] =
  633. {
  634. {&MEDIASUBTYPE_YV12, 3, 12, '21VY'},
  635. {&MEDIASUBTYPE_I420, 3, 12, '024I'},
  636. {&MEDIASUBTYPE_IYUV, 3, 12, 'VUYI'},
  637. {&MEDIASUBTYPE_YUY2, 1, 16, '2YUY'},
  638. {&MEDIASUBTYPE_ARGB32, 1, 32, BI_RGB},
  639. {&MEDIASUBTYPE_RGB32, 1, 32, BI_RGB},
  640. {&MEDIASUBTYPE_RGB24, 1, 24, BI_RGB},
  641. {&MEDIASUBTYPE_RGB565, 1, 16, BI_RGB},
  642. {&MEDIASUBTYPE_RGB555, 1, 16, BI_RGB},
  643. {&MEDIASUBTYPE_ARGB32, 1, 32, BI_BITFIELDS},
  644. {&MEDIASUBTYPE_RGB32, 1, 32, BI_BITFIELDS},
  645. {&MEDIASUBTYPE_RGB24, 1, 24, BI_BITFIELDS},
  646. {&MEDIASUBTYPE_RGB565, 1, 16, BI_BITFIELDS},
  647. {&MEDIASUBTYPE_RGB555, 1, 16, BI_BITFIELDS},
  648. };
  649. if(iPosition < 0) return E_INVALIDARG;
  650. if(iPosition >= countof(fmts)) return VFW_S_NO_MORE_ITEMS;
  651. BITMAPINFOHEADER bih;
  652. ExtractBIH(&m_pInput->CurrentMediaType(), &bih);
  653. pmt->majortype = MEDIATYPE_Video;
  654. pmt->subtype = *fmts[iPosition].subtype;
  655. pmt->formattype = FORMAT_VideoInfo;
  656. BITMAPINFOHEADER bihOut;
  657. memset(&bihOut, 0, sizeof(bihOut));
  658. bihOut.biSize = sizeof(bihOut);
  659. bihOut.biWidth = bih.biWidth;
  660. bihOut.biHeight = bih.biHeight;
  661. bihOut.biPlanes = fmts[iPosition].biPlanes;
  662. bihOut.biBitCount = fmts[iPosition].biBitCount;
  663. bihOut.biCompression = fmts[iPosition].biCompression;
  664. bihOut.biSizeImage = bih.biWidth*bih.biHeight*bihOut.biBitCount>>3;
  665. VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
  666. memset(vih, 0, sizeof(VIDEOINFOHEADER));
  667. vih->bmiHeader = bihOut;
  668. CorrectMediaType(pmt);
  669. return S_OK;
  670. }
  671. HRESULT CRoQVideoDecoder::StartStreaming()
  672. {
  673. BITMAPINFOHEADER bih;
  674. ExtractBIH(&m_pInput->CurrentMediaType(), &bih);
  675. int size = bih.biWidth*bih.biHeight;
  676. m_y[0] = new BYTE[size*3/2];
  677. m_u[0] = m_y[0] + size;
  678. m_v[0] = m_y[0] + size*5/4;
  679. m_y[1] = new BYTE[size*3/2];
  680. m_u[1] = m_y[1] + size;
  681. m_v[1] = m_y[1] + size*5/4;
  682. m_pitch = bih.biWidth;
  683. return __super::StartStreaming();
  684. }
  685. HRESULT CRoQVideoDecoder::StopStreaming()
  686. {
  687. delete [] m_y[0]; m_y[0] = NULL;
  688. delete [] m_y[1]; m_y[1] = NULL;
  689. return __super::StopStreaming();
  690. }
  691. //
  692. // CRealAudioDecoder
  693. //
  694. CRoQAudioDecoder::CRoQAudioDecoder(LPUNKNOWN lpunk, HRESULT* phr)
  695. : CTransformFilter(NAME("CRoQAudioDecoder"), lpunk, __uuidof(this))
  696. {
  697. if(phr) *phr = S_OK;
  698. }
  699. CRoQAudioDecoder::~CRoQAudioDecoder()
  700. {
  701. }
  702. HRESULT CRoQAudioDecoder::Transform(IMediaSample* pIn, IMediaSample* pOut)
  703. {
  704. HRESULT hr;
  705. AM_MEDIA_TYPE* pmt;
  706. if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
  707. {
  708. CMediaType mt(*pmt);
  709. m_pOutput->SetMediaType(&mt);
  710. DeleteMediaType(pmt);
  711. }
  712. WAVEFORMATEX* pwfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
  713. BYTE* pDataIn = NULL;
  714. if(FAILED(hr = pIn->GetPointer(&pDataIn)))
  715. return hr;
  716. long len = pIn->GetActualDataLength();
  717. if(len <= 0) return S_OK;
  718. REFERENCE_TIME rtStart, rtStop;
  719. pIn->GetTime(&rtStart, &rtStop);
  720. if(pIn->IsPreroll() == S_OK || rtStart < 0)
  721. return S_OK;
  722. BYTE* pDataOut = NULL;
  723. if(FAILED(hr = pOut->GetPointer(&pDataOut)))
  724. return hr;
  725. long size = pOut->GetSize();
  726. if(size <= 0)
  727. return E_FAIL;
  728. roq_chunk* rc = (roq_chunk*)pDataIn;
  729. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
  730. if(wfe->nChannels == 1)
  731. {
  732. int mono = (short)rc->arg;
  733. unsigned char* src = pDataIn + sizeof(roq_chunk);
  734. short* dst = (short*)pDataOut;
  735. for(int i = sizeof(roq_chunk); i < len; i++, src++, dst++)
  736. {
  737. short diff = (*src&0x7f)*(*src&0x7f);
  738. if(*src&0x80) diff = -diff;
  739. mono += diff;
  740. *dst = (short)mono;
  741. }
  742. }
  743. else if(wfe->nChannels == 2)
  744. {
  745. int left = (char)(rc->arg>>8)<<8;
  746. int right = (char)(rc->arg)<<8;
  747. unsigned char* src = pDataIn + sizeof(roq_chunk);
  748. short* dst = (short*)pDataOut;
  749. for(int i = sizeof(roq_chunk); i < len; i+=2, src++, dst++)
  750. {
  751. short diff = (*src&0x7f)*(*src&0x7f);
  752. if(*src&0x80) diff = -diff;
  753. ASSERT((int)left + diff <= SHRT_MAX && (int)left + diff >= SHRT_MIN);
  754. left += diff;
  755. *dst = (short)left;
  756. src++; dst++;
  757. diff = (*src&0x7f)*(*src&0x7f);
  758. if(*src&0x80) diff = -diff;
  759. ASSERT((int)right + diff <= SHRT_MAX && (int)right + diff >= SHRT_MIN);
  760. right += diff;
  761. *dst = (short)right;
  762. }
  763. }
  764. else
  765. {
  766. return E_UNEXPECTED;
  767. }
  768. pOut->SetTime(&rtStart, &rtStop);
  769. pOut->SetActualDataLength(2*(len-sizeof(roq_chunk)));
  770. return S_OK;
  771. }
  772. HRESULT CRoQAudioDecoder::CheckInputType(const CMediaType* mtIn)
  773. {
  774. return mtIn->majortype == MEDIATYPE_Audio && mtIn->subtype == MEDIASUBTYPE_RoQA
  775. ? S_OK
  776. : VFW_E_TYPE_NOT_ACCEPTED;
  777. }
  778. HRESULT CRoQAudioDecoder::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  779. {
  780. return SUCCEEDED(CheckInputType(mtIn))
  781. && mtOut->majortype == MEDIATYPE_Audio && mtOut->subtype == MEDIASUBTYPE_PCM
  782. ? S_OK
  783. : VFW_E_TYPE_NOT_ACCEPTED;
  784. }
  785. HRESULT CRoQAudioDecoder::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
  786. {
  787. if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  788. CComPtr<IMemAllocator> pAllocatorIn;
  789. m_pInput->GetAllocator(&pAllocatorIn);
  790. if(!pAllocatorIn) return E_UNEXPECTED;
  791. WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
  792. // ok, maybe this is too much...
  793. pProperties->cBuffers = 8;
  794. pProperties->cbBuffer = wfe->nChannels*wfe->nSamplesPerSec*wfe->wBitsPerSample>>3; // nAvgBytesPerSec;
  795. pProperties->cbAlign = 1;
  796. pProperties->cbPrefix = 0;
  797. HRESULT hr;
  798. ALLOCATOR_PROPERTIES Actual;
  799.     if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual))) 
  800. return hr;
  801.     return pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
  802. ? E_FAIL
  803. : NOERROR;
  804. }
  805. HRESULT CRoQAudioDecoder::GetMediaType(int iPosition, CMediaType* pmt)
  806. {
  807.     if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
  808. if(iPosition < 0) return E_INVALIDARG;
  809. if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
  810. *pmt = m_pInput->CurrentMediaType();
  811. pmt->subtype = MEDIASUBTYPE_PCM;
  812. WAVEFORMATEX* wfe = (WAVEFORMATEX*)pmt->ReallocFormatBuffer(sizeof(WAVEFORMATEX));
  813. wfe->cbSize = 0;
  814. wfe->wFormatTag = WAVE_FORMAT_PCM;
  815. wfe->nBlockAlign = wfe->nChannels*wfe->wBitsPerSample>>3;
  816. wfe->nAvgBytesPerSec = wfe->nSamplesPerSec*wfe->nBlockAlign;
  817. return S_OK;
  818. }