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)
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
23 #include "SubPicQueueImpl.h"
24 #include "../DSUtil/DSUtil.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
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
)
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
)
76 QI(ISimpleSubPicProvider
)
77 __super::NonDelegatingQueryInterface(riid
, ppv
);
82 STDMETHODIMP
CSubPicQueueImpl::SetSubPicProvider(ISubPicProvider
* pSubPicProvider
)
84 if (pSubPicProvider
!=NULL
)
86 return SetSubPicProviderEx( CSubPicProviderExWrapper::GetSubPicProviderExWrapper(pSubPicProvider
) );
90 return SetSubPicProviderEx( NULL
);
94 STDMETHODIMP
CSubPicQueueImpl::GetSubPicProvider(ISubPicProvider
** pSubPicProvider
)
96 if(!pSubPicProvider
) {
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
)
117 STDMETHODIMP
CSubPicQueueImpl::SetTime(REFERENCE_TIME rtNow
)
126 STDMETHODIMP
CSubPicQueueImpl::SetSubPicProvider( IUnknown
* subpic_provider
)
128 if (subpic_provider
!=NULL
)
130 CComQIPtr
<ISubPicProviderEx
> tmp
= subpic_provider
;
133 return SetSubPicProviderEx(tmp
);
137 CComQIPtr
<ISubPicProvider
> tmp2
= subpic_provider
;
140 return SetSubPicProvider(tmp
);
147 return SetSubPicProviderEx(NULL
);
151 STDMETHODIMP
CSubPicQueueImpl::GetSubPicProvider( IUnknown
** subpic_provider
)
153 if(!subpic_provider
) {
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
;
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();
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
);
196 HRESULT
CSubPicQueueImpl::GetSubPicProviderEx( ISubPicProviderEx
** pSubPicProviderEx
)
198 if(!pSubPicProviderEx
) {
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
)
220 CComPtr
<ISubPicProviderEx
> pSubPicProviderEx
;
221 if(FAILED(GetSubPicProviderEx(&pSubPicProviderEx
)) || !pSubPicProviderEx
) {
225 if(FAILED(pSubPicProviderEx
->Lock())) {
230 if(SUCCEEDED(pSubPic
->Lock(spd
)))
232 DWORD color
= 0xFF000000;
233 // if(spd.type == MSP_YUY2 || spd.type == MSP_YV12 || spd.type == MSP_IYUV)
235 // color = 0xFF801080;
236 // //color = 0xFF000000;
238 // else if(spd.type == MSP_AYUV)
240 // color = 0xFF108080;
244 // color = 0xFF000000;
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();
277 CSubPicQueue::CSubPicQueue(int nMaxSubPic
, BOOL bDisableAnim
, ISubPicExAllocator
* pAllocator
, HRESULT
* phr
)
278 : CSubPicQueueImpl(pAllocator
, phr
)
279 , m_nMaxSubPic(nMaxSubPic
)
280 , m_bDisableAnim(bDisableAnim
)
284 DbgLog((LOG_TRACE
, 3, "CSubPicQueue::CSubPicQueue"));
285 //Trace(_T("SubPicQueue constructing\n"));
287 if(phr
&& FAILED(*phr
))
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
);
300 SetEvent(m_QueueEvents
[QueueEvents_NOTFULL
]);
309 CSubPicQueue::~CSubPicQueue()
311 m_fBreakBuffering
= true;
312 //SetEvent(m_ThreadEvents[EVENT_EXIT]);
313 CAMThread::CallWorker(EVENT_EXIT
);
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"));
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);
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);
350 STDMETHODIMP
CSubPicQueue::Invalidate(REFERENCE_TIME rtInvalidate
)
353 // CAutoLock cQueueLock(&m_csQueueLock);
356 m_rtInvalidate
= rtInvalidate
;
357 m_fBreakBuffering
= true;
364 STDMETHODIMP_(bool) CSubPicQueue::LookupSubPic(REFERENCE_TIME rtNow
, ISubPic
** ppSubPic
)
366 CComPtr
<ISubPicProvider
> pSubPicProvider
;
369 //if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider)) && pSubPicProvider)
371 // if(pSubPicProvider->GetStartPosition(rtNow, fps))
373 CAutoLock
cQueueLock(&m_csQueueLock
);
374 int count
= m_Queue
.GetCount();
376 if(WaitForSingleObject(m_QueueEvents
[QueueEvents_NOTEMPTY
], CSUBPICQUEUE_LOOKUP_WAIT_TIMEOUT
)==WAIT_OBJECT_0
)
378 POSITION pos
= m_Queue
.GetHeadPosition();
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
)
385 else if(rtNow
< pSubPic
->GetStop())
387 *ppSubPic
= pSubPic
.Detach();
391 int count
= m_Queue
.GetCount();
393 SetEvent(m_QueueEvents
[QueueEvents_NOTEMPTY
]);
395 ResetEvent(m_QueueEvents
[QueueEvents_NOTEMPTY
]);
396 if(count
<m_nMaxSubPic
)
397 SetEvent(m_QueueEvents
[QueueEvents_NOTFULL
]);
399 ResetEvent(m_QueueEvents
[QueueEvents_NOTFULL
]);
401 //DbgLog((LOG_TRACE, 3, "CSubPicQueue LookupSubPic return"));
409 STDMETHODIMP_(bool) CSubPicQueue::LookupSubPic( REFERENCE_TIME now
/*[in]*/, ISimpleSubPic
** output_subpic
/*[out]*/ )
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();
421 rtStart
= m_rtQueueStart
;
422 rtStop
= m_Queue
.GetCount() > 0 ? m_Queue
.GetTail()->GetStop() : rtStart
;
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();
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
);
461 int count
= m_Queue
.GetCount();
462 if(rtNow
< m_rtQueueStart
)
469 while(count
>0 && rtNow
>= m_Queue
.GetHead()->GetStop())
471 m_Queue
.RemoveHead();
476 rtNow
= m_Queue
.GetTail()->GetStop();
477 m_rtQueueStart
= m_rtNow
;
479 SetEvent(m_QueueEvents
[QueueEvents_NOTEMPTY
]);
481 ResetEvent(m_QueueEvents
[QueueEvents_NOTEMPTY
]);
482 if(count
<m_nMaxSubPic
)
483 SetEvent(m_QueueEvents
[QueueEvents_NOTFULL
]);
485 ResetEvent(m_QueueEvents
[QueueEvents_NOTFULL
]);
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
);
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)
516 if(CheckRequest(&request
))
518 if(request
==EVENT_EXIT
)
522 if(WaitForSingleObject(m_QueueEvents
[QueueEvents_NOTFULL
], CSUBPICQUEUE_THREAD_PROC_WAIT_TIMEOUT
)!=WAIT_OBJECT_0
)
526 bool reachEnd
= false;
527 CComPtr
<ISubPicEx
> pSubPic
;
528 CComPtr
<ISubPicEx
> pStatic
;
529 CComPtr
<ISubPicProviderEx
> pSubPicProviderEx
;
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();
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
))))
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
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
)
572 //if(rtStart >= m_rtNow + 60*10000000i64) // we are already one minute ahead, this should be enough
577 bool bIsAnimated
= pSubPicProviderEx
->IsAnimated(pos
) && !bDisableAnim
;
578 if(pAllocator
->IsDynamicWriteOnly())
581 HRESULT hr
= RenderTo(pStatic
, rtStart
, rtStop
, fps
, bIsAnimated
);
583 || S_OK
!= hr
// subpic was probably empty
584 || FAILED(pStatic
->CopyTo(pSubPic
))
590 HRESULT hr
= RenderTo(pSubPic
, rtStart
, rtStop
, fps
, bIsAnimated
);
592 || S_OK
!= hr
// subpic was probably empty
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)));*/
605 pSubPicProviderEx
->Unlock();
606 pSubPicProviderEx
= NULL
;
610 m_csQueueLock
.Lock();
612 m_Queue
.AddTail(pSubPic
);
613 int count
= m_Queue
.GetCount();
615 SetEvent(m_QueueEvents
[QueueEvents_NOTEMPTY
]);
617 ResetEvent(m_QueueEvents
[QueueEvents_NOTEMPTY
]);
618 if(count
<m_nMaxSubPic
)
619 SetEvent(m_QueueEvents
[QueueEvents_NOTFULL
]);
621 ResetEvent(m_QueueEvents
[QueueEvents_NOTFULL
]);
622 m_csQueueLock
.Unlock();
625 Sleep(CSUBPICQUEUE_THREAD_PROC_WAIT_TIMEOUT
);
629 // if(pSubPicProvider!=NULL)
630 // pSubPicProvider->Unlock();
631 // ReleaseSemaphore(m_semNotFull, 1, NULL);
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"));
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()
661 STDMETHODIMP
CSubPicQueueNoThread::Invalidate(REFERENCE_TIME rtInvalidate
)
663 CAutoLock
cQueueLock(&m_csLock
);
665 if( m_pSubPic
&& m_pSubPic
->GetStop() >= rtInvalidate
)
672 STDMETHODIMP_(bool) CSubPicQueueNoThread::LookupSubPic(REFERENCE_TIME rtNow
, ISubPic
** ppSubPic
)
677 bool result
= LookupSubPicEx(rtNow
, &temp
);
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();
698 return LookupSubPicEx(now
, NULL
);
703 bool CSubPicQueueNoThread::LookupSubPicEx(REFERENCE_TIME rtNow
, ISubPicEx
** ppSubPic
)
710 CComPtr
<ISubPicEx
> pSubPic
;
713 CAutoLock
cAutoLock(&m_csLock
);
717 if(FAILED(m_pAllocator
->AllocDynamicEx(&m_pSubPic
))) {
725 if(pSubPic
->GetStart() <= rtNow
&& rtNow
< pSubPic
->GetStop())
727 (*ppSubPic
= pSubPic
)->AddRef();
731 CComPtr
<ISubPicProvider
> pSubPicProvider
;
732 if(SUCCEEDED(GetSubPicProvider(&pSubPicProvider
)) && pSubPicProvider
733 && SUCCEEDED(pSubPicProvider
->Lock()))
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
;
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();
760 if(SUCCEEDED(RenderTo(m_pSubPic
, rtNow
, rtNow
+1, fps
, true)))
761 (*ppSubPic
= pSubPic
)->AddRef();
766 pSubPicProvider
->Unlock();
770 CAutoLock
cAutoLock(&m_csLock
);
772 m_pSubPic
= *ppSubPic
;
779 STDMETHODIMP
CSubPicQueueNoThread::GetStats(int& nSubPics
, REFERENCE_TIME
& rtNow
, REFERENCE_TIME
& rtStart
, REFERENCE_TIME
& rtStop
)
781 CAutoLock
cAutoLock(&m_csLock
);
785 rtStart
= rtStop
= 0;
790 rtStart
= m_pSubPic
->GetStart();
791 rtStop
= m_pSubPic
->GetStop();
797 STDMETHODIMP
CSubPicQueueNoThread::GetStats(int nSubPic
, REFERENCE_TIME
& rtStart
, REFERENCE_TIME
& rtStop
)
799 CAutoLock
cAutoLock(&m_csLock
);
801 if(!m_pSubPic
|| nSubPic
!= 0)
804 rtStart
= m_pSubPic
->GetStart();
805 rtStop
= m_pSubPic
->GetStop();