- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# RoQSplitter.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 #include "StdAfx.h"
    00023 #include <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); // "DllMain" of the dshow baseclasses;
    00110 }
    00111
    00112 #endif
    00113
    00114 //
    00115 // CRoQSplitterFilter
    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         // pins
    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; // cut into half, hehe, like anyone would care
    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 // CRoQSourceFilter
    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 // CRoQVideoDecoder
    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; // nothing to do
    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         // TODO: decode picture into m_pI420
    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 // CRealAudioDecoder
    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         // ok, maybe this is too much...
    00976         pProperties->cBuffers = 8;
    00977         pProperties->cbBuffer = wfe->nChannels*wfe->nSamplesPerSec*wfe->wBitsPerSample>>3; // nAvgBytesPerSec;
    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 }