diff options
Diffstat (limited to 'src/plugins/directshow/player/videosurfacefilter.cpp')
-rw-r--r-- | src/plugins/directshow/player/videosurfacefilter.cpp | 810 |
1 files changed, 0 insertions, 810 deletions
diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp deleted file mode 100644 index 4b7afc266..000000000 --- a/src/plugins/directshow/player/videosurfacefilter.cpp +++ /dev/null @@ -1,810 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "videosurfacefilter.h" - -#include "directshoweventloop.h" -#include "directshowglobal.h" -#include "directshowvideobuffer.h" - -#include <QtCore/qthread.h> -#include <QtCore/qloggingcategory.h> -#include <qabstractvideosurface.h> - -#include <mutex> - -#include <initguid.h> - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(qLcRenderFilter, "qt.multimedia.plugins.directshow.renderfilter") - -// { e23cad72-153d-406c-bf3f-4c4b523d96f2 } -DEFINE_GUID(CLSID_VideoSurfaceFilter, -0xe23cad72, 0x153d, 0x406c, 0xbf, 0x3f, 0x4c, 0x4b, 0x52, 0x3d, 0x96, 0xf2); - -class VideoSurfaceInputPin : public DirectShowInputPin -{ - COM_REF_MIXIN -public: - VideoSurfaceInputPin(VideoSurfaceFilter *filter); - - STDMETHODIMP QueryInterface(REFIID riid, void **ppv) override; - - bool isMediaTypeSupported(const AM_MEDIA_TYPE *type) override; - bool setMediaType(const AM_MEDIA_TYPE *type) override; - - HRESULT completeConnection(IPin *pin) override; - HRESULT connectionEnded() override; - - // IPin - STDMETHODIMP ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) override; - STDMETHODIMP Disconnect() override; - STDMETHODIMP EndOfStream() override; - STDMETHODIMP BeginFlush() override; - STDMETHODIMP EndFlush() override; - - // IMemInputPin - STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) override; - STDMETHODIMP Receive(IMediaSample *pMediaSample) override; - -private: - VideoSurfaceFilter *m_videoSurfaceFilter; -}; - -VideoSurfaceInputPin::VideoSurfaceInputPin(VideoSurfaceFilter *filter) - : DirectShowInputPin(filter, QStringLiteral("Input")) - , m_videoSurfaceFilter(filter) -{ -} - -HRESULT VideoSurfaceInputPin::QueryInterface(REFIID riid, void **ppv) -{ - if (ppv == nullptr) - return E_POINTER; - if (riid == IID_IUnknown) - *ppv = static_cast<IUnknown *>(static_cast<DirectShowPin *>(this)); - else if (riid == IID_IPin) - *ppv = static_cast<IPin *>(this); - else if (riid == IID_IMemInputPin) - *ppv =static_cast<IMemInputPin*>(this); - else - return E_NOINTERFACE; - AddRef(); - return S_OK; -} - -bool VideoSurfaceInputPin::isMediaTypeSupported(const AM_MEDIA_TYPE *type) -{ - return m_videoSurfaceFilter->isMediaTypeSupported(type); -} - -bool VideoSurfaceInputPin::setMediaType(const AM_MEDIA_TYPE *type) -{ - if (!DirectShowInputPin::setMediaType(type)) - return false; - - return m_videoSurfaceFilter->setMediaType(type); -} - -HRESULT VideoSurfaceInputPin::completeConnection(IPin *pin) -{ - HRESULT hr = DirectShowInputPin::completeConnection(pin); - if (FAILED(hr)) - return hr; - - return m_videoSurfaceFilter->completeConnection(pin); -} - -HRESULT VideoSurfaceInputPin::connectionEnded() -{ - HRESULT hr = DirectShowInputPin::connectionEnded(); - if (FAILED(hr)) - return hr; - - return m_videoSurfaceFilter->connectionEnded(); -} - -HRESULT VideoSurfaceInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - return DirectShowInputPin::ReceiveConnection(pConnector, pmt); -} - -HRESULT VideoSurfaceInputPin::Disconnect() -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - return DirectShowInputPin::Disconnect(); -} - -HRESULT VideoSurfaceInputPin::EndOfStream() -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - const std::lock_guard<QRecursiveMutex> renderLocker(m_videoSurfaceFilter->m_renderMutex); - - HRESULT hr = DirectShowInputPin::EndOfStream(); - if (hr != S_OK) - return hr; - - return m_videoSurfaceFilter->EndOfStream(); -} - -HRESULT VideoSurfaceInputPin::BeginFlush() -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - { - const std::lock_guard<QRecursiveMutex> renderLocker(m_videoSurfaceFilter->m_renderMutex); - DirectShowInputPin::BeginFlush(); - m_videoSurfaceFilter->BeginFlush(); - } - m_videoSurfaceFilter->resetEOS(); - - return S_OK; -} - -HRESULT VideoSurfaceInputPin::EndFlush() -{ - QMutexLocker lock(&m_videoSurfaceFilter->m_mutex); - const std::lock_guard<QRecursiveMutex> renderLocker(m_videoSurfaceFilter->m_renderMutex); - - HRESULT hr = m_videoSurfaceFilter->EndFlush(); - if (SUCCEEDED(hr)) - hr = DirectShowInputPin::EndFlush(); - return hr; -} - -HRESULT VideoSurfaceInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) -{ - if (!pProps) - return E_POINTER; - - // We need at least two allocated buffers, one for holding the frame currently being - // rendered and another one to decode the following frame at the same time. - pProps->cBuffers = 2; - - return S_OK; -} - -HRESULT VideoSurfaceInputPin::Receive(IMediaSample *pMediaSample) -{ - HRESULT hr = m_videoSurfaceFilter->Receive(pMediaSample); - if (FAILED(hr)) { - QMutexLocker locker(&m_videoSurfaceFilter->m_mutex); - if (m_videoSurfaceFilter->state() != State_Stopped && !m_flushing && !m_inErrorState) { - m_videoSurfaceFilter->NotifyEvent(EC_ERRORABORT, hr, 0); - { - const std::lock_guard<QRecursiveMutex> renderLocker(m_videoSurfaceFilter->m_renderMutex); - if (m_videoSurfaceFilter->m_running && !m_videoSurfaceFilter->m_EOSDelivered) - m_videoSurfaceFilter->notifyEOS(); - } - m_inErrorState = true; - } - } - - return hr; -} - - -VideoSurfaceFilter::VideoSurfaceFilter(QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent) - : QObject(parent) - , m_loop(loop) - , m_surface(surface) - , m_renderEvent(CreateEvent(nullptr, FALSE, FALSE, nullptr)) - , m_flushEvent(CreateEvent(nullptr, TRUE, FALSE, nullptr)) -{ - supportedFormatsChanged(); - connect(surface, &QAbstractVideoSurface::supportedFormatsChanged, - this, &VideoSurfaceFilter::supportedFormatsChanged); -} - -VideoSurfaceFilter::~VideoSurfaceFilter() -{ - clearPendingSample(); - - if (m_pin) - m_pin->Release(); - - CloseHandle(m_flushEvent); - CloseHandle(m_renderEvent); -} - -HRESULT VideoSurfaceFilter::QueryInterface(REFIID riid, void **ppv) -{ - if (ppv == nullptr) - return E_POINTER; - if (riid == IID_IUnknown) - *ppv = static_cast<IUnknown *>(static_cast<DirectShowBaseFilter *>(this)); - else if (riid == IID_IPersist || riid == IID_IMediaFilter || riid == IID_IBaseFilter) - *ppv = static_cast<IBaseFilter *>(this); - else if (riid == IID_IAMFilterMiscFlags) - *ppv = static_cast<IAMFilterMiscFlags *>(this); - else - return E_NOINTERFACE; - AddRef(); - return S_OK; -} - -QList<DirectShowPin *> VideoSurfaceFilter::pins() -{ - if (!m_pin) - m_pin = new VideoSurfaceInputPin(this); - - return QList<DirectShowPin *>() << m_pin; -} - -HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID) -{ - *pClassID = CLSID_VideoSurfaceFilter; - return S_OK; -} - -ULONG VideoSurfaceFilter::GetMiscFlags() -{ - return AM_FILTER_MISC_FLAGS_IS_RENDERER; -} - -void VideoSurfaceFilter::supportedFormatsChanged() -{ - QWriteLocker writeLocker(&m_typesLock); - - qCDebug(qLcRenderFilter, "supportedFormatChanged"); - - m_supportedTypes.clear(); - - const QList<QVideoFrame::PixelFormat> formats = m_surface->supportedPixelFormats(); - m_supportedTypes.reserve(formats.count()); - - for (QVideoFrame::PixelFormat format : formats) { - GUID subtype = DirectShowMediaType::convertPixelFormat(format); - if (!IsEqualGUID(subtype, MEDIASUBTYPE_None)) { - qCDebug(qLcRenderFilter) << " " << format; - m_supportedTypes.append(subtype); - } - } -} - -bool VideoSurfaceFilter::isMediaTypeSupported(const AM_MEDIA_TYPE *type) -{ - if (type->majortype != MEDIATYPE_Video || type->bFixedSizeSamples == FALSE) - return false; - - QReadLocker readLocker(&m_typesLock); - - for (const GUID &supportedType : m_supportedTypes) { - if (IsEqualGUID(supportedType, type->subtype)) - return true; - } - - return false; -} - -bool VideoSurfaceFilter::setMediaType(const AM_MEDIA_TYPE *type) -{ - if (!type) { - qCDebug(qLcRenderFilter, "clear media type"); - m_surfaceFormat = QVideoSurfaceFormat(); - m_bytesPerLine = 0; - return true; - } - m_surfaceFormat = DirectShowMediaType::videoFormatFromType(type); - m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat); - qCDebug(qLcRenderFilter) << "setMediaType -->" << m_surfaceFormat; - return m_surfaceFormat.isValid(); -} - -HRESULT VideoSurfaceFilter::completeConnection(IPin *pin) -{ - Q_UNUSED(pin); - - qCDebug(qLcRenderFilter, "completeConnection"); - - return startSurface() ? S_OK : VFW_E_TYPE_NOT_ACCEPTED; -} - -HRESULT VideoSurfaceFilter::connectionEnded() -{ - qCDebug(qLcRenderFilter, "connectionEnded"); - - stopSurface(); - - return S_OK; -} - -HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart) -{ - QMutexLocker locker(&m_mutex); - - if (m_state == State_Running) - return S_OK; - - qCDebug(qLcRenderFilter, "Run (start=%lli)", tStart); - - HRESULT hr = DirectShowBaseFilter::Run(tStart); - if (FAILED(hr)) - return hr; - - ResetEvent(m_flushEvent); - - IMemAllocator *allocator; - if (SUCCEEDED(m_pin->GetAllocator(&allocator))) { - allocator->Commit(); - allocator->Release(); - } - - const std::lock_guard<QRecursiveMutex> renderLocker(m_renderMutex); - - m_running = true; - - if (!m_pendingSample) - checkEOS(); - else if (!scheduleSample(m_pendingSample)) - SetEvent(m_renderEvent); // render immediately - - return S_OK; -} - -HRESULT VideoSurfaceFilter::Pause() -{ - QMutexLocker locker(&m_mutex); - - if (m_state == State_Paused) - return S_OK; - - qCDebug(qLcRenderFilter, "Pause"); - - HRESULT hr = DirectShowBaseFilter::Pause(); - if (FAILED(hr)) - return hr; - - m_renderMutex.lock(); - m_EOSDelivered = false; - m_running = false; - m_renderMutex.unlock(); - - resetEOSTimer(); - ResetEvent(m_flushEvent); - unscheduleSample(); - - IMemAllocator *allocator; - if (SUCCEEDED(m_pin->GetAllocator(&allocator))) { - allocator->Commit(); - allocator->Release(); - } - - return S_OK; -} - -HRESULT VideoSurfaceFilter::Stop() -{ - QMutexLocker locker(&m_mutex); - - if (m_state == State_Stopped) - return S_OK; - - qCDebug(qLcRenderFilter, "Stop"); - - DirectShowBaseFilter::Stop(); - - clearPendingSample(); - - m_renderMutex.lock(); - m_EOSDelivered = false; - m_running = false; - m_renderMutex.unlock(); - - SetEvent(m_flushEvent); - resetEOS(); - unscheduleSample(); - flushSurface(); - - IMemAllocator *allocator; - if (SUCCEEDED(m_pin->GetAllocator(&allocator))) { - allocator->Decommit(); - allocator->Release(); - } - - return S_OK; -} - -HRESULT VideoSurfaceFilter::EndOfStream() -{ - const std::lock_guard<QRecursiveMutex> renderLocker(m_renderMutex); - - qCDebug(qLcRenderFilter, "EndOfStream"); - - m_EOS = true; - - if (!m_pendingSample && m_running) - checkEOS(); - - stopSurface(); - return S_OK; -} - -HRESULT VideoSurfaceFilter::BeginFlush() -{ - qCDebug(qLcRenderFilter, "BeginFlush"); - - SetEvent(m_flushEvent); - unscheduleSample(); - clearPendingSample(); - - return S_OK; -} - -HRESULT VideoSurfaceFilter::EndFlush() -{ - qCDebug(qLcRenderFilter, "EndFlush"); - - ResetEvent(m_flushEvent); - return S_OK; -} - -HRESULT VideoSurfaceFilter::Receive(IMediaSample *pMediaSample) -{ - { - QMutexLocker locker(&m_mutex); - - qCDebug(qLcRenderFilter, "Receive (sample=%p)", pMediaSample); - - HRESULT hr = m_pin->DirectShowInputPin::Receive(pMediaSample); - if (hr != S_OK) { - qCDebug(qLcRenderFilter, " can't receive sample (error %X)", uint(hr)); - return E_FAIL; - } - - // If the format dynamically changed, the sample contains information about the new format. - // We need to reset the format and restart the QAbstractVideoSurface. - if (m_pin->currentSampleProperties()->pMediaType - && (!m_pin->setMediaType(m_pin->currentSampleProperties()->pMediaType) - || !restartSurface())) { - qCWarning(qLcRenderFilter, " dynamic format change failed, aborting rendering"); - NotifyEvent(EC_ERRORABORT, VFW_E_TYPE_NOT_ACCEPTED, 0); - return VFW_E_INVALIDMEDIATYPE; - } - - { - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (m_pendingSample || m_EOS) - return E_UNEXPECTED; - - if (m_running && !scheduleSample(pMediaSample)) { - qCWarning(qLcRenderFilter, " sample can't be scheduled, discarding it"); - return S_OK; - } - - m_pendingSample = pMediaSample; - m_pendingSample->AddRef(); - m_pendingSampleEndTime = m_pin->currentSampleProperties()->tStop; - } - - if (m_state == State_Paused) // Render immediately - renderPendingSample(); - } - - qCDebug(qLcRenderFilter, " waiting for render time"); - - // Wait for render time. The clock will wake us up whenever the time comes. - // It can also be interrupted by a flush, pause or stop. - HANDLE waitObjects[] = { m_flushEvent, m_renderEvent }; - DWORD result = WAIT_TIMEOUT; - while (result == WAIT_TIMEOUT) - result = WaitForMultipleObjects(2, waitObjects, FALSE, INFINITE); - - if (result == WAIT_OBJECT_0) { - // render interrupted (flush, pause, stop) - qCDebug(qLcRenderFilter, " rendering of sample %p interrupted", pMediaSample); - return S_OK; - } - - m_adviseCookie = 0; - - QMutexLocker locker(&m_mutex); - - // State might have changed just before the lock - if (m_state == State_Stopped) { - qCDebug(qLcRenderFilter, " state changed to Stopped, discarding sample (%p)", pMediaSample); - return S_OK; - } - - std::unique_lock<QRecursiveMutex> renderLocker(m_renderMutex); - - // Flush or pause might have happened just before the lock - if (m_pendingSample && m_running) { - renderLocker.unlock(); - renderPendingSample(); - renderLocker.lock(); - } else { - qCDebug(qLcRenderFilter, " discarding sample (%p)", pMediaSample); - } - - clearPendingSample(); - checkEOS(); - ResetEvent(m_renderEvent); - - return S_OK; -} - -bool VideoSurfaceFilter::scheduleSample(IMediaSample *sample) -{ - if (!sample) - return false; - - qCDebug(qLcRenderFilter, "scheduleSample (sample=%p)", sample); - - REFERENCE_TIME sampleStart, sampleEnd; - if (FAILED(sample->GetTime(&sampleStart, &sampleEnd)) || !m_clock) { - qCDebug(qLcRenderFilter, " render now"); - SetEvent(m_renderEvent); // Render immediately - return true; - } - - if (sampleEnd < sampleStart) { // incorrect times - qCWarning(qLcRenderFilter, " invalid sample times (start=%lli, end=%lli)", sampleStart, sampleEnd); - return false; - } - - HRESULT hr = m_clock->AdviseTime(m_startTime, sampleStart, (HEVENT)m_renderEvent, &m_adviseCookie); - if (FAILED(hr)) { - qCWarning(qLcRenderFilter, " clock failed to advise time (error=%X)", uint(hr)); - return false; - } - - return true; -} - -void VideoSurfaceFilter::unscheduleSample() -{ - if (m_adviseCookie) { - qCDebug(qLcRenderFilter, "unscheduleSample"); - m_clock->Unadvise(m_adviseCookie); - m_adviseCookie = 0; - } - - ResetEvent(m_renderEvent); -} - -void VideoSurfaceFilter::clearPendingSample() -{ - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - if (m_pendingSample) { - qCDebug(qLcRenderFilter, "clearPendingSample"); - m_pendingSample->Release(); - m_pendingSample = nullptr; - } -} - -void QT_WIN_CALLBACK EOSTimerCallback(UINT, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR) -{ - VideoSurfaceFilter *that = reinterpret_cast<VideoSurfaceFilter *>(dwUser); - that->onEOSTimerTimeout(); -} - -void VideoSurfaceFilter::onEOSTimerTimeout() -{ - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (m_EOSTimer) { - m_EOSTimer = 0; - checkEOS(); - } -} - -void VideoSurfaceFilter::checkEOS() -{ - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (!m_EOS || m_EOSDelivered || m_EOSTimer) - return; - - if (!m_clock) { - notifyEOS(); - return; - } - - REFERENCE_TIME eosTime = m_startTime + m_pendingSampleEndTime; - REFERENCE_TIME currentTime; - m_clock->GetTime(¤tTime); - LONG delay = LONG((eosTime - currentTime) / 10000); - - if (delay < 1) { - notifyEOS(); - } else { - qCDebug(qLcRenderFilter, "will trigger EOS in %li", delay); - - m_EOSTimer = timeSetEvent(delay, - 1, - EOSTimerCallback, - reinterpret_cast<DWORD_PTR>(this), - TIME_ONESHOT | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS); - - if (!m_EOSTimer) { - qDebug("Error with timer"); - notifyEOS(); - } - } -} - -void VideoSurfaceFilter::notifyEOS() -{ - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (!m_running) - return; - - qCDebug(qLcRenderFilter, "notifyEOS, delivering EC_COMPLETE event"); - - m_EOSTimer = 0; - m_EOSDelivered = true; - NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)this); -} - -void VideoSurfaceFilter::resetEOS() -{ - resetEOSTimer(); - - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - - if (m_EOS) - qCDebug(qLcRenderFilter, "resetEOS (delivered=%s)", m_EOSDelivered ? "true" : "false"); - - m_EOS = false; - m_EOSDelivered = false; - m_pendingSampleEndTime = 0; -} - -void VideoSurfaceFilter::resetEOSTimer() -{ - if (m_EOSTimer) { - timeKillEvent(m_EOSTimer); - m_EOSTimer = 0; - } -} - -bool VideoSurfaceFilter::startSurface() -{ - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface))); - m_waitSurface.wait(&m_mutex); - return m_surfaceStarted; - } - m_surfaceStarted = m_surface->start(m_surfaceFormat); - qCDebug(qLcRenderFilter, "startSurface %s", m_surfaceStarted ? "succeeded" : "failed"); - return m_surfaceStarted; -} - -void VideoSurfaceFilter::stopSurface() -{ - if (!m_surfaceStarted) - return; - - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(StopSurface))); - m_waitSurface.wait(&m_mutex); - } else { - qCDebug(qLcRenderFilter, "stopSurface"); - m_surface->stop(); - m_surfaceStarted = false; - } -} - -bool VideoSurfaceFilter::restartSurface() -{ - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(RestartSurface))); - m_waitSurface.wait(&m_mutex); - return m_surfaceStarted; - } - m_surface->stop(); - m_surfaceStarted = m_surface->start(m_surfaceFormat); - qCDebug(qLcRenderFilter, "restartSurface %s", m_surfaceStarted ? "succeeded" : "failed"); - return m_surfaceStarted; -} - -void VideoSurfaceFilter::flushSurface() -{ - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface))); - m_waitSurface.wait(&m_mutex); - } else { - qCDebug(qLcRenderFilter, "flushSurface"); - m_surface->present(QVideoFrame()); - } -} - -void VideoSurfaceFilter::renderPendingSample() -{ - if (QThread::currentThread() != thread()) { - m_loop->postEvent(this, new QEvent(QEvent::Type(RenderSample))); - m_waitSurface.wait(&m_mutex); - } else { - const std::lock_guard<QRecursiveMutex> locker(m_renderMutex); - if (!m_pendingSample) - return; - - qCDebug(qLcRenderFilter, "presentSample (sample=%p)", m_pendingSample); - - m_surface->present(QVideoFrame(new DirectShowVideoBuffer(m_pendingSample, m_bytesPerLine), - m_surfaceFormat.frameSize(), - m_surfaceFormat.pixelFormat())); - } -} - -bool VideoSurfaceFilter::event(QEvent *e) -{ - switch (e->type()) { - case StartSurface: { - QMutexLocker locker(&m_mutex); - startSurface(); - m_waitSurface.wakeAll(); - return true; - } - case StopSurface: { - QMutexLocker locker(&m_mutex); - stopSurface(); - m_waitSurface.wakeAll(); - return true; - } - case RestartSurface: { - QMutexLocker locker(&m_mutex); - restartSurface(); - m_waitSurface.wakeAll(); - return true; - } - case FlushSurface: { - QMutexLocker locker(&m_mutex); - flushSurface(); - m_waitSurface.wakeAll(); - return true; - } - case RenderSample: { - QMutexLocker locker(&m_mutex); - renderPendingSample(); - m_waitSurface.wakeAll(); - return true; - } - default: - break; - } - - return QObject::event(e); -} - -QT_END_NAMESPACE |