00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include <initguid.h>
00024 #include "RoQSplitter.h"
00025 #include "..\..\..\..\include\moreuuids.h"
00026
00027 #ifdef REGISTER_FILTER
00028
00029 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00030 {
00031 {&MEDIATYPE_Stream, &MEDIASUBTYPE_RoQ},
00032 {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL},
00033 };
00034
00035 const AMOVIESETUP_PIN sudpPins[] =
00036 {
00037 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00038 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
00039 };
00040
00041 const AMOVIESETUP_MEDIATYPE sudPinTypesIn2[] =
00042 {
00043 {&MEDIATYPE_Video, &MEDIASUBTYPE_RoQV},
00044 };
00045
00046 const AMOVIESETUP_MEDIATYPE sudPinTypesOut2[] =
00047 {
00048 {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
00049 };
00050
00051 const AMOVIESETUP_PIN sudpPins2[] =
00052 {
00053 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn2), sudPinTypesIn2},
00054 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut2), sudPinTypesOut2}
00055 };
00056
00057 const AMOVIESETUP_MEDIATYPE sudPinTypesIn3[] =
00058 {
00059 {&MEDIATYPE_Audio, &MEDIASUBTYPE_RoQA},
00060 };
00061
00062 const AMOVIESETUP_MEDIATYPE sudPinTypesOut3[] =
00063 {
00064 {&MEDIATYPE_Audio, &MEDIASUBTYPE_PCM},
00065 };
00066
00067 const AMOVIESETUP_PIN sudpPins3[] =
00068 {
00069 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn3), sudPinTypesIn3},
00070 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut3), sudPinTypesOut3}
00071 };
00072
00073 const AMOVIESETUP_FILTER sudFilter[] =
00074 {
00075 {&__uuidof(CRoQSplitterFilter), L"RoQ Splitter", MERIT_NORMAL+1, countof(sudpPins), sudpPins},
00076 {&__uuidof(CRoQSourceFilter), L"RoQ Source", MERIT_NORMAL+1, 0, NULL},
00077 {&__uuidof(CRoQVideoDecoder), L"RoQ Video Decoder", MERIT_UNLIKELY, countof(sudpPins2), sudpPins2},
00078 {&__uuidof(CRoQAudioDecoder), L"RoQ Audio Decoder", MERIT_UNLIKELY, countof(sudpPins3), sudpPins3},
00079 };
00080
00081 CFactoryTemplate g_Templates[] =
00082 {
00083 {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CRoQSplitterFilter>, NULL, &sudFilter[0]},
00084 {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CRoQSourceFilter>, NULL, &sudFilter[1]},
00085 {sudFilter[2].strName, sudFilter[2].clsID, CreateInstance<CRoQVideoDecoder>, NULL, &sudFilter[2]},
00086 {sudFilter[3].strName, sudFilter[3].clsID, CreateInstance<CRoQAudioDecoder>, NULL, &sudFilter[3]},
00087 };
00088
00089 int g_cTemplates = countof(g_Templates);
00090
00091 STDAPI DllRegisterServer()
00092 {
00093 RegisterSourceFilter(CLSID_AsyncReader, MEDIASUBTYPE_RoQ, _T("0,8,,8410FFFFFFFF1E00"), _T(".roq"), NULL);
00094
00095 return AMovieDllRegisterServer2(TRUE);
00096 }
00097
00098 STDAPI DllUnregisterServer()
00099 {
00100 UnRegisterSourceFilter(MEDIASUBTYPE_RoQ);
00101
00102 return AMovieDllRegisterServer2(FALSE);
00103 }
00104
00105 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00106
00107 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00108 {
00109 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00110 }
00111
00112 #endif
00113
00114
00115
00116
00117
00118 CRoQSplitterFilter::CRoQSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
00119 : CBaseSplitterFilter(NAME("CRoQSplitterFilter"), pUnk, phr, __uuidof(this))
00120 {
00121 }
00122
00123 HRESULT CRoQSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
00124 {
00125 CheckPointer(pAsyncReader, E_POINTER);
00126
00127 HRESULT hr = E_FAIL;
00128
00129 m_pAsyncReader = pAsyncReader;
00130
00131 UINT64 hdr = 0, hdrchk = 0x001effffffff1084;
00132 m_pAsyncReader->SyncRead(0, 8, (BYTE*)&hdr);
00133 if(hdr != hdrchk) return E_FAIL;
00134
00135
00136
00137 m_rtNewStart = m_rtCurrent = 0;
00138 m_rtNewStop = m_rtStop = m_rtDuration = 0;
00139
00140
00141
00142 CMediaType mt;
00143 CArray<CMediaType> mts;
00144
00145 int iHasVideo = 0;
00146 int iHasAudio = 0;
00147
00148 m_index.RemoveAll();
00149 __int64 audiosamples = 0;
00150
00151 roq_info ri;
00152 memset(&ri, 0, sizeof(ri));
00153
00154 roq_chunk rc;
00155
00156 UINT64 pos = 8;
00157
00158 while(S_OK == m_pAsyncReader->SyncRead(pos, sizeof(rc), (BYTE*)&rc))
00159 {
00160 pos += sizeof(rc);
00161
00162 if(rc.id == 0x1001)
00163 {
00164 if(S_OK != m_pAsyncReader->SyncRead(pos, sizeof(ri), (BYTE*)&ri) || ri.w == 0 || ri.h == 0)
00165 break;
00166 }
00167 else if(rc.id == 0x1002 || rc.id == 0x1011)
00168 {
00169 if(!iHasVideo && ri.w > 0 && ri.h > 0)
00170 {
00171 mts.RemoveAll();
00172
00173 mt.InitMediaType();
00174 mt.majortype = MEDIATYPE_Video;
00175 mt.subtype = MEDIASUBTYPE_RoQV;
00176 mt.formattype = FORMAT_VideoInfo;
00177 VIDEOINFOHEADER vih;
00178 memset(&vih, 0, sizeof(vih));
00179 vih.AvgTimePerFrame = 10000000i64/30;
00180 vih.bmiHeader.biSize = sizeof(vih.bmiHeader.biSize);
00181 vih.bmiHeader.biWidth = ri.w;
00182 vih.bmiHeader.biHeight = ri.h;
00183 vih.bmiHeader.biCompression = MEDIASUBTYPE_RoQV.Data1;
00184 mt.SetFormat((BYTE*)&vih, sizeof(vih));
00185 mt.lSampleSize = 1;
00186
00187 mts.Add(mt);
00188
00189 CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CBaseSplitterOutputPin(mts, L"Video", this, this, &hr));
00190 AddOutputPin(0, pPinOut);
00191 }
00192
00193 if(rc.id == 0x1002)
00194 {
00195 iHasVideo++;
00196
00197 index i;
00198 i.rtv = 10000000i64*m_index.GetCount()/30;
00199 i.rta = 10000000i64*audiosamples/22050;
00200 i.fp = pos - sizeof(rc);
00201 m_index.AddTail(i);
00202 }
00203 }
00204 else if(rc.id == 0x1020 || rc.id == 0x1021)
00205 {
00206 if(!iHasAudio)
00207 {
00208 mts.RemoveAll();
00209
00210 mt.InitMediaType();
00211 mt.majortype = MEDIATYPE_Audio;
00212 mt.subtype = MEDIASUBTYPE_RoQA;
00213 mt.formattype = FORMAT_WaveFormatEx;
00214 WAVEFORMATEX wfe;
00215 memset(&wfe, 0, sizeof(wfe));
00216 wfe.wFormatTag = (WORD)WAVE_FORMAT_RoQA;
00217 wfe.nChannels = (rc.id&1)+1;
00218 wfe.nSamplesPerSec = 22050;
00219 wfe.wBitsPerSample = 16;
00220 mt.SetFormat((BYTE*)&wfe, sizeof(wfe));
00221 mt.lSampleSize = 1;
00222 mts.Add(mt);
00223
00224 CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CBaseSplitterOutputPin(mts, L"Audio", this, this, &hr));
00225 AddOutputPin(1, pPinOut);
00226 }
00227
00228 iHasAudio++;
00229
00230 audiosamples += rc.size / ((rc.id&1)+1);
00231 }
00232
00233 pos += rc.size;
00234 }
00235
00236
00237
00238 m_rtNewStop = m_rtStop = m_rtDuration = 10000000i64*iHasVideo/30;
00239
00240 return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
00241 }
00242
00243 bool CRoQSplitterFilter::DemuxInit()
00244 {
00245 m_indexpos = m_index.GetHeadPosition();
00246
00247 return(true);
00248 }
00249
00250 void CRoQSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
00251 {
00252 if(rt <= 0)
00253 {
00254 m_indexpos = m_index.GetHeadPosition();
00255 }
00256 else
00257 {
00258 m_indexpos = m_index.GetTailPosition();
00259 while(m_indexpos && m_index.GetPrev(m_indexpos).rtv > rt);
00260 }
00261 }
00262
00263 bool CRoQSplitterFilter::DemuxLoop()
00264 {
00265 if(!m_indexpos) return(true);
00266
00267 index& i = m_index.GetAt(m_indexpos);
00268
00269 REFERENCE_TIME rtVideo = i.rtv, rtAudio = i.rta;
00270
00271 HRESULT hr = S_OK;
00272
00273 UINT64 pos = i.fp;
00274
00275 roq_chunk rc;
00276 while(S_OK == (hr = m_pAsyncReader->SyncRead(pos, sizeof(rc), (BYTE*)&rc))
00277 && !CheckRequest(NULL))
00278 {
00279 pos += sizeof(rc);
00280
00281 CAutoPtr<Packet> p(new Packet());
00282
00283 if(rc.id == 0x1002 || rc.id == 0x1011 || rc.id == 0x1020 || rc.id == 0x1021)
00284 {
00285 p->pData.SetSize(sizeof(rc) + rc.size);
00286 memcpy(p->pData.GetData(), &rc, sizeof(rc));
00287 if(S_OK != (hr = m_pAsyncReader->SyncRead(pos, rc.size, p->pData.GetData() + sizeof(rc))))
00288 break;
00289 }
00290
00291 if(rc.id == 0x1002 || rc.id == 0x1011)
00292 {
00293 p->TrackNumber = 0;
00294 p->bSyncPoint = rtVideo == 0;
00295 p->rtStart = rtVideo;
00296 p->rtStop = rtVideo += (rc.id == 0x1011 ? 10000000i64/30 : 0);
00297 TRACE(_T("v: %I64d - %I64d (%d)\n"), p->rtStart/10000, p->rtStop/10000, p->pData.GetSize());
00298 }
00299 else if(rc.id == 0x1020 || rc.id == 0x1021)
00300 {
00301 int nChannels = (rc.id&1)+1;
00302
00303 p->TrackNumber = 1;
00304 p->bSyncPoint = TRUE;
00305 p->rtStart = rtAudio;
00306 p->rtStop = rtAudio += 10000000i64*rc.size/(nChannels*22050);
00307 TRACE(_T("a: %I64d - %I64d (%d)\n"), p->rtStart/10000, p->rtStop/10000, p->pData.GetSize());
00308 }
00309
00310 if(rc.id == 0x1002 || rc.id == 0x1011 || rc.id == 0x1020 || rc.id == 0x1021)
00311 {
00312 hr = DeliverPacket(p);
00313 }
00314
00315 pos += rc.size;
00316 }
00317
00318 return(true);
00319 }
00320
00321
00322
00323
00324
00325 CRoQSourceFilter::CRoQSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
00326 : CRoQSplitterFilter(pUnk, phr)
00327 {
00328 m_clsid = __uuidof(this);
00329 m_pInput.Free();
00330 }
00331
00332
00333
00334
00335
00336 CRoQVideoDecoder::CRoQVideoDecoder(LPUNKNOWN lpunk, HRESULT* phr)
00337 : CTransformFilter(NAME("CRoQVideoDecoder"), lpunk, __uuidof(this))
00338 {
00339 if(phr) *phr = S_OK;
00340 }
00341
00342 CRoQVideoDecoder::~CRoQVideoDecoder()
00343 {
00344 }
00345
00346 void CRoQVideoDecoder::apply_vector_2x2(int x, int y, roq_cell* cell)
00347 {
00348 unsigned char* yptr;
00349 yptr = m_y[0] + (y * m_pitch) + x;
00350 *yptr++ = cell->y0;
00351 *yptr++ = cell->y1;
00352 yptr += (m_pitch - 2);
00353 *yptr++ = cell->y2;
00354 *yptr++ = cell->y3;
00355 m_u[0][(y/2) * (m_pitch/2) + x/2] = cell->u;
00356 m_v[0][(y/2) * (m_pitch/2) + x/2] = cell->v;
00357 }
00358
00359 void CRoQVideoDecoder::apply_vector_4x4(int x, int y, roq_cell* cell)
00360 {
00361 unsigned long row_inc, c_row_inc;
00362 register unsigned char y0, y1, u, v;
00363 unsigned char *yptr, *uptr, *vptr;
00364
00365 yptr = m_y[0] + (y * m_pitch) + x;
00366 uptr = m_u[0] + (y/2) * (m_pitch/2) + x/2;
00367 vptr = m_v[0] + (y/2) * (m_pitch/2) + x/2;
00368
00369 row_inc = m_pitch - 4;
00370 c_row_inc = (m_pitch/2) - 2;
00371 *yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v;
00372 *yptr++ = y0;
00373 *yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
00374 *yptr++ = y1;
00375
00376 yptr += row_inc;
00377
00378 *yptr++ = y0;
00379 *yptr++ = y0;
00380 *yptr++ = y1;
00381 *yptr++ = y1;
00382
00383 yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
00384
00385 *yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
00386 *yptr++ = y0;
00387 *yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
00388 *yptr++ = y1;
00389
00390 yptr += row_inc;
00391
00392 *yptr++ = y0;
00393 *yptr++ = y0;
00394 *yptr++ = y1;
00395 *yptr++ = y1;
00396 }
00397
00398 void CRoQVideoDecoder::apply_motion_4x4(int x, int y, unsigned char mv, char mean_x, char mean_y)
00399 {
00400 int i, mx, my;
00401 unsigned char *pa, *pb;
00402
00403 mx = x + 8 - (mv >> 4) - mean_x;
00404 my = y + 8 - (mv & 0xf) - mean_y;
00405
00406 pa = m_y[0] + (y * m_pitch) + x;
00407 pb = m_y[1] + (my * m_pitch) + mx;
00408 for(i = 0; i < 4; i++)
00409 {
00410 pa[0] = pb[0];
00411 pa[1] = pb[1];
00412 pa[2] = pb[2];
00413 pa[3] = pb[3];
00414 pa += m_pitch;
00415 pb += m_pitch;
00416 }
00417
00418 pa = m_u[0] + (y/2) * (m_pitch/2) + x/2;
00419 pb = m_u[1] + (my/2) * (m_pitch/2) + (mx + 1)/2;
00420 for(i = 0; i < 2; i++)
00421 {
00422 pa[0] = pb[0];
00423 pa[1] = pb[1];
00424 pa += m_pitch/2;
00425 pb += m_pitch/2;
00426 }
00427
00428 pa = m_v[0] + (y/2) * (m_pitch/2) + x/2;
00429 pb = m_v[1] + (my/2) * (m_pitch/2) + (mx + 1)/2;
00430 for(i = 0; i < 2; i++)
00431 {
00432 pa[0] = pb[0];
00433 pa[1] = pb[1];
00434 pa += m_pitch/2;
00435 pb += m_pitch/2;
00436 }
00437 }
00438
00439 void CRoQVideoDecoder::apply_motion_8x8(int x, int y, unsigned char mv, char mean_x, char mean_y)
00440 {
00441 int mx, my, i;
00442 unsigned char *pa, *pb;
00443
00444 mx = x + 8 - (mv >> 4) - mean_x;
00445 my = y + 8 - (mv & 0xf) - mean_y;
00446
00447 pa = m_y[0] + (y * m_pitch) + x;
00448 pb = m_y[1] + (my * m_pitch) + mx;
00449 for(i = 0; i < 8; i++)
00450 {
00451 pa[0] = pb[0];
00452 pa[1] = pb[1];
00453 pa[2] = pb[2];
00454 pa[3] = pb[3];
00455 pa[4] = pb[4];
00456 pa[5] = pb[5];
00457 pa[6] = pb[6];
00458 pa[7] = pb[7];
00459 pa += m_pitch;
00460 pb += m_pitch;
00461 }
00462
00463 pa = m_u[0] + (y/2) * (m_pitch/2) + x/2;
00464 pb = m_u[1] + (my/2) * (m_pitch/2) + (mx + 1)/2;
00465 for(i = 0; i < 4; i++)
00466 {
00467 pa[0] = pb[0];
00468 pa[1] = pb[1];
00469 pa[2] = pb[2];
00470 pa[3] = pb[3];
00471 pa += m_pitch/2;
00472 pb += m_pitch/2;
00473 }
00474
00475 pa = m_v[0] + (y/2) * (m_pitch/2) + x/2;
00476 pb = m_v[1] + (my/2) * (m_pitch/2) + (mx + 1)/2;
00477 for(i = 0; i < 4; i++)
00478 {
00479 pa[0] = pb[0];
00480 pa[1] = pb[1];
00481 pa[2] = pb[2];
00482 pa[3] = pb[3];
00483 pa += m_pitch/2;
00484 pb += m_pitch/2;
00485 }
00486 }
00487
00488 HRESULT CRoQVideoDecoder::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
00489 {
00490 CAutoLock cAutoLock(&m_csReceive);
00491
00492 m_rtStart = tStart;
00493
00494 BITMAPINFOHEADER bih;
00495 ExtractBIH(&m_pInput->CurrentMediaType(), &bih);
00496
00497 int size = bih.biWidth*bih.biHeight;
00498
00499 memset(m_y[0], 0, size);
00500 memset(m_u[0], 0x80, size/2);
00501 memset(m_y[1], 0, size);
00502 memset(m_u[1], 0x80, size/2);
00503
00504 return __super::NewSegment(tStart, tStop, dRate);
00505 }
00506
00507 HRESULT CRoQVideoDecoder::Transform(IMediaSample* pIn, IMediaSample* pOut)
00508 {
00509 CAutoLock cAutoLock(&m_csReceive);
00510
00511 HRESULT hr;
00512
00513 AM_MEDIA_TYPE* pmt;
00514 if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
00515 {
00516 CMediaType mt(*pmt);
00517 m_pOutput->SetMediaType(&mt);
00518 DeleteMediaType(pmt);
00519 }
00520
00521 BYTE* pDataIn = NULL;
00522 if(FAILED(hr = pIn->GetPointer(&pDataIn))) return hr;
00523
00524 long len = pIn->GetActualDataLength();
00525 if(len <= 0) return S_OK;
00526
00527 REFERENCE_TIME rtStart = 0, rtStop = 0;
00528 pIn->GetTime(&rtStart, &rtStop);
00529
00530 if(pIn->IsPreroll() == S_OK || rtStart < 0)
00531 return S_OK;
00532
00533 BYTE* pDataOut = NULL;
00534 if(FAILED(hr = pOut->GetPointer(&pDataOut)))
00535 return hr;
00536
00537 BITMAPINFOHEADER bih;
00538 ExtractBIH(&m_pInput->CurrentMediaType(), &bih);
00539
00540 int w = bih.biWidth, h = bih.biHeight;
00541
00542
00543
00544 roq_chunk* rc = (roq_chunk*)pDataIn;
00545
00546 pDataIn += sizeof(roq_chunk);
00547
00548 if(rc->id == 0x1002)
00549 {
00550 DWORD nv1 = rc->arg>>8;
00551 if(nv1 == 0) nv1 = 256;
00552
00553 DWORD nv2 = rc->arg&0xff;
00554 if(nv2 == 0 && nv1 * 6 < rc->size) nv2 = 256;
00555
00556 memcpy(m_cells, pDataIn, sizeof(m_cells[0])*nv1);
00557 pDataIn += sizeof(m_cells[0])*nv1;
00558
00559 for(int i = 0; i < (int)nv2; i++)
00560 for(int j = 0; j < 4; j++)
00561 m_qcells[i].idx[j] = &m_cells[*pDataIn++];
00562
00563 return S_FALSE;
00564 }
00565 else if(rc->id == 0x1011)
00566 {
00567 int bpos = 0, xpos = 0, ypos = 0;
00568 int vqflg = 0, vqflg_pos = -1, vqid;
00569 roq_qcell* qcell = NULL;
00570
00571 BYTE* buf = pDataIn;
00572
00573 while(bpos < (int)rc->size && ypos < h)
00574 {
00575 for(int yp = ypos; yp < ypos + 16; yp += 8)
00576 {
00577 for(int xp = xpos; xp < xpos + 16; xp += 8)
00578 {
00579 if(vqflg_pos < 0)
00580 {
00581 vqflg = buf[bpos++];
00582 vqflg |= buf[bpos++]<<8;
00583 vqflg_pos = 7;
00584 }
00585
00586 vqid = (vqflg >> (vqflg_pos * 2)) & 3;
00587 vqflg_pos--;
00588
00589 switch(vqid)
00590 {
00591 case 0:
00592 break;
00593 case 1:
00594 apply_motion_8x8(xp, yp, buf[bpos++], rc->arg >> 8, rc->arg & 0xff);
00595 break;
00596 case 2:
00597 qcell = m_qcells + buf[bpos++];
00598 apply_vector_4x4(xp, yp, qcell->idx[0]);
00599 apply_vector_4x4(xp+4, yp, qcell->idx[1]);
00600 apply_vector_4x4(xp, yp+4, qcell->idx[2]);
00601 apply_vector_4x4(xp+4, yp+4, qcell->idx[3]);
00602 break;
00603 case 3:
00604 for(int k = 0; k < 4; k++)
00605 {
00606 int x = xp, y = yp;
00607 if(k&1) x += 4;
00608 if(k&2) y += 4;
00609
00610 if(vqflg_pos < 0)
00611 {
00612 vqflg = buf[bpos++];
00613 vqflg |= buf[bpos++]<<8;
00614 vqflg_pos = 7;
00615 }
00616
00617 vqid = (vqflg >> (vqflg_pos * 2)) & 3;
00618 vqflg_pos--;
00619
00620 switch(vqid)
00621 {
00622 case 0:
00623 break;
00624 case 1:
00625 apply_motion_4x4(x, y, buf[bpos++], rc->arg >> 8, rc->arg & 0xff);
00626 break;
00627 case 2:
00628 qcell = m_qcells + buf[bpos++];
00629 apply_vector_2x2(x, y, qcell->idx[0]);
00630 apply_vector_2x2(x+2, y, qcell->idx[1]);
00631 apply_vector_2x2(x, y+2, qcell->idx[2]);
00632 apply_vector_2x2(x+2, y+2, qcell->idx[3]);
00633 break;
00634 case 3:
00635 apply_vector_2x2(x, y, &m_cells[buf[bpos++]]);
00636 apply_vector_2x2(x+2, y, &m_cells[buf[bpos++]]);
00637 apply_vector_2x2(x, y+2, &m_cells[buf[bpos++]]);
00638 apply_vector_2x2(x+2, y+2, &m_cells[buf[bpos++]]);
00639 break;
00640 }
00641 }
00642 break;
00643 }
00644 }
00645 }
00646
00647 xpos += 16;
00648 if(xpos >= w) {xpos -= w; ypos += 16;}
00649 }
00650
00651 if(m_rtStart+rtStart == 0)
00652 {
00653 memcpy(m_y[1], m_y[0], w*h*3/2);
00654 }
00655 else
00656 {
00657 BYTE* tmp;
00658 tmp = m_y[0]; m_y[0] = m_y[1]; m_y[1] = tmp;
00659 tmp = m_u[0]; m_u[0] = m_u[1]; m_u[1] = tmp;
00660 tmp = m_v[0]; m_v[0] = m_v[1]; m_v[1] = tmp;
00661 }
00662 }
00663 else
00664 {
00665 return E_UNEXPECTED;
00666 }
00667
00668 if(rtStart < 0)
00669 return S_FALSE;
00670
00671 Copy(pDataOut, m_y[1], w, h);
00672
00673 pOut->SetTime(&rtStart, &rtStop);
00674
00675 return S_OK;
00676 }
00677
00678 void CRoQVideoDecoder::Copy(BYTE* pOut, BYTE* pIn, DWORD w, DWORD h)
00679 {
00680 BITMAPINFOHEADER bihOut;
00681 ExtractBIH(&m_pOutput->CurrentMediaType(), &bihOut);
00682
00683 int pitchIn = w;
00684 int pitchInUV = pitchIn>>1;
00685 BYTE* pInU = pIn + pitchIn*h;
00686 BYTE* pInV = pInU + pitchInUV*h/2;
00687
00688 if(bihOut.biCompression == '2YUY')
00689 {
00690 BitBltFromI420ToYUY2(w, h, pOut, bihOut.biWidth*2, pIn, pInU, pInV, pitchIn);
00691 }
00692 else if(bihOut.biCompression == 'I420' || bihOut.biCompression == 'VUYI')
00693 {
00694 BitBltFromI420ToI420(w, h, pOut, pOut + bihOut.biWidth*h, pOut + bihOut.biWidth*h*5/4, bihOut.biWidth, pIn, pInU, pInV, pitchIn);
00695 }
00696 else if(bihOut.biCompression == '21VY')
00697 {
00698 BitBltFromI420ToI420(w, h, pOut, pOut + bihOut.biWidth*h*5/4, pOut + bihOut.biWidth*h, bihOut.biWidth, pIn, pInU, pInV, pitchIn);
00699 }
00700 else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
00701 {
00702 int pitchOut = bihOut.biWidth*bihOut.biBitCount>>3;
00703
00704 if(bihOut.biHeight > 0)
00705 {
00706 pOut += pitchOut*(h-1);
00707 pitchOut = -pitchOut;
00708 }
00709
00710 if(!BitBltFromI420ToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, pIn, pInU, pInV, pitchIn))
00711 {
00712 for(DWORD y = 0; y < h; y++, pIn += pitchIn, pOut += pitchOut)
00713 memset(pOut, 0, pitchOut);
00714 }
00715 }
00716 }
00717
00718 HRESULT CRoQVideoDecoder::CheckInputType(const CMediaType* mtIn)
00719 {
00720 return mtIn->majortype == MEDIATYPE_Video && mtIn->subtype == MEDIASUBTYPE_RoQV
00721 ? S_OK
00722 : VFW_E_TYPE_NOT_ACCEPTED;
00723 }
00724
00725 HRESULT CRoQVideoDecoder::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
00726 {
00727 if(m_pOutput && m_pOutput->IsConnected())
00728 {
00729 BITMAPINFOHEADER bih1, bih2;
00730 if(ExtractBIH(mtOut, &bih1) && ExtractBIH(&m_pOutput->CurrentMediaType(), &bih2)
00731 && abs(bih1.biHeight) != abs(bih2.biHeight))
00732 return VFW_E_TYPE_NOT_ACCEPTED;
00733 }
00734
00735 return SUCCEEDED(CheckInputType(mtIn))
00736 && mtOut->majortype == MEDIATYPE_Video && (mtOut->subtype == MEDIASUBTYPE_YUY2
00737 || mtOut->subtype == MEDIASUBTYPE_YV12
00738 || mtOut->subtype == MEDIASUBTYPE_I420
00739 || mtOut->subtype == MEDIASUBTYPE_IYUV
00740 || mtOut->subtype == MEDIASUBTYPE_ARGB32
00741 || mtOut->subtype == MEDIASUBTYPE_RGB32
00742 || mtOut->subtype == MEDIASUBTYPE_RGB24
00743 || mtOut->subtype == MEDIASUBTYPE_RGB565
00744 || mtOut->subtype == MEDIASUBTYPE_RGB555)
00745 ? S_OK
00746 : VFW_E_TYPE_NOT_ACCEPTED;
00747 }
00748
00749 HRESULT CRoQVideoDecoder::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
00750 {
00751 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00752
00753 BITMAPINFOHEADER bih;
00754 ExtractBIH(&m_pOutput->CurrentMediaType(), &bih);
00755
00756 pProperties->cBuffers = 1;
00757 pProperties->cbBuffer = bih.biSizeImage;
00758 pProperties->cbAlign = 1;
00759 pProperties->cbPrefix = 0;
00760
00761 HRESULT hr;
00762 ALLOCATOR_PROPERTIES Actual;
00763 if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
00764 return hr;
00765
00766 return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
00767 ? E_FAIL
00768 : NOERROR);
00769 }
00770
00771 HRESULT CRoQVideoDecoder::GetMediaType(int iPosition, CMediaType* pmt)
00772 {
00773 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00774
00775 struct {const GUID* subtype; WORD biPlanes, biBitCount; DWORD biCompression;} fmts[] =
00776 {
00777 {&MEDIASUBTYPE_YV12, 3, 12, '21VY'},
00778 {&MEDIASUBTYPE_I420, 3, 12, '024I'},
00779 {&MEDIASUBTYPE_IYUV, 3, 12, 'VUYI'},
00780 {&MEDIASUBTYPE_YUY2, 1, 16, '2YUY'},
00781 {&MEDIASUBTYPE_ARGB32, 1, 32, BI_RGB},
00782 {&MEDIASUBTYPE_RGB32, 1, 32, BI_RGB},
00783 {&MEDIASUBTYPE_RGB24, 1, 24, BI_RGB},
00784 {&MEDIASUBTYPE_RGB565, 1, 16, BI_RGB},
00785 {&MEDIASUBTYPE_RGB555, 1, 16, BI_RGB},
00786 {&MEDIASUBTYPE_ARGB32, 1, 32, BI_BITFIELDS},
00787 {&MEDIASUBTYPE_RGB32, 1, 32, BI_BITFIELDS},
00788 {&MEDIASUBTYPE_RGB24, 1, 24, BI_BITFIELDS},
00789 {&MEDIASUBTYPE_RGB565, 1, 16, BI_BITFIELDS},
00790 {&MEDIASUBTYPE_RGB555, 1, 16, BI_BITFIELDS},
00791 };
00792
00793 if(iPosition < 0) return E_INVALIDARG;
00794 if(iPosition >= countof(fmts)) return VFW_S_NO_MORE_ITEMS;
00795
00796 BITMAPINFOHEADER bih;
00797 ExtractBIH(&m_pInput->CurrentMediaType(), &bih);
00798
00799 pmt->majortype = MEDIATYPE_Video;
00800 pmt->subtype = *fmts[iPosition].subtype;
00801 pmt->formattype = FORMAT_VideoInfo;
00802
00803 BITMAPINFOHEADER bihOut;
00804 memset(&bihOut, 0, sizeof(bihOut));
00805 bihOut.biSize = sizeof(bihOut);
00806 bihOut.biWidth = bih.biWidth;
00807 bihOut.biHeight = bih.biHeight;
00808 bihOut.biPlanes = fmts[iPosition].biPlanes;
00809 bihOut.biBitCount = fmts[iPosition].biBitCount;
00810 bihOut.biCompression = fmts[iPosition].biCompression;
00811 bihOut.biSizeImage = bih.biWidth*bih.biHeight*bihOut.biBitCount>>3;
00812
00813 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00814 memset(vih, 0, sizeof(VIDEOINFOHEADER));
00815 vih->bmiHeader = bihOut;
00816
00817 CorrectMediaType(pmt);
00818
00819 return S_OK;
00820 }
00821
00822 HRESULT CRoQVideoDecoder::StartStreaming()
00823 {
00824 BITMAPINFOHEADER bih;
00825 ExtractBIH(&m_pInput->CurrentMediaType(), &bih);
00826
00827 int size = bih.biWidth*bih.biHeight;
00828
00829 m_y[0] = new BYTE[size*3/2];
00830 m_u[0] = m_y[0] + size;
00831 m_v[0] = m_y[0] + size*5/4;
00832 m_y[1] = new BYTE[size*3/2];
00833 m_u[1] = m_y[1] + size;
00834 m_v[1] = m_y[1] + size*5/4;
00835
00836 m_pitch = bih.biWidth;
00837
00838 return __super::StartStreaming();
00839 }
00840
00841 HRESULT CRoQVideoDecoder::StopStreaming()
00842 {
00843 delete [] m_y[0]; m_y[0] = NULL;
00844 delete [] m_y[1]; m_y[1] = NULL;
00845
00846 return __super::StopStreaming();
00847 }
00848
00849
00850
00851
00852
00853 CRoQAudioDecoder::CRoQAudioDecoder(LPUNKNOWN lpunk, HRESULT* phr)
00854 : CTransformFilter(NAME("CRoQAudioDecoder"), lpunk, __uuidof(this))
00855 {
00856 if(phr) *phr = S_OK;
00857 }
00858
00859 CRoQAudioDecoder::~CRoQAudioDecoder()
00860 {
00861 }
00862
00863 HRESULT CRoQAudioDecoder::Transform(IMediaSample* pIn, IMediaSample* pOut)
00864 {
00865 HRESULT hr;
00866
00867 AM_MEDIA_TYPE* pmt;
00868 if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
00869 {
00870 CMediaType mt(*pmt);
00871 m_pOutput->SetMediaType(&mt);
00872 DeleteMediaType(pmt);
00873 }
00874
00875 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
00876
00877 BYTE* pDataIn = NULL;
00878 if(FAILED(hr = pIn->GetPointer(&pDataIn)))
00879 return hr;
00880
00881 long len = pIn->GetActualDataLength();
00882 if(len <= 0) return S_OK;
00883
00884 REFERENCE_TIME rtStart, rtStop;
00885 pIn->GetTime(&rtStart, &rtStop);
00886
00887 if(pIn->IsPreroll() == S_OK || rtStart < 0)
00888 return S_OK;
00889
00890 BYTE* pDataOut = NULL;
00891 if(FAILED(hr = pOut->GetPointer(&pDataOut)))
00892 return hr;
00893
00894 long size = pOut->GetSize();
00895 if(size <= 0)
00896 return E_FAIL;
00897
00898 roq_chunk* rc = (roq_chunk*)pDataIn;
00899
00900 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
00901
00902 if(wfe->nChannels == 1)
00903 {
00904 int mono = (short)rc->arg;
00905 unsigned char* src = pDataIn + sizeof(roq_chunk);
00906 short* dst = (short*)pDataOut;
00907 for(int i = sizeof(roq_chunk); i < len; i++, src++, dst++)
00908 {
00909 short diff = (*src&0x7f)*(*src&0x7f);
00910 if(*src&0x80) diff = -diff;
00911 mono += diff;
00912 *dst = (short)mono;
00913 }
00914 }
00915 else if(wfe->nChannels == 2)
00916 {
00917 int left = (char)(rc->arg>>8)<<8;
00918 int right = (char)(rc->arg)<<8;
00919 unsigned char* src = pDataIn + sizeof(roq_chunk);
00920 short* dst = (short*)pDataOut;
00921 for(int i = sizeof(roq_chunk); i < len; i+=2, src++, dst++)
00922 {
00923 short diff = (*src&0x7f)*(*src&0x7f);
00924 if(*src&0x80) diff = -diff;
00925 ASSERT((int)left + diff <= SHRT_MAX && (int)left + diff >= SHRT_MIN);
00926 left += diff;
00927 *dst = (short)left;
00928
00929 src++; dst++;
00930
00931 diff = (*src&0x7f)*(*src&0x7f);
00932 if(*src&0x80) diff = -diff;
00933 ASSERT((int)right + diff <= SHRT_MAX && (int)right + diff >= SHRT_MIN);
00934 right += diff;
00935 *dst = (short)right;
00936 }
00937 }
00938 else
00939 {
00940 return E_UNEXPECTED;
00941 }
00942
00943 pOut->SetTime(&rtStart, &rtStop);
00944
00945 pOut->SetActualDataLength(2*(len-sizeof(roq_chunk)));
00946
00947 return S_OK;
00948 }
00949
00950 HRESULT CRoQAudioDecoder::CheckInputType(const CMediaType* mtIn)
00951 {
00952 return mtIn->majortype == MEDIATYPE_Audio && mtIn->subtype == MEDIASUBTYPE_RoQA
00953 ? S_OK
00954 : VFW_E_TYPE_NOT_ACCEPTED;
00955 }
00956
00957 HRESULT CRoQAudioDecoder::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
00958 {
00959 return SUCCEEDED(CheckInputType(mtIn))
00960 && mtOut->majortype == MEDIATYPE_Audio && mtOut->subtype == MEDIASUBTYPE_PCM
00961 ? S_OK
00962 : VFW_E_TYPE_NOT_ACCEPTED;
00963 }
00964
00965 HRESULT CRoQAudioDecoder::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
00966 {
00967 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00968
00969 CComPtr<IMemAllocator> pAllocatorIn;
00970 m_pInput->GetAllocator(&pAllocatorIn);
00971 if(!pAllocatorIn) return E_UNEXPECTED;
00972
00973 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
00974
00975
00976 pProperties->cBuffers = 8;
00977 pProperties->cbBuffer = wfe->nChannels*wfe->nSamplesPerSec*wfe->wBitsPerSample>>3;
00978 pProperties->cbAlign = 1;
00979 pProperties->cbPrefix = 0;
00980
00981 HRESULT hr;
00982 ALLOCATOR_PROPERTIES Actual;
00983 if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
00984 return hr;
00985
00986 return pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
00987 ? E_FAIL
00988 : NOERROR;
00989 }
00990
00991 HRESULT CRoQAudioDecoder::GetMediaType(int iPosition, CMediaType* pmt)
00992 {
00993 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
00994
00995 if(iPosition < 0) return E_INVALIDARG;
00996 if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
00997
00998 *pmt = m_pInput->CurrentMediaType();
00999 pmt->subtype = MEDIASUBTYPE_PCM;
01000
01001 WAVEFORMATEX* wfe = (WAVEFORMATEX*)pmt->ReallocFormatBuffer(sizeof(WAVEFORMATEX));
01002 wfe->cbSize = 0;
01003 wfe->wFormatTag = WAVE_FORMAT_PCM;
01004 wfe->nBlockAlign = wfe->nChannels*wfe->wBitsPerSample>>3;
01005 wfe->nAvgBytesPerSec = wfe->nSamplesPerSec*wfe->nBlockAlign;
01006
01007 return S_OK;
01008 }