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 <Shlwapi.h>
00024 #include <atlpath.h>
00025 #include <mmreg.h>
00026 #include <ks.h>
00027 #include <ksmedia.h>
00028 #include "..\..\..\DSUtil\DSUtil.h"
00029 #include "..\..\..\DSUtil\MediaTypes.h"
00030 #include "RealMediaSplitter.h"
00031 #include "..\..\..\subtitles\SubtitleInputPin.h"
00032
00033
00034
00035 #include <initguid.h>
00036 #include "..\..\..\..\include\moreuuids.h"
00037
00038 template<typename T>
00039 static void bswap(T& var)
00040 {
00041 BYTE* s = (BYTE*)&var;
00042 for(BYTE* d = s + sizeof(var)-1; s < d; s++, d--)
00043 *s ^= *d, *d ^= *s, *s ^= *d;
00044 }
00045
00046 void rvinfo::bswap()
00047 {
00048 ::bswap(dwSize);
00049 ::bswap(w); ::bswap(h); ::bswap(bpp);
00050 ::bswap(unk1); ::bswap(fps);
00051 ::bswap(type1); ::bswap(type2);
00052 }
00053
00054 void rainfo::bswap()
00055 {
00056 ::bswap(version1);
00057 ::bswap(version2);
00058 ::bswap(header_size);
00059 ::bswap(flavor);
00060 ::bswap(coded_frame_size);
00061 ::bswap(sub_packet_h);
00062 ::bswap(frame_size);
00063 ::bswap(sub_packet_size);
00064 }
00065
00066 void rainfo4::bswap()
00067 {
00068 __super::bswap();
00069 ::bswap(sample_rate);
00070 ::bswap(sample_size);
00071 ::bswap(channels);
00072 }
00073
00074 void rainfo5::bswap()
00075 {
00076 __super::bswap();
00077 ::bswap(sample_rate);
00078 ::bswap(sample_size);
00079 ::bswap(channels);
00080 }
00081
00082 using namespace RMFF;
00083
00084 #ifdef REGISTER_FILTER
00085
00086 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00087 {
00088 {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL},
00089 };
00090
00091 const AMOVIESETUP_PIN sudpPins[] =
00092 {
00093 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00094 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
00095 };
00096
00097 const AMOVIESETUP_MEDIATYPE sudPinTypesIn2[] =
00098 {
00099 {&MEDIATYPE_Video, &MEDIASUBTYPE_RV20},
00100 {&MEDIATYPE_Video, &MEDIASUBTYPE_RV30},
00101 {&MEDIATYPE_Video, &MEDIASUBTYPE_RV40},
00102 {&MEDIATYPE_Video, &MEDIASUBTYPE_RV41},
00103 };
00104
00105 const AMOVIESETUP_MEDIATYPE sudPinTypesOut2[] =
00106 {
00107 {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
00108 };
00109
00110 const AMOVIESETUP_PIN sudpPins2[] =
00111 {
00112 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn2), sudPinTypesIn2},
00113 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut2), sudPinTypesOut2}
00114 };
00115
00116 const AMOVIESETUP_MEDIATYPE sudPinTypesIn3[] =
00117 {
00118 {&MEDIATYPE_Audio, &MEDIASUBTYPE_14_4},
00119 {&MEDIATYPE_Audio, &MEDIASUBTYPE_28_8},
00120 {&MEDIATYPE_Audio, &MEDIASUBTYPE_ATRC},
00121 {&MEDIATYPE_Audio, &MEDIASUBTYPE_COOK},
00122 {&MEDIATYPE_Audio, &MEDIASUBTYPE_DNET},
00123 {&MEDIATYPE_Audio, &MEDIASUBTYPE_SIPR},
00124 {&MEDIATYPE_Audio, &MEDIASUBTYPE_AAC},
00125 {&MEDIATYPE_Audio, &MEDIASUBTYPE_RAAC},
00126 {&MEDIATYPE_Audio, &MEDIASUBTYPE_RACP},
00127 };
00128
00129 const AMOVIESETUP_MEDIATYPE sudPinTypesOut3[] =
00130 {
00131 {&MEDIATYPE_Audio, &MEDIASUBTYPE_PCM},
00132 };
00133
00134 const AMOVIESETUP_PIN sudpPins3[] =
00135 {
00136 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn3), sudPinTypesIn3},
00137 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut3), sudPinTypesOut3}
00138 };
00139
00140 const AMOVIESETUP_FILTER sudFilter[] =
00141 {
00142 {&__uuidof(CRealMediaSplitterFilter), L"RealMedia Splitter", MERIT_NORMAL, countof(sudpPins), sudpPins},
00143 {&__uuidof(CRealMediaSourceFilter), L"RealMedia Source", MERIT_NORMAL, 0, NULL},
00144 {&__uuidof(CRealVideoDecoder), L"RealVideo Decoder", MERIT_UNLIKELY, countof(sudpPins2), sudpPins2},
00145 {&__uuidof(CRealAudioDecoder), L"RealAudio Decoder", MERIT_UNLIKELY, countof(sudpPins3), sudpPins3},
00146 };
00147
00148 CFactoryTemplate g_Templates[] =
00149 {
00150 {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CRealMediaSplitterFilter>, NULL, &sudFilter[0]},
00151 {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CRealMediaSourceFilter>, NULL, &sudFilter[1]},
00152 {sudFilter[2].strName, sudFilter[2].clsID, CreateInstance<CRealVideoDecoder>, NULL, &sudFilter[2]},
00153 {sudFilter[3].strName, sudFilter[3].clsID, CreateInstance<CRealAudioDecoder>, NULL, &sudFilter[3]},
00154 };
00155
00156 int g_cTemplates = countof(g_Templates);
00157
00158 STDAPI DllRegisterServer()
00159 {
00160 RegisterSourceFilter(
00161 CLSID_AsyncReader,
00162 MEDIASUBTYPE_RealMedia,
00163 _T("0,4,,2E524D46"),
00164 _T(".rm"), _T(".rmvb"), _T(".ram"), NULL);
00165
00166 return AMovieDllRegisterServer2(TRUE);
00167 }
00168
00169 STDAPI DllUnregisterServer()
00170 {
00171 UnRegisterSourceFilter(MEDIASUBTYPE_RealMedia);
00172
00173 return AMovieDllRegisterServer2(FALSE);
00174 }
00175
00176 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00177
00178 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00179 {
00180 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00181 }
00182
00183 #endif
00184
00185
00186
00187
00188
00189 CRealMediaSplitterFilter::CRealMediaSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
00190 : CBaseSplitterFilter(NAME("CRealMediaSplitterFilter"), pUnk, phr, __uuidof(this))
00191 {
00192 }
00193
00194 CRealMediaSplitterFilter::~CRealMediaSplitterFilter()
00195 {
00196 }
00197
00198 HRESULT CRealMediaSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
00199 {
00200 CheckPointer(pAsyncReader, E_POINTER);
00201
00202 {
00203 DWORD dw;
00204 if(FAILED(pAsyncReader->SyncRead(0, 4, (BYTE*)&dw)) || dw != 'FMR.')
00205 return E_FAIL;
00206 }
00207
00208 HRESULT hr = E_FAIL;
00209
00210 m_pFile.Free();
00211
00212 m_pFile.Attach(new CRMFile(pAsyncReader, hr));
00213 if(!m_pFile) return E_OUTOFMEMORY;
00214 if(FAILED(hr)) {m_pFile.Free(); return hr;}
00215
00216 m_rtNewStart = m_rtCurrent = 0;
00217 m_rtNewStop = m_rtStop = 0;
00218
00219 m_rtStop = 10000i64*m_pFile->m_p.tDuration;
00220
00221 POSITION pos = m_pFile->m_mps.GetHeadPosition();
00222 while(pos)
00223 {
00224 MediaProperies* pmp = m_pFile->m_mps.GetNext(pos);
00225
00226 CStringW name;
00227 name.Format(L"Output %02d", pmp->stream);
00228 if(!pmp->name.IsEmpty()) name += L" (" + CStringW(pmp->name) + L")";
00229
00230 CArray<CMediaType> mts;
00231
00232 CMediaType mt;
00233 mt.SetSampleSize(max(pmp->maxPacketSize*16, 1));
00234
00235 if(pmp->mime == "video/x-pn-realvideo")
00236 {
00237 mt.majortype = MEDIATYPE_Video;
00238 mt.formattype = FORMAT_VideoInfo;
00239
00240 VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER) + pmp->typeSpecData.GetCount());
00241 memset(mt.Format(), 0, mt.FormatLength());
00242 memcpy(pvih + 1, pmp->typeSpecData.GetData(), pmp->typeSpecData.GetCount());
00243
00244 rvinfo rvi = *(rvinfo*)pmp->typeSpecData.GetData();
00245 rvi.bswap();
00246
00247 ASSERT(rvi.dwSize >= FIELD_OFFSET(rvinfo, morewh));
00248 ASSERT(rvi.fcc1 == 'ODIV');
00249
00250 mt.subtype = FOURCCMap(rvi.fcc2);
00251 if(rvi.fps > 0x10000) pvih->AvgTimePerFrame = REFERENCE_TIME(10000000i64 / ((float)rvi.fps/0x10000));
00252 pvih->dwBitRate = pmp->avgBitRate;
00253 pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
00254 pvih->bmiHeader.biWidth = rvi.w;
00255 pvih->bmiHeader.biHeight = rvi.h;
00256 pvih->bmiHeader.biPlanes = 3;
00257 pvih->bmiHeader.biBitCount = rvi.bpp;
00258 pvih->bmiHeader.biCompression = rvi.fcc2;
00259 pvih->bmiHeader.biSizeImage = rvi.w*rvi.h*3/2;
00260
00261 mts.Add(mt);
00262
00263 if(pmp->width > 0 && pmp->height > 0)
00264 {
00265 BITMAPINFOHEADER bmi = pvih->bmiHeader;
00266 mt.formattype = FORMAT_VideoInfo2;
00267 VIDEOINFOHEADER2* pvih2 = (VIDEOINFOHEADER2*)mt.ReallocFormatBuffer(sizeof(VIDEOINFOHEADER2) + pmp->typeSpecData.GetCount());
00268 memset(mt.Format() + FIELD_OFFSET(VIDEOINFOHEADER2, dwInterlaceFlags), 0, mt.FormatLength() - FIELD_OFFSET(VIDEOINFOHEADER2, dwInterlaceFlags));
00269 memcpy(pvih2 + 1, pmp->typeSpecData.GetData(), pmp->typeSpecData.GetCount());
00270 pvih2->bmiHeader = bmi;
00271 pvih2->bmiHeader.biWidth = (DWORD)pmp->width;
00272 pvih2->bmiHeader.biHeight = (DWORD)pmp->height;
00273 pvih2->dwPictAspectRatioX = rvi.w;
00274 pvih2->dwPictAspectRatioY = rvi.h;
00275
00276 mts.InsertAt(0, mt);
00277 }
00278 }
00279 else if(pmp->mime == "audio/x-pn-realaudio")
00280 {
00281 mt.majortype = MEDIATYPE_Audio;
00282 mt.formattype = FORMAT_WaveFormatEx;
00283 mt.bTemporalCompression = 1;
00284
00285 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)mt.AllocFormatBuffer(sizeof(WAVEFORMATEX) + pmp->typeSpecData.GetCount());
00286 memset(mt.Format(), 0, mt.FormatLength());
00287 memcpy(pwfe + 1, pmp->typeSpecData.GetData(), pmp->typeSpecData.GetCount());
00288
00289 union {
00290 DWORD fcc;
00291 char fccstr[5];
00292 };
00293
00294 fcc = 0;
00295 fccstr[4] = 0;
00296
00297 BYTE* fmt = pmp->typeSpecData.GetData();
00298 for(int i = 0; i < pmp->typeSpecData.GetSize()-4; i++, fmt++)
00299 {
00300 if(fmt[0] == '.' || fmt[1] == 'r' || fmt[2] == 'a')
00301 break;
00302 }
00303
00304 rainfo rai = *(rainfo*)fmt;
00305 rai.bswap();
00306
00307 BYTE* extra = NULL;
00308
00309 if(rai.version2 == 4)
00310 {
00311 rainfo4 rai4 = *(rainfo4*)fmt;
00312 rai4.bswap();
00313 pwfe->nChannels = rai4.channels;
00314 pwfe->wBitsPerSample = rai4.sample_size;
00315 pwfe->nSamplesPerSec = rai4.sample_rate;
00316 pwfe->nBlockAlign = rai4.frame_size;
00317 BYTE* p = (BYTE*)((rainfo4*)fmt+1);
00318 int len = *p++; p += len; len = *p++; ASSERT(len == 4);
00319 if(len == 4)
00320 fcc = MAKEFOURCC(p[0],p[1],p[2],p[3]);
00321 extra = p + len + 3;
00322 }
00323 else if(rai.version2 == 5)
00324 {
00325 rainfo5 rai5 = *(rainfo5*)fmt;
00326 rai5.bswap();
00327 pwfe->nChannels = rai5.channels;
00328 pwfe->wBitsPerSample = rai5.sample_size;
00329 pwfe->nSamplesPerSec = rai5.sample_rate;
00330 pwfe->nBlockAlign = rai5.frame_size;
00331 fcc = rai5.fourcc3;
00332 extra = fmt + sizeof(rainfo5) + 4;
00333 }
00334 else
00335 {
00336 continue;
00337 }
00338
00339 _strupr(fccstr);
00340
00341 mt.subtype = FOURCCMap(fcc);
00342
00343 bswap(fcc);
00344
00345 switch(fcc)
00346 {
00347 case '14_4': pwfe->wFormatTag = WAVE_FORMAT_14_4; break;
00348 case '28_8': pwfe->wFormatTag = WAVE_FORMAT_28_8; break;
00349 case 'ATRC': pwfe->wFormatTag = WAVE_FORMAT_ATRC; break;
00350 case 'COOK': pwfe->wFormatTag = WAVE_FORMAT_COOK; break;
00351 case 'DNET': pwfe->wFormatTag = WAVE_FORMAT_DNET; break;
00352 case 'SIPR': pwfe->wFormatTag = WAVE_FORMAT_SIPR; break;
00353 case 'RAAC': pwfe->wFormatTag = WAVE_FORMAT_RAAC; break;
00354 case 'RACP': pwfe->wFormatTag = WAVE_FORMAT_RACP; break;
00355 }
00356
00357 if(pwfe->wFormatTag)
00358 {
00359 mts.Add(mt);
00360
00361 if(fcc == 'DNET')
00362 {
00363 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_DOLBY_AC3);
00364 mts.InsertAt(0, mt);
00365 }
00366 else if(fcc == 'RAAC' || fcc == 'RACP')
00367 {
00368 mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_AAC);
00369 int extralen = *(DWORD*)extra; extra += 4;
00370 ::bswap(extralen);
00371 ASSERT(*extra == 2);
00372 if(*extra == 2)
00373 {
00374 extra++; extralen--;
00375 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + extralen);
00376 pwfe->cbSize = extralen;
00377 memcpy(pwfe + 1, extra, extralen);
00378 }
00379 else
00380 {
00381 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + 5);
00382 pwfe->cbSize = MakeAACInitData((BYTE*)(pwfe+1), 0, pwfe->nSamplesPerSec, pwfe->nChannels);
00383 }
00384 mts.InsertAt(0, mt);
00385 }
00386 }
00387 }
00388 else if(pmp->mime == "logical-fileinfo")
00389 {
00390 CMap<CStringA,LPCSTR,CStringA,LPCSTR> lfi;
00391 CStringA key, value;
00392
00393 BYTE* p = pmp->typeSpecData.GetData();
00394 BYTE* end = p + pmp->typeSpecData.GetCount();
00395 p += 8;
00396
00397 DWORD cnt = p <= end-4 ? *(DWORD*)p : 0; bswap(cnt); p += 4;
00398
00399 if(cnt > 0xffff)
00400 {
00401 p += 2;
00402 cnt = p <= end-4 ? *(DWORD*)p : 0; bswap(cnt); p += 4;
00403 }
00404
00405 while(p < end-4 && cnt-- > 0)
00406 {
00407 BYTE* base = p;
00408 DWORD len = *(DWORD*)p; bswap(len); p += 4;
00409 if(base + len > end) break;
00410
00411 p++;
00412 WORD keylen = *(WORD*)p; bswap(keylen); p += 2;
00413 memcpy(key.GetBufferSetLength(keylen), p, keylen);
00414 p += keylen;
00415
00416 p+=4;
00417 WORD valuelen = *(WORD*)p; bswap(valuelen); p += 2;
00418 memcpy(value.GetBufferSetLength(valuelen), p, valuelen);
00419 p += valuelen;
00420
00421 ASSERT(p == base + len);
00422 p = base + len;
00423
00424 lfi[key] = value;
00425 }
00426
00427 POSITION pos = lfi.GetStartPosition();
00428 while(pos)
00429 {
00430 lfi.GetNextAssoc(pos, key, value);
00431
00432 int n;
00433 if(key.Find("CHAPTER") == 0 && key.Find("TIME") == key.GetLength()-4
00434 && (n = strtol(key.Mid(7), NULL, 10)) > 0)
00435 {
00436 int h, m, s, ms;
00437 char c;
00438 if(7 != sscanf(value, "%d%c%d%c%d%c%d", &h, &c, &m, &c, &s, &c, &ms))
00439 continue;
00440
00441 key.Format("CHAPTER%02dNAME", n);
00442 if(!lfi.Lookup(key, value) || value.IsEmpty())
00443 value.Format("Chapter %d", n);
00444
00445 ChapAppend(
00446 ((((REFERENCE_TIME)h*60+m)*60+s)*1000+ms)*10000,
00447 CStringW(CString(value)));
00448 }
00449 }
00450 }
00451
00452 if(mts.IsEmpty())
00453 {
00454 TRACE(_T("Unsupported RealMedia stream (%d): %s\n"), pmp->stream, CString(pmp->mime));
00455 continue;
00456 }
00457
00458 HRESULT hr;
00459
00460 CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CRealMediaSplitterOutputPin(mts, name, this, this, &hr));
00461 if(SUCCEEDED(AddOutputPin((DWORD)pmp->stream, pPinOut)))
00462 {
00463 if(!m_rtStop)
00464 m_pFile->m_p.tDuration = max(m_pFile->m_p.tDuration, pmp->tDuration);
00465 }
00466 }
00467
00468 pos = m_pFile->m_subs.GetHeadPosition();
00469 for(DWORD stream = 0; pos; stream++)
00470 {
00471 CRMFile::subtitle& s = m_pFile->m_subs.GetNext(pos);
00472
00473 CStringW name;
00474 name.Format(L"Subtitle %02d", stream);
00475 if(!s.name.IsEmpty()) name += L" (" + CStringW(CString(s.name)) + L")";
00476
00477 CMediaType mt;
00478 mt.SetSampleSize(1);
00479 mt.majortype = MEDIATYPE_Text;
00480
00481 CArray<CMediaType> mts;
00482 mts.Add(mt);
00483
00484 HRESULT hr;
00485
00486 CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CRealMediaSplitterOutputPin(mts, name, this, this, &hr));
00487 AddOutputPin((DWORD)~stream, pPinOut);
00488 }
00489
00490 m_rtDuration = m_rtNewStop = m_rtStop = 10000i64*m_pFile->m_p.tDuration;
00491
00492 SetProperty(L"TITL", CStringW(m_pFile->m_cd.title));
00493 SetProperty(L"AUTH", CStringW(m_pFile->m_cd.author));
00494 SetProperty(L"CPYR", CStringW(m_pFile->m_cd.copyright));
00495 SetProperty(L"DESC", CStringW(m_pFile->m_cd.comment));
00496
00497 return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
00498 }
00499
00500 bool CRealMediaSplitterFilter::DemuxInit()
00501 {
00502 if(!m_pFile) return(false);
00503
00504
00505
00506 if(m_pFile->m_irs.GetCount() == 0)
00507 {
00508 m_nOpenProgress = 0;
00509 m_rtDuration = 0;
00510
00511 int stream = m_pFile->GetMasterStream();
00512
00513 UINT32 tLastStart = -1;
00514 UINT32 nPacket = 0;
00515
00516 POSITION pos = m_pFile->m_dcs.GetHeadPosition();
00517 while(pos && !m_fAbort)
00518 {
00519 DataChunk* pdc = m_pFile->m_dcs.GetNext(pos);
00520
00521 m_pFile->Seek(pdc->pos);
00522
00523 for(UINT32 i = 0; i < pdc->nPackets && !m_fAbort; i++, nPacket++)
00524 {
00525 UINT64 filepos = m_pFile->GetPos();
00526
00527 HRESULT hr;
00528
00529 MediaPacketHeader mph;
00530 if(S_OK != (hr = m_pFile->Read(mph, false)))
00531 break;
00532
00533 if(mph.stream == stream && (mph.flags&MediaPacketHeader::PN_KEYFRAME_FLAG) && tLastStart != mph.tStart)
00534 {
00535 m_rtDuration = max((__int64)(10000i64*mph.tStart), m_rtDuration);
00536
00537 CAutoPtr<IndexRecord> pir(new IndexRecord());
00538 pir->tStart = mph.tStart;
00539 pir->ptrFilePos = (UINT32)filepos;
00540 pir->packet = nPacket;
00541 m_pFile->m_irs.AddTail(pir);
00542
00543 tLastStart = mph.tStart;
00544 }
00545
00546 m_nOpenProgress = m_pFile->GetPos()*100/m_pFile->GetLength();
00547
00548 DWORD cmd;
00549 if(CheckRequest(&cmd))
00550 {
00551 if(cmd == CMD_EXIT) m_fAbort = true;
00552 else Reply(S_OK);
00553 }
00554 }
00555 }
00556
00557 m_nOpenProgress = 100;
00558
00559 if(m_fAbort) m_pFile->m_irs.RemoveAll();
00560
00561 m_fAbort = false;
00562 }
00563
00564 m_seekpos = NULL;
00565 m_seekpacket = 0;
00566 m_seekfilepos = 0;
00567
00568 return(true);
00569 }
00570
00571 void CRealMediaSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
00572 {
00573 if(rt <= 0)
00574 {
00575 m_seekpos = m_pFile->m_dcs.GetHeadPosition();
00576 m_seekpacket = 0;
00577 m_seekfilepos = m_pFile->m_dcs.GetHead()->pos;
00578 }
00579 else
00580 {
00581 m_seekpos = NULL;
00582
00583 POSITION pos = m_pFile->m_irs.GetTailPosition();
00584 while(pos && !m_seekpos)
00585 {
00586 IndexRecord* pir = m_pFile->m_irs.GetPrev(pos);
00587 if(pir->tStart <= rt/10000)
00588 {
00589 m_seekpacket = pir->packet;
00590
00591 pos = m_pFile->m_dcs.GetTailPosition();
00592 while(pos && !m_seekpos)
00593 {
00594 POSITION tmp = pos;
00595
00596 DataChunk* pdc = m_pFile->m_dcs.GetPrev(pos);
00597
00598 if(pdc->pos <= pir->ptrFilePos)
00599 {
00600 m_seekpos = tmp;
00601 m_seekfilepos = pir->ptrFilePos;
00602
00603 POSITION pos = m_pFile->m_dcs.GetHeadPosition();
00604 while(pos != m_seekpos)
00605 {
00606 m_seekpacket -= m_pFile->m_dcs.GetNext(pos)->nPackets;
00607 }
00608 }
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 }
00646 }
00647
00648 if(!m_seekpos)
00649 {
00650 m_seekpos = m_pFile->m_dcs.GetHeadPosition();
00651 m_seekpacket = 0;
00652 m_seekfilepos = m_pFile->m_dcs.GetAt(m_seekpos)->pos;
00653 }
00654 }
00655 }
00656
00657 bool CRealMediaSplitterFilter::DemuxLoop()
00658 {
00659 HRESULT hr = S_OK;
00660 POSITION pos;
00661
00662 pos = m_pFile->m_subs.GetHeadPosition();
00663 for(DWORD stream = 0; pos && SUCCEEDED(hr) && !CheckRequest(NULL); stream++)
00664 {
00665 CRMFile::subtitle& s = m_pFile->m_subs.GetNext(pos);
00666
00667 CAutoPtr<Packet> p(new Packet);
00668
00669 p->TrackNumber = ~stream;
00670 p->bSyncPoint = TRUE;
00671 p->rtStart = 0;
00672 p->rtStop = 1;
00673
00674 p->pData.SetSize((4+1) + (2+4+(s.name.GetLength()+1)*2) + (2+4+s.data.GetLength()));
00675 BYTE* ptr = p->pData.GetData();
00676
00677 strcpy((char*)ptr, "GAB2"); ptr += 4+1;
00678
00679 *(WORD*)ptr = 2; ptr += 2;
00680 *(DWORD*)ptr = (s.name.GetLength()+1)*2; ptr += 4;
00681 wcscpy((WCHAR*)ptr, CStringW(s.name)); ptr += (s.name.GetLength()+1)*2;
00682
00683 *(WORD*)ptr = 4; ptr += 2;
00684 *(DWORD*)ptr = s.data.GetLength(); ptr += 4;
00685 memcpy((char*)ptr, s.data, s.data.GetLength()); ptr += s.name.GetLength();
00686
00687 hr = DeliverPacket(p);
00688 }
00689
00690 pos = m_seekpos;
00691 while(pos && SUCCEEDED(hr) && !CheckRequest(NULL))
00692 {
00693 DataChunk* pdc = m_pFile->m_dcs.GetNext(pos);
00694
00695 m_pFile->Seek(m_seekfilepos > 0 ? m_seekfilepos : pdc->pos);
00696
00697 for(UINT32 i = m_seekpacket; i < pdc->nPackets && SUCCEEDED(hr) && !CheckRequest(NULL); i++)
00698 {
00699 MediaPacketHeader mph;
00700 if(S_OK != (hr = m_pFile->Read(mph)))
00701 break;
00702
00703 CAutoPtr<Packet> p(new Packet);
00704 p->TrackNumber = mph.stream;
00705 p->bSyncPoint = !!(mph.flags&MediaPacketHeader::PN_KEYFRAME_FLAG);
00706 p->rtStart = 10000i64*(mph.tStart);
00707 p->rtStop = p->rtStart+1;
00708 p->pData.Copy(mph.pData);
00709 hr = DeliverPacket(p);
00710 }
00711
00712 m_seekpacket = 0;
00713 m_seekfilepos = 0;
00714 }
00715
00716 return(true);
00717 }
00718
00719
00720
00721 STDMETHODIMP CRealMediaSplitterFilter::GetKeyFrameCount(UINT& nKFs)
00722 {
00723 if(!m_pFile) return E_UNEXPECTED;
00724 nKFs = m_pFile->m_irs.GetCount();
00725 return S_OK;
00726 }
00727
00728 STDMETHODIMP CRealMediaSplitterFilter::GetKeyFrames(const GUID* pFormat, REFERENCE_TIME* pKFs, UINT& nKFs)
00729 {
00730 CheckPointer(pFormat, E_POINTER);
00731 CheckPointer(pKFs, E_POINTER);
00732
00733 if(!m_pFile) return E_UNEXPECTED;
00734 if(*pFormat != TIME_FORMAT_MEDIA_TIME) return E_INVALIDARG;
00735
00736 UINT nKFsTmp = 0;
00737 POSITION pos = m_pFile->m_irs.GetHeadPosition();
00738 for(int i = 0; pos && nKFsTmp < nKFs; i++)
00739 pKFs[nKFsTmp++] = 10000i64*m_pFile->m_irs.GetNext(pos)->tStart;
00740 nKFs = nKFsTmp;
00741
00742 return S_OK;
00743 }
00744
00745
00746
00747
00748
00749 CRealMediaSplitterOutputPin::CRealMediaSplitterOutputPin(CArray<CMediaType>& mts, LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
00750 : CBaseSplitterOutputPin(mts, pName, pFilter, pLock, phr)
00751 {
00752 }
00753
00754 CRealMediaSplitterOutputPin::~CRealMediaSplitterOutputPin()
00755 {
00756 }
00757
00758 HRESULT CRealMediaSplitterOutputPin::DeliverEndFlush()
00759 {
00760 {
00761 CAutoLock cAutoLock(&m_csQueue);
00762 m_segments.Clear();
00763 }
00764
00765 return __super::DeliverEndFlush();
00766 }
00767
00768 HRESULT CRealMediaSplitterOutputPin::DeliverSegments()
00769 {
00770 HRESULT hr;
00771
00772 if(m_segments.GetCount() == 0)
00773 {
00774 m_segments.Clear();
00775 return S_OK;
00776 }
00777
00778 CAutoPtr<Packet> p(new Packet());
00779
00780 p->TrackNumber = -1;
00781 p->bDiscontinuity = m_segments.fDiscontinuity;
00782 p->bSyncPoint = m_segments.fSyncPoint;
00783 p->rtStart = m_segments.rtStart;
00784 p->rtStop = m_segments.rtStart+1;
00785
00786 DWORD len = 0, total = 0;
00787 POSITION pos = m_segments.GetHeadPosition();
00788 while(pos)
00789 {
00790 segment* s = m_segments.GetNext(pos);
00791 len = max(len, s->offset + s->data.GetCount());
00792 total += s->data.GetCount();
00793 }
00794 ASSERT(len == total);
00795 len += 1 + 2*4*(!m_segments.fMerged ? m_segments.GetCount() : 1);
00796
00797 p->pData.SetSize(len);
00798
00799 BYTE* pData = p->pData.GetData();
00800
00801 *pData++ = m_segments.fMerged ? 0 : m_segments.GetCount()-1;
00802
00803 if(m_segments.fMerged)
00804 {
00805 *((DWORD*)pData) = 1; pData += 4;
00806 *((DWORD*)pData) = 0; pData += 4;
00807 }
00808 else
00809 {
00810 pos = m_segments.GetHeadPosition();
00811 while(pos)
00812 {
00813 *((DWORD*)pData) = 1; pData += 4;
00814 *((DWORD*)pData) = m_segments.GetNext(pos)->offset; pData += 4;
00815 }
00816 }
00817
00818 pos = m_segments.GetHeadPosition();
00819 while(pos)
00820 {
00821 segment* s = m_segments.GetNext(pos);
00822 memcpy(pData + s->offset, s->data.GetData(), s->data.GetCount());
00823 }
00824
00825 hr = __super::DeliverPacket(p);
00826
00827 m_segments.Clear();
00828
00829 return hr;
00830 }
00831
00832 HRESULT CRealMediaSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p)
00833 {
00834 HRESULT hr = S_OK;
00835
00836 ASSERT(p->rtStart < p->rtStop);
00837
00838 if(m_mt.subtype == MEDIASUBTYPE_WAVE_DOLBY_AC3)
00839 {
00840 WORD* s = (WORD*)p->pData.GetData();
00841 WORD* e = s + p->pData.GetSize()/2;
00842 while(s < e) bswap(*s++);
00843 }
00844
00845 if(m_mt.subtype == MEDIASUBTYPE_RV10 || m_mt.subtype == MEDIASUBTYPE_RV20
00846 || m_mt.subtype == MEDIASUBTYPE_RV30 || m_mt.subtype == MEDIASUBTYPE_RV40
00847 || m_mt.subtype == MEDIASUBTYPE_RV41)
00848 {
00849 CAutoLock cAutoLock(&m_csQueue);
00850
00851 int len = p->pData.GetCount();
00852 BYTE* pIn = p->pData.GetData();
00853 BYTE* pInOrg = pIn;
00854
00855 if(m_segments.rtStart != p->rtStart)
00856 {
00857 if(S_OK != (hr = DeliverSegments()))
00858 return hr;
00859 }
00860
00861 if(!m_segments.fDiscontinuity && p->bDiscontinuity)
00862 m_segments.fDiscontinuity = true;
00863 m_segments.fSyncPoint = !!p->bSyncPoint;
00864 m_segments.rtStart = p->rtStart;
00865
00866 while(pIn - pInOrg < len)
00867 {
00868 BYTE hdr = *pIn++, subseq = 0, seqnum = 0;
00869 DWORD packetlen = 0, packetoffset = 0;
00870
00871 if((hdr&0xc0) == 0x40)
00872 {
00873 pIn++;
00874 packetlen = len - (pIn - pInOrg);
00875 }
00876 else
00877 {
00878 if((hdr&0x40) == 0)
00879 subseq = (*pIn++)&0x7f;
00880
00881 #define GetWORD(var) \
00882 var = (var<<8)|(*pIn++); \
00883 var = (var<<8)|(*pIn++); \
00884
00885 GetWORD(packetlen);
00886 if(packetlen&0x8000) m_segments.fMerged = true;
00887 if((packetlen&0x4000) == 0) {GetWORD(packetlen); packetlen &= 0x3fffffff;}
00888 else packetlen &= 0x3fff;
00889
00890 GetWORD(packetoffset);
00891 if((packetoffset&0x4000) == 0) {GetWORD(packetoffset); packetoffset &= 0x3fffffff;}
00892 else packetoffset &= 0x3fff;
00893
00894 #undef GetWORD
00895
00896 if((hdr&0xc0) == 0xc0)
00897 m_segments.rtStart = 10000i64*packetoffset - m_rtStart, packetoffset = 0;
00898 else if((hdr&0xc0) == 0x80)
00899 packetoffset = packetlen - packetoffset;
00900
00901 seqnum = *pIn++;
00902 }
00903
00904 int len2 = min(len - (pIn - pInOrg), packetlen - packetoffset);
00905
00906 CAutoPtr<segment> s(new segment);
00907 s->offset = packetoffset;
00908 s->data.SetSize(len2);
00909 memcpy(s->data.GetData(), pIn, len2);
00910 m_segments.AddTail(s);
00911
00912 pIn += len2;
00913
00914 if((hdr&0x80) || packetoffset+len2 >= packetlen)
00915 {
00916 if(S_OK != (hr = DeliverSegments()))
00917 return hr;
00918 }
00919 }
00920 }
00921 else if(m_mt.subtype == MEDIASUBTYPE_RAAC || m_mt.subtype == MEDIASUBTYPE_RACP
00922 || m_mt.subtype == MEDIASUBTYPE_AAC)
00923 {
00924 BYTE* ptr = p->pData.GetData()+2;
00925
00926 CList<WORD> sizes;
00927 int total = 0;
00928 int remaining = p->pData.GetSize()-2;
00929 int expected = *(ptr-1)>>4;
00930
00931 while(total < remaining)
00932 {
00933 int size = (ptr[0]<<8)|(ptr[1]);
00934 sizes.AddTail(size);
00935 total += size;
00936 ptr += 2;
00937 remaining -= 2;
00938 expected--;
00939 }
00940
00941 ASSERT(total == remaining);
00942 ASSERT(expected == 0);
00943
00944 WAVEFORMATEX* wfe = (WAVEFORMATEX*)m_mt.pbFormat;
00945 REFERENCE_TIME rtDur = 10240000000i64/wfe->nSamplesPerSec * (wfe->cbSize>2?2:1);
00946 REFERENCE_TIME rtStart = p->rtStart;
00947 BOOL bDiscontinuity = p->bDiscontinuity;
00948
00949 POSITION pos = sizes.GetHeadPosition();
00950 while(pos)
00951 {
00952 CAutoPtr<Packet> p(new Packet);
00953 p->bDiscontinuity = bDiscontinuity;
00954 p->bSyncPoint = true;
00955 p->rtStart = rtStart;
00956 p->rtStop = rtStart + rtDur;
00957 p->pData.SetSize(sizes.GetNext(pos));
00958 memcpy(p->pData.GetData(), ptr, p->pData.GetSize());
00959 ptr += p->pData.GetSize();
00960 rtStart = p->rtStop;
00961 bDiscontinuity = false;
00962 if(S_OK != (hr = __super::DeliverPacket(p)))
00963 break;
00964 }
00965 }
00966 else
00967 {
00968 hr = __super::DeliverPacket(p);
00969 }
00970
00971 return hr;
00972 }
00973
00974
00975
00976
00977
00978 CRealMediaSourceFilter::CRealMediaSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
00979 : CRealMediaSplitterFilter(pUnk, phr)
00980 {
00981 m_clsid = __uuidof(this);
00982 m_pInput.Free();
00983 }
00984
00985
00986
00987
00988
00989 CRMFile::CRMFile(IAsyncReader* pAsyncReader, HRESULT& hr)
00990 : CBaseSplitterFile(pAsyncReader, hr)
00991 {
00992 if(FAILED(hr)) return;
00993 hr = Init();
00994 }
00995
00996 template<typename T>
00997 HRESULT CRMFile::Read(T& var)
00998 {
00999 HRESULT hr = Read((BYTE*)&var, sizeof(var));
01000 bswap(var);
01001 return hr;
01002 }
01003
01004 HRESULT CRMFile::Read(ChunkHdr& hdr)
01005 {
01006 memset(&hdr, 0, sizeof(hdr));
01007 HRESULT hr;
01008 if(S_OK != (hr = Read(hdr.object_id))
01009 || S_OK != (hr = Read(hdr.size))
01010 || S_OK != (hr = Read(hdr.object_version)))
01011 return hr;
01012 return S_OK;
01013 }
01014
01015 HRESULT CRMFile::Read(MediaPacketHeader& mph, bool fFull)
01016 {
01017 memset(&mph, 0, FIELD_OFFSET(MediaPacketHeader, pData));
01018 mph.stream = -1;
01019
01020 HRESULT hr;
01021
01022 UINT16 object_version;
01023 if(S_OK != (hr = Read(object_version))) return hr;
01024 if(object_version != 0 && object_version != 1) return S_OK;
01025
01026 UINT8 flags;
01027 if(S_OK != (hr = Read(mph.len))
01028 || S_OK != (hr = Read(mph.stream))
01029 || S_OK != (hr = Read(mph.tStart))
01030 || S_OK != (hr = Read(mph.reserved))
01031 || S_OK != (hr = Read(flags)))
01032 return hr;
01033 mph.flags = (MediaPacketHeader::flag_t)flags;
01034
01035 LONG len = mph.len;
01036 len -= sizeof(object_version);
01037 len -= FIELD_OFFSET(MediaPacketHeader, flags);
01038 len -= sizeof(flags);
01039 ASSERT(len >= 0);
01040 len = max(len, 0);
01041
01042 if(fFull)
01043 {
01044 mph.pData.SetSize(len);
01045 if(mph.len > 0 && S_OK != (hr = Read(mph.pData.GetData(), len)))
01046 return hr;
01047 }
01048 else
01049 {
01050 Seek(GetPos() + len);
01051 }
01052
01053 return S_OK;
01054 }
01055
01056
01057 HRESULT CRMFile::Init()
01058 {
01059 Seek(0);
01060
01061 bool fFirstChunk = true;
01062
01063 HRESULT hr;
01064
01065 ChunkHdr hdr;
01066 while(GetPos() < GetLength() && S_OK == (hr = Read(hdr)))
01067 {
01068 __int64 pos = GetPos() - sizeof(hdr);
01069
01070 if(fFirstChunk && hdr.object_id != '.RMF')
01071 return E_FAIL;
01072
01073 fFirstChunk = false;
01074
01075 if(pos + hdr.size > GetLength() && hdr.object_id != 'DATA')
01076 break;
01077
01078 if(hdr.object_id == 0x2E7261FD)
01079 return E_FAIL;
01080
01081 if(hdr.object_version == 0)
01082 {
01083 switch(hdr.object_id)
01084 {
01085 case '.RMF':
01086 if(S_OK != (hr = Read(m_fh.version))) return hr;
01087 if(hdr.size == 0x10) {WORD w = 0; if(S_OK != (hr = Read(w))) return hr; m_fh.nHeaders = w;}
01088 else if(S_OK != (hr = Read(m_fh.nHeaders))) return hr;
01089 break;
01090 case 'CONT':
01091 UINT16 slen;
01092 if(S_OK != (hr = Read(slen))) return hr;
01093 if(slen > 0 && S_OK != (hr = Read((BYTE*)m_cd.title.GetBufferSetLength(slen), slen))) return hr;
01094 if(S_OK != (hr = Read(slen))) return hr;
01095 if(slen > 0 && S_OK != (hr = Read((BYTE*)m_cd.author.GetBufferSetLength(slen), slen))) return hr;
01096 if(S_OK != (hr = Read(slen))) return hr;
01097 if(slen > 0 && S_OK != (hr = Read((BYTE*)m_cd.copyright.GetBufferSetLength(slen), slen))) return hr;
01098 if(S_OK != (hr = Read(slen))) return hr;
01099 if(slen > 0 && S_OK != (hr = Read((BYTE*)m_cd.comment.GetBufferSetLength(slen), slen))) return hr;
01100 break;
01101 case 'PROP':
01102 if(S_OK != (hr = Read(m_p.maxBitRate))) return hr;
01103 if(S_OK != (hr = Read(m_p.avgBitRate))) return hr;
01104 if(S_OK != (hr = Read(m_p.maxPacketSize))) return hr;
01105 if(S_OK != (hr = Read(m_p.avgPacketSize))) return hr;
01106 if(S_OK != (hr = Read(m_p.nPackets))) return hr;
01107 if(S_OK != (hr = Read(m_p.tDuration))) return hr;
01108 if(S_OK != (hr = Read(m_p.tPreroll))) return hr;
01109 if(S_OK != (hr = Read(m_p.ptrIndex))) return hr;
01110 if(S_OK != (hr = Read(m_p.ptrData))) return hr;
01111 if(S_OK != (hr = Read(m_p.nStreams))) return hr;
01112 UINT16 flags;
01113 if(S_OK != (hr = Read(flags))) return hr;
01114 m_p.flags = (Properies::flags_t)flags;
01115 break;
01116 case 'MDPR':
01117 {
01118 CAutoPtr<MediaProperies> mp(new MediaProperies);
01119 if(S_OK != (hr = Read(mp->stream))) return hr;
01120 if(S_OK != (hr = Read(mp->maxBitRate))) return hr;
01121 if(S_OK != (hr = Read(mp->avgBitRate))) return hr;
01122 if(S_OK != (hr = Read(mp->maxPacketSize))) return hr;
01123 if(S_OK != (hr = Read(mp->avgPacketSize))) return hr;
01124 if(S_OK != (hr = Read(mp->tStart))) return hr;
01125 if(S_OK != (hr = Read(mp->tPreroll))) return hr;
01126 if(S_OK != (hr = Read(mp->tDuration))) return hr;
01127 UINT8 slen;
01128 if(S_OK != (hr = Read(slen))) return hr;
01129 if(slen > 0 && S_OK != (hr = Read((BYTE*)mp->name.GetBufferSetLength(slen), slen))) return hr;
01130 if(S_OK != (hr = Read(slen))) return hr;
01131 if(slen > 0 && S_OK != (hr = Read((BYTE*)mp->mime.GetBufferSetLength(slen), slen))) return hr;
01132 UINT32 tsdlen;
01133 if(S_OK != (hr = Read(tsdlen))) return hr;
01134 mp->typeSpecData.SetSize(tsdlen);
01135 if(tsdlen > 0 && S_OK != (hr = Read(mp->typeSpecData.GetData(), tsdlen))) return hr;
01136 mp->width = mp->height = 0;
01137 mp->interlaced = mp->top_field_first = false;
01138 m_mps.AddTail(mp);
01139 break;
01140 }
01141 case 'DATA':
01142 {
01143 CAutoPtr<DataChunk> dc(new DataChunk);
01144 if(S_OK != (hr = Read(dc->nPackets))) return hr;
01145 if(S_OK != (hr = Read(dc->ptrNext))) return hr;
01146 dc->pos = GetPos();
01147 m_dcs.AddTail(dc);
01148 GetDimensions();
01149 break;
01150 }
01151 case 'INDX':
01152 {
01153 IndexChunkHeader ich;
01154 if(S_OK != (hr = Read(ich.nIndices))) return hr;
01155 if(S_OK != (hr = Read(ich.stream))) return hr;
01156 if(S_OK != (hr = Read(ich.ptrNext))) return hr;
01157 int stream = GetMasterStream();
01158 while(ich.nIndices-- > 0)
01159 {
01160 UINT16 object_version;
01161 if(S_OK != (hr = Read(object_version))) return hr;
01162 if(object_version == 0)
01163 {
01164 CAutoPtr<IndexRecord> ir(new IndexRecord);
01165 if(S_OK != (hr = Read(ir->tStart))) return hr;
01166 if(S_OK != (hr = Read(ir->ptrFilePos))) return hr;
01167 if(S_OK != (hr = Read(ir->packet))) return hr;
01168 if(ich.stream == stream) m_irs.AddTail(ir);
01169 }
01170 }
01171 break;
01172 }
01173 case '.SUB':
01174 if(hdr.size > sizeof(hdr))
01175 {
01176 int size = hdr.size - sizeof(hdr);
01177 CAutoVectorPtr<char> buff;
01178 if(!buff.Allocate(size)) return E_OUTOFMEMORY;
01179 char* p = buff;
01180 if(S_OK != (hr = Read((BYTE*)p, size))) return hr;
01181 for(char* end = p + size; p < end; )
01182 {
01183 subtitle s;
01184 s.name = p; p += s.name.GetLength()+1;
01185 CStringA len(p); p += len.GetLength()+1;
01186 s.data = CStringA(p, strtol(len, NULL, 10)); p += s.data.GetLength();
01187 m_subs.AddTail(s);
01188 }
01189 }
01190 break;
01191 }
01192 }
01193
01194 ASSERT(hdr.object_id == 'DATA'
01195 || GetPos() == pos + hdr.size
01196 || GetPos() == pos + sizeof(hdr));
01197
01198 pos += hdr.size;
01199 if(pos > GetPos())
01200 Seek(pos);
01201 }
01202
01203 return S_OK;
01204 }
01205
01206 #define GetBits(n) GetBits2(n, p, bit_offset, bit_buffer)
01207
01208 unsigned int GetBits2(int n, unsigned char*& p, unsigned int& bit_offset, unsigned int& bit_buffer)
01209 {
01210 unsigned int ret = ((unsigned int)bit_buffer >> (32-(n)));
01211
01212 bit_offset += n;
01213 bit_buffer <<= n;
01214 if(bit_offset > (32-16))
01215 {
01216 p += bit_offset >> 3;
01217 bit_offset &= 7;
01218 bit_buffer = (unsigned int)p[0] << 24;
01219 bit_buffer |= (unsigned int)p[1] << 16;
01220 bit_buffer |= (unsigned int)p[2] << 8;
01221 bit_buffer |= (unsigned int)p[3];
01222 bit_buffer <<= bit_offset;
01223 }
01224
01225 return ret;
01226 }
01227
01228 void GetDimensions(unsigned char* p, unsigned int* wi, unsigned int* hi)
01229 {
01230 unsigned int w, h, c;
01231
01232 const unsigned int cw[8] = {160, 176, 240, 320, 352, 640, 704, 0};
01233 const unsigned int ch1[8] = {120, 132, 144, 240, 288, 480, 0, 0};
01234 const unsigned int ch2[4] = {180, 360, 576, 0};
01235
01236 unsigned int bit_offset = 0;
01237 unsigned int bit_buffer = *(unsigned int*)p;
01238 bswap(bit_buffer);
01239
01240 GetBits(13);
01241
01242 GetBits(13);
01243
01244 w = cw[GetBits(3)];
01245 if(w == 0)
01246 {
01247 do
01248 {
01249 c = GetBits(8);
01250 w += (c << 2);
01251 }
01252 while(c == 255);
01253 }
01254
01255 c = GetBits(3);
01256
01257 h = ch1[c];
01258 if(h == 0)
01259 {
01260 c = ((c << 1) | GetBits(1)) & 3;
01261
01262 h = ch2[c];
01263 if(h == 0)
01264 {
01265 do
01266 {
01267 c = GetBits(8);
01268 h += (c << 2);
01269 }
01270 while(c == 255);
01271 }
01272 }
01273
01274 *wi = w;
01275 *hi = h;
01276 }
01277
01278 void GetDimensions_X10(unsigned char* p, unsigned int* wi, unsigned int* hi,
01279 bool *interlaced, bool *top_field_first, bool *repeat_field)
01280 {
01281 unsigned int w, h, c;
01282
01283 const unsigned int cw[8] = {160, 176, 240, 320, 352, 640, 704, 0};
01284 const unsigned int ch1[8] = {120, 132, 144, 240, 288, 480, 0, 0};
01285 const unsigned int ch2[4] = {180, 360, 576, 0};
01286
01287 unsigned int bit_offset = 0;
01288 unsigned int bit_buffer = *(unsigned int*)p;
01289 bswap(bit_buffer);
01290
01291 GetBits(9);
01292
01293 *interlaced = false;
01294 *top_field_first = false;
01295 *repeat_field = false;
01296 c = GetBits(1);
01297 if (c)
01298 {
01299 c = GetBits(1);
01300 if (c)
01301 *interlaced = true;
01302 c = GetBits(1);
01303 if (c)
01304 *top_field_first = true;
01305 c = GetBits(1);
01306 if (c)
01307 *repeat_field = true;
01308
01309 c = GetBits(1);
01310 c = GetBits(1);
01311 if (c)
01312 GetBits(2);
01313 }
01314
01315 GetBits(16);
01316
01317 w = cw[GetBits(3)];
01318 if(w == 0)
01319 {
01320 do
01321 {
01322 c = GetBits(8);
01323 w += (c << 2);
01324 }
01325 while(c == 255);
01326 }
01327
01328 c = GetBits(3);
01329
01330 h = ch1[c];
01331 if(h == 0)
01332 {
01333 c = ((c << 1) | GetBits(1)) & 3;
01334
01335 h = ch2[c];
01336 if(h == 0)
01337 {
01338 do
01339 {
01340 c = GetBits(8);
01341 h += (c << 2);
01342 }
01343 while(c == 255);
01344 }
01345 }
01346
01347 *wi = w;
01348 *hi = h;
01349 }
01350
01351 void CRMFile::GetDimensions()
01352 {
01353 POSITION pos = m_mps.GetHeadPosition();
01354 while(pos)
01355 {
01356 UINT64 filepos = GetPos();
01357
01358 MediaProperies* pmp = m_mps.GetNext(pos);
01359 if(pmp->mime == "video/x-pn-realvideo")
01360 {
01361 pmp->width = pmp->height = 0;
01362
01363 rvinfo rvi = *(rvinfo*)pmp->typeSpecData.GetData();
01364 rvi.bswap();
01365
01366 if(rvi.fcc2 != '04VR' && rvi.fcc2 != '14VR')
01367 continue;
01368
01369 MediaPacketHeader mph;
01370 while(S_OK == Read(mph))
01371 {
01372 if(mph.stream != pmp->stream || mph.len == 0
01373 || !(mph.flags&MediaPacketHeader::PN_KEYFRAME_FLAG))
01374 continue;
01375
01376 BYTE* p = mph.pData.GetData();
01377 BYTE* p0 = p;
01378 int len = mph.pData.GetCount();
01379
01380 BYTE hdr = *p++;
01381 DWORD packetlen = 0, packetoffset = 0;
01382
01383 if((hdr&0xc0) == 0x40)
01384 {
01385 packetlen = len - (++p - p0);
01386 }
01387 else
01388 {
01389 if((hdr&0x40) == 0) p++;
01390
01391 #define GetWORD(var) \
01392 var = (var<<8)|(*p++); \
01393 var = (var<<8)|(*p++); \
01394
01395 GetWORD(packetlen);
01396 if((packetlen&0x4000) == 0) {GetWORD(packetlen); packetlen &= 0x3fffffff;}
01397 else packetlen &= 0x3fff;
01398
01399 GetWORD(packetoffset);
01400 if((packetoffset&0x4000) == 0) {GetWORD(packetoffset); packetoffset &= 0x3fffffff;}
01401 else packetoffset &= 0x3fff;
01402
01403 #undef GetWORD
01404
01405 if((hdr&0xc0) == 0xc0) packetoffset = 0;
01406 else if((hdr&0xc0) == 0x80) packetoffset = packetlen - packetoffset;
01407
01408 p++;
01409 }
01410
01411 len = min(len - (p - p0), packetlen - packetoffset);
01412
01413 if(len > 0)
01414 {
01415 bool repeat_field;
01416 if(rvi.fcc2 == '14VR') ::GetDimensions_X10(p, &pmp->width, &pmp->height, &pmp->interlaced, &pmp->top_field_first, &repeat_field);
01417 else ::GetDimensions(p, &pmp->width, &pmp->height);
01418
01419 if(rvi.w == pmp->width && rvi.h == pmp->height)
01420 pmp->width = pmp->height = 0;
01421
01422 break;
01423 }
01424 }
01425 }
01426
01427 Seek(filepos);
01428 }
01429 }
01430
01431 int CRMFile::GetMasterStream()
01432 {
01433 int s1 = -1, s2 = -1;
01434
01435 POSITION pos = m_mps.GetHeadPosition();
01436 while(pos)
01437 {
01438 MediaProperies* pmp = m_mps.GetNext(pos);
01439 if(pmp->mime == "video/x-pn-realvideo") {s1 = pmp->stream; break;}
01440 else if(pmp->mime == "audio/x-pn-realaudio" && s2 == -1) s2 = pmp->stream;
01441 }
01442
01443 if(s1 == -1)
01444 s1 = s2;
01445
01446 return s1;
01447 }
01448
01449
01451
01452
01453
01454
01455
01456 CRealVideoDecoder::CRealVideoDecoder(LPUNKNOWN lpunk, HRESULT* phr)
01457 : CBaseVideoFilter(NAME("CRealVideoDecoder"), lpunk, phr, __uuidof(this))
01458 , m_hDrvDll(NULL)
01459 , m_dwCookie(0)
01460 {
01461 }
01462
01463 CRealVideoDecoder::~CRealVideoDecoder()
01464 {
01465 if(m_hDrvDll) FreeLibrary(m_hDrvDll);
01466 }
01467
01468 HRESULT CRealVideoDecoder::InitRV(const CMediaType* pmt)
01469 {
01470 FreeRV();
01471
01472 HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
01473
01474 rvinfo rvi = *(rvinfo*)(pmt->Format() + (pmt->formattype == FORMAT_VideoInfo ? sizeof(VIDEOINFOHEADER) : sizeof(VIDEOINFOHEADER2)));
01475 rvi.bswap();
01476
01477 #pragma pack(push, 1)
01478 struct {WORD unk1, w, h, unk3; DWORD unk2, subformat, unk5, format;} i =
01479 {11, rvi.w, rvi.h, 0, 0, rvi.type1, 1, rvi.type2};
01480 #pragma pack(pop)
01481
01482 if(FAILED(hr = RVInit(&i, &m_dwCookie)))
01483 return hr;
01484
01485 if(rvi.fcc2 <= '03VR' && rvi.type2 >= 0x20200002)
01486 {
01487 int nWidthHeight = (1+((rvi.type1>>16)&7));
01488 UINT32* pWH = new UINT32[nWidthHeight*2];
01489 pWH[0] = rvi.w; pWH[1] = rvi.h;
01490 for(int i = 2; i < nWidthHeight*2; i++)
01491 pWH[i] = rvi.morewh[i-2]*4;
01492 #pragma pack(push, 1)
01493 struct {UINT32 data1; UINT32 data2; UINT32* dimensions;} cmsg_data =
01494 {0x24, nWidthHeight, pWH};
01495 #pragma pack(pop)
01496 hr = RVCustomMessage(&cmsg_data, m_dwCookie);
01497 delete [] pWH;
01498 }
01499
01500 return hr;
01501 }
01502
01503 void CRealVideoDecoder::FreeRV()
01504 {
01505 if(m_dwCookie)
01506 {
01507 RVFree(m_dwCookie);
01508 m_dwCookie = 0;
01509 }
01510 }
01511
01512 HRESULT CRealVideoDecoder::Transform(IMediaSample* pIn)
01513 {
01514 CAutoLock cAutoLock(&m_csReceive);
01515
01516 HRESULT hr;
01517
01518 BYTE* pDataIn = NULL;
01519 if(FAILED(hr = pIn->GetPointer(&pDataIn)))
01520 return hr;
01521
01522 long len = pIn->GetActualDataLength();
01523 if(len <= 0) return S_OK;
01524
01525 REFERENCE_TIME rtStart, rtStop;
01526 pIn->GetTime(&rtStart, &rtStop);
01527
01528 rtStart += m_tStart;
01529
01530 int offset = 1+((*pDataIn)+1)*8;
01531
01532 #pragma pack(push, 1)
01533 struct {DWORD len, unk1, chunks; DWORD* extra; DWORD unk2, timestamp;} transform_in =
01534 {len - offset, 0, *pDataIn, (DWORD*)(pDataIn+1), 0, (DWORD)(rtStart/10000)};
01535 struct {DWORD unk1, unk2, timestamp, w, h;} transform_out =
01536 {0,0,0,0,0};
01537 #pragma pack(pop)
01538
01539 pDataIn += offset;
01540
01541 if(m_fDropFrames && m_timestamp+1 == transform_in.timestamp)
01542 {
01543 m_timestamp = transform_in.timestamp;
01544 return S_OK;
01545 }
01546
01547 hr = RVTransform(pDataIn, (BYTE*)m_pI420, &transform_in, &transform_out, m_dwCookie);
01548
01549 unsigned int tmp1, tmp2;
01550 bool interlaced = false, tmp3, tmp4;
01551 ::GetDimensions_X10(pDataIn, &tmp1, &tmp2, &interlaced, &tmp3, &tmp4);
01552
01553 m_timestamp = transform_in.timestamp;
01554
01555 if(FAILED(hr))
01556 {
01557 TRACE(_T("RV returned an error code!!!\n"));
01558 ASSERT(!(transform_out.unk1&1));
01559
01560 }
01561
01562 if(pIn->IsPreroll() == S_OK || rtStart < 0 || !(transform_out.unk1&1))
01563 return S_OK;
01564
01565 CComPtr<IMediaSample> pOut;
01566 BYTE* pDataOut = NULL;
01567 if(
01568 FAILED(hr = GetDeliveryBuffer(m_w, m_h, &pOut))
01569 || FAILED(hr = pOut->GetPointer(&pDataOut)))
01570 return hr;
01571
01572 BYTE* pI420[3] = {m_pI420, m_pI420Tmp, NULL};
01573
01574 if(interlaced)
01575 {
01576 int size = m_w*m_h;
01577 DeinterlaceBlend(pI420[1], pI420[0], m_w, m_h, m_w, m_w);
01578 DeinterlaceBlend(pI420[1]+size, pI420[0]+size, m_w/2, m_h/2, m_w/2, m_w/2);
01579 DeinterlaceBlend(pI420[1]+size*5/4, pI420[0]+size*5/4, m_w/2, m_h/2, m_w/2, m_w/2);
01580 pI420[2] = pI420[1], pI420[1] = pI420[0], pI420[0] = pI420[2];
01581 }
01582
01583 if(transform_out.w != m_w || transform_out.h != m_h)
01584 {
01585 Resize(pI420[0], transform_out.w, transform_out.h, pI420[1], m_w, m_h);
01586
01587 if(transform_out.w == m_w || transform_out.h == m_h)
01588 pI420[2] = pI420[1], pI420[1] = pI420[0], pI420[0] = pI420[2];
01589 }
01590
01591 rtStart = 10000i64*transform_out.timestamp - m_tStart;
01592 rtStop = rtStart + 1;
01593 pOut->SetTime(&rtStart, &rtStop);
01594
01595 pOut->SetDiscontinuity(pIn->IsDiscontinuity() == S_OK);
01596
01597 CopyBuffer(pDataOut, pI420[0], m_w, m_h, m_w, MEDIASUBTYPE_I420);
01598
01599 DbgLog((LOG_TRACE, 0, _T("V: rtStart=%I64d, rtStop=%I64d, disc=%d, sync=%d"),
01600 rtStart, rtStop, pOut->IsDiscontinuity() == S_OK, pOut->IsSyncPoint() == S_OK));
01601
01602 return m_pOutput->Deliver(pOut);
01603 }
01604
01605 void CRealVideoDecoder::Resize(BYTE* pIn, DWORD wi, DWORD hi, BYTE* pOut, DWORD wo, DWORD ho)
01606 {
01607 int si = wi*hi, so = wo*ho;
01608 ASSERT(((si*so)&3) == 0);
01609
01610 if(wi < wo)
01611 {
01612 ResizeWidth(pIn, wi, hi, pOut, wo, ho);
01613 ResizeWidth(pIn + si, wi/2, hi/2, pOut + so, wo/2, ho/2);
01614 ResizeWidth(pIn + si + si/4, wi/2, hi/2, pOut + so + so/4, wo/2, ho/2);
01615 if(hi == ho) return;
01616 ResizeHeight(pOut, wo, hi, pIn, wo, ho);
01617 ResizeHeight(pOut + so, wo/2, hi/2, pIn + so, wo/2, ho/2);
01618 ResizeHeight(pOut + so + so/4, wo/2, hi/2, pIn + so + so/4, wo/2, ho/2);
01619 }
01620 else if(hi < ho)
01621 {
01622 ResizeHeight(pIn, wi, hi, pOut, wo, ho);
01623 ResizeHeight(pIn + si, wi/2, hi/2, pOut + so, wo/2, ho/2);
01624 ResizeHeight(pIn + si + si/4, wi/2, hi/2, pOut + so + so/4, wo/2, ho/2);
01625 if(wi == wo) return;
01626 ASSERT(0);
01627 ResizeWidth(pOut, wi, ho, pIn, wo, ho);
01628 ResizeWidth(pOut + so, wi/2, ho/2, pIn + so, wo/2, ho/2);
01629 ResizeWidth(pOut + so + so/4, wi/2, ho/2, pIn + so + so/4, wo/2, ho/2);
01630 }
01631 }
01632
01633 void CRealVideoDecoder::ResizeWidth(BYTE* pIn, DWORD wi, DWORD hi, BYTE* pOut, DWORD wo, DWORD ho)
01634 {
01635 for(DWORD y = 0; y < hi; y++, pIn += wi, pOut += wo)
01636 {
01637 if(wi == wo) memcpy_accel(pOut, pIn, wo);
01638 else ResizeRow(pIn, wi, 1, pOut, wo, 1);
01639 }
01640 }
01641
01642 void CRealVideoDecoder::ResizeHeight(BYTE* pIn, DWORD wi, DWORD hi, BYTE* pOut, DWORD wo, DWORD ho)
01643 {
01644 if(hi == ho)
01645 {
01646 memcpy_accel(pOut, pIn, wo*ho);
01647 }
01648 else
01649 {
01650 for(DWORD x = 0; x < wo; x++, pIn++, pOut++)
01651 ResizeRow(pIn, hi, wo, pOut, ho, wo);
01652 }
01653 }
01654
01655 void CRealVideoDecoder::ResizeRow(BYTE* pIn, DWORD wi, DWORD dpi, BYTE* pOut, DWORD wo, DWORD dpo)
01656 {
01657 ASSERT(wi < wo);
01658
01659 if(dpo == 1)
01660 {
01661 for(DWORD i = 0, j = 0, dj = (wi<<16)/wo; i < wo-1; i++, pOut++, j += dj)
01662
01663 {
01664 BYTE* p = &pIn[j>>16];
01665 DWORD jf = j&0xffff;
01666 *pOut = ((p[0]*(0xffff-jf) + p[1]*jf) + 0x7fff) >> 16;
01667 }
01668
01669 *pOut = pIn[wi-1];
01670 }
01671 else
01672 {
01673 for(DWORD i = 0, j = 0, dj = (wi<<16)/wo; i < wo-1; i++, pOut += dpo, j += dj)
01674
01675 {
01676 BYTE* p = &pIn[dpi*(j>>16)];
01677 DWORD jf = j&0xffff;
01678 *pOut = ((p[0]*(0xffff-jf) + p[dpi]*jf) + 0x7fff) >> 16;
01679 }
01680
01681 *pOut = pIn[dpi*(wi-1)];
01682 }
01683 }
01684
01685 HRESULT CRealVideoDecoder::CheckInputType(const CMediaType* mtIn)
01686 {
01687 if(mtIn->majortype != MEDIATYPE_Video
01688 || mtIn->subtype != MEDIASUBTYPE_RV20
01689 && mtIn->subtype != MEDIASUBTYPE_RV30
01690 && mtIn->subtype != MEDIASUBTYPE_RV40
01691 && mtIn->subtype != MEDIASUBTYPE_RV41)
01692 return VFW_E_TYPE_NOT_ACCEPTED;
01693
01694 if(mtIn->formattype == FORMAT_VideoInfo2)
01695 {
01696 VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)mtIn->Format();
01697 if(vih2->dwPictAspectRatioX < vih2->bmiHeader.biWidth
01698 || vih2->dwPictAspectRatioY < vih2->bmiHeader.biHeight)
01699 return VFW_E_TYPE_NOT_ACCEPTED;
01700 }
01701
01702 if(!m_pInput->IsConnected())
01703 {
01704 if(m_hDrvDll) {FreeLibrary(m_hDrvDll); m_hDrvDll = NULL;}
01705
01706 CList<CString> paths;
01707 CString olddll, newdll, oldpath, newpath;
01708
01709 olddll.Format(_T("drv%c3260.dll"), (TCHAR)((mtIn->subtype.Data1>>16)&0xff));
01710 newdll =
01711 mtIn->subtype == FOURCCMap('14VR') ? _T("drvi.dll") :
01712 mtIn->subtype == FOURCCMap('02VR') ? _T("drv2.dll") :
01713 _T("drvc.dll");
01714
01715 CRegKey key;
01716 TCHAR buff[MAX_PATH];
01717 ULONG len = sizeof(buff);
01718 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Software\\RealNetworks\\Preferences\\DT_Codecs"), KEY_READ)
01719 && ERROR_SUCCESS == key.QueryStringValue(NULL, buff, &len) && _tcslen(buff) > 0)
01720 {
01721 oldpath = buff;
01722 TCHAR c = oldpath[oldpath.GetLength()-1];
01723 if(c != '\\' && c != '/') oldpath += '\\';
01724 key.Close();
01725 }
01726 len = sizeof(buff);
01727 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Helix\\HelixSDK\\10.0\\Preferences\\DT_Codecs"), KEY_READ)
01728 && ERROR_SUCCESS == key.QueryStringValue(NULL, buff, &len) && _tcslen(buff) > 0)
01729 {
01730 newpath = buff;
01731 TCHAR c = newpath[newpath.GetLength()-1];
01732 if(c != '\\' && c != '/') newpath += '\\';
01733 key.Close();
01734 }
01735
01736 if(!newpath.IsEmpty()) paths.AddTail(newpath + newdll);
01737 if(!oldpath.IsEmpty()) paths.AddTail(oldpath + newdll);
01738 paths.AddTail(newdll);
01739 if(!newpath.IsEmpty()) paths.AddTail(newpath + olddll);
01740 if(!oldpath.IsEmpty()) paths.AddTail(oldpath + olddll);
01741 paths.AddTail(olddll);
01742
01743 POSITION pos = paths.GetHeadPosition();
01744 while(pos && !(m_hDrvDll = LoadLibrary(paths.GetNext(pos))));
01745
01746 if(m_hDrvDll)
01747 {
01748 RVCustomMessage = (PRVCustomMessage)GetProcAddress(m_hDrvDll, "RV20toYUV420CustomMessage");
01749 RVFree = (PRVFree)GetProcAddress(m_hDrvDll, "RV20toYUV420Free");
01750 RVHiveMessage = (PRVHiveMessage)GetProcAddress(m_hDrvDll, "RV20toYUV420HiveMessage");
01751 RVInit = (PRVInit)GetProcAddress(m_hDrvDll, "RV20toYUV420Init");
01752 RVTransform = (PRVTransform)GetProcAddress(m_hDrvDll, "RV20toYUV420Transform");
01753
01754 if(!RVCustomMessage) RVCustomMessage = (PRVCustomMessage)GetProcAddress(m_hDrvDll, "RV40toYUV420CustomMessage");
01755 if(!RVFree) RVFree = (PRVFree)GetProcAddress(m_hDrvDll, "RV40toYUV420Free");
01756 if(!RVHiveMessage) RVHiveMessage = (PRVHiveMessage)GetProcAddress(m_hDrvDll, "RV40toYUV420HiveMessage");
01757 if(!RVInit) RVInit = (PRVInit)GetProcAddress(m_hDrvDll, "RV40toYUV420Init");
01758 if(!RVTransform) RVTransform = (PRVTransform)GetProcAddress(m_hDrvDll, "RV40toYUV420Transform");
01759 }
01760
01761 if(!m_hDrvDll || !RVCustomMessage
01762 || !RVFree || !RVHiveMessage
01763 || !RVInit || !RVTransform)
01764 return VFW_E_TYPE_NOT_ACCEPTED;
01765
01766 if(FAILED(InitRV(mtIn)))
01767 return VFW_E_TYPE_NOT_ACCEPTED;
01768 }
01769
01770 return S_OK;
01771 }
01772
01773 HRESULT CRealVideoDecoder::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
01774 {
01775 if(m_pOutput && m_pOutput->IsConnected())
01776 {
01777 BITMAPINFOHEADER bih1, bih2;
01778 if(ExtractBIH(mtOut, &bih1) && ExtractBIH(&m_pOutput->CurrentMediaType(), &bih2)
01779 && abs(bih1.biHeight) != abs(bih2.biHeight))
01780 return VFW_E_TYPE_NOT_ACCEPTED;
01781 }
01782
01783 return __super::CheckTransform(mtIn, mtOut);
01784 }
01785
01786 HRESULT CRealVideoDecoder::StartStreaming()
01787 {
01788 const CMediaType& mt = m_pInput->CurrentMediaType();
01789 if(FAILED(InitRV(&mt)))
01790 return E_FAIL;
01791
01792 int size = m_w*m_h;
01793 m_pI420.Allocate(size*3/2);
01794 memset(m_pI420, 0, size);
01795 memset(m_pI420 + size, 0x80, size/2);
01796 m_pI420Tmp.Allocate(size*3/2);
01797 memset(m_pI420Tmp, 0, size);
01798 memset(m_pI420Tmp + size, 0x80, size/2);
01799
01800 return __super::StartStreaming();
01801 }
01802
01803 HRESULT CRealVideoDecoder::StopStreaming()
01804 {
01805 m_pI420.Free();
01806 m_pI420Tmp.Free();
01807
01808 FreeRV();
01809
01810 return __super::StopStreaming();
01811 }
01812
01813 HRESULT CRealVideoDecoder::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
01814 {
01815 CAutoLock cAutoLock(&m_csReceive);
01816
01817 m_timestamp = ~0;
01818 m_fDropFrames = false;
01819
01820 DWORD tmp[2] = {20, 0};
01821 RVHiveMessage(tmp, m_dwCookie);
01822
01823 m_tStart = tStart;
01824 return __super::NewSegment(tStart, tStop, dRate);
01825 }
01826
01827 HRESULT CRealVideoDecoder::AlterQuality(Quality q)
01828 {
01829 if(q.Late > 500*10000i64) m_fDropFrames = true;
01830 if(q.Late <= 0) m_fDropFrames = false;
01831
01832 return E_NOTIMPL;
01833 }
01834
01836
01837
01838
01839
01840
01841 CRealAudioDecoder::CRealAudioDecoder(LPUNKNOWN lpunk, HRESULT* phr)
01842 : CTransformFilter(NAME("CRealAudioDecoder"), lpunk, __uuidof(this))
01843 , m_hDrvDll(NULL)
01844 , m_dwCookie(0)
01845 {
01846 if(phr) *phr = S_OK;
01847 }
01848
01849 CRealAudioDecoder::~CRealAudioDecoder()
01850 {
01851
01852 if(m_hDrvDll) FreeLibrary(m_hDrvDll);
01853 }
01854
01855 HRESULT CRealAudioDecoder::InitRA(const CMediaType* pmt)
01856 {
01857 FreeRA();
01858
01859 HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
01860
01861 if(RAOpenCodec2 && FAILED(hr = RAOpenCodec2(&m_dwCookie, m_dllpath))
01862 || RAOpenCodec && FAILED(hr = RAOpenCodec(&m_dwCookie)))
01863 return hr;
01864
01865 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)pmt->Format();
01866
01867
01868
01869
01870 DWORD cbSize = pwfe->cbSize;
01871 if(cbSize == sizeof(WAVEFORMATEX)) {ASSERT(0); cbSize = 0;}
01872
01873 WORD wBitsPerSample = pwfe->wBitsPerSample;
01874 if(!wBitsPerSample) wBitsPerSample = 16;
01875
01876 #pragma pack(push, 1)
01877 struct {DWORD freq; WORD bpsample, channels, quality; DWORD bpframe, packetsize, extralen; void* extra;} initdata =
01878 {pwfe->nSamplesPerSec, wBitsPerSample, pwfe->nChannels, 100,
01879 0, 0, 0, NULL};
01880 #pragma pack(pop)
01881
01882 CAutoVectorPtr<BYTE> pBuff;
01883
01884 if(pmt->subtype == MEDIASUBTYPE_AAC)
01885 {
01886 pBuff.Allocate(cbSize+1);
01887 pBuff[0] = 0x02;
01888 memcpy(pBuff+1, pwfe+1, cbSize);
01889 initdata.extralen = cbSize+1;
01890 initdata.extra = pBuff;
01891 }
01892 else
01893 {
01894 if(pmt->FormatLength() <= sizeof(WAVEFORMATEX) + cbSize)
01895 return hr;
01896
01897 BYTE* fmt = pmt->Format() + sizeof(WAVEFORMATEX) + cbSize;
01898
01899 for(int i = 0, len = pmt->FormatLength() - (sizeof(WAVEFORMATEX) + cbSize); i < len-4; i++, fmt++)
01900 {
01901 if(fmt[0] == '.' || fmt[1] == 'r' || fmt[2] == 'a')
01902 break;
01903 }
01904
01905 m_rai = *(rainfo*)fmt;
01906 m_rai.bswap();
01907
01908 BYTE* p;
01909
01910 if(m_rai.version2 == 4)
01911 {
01912 p = (BYTE*)((rainfo4*)fmt+1);
01913 int len = *p++; p += len; len = *p++; p += len;
01914 ASSERT(len == 4);
01915 }
01916 else if(m_rai.version2 == 5)
01917 {
01918 p = (BYTE*)((rainfo5*)fmt+1);
01919 }
01920 else
01921 {
01922 return hr;
01923 }
01924
01925 p += 3;
01926 if(m_rai.version2 == 5) p++;
01927
01928 initdata.bpframe = m_rai.sub_packet_size;
01929 initdata.packetsize = m_rai.coded_frame_size;
01930 initdata.extralen = *(DWORD*)p;
01931 initdata.extra = p + 4;
01932 }
01933
01934 if(FAILED(hr = RAInitDecoder(m_dwCookie, &initdata)))
01935 return hr;
01936
01937 if(RASetPwd)
01938 RASetPwd(m_dwCookie, "Ardubancel Quazanga");
01939
01940 if(RASetFlavor && FAILED(hr = RASetFlavor(m_dwCookie, m_rai.flavor)))
01941 return hr;
01942
01943 return hr;
01944 }
01945
01946 void CRealAudioDecoder::FreeRA()
01947 {
01948 if(m_dwCookie)
01949 {
01950 RAFreeDecoder(m_dwCookie);
01951 RACloseCodec(m_dwCookie);
01952 m_dwCookie = 0;
01953 }
01954 }
01955
01956 HRESULT CRealAudioDecoder::Receive(IMediaSample* pIn)
01957 {
01958 CAutoLock cAutoLock(&m_csReceive);
01959
01960 HRESULT hr;
01961
01962 AM_SAMPLE2_PROPERTIES* const pProps = m_pInput->SampleProps();
01963 if(pProps->dwStreamId != AM_STREAM_MEDIA)
01964 return m_pOutput->Deliver(pIn);
01965
01966 BYTE* pDataIn = NULL;
01967 if(FAILED(hr = pIn->GetPointer(&pDataIn))) return hr;
01968 BYTE* pDataInOrg = pDataIn;
01969
01970 long len = pIn->GetActualDataLength();
01971 if(len <= 0) return S_OK;
01972
01973 REFERENCE_TIME rtStart, rtStop;
01974 pIn->GetTime(&rtStart, &rtStop);
01975
01976
01977
01978
01979
01980
01981 if(S_OK == pIn->IsSyncPoint())
01982 {
01983 m_bufflen = 0;
01984 m_rtBuffStart = rtStart;
01985 m_fBuffDiscontinuity = pIn->IsDiscontinuity() == S_OK;
01986 }
01987
01988 BYTE* src = NULL;
01989 BYTE* dst = NULL;
01990
01991 int w = m_rai.coded_frame_size;
01992 int h = m_rai.sub_packet_h;
01993 int sps = m_rai.sub_packet_size;
01994
01995 if(m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_RAAC
01996 || m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_RACP
01997 || m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_AAC)
01998 {
01999 src = pDataIn;
02000 dst = pDataIn + len;
02001 w = len;
02002 }
02003 else
02004 {
02005 memcpy(&m_buff[m_bufflen], pDataIn, len);
02006 m_bufflen += len;
02007
02008 len = w*h;
02009
02010 if(m_bufflen >= len)
02011 {
02012 ASSERT(m_bufflen == len);
02013
02014 src = m_buff;
02015 dst = m_buff + len;
02016
02017 if(sps > 0
02018 && (m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_COOK
02019 || m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_ATRC))
02020 {
02021 for(int y = 0; y < h; y++)
02022 {
02023 for(int x = 0, w2 = w / sps; x < w2; x++)
02024 {
02025
02026 memcpy(dst + sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), src, sps);
02027 src += sps;
02028 }
02029 }
02030
02031 src = m_buff + len;
02032 dst = m_buff + len*2;
02033 }
02034 else if(m_pInput->CurrentMediaType().subtype == MEDIASUBTYPE_SIPR)
02035 {
02036
02037
02038 static BYTE sipr_swaps[38][2]={
02039 {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68},
02040 {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46},
02041 {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56},
02042 {42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83},
02043 {77,80} };
02044
02045 int bs=h*w*2/96;
02046 for(int n=0;n<38;n++){
02047 int i=bs*sipr_swaps[n][0];
02048 int o=bs*sipr_swaps[n][1];
02049
02050 for(int j=0;j<bs;j++){
02051 int x=(i&1) ? (src[(i>>1)]>>4) : (src[(i>>1)]&15);
02052 int y=(o&1) ? (src[(o>>1)]>>4) : (src[(o>>1)]&15);
02053 if(o&1) src[(o>>1)]=(src[(o>>1)]&0x0F)|(x<<4);
02054 else src[(o>>1)]=(src[(o>>1)]&0xF0)|x;
02055 if(i&1) src[(i>>1)]=(src[(i>>1)]&0x0F)|(y<<4);
02056 else src[(i>>1)]=(src[(i>>1)]&0xF0)|y;
02057 ++i;++o;
02058 }
02059 }
02060 }
02061
02062 m_bufflen = 0;
02063 }
02064 }
02065
02066 rtStart = m_rtBuffStart;
02067
02068 for(; src < dst; src += w)
02069 {
02070 CComPtr<IMediaSample> pOut;
02071 BYTE* pDataOut = NULL;
02072 if(FAILED(hr = m_pOutput->GetDeliveryBuffer(&pOut, NULL, NULL, 0))
02073 || FAILED(hr = pOut->GetPointer(&pDataOut)))
02074 return hr;
02075
02076 AM_MEDIA_TYPE* pmt;
02077 if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
02078 {
02079 CMediaType mt(*pmt);
02080 m_pOutput->SetMediaType(&mt);
02081 DeleteMediaType(pmt);
02082 }
02083
02084 hr = RADecode(m_dwCookie, src, w, pDataOut, &len, -1);
02085
02086 if(FAILED(hr))
02087 {
02088 TRACE(_T("RA returned an error code!!!\n"));
02089 continue;
02090
02091 }
02092
02093 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
02094
02095 rtStop = rtStart + 1000i64*len/pwfe->nAvgBytesPerSec*10000;
02096 pOut->SetTime(&rtStart, &rtStop);
02097 pOut->SetMediaTime(NULL, NULL);
02098
02099 pOut->SetDiscontinuity(m_fBuffDiscontinuity); m_fBuffDiscontinuity = false;
02100 pOut->SetSyncPoint(TRUE);
02101
02102 pOut->SetActualDataLength(len);
02103
02104 DbgLog((LOG_TRACE, 0, _T("A: rtStart=%I64d, rtStop=%I64d, disc=%d, sync=%d"),
02105 rtStart, rtStop, pOut->IsDiscontinuity() == S_OK, pOut->IsSyncPoint() == S_OK));
02106
02107 if(rtStart >= 0 && S_OK != (hr = m_pOutput->Deliver(pOut)))
02108 return hr;
02109
02110 rtStart = rtStop;
02111 }
02112
02113 m_rtBuffStart = rtStart;
02114
02115 return S_OK;
02116 }
02117
02118 HRESULT CRealAudioDecoder::CheckInputType(const CMediaType* mtIn)
02119 {
02120 if(mtIn->majortype != MEDIATYPE_Audio
02121 || mtIn->subtype != MEDIASUBTYPE_14_4
02122 && mtIn->subtype != MEDIASUBTYPE_28_8
02123 && mtIn->subtype != MEDIASUBTYPE_ATRC
02124 && mtIn->subtype != MEDIASUBTYPE_COOK
02125 && mtIn->subtype != MEDIASUBTYPE_DNET
02126 && mtIn->subtype != MEDIASUBTYPE_SIPR
02127 && mtIn->subtype != MEDIASUBTYPE_RAAC
02128 && mtIn->subtype != MEDIASUBTYPE_RACP
02129 && mtIn->subtype != MEDIASUBTYPE_AAC)
02130 return VFW_E_TYPE_NOT_ACCEPTED;
02131
02132 if(!m_pInput->IsConnected())
02133 {
02134 if(m_hDrvDll) {FreeLibrary(m_hDrvDll); m_hDrvDll = NULL;}
02135
02136 CList<CString> paths;
02137 CString olddll, newdll, oldpath, newpath;
02138
02139 TCHAR fourcc[5] =
02140 {
02141 (TCHAR)((mtIn->subtype.Data1>>0)&0xff),
02142 (TCHAR)((mtIn->subtype.Data1>>8)&0xff),
02143 (TCHAR)((mtIn->subtype.Data1>>16)&0xff),
02144 (TCHAR)((mtIn->subtype.Data1>>24)&0xff),
02145 0
02146 };
02147
02148 if(!_tcscmp(_T("RACP"), fourcc) || !_tcscmp(_T("\xff"), fourcc))
02149 _tcscpy(fourcc, _T("RAAC"));
02150
02151 olddll.Format(_T("%s3260.dll"), fourcc);
02152 newdll.Format(_T("%s.dll"), fourcc);
02153
02154 CRegKey key;
02155 TCHAR buff[MAX_PATH];
02156 ULONG len = sizeof(buff);
02157 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Software\\RealNetworks\\Preferences\\DT_Codecs"), KEY_READ)
02158 && ERROR_SUCCESS == key.QueryStringValue(NULL, buff, &len) && _tcslen(buff) > 0)
02159 {
02160 oldpath = buff;
02161 TCHAR c = oldpath[oldpath.GetLength()-1];
02162 if(c != '\\' && c != '/') oldpath += '\\';
02163 key.Close();
02164 }
02165 len = sizeof(buff);
02166 if(ERROR_SUCCESS == key.Open(HKEY_CLASSES_ROOT, _T("Helix\\HelixSDK\\10.0\\Preferences\\DT_Codecs"), KEY_READ)
02167 && ERROR_SUCCESS == key.QueryStringValue(NULL, buff, &len) && _tcslen(buff) > 0)
02168 {
02169 newpath = buff;
02170 TCHAR c = newpath[newpath.GetLength()-1];
02171 if(c != '\\' && c != '/') newpath += '\\';
02172 key.Close();
02173 }
02174
02175 if(!newpath.IsEmpty()) paths.AddTail(newpath + newdll);
02176 if(!oldpath.IsEmpty()) paths.AddTail(oldpath + newdll);
02177 paths.AddTail(newdll);
02178 if(!newpath.IsEmpty()) paths.AddTail(newpath + olddll);
02179 if(!oldpath.IsEmpty()) paths.AddTail(oldpath + olddll);
02180 paths.AddTail(olddll);
02181
02182 POSITION pos = paths.GetHeadPosition();
02183 while(pos && !(m_hDrvDll = LoadLibrary(paths.GetNext(pos))));
02184
02185 if(m_hDrvDll)
02186 {
02187 RACloseCodec = (PCloseCodec)GetProcAddress(m_hDrvDll, "RACloseCodec");
02188 RADecode = (PDecode)GetProcAddress(m_hDrvDll, "RADecode");
02189 RAFlush = (PFlush)GetProcAddress(m_hDrvDll, "RAFlush");
02190 RAFreeDecoder = (PFreeDecoder)GetProcAddress(m_hDrvDll, "RAFreeDecoder");
02191 RAGetFlavorProperty = (PGetFlavorProperty)GetProcAddress(m_hDrvDll, "RAGetFlavorProperty");
02192 RAInitDecoder = (PInitDecoder)GetProcAddress(m_hDrvDll, "RAInitDecoder");
02193 RAOpenCodec = (POpenCodec)GetProcAddress(m_hDrvDll, "RAOpenCodec");
02194 RAOpenCodec2 = (POpenCodec2)GetProcAddress(m_hDrvDll, "RAOpenCodec2");
02195 RASetFlavor = (PSetFlavor)GetProcAddress(m_hDrvDll, "RASetFlavor");
02196 RASetDLLAccessPath = (PSetDLLAccessPath)GetProcAddress(m_hDrvDll, "RASetDLLAccessPath");
02197 RASetPwd = (PSetPwd)GetProcAddress(m_hDrvDll, "RASetPwd");
02198 }
02199
02200 if(!m_hDrvDll || !RACloseCodec || !RADecode
02201 || !RAFreeDecoder || !RAGetFlavorProperty || !RAInitDecoder
02202 || !(RAOpenCodec || RAOpenCodec2) )
02203 return VFW_E_TYPE_NOT_ACCEPTED;
02204
02205 if(m_hDrvDll)
02206 {
02207 char buff[MAX_PATH];
02208 GetModuleFileNameA(m_hDrvDll, buff, MAX_PATH);
02209 CPathA p(buff);
02210 p.RemoveFileSpec();
02211 p.AddBackslash();
02212 m_dllpath = p.m_strPath;
02213 if(RASetDLLAccessPath)
02214 RASetDLLAccessPath("DT_Codecs=" + m_dllpath);
02215 }
02216
02217 if(FAILED(InitRA(mtIn)))
02218 return VFW_E_TYPE_NOT_ACCEPTED;
02219 }
02220
02221 return S_OK;
02222 }
02223
02224 HRESULT CRealAudioDecoder::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
02225 {
02226 return mtIn->majortype == MEDIATYPE_Audio && (mtIn->subtype == MEDIASUBTYPE_14_4
02227 || mtIn->subtype == MEDIASUBTYPE_28_8
02228 || mtIn->subtype == MEDIASUBTYPE_ATRC
02229 || mtIn->subtype == MEDIASUBTYPE_COOK
02230 || mtIn->subtype == MEDIASUBTYPE_DNET
02231 || mtIn->subtype == MEDIASUBTYPE_SIPR
02232 || mtIn->subtype == MEDIASUBTYPE_RAAC
02233 || mtIn->subtype == MEDIASUBTYPE_RACP
02234 || mtIn->subtype == MEDIASUBTYPE_AAC)
02235 && mtOut->majortype == MEDIATYPE_Audio && mtOut->subtype == MEDIASUBTYPE_PCM
02236 ? S_OK
02237 : VFW_E_TYPE_NOT_ACCEPTED;
02238 }
02239
02240 HRESULT CRealAudioDecoder::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
02241 {
02242 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
02243
02244 CComPtr<IMemAllocator> pAllocatorIn;
02245 m_pInput->GetAllocator(&pAllocatorIn);
02246 if(!pAllocatorIn) return E_UNEXPECTED;
02247
02248 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
02249
02250 WORD wBitsPerSample = pwfe->wBitsPerSample;
02251 if(!wBitsPerSample) wBitsPerSample = 16;
02252
02253
02254 pProperties->cBuffers = 8;
02255 pProperties->cbBuffer = pwfe->nChannels*pwfe->nSamplesPerSec*wBitsPerSample>>3;
02256 pProperties->cbAlign = 1;
02257 pProperties->cbPrefix = 0;
02258
02259 HRESULT hr;
02260 ALLOCATOR_PROPERTIES Actual;
02261 if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
02262 return hr;
02263
02264 return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
02265 ? E_FAIL
02266 : NOERROR);
02267 }
02268
02269 HRESULT CRealAudioDecoder::GetMediaType(int iPosition, CMediaType* pmt)
02270 {
02271 if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
02272
02273 *pmt = m_pInput->CurrentMediaType();
02274 pmt->subtype = MEDIASUBTYPE_PCM;
02275 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)pmt->ReallocFormatBuffer(sizeof(WAVEFORMATEX));
02276
02277 if(iPosition < 0) return E_INVALIDARG;
02278 if(iPosition > (pwfe->nChannels > 2 && pwfe->nChannels <= 6 ? 1 : 0)) return VFW_S_NO_MORE_ITEMS;
02279
02280 if(!pwfe->wBitsPerSample) pwfe->wBitsPerSample = 16;
02281
02282 pwfe->cbSize = 0;
02283 pwfe->wFormatTag = WAVE_FORMAT_PCM;
02284 pwfe->nBlockAlign = pwfe->nChannels*pwfe->wBitsPerSample>>3;
02285 pwfe->nAvgBytesPerSec = pwfe->nSamplesPerSec*pwfe->nBlockAlign;
02286
02287 if(iPosition == 0 && pwfe->nChannels > 2 && pwfe->nChannels <= 6)
02288 {
02289 static DWORD chmask[] =
02290 {
02291 KSAUDIO_SPEAKER_DIRECTOUT,
02292 KSAUDIO_SPEAKER_MONO,
02293 KSAUDIO_SPEAKER_STEREO,
02294 KSAUDIO_SPEAKER_STEREO|SPEAKER_FRONT_CENTER,
02295 KSAUDIO_SPEAKER_QUAD,
02296 KSAUDIO_SPEAKER_QUAD|SPEAKER_FRONT_CENTER,
02297 KSAUDIO_SPEAKER_5POINT1
02298 };
02299
02300 WAVEFORMATEXTENSIBLE* pwfex = (WAVEFORMATEXTENSIBLE*)pmt->ReallocFormatBuffer(sizeof(WAVEFORMATEXTENSIBLE));
02301 pwfex->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
02302 pwfex->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
02303 pwfex->dwChannelMask = chmask[pwfex->Format.nChannels];
02304 pwfex->Samples.wValidBitsPerSample = pwfex->Format.wBitsPerSample;
02305 pwfex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
02306 }
02307
02308 return S_OK;
02309 }
02310
02311 HRESULT CRealAudioDecoder::StartStreaming()
02312 {
02313 int w = m_rai.coded_frame_size;
02314 int h = m_rai.sub_packet_h;
02315 int sps = m_rai.sub_packet_size;
02316
02317 int len = w*h;
02318
02319 m_buff.Allocate(len*2);
02320 m_bufflen = 0;
02321 m_rtBuffStart = 0;
02322
02323 return __super::StartStreaming();
02324 }
02325
02326 HRESULT CRealAudioDecoder::StopStreaming()
02327 {
02328 m_buff.Free();
02329 m_bufflen = 0;
02330
02331 return __super::StopStreaming();
02332 }
02333
02334 HRESULT CRealAudioDecoder::EndOfStream()
02335 {
02336 return __super::EndOfStream();
02337 }
02338
02339 HRESULT CRealAudioDecoder::BeginFlush()
02340 {
02341 return __super::BeginFlush();
02342 }
02343
02344 HRESULT CRealAudioDecoder::EndFlush()
02345 {
02346 return __super::EndFlush();
02347 }
02348
02349 HRESULT CRealAudioDecoder::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
02350 {
02351 CAutoLock cAutoLock(&m_csReceive);
02352 m_tStart = tStart;
02353 m_bufflen = 0;
02354 m_rtBuffStart = 0;
02355 return __super::NewSegment(tStart, tStop, dRate);
02356 }