AJA NTV2 SDK  18.0.0.2717
NTV2 SDK 18.0.0.2717
outputq.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // File: OutputQ.cpp
3 //
4 // Desc: DirectShow base classes - implements COutputQueue class used by an
5 // output pin which may sometimes want to queue output samples on a
6 // separate thread and sometimes call Receive() directly on the input
7 // pin.
8 //
9 // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
10 //------------------------------------------------------------------------------
11 
12 
13 #include <streams.h>
14 
15 
16 //
17 // COutputQueue Constructor :
18 //
19 // Determines if a thread is to be created and creates resources
20 //
21 // pInputPin - the downstream input pin we're queueing samples to
22 //
23 // phr - changed to a failure code if this function fails
24 // (otherwise unchanges)
25 //
26 // bAuto - Ask pInputPin if it can block in Receive by calling
27 // its ReceiveCanBlock method and create a thread if
28 // it can block, otherwise not.
29 //
30 // bQueue - if bAuto == FALSE then we create a thread if and only
31 // if bQueue == TRUE
32 //
33 // lBatchSize - work in batches of lBatchSize
34 //
35 // bBatchEact - Use exact batch sizes so don't send until the
36 // batch is full or SendAnyway() is called
37 //
38 // lListSize - If we create a thread make the list of samples queued
39 // to the thread have this size cache
40 //
41 // dwPriority - If we create a thread set its priority to this
42 //
44  IPin *pInputPin, // Pin to send stuff to
45  __inout HRESULT *phr, // 'Return code'
46  BOOL bAuto, // Ask pin if queue or not
47  BOOL bQueue, // Send through queue
48  LONG lBatchSize, // Batch
49  BOOL bBatchExact, // Batch exactly to BatchSize
50  LONG lListSize,
51  DWORD dwPriority,
52  bool bFlushingOpt // flushing optimization
53  ) : m_lBatchSize(lBatchSize),
54  m_bBatchExact(bBatchExact && (lBatchSize > 1)),
55  m_hThread(NULL),
56  m_hSem(NULL),
57  m_List(NULL),
58  m_pPin(pInputPin),
59  m_ppSamples(NULL),
60  m_lWaiting(0),
61  m_evFlushComplete(FALSE, phr),
62  m_pInputPin(NULL),
63  m_bSendAnyway(FALSE),
64  m_nBatched(0),
65  m_bFlushing(FALSE),
66  m_bFlushed(TRUE),
67  m_bFlushingOpt(bFlushingOpt),
68  m_bTerminate(FALSE),
69  m_hEventPop(NULL),
70  m_hr(S_OK)
71 {
72  ASSERT(m_lBatchSize > 0);
73 
74 
75  if (FAILED(*phr)) {
76  return;
77  }
78 
79  // Check the input pin is OK and cache its IMemInputPin interface
80 
81  *phr = pInputPin->QueryInterface(IID_IMemInputPin, (void **)&m_pInputPin);
82  if (FAILED(*phr)) {
83  return;
84  }
85 
86  // See if we should ask the downstream pin
87 
88  if (bAuto) {
89  HRESULT hr = m_pInputPin->ReceiveCanBlock();
90  if (SUCCEEDED(hr)) {
91  bQueue = hr == S_OK;
92  }
93  }
94 
95  // Create our sample batch
96 
97  m_ppSamples = new PMEDIASAMPLE[m_lBatchSize];
98  if (m_ppSamples == NULL) {
99  *phr = E_OUTOFMEMORY;
100  return;
101  }
102 
103  // If we're queueing allocate resources
104 
105  if (bQueue) {
106  DbgLog((LOG_TRACE, 2, TEXT("Creating thread for output pin")));
107  m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
108  if (m_hSem == NULL) {
109  DWORD dwError = GetLastError();
110  *phr = AmHresultFromWin32(dwError);
111  return;
112  }
113  m_List = new CSampleList(NAME("Sample Queue List"),
114  lListSize,
115  FALSE // No lock
116  );
117  if (m_List == NULL) {
118  *phr = E_OUTOFMEMORY;
119  return;
120  }
121 
122 
123  DWORD dwThreadId;
124  m_hThread = CreateThread(NULL,
125  0,
127  (LPVOID)this,
128  0,
129  &dwThreadId);
130  if (m_hThread == NULL) {
131  DWORD dwError = GetLastError();
132  *phr = AmHresultFromWin32(dwError);
133  return;
134  }
135  SetThreadPriority(m_hThread, dwPriority);
136  } else {
137  DbgLog((LOG_TRACE, 2, TEXT("Calling input pin directly - no thread")));
138  }
139 }
140 
141 //
142 // COutputQueuee Destructor :
143 //
144 // Free all resources -
145 //
146 // Thread,
147 // Batched samples
148 //
150 {
151  DbgLog((LOG_TRACE, 3, TEXT("COutputQueue::~COutputQueue")));
152  /* Free our pointer */
153  if (m_pInputPin != NULL) {
154  m_pInputPin->Release();
155  }
156  if (m_hThread != NULL) {
157  {
158  CAutoLock lck(this);
159  m_bTerminate = TRUE;
160  m_hr = S_FALSE;
161  NotifyThread();
162  }
164  EXECUTE_ASSERT(CloseHandle(m_hThread));
165 
166  // The thread frees the samples when asked to terminate
167 
168  ASSERT(m_List->GetCount() == 0);
169  delete m_List;
170  } else {
171  FreeSamples();
172  }
173  if (m_hSem != NULL) {
174  EXECUTE_ASSERT(CloseHandle(m_hSem));
175  }
176  delete [] m_ppSamples;
177 }
178 
179 //
180 // Call the real thread proc as a member function
181 //
182 DWORD WINAPI COutputQueue::InitialThreadProc(__in LPVOID pv)
183 {
184  HRESULT hrCoInit = CAMThread::CoInitializeHelper();
185 
186  COutputQueue *pSampleQueue = (COutputQueue *)pv;
187  DWORD dwReturn = pSampleQueue->ThreadProc();
188 
189  if(hrCoInit == S_OK) {
190  CoUninitialize();
191  }
192 
193  return dwReturn;
194 }
195 
196 //
197 // Thread sending the samples downstream :
198 //
199 // When there is nothing to do the thread sets m_lWaiting (while
200 // holding the critical section) and then waits for m_hSem to be
201 // set (not holding the critical section)
202 //
204 {
205  while (TRUE) {
206  BOOL bWait = FALSE;
207  IMediaSample *pSample;
208  LONG lNumberToSend; // Local copy
209  NewSegmentPacket* ppacket;
210 
211  //
212  // Get a batch of samples and send it if possible
213  // In any case exit the loop if there is a control action
214  // requested
215  //
216  {
217  CAutoLock lck(this);
218  while (TRUE) {
219 
220  if (m_bTerminate) {
221  FreeSamples();
222  return 0;
223  }
224  if (m_bFlushing) {
225  FreeSamples();
226  SetEvent(m_evFlushComplete);
227  }
228 
229  // Get a sample off the list
230 
231  pSample = m_List->RemoveHead();
232  // inform derived class we took something off the queue
233  if (m_hEventPop) {
234  //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
235  SetEvent(m_hEventPop);
236  }
237 
238  if (pSample != NULL &&
239  !IsSpecialSample(pSample)) {
240 
241  // If its just a regular sample just add it to the batch
242  // and exit the loop if the batch is full
243 
244  m_ppSamples[m_nBatched++] = pSample;
245  if (m_nBatched == m_lBatchSize) {
246  break;
247  }
248  } else {
249 
250  // If there was nothing in the queue and there's nothing
251  // to send (either because there's nothing or the batch
252  // isn't full) then prepare to wait
253 
254  if (pSample == NULL &&
255  (m_bBatchExact || m_nBatched == 0)) {
256 
257  // Tell other thread to set the event when there's
258  // something do to
259 
260  ASSERT(m_lWaiting == 0);
261  m_lWaiting++;
262  bWait = TRUE;
263  } else {
264 
265  // We break out of the loop on SEND_PACKET unless
266  // there's nothing to send
267 
268  if (pSample == SEND_PACKET && m_nBatched == 0) {
269  continue;
270  }
271 
272  if (pSample == NEW_SEGMENT) {
273  // now we need the parameters - we are
274  // guaranteed that the next packet contains them
275  ppacket = (NewSegmentPacket *) m_List->RemoveHead();
276  // we took something off the queue
277  if (m_hEventPop) {
278  //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
279  SetEvent(m_hEventPop);
280  }
281 
282  ASSERT(ppacket);
283  }
284  // EOS_PACKET falls through here and we exit the loop
285  // In this way it acts like SEND_PACKET
286  }
287  break;
288  }
289  }
290  if (!bWait) {
291  // We look at m_nBatched from the client side so keep
292  // it up to date inside the critical section
293  lNumberToSend = m_nBatched; // Local copy
294  m_nBatched = 0;
295  }
296  }
297 
298  // Wait for some more data
299 
300  if (bWait) {
302  continue;
303  }
304 
305 
306 
307  // OK - send it if there's anything to send
308  // We DON'T check m_bBatchExact here because either we've got
309  // a full batch or we dropped through because we got
310  // SEND_PACKET or EOS_PACKET - both of which imply we should
311  // flush our batch
312 
313  if (lNumberToSend != 0) {
314  long nProcessed;
315  if (m_hr == S_OK) {
316  ASSERT(!m_bFlushed);
317  HRESULT hr = m_pInputPin->ReceiveMultiple(m_ppSamples,
318  lNumberToSend,
319  &nProcessed);
320  /* Don't overwrite a flushing state HRESULT */
321  CAutoLock lck(this);
322  if (m_hr == S_OK) {
323  m_hr = hr;
324  }
325  ASSERT(!m_bFlushed);
326  }
327  while (lNumberToSend != 0) {
328  m_ppSamples[--lNumberToSend]->Release();
329  }
330  if (m_hr != S_OK) {
331 
332  // In any case wait for more data - S_OK just
333  // means there wasn't an error
334 
335  DbgLog((LOG_ERROR, 2, TEXT("ReceiveMultiple returned %8.8X"),
336  m_hr));
337  }
338  }
339 
340  // Check for end of stream
341 
342  if (pSample == EOS_PACKET) {
343 
344  // We don't send even end of stream on if we've previously
345  // returned something other than S_OK
346  // This is because in that case the pin which returned
347  // something other than S_OK should have either sent
348  // EndOfStream() or notified the filter graph
349 
350  if (m_hr == S_OK) {
351  DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()")));
352  HRESULT hr = m_pPin->EndOfStream();
353  if (FAILED(hr)) {
354  DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()")));
355  }
356  }
357  }
358 
359  // Data from a new source
360 
361  if (pSample == RESET_PACKET) {
362  m_hr = S_OK;
363  SetEvent(m_evFlushComplete);
364  }
365 
366  if (pSample == NEW_SEGMENT) {
367  m_pPin->NewSegment(ppacket->tStart, ppacket->tStop, ppacket->dRate);
368  delete ppacket;
369  }
370  }
371 }
372 
373 // Send batched stuff anyway
375 {
376  if (!IsQueued()) {
377 
378  // m_bSendAnyway is a private parameter checked in ReceiveMultiple
379 
380  m_bSendAnyway = TRUE;
381  LONG nProcessed;
382  ReceiveMultiple(NULL, 0, &nProcessed);
383  m_bSendAnyway = FALSE;
384 
385  } else {
386  CAutoLock lck(this);
388  NotifyThread();
389  }
390 }
391 
392 void
394  REFERENCE_TIME tStart,
395  REFERENCE_TIME tStop,
396  double dRate)
397 {
398  if (!IsQueued()) {
399  if (S_OK == m_hr) {
400  if (m_bBatchExact) {
401  SendAnyway();
402  }
403  m_pPin->NewSegment(tStart, tStop, dRate);
404  }
405  } else {
406  if (m_hr == S_OK) {
407  //
408  // we need to queue the new segment to appear in order in the
409  // data, but we need to pass parameters to it. Rather than
410  // take the hit of wrapping every single sample so we can tell
411  // special ones apart, we queue special pointers to indicate
412  // special packets, and we guarantee (by holding the
413  // critical section) that the packet immediately following a
414  // NEW_SEGMENT value is a NewSegmentPacket containing the
415  // parameters.
416  NewSegmentPacket * ppack = new NewSegmentPacket;
417  if (ppack == NULL) {
418  return;
419  }
420  ppack->tStart = tStart;
421  ppack->tStop = tStop;
422  ppack->dRate = dRate;
423 
424  CAutoLock lck(this);
426  QueueSample( (IMediaSample*) ppack);
427  NotifyThread();
428  }
429  }
430 }
431 
432 
433 //
434 // End of Stream is queued to output device
435 //
437 {
438  CAutoLock lck(this);
439  if (!IsQueued()) {
440  if (m_bBatchExact) {
441  SendAnyway();
442  }
443  if (m_hr == S_OK) {
444  DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()")));
445  m_bFlushed = FALSE;
446  HRESULT hr = m_pPin->EndOfStream();
447  if (FAILED(hr)) {
448  DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()")));
449  }
450  }
451  } else {
452  if (m_hr == S_OK) {
453  m_bFlushed = FALSE;
455  NotifyThread();
456  }
457  }
458 }
459 
460 //
461 // Flush all the samples in the queue
462 //
464 {
465  if (IsQueued()) {
466  {
467  CAutoLock lck(this);
468 
469  // block receives -- we assume this is done by the
470  // filter in which we are a component
471 
472  // discard all queued data
473 
474  m_bFlushing = TRUE;
475 
476  // Make sure we discard all samples from now on
477 
478  if (m_hr == S_OK) {
479  m_hr = S_FALSE;
480  }
481 
482  // Optimize so we don't keep calling downstream all the time
483 
484  if (m_bFlushed && m_bFlushingOpt) {
485  return;
486  }
487 
488  // Make sure we really wait for the flush to complete
490 
491  NotifyThread();
492  }
493 
494  // pass this downstream
495 
496  m_pPin->BeginFlush();
497  } else {
498  // pass downstream first to avoid deadlocks
499  m_pPin->BeginFlush();
500  CAutoLock lck(this);
501  // discard all queued data
502 
503  m_bFlushing = TRUE;
504 
505  // Make sure we discard all samples from now on
506 
507  if (m_hr == S_OK) {
508  m_hr = S_FALSE;
509  }
510  }
511 
512 }
513 
514 //
515 // leave flush mode - pass this downstream
517 {
518  {
519  CAutoLock lck(this);
521  if (m_bFlushingOpt && m_bFlushed && IsQueued()) {
522  m_bFlushing = FALSE;
523  m_hr = S_OK;
524  return;
525  }
526  }
527 
528  // sync with pushing thread -- done in BeginFlush
529  // ensure no more data to go downstream -- done in BeginFlush
530  //
531  // Because we are synching here there is no need to hold the critical
532  // section (in fact we'd deadlock if we did!)
533 
534  if (IsQueued()) {
536  } else {
537  FreeSamples();
538  }
539 
540  // Be daring - the caller has guaranteed no samples will arrive
541  // before EndFlush() returns
542 
543  m_bFlushing = FALSE;
544  m_bFlushed = TRUE;
545 
546  // call EndFlush on downstream pins
547 
548  m_pPin->EndFlush();
549 
550  m_hr = S_OK;
551 }
552 
553 // COutputQueue::QueueSample
554 //
555 // private method to Send a sample to the output queue
556 // The critical section MUST be held when this is called
557 
558 void COutputQueue::QueueSample(IMediaSample *pSample)
559 {
560  if (NULL == m_List->AddTail(pSample)) {
561  if (!IsSpecialSample(pSample)) {
562  pSample->Release();
563  }
564  }
565 }
566 
567 //
568 // COutputQueue::Receive()
569 //
570 // Send a single sample by the multiple sample route
571 // (NOTE - this could be optimized if necessary)
572 //
573 // On return the sample will have been Release()'d
574 //
575 
576 HRESULT COutputQueue::Receive(IMediaSample *pSample)
577 {
578  LONG nProcessed;
579  return ReceiveMultiple(&pSample, 1, &nProcessed);
580 }
581 
582 //
583 // COutputQueue::ReceiveMultiple()
584 //
585 // Send a set of samples to the downstream pin
586 //
587 // ppSamples - array of samples
588 // nSamples - how many
589 // nSamplesProcessed - How many were processed
590 //
591 // On return all samples will have been Release()'d
592 //
593 
595  __in_ecount(nSamples) IMediaSample **ppSamples,
596  long nSamples,
597  __out long *nSamplesProcessed)
598 {
599  if (nSamples < 0) {
600  return E_INVALIDARG;
601  }
602 
603  CAutoLock lck(this);
604  // Either call directly or queue up the samples
605 
606  if (!IsQueued()) {
607 
608  // If we already had a bad return code then just return
609 
610  if (S_OK != m_hr) {
611 
612  // If we've never received anything since the last Flush()
613  // and the sticky return code is not S_OK we must be
614  // flushing
615  // ((!A || B) is equivalent to A implies B)
617 
618  // We're supposed to Release() them anyway!
619  *nSamplesProcessed = 0;
620  for (int i = 0; i < nSamples; i++) {
621  DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (direct) : Discarding %d samples code 0x%8.8X"),
622  nSamples, m_hr));
623  ppSamples[i]->Release();
624  }
625 
626  return m_hr;
627  }
628  //
629  // If we're flushing the sticky return code should be S_FALSE
630  //
632  m_bFlushed = FALSE;
633 
634  ASSERT(m_nBatched < m_lBatchSize);
635  ASSERT(m_nBatched == 0 || m_bBatchExact);
636 
637  // Loop processing the samples in batches
638 
639  LONG iLost = 0;
640  long iDone = 0;
641  for (iDone = 0;
642  iDone < nSamples || (m_nBatched != 0 && m_bSendAnyway);
643  ) {
644 
645 //pragma message (REMIND("Implement threshold scheme"))
646  ASSERT(m_nBatched < m_lBatchSize);
647  if (iDone < nSamples) {
648  m_ppSamples[m_nBatched++] = ppSamples[iDone++];
649  }
650  if (m_nBatched == m_lBatchSize ||
651  nSamples == 0 && (m_bSendAnyway || !m_bBatchExact)) {
652  LONG nDone;
653  DbgLog((LOG_TRACE, 4, TEXT("Batching %d samples"),
654  m_nBatched));
655 
656  if (m_hr == S_OK) {
657  m_hr = m_pInputPin->ReceiveMultiple(m_ppSamples,
658  m_nBatched,
659  &nDone);
660  } else {
661  nDone = 0;
662  }
663  iLost += m_nBatched - nDone;
664  for (LONG i = 0; i < m_nBatched; i++) {
665  m_ppSamples[i]->Release();
666  }
667  m_nBatched = 0;
668  }
669  }
670  *nSamplesProcessed = iDone - iLost;
671  if (*nSamplesProcessed < 0) {
672  *nSamplesProcessed = 0;
673  }
674  return m_hr;
675  } else {
676  /* We're sending to our thread */
677 
678  if (m_hr != S_OK) {
679  *nSamplesProcessed = 0;
680  DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (queued) : Discarding %d samples code 0x%8.8X"),
681  nSamples, m_hr));
682  for (int i = 0; i < nSamples; i++) {
683  ppSamples[i]->Release();
684  }
685  return m_hr;
686  }
687  m_bFlushed = FALSE;
688  for (long i = 0; i < nSamples; i++) {
689  QueueSample(ppSamples[i]);
690  }
691  *nSamplesProcessed = nSamples;
692  if (!m_bBatchExact ||
693  m_nBatched + m_List->GetCount() >= m_lBatchSize) {
694  NotifyThread();
695  }
696  return S_OK;
697  }
698 }
699 
700 // Get ready for new data - cancels sticky m_hr
702 {
703  if (!IsQueued()) {
704  m_hr = S_OK;
705  } else {
706  {
707  CAutoLock lck(this);
709  NotifyThread();
710  }
712  }
713 }
714 
715 // Remove and Release() all queued and Batched samples
717 {
718  CAutoLock lck(this);
719  if (IsQueued()) {
720  while (TRUE) {
721  IMediaSample *pSample = m_List->RemoveHead();
722  // inform derived class we took something off the queue
723  if (m_hEventPop) {
724  //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
725  SetEvent(m_hEventPop);
726  }
727 
728  if (pSample == NULL) {
729  break;
730  }
731  if (!IsSpecialSample(pSample)) {
732  pSample->Release();
733  } else {
734  if (pSample == NEW_SEGMENT) {
735  // Free NEW_SEGMENT packet
736  NewSegmentPacket *ppacket =
738  // inform derived class we took something off the queue
739  if (m_hEventPop) {
740  //DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
741  SetEvent(m_hEventPop);
742  }
743 
744  ASSERT(ppacket != NULL);
745  delete ppacket;
746  }
747  }
748  }
749  }
750  for (int i = 0; i < m_nBatched; i++) {
751  m_ppSamples[i]->Release();
752  }
753  m_nBatched = 0;
754 }
755 
756 // Notify the thread if there is something to do
757 //
758 // The critical section MUST be held when this is called
760 {
761  // Optimize - no need to signal if it's not waiting
762  ASSERT(IsQueued());
763  if (m_lWaiting) {
764  ReleaseSemaphore(m_hSem, m_lWaiting, NULL);
765  m_lWaiting = 0;
766  }
767 }
768 
769 // See if there's any work to do
770 // Returns
771 // TRUE if there is nothing on the queue and nothing in the batch
772 // and all data has been sent
773 // FALSE otherwise
774 //
776 {
777  CAutoLock lck(this);
778 
779  // We're idle if
780  // there is no thread (!IsQueued()) OR
781  // the thread is waiting for more work (m_lWaiting != 0)
782  // AND
783  // there's nothing in the current batch (m_nBatched == 0)
784 
785  if (IsQueued() && m_lWaiting == 0 || m_nBatched != 0) {
786  return FALSE;
787  } else {
788 
789  // If we're idle it shouldn't be possible for there
790  // to be anything on the work queue
791 
792  ASSERT(!IsQueued() || m_List->GetCount() == 0);
793  return TRUE;
794  }
795 }
796 
797 
799 {
800  m_hEventPop = hEvent;
801 }
COutputQueue::BeginFlush
void BeginFlush()
Definition: outputq.cpp:463
COutputQueue::IsIdle
BOOL IsIdle()
Definition: outputq.cpp:775
COutputQueue::m_hr
HRESULT volatile m_hr
Definition: outputq.h:132
DbgWaitForSingleObject
#define DbgWaitForSingleObject(h)
Definition: wxdebug.h:195
SEND_PACKET
#define SEND_PACKET
Definition: outputq.h:90
HANDLE
short HANDLE
Definition: ajatypes.h:338
COutputQueue::ThreadProc
DWORD ThreadProc()
Definition: outputq.cpp:203
streams.h
NULL
#define NULL
Definition: ntv2caption608types.h:19
COutputQueue::m_List
CSampleList * m_List
Definition: outputq.h:108
LOG_TRACE
@ LOG_TRACE
Definition: wxdebug.h:45
COutputQueue::Receive
HRESULT Receive(IMediaSample *pSample)
Definition: outputq.cpp:576
NAME
#define NAME(_x_)
Definition: wxdebug.h:179
COutputQueue::m_bSendAnyway
BOOL m_bSendAnyway
Definition: outputq.h:129
COutputQueue::Reset
void Reset()
Definition: outputq.cpp:701
COutputQueue::EndFlush
void EndFlush()
Definition: outputq.cpp:516
CAutoLock
Definition: wxutil.h:83
CSampleList
CGenericList< IMediaSample > CSampleList
Definition: outputq.h:12
COutputQueue::NewSegmentPacket::tStart
REFERENCE_TIME tStart
Definition: outputq.h:97
COutputQueue::m_pInputPin
IMemInputPin * m_pInputPin
Definition: outputq.h:104
COutputQueue::m_bBatchExact
const BOOL m_bBatchExact
Definition: outputq.h:105
COutputQueue::NewSegment
void NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
Definition: outputq.cpp:393
COutputQueue::m_bFlushingOpt
bool m_bFlushingOpt
Definition: outputq.h:123
CGenericList::GetCount
int GetCount() const
Definition: wxlist.h:517
LOG_ERROR
@ LOG_ERROR
Definition: wxdebug.h:48
CAMEvent::Wait
BOOL Wait(DWORD dwTimeout=INFINITE)
Definition: wxutil.h:127
DbgLog
#define DbgLog(_x_)
Definition: wxdebug.h:183
COutputQueue::NotifyThread
void NotifyThread()
Definition: outputq.cpp:759
COutputQueue::m_hThread
HANDLE m_hThread
Definition: outputq.h:111
COutputQueue::SendAnyway
void SendAnyway()
Definition: outputq.cpp:374
COutputQueue::m_pPin
IPin *const m_pPin
Definition: outputq.h:103
COutputQueue::m_lBatchSize
const LONG m_lBatchSize
Definition: outputq.h:106
COutputQueue::InitialThreadProc
static DWORD WINAPI InitialThreadProc(__in LPVOID pv)
Definition: outputq.cpp:182
EOS_PACKET
#define EOS_PACKET
Definition: outputq.h:91
COutputQueue::ReceiveMultiple
HRESULT ReceiveMultiple(__in_ecount(nSamples) IMediaSample **pSamples, long nSamples, __out long *nSamplesProcessed)
Definition: outputq.cpp:594
COutputQueue::FreeSamples
void FreeSamples()
Definition: outputq.cpp:716
COutputQueue::IsSpecialSample
BOOL IsSpecialSample(IMediaSample *pSample)
Definition: outputq.h:76
EXECUTE_ASSERT
#define EXECUTE_ASSERT(_x_)
Definition: wxdebug.h:207
COutputQueue::m_bTerminate
BOOL m_bTerminate
Definition: outputq.h:126
CGenericList::AddTail
__out_opt POSITION AddTail(__in OBJECT *pObj)
Definition: wxlist.h:533
COutputQueue::m_lWaiting
LONG m_lWaiting
Definition: outputq.h:116
COutputQueue::COutputQueue
COutputQueue(IPin *pInputPin, __inout HRESULT *phr, BOOL bAuto=TRUE, BOOL bQueue=TRUE, LONG lBatchSize=1, BOOL bBatchExact=FALSE, LONG lListSize=DEFAULTCACHE, DWORD dwPriority=THREAD_PRIORITY_NORMAL, bool bFlushingOpt=false)
Definition: outputq.cpp:43
COutputQueue::m_bFlushing
BOOL m_bFlushing
Definition: outputq.h:118
COutputQueue::EOS
void EOS()
Definition: outputq.cpp:436
COutputQueue::m_bFlushed
BOOL m_bFlushed
Definition: outputq.h:122
COutputQueue::IsQueued
BOOL IsQueued()
Definition: outputq.h:68
RESET_PACKET
#define RESET_PACKET
Definition: outputq.h:92
COutputQueue::QueueSample
void QueueSample(IMediaSample *pSample)
Definition: outputq.cpp:558
AmHresultFromWin32
#define AmHresultFromWin32(x)
Definition: wxutil.h:472
COutputQueue::m_hSem
HANDLE m_hSem
Definition: outputq.h:109
pv
__in REFIID __deref_out void ** pv
Definition: dllentry.cpp:194
COutputQueue::NewSegmentPacket::tStop
REFERENCE_TIME tStop
Definition: outputq.h:98
COutputQueue::m_hEventPop
HANDLE m_hEventPop
Definition: outputq.h:135
CGenericList::RemoveHead
__out_opt OBJECT * RemoveHead()
Definition: wxlist.h:525
NEW_SEGMENT
#define NEW_SEGMENT
Definition: outputq.h:93
ASSERT
#define ASSERT(_x_)
Definition: wxdebug.h:205
hr
__out HRESULT & hr
Definition: pstream.cpp:145
COutputQueue
Definition: outputq.h:14
COutputQueue::~COutputQueue
~COutputQueue()
Definition: outputq.cpp:149
COutputQueue::NewSegmentPacket::dRate
double dRate
Definition: outputq.h:99
COutputQueue::m_evFlushComplete
CAMEvent m_evFlushComplete
Definition: outputq.h:110
COutputQueue::SetPopEvent
void SetPopEvent(HANDLE hEvent)
Definition: outputq.cpp:798
COutputQueue::NewSegmentPacket
Definition: outputq.h:96
CAMEvent::Reset
void Reset()
Definition: wxutil.h:130