diff options
Diffstat (limited to 'src/plugins/directshow')
10 files changed, 120 insertions, 151 deletions
diff --git a/src/plugins/directshow/common/directshowutils.cpp b/src/plugins/directshow/common/directshowutils.cpp index 8f3f321e7..d1c1d42ab 100644 --- a/src/plugins/directshow/common/directshowutils.cpp +++ b/src/plugins/directshow/common/directshowutils.cpp @@ -56,8 +56,10 @@ bool DirectShowUtils::isPinConnected(IPin *pin, HRESULT *hrOut) hrOut = &hr; *hrOut = pin->ConnectedTo(&connectedPin); - if (*hrOut == VFW_E_NOT_CONNECTED) // Not an error in this case + if (*hrOut == VFW_E_NOT_CONNECTED) { // Not an error in this case *hrOut = S_OK; + return false; + } if (FAILED(*hrOut)) { qCDebug(qtDirectShowPlugin, "Querying pin connection failed!"); @@ -282,7 +284,7 @@ bool DirectShowUtils::connectFilters(IGraphBuilder *graph, // Try to connect to the upstream filter first. if (findAndConnect(upstreamFilter)) - return false; + return true; const auto getFilters = [graph, hrOut]() -> IEnumFilters * { IEnumFilters *f = nullptr; diff --git a/src/plugins/directshow/directshow.pro b/src/plugins/directshow/directshow.pro index 54d617166..e531efc53 100644 --- a/src/plugins/directshow/directshow.pro +++ b/src/plugins/directshow/directshow.pro @@ -17,12 +17,11 @@ mingw { } include(common/common.pri) -qtConfig(directshow-player): include(player/player.pri) +include(player/player.pri) include(camera/camera.pri) OTHER_FILES += \ - directshow.json \ - directshow_camera.json + directshow.json PLUGIN_TYPE = mediaservice PLUGIN_CLASS_NAME = DSServicePlugin diff --git a/src/plugins/directshow/directshow_camera.json b/src/plugins/directshow/directshow_camera.json deleted file mode 100644 index c37ce2c9a..000000000 --- a/src/plugins/directshow/directshow_camera.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "Keys": ["directshow"], - "Services": ["org.qt-project.qt.camera"] -} diff --git a/src/plugins/directshow/dsserviceplugin.cpp b/src/plugins/directshow/dsserviceplugin.cpp index 64b30f561..727a11b55 100644 --- a/src/plugins/directshow/dsserviceplugin.cpp +++ b/src/plugins/directshow/dsserviceplugin.cpp @@ -51,9 +51,7 @@ #include <dshow.h> #include "dscameraservice.h" -#if QT_CONFIG(directshow_player) #include "directshowplayerservice.h" -#endif #include <qmediaserviceproviderplugin.h> @@ -95,12 +93,11 @@ QMediaService* DSServicePlugin::create(QString const& key) addRefCount(); return new DSCameraService; } -#if QT_CONFIG(directshow_player) + if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) { addRefCount(); return new DirectShowPlayerService; } -#endif return 0; } diff --git a/src/plugins/directshow/dsserviceplugin.h b/src/plugins/directshow/dsserviceplugin.h index 2e87058c3..55db9310c 100644 --- a/src/plugins/directshow/dsserviceplugin.h +++ b/src/plugins/directshow/dsserviceplugin.h @@ -55,13 +55,7 @@ class DSServicePlugin Q_INTERFACES(QMediaServiceSupportedDevicesInterface) Q_INTERFACES(QMediaServiceDefaultDeviceInterface) Q_INTERFACES(QMediaServiceFeaturesInterface) - // The player service provided by the WMF-plugin should preferably be used. - // DirectShow should then only provide the camera (see QTBUG-29172, QTBUG-29175). -#if QT_CONFIG(directshow_player) Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "directshow.json") -#else - Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "directshow_camera.json") -#endif public: QMediaService* create(QString const& key) override; diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp index 90d2b3e7d..52b73a7df 100644 --- a/src/plugins/directshow/player/directshowmetadatacontrol.cpp +++ b/src/plugins/directshow/player/directshowmetadatacontrol.cpp @@ -477,21 +477,14 @@ static QString convertBSTR(BSTR *string) return value; } -void DirectShowMetaDataControl::reset() +void DirectShowMetaDataControl::setMetadata(const QVariantMap &metadata) { - bool hadMetadata = !m_metadata.isEmpty(); - m_metadata.clear(); - - setMetadataAvailable(false); - - if (hadMetadata) - emit metaDataChanged(); + m_metadata = metadata; + setMetadataAvailable(!m_metadata.isEmpty()); } -void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter *source, const QString &fileSrc) +void DirectShowMetaDataControl::updateMetadata(const QString &fileSrc, QVariantMap &metadata) { - m_metadata.clear(); - #if QT_CONFIG(wshellitem) if (!sHCreateItemFromParsingName) { QSystemLibrary lib(QStringLiteral("shell32")); @@ -518,90 +511,90 @@ void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter continue; if (IsEqualPropertyKey(key, PKEY_Author)) { - m_metadata.insert(QMediaMetaData::Author, convertValue(var)); + metadata.insert(QMediaMetaData::Author, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Title)) { - m_metadata.insert(QMediaMetaData::Title, convertValue(var)); + metadata.insert(QMediaMetaData::Title, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_SubTitle)) { - m_metadata.insert(QMediaMetaData::SubTitle, convertValue(var)); + metadata.insert(QMediaMetaData::SubTitle, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_ParentalRating)) { - m_metadata.insert(QMediaMetaData::ParentalRating, convertValue(var)); + metadata.insert(QMediaMetaData::ParentalRating, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Comment)) { - m_metadata.insert(QMediaMetaData::Description, convertValue(var)); + metadata.insert(QMediaMetaData::Description, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Copyright)) { - m_metadata.insert(QMediaMetaData::Copyright, convertValue(var)); + metadata.insert(QMediaMetaData::Copyright, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_ProviderStyle)) { - m_metadata.insert(QMediaMetaData::Genre, convertValue(var)); + metadata.insert(QMediaMetaData::Genre, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Year)) { - m_metadata.insert(QMediaMetaData::Year, convertValue(var)); + metadata.insert(QMediaMetaData::Year, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_DateEncoded)) { - m_metadata.insert(QMediaMetaData::Date, convertValue(var)); + metadata.insert(QMediaMetaData::Date, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Rating)) { - m_metadata.insert(QMediaMetaData::UserRating, + metadata.insert(QMediaMetaData::UserRating, int((convertValue(var).toUInt() - 1) / qreal(98) * 100)); } else if (IsEqualPropertyKey(key, PKEY_Keywords)) { - m_metadata.insert(QMediaMetaData::Keywords, convertValue(var)); + metadata.insert(QMediaMetaData::Keywords, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Language)) { - m_metadata.insert(QMediaMetaData::Language, convertValue(var)); + metadata.insert(QMediaMetaData::Language, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Publisher)) { - m_metadata.insert(QMediaMetaData::Publisher, convertValue(var)); + metadata.insert(QMediaMetaData::Publisher, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Duration)) { - m_metadata.insert(QMediaMetaData::Duration, + metadata.insert(QMediaMetaData::Duration, (convertValue(var).toLongLong() + 10000) / 10000); } else if (IsEqualPropertyKey(key, PKEY_Audio_EncodingBitrate)) { - m_metadata.insert(QMediaMetaData::AudioBitRate, convertValue(var)); + metadata.insert(QMediaMetaData::AudioBitRate, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_AverageLevel)) { - m_metadata.insert(QMediaMetaData::AverageLevel, convertValue(var)); + metadata.insert(QMediaMetaData::AverageLevel, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Audio_ChannelCount)) { - m_metadata.insert(QMediaMetaData::ChannelCount, convertValue(var)); + metadata.insert(QMediaMetaData::ChannelCount, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Audio_PeakValue)) { - m_metadata.insert(QMediaMetaData::PeakValue, convertValue(var)); + metadata.insert(QMediaMetaData::PeakValue, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Audio_SampleRate)) { - m_metadata.insert(QMediaMetaData::SampleRate, convertValue(var)); + metadata.insert(QMediaMetaData::SampleRate, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_AlbumTitle)) { - m_metadata.insert(QMediaMetaData::AlbumTitle, convertValue(var)); + metadata.insert(QMediaMetaData::AlbumTitle, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_AlbumArtist)) { - m_metadata.insert(QMediaMetaData::AlbumArtist, convertValue(var)); + metadata.insert(QMediaMetaData::AlbumArtist, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Artist)) { - m_metadata.insert(QMediaMetaData::ContributingArtist, convertValue(var)); + metadata.insert(QMediaMetaData::ContributingArtist, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Composer)) { - m_metadata.insert(QMediaMetaData::Composer, convertValue(var)); + metadata.insert(QMediaMetaData::Composer, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Conductor)) { - m_metadata.insert(QMediaMetaData::Conductor, convertValue(var)); + metadata.insert(QMediaMetaData::Conductor, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Lyrics)) { - m_metadata.insert(QMediaMetaData::Lyrics, convertValue(var)); + metadata.insert(QMediaMetaData::Lyrics, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Mood)) { - m_metadata.insert(QMediaMetaData::Mood, convertValue(var)); + metadata.insert(QMediaMetaData::Mood, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_TrackNumber)) { - m_metadata.insert(QMediaMetaData::TrackNumber, convertValue(var)); + metadata.insert(QMediaMetaData::TrackNumber, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Music_Genre)) { - m_metadata.insert(QMediaMetaData::Genre, convertValue(var)); + metadata.insert(QMediaMetaData::Genre, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_ThumbnailStream)) { - m_metadata.insert(QMediaMetaData::ThumbnailImage, convertValue(var)); + metadata.insert(QMediaMetaData::ThumbnailImage, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Video_FrameHeight)) { QSize res; res.setHeight(convertValue(var).toUInt()); if (SUCCEEDED(pStore->GetValue(PKEY_Video_FrameWidth, &var))) res.setWidth(convertValue(var).toUInt()); - m_metadata.insert(QMediaMetaData::Resolution, res); + metadata.insert(QMediaMetaData::Resolution, res); } else if (IsEqualPropertyKey(key, PKEY_Video_HorizontalAspectRatio)) { QSize aspectRatio; aspectRatio.setWidth(convertValue(var).toUInt()); if (SUCCEEDED(pStore->GetValue(PKEY_Video_VerticalAspectRatio, &var))) aspectRatio.setHeight(convertValue(var).toUInt()); - m_metadata.insert(QMediaMetaData::PixelAspectRatio, aspectRatio); + metadata.insert(QMediaMetaData::PixelAspectRatio, aspectRatio); } else if (IsEqualPropertyKey(key, PKEY_Video_FrameRate)) { - m_metadata.insert(QMediaMetaData::VideoFrameRate, + metadata.insert(QMediaMetaData::VideoFrameRate, convertValue(var).toReal() / 1000); } else if (IsEqualPropertyKey(key, PKEY_Video_EncodingBitrate)) { - m_metadata.insert(QMediaMetaData::VideoBitRate, convertValue(var)); + metadata.insert(QMediaMetaData::VideoBitRate, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Video_Director)) { - m_metadata.insert(QMediaMetaData::Director, convertValue(var)); + metadata.insert(QMediaMetaData::Director, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Media_Writer)) { - m_metadata.insert(QMediaMetaData::Writer, convertValue(var)); + metadata.insert(QMediaMetaData::Writer, convertValue(var)); } else if (IsEqualPropertyKey(key, PKEY_Video_Compression)) { - m_metadata.insert(QMediaMetaData::VideoCodec, nameForGUIDString(convertValue(var).toString())); + metadata.insert(QMediaMetaData::VideoCodec, nameForGUIDString(convertValue(var).toString())); } else if (IsEqualPropertyKey(key, PKEY_Audio_Format)) { - m_metadata.insert(QMediaMetaData::AudioCodec, nameForGUIDString(convertValue(var).toString())); + metadata.insert(QMediaMetaData::AudioCodec, nameForGUIDString(convertValue(var).toString())); } PropVariantClear(&var); @@ -614,11 +607,14 @@ void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter shellItem->Release(); } } - - if (!m_metadata.isEmpty()) - goto send_event; +#else + Q_UNUSED(fileSrc); + Q_UNUSED(metadata); #endif +} +void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter *source, QVariantMap &metadata) +{ #if QT_CONFIG(wmsdk) if (IWMHeaderInfo *info = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo)) { const auto keys = *qt_wmMetaDataKeys(); @@ -644,15 +640,15 @@ void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter var = (var.toUInt() - 1) / qreal(98) * 100; } - m_metadata.insert(key.qtName, var); + metadata.insert(key.qtName, var); } } info->Release(); } - if (!m_metadata.isEmpty()) - goto send_event; + if (!metadata.isEmpty()) + return; #endif { IAMMediaContent *content = 0; @@ -668,41 +664,23 @@ void DirectShowMetaDataControl::updateMetadata(IFilterGraph2 *graph, IBaseFilter BSTR string = 0; if (content->get_AuthorName(&string) == S_OK) - m_metadata.insert(QMediaMetaData::Author, convertBSTR(&string)); + metadata.insert(QMediaMetaData::Author, convertBSTR(&string)); if (content->get_Title(&string) == S_OK) - m_metadata.insert(QMediaMetaData::Title, convertBSTR(&string)); + metadata.insert(QMediaMetaData::Title, convertBSTR(&string)); if (content->get_Description(&string) == S_OK) - m_metadata.insert(QMediaMetaData::Description, convertBSTR(&string)); + metadata.insert(QMediaMetaData::Description, convertBSTR(&string)); if (content->get_Rating(&string) == S_OK) - m_metadata.insert(QMediaMetaData::UserRating, convertBSTR(&string)); + metadata.insert(QMediaMetaData::UserRating, convertBSTR(&string)); if (content->get_Copyright(&string) == S_OK) - m_metadata.insert(QMediaMetaData::Copyright, convertBSTR(&string)); + metadata.insert(QMediaMetaData::Copyright, convertBSTR(&string)); content->Release(); } } - -send_event: - // DirectShowMediaPlayerService holds a lock at this point so defer emitting signals to a later - // time. - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(MetaDataChanged))); -} - -void DirectShowMetaDataControl::customEvent(QEvent *event) -{ - if (event->type() == QEvent::Type(MetaDataChanged)) { - event->accept(); - - setMetadataAvailable(!m_metadata.isEmpty()); - - emit metaDataChanged(); - } else { - QMetaDataReaderControl::customEvent(event); - } } void DirectShowMetaDataControl::setMetadataAvailable(bool available) @@ -711,5 +689,10 @@ void DirectShowMetaDataControl::setMetadataAvailable(bool available) return; m_available = available; - emit metaDataAvailableChanged(m_available); + + // If the metadata is not available, notify about it immediately. + Qt::ConnectionType type = m_available ? Qt::QueuedConnection : Qt::AutoConnection; + QMetaObject::invokeMethod(this, "metaDataAvailableChanged", type, Q_ARG(bool, m_available)); + // Currently the metadata is changed only with its availability. + QMetaObject::invokeMethod(this, "metaDataChanged", type); } diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.h b/src/plugins/directshow/player/directshowmetadatacontrol.h index ea20bf0c5..4196a7950 100644 --- a/src/plugins/directshow/player/directshowmetadatacontrol.h +++ b/src/plugins/directshow/player/directshowmetadatacontrol.h @@ -62,12 +62,10 @@ public: QVariant metaData(const QString &key) const override; QStringList availableMetaData() const override; - void reset(); - void updateMetadata(IFilterGraph2 *graph, IBaseFilter *source, - const QString &fileSrc = QString()); + void setMetadata(const QVariantMap &metadata); -protected: - void customEvent(QEvent *event) override; + static void updateMetadata(const QString &fileSrc, QVariantMap &metadata); + static void updateMetadata(IFilterGraph2 *graph, IBaseFilter *source, QVariantMap &metadata); private: void setMetadataAvailable(bool available); diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp index 08d99d735..d48350fa2 100644 --- a/src/plugins/directshow/player/directshowplayerservice.cpp +++ b/src/plugins/directshow/player/directshowplayerservice.cpp @@ -142,6 +142,7 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent) , m_graphStatus(NoMedia) , m_stream(0) , m_graph(0) + , m_graphBuilder(nullptr) , m_source(0) , m_audioOutput(0) , m_videoOutput(0) @@ -297,7 +298,7 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream if (m_graph) releaseGraph(); - m_resources = media.resources(); + m_url = media.canonicalUrl(); m_stream = stream; m_error = QMediaPlayer::NoError; m_errorString = QString(); @@ -310,13 +311,11 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream m_seekable = false; m_atEnd = false; m_dontCacheNextSeekResult = false; - m_metaDataControl->reset(); + m_metaDataControl->setMetadata(QVariantMap()); - if (m_resources.isEmpty() && !stream) { + if (m_url.isEmpty() && !stream) { m_pendingTasks = 0; m_graphStatus = NoMedia; - - m_url.clear(); } else if (stream && (!stream->isReadable() || stream->isSequential())) { m_pendingTasks = 0; m_graphStatus = InvalidMedia; @@ -328,6 +327,15 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream m_graphStatus = Loading; m_graph = com_new<IFilterGraph2>(CLSID_FilterGraph, iid_IFilterGraph2); + m_graphBuilder = com_new<ICaptureGraphBuilder2>(CLSID_CaptureGraphBuilder2, IID_ICaptureGraphBuilder2); + + // Attach the filter graph to the capture graph. + HRESULT hr = m_graphBuilder->SetFiltergraph(m_graph); + if (FAILED(hr)) { + qCWarning(qtDirectShowPlugin, "[0x%x] Failed to attach filter to capture graph", hr); + m_graphBuilder->Release(); + m_graphBuilder = nullptr; + } if (stream) m_pendingTasks = SetStreamSource; @@ -348,9 +356,6 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) { IBaseFilter *source = 0; - QMediaResource resource = m_resources.takeFirst(); - m_url = resource.url(); - HRESULT hr = E_FAIL; if (m_url.scheme() == QLatin1String("http") || m_url.scheme() == QLatin1String("https")) { static const GUID clsid_WMAsfReader = { @@ -403,7 +408,7 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) m_pendingTasks |= SetRate; m_source = source; - } else if (!m_resources.isEmpty()) { + } else if (!m_url.isEmpty()) { m_pendingTasks |= SetUrlSource; } else { m_graphStatus = InvalidMedia; @@ -596,7 +601,6 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) void DirectShowPlayerService::doFinalizeLoad(QMutexLocker *locker) { - Q_UNUSED(locker) if (m_graphStatus != Loaded) { if (IMediaEvent *event = com_cast<IMediaEvent>(m_graph, IID_IMediaEvent)) { event->GetEventHandle(reinterpret_cast<OAEVENT *>(&m_eventHandle)); @@ -625,6 +629,11 @@ void DirectShowPlayerService::doFinalizeLoad(QMutexLocker *locker) m_graphStatus = Loaded; + // Do not block gui thread while updating metadata from file. + locker->unlock(); + DirectShowMetaDataControl::updateMetadata(m_url.toString(), m_metadata); + locker->relock(); + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(FinalizedLoad))); } @@ -674,6 +683,11 @@ void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker) m_graph->Release(); m_graph = 0; + if (m_graphBuilder) { + m_graphBuilder->Release(); + m_graphBuilder = nullptr; + } + m_loop->wake(); } @@ -684,7 +698,7 @@ void DirectShowPlayerService::doSetVideoProbe(QMutexLocker *locker) { Q_UNUSED(locker); - if (!m_graph) { + if (!m_graph || !m_graphBuilder) { qCWarning(qtDirectShowPlugin, "Attempting to set a video probe without a valid graph!"); return; } @@ -700,41 +714,14 @@ void DirectShowPlayerService::doSetVideoProbe(QMutexLocker *locker) return; } - // TODO: Make util function for getting this, so it's easy to keep it in sync. - static const GUID subtypes[] = { MEDIASUBTYPE_ARGB32, - MEDIASUBTYPE_RGB32, - MEDIASUBTYPE_RGB24, - MEDIASUBTYPE_RGB565, - MEDIASUBTYPE_RGB555, - MEDIASUBTYPE_AYUV, - MEDIASUBTYPE_I420, - MEDIASUBTYPE_IYUV, - MEDIASUBTYPE_YV12, - MEDIASUBTYPE_UYVY, - MEDIASUBTYPE_YUYV, - MEDIASUBTYPE_YUY2, - MEDIASUBTYPE_NV12, - MEDIASUBTYPE_MJPG, - MEDIASUBTYPE_IMC1, - MEDIASUBTYPE_IMC2, - MEDIASUBTYPE_IMC3, - MEDIASUBTYPE_IMC4 }; - - // Negotiate the subtype - DirectShowMediaType mediaType(AM_MEDIA_TYPE { MEDIATYPE_Video }); - const int items = (sizeof subtypes / sizeof(GUID)); - bool connected = false; - for (int i = 0; i != items; ++i) { - mediaType->subtype = subtypes[i]; - m_videoSampleGrabber->setMediaType(&mediaType); - if (DirectShowUtils::connectFilters(m_graph, m_source, m_videoSampleGrabber->filter(), true)) { - connected = true; - break; - } - } + DirectShowMediaType mediaType({ MEDIATYPE_Video, MEDIASUBTYPE_ARGB32 }); + m_videoSampleGrabber->setMediaType(&mediaType); - if (!connected) { - qCWarning(qtDirectShowPlugin, "Unable to connect the video probe!"); + // Connect source filter to sample grabber filter. + HRESULT hr = m_graphBuilder->RenderStream(nullptr, &MEDIATYPE_Video, + m_source, nullptr, m_videoSampleGrabber->filter()); + if (FAILED(hr)) { + qCWarning(qtDirectShowPlugin, "[0x%x] Failed to connect the video sample grabber", hr); return; } @@ -765,8 +752,15 @@ void DirectShowPlayerService::doSetAudioProbe(QMutexLocker *locker) } if (!DirectShowUtils::connectFilters(m_graph, m_source, m_audioSampleGrabber->filter(), true)) { - qCWarning(qtDirectShowPlugin, "Failed to connect the audio sample grabber"); - return; + // Connect source filter to sample grabber filter. + HRESULT hr = m_graphBuilder + ? m_graphBuilder->RenderStream(nullptr, &MEDIATYPE_Audio, + m_source, nullptr, m_audioSampleGrabber->filter()) + : E_FAIL; + if (FAILED(hr)) { + qCWarning(qtDirectShowPlugin, "[0x%x] Failed to connect the audio sample grabber", hr); + return; + } } m_audioSampleGrabber->start(DirectShowSampleGrabber::CallbackMethod::BufferCB); @@ -1406,7 +1400,11 @@ void DirectShowPlayerService::customEvent(QEvent *event) QMutexLocker locker(&m_mutex); m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); - m_metaDataControl->updateMetadata(m_graph, m_source, m_url.toString()); + if (m_metadata.isEmpty()) + DirectShowMetaDataControl::updateMetadata(m_graph, m_source, m_metadata); + + m_metaDataControl->setMetadata(m_metadata); + m_metadata.clear(); updateStatus(); } else if (event->type() == QEvent::Type(Error)) { diff --git a/src/plugins/directshow/player/directshowplayerservice.h b/src/plugins/directshow/player/directshowplayerservice.h index 4a9e25678..a6eeb8a77 100644 --- a/src/plugins/directshow/player/directshowplayerservice.h +++ b/src/plugins/directshow/player/directshowplayerservice.h @@ -215,6 +215,7 @@ private: QMediaPlayer::Error m_error; QIODevice *m_stream; IFilterGraph2 *m_graph; + ICaptureGraphBuilder2 *m_graphBuilder; IBaseFilter *m_source; IBaseFilter *m_audioOutput; IBaseFilter *m_videoOutput; @@ -224,13 +225,13 @@ private: qint64 m_duration; QMediaTimeRange m_playbackRange; QUrl m_url; - QMediaResourceList m_resources; QString m_errorString; QMutex m_mutex; bool m_buffering; bool m_seekable; bool m_atEnd; bool m_dontCacheNextSeekResult; + QVariantMap m_metadata; friend class DirectShowPlayerServiceThread; }; diff --git a/src/plugins/directshow/player/videosurfacefilter.cpp b/src/plugins/directshow/player/videosurfacefilter.cpp index 826d26bdb..74d59231c 100644 --- a/src/plugins/directshow/player/videosurfacefilter.cpp +++ b/src/plugins/directshow/player/videosurfacefilter.cpp @@ -462,6 +462,7 @@ HRESULT VideoSurfaceFilter::EndOfStream() if (!m_pendingSample && m_running) checkEOS(); + stopSurface(); return S_OK; } |