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 "ISubPic.h"
00024 #include "..\DSUtil\DSUtil.h"
00025
00026
00027
00028
00029
00030 ISubPicImpl::ISubPicImpl()
00031 : CUnknown(NAME("ISubPicImpl"), NULL)
00032 , m_rtStart(0), m_rtStop(0)
00033 , m_rcDirty(0, 0, 0, 0), m_maxsize(0, 0), m_size(0, 0), m_vidrect(0, 0, 0, 0)
00034 {
00035 }
00036
00037 STDMETHODIMP ISubPicImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00038 {
00039 return
00040 QI(ISubPic)
00041 __super::NonDelegatingQueryInterface(riid, ppv);
00042 }
00043
00044
00045
00046 STDMETHODIMP_(REFERENCE_TIME) ISubPicImpl::GetStart()
00047 {
00048 return(m_rtStart);
00049 }
00050
00051 STDMETHODIMP_(REFERENCE_TIME) ISubPicImpl::GetStop()
00052 {
00053 return(m_rtStop);
00054 }
00055
00056 STDMETHODIMP_(void) ISubPicImpl::SetStart(REFERENCE_TIME rtStart)
00057 {
00058 m_rtStart = rtStart;
00059 }
00060
00061 STDMETHODIMP_(void) ISubPicImpl::SetStop(REFERENCE_TIME rtStop)
00062 {
00063 m_rtStop = rtStop;
00064 }
00065
00066 STDMETHODIMP ISubPicImpl::CopyTo(ISubPic* pSubPic)
00067 {
00068 if(!pSubPic)
00069 return E_POINTER;
00070
00071 pSubPic->SetStart(m_rtStart);
00072 pSubPic->SetStop(m_rtStop);
00073 pSubPic->SetDirtyRect(m_rcDirty);
00074 pSubPic->SetSize(m_size, m_vidrect);
00075
00076 return S_OK;
00077 }
00078
00079 STDMETHODIMP ISubPicImpl::GetDirtyRect(RECT* pDirtyRect)
00080 {
00081 return pDirtyRect ? *pDirtyRect = m_rcDirty, S_OK : E_POINTER;
00082 }
00083
00084 STDMETHODIMP ISubPicImpl::SetDirtyRect(RECT* pDirtyRect)
00085 {
00086 return pDirtyRect ? m_rcDirty = *pDirtyRect, S_OK : E_POINTER;
00087 }
00088
00089 STDMETHODIMP ISubPicImpl::GetMaxSize(SIZE* pMaxSize)
00090 {
00091 return pMaxSize ? *pMaxSize = m_maxsize, S_OK : E_POINTER;
00092 }
00093
00094 STDMETHODIMP ISubPicImpl::SetSize(SIZE size, RECT vidrect)
00095 {
00096 m_size = size;
00097 m_vidrect = vidrect;
00098
00099 if(m_size.cx > m_maxsize.cx)
00100 {
00101 m_size.cy = MulDiv(m_size.cy, m_maxsize.cx, m_size.cx);
00102 m_size.cx = m_maxsize.cx;
00103 }
00104
00105 if(m_size.cy > m_maxsize.cy)
00106 {
00107 m_size.cx = MulDiv(m_size.cx, m_maxsize.cy, m_size.cy);
00108 m_size.cy = m_maxsize.cy;
00109 }
00110
00111 if(m_size.cx != size.cx || m_size.cy != size.cy)
00112 {
00113 m_vidrect.top = MulDiv(m_vidrect.top, m_size.cx, size.cx);
00114 m_vidrect.bottom = MulDiv(m_vidrect.bottom, m_size.cx, size.cx);
00115 m_vidrect.left = MulDiv(m_vidrect.left, m_size.cy, size.cy);
00116 m_vidrect.right = MulDiv(m_vidrect.right, m_size.cy, size.cy);
00117 }
00118
00119 return S_OK;
00120 }
00121
00122
00123
00124
00125
00126 ISubPicAllocatorImpl::ISubPicAllocatorImpl(SIZE cursize, bool fDynamicWriteOnly, bool fPow2Textures)
00127 : CUnknown(NAME("ISubPicAllocatorImpl"), NULL)
00128 , m_cursize(cursize)
00129 , m_fDynamicWriteOnly(fDynamicWriteOnly)
00130 , m_fPow2Textures(fPow2Textures)
00131 {
00132 m_curvidrect = CRect(CPoint(0,0), m_cursize);
00133 }
00134
00135 STDMETHODIMP ISubPicAllocatorImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00136 {
00137 return
00138 QI(ISubPicAllocator)
00139 __super::NonDelegatingQueryInterface(riid, ppv);
00140 }
00141
00142
00143
00144 STDMETHODIMP ISubPicAllocatorImpl::SetCurSize(SIZE cursize)
00145 {
00146 m_cursize = cursize;
00147 return S_OK;
00148 }
00149
00150 STDMETHODIMP ISubPicAllocatorImpl::SetCurVidRect(RECT curvidrect)
00151 {
00152 m_curvidrect = curvidrect;
00153 return S_OK;
00154 }
00155
00156 STDMETHODIMP ISubPicAllocatorImpl::GetStatic(ISubPic** ppSubPic)
00157 {
00158 if(!ppSubPic)
00159 return E_POINTER;
00160
00161 if(!m_pStatic)
00162 {
00163 if(!Alloc(true, &m_pStatic) || !m_pStatic)
00164 return E_OUTOFMEMORY;
00165 }
00166
00167 m_pStatic->SetSize(m_cursize, m_curvidrect);
00168
00169 (*ppSubPic = m_pStatic)->AddRef();
00170
00171 return S_OK;
00172 }
00173
00174 STDMETHODIMP ISubPicAllocatorImpl::AllocDynamic(ISubPic** ppSubPic)
00175 {
00176 if(!ppSubPic)
00177 return E_POINTER;
00178
00179 if(!Alloc(false, ppSubPic) || !*ppSubPic)
00180 return E_OUTOFMEMORY;
00181
00182 (*ppSubPic)->SetSize(m_cursize, m_curvidrect);
00183
00184 return S_OK;
00185 }
00186
00187 STDMETHODIMP_(bool) ISubPicAllocatorImpl::IsDynamicWriteOnly()
00188 {
00189 return(m_fDynamicWriteOnly);
00190 }
00191
00192 STDMETHODIMP ISubPicAllocatorImpl::ChangeDevice(IUnknown* pDev)
00193 {
00194 m_pStatic = NULL;
00195 return S_OK;
00196 }
00197
00198
00199
00200
00201
00202 ISubPicProviderImpl::ISubPicProviderImpl(CCritSec* pLock)
00203 : CUnknown(NAME("ISubPicProviderImpl"), NULL)
00204 , m_pLock(pLock)
00205 {
00206 }
00207
00208 ISubPicProviderImpl::~ISubPicProviderImpl()
00209 {
00210 }
00211
00212 STDMETHODIMP ISubPicProviderImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00213 {
00214 return
00215 QI(ISubPicProvider)
00216 __super::NonDelegatingQueryInterface(riid, ppv);
00217 }
00218
00219
00220
00221 STDMETHODIMP ISubPicProviderImpl::Lock()
00222 {
00223 return m_pLock ? m_pLock->Lock(), S_OK : E_FAIL;
00224 }
00225
00226 STDMETHODIMP ISubPicProviderImpl::Unlock()
00227 {
00228 return m_pLock ? m_pLock->Unlock(), S_OK : E_FAIL;
00229 }
00230
00231
00232
00233
00234
00235 ISubPicQueueImpl::ISubPicQueueImpl(ISubPicAllocator* pAllocator, HRESULT* phr)
00236 : CUnknown(NAME("ISubPicQueueImpl"), NULL)
00237 , m_pAllocator(pAllocator)
00238 , m_rtNow(0)
00239 , m_fps(25.0)
00240 {
00241 if(phr) *phr = S_OK;
00242
00243 if(!m_pAllocator)
00244 {
00245 if(phr) *phr = E_FAIL;
00246 return;
00247 }
00248 }
00249
00250 ISubPicQueueImpl::~ISubPicQueueImpl()
00251 {
00252 }
00253
00254 STDMETHODIMP ISubPicQueueImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00255 {
00256 return
00257 QI(ISubPicQueue)
00258 __super::NonDelegatingQueryInterface(riid, ppv);
00259 }
00260
00261
00262
00263 STDMETHODIMP ISubPicQueueImpl::SetSubPicProvider(ISubPicProvider* pSubPicProvider)
00264 {
00265 CAutoLock cAutoLock(&m_csSubPicProvider);
00266
00267
00268 {
00269 m_pSubPicProvider = pSubPicProvider;
00270
00271 Invalidate();
00272 }
00273
00274 return S_OK;
00275 }
00276
00277 STDMETHODIMP ISubPicQueueImpl::GetSubPicProvider(ISubPicProvider** pSubPicProvider)
00278 {
00279 if(!pSubPicProvider)
00280 return E_POINTER;
00281
00282 CAutoLock cAutoLock(&m_csSubPicProvider);
00283
00284 if(m_pSubPicProvider)
00285 (*pSubPicProvider = m_pSubPicProvider)->AddRef();
00286
00287 return !!*pSubPicProvider ? S_OK : E_FAIL;
00288 }
00289
00290 STDMETHODIMP ISubPicQueueImpl::SetFPS(double fps)
00291 {
00292 m_fps = fps;
00293
00294 return S_OK;
00295 }
00296
00297 STDMETHODIMP ISubPicQueueImpl::SetTime(REFERENCE_TIME rtNow)
00298 {
00299 m_rtNow = rtNow;
00300
00301 return S_OK;
00302 }
00303
00304
00305
00306 HRESULT ISubPicQueueImpl::RenderTo(ISubPic* pSubPic, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double fps)
00307 {
00308 HRESULT hr = E_FAIL;
00309
00310 if(!pSubPic)
00311 return hr;
00312
00313 CComPtr<ISubPicProvider> pSubPicProvider;
00314 if(FAILED(GetSubPicProvider(&pSubPicProvider)) || !pSubPicProvider)
00315 return hr;
00316
00317 if(FAILED(pSubPicProvider->Lock()))
00318 return hr;
00319
00320 SubPicDesc spd;
00321 if(SUCCEEDED(pSubPic->ClearDirtyRect(0xFF000000))
00322 && SUCCEEDED(pSubPic->Lock(spd)))
00323 {
00324 CRect r(0,0,0,0);
00325 hr = pSubPicProvider->Render(spd, (rtStart+rtStop)/2, fps, r);
00326
00327 pSubPic->SetStart(rtStart);
00328 pSubPic->SetStop(rtStop);
00329
00330 pSubPic->Unlock(r);
00331 }
00332
00333 pSubPicProvider->Unlock();
00334
00335 return hr;
00336 }
00337
00338
00339
00340
00341
00342 CSubPicQueue::CSubPicQueue(int nMaxSubPic, ISubPicAllocator* pAllocator, HRESULT* phr)
00343 : ISubPicQueueImpl(pAllocator, phr)
00344 , m_nMaxSubPic(nMaxSubPic)
00345 , m_rtQueueStart(0)
00346 {
00347 if(phr && FAILED(*phr))
00348 return;
00349
00350 if(m_nMaxSubPic < 1)
00351 {if(phr) *phr = E_INVALIDARG; return;}
00352
00353 m_fBreakBuffering = false;
00354 for(int i = 0; i < EVENT_COUNT; i++)
00355 m_ThreadEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
00356 CAMThread::Create();
00357 }
00358
00359 CSubPicQueue::~CSubPicQueue()
00360 {
00361 m_fBreakBuffering = true;
00362 SetEvent(m_ThreadEvents[EVENT_EXIT]);
00363 CAMThread::Close();
00364 for(int i = 0; i < EVENT_COUNT; i++)
00365 CloseHandle(m_ThreadEvents[i]);
00366 }
00367
00368
00369
00370 STDMETHODIMP CSubPicQueue::SetFPS(double fps)
00371 {
00372 HRESULT hr = __super::SetFPS(fps);
00373 if(FAILED(hr)) return hr;
00374
00375 SetEvent(m_ThreadEvents[EVENT_TIME]);
00376
00377 return S_OK;
00378 }
00379
00380 STDMETHODIMP CSubPicQueue::SetTime(REFERENCE_TIME rtNow)
00381 {
00382 HRESULT hr = __super::SetTime(rtNow);
00383 if(FAILED(hr)) return hr;
00384
00385 SetEvent(m_ThreadEvents[EVENT_TIME]);
00386
00387 return S_OK;
00388 }
00389
00390 STDMETHODIMP CSubPicQueue::Invalidate(REFERENCE_TIME rtInvalidate)
00391 {
00392 {
00393
00394
00395
00396 m_rtInvalidate = rtInvalidate;
00397 m_fBreakBuffering = true;
00398 SetEvent(m_ThreadEvents[EVENT_TIME]);
00399 }
00400
00401 return S_OK;
00402 }
00403
00404 STDMETHODIMP_(bool) CSubPicQueue::LookupSubPic(REFERENCE_TIME rtNow, ISubPic** ppSubPic)
00405 {
00406 if(!ppSubPic)
00407 return(false);
00408
00409 *ppSubPic = NULL;
00410
00411 CAutoLock cQueueLock(&m_csQueueLock);
00412
00413 POSITION pos = GetHeadPosition();
00414 while(pos)
00415 {
00416 CComPtr<ISubPic> pSubPic = GetNext(pos);
00417 if(pSubPic->GetStart() <= rtNow && rtNow < pSubPic->GetStop())
00418 {
00419 *ppSubPic = pSubPic.Detach();
00420 break;
00421 }
00422 }
00423
00424 return(!!*ppSubPic);
00425 }
00426
00427 STDMETHODIMP CSubPicQueue::GetStats(int& nSubPics, REFERENCE_TIME& rtNow, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
00428 {
00429 CAutoLock cQueueLock(&m_csQueueLock);
00430
00431 nSubPics = GetCount();
00432 rtNow = m_rtNow;
00433 rtStart = m_rtQueueStart;
00434 rtStop = GetCount() > 0 ? GetTail()->GetStop() : rtStart;
00435
00436 return S_OK;
00437 }
00438
00439 STDMETHODIMP CSubPicQueue::GetStats(int nSubPic, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
00440 {
00441 CAutoLock cQueueLock(&m_csQueueLock);
00442
00443 rtStart = rtStop = -1;
00444
00445 if(nSubPic >= 0 && nSubPic < (int)GetCount())
00446 {
00447 if(POSITION pos = FindIndex(nSubPic))
00448 {
00449 rtStart = GetAt(pos)->GetStart();
00450 rtStop = GetAt(pos)->GetStop();
00451 }
00452 }
00453 else
00454 {
00455 return E_INVALIDARG;
00456 }
00457
00458 return S_OK;
00459 }
00460
00461
00462
00463 REFERENCE_TIME CSubPicQueue::UpdateQueue()
00464 {
00465 CAutoLock cQueueLock(&m_csQueueLock);
00466
00467 REFERENCE_TIME rtNow = m_rtNow;
00468
00469 if(rtNow < m_rtQueueStart)
00470 {
00471 RemoveAll();
00472 }
00473 else
00474 {
00475 while(GetCount() > 0 && rtNow >= GetHead()->GetStop())
00476 RemoveHead();
00477 }
00478
00479 m_rtQueueStart = rtNow;
00480
00481 if(GetCount() > 0)
00482 rtNow = GetTail()->GetStop();
00483
00484 return(rtNow);
00485 }
00486
00487 void CSubPicQueue::AppendQueue(ISubPic* pSubPic)
00488 {
00489 CAutoLock cQueueLock(&m_csQueueLock);
00490
00491 AddTail(pSubPic);
00492 }
00493
00494
00495
00496 DWORD CSubPicQueue::ThreadProc()
00497 {
00498 SetThreadPriority(m_hThread, THREAD_PRIORITY_LOWEST);
00499
00500 while((WaitForMultipleObjects(EVENT_COUNT, m_ThreadEvents, FALSE, INFINITE) - WAIT_OBJECT_0) == EVENT_TIME)
00501 {
00502 double fps = m_fps;
00503 REFERENCE_TIME rtNow = UpdateQueue();
00504
00505 int nMaxSubPic = m_nMaxSubPic;
00506
00507 CComPtr<ISubPicProvider> pSubPicProvider;
00508 if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider
00509 && SUCCEEDED(pSubPicProvider->Lock()))
00510 {
00511 for(POSITION pos = pSubPicProvider->GetStartPosition(rtNow, fps);
00512 pos && !m_fBreakBuffering && GetCount() < (size_t)nMaxSubPic;
00513 pos = pSubPicProvider->GetNext(pos))
00514 {
00515 REFERENCE_TIME rtStart = pSubPicProvider->GetStart(pos, fps);
00516 REFERENCE_TIME rtStop = pSubPicProvider->GetStop(pos, fps);
00517
00518 if(m_rtNow >= rtStart)
00519 {
00520
00521 if(m_rtNow >= rtStop) continue;
00522 }
00523
00524 if(rtStart >= m_rtNow + 60*10000000i64)
00525 break;
00526
00527 if(rtNow < rtStop)
00528 {
00529 CComPtr<ISubPic> pStatic;
00530 if(FAILED(m_pAllocator->GetStatic(&pStatic)))
00531 break;
00532
00533 HRESULT hr = RenderTo(pStatic, rtStart, rtStop, fps);
00534
00535 if(FAILED(hr))
00536 break;
00537
00538 if(S_OK != hr)
00539 continue;
00540
00541 CComPtr<ISubPic> pDynamic;
00542 if(FAILED(m_pAllocator->AllocDynamic(&pDynamic))
00543 || FAILED(pStatic->CopyTo(pDynamic)))
00544 break;
00545
00546 AppendQueue(pDynamic);
00547 }
00548 }
00549
00550 pSubPicProvider->Unlock();
00551 }
00552
00553 if(m_fBreakBuffering)
00554 {
00555 CAutoLock cQueueLock(&m_csQueueLock);
00556
00557 REFERENCE_TIME rtInvalidate = m_rtInvalidate;
00558
00559 while(GetCount() && GetTail()->GetStop() > rtInvalidate)
00560 {
00561 if(GetTail()->GetStart() < rtInvalidate)
00562 GetTail()->SetStop(rtInvalidate);
00563 else
00564 RemoveTail();
00565 }
00566
00567 m_fBreakBuffering = false;
00568 }
00569 }
00570
00571 return(0);
00572 }
00573
00574
00575
00576
00577
00578 CSubPicQueueNoThread::CSubPicQueueNoThread(ISubPicAllocator* pAllocator, HRESULT* phr)
00579 : ISubPicQueueImpl(pAllocator, phr)
00580 {
00581 }
00582
00583 CSubPicQueueNoThread::~CSubPicQueueNoThread()
00584 {
00585 }
00586
00587
00588
00589 STDMETHODIMP CSubPicQueueNoThread::Invalidate(REFERENCE_TIME rtInvalidate)
00590 {
00591 CAutoLock cQueueLock(&m_csLock);
00592
00593 m_pSubPic = NULL;
00594
00595 return S_OK;
00596 }
00597
00598 STDMETHODIMP_(bool) CSubPicQueueNoThread::LookupSubPic(REFERENCE_TIME rtNow, ISubPic** ppSubPic)
00599 {
00600 if(!ppSubPic)
00601 return(false);
00602
00603 *ppSubPic = NULL;
00604
00605 CComPtr<ISubPic> pSubPic;
00606
00607 {
00608 CAutoLock cAutoLock(&m_csLock);
00609
00610 if(!m_pSubPic)
00611 {
00612 if(FAILED(m_pAllocator->AllocDynamic(&m_pSubPic)))
00613 return(false);
00614 }
00615
00616 pSubPic = m_pSubPic;
00617 }
00618
00619 if(pSubPic->GetStart() <= rtNow && rtNow < pSubPic->GetStop())
00620 {
00621 (*ppSubPic = pSubPic)->AddRef();
00622 }
00623 else
00624 {
00625 CComPtr<ISubPicProvider> pSubPicProvider;
00626 if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider
00627 && SUCCEEDED(pSubPicProvider->Lock()))
00628 {
00629 double fps = m_fps;
00630
00631 if(POSITION pos = pSubPicProvider->GetStartPosition(rtNow, fps))
00632 {
00633 REFERENCE_TIME rtStart = pSubPicProvider->GetStart(pos, fps);
00634 REFERENCE_TIME rtStop = pSubPicProvider->GetStop(pos, fps);
00635
00636 if(pSubPicProvider->IsAnimated(pos))
00637 {
00638 rtStart = rtNow;
00639 rtStop = rtNow+1;
00640 }
00641
00642 if(rtStart <= rtNow && rtNow < rtStop)
00643 {
00644 if(m_pAllocator->IsDynamicWriteOnly())
00645 {
00646 CComPtr<ISubPic> pStatic;
00647 if(SUCCEEDED(m_pAllocator->GetStatic(&pStatic))
00648 && SUCCEEDED(RenderTo(pStatic, rtStart, rtStop, fps))
00649 && SUCCEEDED(pStatic->CopyTo(pSubPic)))
00650 (*ppSubPic = pSubPic)->AddRef();
00651 }
00652 else
00653 {
00654 if(SUCCEEDED(RenderTo(m_pSubPic, rtStart, rtStop, fps)))
00655 (*ppSubPic = pSubPic)->AddRef();
00656 }
00657 }
00658 }
00659
00660 pSubPicProvider->Unlock();
00661
00662 if(*ppSubPic)
00663 {
00664 CAutoLock cAutoLock(&m_csLock);
00665
00666 m_pSubPic = *ppSubPic;
00667 }
00668 }
00669 }
00670
00671 return(!!*ppSubPic);
00672 }
00673
00674 STDMETHODIMP CSubPicQueueNoThread::GetStats(int& nSubPics, REFERENCE_TIME& rtNow, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
00675 {
00676 CAutoLock cAutoLock(&m_csLock);
00677
00678 nSubPics = 0;
00679 rtNow = m_rtNow;
00680 rtStart = rtStop = 0;
00681
00682 if(m_pSubPic)
00683 {
00684 nSubPics = 1;
00685 rtStart = m_pSubPic->GetStart();
00686 rtStop = m_pSubPic->GetStop();
00687 }
00688
00689 return S_OK;
00690 }
00691
00692 STDMETHODIMP CSubPicQueueNoThread::GetStats(int nSubPic, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
00693 {
00694 CAutoLock cAutoLock(&m_csLock);
00695
00696 if(!m_pSubPic || nSubPic != 0)
00697 return E_INVALIDARG;
00698
00699 rtStart = m_pSubPic->GetStart();
00700 rtStop = m_pSubPic->GetStop();
00701
00702 return S_OK;
00703 }
00704
00705
00706
00707
00708
00709 ISubPicAllocatorPresenterImpl::ISubPicAllocatorPresenterImpl(HWND hWnd)
00710 : CUnknown(NAME("ISubPicAllocatorPresenterImpl"), NULL)
00711 , m_hWnd(hWnd)
00712 , m_NativeVideoSize(0, 0), m_AspectRatio(0, 0)
00713 , m_VideoRect(0, 0, 0, 0), m_WindowRect(0, 0, 0, 0)
00714 , m_fps(25.0)
00715 {
00716 SetVideoAngle(Vector(), false);
00717 }
00718
00719 ISubPicAllocatorPresenterImpl::~ISubPicAllocatorPresenterImpl()
00720 {
00721 }
00722
00723 STDMETHODIMP ISubPicAllocatorPresenterImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00724 {
00725 return
00726 QI(ISubPicAllocatorPresenter)
00727 __super::NonDelegatingQueryInterface(riid, ppv);
00728 }
00729
00730 void ISubPicAllocatorPresenterImpl::AlphaBltSubPic(CSize size, SubPicDesc* pTarget)
00731 {
00732 CComPtr<ISubPic> pSubPic;
00733 if(m_pSubPicQueue->LookupSubPic(m_rtNow, &pSubPic))
00734 {
00735 SubPicDesc spd;
00736 pSubPic->GetDesc(spd);
00737
00738 CRect r;
00739 pSubPic->GetDirtyRect(r);
00740
00741
00742 r.DeflateRect(1, 1);
00743
00744 CRect rDstText(
00745 r.left * size.cx / spd.w,
00746 r.top * size.cy / spd.h,
00747 r.right * size.cx / spd.w,
00748 r.bottom * size.cy / spd.h);
00749
00750 pSubPic->AlphaBlt(r, rDstText, pTarget);
00751 }
00752 }
00753
00754
00755
00756 STDMETHODIMP_(SIZE) ISubPicAllocatorPresenterImpl::GetVideoSize(bool fCorrectAR)
00757 {
00758 CSize VideoSize(m_NativeVideoSize);
00759
00760 if(fCorrectAR && m_AspectRatio.cx > 0 && m_AspectRatio.cy > 0)
00761 VideoSize.cx = VideoSize.cy*m_AspectRatio.cx/m_AspectRatio.cy;
00762
00763 return(VideoSize);
00764 }
00765
00766 STDMETHODIMP_(void) ISubPicAllocatorPresenterImpl::SetPosition(RECT w, RECT v)
00767 {
00768 bool fWindowPosChanged = !!(m_WindowRect != w);
00769 bool fWindowSizeChanged = !!(m_WindowRect.Size() != CRect(w).Size());
00770
00771 m_WindowRect = w;
00772
00773 bool fVideoRectChanged = !!(m_VideoRect != v);
00774
00775 m_VideoRect = v;
00776
00777 if(fWindowSizeChanged || fVideoRectChanged)
00778 {
00779 if(m_pAllocator)
00780 {
00781 m_pAllocator->SetCurSize(m_WindowRect.Size());
00782 m_pAllocator->SetCurVidRect(m_VideoRect);
00783 }
00784
00785 if(m_pSubPicQueue)
00786 {
00787 m_pSubPicQueue->Invalidate();
00788 }
00789 }
00790
00791 if(fWindowPosChanged || fVideoRectChanged)
00792 Paint(fWindowSizeChanged || fVideoRectChanged);
00793 }
00794
00795 STDMETHODIMP_(void) ISubPicAllocatorPresenterImpl::SetTime(REFERENCE_TIME rtNow)
00796 {
00797 m_rtNow = rtNow;
00798
00799 if(m_pSubPicQueue)
00800 {
00801 m_pSubPicQueue->SetTime(rtNow);
00802 }
00803 }
00804
00805 STDMETHODIMP_(double) ISubPicAllocatorPresenterImpl::GetFPS()
00806 {
00807 return(m_fps);
00808 }
00809
00810 STDMETHODIMP_(void) ISubPicAllocatorPresenterImpl::SetSubPicProvider(ISubPicProvider* pSubPicProvider)
00811 {
00812
00813
00814
00815 CComPtr<ISubPicProvider> pSPP = pSubPicProvider;
00816
00817 if(m_pSubPicQueue)
00818 m_pSubPicQueue->SetSubPicProvider(pSPP);
00819 }
00820
00821 STDMETHODIMP_(void) ISubPicAllocatorPresenterImpl::Invalidate(REFERENCE_TIME rtInvalidate)
00822 {
00823 if(m_pSubPicQueue)
00824 m_pSubPicQueue->Invalidate(rtInvalidate);
00825 }
00826
00827 #include <math.h>
00828
00829 void ISubPicAllocatorPresenterImpl::Transform(CRect r, Vector v[4])
00830 {
00831 v[0] = Vector(r.left, r.top, 0);
00832 v[1] = Vector(r.right, r.top, 0);
00833 v[2] = Vector(r.left, r.bottom, 0);
00834 v[3] = Vector(r.right, r.bottom, 0);
00835
00836 Vector center(r.CenterPoint().x, r.CenterPoint().y, 0);
00837 int l = (int)(Vector(r.Size().cx, r.Size().cy, 0).Length()*1.5f)+1;
00838
00839 for(int i = 0; i < 4; i++)
00840 {
00841 v[i] = m_xform << (v[i] - center);
00842 v[i].z = v[i].z / l + 0.5f;
00843 v[i].x /= v[i].z*2;
00844 v[i].y /= v[i].z*2;
00845 v[i] += center;
00846 }
00847 }
00848
00849 STDMETHODIMP ISubPicAllocatorPresenterImpl::SetVideoAngle(Vector v, bool fRepaint)
00850 {
00851 m_xform = XForm(Ray(Vector(0, 0, 0), v), Vector(1, 1, 1), false);
00852 if(fRepaint) Paint(true);
00853 return S_OK;
00854 }