diff options
Diffstat (limited to 'src/plugins/multimedia/gstreamer/common/qgstreamermediaplayer_p.h')
-rw-r--r-- | src/plugins/multimedia/gstreamer/common/qgstreamermediaplayer_p.h | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/src/plugins/multimedia/gstreamer/common/qgstreamermediaplayer_p.h b/src/plugins/multimedia/gstreamer/common/qgstreamermediaplayer_p.h new file mode 100644 index 000000000..cf337f32c --- /dev/null +++ b/src/plugins/multimedia/gstreamer/common/qgstreamermediaplayer_p.h @@ -0,0 +1,197 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QGSTREAMERMEDIAPLAYER_P_H +#define QGSTREAMERMEDIAPLAYER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qstack.h> +#include <private/qplatformmediaplayer_p.h> +#include <private/qtmultimediaglobal_p.h> +#include <private/qmultimediautils_p.h> +#include <qurl.h> +#include <common/qgst_p.h> +#include <common/qgstpipeline_p.h> + +#include <QtCore/qtimer.h> + +#include <array> + +QT_BEGIN_NAMESPACE + +class QNetworkAccessManager; +class QGstreamerMessage; +class QGstAppSource; +class QGstreamerAudioOutput; +class QGstreamerVideoOutput; + +class QGstreamerMediaPlayer : public QObject, + public QPlatformMediaPlayer, + public QGstreamerBusMessageFilter, + public QGstreamerSyncMessageFilter +{ +public: + static QMaybe<QPlatformMediaPlayer *> create(QMediaPlayer *parent = nullptr); + ~QGstreamerMediaPlayer(); + + qint64 duration() const override; + + float bufferProgress() const override; + + QMediaTimeRange availablePlaybackRanges() const override; + + qreal playbackRate() const override; + void setPlaybackRate(qreal rate) override; + + QUrl media() const override; + const QIODevice *mediaStream() const override; + void setMedia(const QUrl &, QIODevice *) override; + + bool streamPlaybackSupported() const override { return true; } + + void setAudioOutput(QPlatformAudioOutput *output) override; + + QMediaMetaData metaData() const override; + + void setVideoSink(QVideoSink *sink) override; + + int trackCount(TrackType) override; + QMediaMetaData trackMetaData(TrackType /*type*/, int /*streamNumber*/) override; + int activeTrack(TrackType) override; + void setActiveTrack(TrackType, int /*streamNumber*/) override; + + void setPosition(qint64 pos) override; + void setPosition(std::chrono::milliseconds pos); + + void play() override; + void pause() override; + void stop() override; + + const QGstPipeline &pipeline() const; + + bool processBusMessage(const QGstreamerMessage& message) override; + bool processSyncMessage(const QGstreamerMessage& message) override; + +private: + QGstreamerMediaPlayer(QGstreamerVideoOutput *videoOutput, QMediaPlayer *parent); + + struct TrackSelector + { + TrackSelector(TrackType, QGstElement selector); + QGstPad createInputPad(); + void removeInputPad(QGstPad pad); + void removeAllInputPads(); + QGstPad inputPad(int index); + int activeInputIndex() const { return isConnected ? tracks.indexOf(activeInputPad()) : -1; } + QGstPad activeInputPad() const + { + return isConnected ? QGstPad{ selector.getObject("active-pad") } : QGstPad{}; + } + void setActiveInputPad(QGstPad input) { selector.set("active-pad", input); } + int trackCount() const { return tracks.count(); } + + QGstElement selector; + TrackType type; + QList<QGstPad> tracks; + bool isConnected = false; + }; + + friend class QGstreamerStreamsControl; + void decoderPadAdded(const QGstElement &src, const QGstPad &pad); + void decoderPadRemoved(const QGstElement &src, const QGstPad &pad); + void disconnectDecoderHandlers(); + static void uridecodebinElementAddedCallback(GstElement *uridecodebin, GstElement *child, + QGstreamerMediaPlayer *that); + static void sourceSetupCallback(GstElement *uridecodebin, GstElement *source, + QGstreamerMediaPlayer *that); + static void unknownTypeCallback(GstElement *decodebin, GstPad *pad, GstCaps *caps, + QGstreamerMediaPlayer *self); + static void decodebinElementAddedCallback(GstBin *decodebin, GstBin *sub_bin, + GstElement *element, QGstreamerMediaPlayer *self); + static void decodebinElementRemovedCallback(GstBin *decodebin, GstBin *sub_bin, + GstElement *element, QGstreamerMediaPlayer *self); + + void parseStreamsAndMetadata(); + void connectOutput(TrackSelector &ts); + void removeOutput(TrackSelector &ts); + void removeDynamicPipelineElements(); + void removeAllOutputs(); + void stopOrEOS(bool eos); + bool canTrackProgress() const { return decodeBinQueues > 0; } + void detectPipelineIsSeekable(); + + std::chrono::nanoseconds pipelinePosition() const; + void updatePositionFromPipeline(); + + std::array<TrackSelector, NTrackTypes> trackSelectors; + TrackSelector &trackSelector(TrackType type); + + QMediaMetaData m_metaData; + + int m_bufferProgress = 0; + QUrl m_url; + QIODevice *m_stream = nullptr; + + enum class ResourceErrorState : uint8_t { + NoError, + ErrorOccurred, + ErrorReported, + }; + + bool prerolling = false; + bool m_requiresSeekOnPlay = false; + bool m_initialBufferProgressSent = false; + ResourceErrorState m_resourceErrorState = ResourceErrorState::NoError; + float m_rate = 1.f; + std::chrono::milliseconds m_duration{}; + QTimer positionUpdateTimer; + + QGstAppSource *m_appSrc = nullptr; + + QUniqueGstStructureHandle topology; + + // Gst elements + QGstPipeline playerPipeline; + QGstElement src; + QGstElement decoder; + + QGstreamerAudioOutput *gstAudioOutput = nullptr; + QGstreamerVideoOutput *gstVideoOutput = nullptr; + + // QGstElement streamSynchronizer; + + struct QGstPadLess + { + bool operator()(const QGstPad &lhs, const QGstPad &rhs) const + { + return lhs.pad() < rhs.pad(); + } + }; + + std::map<QGstPad, QGstPad, QGstPadLess> decoderOutputMap; + + // decoder connections + QGObjectHandlerScopedConnection padAdded; + QGObjectHandlerScopedConnection padRemoved; + QGObjectHandlerScopedConnection sourceSetup; + QGObjectHandlerScopedConnection uridecodebinElementAdded; + QGObjectHandlerScopedConnection unknownType; + QGObjectHandlerScopedConnection elementAdded; + QGObjectHandlerScopedConnection elementRemoved; + + int decodeBinQueues = 0; +}; + +QT_END_NAMESPACE + +#endif |