Support unrar64.dll
[xy_vsfilter.git] / src / subpic / SubPicQueueImpl.cpp
blob05d2ed2a1176166e8b593b92b44b5dc907aeb7c0
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 if (pSubPicProvider!=NULL)
86 return SetSubPicProviderEx( CSubPicProviderExWrapper::GetSubPicProviderExWrapper(pSubPicProvider) );
88 else
90 return SetSubPicProviderEx( NULL );
94 STDMETHODIMP CSubPicQueueImpl::GetSubPicProvider(ISubPicProvider** pSubPicProvider)
96 if(!pSubPicProvider) {
97 return E_POINTER;
100 CAutoLock cAutoLock(&m_csSubPicProvider);
102 if(m_pSubPicProviderEx) {
103 *pSubPicProvider = m_pSubPicProviderEx;
104 (*pSubPicProvider)->AddRef();
107 return !!*pSubPicProvider ? S_OK : E_FAIL;
110 STDMETHODIMP CSubPicQueueImpl::SetFPS(double fps)
112 m_fps = fps;
114 return S_OK;
117 STDMETHODIMP CSubPicQueueImpl::SetTime(REFERENCE_TIME rtNow)
119 m_rtNow = rtNow;
121 return S_OK;
124 // ISubPicQueueEx
126 STDMETHODIMP CSubPicQueueImpl::SetSubPicProvider( IUnknown* subpic_provider )
128 if (subpic_provider!=NULL)
130 CComQIPtr<ISubPicProviderEx> tmp = subpic_provider;
131 if (tmp)
133 return SetSubPicProviderEx(tmp);
135 else
137 CComQIPtr<ISubPicProvider> tmp2 = subpic_provider;
138 if (tmp2)
140 return SetSubPicProvider(tmp);
143 return E_NOTIMPL;
145 else
147 return SetSubPicProviderEx(NULL);
151 STDMETHODIMP CSubPicQueueImpl::GetSubPicProvider( IUnknown** subpic_provider )
153 if(!subpic_provider) {
154 return E_POINTER;
157 CAutoLock cAutoLock(&m_csSubPicProvider);
159 if(m_pSubPicProviderEx) {
160 *subpic_provider = m_pSubPicProviderEx;
161 (*subpic_provider)->AddRef();
164 return !!*subpic_provider ? S_OK : E_FAIL;
167 // private
169 HRESULT CSubPicQueueImpl::SetSubPicProviderEx( ISubPicProviderEx* pSubPicProviderEx )
171 // if(m_pSubPicProvider != pSubPicProvider)
173 CAutoLock cAutoLock(&m_csSubPicProvider);
174 m_pSubPicProviderEx = pSubPicProviderEx;
176 if(m_pSubPicProviderEx!=NULL && m_pAllocator!=NULL)
178 POSITION pos = m_prefered_colortype.GetHeadPosition();
179 while(pos!=NULL)
181 int color_type = m_prefered_colortype.GetNext(pos);
182 if( m_pSubPicProviderEx->IsColorTypeSupported( color_type ) &&
183 m_pAllocator->IsSpdColorTypeSupported( color_type ) )
185 m_pAllocator->SetSpdColorType(color_type);
186 break;
191 Invalidate();
193 return S_OK;
196 HRESULT CSubPicQueueImpl::GetSubPicProviderEx( ISubPicProviderEx** pSubPicProviderEx )
198 if(!pSubPicProviderEx) {
199 return E_POINTER;
202 CAutoLock cAutoLock(&m_csSubPicProvider);
204 if(m_pSubPicProviderEx) {
205 *pSubPicProviderEx = m_pSubPicProviderEx;
206 (*pSubPicProviderEx)->AddRef();
209 return !!*pSubPicProviderEx ? S_OK : E_FAIL;
212 HRESULT CSubPicQueueImpl::RenderTo(ISubPicEx* pSubPic, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double fps, BOOL bIsAnimated)
214 HRESULT hr = E_FAIL;
216 if(!pSubPic) {
217 return hr;
220 CComPtr<ISubPicProviderEx> pSubPicProviderEx;
221 if(FAILED(GetSubPicProviderEx(&pSubPicProviderEx)) || !pSubPicProviderEx) {
222 return hr;
225 if(FAILED(pSubPicProviderEx->Lock())) {
226 return hr;
229 SubPicDesc spd;
230 if(SUCCEEDED(pSubPic->Lock(spd)))
232 DWORD color = 0xFF000000;
233 // if(spd.type == MSP_YUY2 || spd.type == MSP_YV12 || spd.type == MSP_IYUV)
234 // {
235 // color = 0xFF801080;
236 // //color = 0xFF000000;
237 // }
238 // else if(spd.type == MSP_AYUV)
239 // {
240 // color = 0xFF108080;
241 // }
242 // else
243 // {
244 // color = 0xFF000000;
245 // }
246 if(SUCCEEDED(pSubPic->ClearDirtyRect(color)))
248 CAtlList<CRect> rectList;
250 hr = pSubPicProviderEx->RenderEx(spd, bIsAnimated ? rtStart : ((rtStart+rtStop)/2), fps, rectList);
252 DbgLog((LOG_TRACE, 3, "CSubPicQueueImpl::RenderTo => GetStartPosition"));
253 POSITION pos = pSubPicProviderEx->GetStartPosition(rtStart, fps);
255 DbgLog((LOG_TRACE, 3, "CSubPicQueueImpl::RenderTo => GetStartStop rtStart:%lu", (ULONG)rtStart/10000));
256 pSubPicProviderEx->GetStartStop(pos, fps, rtStart, rtStop);
257 DbgLog((LOG_TRACE, 3, "rtStart:%lu", (ULONG)rtStart/10000));
259 //DbgLog((LOG_TRACE, 3, TEXT("rtStart=%lu rtStop=%lu pos:%x fps:%f"), (ULONG)rtStart/10000, (ULONG)rtStop/10000, pos, fps));
261 pSubPic->SetStart(rtStart);
262 pSubPic->SetStop(rtStop);
264 pSubPic->Unlock(&rectList);
268 pSubPicProviderEx->Unlock();
270 return hr;
274 // CSubPicQueue
277 CSubPicQueue::CSubPicQueue(int nMaxSubPic, BOOL bDisableAnim, ISubPicExAllocator* pAllocator, HRESULT* phr)
278 : CSubPicQueueImpl(pAllocator, phr)
279 , m_nMaxSubPic(nMaxSubPic)
280 , m_bDisableAnim(bDisableAnim)
281 , m_rtQueueStart(0)
283 //InitTracer;
284 DbgLog((LOG_TRACE, 3, "CSubPicQueue::CSubPicQueue"));
285 //Trace(_T("SubPicQueue constructing\n"));
287 if(phr && FAILED(*phr))
288 return;
290 if(m_nMaxSubPic < 1)
291 {if(phr) *phr = E_INVALIDARG; return;}
293 m_fBreakBuffering = false;
294 for(int i = 0; i < EVENT_COUNT; i++)
295 m_ThreadEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
296 for(int i=0;i<QueueEvents_COUNT; i++)
297 m_QueueEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
298 if(m_nMaxSubPic > 0)
300 SetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
304 //m_subPos = NULL;
306 CAMThread::Create();
309 CSubPicQueue::~CSubPicQueue()
311 m_fBreakBuffering = true;
312 //SetEvent(m_ThreadEvents[EVENT_EXIT]);
313 CAMThread::CallWorker(EVENT_EXIT);
314 CAMThread::Close();
315 for(int i=0;i<QueueEvents_COUNT; i++)
316 CloseHandle(m_QueueEvents[i]);
317 for(int i = 0; i < EVENT_COUNT; i++)
318 CloseHandle(m_ThreadEvents[i]);
319 DbgLog((LOG_TRACE, 3, "CSubPicQueue::~CSubPicQueue"));
320 //ReleaseTracer;
323 // ISubPicQueue
325 STDMETHODIMP CSubPicQueue::SetFPS(double fps)
327 HRESULT hr = __super::SetFPS(fps);
328 if(FAILED(hr)) return hr;
330 //SetEvent(m_ThreadEvents[EVENT_TIME]);
331 //CallWorker(EVENT_TIME);
332 UpdateQueue();
334 return S_OK;
337 STDMETHODIMP CSubPicQueue::SetTime(REFERENCE_TIME rtNow)
339 HRESULT hr = __super::SetTime(rtNow);
340 if(FAILED(hr)) return hr;
342 //SetEvent(m_ThreadEvents[EVENT_TIME]);
343 //DbgLog((LOG_LOCKING, 3, "SetTime::CallWorker(EVENT_TIME)"));
344 //CallWorker(EVENT_TIME);
345 UpdateQueue();
347 return S_OK;
350 STDMETHODIMP CSubPicQueue::Invalidate(REFERENCE_TIME rtInvalidate)
353 // CAutoLock cQueueLock(&m_csQueueLock);
354 // RemoveAll();
356 m_rtInvalidate = rtInvalidate;
357 m_fBreakBuffering = true;
358 UpdateQueue();
361 return S_OK;
364 STDMETHODIMP_(bool) CSubPicQueue::LookupSubPic(REFERENCE_TIME rtNow, ISubPic** ppSubPic)
366 CComPtr<ISubPicProvider> pSubPicProvider;
367 double fps = m_fps;
368 *ppSubPic = NULL;
369 //if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider)
371 // if(pSubPicProvider->GetStartPosition(rtNow, fps))
373 CAutoLock cQueueLock(&m_csQueueLock);
374 int count = m_Queue.GetCount();
375 if(count>0)
376 if(WaitForSingleObject(m_QueueEvents[QueueEvents_NOTEMPTY], CSUBPICQUEUE_LOOKUP_WAIT_TIMEOUT)==WAIT_OBJECT_0)
378 POSITION pos = m_Queue.GetHeadPosition();
379 while(pos)
381 CComPtr<ISubPic> pSubPic = m_Queue.GetNext(pos);
382 //DbgLog((LOG_TRACE, 3, "picStart:%lu picStop:%lu rtNow:%lu", (ULONG)pSubPic->GetStart()/10000, (ULONG)pSubPic->GetStop()/10000, (ULONG)rtNow/10000));
383 if(pSubPic->GetStart() > rtNow)
384 break;
385 else if(rtNow < pSubPic->GetStop())
387 *ppSubPic = pSubPic.Detach();
388 break;
391 int count = m_Queue.GetCount();
392 if(count>0)
393 SetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
394 else//important
395 ResetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
396 if(count<m_nMaxSubPic)
397 SetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
398 else//important
399 ResetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
401 //DbgLog((LOG_TRACE, 3, "CSubPicQueue LookupSubPic return"));
406 return(!!*ppSubPic);
409 STDMETHODIMP_(bool) CSubPicQueue::LookupSubPic( REFERENCE_TIME now /*[in]*/, ISimpleSubPic** output_subpic/*[out]*/ )
411 //ToDo: fix me
412 return false;
415 STDMETHODIMP CSubPicQueue::GetStats(int& nSubPics, REFERENCE_TIME& rtNow, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
417 CAutoLock cQueueLock(&m_csQueueLock);
419 nSubPics = m_Queue.GetCount();
420 rtNow = m_rtNow;
421 rtStart = m_rtQueueStart;
422 rtStop = m_Queue.GetCount() > 0 ? m_Queue.GetTail()->GetStop() : rtStart;
424 return S_OK;
427 STDMETHODIMP CSubPicQueue::GetStats(int nSubPic, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
429 CAutoLock cQueueLock(&m_csQueueLock);
431 rtStart = rtStop = -1;
433 if(nSubPic >= 0 && nSubPic < (int)m_Queue.GetCount())
435 if(POSITION pos = m_Queue.FindIndex(nSubPic))
437 rtStart = m_Queue.GetAt(pos)->GetStart();
438 rtStop = m_Queue.GetAt(pos)->GetStop();
441 else
443 return E_INVALIDARG;
446 return S_OK;
449 // private
451 REFERENCE_TIME CSubPicQueue::UpdateQueue()
453 //DbgLog((LOG_TRACE, 3, "CSubPicQueue UpdateQueue"));
454 REFERENCE_TIME rtNow=0;
457 //if(WaitForMultipleObjects(QueueEvents_COUNT, m_QueueEvents, true, CSUBPICQUEUE_UPDATEQUEUE_WAIT_TIMEOUT))
459 CAutoLock cQueueLock(&m_csQueueLock);
460 rtNow = m_rtNow;
461 int count = m_Queue.GetCount();
462 if(rtNow < m_rtQueueStart)
464 m_Queue.RemoveAll();
465 count = 0;
467 else
469 while(count>0 && rtNow >= m_Queue.GetHead()->GetStop())
471 m_Queue.RemoveHead();
472 count--;
475 if(count>0)
476 rtNow = m_Queue.GetTail()->GetStop();
477 m_rtQueueStart = m_rtNow;
478 if(count>0)
479 SetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
480 else//important
481 ResetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
482 if(count<m_nMaxSubPic)
483 SetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
484 else//important
485 ResetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
487 return(rtNow);
490 int CSubPicQueue::GetQueueCount()
492 CAutoLock cQueueLock(&m_csQueueLock);
494 return m_Queue.GetCount();
496 void CSubPicQueue::AppendQueue(ISubPic* pSubPic)
498 CAutoLock cQueueLock(&m_csQueueLock);
500 m_Queue.AddTail(pSubPic);
503 // overrides
505 DWORD CSubPicQueue::ThreadProc()
507 BOOL bDisableAnim = m_bDisableAnim;
508 SetThreadPriority(m_hThread, bDisableAnim ? THREAD_PRIORITY_LOWEST : THREAD_PRIORITY_ABOVE_NORMAL/*THREAD_PRIORITY_BELOW_NORMAL*/);
510 //Trace(_T("CSubPicQueue Thread Start\n"));
511 DbgLog((LOG_TRACE, 3, "CSubPicQueue Thread Start"));
512 //while((WaitForMultipleObjects(EVENT_COUNT, m_ThreadEvents, FALSE, INFINITE) - WAIT_OBJECT_0) == EVENT_TIME)
513 DWORD request;
514 while(true)
516 if(CheckRequest(&request))
518 if(request==EVENT_EXIT)
519 break;
522 if(WaitForSingleObject(m_QueueEvents[QueueEvents_NOTFULL], CSUBPICQUEUE_THREAD_PROC_WAIT_TIMEOUT)!=WAIT_OBJECT_0)
523 continue;
525 bool failed = true;
526 bool reachEnd = false;
527 CComPtr<ISubPicEx> pSubPic;
528 CComPtr<ISubPicEx> pStatic;
529 CComPtr<ISubPicProviderEx> pSubPicProviderEx;
531 double fps = m_fps;
532 int nMaxSubPic = m_nMaxSubPic;
534 m_csQueueLock.Lock();
535 REFERENCE_TIME rtNow = 0;
536 if(m_Queue.GetCount()>0)
537 rtNow = m_Queue.GetTail()->GetStop();
538 if(rtNow < m_rtNow)
539 rtNow = m_rtNow;
540 CComPtr<ISubPicExAllocator> pAllocator = m_pAllocator;
541 m_csQueueLock.Unlock();
543 //for(int i=0;i<1;i++)
545 if(FAILED(pAllocator->AllocDynamicEx(&pSubPic))
546 || (pAllocator->IsDynamicWriteOnly() && FAILED(pAllocator->GetStaticEx(&pStatic))))
547 break;
549 if(SUCCEEDED(GetSubPicProviderEx(&pSubPicProviderEx)) && pSubPicProviderEx
550 && SUCCEEDED(pSubPicProviderEx->Lock()))
552 REFERENCE_TIME rtStart, rtStop;
554 //DbgLog((LOG_TRACE, 3, "CSubPicQueue::ThreadProc => GetStartPosition"));
555 POSITION pos = pSubPicProviderEx->GetStartPosition(rtNow, fps);
557 //DbgLog((LOG_TRACE, 3, "pos:%x, m_fBreakBuffering:%d GetCount():%d nMaxSubPic:%d", pos, m_fBreakBuffering, GetCount(), nMaxSubPic));
559 if(pos!=NULL)//!m_fBreakBuffering
561 reachEnd = false;
562 ASSERT(m_Queue.GetCount() < (size_t)nMaxSubPic);
564 //DbgLog((LOG_TRACE, 3, "CSubPicQueue::ThreadProc => GetStartStop"));
565 pSubPicProviderEx->GetStartStop(pos, fps, rtStart, rtStop);
567 //DbgLog((LOG_TRACE, 3, "rtStart=%lu rtStop=%lu fps=%f rtNow=%lu m_rtNow=%lu", (ULONG)rtStart/10000, (ULONG)rtStop/10000,
568 // fps, (ULONG)rtNow/10000, (ULONG)m_rtNow/10000));
570 if(m_rtNow >= rtStop)
571 break;
572 //if(rtStart >= m_rtNow + 60*10000000i64) // we are already one minute ahead, this should be enough
573 // break;
575 if(rtNow < rtStop)
577 bool bIsAnimated = pSubPicProviderEx->IsAnimated(pos) && !bDisableAnim;
578 if(pAllocator->IsDynamicWriteOnly())
579 //if(true)
581 HRESULT hr = RenderTo(pStatic, rtStart, rtStop, fps, bIsAnimated);
582 if(FAILED(hr)
583 || S_OK != hr// subpic was probably empty
584 || FAILED(pStatic->CopyTo(pSubPic))
586 break;
588 else
590 HRESULT hr = RenderTo(pSubPic, rtStart, rtStop, fps, bIsAnimated);
591 if(FAILED(hr)
592 || S_OK != hr// subpic was probably empty
594 break;
596 /*DbgLog((LOG_TRACE, 3, "picStart:%lu picStop:%lu seg:%d idx:%d pos:%x",
597 (ULONG)pSubPic->GetStart()/10000,
598 (ULONG)pSubPic->GetStop()/10000,
599 (int)pos >> 16, (int)pos & ((1<<16)-1)));*/
600 failed = false;
603 else
604 reachEnd = true;
605 pSubPicProviderEx->Unlock();
606 pSubPicProviderEx = NULL;
610 m_csQueueLock.Lock();
611 if(!failed)
612 m_Queue.AddTail(pSubPic);
613 int count = m_Queue.GetCount();
614 if(count>0)
615 SetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
616 else//important
617 ResetEvent(m_QueueEvents[QueueEvents_NOTEMPTY]);
618 if(count<m_nMaxSubPic)
619 SetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
620 else//important
621 ResetEvent(m_QueueEvents[QueueEvents_NOTFULL]);
622 m_csQueueLock.Unlock();
624 if(reachEnd)
625 Sleep(CSUBPICQUEUE_THREAD_PROC_WAIT_TIMEOUT);
627 //if(failed)
629 // if(pSubPicProvider!=NULL)
630 // pSubPicProvider->Unlock();
631 // ReleaseSemaphore(m_semNotFull, 1, NULL);
633 //else
634 // ReleaseSemaphore(m_semNotEmpty, 1, NULL);
636 //DbgLog((LOG_LOCKING, 3, "ReleaseMutex m_mtxResetNotFull"));
637 //ReleaseMutex(m_mtxResetNotFull);
640 //Trace(_T("CSubPicQueue Thread Return\n"));
641 DbgLog((LOG_TRACE, 3, "CSubPicQueue Thread Return"));
642 Reply(EVENT_EXIT);
643 return(0);
647 // CSubPicQueueNoThread
650 CSubPicQueueNoThread::CSubPicQueueNoThread(ISubPicExAllocator* pAllocator, HRESULT* phr, const int *prefered_colortype/*=NULL*/, int prefered_colortype_num/*=0*/)
651 : CSubPicQueueImpl(pAllocator, phr, prefered_colortype, prefered_colortype_num)
655 CSubPicQueueNoThread::~CSubPicQueueNoThread()
659 // ISubPicQueue
661 STDMETHODIMP CSubPicQueueNoThread::Invalidate(REFERENCE_TIME rtInvalidate)
663 CAutoLock cQueueLock(&m_csLock);
665 if( m_pSubPic && m_pSubPic->GetStop() >= rtInvalidate)
667 m_pSubPic = NULL;
669 return S_OK;
672 STDMETHODIMP_(bool) CSubPicQueueNoThread::LookupSubPic(REFERENCE_TIME rtNow, ISubPic** ppSubPic)
674 if(ppSubPic!=NULL)
676 ISubPicEx* temp;
677 bool result = LookupSubPicEx(rtNow, &temp);
678 *ppSubPic = temp;
679 return result;
681 else
683 return LookupSubPicEx(rtNow, NULL);
687 STDMETHODIMP_(bool) CSubPicQueueNoThread::LookupSubPic( REFERENCE_TIME now /*[in]*/, ISimpleSubPic** output_subpic /*[out]*/ )
689 if(output_subpic!=NULL)
691 CComPtr<ISubPicEx> temp;
692 bool result = LookupSubPicEx(now, &temp);
693 (*output_subpic = new SimpleSubPicWrapper(temp))->AddRef();
694 return result;
696 else
698 return LookupSubPicEx(now, NULL);
703 bool CSubPicQueueNoThread::LookupSubPicEx(REFERENCE_TIME rtNow, ISubPicEx** ppSubPic)
705 if(!ppSubPic)
706 return(false);
708 *ppSubPic = NULL;
710 CComPtr<ISubPicEx> pSubPic;
713 CAutoLock cAutoLock(&m_csLock);
715 if(!m_pSubPic)
717 if(FAILED(m_pAllocator->AllocDynamicEx(&m_pSubPic))) {
718 return false;
722 pSubPic = m_pSubPic;
725 if(pSubPic->GetStart() <= rtNow && rtNow < pSubPic->GetStop())
727 (*ppSubPic = pSubPic)->AddRef();
729 else
731 CComPtr<ISubPicProvider> pSubPicProvider;
732 if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider
733 && SUCCEEDED(pSubPicProvider->Lock()))
735 double fps = m_fps;
737 if(POSITION pos = pSubPicProvider->GetStartPosition(rtNow, fps))
739 REFERENCE_TIME rtStart = pSubPicProvider->GetStart(pos, fps);
740 REFERENCE_TIME rtStop = pSubPicProvider->GetStop(pos, fps);
742 if(rtStart <= rtNow && rtNow < rtStop)
744 SIZE MaxTextureSize, VirtualSize;
745 POINT VirtualTopLeft;
746 HRESULT hr2;
747 if (SUCCEEDED (hr2 = pSubPicProvider->GetTextureSize(pos, MaxTextureSize, VirtualSize, VirtualTopLeft))) {
748 m_pAllocator->SetMaxTextureSize(MaxTextureSize);
750 if(m_pAllocator->IsDynamicWriteOnly())
752 CComPtr<ISubPicEx> pStatic;
753 if(SUCCEEDED(m_pAllocator->GetStaticEx(&pStatic))
754 && SUCCEEDED(RenderTo(pStatic, rtNow, rtNow+1, fps, true))
755 && SUCCEEDED(pStatic->CopyTo(pSubPic)))
756 (*ppSubPic = pSubPic)->AddRef();
758 else
760 if(SUCCEEDED(RenderTo(m_pSubPic, rtNow, rtNow+1, fps, true)))
761 (*ppSubPic = pSubPic)->AddRef();
766 pSubPicProvider->Unlock();
768 if(*ppSubPic)
770 CAutoLock cAutoLock(&m_csLock);
772 m_pSubPic = *ppSubPic;
776 return(!!*ppSubPic);
779 STDMETHODIMP CSubPicQueueNoThread::GetStats(int& nSubPics, REFERENCE_TIME& rtNow, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
781 CAutoLock cAutoLock(&m_csLock);
783 nSubPics = 0;
784 rtNow = m_rtNow;
785 rtStart = rtStop = 0;
787 if(m_pSubPic)
789 nSubPics = 1;
790 rtStart = m_pSubPic->GetStart();
791 rtStop = m_pSubPic->GetStop();
794 return S_OK;
797 STDMETHODIMP CSubPicQueueNoThread::GetStats(int nSubPic, REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop)
799 CAutoLock cAutoLock(&m_csLock);
801 if(!m_pSubPic || nSubPic != 0)
802 return E_INVALIDARG;
804 rtStart = m_pSubPic->GetStart();
805 rtStop = m_pSubPic->GetStop();
807 return S_OK;