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 <math.h>
00024 #include <atlbase.h>
00025 #include <ks.h>
00026 #include <ksmedia.h>
00027 #include "libmpeg2.h"
00028 #include "Mpeg2DecFilter.h"
00029
00030 #include "..\..\..\DSUtil\DSUtil.h"
00031 #include "..\..\..\DSUtil\MediaTypes.h"
00032
00033 #include <initguid.h>
00034 #include "..\..\..\..\include\moreuuids.h"
00035 #include "..\..\..\..\include\matroska\matroska.h"
00036
00037 #ifdef REGISTER_FILTER
00038
00039 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00040 {
00041 {&MEDIATYPE_DVD_ENCRYPTED_PACK, &MEDIASUBTYPE_MPEG2_VIDEO},
00042 {&MEDIATYPE_MPEG2_PACK, &MEDIASUBTYPE_MPEG2_VIDEO},
00043 {&MEDIATYPE_MPEG2_PES, &MEDIASUBTYPE_MPEG2_VIDEO},
00044 {&MEDIATYPE_Video, &MEDIASUBTYPE_MPEG2_VIDEO},
00045 {&MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Packet},
00046 {&MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Payload},
00047 };
00048
00049 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00050 {
00051 {&MEDIATYPE_Video, &MEDIASUBTYPE_IYUV},
00052 };
00053
00054 const AMOVIESETUP_PIN sudpPins[] =
00055 {
00056 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00057 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
00058 };
00059
00060 const AMOVIESETUP_FILTER sudFilter[] =
00061 {
00062 {&__uuidof(CMpeg2DecFilter), L"Mpeg2Dec Filter", 0x40000002, countof(sudpPins), sudpPins},
00063 };
00064
00065 CFactoryTemplate g_Templates[] =
00066 {
00067 {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CMpeg2DecFilter>, NULL, &sudFilter[0]},
00068 };
00069
00070 int g_cTemplates = countof(g_Templates);
00071
00072 STDAPI DllRegisterServer()
00073 {
00074 return AMovieDllRegisterServer2(TRUE);
00075 }
00076
00077 STDAPI DllUnregisterServer()
00078 {
00079 return AMovieDllRegisterServer2(FALSE);
00080 }
00081
00082
00083
00084 #include "..\..\..\..\include\detours\detours.h"
00085
00086 DETOUR_TRAMPOLINE(BOOL WINAPI Real_IsDebuggerPresent(), IsDebuggerPresent);
00087 BOOL WINAPI Mine_IsDebuggerPresent()
00088 {
00089 TRACE(_T("Oops, somebody was trying to be naughty! (called IsDebuggerPresent)\n"));
00090 return FALSE;
00091 }
00092
00093 DETOUR_TRAMPOLINE(LONG WINAPI Real_ChangeDisplaySettingsExA(LPCSTR lpszDeviceName, LPDEVMODEA lpDevMode, HWND hwnd, DWORD dwFlags, LPVOID lParam), ChangeDisplaySettingsExA);
00094 DETOUR_TRAMPOLINE(LONG WINAPI Real_ChangeDisplaySettingsExW(LPCWSTR lpszDeviceName, LPDEVMODEW lpDevMode, HWND hwnd, DWORD dwFlags, LPVOID lParam), ChangeDisplaySettingsExW);
00095 LONG WINAPI Mine_ChangeDisplaySettingsEx(LONG ret, DWORD dwFlags, LPVOID lParam)
00096 {
00097 if(dwFlags&CDS_VIDEOPARAMETERS)
00098 {
00099 VIDEOPARAMETERS* vp = (VIDEOPARAMETERS*)lParam;
00100
00101 if(vp->Guid == GUIDFromCString(_T("{02C62061-1097-11d1-920F-00A024DF156E}"))
00102 && (vp->dwFlags&VP_FLAGS_COPYPROTECT))
00103 {
00104 if(vp->dwCommand == VP_COMMAND_GET)
00105 {
00106 if((vp->dwTVStandard&VP_TV_STANDARD_WIN_VGA) && vp->dwTVStandard != VP_TV_STANDARD_WIN_VGA)
00107 {
00108 TRACE(_T("Ooops, tv-out enabled? macrovision checks suck..."));
00109 vp->dwTVStandard = VP_TV_STANDARD_WIN_VGA;
00110 }
00111 }
00112 else if(vp->dwCommand == VP_COMMAND_SET)
00113 {
00114 TRACE(_T("Ooops, as I already told ya, no need for any macrovision bs here"));
00115 return 0;
00116 }
00117 }
00118 }
00119
00120 return ret;
00121 }
00122 LONG WINAPI Mine_ChangeDisplaySettingsExA(LPCSTR lpszDeviceName, LPDEVMODEA lpDevMode, HWND hwnd, DWORD dwFlags, LPVOID lParam)
00123 {
00124 return Mine_ChangeDisplaySettingsEx(Real_ChangeDisplaySettingsExA(lpszDeviceName, lpDevMode, hwnd, dwFlags, lParam), dwFlags, lParam);
00125 }
00126 LONG WINAPI Mine_ChangeDisplaySettingsExW(LPCWSTR lpszDeviceName, LPDEVMODEW lpDevMode, HWND hwnd, DWORD dwFlags, LPVOID lParam)
00127 {
00128 return Mine_ChangeDisplaySettingsEx(Real_ChangeDisplaySettingsExW(lpszDeviceName, lpDevMode, hwnd, dwFlags, lParam), dwFlags, lParam);
00129 }
00130
00131 bool fDetourInited = false;
00132
00133
00134
00135 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00136
00137 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00138 {
00139 if(!fDetourInited)
00140 {
00141 DetourFunctionWithTrampoline((PBYTE)Real_IsDebuggerPresent, (PBYTE)Mine_IsDebuggerPresent);
00142 DetourFunctionWithTrampoline((PBYTE)Real_ChangeDisplaySettingsExA, (PBYTE)Mine_ChangeDisplaySettingsExA);
00143 DetourFunctionWithTrampoline((PBYTE)Real_ChangeDisplaySettingsExW, (PBYTE)Mine_ChangeDisplaySettingsExW);
00144 fDetourInited = true;
00145 }
00146
00147 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00148 }
00149
00150 #endif
00151
00152
00153
00154
00155
00156 CMpeg2DecFilter::CMpeg2DecFilter(LPUNKNOWN lpunk, HRESULT* phr)
00157 : CBaseVideoFilter(NAME("CMpeg2DecFilter"), lpunk, phr, __uuidof(this))
00158 , m_fWaitForKeyFrame(true)
00159 {
00160 delete m_pInput;
00161
00162 if(FAILED(*phr)) return;
00163
00164 if(!(m_pInput = new CMpeg2DecInputPin(this, phr, L"Video"))) *phr = E_OUTOFMEMORY;
00165 if(FAILED(*phr)) return;
00166
00167 if(!(m_pSubpicInput = new CSubpicInputPin(this, phr))) *phr = E_OUTOFMEMORY;
00168 if(FAILED(*phr)) return;
00169
00170 if(!(m_pClosedCaptionOutput = new CClosedCaptionOutputPin(this, m_pLock, phr))) *phr = E_OUTOFMEMORY;
00171 if(FAILED(*phr)) return;
00172
00173 SetDeinterlaceMethod(DIAuto);
00174 SetBrightness(0.0);
00175 SetContrast(1.0);
00176 SetHue(0.0);
00177 SetSaturation(1.0);
00178 EnableForcedSubtitles(true);
00179 EnablePlanarYUV(true);
00180
00181 m_rate.Rate = 10000;
00182 m_rate.StartTime = 0;
00183 }
00184
00185 CMpeg2DecFilter::~CMpeg2DecFilter()
00186 {
00187 delete m_pSubpicInput;
00188 delete m_pClosedCaptionOutput;
00189 }
00190
00191 STDMETHODIMP CMpeg2DecFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00192 {
00193 return
00194 QI(IMpeg2DecFilter)
00195 __super::NonDelegatingQueryInterface(riid, ppv);
00196 }
00197
00198 int CMpeg2DecFilter::GetPinCount()
00199 {
00200 return 4;
00201 }
00202
00203 CBasePin* CMpeg2DecFilter::GetPin(int n)
00204 {
00205 switch(n)
00206 {
00207 case 0: return m_pInput;
00208 case 1: return m_pOutput;
00209 case 2: return m_pSubpicInput;
00210 case 3: return m_pClosedCaptionOutput;
00211 }
00212 return NULL;
00213 }
00214
00215 HRESULT CMpeg2DecFilter::EndOfStream()
00216 {
00217 CAutoLock cAutoLock(&m_csReceive);
00218 m_pClosedCaptionOutput->EndOfStream();
00219 return __super::EndOfStream();
00220 }
00221
00222 HRESULT CMpeg2DecFilter::BeginFlush()
00223 {
00224 m_pClosedCaptionOutput->DeliverBeginFlush();
00225 return __super::BeginFlush();
00226 }
00227
00228 HRESULT CMpeg2DecFilter::EndFlush()
00229 {
00230 m_pClosedCaptionOutput->DeliverEndFlush();
00231 return __super::EndFlush();
00232 }
00233
00234 HRESULT CMpeg2DecFilter::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
00235 {
00236 CAutoLock cAutoLock(&m_csReceive);
00237 m_pClosedCaptionOutput->DeliverNewSegment(tStart, tStop, dRate);
00238 m_fDropFrames = false;
00239 return __super::NewSegment(tStart, tStop, dRate);
00240 }
00241
00242 void CMpeg2DecFilter::InputTypeChanged()
00243 {
00244 CAutoLock cAutoLock(&m_csReceive);
00245
00246 TRACE(_T("ResetMpeg2Decoder()\n"));
00247
00248 for(int i = 0; i < countof(m_dec->m_pictures); i++)
00249 {
00250 m_dec->m_pictures[i].rtStart = m_dec->m_pictures[i].rtStop = _I64_MIN+1;
00251 m_dec->m_pictures[i].fDelivered = false;
00252 m_dec->m_pictures[i].flags &= ~PIC_MASK_CODING_TYPE;
00253 }
00254
00255 CMediaType& mt = m_pInput->CurrentMediaType();
00256
00257 BYTE* pSequenceHeader = NULL;
00258 DWORD cbSequenceHeader = 0;
00259
00260 if(mt.formattype == FORMAT_MPEGVideo)
00261 {
00262 pSequenceHeader = ((MPEG1VIDEOINFO*)mt.Format())->bSequenceHeader;
00263 cbSequenceHeader = ((MPEG1VIDEOINFO*)mt.Format())->cbSequenceHeader;
00264 }
00265 else if(mt.formattype == FORMAT_MPEG2_VIDEO)
00266 {
00267 pSequenceHeader = (BYTE*)((MPEG2VIDEOINFO*)mt.Format())->dwSequenceHeader;
00268 cbSequenceHeader = ((MPEG2VIDEOINFO*)mt.Format())->cbSequenceHeader;
00269 }
00270
00271 m_dec->mpeg2_close();
00272 m_dec->mpeg2_init();
00273
00274 m_dec->mpeg2_buffer(pSequenceHeader, pSequenceHeader + cbSequenceHeader);
00275
00276 m_fWaitForKeyFrame = true;
00277
00278 m_fFilm = false;
00279 m_fb.flags = 0;
00280 }
00281
00282 HRESULT CMpeg2DecFilter::Transform(IMediaSample* pIn)
00283 {
00284 HRESULT hr;
00285
00286 BYTE* pDataIn = NULL;
00287 if(FAILED(hr = pIn->GetPointer(&pDataIn)))
00288 return hr;
00289
00290 long len = pIn->GetActualDataLength();
00291
00292 ((CDeCSSInputPin*)m_pInput)->StripPacket(pDataIn, len);
00293
00294 if(pIn->IsDiscontinuity() == S_OK)
00295 {
00296 InputTypeChanged();
00297 }
00298
00299 REFERENCE_TIME rtStart = _I64_MIN, rtStop = _I64_MIN;
00300 hr = pIn->GetTime(&rtStart, &rtStop);
00301 if(FAILED(hr)) rtStart = rtStop = _I64_MIN;
00302
00303 while(len >= 0)
00304 {
00305 mpeg2_state_t state = m_dec->mpeg2_parse();
00306
00307 __asm emms;
00308
00309 switch(state)
00310 {
00311 case STATE_BUFFER:
00312 if(len == 0) len = -1;
00313 else {m_dec->mpeg2_buffer(pDataIn, pDataIn + len); len = 0;}
00314 break;
00315 case STATE_INVALID:
00316 TRACE(_T("STATE_INVALID\n"));
00317
00318
00319 break;
00320 case STATE_GOP:
00321
00322 if(m_dec->m_info.m_user_data_len > 4 && *(DWORD*)m_dec->m_info.m_user_data == 0xf8014343
00323 && m_pClosedCaptionOutput->IsConnected())
00324 {
00325 CComPtr<IMediaSample> pSample;
00326 m_pClosedCaptionOutput->GetDeliveryBuffer(&pSample, NULL, NULL, 0);
00327 BYTE* pData = NULL;
00328 pSample->GetPointer(&pData);
00329 *(DWORD*)pData = 0xb2010000;
00330 memcpy(pData + 4, m_dec->m_info.m_user_data, m_dec->m_info.m_user_data_len);
00331 pSample->SetActualDataLength(m_dec->m_info.m_user_data_len + 4);
00332 m_pClosedCaptionOutput->Deliver(pSample);
00333 }
00334 break;
00335 case STATE_SEQUENCE:
00336 TRACE(_T("STATE_SEQUENCE\n"));
00337 m_AvgTimePerFrame = 10i64 * m_dec->m_info.m_sequence->frame_period / 27;
00338 if(m_AvgTimePerFrame == 0) m_AvgTimePerFrame = ((VIDEOINFOHEADER*)m_pInput->CurrentMediaType().Format())->AvgTimePerFrame;
00339 break;
00340 case STATE_PICTURE:
00341
00342
00343
00344
00345 m_dec->m_picture->rtStart = rtStart;
00346 rtStart = _I64_MIN;
00347 m_dec->m_picture->fDelivered = false;
00348
00349 m_dec->mpeg2_skip(m_fDropFrames && (m_dec->m_picture->flags&PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_B);
00350
00351 break;
00352 case STATE_SLICE:
00353 case STATE_END:
00354 {
00355 mpeg2_picture_t* picture = m_dec->m_info.m_display_picture;
00356 mpeg2_picture_t* picture_2nd = m_dec->m_info.m_display_picture_2nd;
00357 mpeg2_fbuf_t* fbuf = m_dec->m_info.m_display_fbuf;
00358
00359 if(picture && fbuf && !(picture->flags&PIC_FLAG_SKIP))
00360 {
00361 ASSERT(!picture->fDelivered);
00362
00363
00364
00365 m_fb.rtStart = picture->rtStart;
00366 if(m_fb.rtStart == _I64_MIN) m_fb.rtStart = m_fb.rtStop;
00367 m_fb.rtStop = m_fb.rtStart + m_AvgTimePerFrame * picture->nb_fields / (picture_2nd ? 1 : 2);
00368
00369 REFERENCE_TIME rtStart = m_fb.rtStart;
00370 REFERENCE_TIME rtStop = m_fb.rtStop;
00371
00372
00373
00374 if(!(m_dec->m_info.m_sequence->flags&SEQ_FLAG_PROGRESSIVE_SEQUENCE)
00375 && (picture->flags&PIC_FLAG_PROGRESSIVE_FRAME))
00376 {
00377 if(!m_fFilm
00378 && (picture->flags&PIC_FLAG_REPEAT_FIRST_FIELD)
00379 && !(m_fb.flags&PIC_FLAG_REPEAT_FIRST_FIELD))
00380 {
00381 TRACE(_T("m_fFilm = true\n"));
00382 m_fFilm = true;
00383 }
00384 else if(m_fFilm
00385 && !(picture->flags&PIC_FLAG_REPEAT_FIRST_FIELD)
00386 && !(m_fb.flags&PIC_FLAG_REPEAT_FIRST_FIELD))
00387 {
00388 TRACE(_T("m_fFilm = false\n"));
00389 m_fFilm = false;
00390 }
00391 }
00392
00393 m_fb.flags = picture->flags;
00394
00395 ASSERT(!(m_fb.flags&PIC_FLAG_SKIP));
00396
00397
00398
00399 int w = m_dec->m_info.m_sequence->picture_width;
00400 int h = m_dec->m_info.m_sequence->picture_height;
00401 int pitch = m_dec->m_info.m_sequence->width;
00402
00403 if(m_fb.w != w || m_fb.h != h || m_fb.pitch != pitch)
00404 m_fb.alloc(w, h, pitch);
00405
00406
00407
00408 ditype di = GetDeinterlaceMethod();
00409
00410 if(di == DIAuto || di != DIWeave && di != DIBlend && di != DIBob)
00411 {
00412 if(!!(m_dec->m_info.m_sequence->flags&SEQ_FLAG_PROGRESSIVE_SEQUENCE))
00413 di = DIWeave;
00414 else if(m_fFilm)
00415 di = DIWeave;
00416 else if(!(m_fb.flags&PIC_FLAG_PROGRESSIVE_FRAME))
00417 di = DIBlend;
00418 else
00419
00420
00421
00422
00423 di = DIBlend;
00424
00425 }
00426
00427 if(di == DIWeave)
00428 {
00429 BitBltFromI420ToI420(w, h,
00430 m_fb.buf[0], m_fb.buf[1], m_fb.buf[2], pitch,
00431 fbuf->buf[0], fbuf->buf[1], fbuf->buf[2], pitch);
00432 }
00433 else if(di == DIBlend)
00434 {
00435 DeinterlaceBlend(m_fb.buf[0], fbuf->buf[0], w, h, pitch, pitch);
00436 DeinterlaceBlend(m_fb.buf[1], fbuf->buf[1], w/2, h/2, pitch/2, pitch/2);
00437 DeinterlaceBlend(m_fb.buf[2], fbuf->buf[2], w/2, h/2, pitch/2, pitch/2);
00438 }
00439 else if(di == DIBob)
00440 {
00441 if(m_fb.flags&PIC_FLAG_TOP_FIELD_FIRST)
00442 {
00443 BitBltFromRGBToRGB(w, h/2, m_fb.buf[0], pitch*2, 8, fbuf->buf[0], pitch*2, 8);
00444 AvgLines8(m_fb.buf[0], h, pitch);
00445 BitBltFromRGBToRGB(w/2, h/4, m_fb.buf[1], pitch, 8, fbuf->buf[1], pitch, 8);
00446 AvgLines8(m_fb.buf[1], h/2, pitch/2);
00447 BitBltFromRGBToRGB(w/2, h/4, m_fb.buf[2], pitch, 8, fbuf->buf[2], pitch, 8);
00448 AvgLines8(m_fb.buf[2], h/2, pitch/2);
00449 }
00450 else
00451 {
00452 BitBltFromRGBToRGB(w, h/2, m_fb.buf[0]+pitch, pitch*2, 8, fbuf->buf[0]+pitch, pitch*2, 8);
00453 AvgLines8(m_fb.buf[0]+pitch, h-1, pitch);
00454 BitBltFromRGBToRGB(w/2, h/4, m_fb.buf[1]+pitch/2, pitch, 8, fbuf->buf[1]+pitch/2, pitch, 8);
00455 AvgLines8(m_fb.buf[1]+pitch/2, (h-1)/2, pitch/2);
00456 BitBltFromRGBToRGB(w/2, h/4, m_fb.buf[2]+pitch/2, pitch, 8, fbuf->buf[2]+pitch/2, pitch, 8);
00457 AvgLines8(m_fb.buf[2]+pitch/2, (h-1)/2, pitch/2);
00458 }
00459
00460 m_fb.rtStart = rtStart;
00461 m_fb.rtStop = (rtStart + rtStop) / 2;
00462 }
00463
00464
00465
00466 ApplyBrContHueSat(m_fb.buf[0], m_fb.buf[1], m_fb.buf[2], w, h, pitch);
00467
00468
00469
00470 picture->fDelivered = true;
00471
00472 if(FAILED(hr = Deliver(false)))
00473 return hr;
00474
00475
00476
00477 if(di == DIBob)
00478 {
00479 if(m_fb.flags&PIC_FLAG_TOP_FIELD_FIRST)
00480 {
00481 BitBltFromRGBToRGB(w, h/2, m_fb.buf[0]+pitch, pitch*2, 8, fbuf->buf[0]+pitch, pitch*2, 8);
00482 AvgLines8(m_fb.buf[0]+pitch, h-1, pitch);
00483 BitBltFromRGBToRGB(w/2, h/4, m_fb.buf[1]+pitch/2, pitch, 8, fbuf->buf[1]+pitch/2, pitch, 8);
00484 AvgLines8(m_fb.buf[1]+pitch/2, (h-1)/2, pitch/2);
00485 BitBltFromRGBToRGB(w/2, h/4, m_fb.buf[2]+pitch/2, pitch, 8, fbuf->buf[2]+pitch/2, pitch, 8);
00486 AvgLines8(m_fb.buf[2]+pitch/2, (h-1)/2, pitch/2);
00487 }
00488 else
00489 {
00490 BitBltFromRGBToRGB(w, h/2, m_fb.buf[0], pitch*2, 8, fbuf->buf[0], pitch*2, 8);
00491 AvgLines8(m_fb.buf[0], h, pitch);
00492 BitBltFromRGBToRGB(w/2, h/4, m_fb.buf[1], pitch, 8, fbuf->buf[1], pitch, 8);
00493 AvgLines8(m_fb.buf[1], h/2, pitch/2);
00494 BitBltFromRGBToRGB(w/2, h/4, m_fb.buf[2], pitch, 8, fbuf->buf[2], pitch, 8);
00495 AvgLines8(m_fb.buf[2], h/2, pitch/2);
00496 }
00497
00498 m_fb.rtStart = (rtStart + rtStop) / 2;
00499 m_fb.rtStop = rtStop;
00500
00501
00502
00503 ApplyBrContHueSat(m_fb.buf[0], m_fb.buf[1], m_fb.buf[2], w, h, pitch);
00504
00505
00506
00507 picture->fDelivered = true;
00508
00509 if(FAILED(hr = Deliver(false)))
00510 return hr;
00511 }
00512 }
00513 }
00514 break;
00515 default:
00516 break;
00517 }
00518 }
00519
00520 return S_OK;
00521 }
00522
00523 HRESULT CMpeg2DecFilter::Deliver(bool fRepeatLast)
00524 {
00525 CAutoLock cAutoLock(&m_csReceive);
00526
00527 if((m_fb.flags&PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_I)
00528 m_fWaitForKeyFrame = false;
00529
00530 TCHAR frametype[] = {'?','I', 'P', 'B', 'D'};
00531
00532
00533 TRACE(_T("%010I64d - %010I64d [%c] [prsq %d prfr %d tff %d rff %d] (%dx%d %d) (preroll %d)\n"),
00534 m_fb.rtStart, m_fb.rtStop,
00535 frametype[m_fb.flags&PIC_MASK_CODING_TYPE],
00536 !!(m_dec->m_info.m_sequence->flags&SEQ_FLAG_PROGRESSIVE_SEQUENCE),
00537 !!(m_fb.flags&PIC_FLAG_PROGRESSIVE_FRAME),
00538 !!(m_fb.flags&PIC_FLAG_TOP_FIELD_FIRST),
00539 !!(m_fb.flags&PIC_FLAG_REPEAT_FIRST_FIELD),
00540
00541
00542 m_fb.w, m_fb.h, m_fb.pitch,
00543 !!(m_fb.rtStart < 0 || m_fWaitForKeyFrame));
00544
00545 if(m_fb.rtStart < 0 || m_fWaitForKeyFrame)
00546 return S_OK;
00547
00548 HRESULT hr;
00549
00550 CComPtr<IMediaSample> pOut;
00551 BYTE* pDataOut = NULL;
00552 if(FAILED(hr = GetDeliveryBuffer(m_fb.w, m_fb.h, &pOut))
00553 || FAILED(hr = pOut->GetPointer(&pDataOut)))
00554 return hr;
00555
00556 {
00557 CMpeg2DecInputPin* pPin = (CMpeg2DecInputPin*)m_pInput;
00558 CAutoLock cAutoLock(&pPin->m_csRateLock);
00559 if(m_rate.Rate != pPin->m_ratechange.Rate)
00560 {
00561 m_rate.Rate = pPin->m_ratechange.Rate;
00562 m_rate.StartTime = m_fb.rtStart;
00563 }
00564 }
00565
00566 REFERENCE_TIME rtStart = m_fb.rtStart;
00567 REFERENCE_TIME rtStop = m_fb.rtStop;
00568 rtStart = m_rate.StartTime + (rtStart - m_rate.StartTime) * m_rate.Rate / 10000;
00569 rtStop = m_rate.StartTime + (rtStop - m_rate.StartTime) * m_rate.Rate / 10000;
00570
00571 pOut->SetTime(&rtStart, &rtStop);
00572 pOut->SetMediaTime(NULL, NULL);
00573
00574 if(m_fb.h == 1088)
00575 {
00576 memset(m_fb.buf[0] + m_fb.w*(m_fb.h-8), 0xff, m_fb.w*8);
00577 memset(m_fb.buf[1] + m_fb.w*(m_fb.h-8)/4, 0x80, m_fb.w*8/4);
00578 memset(m_fb.buf[2] + m_fb.w*(m_fb.h-8)/4, 0x80, m_fb.w*8/4);
00579 }
00580
00581 BYTE** buf = &m_fb.buf[0];
00582
00583 if(m_pSubpicInput->HasAnythingToRender(m_fb.rtStart))
00584 {
00585 BitBltFromI420ToI420(m_fb.w, m_fb.h,
00586 m_fb.buf[3], m_fb.buf[4], m_fb.buf[5], m_fb.pitch,
00587 m_fb.buf[0], m_fb.buf[1], m_fb.buf[2], m_fb.pitch);
00588
00589 buf = &m_fb.buf[3];
00590
00591 m_pSubpicInput->RenderSubpics(m_fb.rtStart, buf, m_fb.pitch, m_fb.h);
00592 }
00593
00594 CopyBuffer(pDataOut, buf, (m_fb.w+7)&~7, m_fb.h, m_fb.pitch, MEDIASUBTYPE_I420);
00595
00596 if(FAILED(hr = m_pOutput->Deliver(pOut)))
00597 return hr;
00598
00599 return S_OK;
00600 }
00601
00602 #include "..\..\..\..\include\IFilterVersion.h"
00603
00604 [uuid("04FE9017-F873-410E-871E-AB91661A4EF7")]
00605 struct ffdshow {};
00606 [uuid("93A22E7A-5091-45ef-BA61-6DA26156A5D0")]
00607 struct dvs {};
00608 [uuid("9852A670-F845-491b-9BE6-EBD841B8A613")]
00609 struct dvsauto {};
00610 [uuid("fd501043-8ebe-11ce-8183-00aa00577da1")]
00611 struct dladapter {};
00612
00613 HRESULT CMpeg2DecFilter::CheckConnect(PIN_DIRECTION dir, IPin* pPin)
00614 {
00615 if(dir == PINDIR_OUTPUT)
00616 {
00617 if(GetCLSID(m_pInput->GetConnected()) == CLSID_DVDNavigator)
00618 {
00619
00620
00621 CLSID clsid = GetCLSID(pPin);
00622
00623 DWORD ver = 0;
00624 if(CComQIPtr<IFilterVersion> pFV = GetFilterFromPin(pPin))
00625 ver = pFV->GetFilterVersion();
00626
00627 if(clsid != CLSID_OverlayMixer
00628
00629 && clsid != CLSID_VideoMixingRenderer
00630 && clsid != CLSID_VideoMixingRenderer9
00631 && clsid != __uuidof(ffdshow)
00632 && (clsid != __uuidof(dvs) || ver < 0x0234)
00633 && (clsid != __uuidof(dvsauto) || ver < 0x0234)
00634 && clsid != __uuidof(dladapter))
00635 return E_FAIL;
00636 }
00637 }
00638
00639 return __super::CheckConnect(dir, pPin);
00640 }
00641
00642 HRESULT CMpeg2DecFilter::CheckInputType(const CMediaType* mtIn)
00643 {
00644 if(mtIn->formattype == FORMAT_MPEG2_VIDEO && mtIn->pbFormat)
00645 {
00646 MPEG2VIDEOINFO* vih = (MPEG2VIDEOINFO*)mtIn->pbFormat;
00647 if(vih->cbSequenceHeader > 0 && (vih->dwSequenceHeader[0] & 0x00ffffff) != 0x00010000)
00648 return VFW_E_TYPE_NOT_ACCEPTED;
00649 }
00650
00651 return (mtIn->majortype == MEDIATYPE_DVD_ENCRYPTED_PACK && mtIn->subtype == MEDIASUBTYPE_MPEG2_VIDEO
00652 || mtIn->majortype == MEDIATYPE_MPEG2_PACK && mtIn->subtype == MEDIASUBTYPE_MPEG2_VIDEO
00653 || mtIn->majortype == MEDIATYPE_MPEG2_PES && mtIn->subtype == MEDIASUBTYPE_MPEG2_VIDEO
00654 || mtIn->majortype == MEDIATYPE_Video && mtIn->subtype == MEDIASUBTYPE_MPEG2_VIDEO
00655 || mtIn->majortype == MEDIATYPE_Video && mtIn->subtype == MEDIASUBTYPE_MPEG1Packet
00656 || mtIn->majortype == MEDIATYPE_Video && mtIn->subtype == MEDIASUBTYPE_MPEG1Payload)
00657 ? S_OK
00658 : VFW_E_TYPE_NOT_ACCEPTED;
00659 }
00660
00661 HRESULT CMpeg2DecFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
00662 {
00663 bool fPlanarYUV = mtOut->subtype == MEDIASUBTYPE_YV12 || mtOut->subtype == MEDIASUBTYPE_I420 || mtOut->subtype == MEDIASUBTYPE_IYUV;
00664
00665 return SUCCEEDED(__super::CheckTransform(mtIn, mtOut))
00666 && (!fPlanarYUV || IsPlanarYUVEnabled())
00667 ? S_OK
00668 : VFW_E_TYPE_NOT_ACCEPTED;
00669 }
00670
00671 HRESULT CMpeg2DecFilter::StartStreaming()
00672 {
00673 HRESULT hr = __super::StartStreaming();
00674 if(FAILED(hr)) return hr;
00675
00676 m_dec.Attach(new CMpeg2Dec());
00677 if(!m_dec) return E_OUTOFMEMORY;
00678
00679 InputTypeChanged();
00680
00681 return S_OK;
00682 }
00683
00684 HRESULT CMpeg2DecFilter::StopStreaming()
00685 {
00686 m_dec.Free();
00687
00688 return __super::StopStreaming();
00689 }
00690
00691 HRESULT CMpeg2DecFilter::AlterQuality(Quality q)
00692 {
00693 if(q.Late > 500*10000i64) m_fDropFrames = true;
00694 else if(q.Late <= 0) m_fDropFrames = false;
00695
00696
00697 return S_OK;
00698 }
00699
00700
00701
00702 STDMETHODIMP CMpeg2DecFilter::SetDeinterlaceMethod(ditype di)
00703 {
00704 CAutoLock cAutoLock(&m_csProps);
00705 m_di = di;
00706 return S_OK;
00707 }
00708
00709 STDMETHODIMP_(ditype) CMpeg2DecFilter::GetDeinterlaceMethod()
00710 {
00711 CAutoLock cAutoLock(&m_csProps);
00712 return m_di;
00713 }
00714
00715 void CMpeg2DecFilter::CalcBrCont(BYTE* YTbl, double bright, double cont)
00716 {
00717 int Cont = (int)(cont * 512);
00718 int Bright = (int)bright;
00719
00720 for(int i = 0; i < 256; i++)
00721 {
00722 int y = ((Cont * (i - 16)) >> 9) + Bright + 16;
00723 YTbl[i] = min(max(y, 0), 255);
00724
00725 }
00726 }
00727
00728 void CMpeg2DecFilter::CalcHueSat(BYTE* UTbl, BYTE* VTbl, double hue, double sat)
00729 {
00730 int Sat = (int)(sat * 512);
00731 double Hue = (hue * 3.1415926) / 180.0;
00732 int Sin = (int)(sin(Hue) * 4096);
00733 int Cos = (int)(cos(Hue) * 4096);
00734
00735 for(int y = 0; y < 256; y++)
00736 {
00737 for(int x = 0; x < 256; x++)
00738 {
00739 int u = x - 128;
00740 int v = y - 128;
00741 int ux = (u * Cos + v * Sin) >> 12;
00742 v = (v * Cos - u * Sin) >> 12;
00743 u = ((ux * Sat) >> 9) + 128;
00744 v = ((v * Sat) >> 9) + 128;
00745 u = min(max(u, 16), 235);
00746 v = min(max(v, 16), 235);
00747 UTbl[(y << 8) | x] = u;
00748 VTbl[(y << 8) | x] = v;
00749 }
00750 }
00751 }
00752
00753 void CMpeg2DecFilter::ApplyBrContHueSat(BYTE* srcy, BYTE* srcu, BYTE* srcv, int w, int h, int pitch)
00754 {
00755 CAutoLock cAutoLock(&m_csProps);
00756
00757 double EPSILON = 1e-4;
00758
00759 if(fabs(m_bright-0.0) > EPSILON || fabs(m_cont-1.0) > EPSILON)
00760 {
00761 for(int size = pitch*h; size > 0; size--)
00762 {
00763 *srcy++ = m_YTbl[*srcy];
00764 }
00765 }
00766
00767 pitch /= 2;
00768 w /= 2;
00769 h /= 2;
00770
00771 if(fabs(m_hue-0.0) > EPSILON || fabs(m_sat-1.0) > EPSILON)
00772 {
00773 for(int size = pitch*h; size > 0; size--)
00774 {
00775 WORD uv = (*srcv<<8)|*srcu;
00776 *srcu++ = m_UTbl[uv];
00777 *srcv++ = m_VTbl[uv];
00778 }
00779 }
00780 }
00781
00782 STDMETHODIMP CMpeg2DecFilter::SetBrightness(double bright)
00783 {
00784 CAutoLock cAutoLock(&m_csProps);
00785 CalcBrCont(m_YTbl, m_bright = bright, m_cont);
00786 return S_OK;
00787 }
00788
00789 STDMETHODIMP CMpeg2DecFilter::SetContrast(double cont)
00790 {
00791 CAutoLock cAutoLock(&m_csProps);
00792 CalcBrCont(m_YTbl, m_bright, m_cont = cont);
00793 return S_OK;
00794 }
00795
00796 STDMETHODIMP CMpeg2DecFilter::SetHue(double hue)
00797 {
00798 CAutoLock cAutoLock(&m_csProps);
00799 CalcHueSat(m_UTbl, m_VTbl, m_hue = hue, m_sat);
00800 return S_OK;
00801 }
00802
00803 STDMETHODIMP CMpeg2DecFilter::SetSaturation(double sat)
00804 {
00805 CAutoLock cAutoLock(&m_csProps);
00806 CalcHueSat(m_UTbl, m_VTbl, m_hue, m_sat = sat);
00807 return S_OK;
00808 }
00809
00810 STDMETHODIMP_(double) CMpeg2DecFilter::GetBrightness()
00811 {
00812 CAutoLock cAutoLock(&m_csProps);
00813 return m_bright;
00814 }
00815
00816 STDMETHODIMP_(double) CMpeg2DecFilter::GetContrast()
00817 {
00818 CAutoLock cAutoLock(&m_csProps);
00819 return m_cont;
00820 }
00821
00822 STDMETHODIMP_(double) CMpeg2DecFilter::GetHue()
00823 {
00824 CAutoLock cAutoLock(&m_csProps);
00825 return m_hue;
00826 }
00827
00828 STDMETHODIMP_(double) CMpeg2DecFilter::GetSaturation()
00829 {
00830 CAutoLock cAutoLock(&m_csProps);
00831 return m_sat;
00832 }
00833
00834 STDMETHODIMP CMpeg2DecFilter::EnableForcedSubtitles(bool fEnable)
00835 {
00836 CAutoLock cAutoLock(&m_csProps);
00837 m_fForcedSubs = fEnable;
00838 return S_OK;
00839 }
00840
00841 STDMETHODIMP_(bool) CMpeg2DecFilter::IsForcedSubtitlesEnabled()
00842 {
00843 CAutoLock cAutoLock(&m_csProps);
00844 return m_fForcedSubs;
00845 }
00846
00847 STDMETHODIMP CMpeg2DecFilter::EnablePlanarYUV(bool fEnable)
00848 {
00849 CAutoLock cAutoLock(&m_csProps);
00850 m_fPlanarYUV = fEnable;
00851 return S_OK;
00852 }
00853
00854 STDMETHODIMP_(bool) CMpeg2DecFilter::IsPlanarYUVEnabled()
00855 {
00856 CAutoLock cAutoLock(&m_csProps);
00857 return m_fPlanarYUV;
00858 }
00859
00860
00861
00862
00863
00864 CMpeg2DecInputPin::CMpeg2DecInputPin(CTransformFilter* pFilter, HRESULT* phr, LPWSTR pName)
00865 : CDeCSSInputPin(NAME("CMpeg2DecInputPin"), pFilter, phr, pName)
00866 {
00867 m_CorrectTS = 0;
00868 m_ratechange.Rate = 10000;
00869 m_ratechange.StartTime = _I64_MAX;
00870 }
00871
00872
00873
00874 STDMETHODIMP CMpeg2DecInputPin::Set(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength)
00875 {
00876 if(PropSet != AM_KSPROPSETID_TSRateChange )
00877 return __super::Set(PropSet, Id, pInstanceData, InstanceLength, pPropertyData, DataLength);
00878
00879 if(PropSet == AM_KSPROPSETID_TSRateChange)
00880 switch(Id)
00881 {
00882 case AM_RATE_SimpleRateChange:
00883 {
00884 AM_SimpleRateChange* p = (AM_SimpleRateChange*)pPropertyData;
00885 if(!m_CorrectTS) return E_PROP_ID_UNSUPPORTED;
00886 CAutoLock cAutoLock(&m_csRateLock);
00887 m_ratechange = *p;
00888 DbgLog((LOG_TRACE, 0, _T("StartTime=%I64d, Rate=%d"), p->StartTime, p->Rate));
00889 }
00890 break;
00891 case AM_RATE_UseRateVersion:
00892 {
00893 WORD* p = (WORD*)pPropertyData;
00894 if(*p > 0x0101) return E_PROP_ID_UNSUPPORTED;
00895 }
00896 break;
00897 case AM_RATE_CorrectTS:
00898 {
00899 LONG* p = (LONG*)pPropertyData;
00900 m_CorrectTS = *p;
00901 }
00902 break;
00903 default:
00904 return E_PROP_ID_UNSUPPORTED;
00905 }
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919 return S_OK;
00920 }
00921
00922 STDMETHODIMP CMpeg2DecInputPin::Get(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength, ULONG* pBytesReturned)
00923 {
00924 if(PropSet != AM_KSPROPSETID_TSRateChange )
00925 return __super::Get(PropSet, Id, pInstanceData, InstanceLength, pPropertyData, DataLength, pBytesReturned);
00926
00927 if(PropSet == AM_KSPROPSETID_TSRateChange)
00928 switch(Id)
00929 {
00930 case AM_RATE_SimpleRateChange:
00931 {
00932 AM_SimpleRateChange* p = (AM_SimpleRateChange*)pPropertyData;
00933 return E_PROP_ID_UNSUPPORTED;
00934 }
00935 break;
00936 case AM_RATE_MaxFullDataRate:
00937 {
00938 AM_MaxFullDataRate* p = (AM_MaxFullDataRate*)pPropertyData;
00939 *p = 8*10000;
00940 *pBytesReturned = sizeof(AM_MaxFullDataRate);
00941 }
00942 break;
00943 case AM_RATE_QueryFullFrameRate:
00944 {
00945 AM_QueryRate* p = (AM_QueryRate*)pPropertyData;
00946 p->lMaxForwardFullFrame = 8*10000;
00947 p->lMaxReverseFullFrame = 8*10000;
00948 *pBytesReturned = sizeof(AM_QueryRate);
00949 }
00950 break;
00951 case AM_RATE_QueryLastRateSegPTS:
00952 {
00953 REFERENCE_TIME* p = (REFERENCE_TIME*)pPropertyData;
00954 return E_PROP_ID_UNSUPPORTED;
00955 }
00956 break;
00957 default:
00958 return E_PROP_ID_UNSUPPORTED;
00959 }
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988 return S_OK;
00989 }
00990
00991 STDMETHODIMP CMpeg2DecInputPin::QuerySupported(REFGUID PropSet, ULONG Id, ULONG* pTypeSupport)
00992 {
00993 if(PropSet != AM_KSPROPSETID_TSRateChange )
00994 return __super::QuerySupported(PropSet, Id, pTypeSupport);
00995
00996 if(PropSet == AM_KSPROPSETID_TSRateChange)
00997 switch(Id)
00998 {
00999 case AM_RATE_SimpleRateChange:
01000 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
01001 break;
01002 case AM_RATE_MaxFullDataRate:
01003 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
01004 break;
01005 case AM_RATE_UseRateVersion:
01006 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
01007 break;
01008 case AM_RATE_QueryFullFrameRate:
01009 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
01010 break;
01011 case AM_RATE_QueryLastRateSegPTS:
01012 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
01013 break;
01014 case AM_RATE_CorrectTS:
01015 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
01016 break;
01017 default:
01018 return E_PROP_ID_UNSUPPORTED;
01019 }
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 return S_OK;
01044 }
01045
01046
01047
01048
01049
01050 #define PTS2RT(pts) (10000i64*pts/90)
01051
01052 CSubpicInputPin::CSubpicInputPin(CTransformFilter* pFilter, HRESULT* phr)
01053 : CMpeg2DecInputPin(pFilter, phr, L"SubPicture")
01054 , m_spon(TRUE)
01055 , m_fsppal(false)
01056 {
01057 m_sppal[0].Y = 0x00;
01058 m_sppal[0].U = m_sppal[0].V = 0x80;
01059 m_sppal[1].Y = 0xe0;
01060 m_sppal[1].U = m_sppal[1].V = 0x80;
01061 m_sppal[2].Y = 0x80;
01062 m_sppal[2].U = m_sppal[2].V = 0x80;
01063 m_sppal[3].Y = 0x20;
01064 m_sppal[3].U = m_sppal[3].V = 0x80;
01065 }
01066
01067 HRESULT CSubpicInputPin::CheckMediaType(const CMediaType* mtIn)
01068 {
01069 return (mtIn->majortype == MEDIATYPE_DVD_ENCRYPTED_PACK
01070 || mtIn->majortype == MEDIATYPE_MPEG2_PACK
01071 || mtIn->majortype == MEDIATYPE_MPEG2_PES
01072 || mtIn->majortype == MEDIATYPE_Video)
01073 && (mtIn->subtype == MEDIASUBTYPE_DVD_SUBPICTURE
01074 || mtIn->subtype == MEDIASUBTYPE_CVD_SUBPICTURE
01075 || mtIn->subtype == MEDIASUBTYPE_SVCD_SUBPICTURE)
01076 ? S_OK
01077 : VFW_E_TYPE_NOT_ACCEPTED;
01078 }
01079
01080 HRESULT CSubpicInputPin::SetMediaType(const CMediaType* mtIn)
01081 {
01082 return CBasePin::SetMediaType(mtIn);
01083 }
01084
01085 bool CSubpicInputPin::HasAnythingToRender(REFERENCE_TIME rt)
01086 {
01087 if(!IsConnected()) return(false);
01088
01089 CAutoLock cAutoLock(&m_csReceive);
01090
01091 POSITION pos = m_sps.GetHeadPosition();
01092 while(pos)
01093 {
01094 spu* sp = m_sps.GetNext(pos);
01095 if(sp->m_rtStart <= rt && rt < sp->m_rtStop && ( sp->m_fForced || m_spon))
01096 return(true);
01097 }
01098
01099 return(false);
01100 }
01101
01102 void CSubpicInputPin::RenderSubpics(REFERENCE_TIME rt, BYTE** yuv, int w, int h)
01103 {
01104 CAutoLock cAutoLock(&m_csReceive);
01105
01106 POSITION pos;
01107
01108
01109 pos = m_sps.GetHeadPosition();
01110 while(pos)
01111 {
01112 POSITION cur = pos;
01113 spu* sp = m_sps.GetNext(pos);
01114 if(sp->m_rtStop <= rt) m_sps.RemoveAt(cur);
01115 }
01116
01117 pos = m_sps.GetHeadPosition();
01118 while(pos)
01119 {
01120 spu* sp = m_sps.GetNext(pos);
01121 if(sp->m_rtStart <= rt && rt < sp->m_rtStop
01122 && (m_spon || sp->m_fForced && (((CMpeg2DecFilter*)m_pFilter)->IsForcedSubtitlesEnabled() || sp->m_psphli)))
01123 sp->Render(yuv, w, h, m_sppal, m_fsppal);
01124 }
01125 }
01126
01127 HRESULT CSubpicInputPin::Transform(IMediaSample* pSample)
01128 {
01129 HRESULT hr;
01130
01131 AM_MEDIA_TYPE* pmt;
01132 if(SUCCEEDED(pSample->GetMediaType(&pmt)) && pmt)
01133 {
01134 CMediaType mt(*pmt);
01135 SetMediaType(&mt);
01136 DeleteMediaType(pmt);
01137 }
01138
01139 BYTE* pDataIn = NULL;
01140 if(FAILED(hr = pSample->GetPointer(&pDataIn))) return hr;
01141
01142 long len = pSample->GetActualDataLength();
01143
01144 StripPacket(pDataIn, len);
01145
01146 if(len <= 0) return S_FALSE;
01147
01148 if(m_mt.subtype == MEDIASUBTYPE_SVCD_SUBPICTURE)
01149 {
01150 pDataIn += 4;
01151 len -= 4;
01152 }
01153
01154 if(len <= 0) return S_FALSE;
01155
01156 CAutoLock cAutoLock(&m_csReceive);
01157
01158 REFERENCE_TIME rtStart = 0, rtStop = 0;
01159 hr = pSample->GetTime(&rtStart, &rtStop);
01160
01161 bool fRefresh = false;
01162
01163 if(FAILED(hr))
01164 {
01165 if(!m_sps.IsEmpty())
01166 {
01167 spu* sp = m_sps.GetTail();
01168 sp->m_pData.SetSize(sp->m_pData.GetSize() + len);
01169 memcpy(sp->m_pData.GetData() + sp->m_pData.GetSize() - len, pDataIn, len);
01170 }
01171 }
01172 else
01173 {
01174 POSITION pos = m_sps.GetTailPosition();
01175 while(pos)
01176 {
01177 POSITION cur = pos;
01178 spu* sp = m_sps.GetPrev(pos);
01179 if(sp->m_rtStop == _I64_MAX)
01180 {
01181 sp->m_rtStop = rtStart;
01182 break;
01183 }
01184 }
01185
01186 CAutoPtr<spu> p;
01187
01188 if(m_mt.subtype == MEDIASUBTYPE_DVD_SUBPICTURE) p.Attach(new dvdspu());
01189 else if(m_mt.subtype == MEDIASUBTYPE_CVD_SUBPICTURE) p.Attach(new cvdspu());
01190 else if(m_mt.subtype == MEDIASUBTYPE_SVCD_SUBPICTURE) p.Attach(new svcdspu());
01191 else return E_FAIL;
01192
01193 p->m_rtStart = rtStart;
01194 p->m_rtStop = _I64_MAX;
01195
01196 p->m_pData.SetSize(len);
01197 memcpy(p->m_pData.GetData(), pDataIn, len);
01198
01199 if(m_sphli && p->m_rtStart == PTS2RT(m_sphli->StartPTM))
01200 {
01201 p->m_psphli = m_sphli;
01202 fRefresh = true;
01203 }
01204
01205 m_sps.AddTail(p);
01206 }
01207
01208 if(!m_sps.IsEmpty())
01209 {
01210 m_sps.GetTail()->Parse();
01211 }
01212
01213 if(fRefresh)
01214 {
01215
01216 }
01217
01218 return S_FALSE;
01219 }
01220
01221 STDMETHODIMP CSubpicInputPin::EndFlush()
01222 {
01223 CAutoLock cAutoLock(&m_csReceive);
01224 m_sps.RemoveAll();
01225 return S_OK;
01226 }
01227
01228
01229
01230 STDMETHODIMP CSubpicInputPin::Set(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength)
01231 {
01232 if(PropSet != AM_KSPROPSETID_DvdSubPic)
01233 return __super::Set(PropSet, Id, pInstanceData, InstanceLength, pPropertyData, DataLength);
01234
01235 bool fRefresh = false;
01236
01237 switch(Id)
01238 {
01239 case AM_PROPERTY_DVDSUBPIC_PALETTE:
01240 {
01241 CAutoLock cAutoLock(&m_csReceive);
01242 AM_PROPERTY_SPPAL* pSPPAL = (AM_PROPERTY_SPPAL*)pPropertyData;
01243 memcpy(m_sppal, pSPPAL->sppal, sizeof(AM_PROPERTY_SPPAL));
01244 m_fsppal = true;
01245
01246 DbgLog((LOG_TRACE, 0, _T("new palette")));
01247 }
01248 break;
01249 case AM_PROPERTY_DVDSUBPIC_HLI:
01250 {
01251 CAutoLock cAutoLock(&m_csReceive);
01252
01253 AM_PROPERTY_SPHLI* pSPHLI = (AM_PROPERTY_SPHLI*)pPropertyData;
01254
01255 m_sphli.Free();
01256
01257 if(pSPHLI->HLISS)
01258 {
01259 POSITION pos = m_sps.GetHeadPosition();
01260 while(pos)
01261 {
01262 spu* sp = m_sps.GetNext(pos);
01263 if(sp->m_rtStart <= PTS2RT(pSPHLI->StartPTM) && PTS2RT(pSPHLI->StartPTM) < sp->m_rtStop)
01264 {
01265 fRefresh = true;
01266 sp->m_psphli.Free();
01267 sp->m_psphli.Attach(new AM_PROPERTY_SPHLI());
01268 memcpy((AM_PROPERTY_SPHLI*)sp->m_psphli, pSPHLI, sizeof(AM_PROPERTY_SPHLI));
01269 }
01270 }
01271
01272 if(!fRefresh)
01273 {
01274 m_sphli.Attach(new AM_PROPERTY_SPHLI());
01275 memcpy((AM_PROPERTY_SPHLI*)m_sphli, pSPHLI, sizeof(AM_PROPERTY_SPHLI));
01276 }
01277 }
01278 else
01279 {
01280 POSITION pos = m_sps.GetHeadPosition();
01281 while(pos)
01282 {
01283 spu* sp = m_sps.GetNext(pos);
01284 fRefresh |= !!sp->m_psphli;
01285 sp->m_psphli.Free();
01286 }
01287 }
01288
01289 if(pSPHLI->HLISS)
01290 DbgLog((LOG_TRACE, 0, _T("hli: %I64d - %I64d, (%d,%d) - (%d,%d)"),
01291 PTS2RT(pSPHLI->StartPTM)/10000, PTS2RT(pSPHLI->EndPTM)/10000,
01292 pSPHLI->StartX, pSPHLI->StartY, pSPHLI->StopX, pSPHLI->StopY));
01293 }
01294 break;
01295 case AM_PROPERTY_DVDSUBPIC_COMPOSIT_ON:
01296 {
01297 CAutoLock cAutoLock(&m_csReceive);
01298 AM_PROPERTY_COMPOSIT_ON* pCompositOn = (AM_PROPERTY_COMPOSIT_ON*)pPropertyData;
01299 m_spon = *pCompositOn;
01300 }
01301 break;
01302 default:
01303 return E_PROP_ID_UNSUPPORTED;
01304 }
01305
01306 if(fRefresh)
01307 {
01308 ((CMpeg2DecFilter*)m_pFilter)->Deliver(true);
01309 }
01310
01311 return S_OK;
01312 }
01313
01314 STDMETHODIMP CSubpicInputPin::QuerySupported(REFGUID PropSet, ULONG Id, ULONG* pTypeSupport)
01315 {
01316 if(PropSet != AM_KSPROPSETID_DvdSubPic)
01317 return __super::QuerySupported(PropSet, Id, pTypeSupport);
01318
01319 switch(Id)
01320 {
01321 case AM_PROPERTY_DVDSUBPIC_PALETTE:
01322 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
01323 break;
01324 case AM_PROPERTY_DVDSUBPIC_HLI:
01325 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
01326 break;
01327 case AM_PROPERTY_DVDSUBPIC_COMPOSIT_ON:
01328 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
01329 break;
01330 default:
01331 return E_PROP_ID_UNSUPPORTED;
01332 }
01333
01334 return S_OK;
01335 }
01336
01337
01338
01339 static __inline BYTE GetNibble(BYTE* p, DWORD* offset, int& nField, int& fAligned)
01340 {
01341 BYTE ret = (p[offset[nField]] >> (fAligned << 2)) & 0x0f;
01342 offset[nField] += 1-fAligned;
01343 fAligned = !fAligned;
01344 return ret;
01345 }
01346
01347 static __inline BYTE GetHalfNibble(BYTE* p, DWORD* offset, int& nField, int& n)
01348 {
01349 BYTE ret = (p[offset[nField]] >> (n << 1)) & 0x03;
01350 if(!n) offset[nField]++;
01351 n = (n-1+4)&3;
01352 return ret;
01353 }
01354
01355 static __inline void DrawPixel(BYTE** yuv, CPoint pt, int pitch, AM_DVD_YUV& c)
01356 {
01357 if(c.Reserved == 0) return;
01358
01359 BYTE* p = &yuv[0][pt.y*pitch + pt.x];
01360
01361 *p -= (*p - c.Y) * c.Reserved >> 4;
01362
01363 if(pt.y&1) return;
01364
01365 pt.x = (pt.x + 1) / 2;
01366 pt.y = (pt.y ) / 2;
01367 pitch /= 2;
01368
01369
01370
01371 p = &yuv[1][pt.y*pitch + pt.x];
01372
01373 *p -= (*p - c.V) * c.Reserved >> 4;
01374
01375 p = &yuv[2][pt.y*pitch + pt.x];
01376
01377 *p -= (*p - c.U) * c.Reserved >> 4;
01378
01379
01380
01381
01382 }
01383
01384 static __inline void DrawPixels(BYTE** yuv, int pitch, CPoint pt, int len, AM_DVD_YUV& c, CRect& rc)
01385 {
01386 if(pt.y < rc.top || pt.y >= rc.bottom) return;
01387 if(pt.x < rc.left) {len -= rc.left - pt.x; pt.x = rc.left;}
01388 if(pt.x + len > rc.right) len = rc.right - pt.x;
01389 if(len <= 0 || pt.x >= rc.right) return;
01390
01391 if(c.Reserved == 0)
01392 {
01393 if(rc.IsRectEmpty())
01394 return;
01395
01396 if(pt.y < rc.top || pt.y >= rc.bottom
01397 || pt.x+len < rc.left || pt.x >= rc.right)
01398 return;
01399 }
01400
01401 while(len-- > 0)
01402 {
01403 DrawPixel(yuv, pt, pitch, c);
01404 pt.x++;
01405 }
01406 }
01407
01408
01409
01410 bool CSubpicInputPin::dvdspu::Parse()
01411 {
01412 BYTE* p = m_pData.GetData();
01413
01414 WORD packetsize = (p[0]<<8)|p[1];
01415 WORD datasize = (p[2]<<8)|p[3];
01416
01417 if(packetsize > m_pData.GetSize() || datasize > packetsize)
01418 return(false);
01419
01420 int i, next = datasize;
01421
01422 #define GetWORD (p[i]<<8)|p[i+1]; i += 2
01423
01424 do
01425 {
01426 i = next;
01427
01428 int pts = GetWORD;
01429 next = GetWORD;
01430
01431 if(next > packetsize || next < datasize)
01432 return(false);
01433
01434 for(bool fBreak = false; !fBreak; )
01435 {
01436 int len = 0;
01437
01438 switch(p[i])
01439 {
01440 case 0x00: len = 0; break;
01441 case 0x01: len = 0; break;
01442 case 0x02: len = 0; break;
01443 case 0x03: len = 2; break;
01444 case 0x04: len = 2; break;
01445 case 0x05: len = 6; break;
01446 case 0x06: len = 4; break;
01447 default: len = 0; break;
01448 }
01449
01450 if(i+len >= packetsize)
01451 {
01452 TRACE(_T("Warning: Wrong subpicture parameter block ending\n"));
01453 break;
01454 }
01455
01456 switch(p[i++])
01457 {
01458 case 0x00:
01459 m_fForced = true;
01460 break;
01461 case 0x01:
01462 m_fForced = false;
01463 break;
01464 case 0x02:
01465 m_rtStop = m_rtStart + 1024*PTS2RT(pts);
01466 break;
01467 case 0x03:
01468 m_sphli.ColCon.emph2col = p[i]>>4;
01469 m_sphli.ColCon.emph1col = p[i]&0xf;
01470 m_sphli.ColCon.patcol = p[i+1]>>4;
01471 m_sphli.ColCon.backcol = p[i+1]&0xf;
01472 i += 2;
01473 break;
01474 case 0x04:
01475 m_sphli.ColCon.emph2con = p[i]>>4;
01476 m_sphli.ColCon.emph1con = p[i]&0xf;
01477 m_sphli.ColCon.patcon = p[i+1]>>4;
01478 m_sphli.ColCon.backcon = p[i+1]&0xf;
01479 i += 2;
01480 break;
01481 case 0x05:
01482 m_sphli.StartX = (p[i]<<4) + (p[i+1]>>4);
01483 m_sphli.StopX = ((p[i+1]&0x0f)<<8) + p[i+2]+1;
01484 m_sphli.StartY = (p[i+3]<<4) + (p[i+4]>>4);
01485 m_sphli.StopY = ((p[i+4]&0x0f)<<8) + p[i+5]+1;
01486 i += 6;
01487 break;
01488 case 0x06:
01489 m_offset[0] = GetWORD;
01490 m_offset[1] = GetWORD;
01491 break;
01492 case 0xff:
01493 fBreak = true;
01494 continue;
01495 default:
01496 fBreak = true;
01497 break;
01498 }
01499 }
01500 }
01501 while(i <= next && i < packetsize);
01502
01503 return(true);
01504 }
01505
01506 void CSubpicInputPin::dvdspu::Render(BYTE** yuv, int w, int h, AM_DVD_YUV* sppal, bool fsppal)
01507 {
01508 BYTE* p = m_pData.GetData();
01509 DWORD offset[2] = {m_offset[0], m_offset[1]};
01510
01511 AM_PROPERTY_SPHLI sphli = m_sphli;
01512 CPoint pt(sphli.StartX, sphli.StartY);
01513 CRect rc(pt, CPoint(sphli.StopX, sphli.StopY));
01514
01515 CRect rcclip(0, 0, w, h);
01516 rcclip &= rc;
01517
01518 if(m_psphli)
01519 {
01520 rcclip &= CRect(m_psphli->StartX, m_psphli->StartY, m_psphli->StopX, m_psphli->StopY);
01521 sphli = *m_psphli;
01522 }
01523
01524 AM_DVD_YUV pal[4];
01525 pal[0] = sppal[fsppal ? sphli.ColCon.backcol : 0];
01526 pal[0].Reserved = sphli.ColCon.backcon;
01527 pal[1] = sppal[fsppal ? sphli.ColCon.patcol : 1];
01528 pal[1].Reserved = sphli.ColCon.patcon;
01529 pal[2] = sppal[fsppal ? sphli.ColCon.emph1col : 2];
01530 pal[2].Reserved = sphli.ColCon.emph1con;
01531 pal[3] = sppal[fsppal ? sphli.ColCon.emph2col : 3];
01532 pal[3].Reserved = sphli.ColCon.emph2con;
01533
01534 int nField = 0;
01535 int fAligned = 1;
01536
01537 DWORD end[2] = {offset[1], (p[2]<<8)|p[3]};
01538
01539 while((nField == 0 && offset[0] < end[0]) || (nField == 1 && offset[1] < end[1]))
01540 {
01541 DWORD code;
01542
01543 if((code = GetNibble(p, offset, nField, fAligned)) >= 0x4
01544 || (code = (code << 4) | GetNibble(p, offset, nField, fAligned)) >= 0x10
01545 || (code = (code << 4) | GetNibble(p, offset, nField, fAligned)) >= 0x40
01546 || (code = (code << 4) | GetNibble(p, offset, nField, fAligned)) >= 0x100)
01547 {
01548 DrawPixels(yuv, w, pt, code >> 2, pal[code&3], rcclip);
01549 if((pt.x += code >> 2) < rc.right) continue;
01550 }
01551
01552 DrawPixels(yuv, w, pt, rc.right - pt.x, pal[code&3], rcclip);
01553
01554 if(!fAligned) GetNibble(p, offset, nField, fAligned);
01555
01556 pt.x = rc.left;
01557 pt.y++;
01558 nField = 1 - nField;
01559 }
01560 }
01561
01562
01563
01564 bool CSubpicInputPin::cvdspu::Parse()
01565 {
01566 BYTE* p = m_pData.GetData();
01567
01568 WORD packetsize = (p[0]<<8)|p[1];
01569 WORD datasize = (p[2]<<8)|p[3];
01570
01571 if(packetsize > m_pData.GetSize() || datasize > packetsize)
01572 return(false);
01573
01574 p = m_pData.GetData() + datasize;
01575
01576 for(int i = datasize, j = packetsize-4; i <= j; i+=4, p+=4)
01577 {
01578 switch(p[0])
01579 {
01580 case 0x0c:
01581 break;
01582 case 0x04:
01583 m_rtStop = m_rtStart + 10000i64*((p[1]<<16)|(p[2]<<8)|p[3])/90;
01584 break;
01585 case 0x17:
01586 m_sphli.StartX = ((p[1]&0x0f)<<6) + (p[2]>>2);
01587 m_sphli.StartY = ((p[2]&0x03)<<8) + p[3];
01588 break;
01589 case 0x1f:
01590 m_sphli.StopX = ((p[1]&0x0f)<<6) + (p[2]>>2);
01591 m_sphli.StopY = ((p[2]&0x03)<<8) + p[3];
01592 break;
01593 case 0x24: case 0x25: case 0x26: case 0x27:
01594 m_sppal[0][p[0]-0x24].Y = p[1];
01595 m_sppal[0][p[0]-0x24].U = p[2];
01596 m_sppal[0][p[0]-0x24].V = p[3];
01597 break;
01598 case 0x2c: case 0x2d: case 0x2e: case 0x2f:
01599 m_sppal[1][p[0]-0x2c].Y = p[1];
01600 m_sppal[1][p[0]-0x2c].U = p[2];
01601 m_sppal[1][p[0]-0x2c].V = p[3];
01602 break;
01603 case 0x37:
01604 m_sppal[0][3].Reserved = p[2]>>4;
01605 m_sppal[0][2].Reserved = p[2]&0xf;
01606 m_sppal[0][1].Reserved = p[3]>>4;
01607 m_sppal[0][0].Reserved = p[3]&0xf;
01608 break;
01609 case 0x3f:
01610 m_sppal[1][3].Reserved = p[2]>>4;
01611 m_sppal[1][2].Reserved = p[2]&0xf;
01612 m_sppal[1][1].Reserved = p[3]>>4;
01613 m_sppal[1][0].Reserved = p[3]&0xf;
01614 break;
01615 case 0x47:
01616 m_offset[0] = (p[2]<<8)|p[3];
01617 break;
01618 case 0x4f:
01619 m_offset[1] = (p[2]<<8)|p[3];
01620 break;
01621 default:
01622 break;
01623 }
01624 }
01625
01626 return(true);
01627 }
01628
01629 void CSubpicInputPin::cvdspu::Render(BYTE** yuv, int w, int h, AM_DVD_YUV* sppal, bool fsppal)
01630 {
01631 BYTE* p = m_pData.GetData();
01632 DWORD offset[2] = {m_offset[0], m_offset[1]};
01633
01634 CRect rcclip(0, 0, w, h);
01635
01636
01637
01638
01639
01640
01641 CSize size(m_sphli.StopX - m_sphli.StartX, m_sphli.StopY - m_sphli.StartY);
01642 CPoint pt((rcclip.Width() - size.cx) / 2, (rcclip.Height()*3 - size.cy*1) / 4);
01643 CRect rc(pt, size);
01644
01645 int nField = 0;
01646 int fAligned = 1;
01647
01648 DWORD end[2] = {offset[1], (p[2]<<8)|p[3]};
01649
01650 while((nField == 0 && offset[0] < end[0]) || (nField == 1 && offset[1] < end[1]))
01651 {
01652 BYTE code;
01653
01654 if((code = GetNibble(p, offset, nField, fAligned)) >= 0x4)
01655 {
01656 DrawPixels(yuv, w, pt, code >> 2, m_sppal[0][code&3], rcclip);
01657 pt.x += code >> 2;
01658 continue;
01659 }
01660
01661 code = GetNibble(p, offset, nField, fAligned);
01662 DrawPixels(yuv, w, pt, rc.right - pt.x, m_sppal[0][code&3], rcclip);
01663
01664 if(!fAligned) GetNibble(p, offset, nField, fAligned);
01665
01666 pt.x = rc.left;
01667 pt.y++;
01668 nField = 1 - nField;
01669 }
01670 }
01671
01672
01673
01674 bool CSubpicInputPin::svcdspu::Parse()
01675 {
01676 BYTE* p = m_pData.GetData();
01677 BYTE* p0 = p;
01678
01679 if(m_pData.GetSize() < 2)
01680 return(false);
01681
01682 WORD packetsize = (p[0]<<8)|p[1]; p += 2;
01683
01684 if(packetsize > m_pData.GetSize())
01685 return(false);
01686
01687 bool duration = !!(*p++&0x04);
01688
01689 *p++;
01690
01691 if(duration)
01692 {
01693 m_rtStop = m_rtStart + 10000i64*((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3])/90;
01694 p += 4;
01695 }
01696
01697 m_sphli.StartX = m_sphli.StopX = (p[0]<<8)|p[1]; p += 2;
01698 m_sphli.StartY = m_sphli.StopY = (p[0]<<8)|p[1]; p += 2;
01699 m_sphli.StopX += (p[0]<<8)|p[1]; p += 2;
01700 m_sphli.StopY += (p[0]<<8)|p[1]; p += 2;
01701
01702 for(int i = 0; i < 4; i++)
01703 {
01704 m_sppal[i].Y = *p++;
01705 m_sppal[i].U = *p++;
01706 m_sppal[i].V = *p++;
01707 m_sppal[i].Reserved = *p++ >> 4;
01708 }
01709
01710 if(*p++&0xc0)
01711 p += 4;
01712
01713 m_offset[1] = (p[0]<<8)|p[1]; p += 2;
01714
01715 m_offset[0] = p - p0;
01716 m_offset[1] += m_offset[0];
01717
01718 return(true);
01719 }
01720
01721 void CSubpicInputPin::svcdspu::Render(BYTE** yuv, int w, int h, AM_DVD_YUV* sppal, bool fsppal)
01722 {
01723 BYTE* p = m_pData.GetData();
01724 DWORD offset[2] = {m_offset[0], m_offset[1]};
01725
01726 CRect rcclip(0, 0, w, h);
01727
01728
01729
01730
01731
01732
01733 CSize size(m_sphli.StopX - m_sphli.StartX, m_sphli.StopY - m_sphli.StartY);
01734 CPoint pt((rcclip.Width() - size.cx) / 2, (rcclip.Height()*3 - size.cy*1) / 4);
01735 CRect rc(pt, size);
01736
01737 int nField = 0;
01738 int n = 3;
01739
01740 DWORD end[2] = {offset[1], (p[2]<<8)|p[3]};
01741
01742 while((nField == 0 && offset[0] < end[0]) || (nField == 1 && offset[1] < end[1]))
01743 {
01744 BYTE code = GetHalfNibble(p, offset, nField, n);
01745 BYTE repeat = 1 + (code == 0 ? GetHalfNibble(p, offset, nField, n) : 0);
01746
01747 DrawPixels(yuv, w, pt, repeat, m_sppal[code&3], rcclip);
01748 if((pt.x += repeat) < rc.right) continue;
01749
01750 while(n != 3)
01751 GetHalfNibble(p, offset, nField, n);
01752
01753 pt.x = rc.left;
01754 pt.y++;
01755 nField = 1 - nField;
01756 }
01757 }
01758
01759
01760
01761
01762
01763 CClosedCaptionOutputPin::CClosedCaptionOutputPin(CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
01764 : CBaseOutputPin(NAME("CClosedCaptionOutputPin"), pFilter, pLock, phr, L"~CC")
01765 {
01766 }
01767
01768 HRESULT CClosedCaptionOutputPin::CheckMediaType(const CMediaType* mtOut)
01769 {
01770 return mtOut->majortype == MEDIATYPE_AUXLine21Data && mtOut->subtype == MEDIASUBTYPE_Line21_GOPPacket
01771 ? S_OK
01772 : VFW_E_TYPE_NOT_ACCEPTED;
01773 }
01774
01775 HRESULT CClosedCaptionOutputPin::GetMediaType(int iPosition, CMediaType* pmt)
01776 {
01777 if(iPosition < 0) return E_INVALIDARG;
01778 if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
01779
01780 pmt->InitMediaType();
01781 pmt->majortype = MEDIATYPE_AUXLine21Data;
01782 pmt->subtype = MEDIASUBTYPE_Line21_GOPPacket;
01783 pmt->formattype = FORMAT_None;
01784
01785 return S_OK;
01786 }
01787
01788 HRESULT CClosedCaptionOutputPin::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
01789 {
01790 pProperties->cBuffers = 1;
01791 pProperties->cbBuffer = 2048;
01792 pProperties->cbAlign = 1;
01793 pProperties->cbPrefix = 0;
01794
01795 HRESULT hr;
01796 ALLOCATOR_PROPERTIES Actual;
01797 if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
01798 return hr;
01799
01800 return pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
01801 ? E_FAIL
01802 : NOERROR;
01803 }