void DirectShowSampleScheduler::setFlushing(bool flushing) { QMutexLocker locker(&m_mutex); const bool isFlushing = m_state & Flushing; if (isFlushing != flushing) { if (flushing) { m_state |= Flushing; for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) { sample->unschedule(m_clock); m_semaphore.release(1); } m_head = 0; m_tail = 0; ::SetEvent(m_flushEvent); } else { m_state &= ~Flushing; if (m_state != Stopped) ::ResetEvent(m_flushEvent); } } }
HRESULT DirectShowSampleScheduler::Receive(IMediaSample *pSample) { if (!pSample) return E_POINTER; m_semaphore.acquire(1); QMutexLocker locker(&m_mutex); if (m_state & Flushing) { m_semaphore.release(1); return S_FALSE; } else if (m_state == Stopped) { m_semaphore.release(); return VFW_E_WRONG_STATE; } else { DirectShowTimedSample *timedSample = new DirectShowTimedSample(pSample); if (m_tail) m_tail->setNextSample(timedSample); else m_head = timedSample; m_tail = timedSample; if (m_state == Running) { if (!timedSample->schedule(m_clock, m_startTime, m_timeoutEvent)) { // Timing information is unavailable, so schedule frames immediately. QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); } else { locker.unlock(); HANDLE handles[] = { m_flushEvent, m_timeoutEvent }; DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE); locker.relock(); if (result == WAIT_OBJECT_0 + 1) QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); } } else if (m_tail == m_head) { // If this is the first frame make it available. QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); if (m_state == Paused) { ::ResetEvent(m_timeoutEvent); locker.unlock(); HANDLE handles[] = { m_flushEvent, m_timeoutEvent }; ::WaitForMultipleObjects(2, handles, FALSE, INFINITE); locker.relock(); } } return S_OK; } }
void DirectShowSampleScheduler::pause() { QMutexLocker locker(&m_mutex); m_state = (m_state & Flushing) | Paused; for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample()) sample->unschedule(m_clock); }
void DirectShowSampleScheduler::run(REFERENCE_TIME startTime) { QMutexLocker locker(&m_mutex); m_state = (m_state & Flushing) | Running; m_startTime = startTime; for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample()) { sample->schedule(m_clock, m_startTime, m_timeoutEvent); } }
void DirectShowSampleScheduler::stop() { QMutexLocker locker(&m_mutex); m_state = m_state & Flushing; for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) { sample->unschedule(m_clock); m_semaphore.release(1); } m_head = 0; m_tail = 0; }
HRESULT DirectShowSampleScheduler::Receive(IMediaSample *pSample) { if (!pSample) return E_POINTER; m_semaphore.acquire(1); QMutexLocker locker(&m_mutex); if (m_state & Flushing) { m_semaphore.release(1); return S_FALSE; } else if (m_state == Stopped) { m_semaphore.release(); return VFW_E_WRONG_STATE; } else { DirectShowTimedSample *timedSample = new DirectShowTimedSample(pSample); if (m_tail) m_tail->setNextSample(timedSample); else m_head = timedSample; m_tail = timedSample; if (m_state == Running) { if (!timedSample->schedule(m_clock, m_startTime, m_timeoutEvent)) { // Timing information is unavailable, so schedule frames immediately. QMetaObject::invokeMethod(this, "timerActivated", Qt::QueuedConnection); } } else if (m_tail == m_head) { // If this is the first frame make is available. QMetaObject::invokeMethod(this, "timerActivated", Qt::QueuedConnection); } return S_OK; } }