X64 transport [Part 5] (Update plugins.cpp)
[xy_vsfilter.git] / src / subpic / SubPicQueueImpl.cpp
blob326210216a29e1d038780d38a89a282c9372410f
1 /*
2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "stdafx.h"
23 #include "SubPicQueueImpl.h"
24 #include "../DSUtil/DSUtil.h"
25 #include "CRect2.h"
27 #include "SubPicProviderExWrapper.h"
28 #include "SimpleSubPicWrapper.h"
30 #define CSUBPICQUEUE_THREAD_PROC_WAIT_TIMEOUT 20
31 #define CSUBPICQUEUE_LOOKUP_WAIT_TIMEOUT 40
32 #define CSUBPICQUEUE_UPDATEQUEUE_WAIT_TIMEOUT 100
35 // CSubPicQueueImpl
38 CSubPicQueueImpl::CSubPicQueueImpl(ISubPicExAllocator* pAllocator, HRESULT* phr, const int *prefered_colortype/*=NULL*/, int prefered_colortype_num/*=0*/)
39 : CUnknown(NAME("CSubPicQueueImpl"), NULL)
40 , m_pAllocator(pAllocator)
41 , m_rtNow(0)
42 , m_rtNowLast(0)
43 , m_fps(25.0)
45 if(phr) {
46 *phr = S_OK;
49 if(!m_pAllocator) {
50 if(phr) {
51 *phr = E_FAIL;
53 return;
55 for (int i=0;i<prefered_colortype_num;i++)
57 m_prefered_colortype.AddTail(prefered_colortype[i]);
59 if(m_prefered_colortype.IsEmpty())
61 m_prefered_colortype.AddTail(MSP_AYUV_PLANAR);
62 m_prefered_colortype.AddTail(MSP_AYUV);
63 m_prefered_colortype.AddTail(MSP_XY_AUYV);
64 m_prefered_colortype.AddTail(MSP_RGBA);
68 CSubPicQueueImpl::~CSubPicQueueImpl()
72 STDMETHODIMP CSubPicQueueImpl::NonDelegatingQueryInterface(REFIID riid, void** ppv)
74 return
75 QI(ISubPicQueue)
76 QI(ISimpleSubPicProvider)
77 __super::NonDelegatingQueryInterface(riid, ppv);
80 // ISubPicQueue
82 STDMETHODIMP CSubPicQueueImpl::SetSubPicProvider(ISubPicProvider* pSubPicProvider)
84 return SetSubPicProviderEx( CSubPicProviderExWrapper::GetSubPicProviderExWrapper(pSubPicProvider) );
87 STDMETHODIMP CSubPicQueueImpl::GetSubPicProvider(ISubPicProvider** pSubPicProvider)
89 if(!pSubPicProvider) {
90 return E_POINTER;
93 CAutoLock cAutoLock(&m_csSubPicProvider);
95 if(m_pSubPicProviderEx) {
96 *pSubPicProvider = m_pSubPicProviderEx;
97 (*pSubPicProvider)->AddRef();
100 return !!*pSubPicProvider ? S_OK : E_FAIL;
103 STDMETHODIMP CSubPicQueueImpl::SetFPS(double fps)
105 m_fps = fps;
107 return S_OK;
110 STDMETHODIMP CSubPicQueueImpl::SetTime(REFERENCE_TIME rtNow)
112 m_rtNow = rtNow;
114 return S_OK;
117 // ISubPicQueueEx
119 STDMETHODIMP CSubPicQueueImpl::SetSubPicProvider( IUnknown* subpic_provider )
121 CComQIPtr<ISubPicProviderEx> tmp = subpic_provider;
122 if (tmp)
124 return SetSubPicProviderEx(tmp);
126 else
128 CComQIPtr<ISubPicProvider> tmp2 = subpic_provider;
129 if (tmp2)
131 return SetSubPicProvider(tmp);
134 return E_NOTIMPL;
137 STDMETHODIMP CSubPicQueueImpl::GetSubPicProvider( IUnknown** subpic_provider )
139 if(!subpic_provider) {
140 return E_POINTER;
143 CAutoLock cAutoLock(&m_csSubPicProvider);
145 if(m_pSubPicProviderEx) {
146 *subpic_provider = m_pSubPicProviderEx;
147 (*subpic_provider)->AddRef();
150 return !!*subpic_provider ? S_OK : E_FAIL;
153 // private
155 HRESULT CSubPicQueueImpl::SetSubPicProviderEx( ISubPicProviderEx* pSubPicProviderEx )
157 // if(m_pSubPicProvider != pSubPicProvider)
159 CAutoLock cAutoLock(&m_csSubPicProvider);
160 m_pSubPicProviderEx = pSubPicProviderEx;
162 if(m_pSubPicProviderEx!=NULL && m_pAllocator!=NULL)
164 POSITION pos = m_prefered_colortype.GetHeadPosition();
165 while(pos!=NULL)
167 int color_type = m_prefered_colortype.GetNext(pos);
168 if( m_pSubPicProviderEx->IsColorTypeSupported( color_type ) &&
169 m_pAllocator->IsSpdColorTypeSupported( color_type ) )
171 m_pAllocator->SetSpdColorType(color_type);
172 break;
177 Invalidate();
179 return S_OK;
182 HRESULT CSubPicQueueImpl::GetSubPicProviderEx( ISubPicProviderEx** pSubPicProviderEx )
184 if(!pSubPicProviderEx) {
185 return E_POINTER;
188 CAutoLock cAutoLock(&m_csSubPicProvider);
190 if(m_pSubPicProviderEx) {
191 *pSubPicProviderEx = m_pSubPicProviderEx;
192 (*pSubPicProviderEx)->AddRef();
195 return !!*pSubPicProviderEx ? S_OK : E_FAIL;
198 HRESULT CSubPicQueueImpl::RenderTo(ISubPicEx* pSubPic, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double fps, BOOL bIsAnimated)
200 HRESULT hr = E_FAIL;
202 if(!pSubPic) {
203 return hr;
206 CComPtr<ISubPicProviderEx> pSubPicProviderEx;
207 if(FAILED(GetSubPicProviderEx(&pSubPicProviderEx)) || !pSubPicProviderEx) {
208 return hr;
211 if(FAILED(pSubPicProviderEx->Lock())) {
212 return hr;
215 SubPicDesc spd;
216 if(SUCCEEDED(pSubPic->Lock(spd)))
218 DWORD color = 0xFF000000;
219 // if(spd.type == MSP_YUY2 || spd.type == MSP_YV12 || spd.type == MSP_IYUV)
220 // {
221 // color = 0xFF801080;
222 // //color = 0xFF000000;
223 // }
224 // else if(spd.type == MSP_AYUV)
225 // {
226 // color = 0xFF108080;
227 // }
228 // else
229 // {
230 // color = 0xFF000000;
231 // }
232 if(SUCCEEDED(pSubPic->ClearDirtyRect(color)))
234 CAtlList<CRect> rectList;
236 hr = pSubPicProviderEx->RenderEx(spd, bIsAnimated ? rtStart : ((rtStart+rtStop)/2), fps, rectList);
238 DbgLog((LOG_TRACE, 3, "CSubPicQueueImpl::RenderTo => GetStartPosition"));
239 POSITION pos = pSubPicProviderEx->GetStartPosition(rtStart, fps);
241 DbgLog((LOG_TRACE, 3, "CSubPicQueueImpl::RenderTo => GetStartStop rtStart:%lu", (ULONG)rtStart/10000));
242 pSubPicProviderEx->GetStartStop(pos, fps, rtStart, rtStop);
243 DbgLog((LOG_TRACE, 3, "rtStart:%lu", (ULONG)rtStart/10000));
245 //DbgLog((LOG_TRACE, 3, TEXT("rtStart=%lu rtStop=%lu pos:%x fps:%f"), (ULONG)rtStart/10000, (ULONG)rtStop/10000, pos, fps));
247 pSubPic->SetStart(rtStart);
248 pSubPic->SetStop(rtStop);
250 pSubPic->Unlock(&rectList);
254 pSubPicProviderEx->Unlock();
256 return hr;
260 // CSubPicQueue
263 CSubPicQueue::CSubPicQueue(int nMaxSubPic, BOOL bDisableAnim, ISubPicExAllocator* pAllocator, HRESULT* phr)
264 : CSubPicQueueImpl(pAllocator, phr)
265 , m_nMaxSubPic(nMaxSubPic)
266 , m_bDisableAnim(bDisableAnim)
267 , m_rtQueueStart(0)
269 //InitTracer;
270 DbgLog((LOG_TRACE, 3, "CSubPicQueue::CSubPicQueue"));
271 //Trace(_T("SubPicQueue constructing\n"));
273 if(phr && FAILED(*phr))
274 return;
276 if(m_nMaxSubPic < 1)
277 {if(phr) *phr = E_INVALIDARG; return;}
279 m_fBreakBuffering = false;
280 for(int i = 0; i < EVENT_COUNT; i++)
281 m_ThreadEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
282 for(int i=0;i<QueueEvents_COUNT; i++)
283 m_QueueEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
284 if(m_nMaxSubPic > 0)
286 SetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
290 //m_subPos = NULL;
292 CAMThread::Create();
295 CSubPicQueue::~CSubPicQueue()
297 m_fBreakBuffering = true;
298 //SetEvent(m_ThreadEvents[EVENT_EXIT]);
299 CAMThread::CallWorker(EVENT_EXIT);
300 CAMThread::Close();
301 for(int i=0;i<QueueEvents_COUNT; i++)
302 CloseHandle(m_QueueEvents[i]);
303 for(int i = 0; i < EVENT_COUNT; i++)
304 CloseHandle(m_ThreadEvents[i]);
305 DbgLog((LOG_TRACE, 3, "CSubPicQueue::~CSubPicQueue"));
306 //ReleaseTracer;
309 // ISubPicQueue
311 STDMETHODIMP CSubPicQueue::SetFPS(double fps)
313 HRESULT hr = __super::SetFPS(fps);
314 if(FAILED(hr)) return hr;
316 //SetEvent(m_ThreadEvents[EVENT_TIME]);
317 //CallWorker(EVENT_TIME);
318 UpdateQueue();
320 return S_OK;
323 STDMETHODIMP CSubPicQueue::SetTime(REFERENCE_TIME rtNow)
325 HRESULT hr = __super::SetTime(rtNow);
326 if(FAILED(hr)) return hr;
328 //SetEvent(m_ThreadEvents[EVENT_TIME]);
329 //DbgLog((LOG_LOCKING, 3, "SetTime::CallWorker(EVENT_TIME)"));
330 //CallWorker(EVENT_TIME);
331 UpdateQueue();
333 return S_OK;
336 STDMETHODIMP CSubPicQueue::Invalidate(REFERENCE_TIME rtInvalidate)
339 // CAutoLock cQueueLock(&m_csQueueLock);
340 // RemoveAll();
342 m_rtInvalidate = rtInvalidate;
343 m_fBreakBuffering = true;
344 UpdateQueue();
347 return S_OK;
350 STDMETHODIMP_(bool) CSubPicQueue::LookupSubPic(REFERENCE_TIME rtNow, ISubPic** ppSubPic)
352 CComPtr<ISubPicProvider> pSubPicProvider;
353 double fps = m_fps;
354 *ppSubPic = NULL;
355 //if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider)
357 // if(pSubPicProvider->GetStartPosition(rtNow, fps))
359 CAutoLock cQueueLock(&m_csQueueLock);
360 int count = m_Queue.GetCount();
361 if(count>0)
362 if(WaitForSingleObject(m_QueueEvents[QueueEvents_NOTEMPTY], CSUBPICQUEUE_LOOKUP_WAIT_TIMEOUT)==WAIT_OBJECT_0)
364 POSITION pos = m_Queue.GetHeadPosition();
365 while(pos)
367 CComPtr<ISubPic> pSubPic = m_Queue.GetNext(pos);
368 //DbgLog((LOG_TRACE, 3, "picStart:%lu picStop:%lu rtNow:%lu", (ULONG)pSubPic->GetStart()/10000, (ULONG)pSubPic->GetStop()/10000, (ULONG)rtNow/10000));
369 if(pSubPic->GetStart() > rtNow)
370 break;
371 else if(rtNow < pSubPic->GetStop())
373 *ppSubPic = pSubPic.Detach();
374 break;
377 int count = m_Queue.GetCount();
378 if(count>0)
379 SetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
380 else//important
381 ResetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
382 if(count<m_nMaxSubPic)
383 SetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
384 else//important
385 ResetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
387 //DbgLog((LOG_TRACE, 3, "CSubPicQueue LookupSubPic return"));
392 return(!!*ppSubPic);
395 STDMETHODIMP_(bool) CSubPicQueue::LookupSubPic( REFERENCE_TIME now /*[in]*/, ISimpleSubPic** output_subpic/*[out]*/ )
397 //ToDo: fix me
398 return false;
401 STDMETHODIMP CSubPicQueue::GetStats(int& nSubPics, REFERENCE_TIME& rtNow, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
403 CAutoLock cQueueLock(&m_csQueueLock);
405 nSubPics = m_Queue.GetCount();
406 rtNow = m_rtNow;
407 rtStart = m_rtQueueStart;
408 rtStop = m_Queue.GetCount() > 0 ? m_Queue.GetTail()->GetStop() : rtStart;
410 return S_OK;
413 STDMETHODIMP CSubPicQueue::GetStats(int nSubPic, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
415 CAutoLock cQueueLock(&m_csQueueLock);
417 rtStart = rtStop = -1;
419 if(nSubPic >= 0 && nSubPic < (int)m_Queue.GetCount())
421 if(POSITION pos = m_Queue.FindIndex(nSubPic))
423 rtStart = m_Queue.GetAt(pos)->GetStart();
424 rtStop = m_Queue.GetAt(pos)->GetStop();
427 else
429 return E_INVALIDARG;
432 return S_OK;
435 // private
437 REFERENCE_TIME CSubPicQueue::UpdateQueue()
439 //DbgLog((LOG_TRACE, 3, "CSubPicQueue UpdateQueue"));
440 REFERENCE_TIME rtNow=0;
443 //if(WaitForMultipleObjects(QueueEvents_COUNT, m_QueueEvents, true, CSUBPICQUEUE_UPDATEQUEUE_WAIT_TIMEOUT))
445 CAutoLock cQueueLock(&m_csQueueLock);
446 rtNow = m_rtNow;
447 int count = m_Queue.GetCount();
448 if(rtNow < m_rtQueueStart)
450 m_Queue.RemoveAll();
451 count = 0;
453 else
455 while(count>0 && rtNow >= m_Queue.GetHead()->GetStop())
457 m_Queue.RemoveHead();
458 count--;
461 if(count>0)
462 rtNow = m_Queue.GetTail()->GetStop();
463 m_rtQueueStart = m_rtNow;
464 if(count>0)
465 SetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
466 else//important
467 ResetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
468 if(count<m_nMaxSubPic)
469 SetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
470 else//important
471 ResetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
473 return(rtNow);
476 int CSubPicQueue::GetQueueCount()
478 CAutoLock cQueueLock(&m_csQueueLock);
480 return m_Queue.GetCount();
482 void CSubPicQueue::AppendQueue(ISubPic* pSubPic)
484 CAutoLock cQueueLock(&m_csQueueLock);
486 m_Queue.AddTail(pSubPic);
489 // overrides
491 DWORD CSubPicQueue::ThreadProc()
493 BOOL bDisableAnim = m_bDisableAnim;
494 SetThreadPriority(m_hThread, bDisableAnim ? THREAD_PRIORITY_LOWEST : THREAD_PRIORITY_ABOVE_NORMAL/*THREAD_PRIORITY_BELOW_NORMAL*/);
496 //Trace(_T("CSubPicQueue Thread Start\n"));
497 DbgLog((LOG_TRACE, 3, "CSubPicQueue Thread Start"));
498 //while((WaitForMultipleObjects(EVENT_COUNT, m_ThreadEvents, FALSE, INFINITE) - WAIT_OBJECT_0) == EVENT_TIME)
499 DWORD request;
500 while(true)
502 if(CheckRequest(&request))
504 if(request==EVENT_EXIT)
505 break;
508 if(WaitForSingleObject(m_QueueEvents[QueueEvents_NOTFULL], CSUBPICQUEUE_THREAD_PROC_WAIT_TIMEOUT)!=WAIT_OBJECT_0)
509 continue;
511 bool failed = true;
512 bool reachEnd = false;
513 CComPtr<ISubPicEx> pSubPic;
514 CComPtr<ISubPicEx> pStatic;
515 CComPtr<ISubPicProviderEx> pSubPicProviderEx;
517 double fps = m_fps;
518 int nMaxSubPic = m_nMaxSubPic;
520 m_csQueueLock.Lock();
521 REFERENCE_TIME rtNow = 0;
522 if(m_Queue.GetCount()>0)
523 rtNow = m_Queue.GetTail()->GetStop();
524 if(rtNow < m_rtNow)
525 rtNow = m_rtNow;
526 CComPtr<ISubPicExAllocator> pAllocator = m_pAllocator;
527 m_csQueueLock.Unlock();
529 //for(int i=0;i<1;i++)
531 if(FAILED(pAllocator->AllocDynamicEx(&pSubPic))
532 || (pAllocator->IsDynamicWriteOnly() && FAILED(pAllocator->GetStaticEx(&pStatic))))
533 break;
535 if(SUCCEEDED(GetSubPicProviderEx(&pSubPicProviderEx)) && pSubPicProviderEx
536 && SUCCEEDED(pSubPicProviderEx->Lock()))
538 REFERENCE_TIME rtStart, rtStop;
540 //DbgLog((LOG_TRACE, 3, "CSubPicQueue::ThreadProc => GetStartPosition"));
541 POSITION pos = pSubPicProviderEx->GetStartPosition(rtNow, fps);
543 //DbgLog((LOG_TRACE, 3, "pos:%x, m_fBreakBuffering:%d GetCount():%d nMaxSubPic:%d", pos, m_fBreakBuffering, GetCount(), nMaxSubPic));
545 if(pos!=NULL)//!m_fBreakBuffering
547 reachEnd = false;
548 ASSERT(m_Queue.GetCount() < (size_t)nMaxSubPic);
550 //DbgLog((LOG_TRACE, 3, "CSubPicQueue::ThreadProc => GetStartStop"));
551 pSubPicProviderEx->GetStartStop(pos, fps, rtStart, rtStop);
553 //DbgLog((LOG_TRACE, 3, "rtStart=%lu rtStop=%lu fps=%f rtNow=%lu m_rtNow=%lu", (ULONG)rtStart/10000, (ULONG)rtStop/10000,
554 // fps, (ULONG)rtNow/10000, (ULONG)m_rtNow/10000));
556 if(m_rtNow >= rtStop)
557 break;
558 //if(rtStart >= m_rtNow + 60*10000000i64) // we are already one minute ahead, this should be enough
559 // break;
561 if(rtNow < rtStop)
563 bool bIsAnimated = pSubPicProviderEx->IsAnimated(pos) && !bDisableAnim;
564 if(pAllocator->IsDynamicWriteOnly())
565 //if(true)
567 HRESULT hr = RenderTo(pStatic, rtStart, rtStop, fps, bIsAnimated);
568 if(FAILED(hr)
569 || S_OK != hr// subpic was probably empty
570 || FAILED(pStatic->CopyTo(pSubPic))
572 break;
574 else
576 HRESULT hr = RenderTo(pSubPic, rtStart, rtStop, fps, bIsAnimated);
577 if(FAILED(hr)
578 || S_OK != hr// subpic was probably empty
580 break;
582 /*DbgLog((LOG_TRACE, 3, "picStart:%lu picStop:%lu seg:%d idx:%d pos:%x",
583 (ULONG)pSubPic->GetStart()/10000,
584 (ULONG)pSubPic->GetStop()/10000,
585 (int)pos >> 16, (int)pos & ((1<<16)-1)));*/
586 failed = false;
589 else
590 reachEnd = true;
591 pSubPicProviderEx->Unlock();
592 pSubPicProviderEx = NULL;
596 m_csQueueLock.Lock();
597 if(!failed)
598 m_Queue.AddTail(pSubPic);
599 int count = m_Queue.GetCount();
600 if(count>0)
601 SetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
602 else//important
603 ResetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
604 if(count<m_nMaxSubPic)
605 SetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
606 else//important
607 ResetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
608 m_csQueueLock.Unlock();
610 if(reachEnd)
611 Sleep(CSUBPICQUEUE_THREAD_PROC_WAIT_TIMEOUT);
613 //if(failed)
615 // if(pSubPicProvider!=NULL)
616 // pSubPicProvider->Unlock();
617 // ReleaseSemaphore(m_semNotFull, 1, NULL);
619 //else
620 // ReleaseSemaphore(m_semNotEmpty, 1, NULL);
622 //DbgLog((LOG_LOCKING, 3, "ReleaseMutex m_mtxResetNotFull"));
623 //ReleaseMutex(m_mtxResetNotFull);
626 //Trace(_T("CSubPicQueue Thread Return\n"));
627 DbgLog((LOG_TRACE, 3, "CSubPicQueue Thread Return"));
628 Reply(EVENT_EXIT);
629 return(0);
633 // CSubPicQueueNoThread
636 CSubPicQueueNoThread::CSubPicQueueNoThread(ISubPicExAllocator* pAllocator, HRESULT* phr, const int *prefered_colortype/*=NULL*/, int prefered_colortype_num/*=0*/)
637 : CSubPicQueueImpl(pAllocator, phr, prefered_colortype, prefered_colortype_num)
641 CSubPicQueueNoThread::~CSubPicQueueNoThread()
645 // ISubPicQueue
647 STDMETHODIMP CSubPicQueueNoThread::Invalidate(REFERENCE_TIME rtInvalidate)
649 CAutoLock cQueueLock(&m_csLock);
651 if( m_pSubPic && m_pSubPic->GetStop() >= rtInvalidate)
653 m_pSubPic = NULL;
655 return S_OK;
658 STDMETHODIMP_(bool) CSubPicQueueNoThread::LookupSubPic(REFERENCE_TIME rtNow, ISubPic** ppSubPic)
660 if(ppSubPic!=NULL)
662 ISubPicEx* temp;
663 bool result = LookupSubPicEx(rtNow, &temp);
664 *ppSubPic = temp;
665 return result;
667 else
669 return LookupSubPicEx(rtNow, NULL);
673 STDMETHODIMP_(bool) CSubPicQueueNoThread::LookupSubPic( REFERENCE_TIME now /*[in]*/, ISimpleSubPic** output_subpic /*[out]*/ )
675 if(output_subpic!=NULL)
677 CComPtr<ISubPicEx> temp;
678 bool result = LookupSubPicEx(now, &temp);
679 (*output_subpic = new SimpleSubPicWrapper(temp))->AddRef();
680 return result;
682 else
684 return LookupSubPicEx(now, NULL);
689 bool CSubPicQueueNoThread::LookupSubPicEx(REFERENCE_TIME rtNow, ISubPicEx** ppSubPic)
691 if(!ppSubPic)
692 return(false);
694 *ppSubPic = NULL;
696 CComPtr<ISubPicEx> pSubPic;
699 CAutoLock cAutoLock(&m_csLock);
701 if(!m_pSubPic)
703 if(FAILED(m_pAllocator->AllocDynamicEx(&m_pSubPic))) {
704 return false;
708 pSubPic = m_pSubPic;
711 if(pSubPic->GetStart() <= rtNow && rtNow < pSubPic->GetStop())
713 (*ppSubPic = pSubPic)->AddRef();
715 else
717 CComPtr<ISubPicProvider> pSubPicProvider;
718 if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider
719 && SUCCEEDED(pSubPicProvider->Lock()))
721 double fps = m_fps;
723 if(POSITION pos = pSubPicProvider->GetStartPosition(rtNow, fps))
725 REFERENCE_TIME rtStart = pSubPicProvider->GetStart(pos, fps);
726 REFERENCE_TIME rtStop = pSubPicProvider->GetStop(pos, fps);
728 if(rtStart <= rtNow && rtNow < rtStop)
730 SIZE MaxTextureSize, VirtualSize;
731 POINT VirtualTopLeft;
732 HRESULT hr2;
733 if (SUCCEEDED (hr2 = pSubPicProvider->GetTextureSize(pos, MaxTextureSize, VirtualSize, VirtualTopLeft))) {
734 m_pAllocator->SetMaxTextureSize(MaxTextureSize);
736 if(m_pAllocator->IsDynamicWriteOnly())
738 CComPtr<ISubPicEx> pStatic;
739 if(SUCCEEDED(m_pAllocator->GetStaticEx(&pStatic))
740 && SUCCEEDED(RenderTo(pStatic, rtNow, rtNow+1, fps, true))
741 && SUCCEEDED(pStatic->CopyTo(pSubPic)))
742 (*ppSubPic = pSubPic)->AddRef();
744 else
746 if(SUCCEEDED(RenderTo(m_pSubPic, rtNow, rtNow+1, fps, true)))
747 (*ppSubPic = pSubPic)->AddRef();
752 pSubPicProvider->Unlock();
754 if(*ppSubPic)
756 CAutoLock cAutoLock(&m_csLock);
758 m_pSubPic = *ppSubPic;
762 return(!!*ppSubPic);
765 STDMETHODIMP CSubPicQueueNoThread::GetStats(int& nSubPics, REFERENCE_TIME& rtNow, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
767 CAutoLock cAutoLock(&m_csLock);
769 nSubPics = 0;
770 rtNow = m_rtNow;
771 rtStart = rtStop = 0;
773 if(m_pSubPic)
775 nSubPics = 1;
776 rtStart = m_pSubPic->GetStart();
777 rtStop = m_pSubPic->GetStop();
780 return S_OK;
783 STDMETHODIMP CSubPicQueueNoThread::GetStats(int nSubPic, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
785 CAutoLock cAutoLock(&m_csLock);
787 if(!m_pSubPic || nSubPic != 0)
788 return E_INVALIDARG;
790 rtStart = m_pSubPic->GetStart();
791 rtStop = m_pSubPic->GetStop();
793 return S_OK;