ISubPic.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "stdafx.h"
00023 #include "ISubPic.h"
00024 #include "..\DSUtil\DSUtil.h"
00025 
00026 //
00027 // ISubPicImpl
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 // ISubPic
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 // ISubPicAllocatorImpl
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 // ISubPicAllocator
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 // ISubPicProviderImpl
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 // ISubPicProvider
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 // ISubPicQueueImpl
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 // ISubPicQueue
00262 
00263 STDMETHODIMP ISubPicQueueImpl::SetSubPicProvider(ISubPicProvider* pSubPicProvider)
00264 {
00265         CAutoLock cAutoLock(&m_csSubPicProvider);
00266 
00267 //      if(m_pSubPicProvider != pSubPicProvider)
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 // private
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 // CSubPicQueue
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 // ISubPicQueue
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 //              CAutoLock cQueueLock(&m_csQueueLock);
00394 //              RemoveAll();
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 // private
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 // overrides
00495 
00496 DWORD CSubPicQueue::ThreadProc()
00497 {       
00498         SetThreadPriority(m_hThread, THREAD_PRIORITY_LOWEST/*THREAD_PRIORITY_BELOW_NORMAL*/);
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 //                                              m_fBufferUnderrun = true;
00521                                         if(m_rtNow >= rtStop) continue;
00522                                 }
00523 
00524                                 if(rtStart >= m_rtNow + 60*10000000i64) // we are already one minute ahead, this should be enough
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) // subpic was probably empty
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 // CSubPicQueueNoThread
00576 //
00577 
00578 CSubPicQueueNoThread::CSubPicQueueNoThread(ISubPicAllocator* pAllocator, HRESULT* phr) 
00579         : ISubPicQueueImpl(pAllocator, phr)
00580 {
00581 }
00582 
00583 CSubPicQueueNoThread::~CSubPicQueueNoThread()
00584 {
00585 }
00586 
00587 // ISubPicQueue
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 // ISubPicAllocatorPresenterImpl
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                 // FIXME
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 // ISubPicAllocatorPresenter
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         // CComPtr will make sure it gets destroyed even if it was passed 
00813         // here with 0 refcnt and m_pSubPicQueue->SetSubPicProvider fails 
00814         // to accept it.
00815         CComPtr<ISubPicProvider> pSPP = pSubPicProvider;
00816 
00817         if(m_pSubPicQueue)
00818                 m_pSubPicQueue->SetSubPicProvider(pSPP); // pSPP == NULL is ok, we use it to empty the provider
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 }

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