diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-09-02 10:47:15 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-09-07 12:33:53 +0000 |
commit | dec5393964668279d673b73ef8ebac3b4310985f (patch) | |
tree | 0b4f2bc44591b2c1e19f53854bd7c3020433f8b2 | |
parent | 674c93e8677dd270c08c8d7ea05c845088911828 (diff) |
Move gstreamer over to the new subtitle handling
Implement a custom sink for subtitles that notifies the video
sink about changes in the subtitles. Remove the subtitleoverlay
we have been using so far.
Change-Id: I6ecfb1ab8538169d7365f21e0c0648b4aa2cd769
Reviewed-by: Piotr Srebrny <piotr.srebrny@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
(cherry picked from commit 8d5182d03c1967d77ca8da531b004e85bb0892f0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
12 files changed, 379 insertions, 31 deletions
diff --git a/src/multimedia/CMakeLists.txt b/src/multimedia/CMakeLists.txt index 13e166a93..b7d7a8b0d 100644 --- a/src/multimedia/CMakeLists.txt +++ b/src/multimedia/CMakeLists.txt @@ -212,6 +212,7 @@ qt_internal_extend_target(Multimedia CONDITION QT_FEATURE_gstreamer platform/gstreamer/common/qgstutils.cpp platform/gstreamer/common/qgstutils_p.h platform/gstreamer/common/qgstvideobuffer.cpp platform/gstreamer/common/qgstvideobuffer_p.h platform/gstreamer/common/qgstvideorenderersink.cpp platform/gstreamer/common/qgstvideorenderersink_p.h + platform/gstreamer/common/qgstsubtitlesink.cpp platform/gstreamer/common/qgstsubtitlesink_p.h platform/gstreamer/qgstreamermediadevices.cpp platform/gstreamer/qgstreamermediadevices_p.h platform/gstreamer/qgstreamerformatinfo.cpp platform/gstreamer/qgstreamerformatinfo_p.h platform/gstreamer/qgstreamerintegration.cpp platform/gstreamer/qgstreamerintegration_p.h diff --git a/src/multimedia/platform/gstreamer/common/qgst_p.h b/src/multimedia/platform/gstreamer/common/qgst_p.h index f0a0bf79d..12eb123c0 100644 --- a/src/multimedia/platform/gstreamer/common/qgst_p.h +++ b/src/multimedia/platform/gstreamer/common/qgst_p.h @@ -377,6 +377,9 @@ public: GstPad *pad() const { return GST_PAD_CAST(object()); } + GstEvent *stickyEvent(GstEventType type) { return gst_pad_get_sticky_event(pad(), type, 0); } + bool sendEvent(GstEvent *event) { return gst_pad_send_event (pad(), event); } + template<auto Member, typename T> void addProbe(T *instance, GstPadProbeType type) { struct Impl { diff --git a/src/multimedia/platform/gstreamer/common/qgstpipeline.cpp b/src/multimedia/platform/gstreamer/common/qgstpipeline.cpp index ab2aa1c0e..3877694dd 100644 --- a/src/multimedia/platform/gstreamer/common/qgstpipeline.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstpipeline.cpp @@ -66,6 +66,7 @@ public: mutable qint64 m_position = 0; double m_rate = 1.; bool m_flushOnConfigChanges = false; + bool m_pendingFlush = false; int m_configCounter = 0; GstState m_savedState = GST_STATE_NULL; @@ -271,6 +272,16 @@ void QGstPipeline::removeMessageFilter(QGstreamerBusMessageFilter *filter) d->removeMessageFilter(filter); } +GstStateChangeReturn QGstPipeline::setState(GstState state) +{ + auto retval = gst_element_set_state(element(), state); + if (d->m_pendingFlush) { + d->m_pendingFlush = false; + flush(); + } + return retval; +} + void QGstPipeline::beginConfig() { if (!d) @@ -296,8 +307,7 @@ void QGstPipeline::endConfig() if (d->m_configCounter) return; - if (d->m_savedState != GST_STATE_NULL && d->m_flushOnConfigChanges) - flush(); + d->m_pendingFlush = true; if (d->m_savedState == GST_STATE_PLAYING) setState(GST_STATE_PLAYING); d->m_savedState = GST_STATE_NULL; diff --git a/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h b/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h index d5621c1b3..6ffaf33d6 100644 --- a/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstpipeline_p.h @@ -100,6 +100,8 @@ public: void installMessageFilter(QGstreamerBusMessageFilter *filter); void removeMessageFilter(QGstreamerBusMessageFilter *filter); + GstStateChangeReturn setState(GstState state); + GstPipeline *pipeline() const { return GST_PIPELINE_CAST(m_object); } void dumpGraph(const char *fileName) diff --git a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp index 874b7bba1..f1aba4eda 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer.cpp @@ -78,6 +78,11 @@ QGstreamerMediaPlayer::QGstreamerMediaPlayer(QMediaPlayer *parent) inputSelector[AudioStream] = QGstElement("input-selector", "audioInputSelector"); inputSelector[VideoStream] = QGstElement("input-selector", "videoInputSelector"); inputSelector[SubtitleStream] = QGstElement("input-selector", "subTitleInputSelector"); + for (int i = 0; i < 3; ++i) + inputSelector[i].set ("sync-streams", true); + + inputSelector[SubtitleStream].set("sync-mode", 1 /*clock*/); + inputSelector[SubtitleStream].set("cache-buffers", true); playerPipeline.add(inputSelector[AudioStream], inputSelector[VideoStream], inputSelector[SubtitleStream]); @@ -795,6 +800,10 @@ void QGstreamerMediaPlayer::setActiveTrack(QPlatformMediaPlayer::TrackType type, auto &selector = inputSelector[type]; if (selector.isNull()) return; + + if (type == QPlatformMediaPlayer::SubtitleStream) + gstVideoOutput->flushSubtitles(); + selector.set("active-pad", streams.at(index)); // seek to force an immediate change of the stream if (playerPipeline.state() == GST_STATE_PLAYING) diff --git a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h index ca0139784..aba416498 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstreamermediaplayer_p.h @@ -115,6 +115,7 @@ public: bool processBusMessage(const QGstreamerMessage& message) override; bool processSyncMessage(const QGstreamerMessage& message) override; + public Q_SLOTS: void updatePosition() { positionChanged(position()); } diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideooutput.cpp b/src/multimedia/platform/gstreamer/common/qgstreamervideooutput.cpp index 2cc4b38d8..36e0823d8 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamervideooutput.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstreamervideooutput.cpp @@ -39,6 +39,7 @@ #include <private/qgstreamervideooutput_p.h> #include <private/qgstreamervideosink_p.h> +#include <private/qgstsubtitlesink_p.h> #include <qvideosink.h> #include <QtCore/qloggingcategory.h> @@ -55,10 +56,8 @@ QGstreamerVideoOutput::QGstreamerVideoOutput(QObject *parent) videoQueue = QGstElement("queue", "videoQueue"); videoConvert = QGstElement("videoconvert", "videoConvert"); videoSink = QGstElement("fakesink", "fakeVideoSink"); - subTitleQueue = QGstElement("queue", "subtitleQueue"); - subtitleOverlay = QGstElement("subtitleoverlay", "subtitleoverlay"); - gstVideoOutput.add(videoQueue, subtitleOverlay, videoConvert, videoSink, subTitleQueue); - if (!videoQueue.link(subtitleOverlay, videoConvert, videoSink)) + gstVideoOutput.add(videoQueue, videoConvert, videoSink); + if (!videoQueue.link(videoConvert, videoSink)) qCDebug(qLcMediaVideoOutput) << ">>>>>> linking failed"; gstVideoOutput.addGhostPad(videoQueue, "sink"); @@ -72,19 +71,19 @@ QGstreamerVideoOutput::~QGstreamerVideoOutput() void QGstreamerVideoOutput::setVideoSink(QVideoSink *sink) { auto *gstVideoSink = sink ? static_cast<QGstreamerVideoSink *>(sink->platformVideoSink()) : nullptr; - if (gstVideoSink == m_videoWindow) + if (gstVideoSink == m_videoSink) return; - if (m_videoWindow) - m_videoWindow->setPipeline({}); + if (m_videoSink) + m_videoSink->setPipeline({}); - m_videoWindow = gstVideoSink; - if (m_videoWindow) - m_videoWindow->setPipeline(gstPipeline); + m_videoSink = gstVideoSink; + if (m_videoSink) + m_videoSink->setPipeline(gstPipeline); QGstElement gstSink; - if (m_videoWindow) { - gstSink = m_videoWindow->gstSink(); + if (m_videoSink) { + gstSink = m_videoSink->gstSink(); isFakeSink = false; } else { gstSink = QGstElement("fakesink", "fakevideosink"); @@ -107,6 +106,8 @@ void QGstreamerVideoOutput::setVideoSink(QVideoSink *sink) gst_element_send_event(videoSink.element(), event); videoSink.setState(GST_STATE_PAUSED); + doLinkSubtitleStream(); + gstPipeline.endConfig(); qCDebug(qLcMediaVideoOutput) << "sinkChanged" << gstSink.name(); @@ -121,8 +122,8 @@ void QGstreamerVideoOutput::setVideoSink(QVideoSink *sink) void QGstreamerVideoOutput::setPipeline(const QGstPipeline &pipeline) { gstPipeline = pipeline; - if (m_videoWindow) - m_videoWindow->setPipeline(gstPipeline); + if (m_videoSink) + m_videoSink->setPipeline(gstPipeline); } void QGstreamerVideoOutput::linkSubtitleStream(QGstElement src) @@ -132,20 +133,26 @@ void QGstreamerVideoOutput::linkSubtitleStream(QGstElement src) return; gstPipeline.beginConfig(); + subtitleSrc = src; + doLinkSubtitleStream(); + gstPipeline.endConfig(); +} - if (!subtitleSrc.isNull()) { - subtitleSrc.unlink(subTitleQueue); - subTitleQueue.unlink(subtitleOverlay); +void QGstreamerVideoOutput::doLinkSubtitleStream() +{ + if (!subtitleSink.isNull()) { + subtitleSink.setStateSync(GST_STATE_NULL); + gstPipeline.remove(subtitleSink); + subtitleSink = {}; } - subtitleSrc = src; - if (!subtitleSrc.isNull()) { - if (!subtitleSrc.link(subTitleQueue)) - qCDebug(qLcMediaVideoOutput) << "link subtitle stream 1 failed"; - if (!subTitleQueue.link(subtitleOverlay)) - qCDebug(qLcMediaVideoOutput) << "link subtitle stream 1 failed"; + if (!m_videoSink || subtitleSrc.isNull()) + return; + if (subtitleSink.isNull()) { + subtitleSink = m_videoSink->subtitleSink(); + gstPipeline.add(subtitleSink); } - - gstPipeline.endConfig(); + if (!subtitleSrc.link(subtitleSink)) + qCDebug(qLcMediaVideoOutput) << "link subtitle stream failed"; } void QGstreamerVideoOutput::setIsPreview() @@ -159,4 +166,15 @@ void QGstreamerVideoOutput::setIsPreview() videoQueue.set("max-size-time", 0); } +void QGstreamerVideoOutput::flushSubtitles() +{ + if (!subtitleSink.isNull()) { + auto pad = subtitleSink.staticPad("sink"); + auto *event = gst_event_new_flush_start(); + pad.sendEvent(event); + event = gst_event_new_flush_stop(false); + pad.sendEvent(event); + } +} + QT_END_NAMESPACE diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideooutput_p.h b/src/multimedia/platform/gstreamer/common/qgstreamervideooutput_p.h index 1468343ab..41e8da413 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamervideooutput_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstreamervideooutput_p.h @@ -73,7 +73,7 @@ public: ~QGstreamerVideoOutput(); void setVideoSink(QVideoSink *sink); - QGstreamerVideoSink *gstreamerVideoSink() const { return m_videoWindow; } + QGstreamerVideoSink *gstreamerVideoSink() const { return m_videoSink; } void setPipeline(const QGstPipeline &pipeline); @@ -81,23 +81,24 @@ public: void linkSubtitleStream(QGstElement subtitleSrc); void setIsPreview(); + void flushSubtitles(); private: + void doLinkSubtitleStream(); - QPointer<QGstreamerVideoSink> m_videoWindow; + QPointer<QGstreamerVideoSink> m_videoSink; bool isFakeSink = true; // Gst elements QGstPipeline gstPipeline; QGstBin gstVideoOutput; - QGstElement subTitleQueue; QGstElement videoQueue; QGstElement videoConvert; - QGstElement subtitleOverlay; QGstElement videoSink; QGstElement subtitleSrc; + QGstElement subtitleSink; }; QT_END_NAMESPACE diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp b/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp index a770d0e57..ca7daf6eb 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstreamervideosink.cpp @@ -39,6 +39,7 @@ #include "qgstreamervideosink_p.h" #include "private/qgstvideorenderersink_p.h" +#include "private/qgstsubtitlesink_p.h" #include <private/qgstutils_p.h> #include <QtGui/private/qrhi_p.h> @@ -91,6 +92,8 @@ QGstreamerVideoSink::QGstreamerVideoSink(QVideoSink *parent) sinkBin.add(gstQueue, gstPreprocess); gstQueue.link(gstPreprocess); sinkBin.addGhostPad(gstQueue, "sink"); + + gstSubtitleSink = GST_ELEMENT(QGstSubtitleSink::createSink(this)); } QGstreamerVideoSink::~QGstreamerVideoSink() diff --git a/src/multimedia/platform/gstreamer/common/qgstreamervideosink_p.h b/src/multimedia/platform/gstreamer/common/qgstreamervideosink_p.h index e6d588a36..a049bc465 100644 --- a/src/multimedia/platform/gstreamer/common/qgstreamervideosink_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstreamervideosink_p.h @@ -79,6 +79,7 @@ public: QRhi *rhi() const { return m_rhi; } QGstElement gstSink(); + QGstElement subtitleSink() const { return gstSubtitleSink; } void setPipeline(QGstPipeline pipeline); @@ -100,6 +101,7 @@ private: QGstElement gstPreprocess; QGstElement gstVideoSink; QGstElement gstQtSink; + QGstElement gstSubtitleSink; QRhi *m_rhi = nullptr; diff --git a/src/multimedia/platform/gstreamer/common/qgstsubtitlesink.cpp b/src/multimedia/platform/gstreamer/common/qgstsubtitlesink.cpp new file mode 100644 index 000000000..d9b76d57f --- /dev/null +++ b/src/multimedia/platform/gstreamer/common/qgstsubtitlesink.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company +** 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 <QDebug> +#include <QThread> +#include <QEvent> + +#include "qgstreamervideosink_p.h" +#include "qgstsubtitlesink_p.h" +#include "qgstutils_p.h" + +QT_BEGIN_NAMESPACE + +static GstBaseSinkClass *sink_parent_class; +static thread_local QGstreamerVideoSink *current_sink; + +#define ST_SINK(s) QGstSubtitleSink *sink(reinterpret_cast<QGstSubtitleSink *>(s)) + +QGstSubtitleSink *QGstSubtitleSink::createSink(QGstreamerVideoSink *sink) +{ + current_sink = sink; + + QGstSubtitleSink *gstSink = reinterpret_cast<QGstSubtitleSink *>( + g_object_new(QGstSubtitleSink::get_type(), nullptr)); + g_object_set(gstSink, "async", false, nullptr); + + return gstSink; +} + +GType QGstSubtitleSink::get_type() +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = + { + sizeof(QGstSubtitleSinkClass), // class_size + base_init, // base_init + nullptr, // base_finalize + class_init, // class_init + nullptr, // class_finalize + nullptr, // class_data + sizeof(QGstSubtitleSink), // instance_size + 0, // n_preallocs + instance_init, // instance_init + nullptr // value_table + }; + + type = g_type_register_static( + GST_TYPE_BASE_SINK, "QGstSubtitleSink", &info, GTypeFlags(0)); + + // Register the sink type to be used in custom piplines. + // When surface is ready the sink can be used. + gst_element_register(nullptr, "qtsubtitlesink", GST_RANK_PRIMARY, type); + } + + return type; +} + +void QGstSubtitleSink::class_init(gpointer g_class, gpointer class_data) +{ + Q_UNUSED(class_data); + + sink_parent_class = reinterpret_cast<GstBaseSinkClass *>(g_type_class_peek_parent(g_class)); + + GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class); + base_sink_class->render = QGstSubtitleSink::render; + base_sink_class->get_caps = QGstSubtitleSink::get_caps; + base_sink_class->set_caps = QGstSubtitleSink::set_caps; + base_sink_class->propose_allocation = QGstSubtitleSink::propose_allocation; + base_sink_class->wait_event = QGstSubtitleSink::wait_event; + + GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class); + element_class->change_state = QGstSubtitleSink::change_state; + gst_element_class_set_metadata(element_class, + "Qt built-in subtitle sink", + "Sink/Subtitle", + "Qt default built-in subtitle sink", + "The Qt Company"); + + GObjectClass *object_class = reinterpret_cast<GObjectClass *>(g_class); + object_class->finalize = QGstSubtitleSink::finalize; +} + +void QGstSubtitleSink::base_init(gpointer g_class) +{ + static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE( + "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("ANY")); + + gst_element_class_add_pad_template( + GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template)); +} + +void QGstSubtitleSink::instance_init(GTypeInstance *instance, gpointer g_class) +{ + Q_UNUSED(g_class); + ST_SINK(instance); + + Q_ASSERT(current_sink); + sink->sink = current_sink; + current_sink = nullptr; +} + +void QGstSubtitleSink::finalize(GObject *object) +{ + // Chain up + G_OBJECT_CLASS(sink_parent_class)->finalize(object); +} + +GstStateChangeReturn QGstSubtitleSink::change_state(GstElement *element, GstStateChange transition) +{ + return GST_ELEMENT_CLASS(sink_parent_class)->change_state(element, transition); +} + +GstCaps *QGstSubtitleSink::get_caps(GstBaseSink *base, GstCaps *filter) +{ + return sink_parent_class->get_caps(base, filter); +} + +gboolean QGstSubtitleSink::set_caps(GstBaseSink *base, GstCaps *caps) +{ + qDebug() << "set_caps:" << QGstCaps(caps).toString(); + return sink_parent_class->set_caps(base, caps); +} + +gboolean QGstSubtitleSink::propose_allocation(GstBaseSink *base, GstQuery *query) +{ + return sink_parent_class->propose_allocation(base, query); +} + +GstFlowReturn QGstSubtitleSink::wait_event(GstBaseSink *base, GstEvent *event) +{ + GstFlowReturn retval = sink_parent_class->wait_event(base, event); + ST_SINK(base); + if (event->type == GST_EVENT_GAP) { +// qDebug() << "gap, clearing subtitle"; + sink->sink->setSubtitleText(QString()); + } + return retval; +} + +GstFlowReturn QGstSubtitleSink::render(GstBaseSink *base, GstBuffer *buffer) +{ + ST_SINK(base); + GstMemory *mem = gst_buffer_get_memory(buffer, 0); + GstMapInfo info; + QString subtitle; + if (gst_memory_map(mem, &info, GST_MAP_READ)) + subtitle = QString::fromUtf8(info.data); + gst_memory_unmap(mem, &info); +// qDebug() << "render" << buffer << subtitle; + sink->sink->setSubtitleText(subtitle); + return GST_FLOW_OK; +} + +QT_END_NAMESPACE diff --git a/src/multimedia/platform/gstreamer/common/qgstsubtitlesink_p.h b/src/multimedia/platform/gstreamer/common/qgstsubtitlesink_p.h new file mode 100644 index 000000000..aa9127c7d --- /dev/null +++ b/src/multimedia/platform/gstreamer/common/qgstsubtitlesink_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company +** 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$ +** +****************************************************************************/ + +#ifndef QGSTSUBTITLESINK_P_H +#define QGSTSUBTITLESINK_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 <QtMultimedia/private/qtmultimediaglobal_p.h> + +#include <QtCore/qlist.h> +#include <QtCore/qmutex.h> +#include <QtCore/qqueue.h> +#include <QtCore/qpointer.h> +#include <QtCore/qwaitcondition.h> +#include <private/qgst_p.h> +#include <gst/base/gstbasesink.h> + +QT_BEGIN_NAMESPACE + +class QGstreamerVideoSink; + +class Q_MULTIMEDIA_EXPORT QGstSubtitleSink +{ +public: + GstBaseSink parent; + + static QGstSubtitleSink *createSink(QGstreamerVideoSink *sink); + +private: + static GType get_type(); + static void class_init(gpointer g_class, gpointer class_data); + static void base_init(gpointer g_class); + static void instance_init(GTypeInstance *instance, gpointer g_class); + + static void finalize(GObject *object); + + static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition); + + static GstCaps *get_caps(GstBaseSink *sink, GstCaps *filter); + static gboolean set_caps(GstBaseSink *sink, GstCaps *caps); + + static gboolean propose_allocation(GstBaseSink *sink, GstQuery *query); + + static GstFlowReturn wait_event(GstBaseSink * sink, GstEvent * event); + static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer); + +private: + QGstreamerVideoSink *sink = nullptr; +}; + + +class QGstSubtitleSinkClass +{ +public: + GstBaseSinkClass parent_class; +}; + +QT_END_NAMESPACE + +#endif |