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 }

Generated on Tue Dec 13 14:47:22 2005 for guliverkli by  doxygen 1.4.5