summaryrefslogtreecommitdiffstats
path: root/src/gsttools/qgstvideorenderersink.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gsttools/qgstvideorenderersink.cpp')
-rw-r--r--src/gsttools/qgstvideorenderersink.cpp810
1 files changed, 0 insertions, 810 deletions
diff --git a/src/gsttools/qgstvideorenderersink.cpp b/src/gsttools/qgstvideorenderersink.cpp
deleted file mode 100644
index 8f4f59358..000000000
--- a/src/gsttools/qgstvideorenderersink.cpp
+++ /dev/null
@@ -1,810 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Jolla 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 <qabstractvideosurface.h>
-#include <qvideoframe.h>
-#include <QDebug>
-#include <QMap>
-#include <QThread>
-#include <QEvent>
-#include <QCoreApplication>
-
-#include <private/qmediapluginloader_p.h>
-#include "qgstvideobuffer_p.h"
-
-#include "qgstvideorenderersink_p.h"
-
-#include <gst/video/video.h>
-
-#include "qgstutils_p.h"
-
-#if QT_CONFIG(gstreamer_gl)
-#include <QOpenGLContext>
-#include <QGuiApplication>
-#include <QWindow>
-#include <qpa/qplatformnativeinterface.h>
-
-#include <gst/gl/gstglconfig.h>
-
-#if GST_GL_HAVE_WINDOW_X11
-# include <gst/gl/x11/gstgldisplay_x11.h>
-#endif
-#if GST_GL_HAVE_PLATFORM_EGL
-# include <gst/gl/egl/gstgldisplay_egl.h>
-#endif
-#if GST_CHECK_VERSION(1,11,1) && GST_GL_HAVE_WINDOW_WAYLAND
-# include <gst/gl/wayland/gstgldisplay_wayland.h>
-#endif
-#endif // #if QT_CONFIG(gstreamer_gl)
-
-//#define DEBUG_VIDEO_SURFACE_SINK
-
-QT_BEGIN_NAMESPACE
-
-QGstDefaultVideoRenderer::QGstDefaultVideoRenderer()
-{
-}
-
-QGstDefaultVideoRenderer::~QGstDefaultVideoRenderer()
-{
-}
-
-GstCaps *QGstDefaultVideoRenderer::getCaps(QAbstractVideoSurface *surface)
-{
-#if QT_CONFIG(gstreamer_gl)
- if (QGstUtils::useOpenGL()) {
- m_handleType = QAbstractVideoBuffer::GLTextureHandle;
- auto formats = surface->supportedPixelFormats(m_handleType);
- // Even if the surface does not support gl textures,
- // glupload will be added to the pipeline and GLMemory will be requested.
- // This will lead to upload data to gl textures
- // and download it when the buffer will be used within rendering.
- if (formats.isEmpty()) {
- m_handleType = QAbstractVideoBuffer::NoHandle;
- formats = surface->supportedPixelFormats(m_handleType);
- }
-
- GstCaps *caps = QGstUtils::capsForFormats(formats);
- for (guint i = 0; i < gst_caps_get_size(caps); ++i)
- gst_caps_set_features(caps, i, gst_caps_features_from_string("memory:GLMemory"));
-
- return caps;
- }
-#endif
- return QGstUtils::capsForFormats(surface->supportedPixelFormats(QAbstractVideoBuffer::NoHandle));
-}
-
-bool QGstDefaultVideoRenderer::start(QAbstractVideoSurface *surface, GstCaps *caps)
-{
- m_flushed = true;
- m_format = QGstUtils::formatForCaps(caps, &m_videoInfo, m_handleType);
-
- return m_format.isValid() && surface->start(m_format);
-}
-
-void QGstDefaultVideoRenderer::stop(QAbstractVideoSurface *surface)
-{
- m_flushed = true;
- if (surface)
- surface->stop();
-}
-
-bool QGstDefaultVideoRenderer::present(QAbstractVideoSurface *surface, GstBuffer *buffer)
-{
- m_flushed = false;
-
- QGstVideoBuffer *videoBuffer = nullptr;
-#if QT_CONFIG(gstreamer_gl)
- if (m_format.handleType() == QAbstractVideoBuffer::GLTextureHandle) {
- GstGLMemory *glmem = GST_GL_MEMORY_CAST(gst_buffer_peek_memory(buffer, 0));
- guint textureId = gst_gl_memory_get_texture_id(glmem);
- videoBuffer = new QGstVideoBuffer(buffer, m_videoInfo, m_format.handleType(), textureId);
- }
-#endif
-
- if (!videoBuffer)
- videoBuffer = new QGstVideoBuffer(buffer, m_videoInfo);
-
- auto meta = gst_buffer_get_video_crop_meta (buffer);
- if (meta) {
- QRect vp(meta->x, meta->y, meta->width, meta->height);
- if (m_format.viewport() != vp) {
-#ifdef DEBUG_VIDEO_SURFACE_SINK
- qDebug() << Q_FUNC_INFO << " Update viewport on Metadata: [" << meta->height << "x" << meta->width << " | " << meta->x << "x" << meta->y << "]";
-#endif
- //Update viewport if data is not the same
- m_format.setViewport(vp);
- surface->start(m_format);
- }
- }
-
- QVideoFrame frame(
- videoBuffer,
- m_format.frameSize(),
- m_format.pixelFormat());
- QGstUtils::setFrameTimeStamps(&frame, buffer);
-
- return surface->present(frame);
-}
-
-void QGstDefaultVideoRenderer::flush(QAbstractVideoSurface *surface)
-{
- if (surface && !m_flushed)
- surface->present(QVideoFrame());
- m_flushed = true;
-}
-
-bool QGstDefaultVideoRenderer::proposeAllocation(GstQuery *)
-{
- return true;
-}
-
-Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, rendererLoader,
- (QGstVideoRendererInterface_iid, QLatin1String("video/gstvideorenderer"), Qt::CaseInsensitive))
-
-QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(QAbstractVideoSurface *surface)
- : m_surface(surface)
-{
- const auto instances = rendererLoader()->instances(QGstVideoRendererPluginKey);
- for (QObject *instance : instances) {
- auto plugin = qobject_cast<QGstVideoRendererInterface*>(instance);
- if (QGstVideoRenderer *renderer = plugin ? plugin->createRenderer() : nullptr)
- m_renderers.append(renderer);
- }
-
- m_renderers.append(new QGstDefaultVideoRenderer);
- updateSupportedFormats();
- connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats()));
-}
-
-QVideoSurfaceGstDelegate::~QVideoSurfaceGstDelegate()
-{
- qDeleteAll(m_renderers);
-
- if (m_surfaceCaps)
- gst_caps_unref(m_surfaceCaps);
- if (m_startCaps)
- gst_caps_unref(m_startCaps);
-#if QT_CONFIG(gstreamer_gl)
- if (m_gstGLDisplayContext)
- gst_object_unref(m_gstGLDisplayContext);
-#endif
-}
-
-GstCaps *QVideoSurfaceGstDelegate::caps()
-{
- QMutexLocker locker(&m_mutex);
-
- gst_caps_ref(m_surfaceCaps);
-
- return m_surfaceCaps;
-}
-
-bool QVideoSurfaceGstDelegate::start(GstCaps *caps)
-{
- QMutexLocker locker(&m_mutex);
-
- if (m_activeRenderer) {
- m_flush = true;
- m_stop = true;
- }
-
- if (m_startCaps)
- gst_caps_unref(m_startCaps);
- m_startCaps = caps;
- gst_caps_ref(m_startCaps);
-
- /*
- Waiting for start() to be invoked in the main thread may block
- if gstreamer blocks the main thread until this call is finished.
- This situation is rare and usually caused by setState(Null)
- while pipeline is being prerolled.
-
- The proper solution to this involves controlling gstreamer pipeline from
- other thread than video surface.
-
- Currently start() fails if wait() timed out.
- */
- if (!waitForAsyncEvent(&locker, &m_setupCondition, 1000) && m_startCaps) {
- qWarning() << "Failed to start video surface due to main thread blocked.";
- gst_caps_unref(m_startCaps);
- m_startCaps = 0;
- }
-
- return m_activeRenderer != 0;
-}
-
-void QVideoSurfaceGstDelegate::stop()
-{
- QMutexLocker locker(&m_mutex);
-
- if (!m_activeRenderer)
- return;
-
- m_flush = true;
- m_stop = true;
-
- if (m_startCaps) {
- gst_caps_unref(m_startCaps);
- m_startCaps = 0;
- }
-
- waitForAsyncEvent(&locker, &m_setupCondition, 500);
-}
-
-void QVideoSurfaceGstDelegate::unlock()
-{
- QMutexLocker locker(&m_mutex);
-
- m_setupCondition.wakeAll();
- m_renderCondition.wakeAll();
-}
-
-bool QVideoSurfaceGstDelegate::proposeAllocation(GstQuery *query)
-{
- QMutexLocker locker(&m_mutex);
-
- if (QGstVideoRenderer *pool = m_activeRenderer) {
- locker.unlock();
-
- return pool->proposeAllocation(query);
- } else {
- return false;
- }
-}
-
-void QVideoSurfaceGstDelegate::flush()
-{
- QMutexLocker locker(&m_mutex);
-
- m_flush = true;
- m_renderBuffer = 0;
- m_renderCondition.wakeAll();
-
- notify();
-}
-
-GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
-{
- QMutexLocker locker(&m_mutex);
-
- m_renderReturn = GST_FLOW_OK;
- m_renderBuffer = buffer;
-
- waitForAsyncEvent(&locker, &m_renderCondition, 300);
-
- m_renderBuffer = 0;
-
- return m_renderReturn;
-}
-
-#if QT_CONFIG(gstreamer_gl)
-static GstGLContext *gstGLDisplayContext(QAbstractVideoSurface *surface)
-{
- auto glContext = qobject_cast<QOpenGLContext*>(surface->property("GLContext").value<QObject*>());
- // Context is not ready yet.
- if (!glContext)
- return nullptr;
-
- GstGLDisplay *display = nullptr;
- const QString platform = QGuiApplication::platformName();
- const char *contextName = "eglcontext";
- GstGLPlatform glPlatform = GST_GL_PLATFORM_EGL;
- QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface();
-
-#if GST_GL_HAVE_WINDOW_X11
- if (platform == QLatin1String("xcb")) {
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
- contextName = "glxcontext";
- glPlatform = GST_GL_PLATFORM_GLX;
- }
-
- display = (GstGLDisplay *)gst_gl_display_x11_new_with_display(
- (Display *)pni->nativeResourceForIntegration("display"));
- }
-#endif
-
-#if GST_GL_HAVE_PLATFORM_EGL
- if (!display && platform == QLatin1String("eglfs")) {
- display = (GstGLDisplay *)gst_gl_display_egl_new_with_egl_display(
- pni->nativeResourceForIntegration("egldisplay"));
- }
-#endif
-
-#if GST_CHECK_VERSION(1,11,1)
-#if GST_GL_HAVE_WINDOW_WAYLAND
- if (!display && platform.startsWith(QLatin1String("wayland"))) {
- const char *displayName = (platform == QLatin1String("wayland"))
- ? "display" : "egldisplay";
-
- display = (GstGLDisplay *)gst_gl_display_wayland_new_with_display(
- (struct wl_display *)pni->nativeResourceForIntegration(displayName));
- }
-#endif
-#endif
-
- if (!display) {
- qWarning() << "Could not create GstGLDisplay";
- return nullptr;
- }
-
- void *nativeContext = pni->nativeResourceForContext(contextName, glContext);
- if (!nativeContext)
- qWarning() << "Could not find resource for" << contextName;
-
- GstGLContext *appContext = gst_gl_context_new_wrapped(display, (guintptr)nativeContext, glPlatform, GST_GL_API_ANY);
- if (!appContext)
- qWarning() << "Could not create wrappped context for platform:" << glPlatform;
-
- GstGLContext *displayContext = nullptr;
- GError *error = nullptr;
- gst_gl_display_create_context(display, appContext, &displayContext, &error);
- if (error) {
- qWarning() << "Could not create display context:" << error->message;
- g_clear_error(&error);
- }
-
- if (appContext)
- gst_object_unref(appContext);
-
- gst_object_unref(display);
-
- return displayContext;
-}
-#endif // #if QT_CONFIG(gstreamer_gl)
-
-bool QVideoSurfaceGstDelegate::query(GstQuery *query)
-{
-#if QT_CONFIG(gstreamer_gl)
- if (GST_QUERY_TYPE(query) == GST_QUERY_CONTEXT) {
- const gchar *type;
- gst_query_parse_context_type(query, &type);
-
- if (strcmp(type, "gst.gl.local_context") != 0)
- return false;
-
- if (!m_gstGLDisplayContext)
- m_gstGLDisplayContext = gstGLDisplayContext(m_surface);
-
- // No context yet.
- if (!m_gstGLDisplayContext)
- return false;
-
- GstContext *context = nullptr;
- gst_query_parse_context(query, &context);
- context = context ? gst_context_copy(context) : gst_context_new(type, FALSE);
- GstStructure *structure = gst_context_writable_structure(context);
-#if GST_CHECK_VERSION(1,11,1)
- gst_structure_set(structure, "context", GST_TYPE_GL_CONTEXT, m_gstGLDisplayContext, nullptr);
-#else
- gst_structure_set(structure, "context", GST_GL_TYPE_CONTEXT, m_gstGLDisplayContext, nullptr);
-#endif
- gst_query_set_context(query, context);
- gst_context_unref(context);
-
- return m_gstGLDisplayContext;
- }
-#else
- Q_UNUSED(query);
-#endif
- return false;
-}
-
-bool QVideoSurfaceGstDelegate::event(QEvent *event)
-{
- if (event->type() == QEvent::UpdateRequest) {
- QMutexLocker locker(&m_mutex);
-
- if (m_notified) {
- while (handleEvent(&locker)) {}
- m_notified = false;
- }
- return true;
- } else {
- return QObject::event(event);
- }
-}
-
-bool QVideoSurfaceGstDelegate::handleEvent(QMutexLocker<QMutex> *locker)
-{
- if (m_flush) {
- m_flush = false;
- if (m_activeRenderer) {
- locker->unlock();
-
- m_activeRenderer->flush(m_surface);
- }
- } else if (m_stop) {
- m_stop = false;
-
- if (QGstVideoRenderer * const activePool = m_activeRenderer) {
- m_activeRenderer = 0;
- locker->unlock();
-
- activePool->stop(m_surface);
-
- locker->relock();
- }
- } else if (m_startCaps) {
- Q_ASSERT(!m_activeRenderer);
-
- GstCaps * const startCaps = m_startCaps;
- m_startCaps = 0;
-
- if (m_renderer && m_surface) {
- locker->unlock();
-
- const bool started = m_renderer->start(m_surface, startCaps);
-
- locker->relock();
-
- m_activeRenderer = started
- ? m_renderer
- : 0;
- } else if (QGstVideoRenderer * const activePool = m_activeRenderer) {
- m_activeRenderer = 0;
- locker->unlock();
-
- activePool->stop(m_surface);
-
- locker->relock();
- }
-
- gst_caps_unref(startCaps);
- } else if (m_renderBuffer) {
- GstBuffer *buffer = m_renderBuffer;
- m_renderBuffer = 0;
- m_renderReturn = GST_FLOW_ERROR;
-
- if (m_activeRenderer && m_surface) {
- gst_buffer_ref(buffer);
-
- locker->unlock();
-
- const bool rendered = m_activeRenderer->present(m_surface, buffer);
-
- gst_buffer_unref(buffer);
-
- locker->relock();
-
- if (rendered)
- m_renderReturn = GST_FLOW_OK;
- }
-
- m_renderCondition.wakeAll();
- } else {
- m_setupCondition.wakeAll();
-
- return false;
- }
- return true;
-}
-
-void QVideoSurfaceGstDelegate::notify()
-{
- if (!m_notified) {
- m_notified = true;
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
- }
-}
-
-bool QVideoSurfaceGstDelegate::waitForAsyncEvent(
- QMutexLocker<QMutex> *locker, QWaitCondition *condition, unsigned long time)
-{
- if (QThread::currentThread() == thread()) {
- while (handleEvent(locker)) {}
- m_notified = false;
-
- return true;
- } else {
- notify();
-
- return condition->wait(&m_mutex, time);
- }
-}
-
-void QVideoSurfaceGstDelegate::updateSupportedFormats()
-{
- if (m_surfaceCaps) {
- gst_caps_unref(m_surfaceCaps);
- m_surfaceCaps = 0;
- }
-
- for (QGstVideoRenderer *pool : qAsConst(m_renderers)) {
- if (GstCaps *caps = pool->getCaps(m_surface)) {
- if (gst_caps_is_empty(caps)) {
- gst_caps_unref(caps);
- continue;
- }
-
- if (m_surfaceCaps)
- gst_caps_unref(m_surfaceCaps);
-
- m_renderer = pool;
- m_surfaceCaps = caps;
- break;
- } else {
- gst_caps_unref(caps);
- }
- }
-}
-
-static GstVideoSinkClass *sink_parent_class;
-static QAbstractVideoSurface *current_surface;
-
-#define VO_SINK(s) QGstVideoRendererSink *sink(reinterpret_cast<QGstVideoRendererSink *>(s))
-
-QGstVideoRendererSink *QGstVideoRendererSink::createSink(QAbstractVideoSurface *surface)
-{
- setSurface(surface);
- QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(
- g_object_new(QGstVideoRendererSink::get_type(), 0));
-
- g_signal_connect(G_OBJECT(sink), "notify::show-preroll-frame", G_CALLBACK(handleShowPrerollChange), sink);
-
- return sink;
-}
-
-void QGstVideoRendererSink::setSurface(QAbstractVideoSurface *surface)
-{
- current_surface = surface;
- get_type();
-}
-
-GType QGstVideoRendererSink::get_type()
-{
- static GType type = 0;
-
- if (type == 0) {
- static const GTypeInfo info =
- {
- sizeof(QGstVideoRendererSinkClass), // class_size
- base_init, // base_init
- nullptr, // base_finalize
- class_init, // class_init
- nullptr, // class_finalize
- nullptr, // class_data
- sizeof(QGstVideoRendererSink), // instance_size
- 0, // n_preallocs
- instance_init, // instance_init
- 0 // value_table
- };
-
- type = g_type_register_static(
- GST_TYPE_VIDEO_SINK, "QGstVideoRendererSink", &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, "qtvideosink", GST_RANK_PRIMARY, type);
- }
-
- return type;
-}
-
-void QGstVideoRendererSink::class_init(gpointer g_class, gpointer class_data)
-{
- Q_UNUSED(class_data);
-
- sink_parent_class = reinterpret_cast<GstVideoSinkClass *>(g_type_class_peek_parent(g_class));
-
- GstVideoSinkClass *video_sink_class = reinterpret_cast<GstVideoSinkClass *>(g_class);
- video_sink_class->show_frame = QGstVideoRendererSink::show_frame;
-
- GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class);
- base_sink_class->get_caps = QGstVideoRendererSink::get_caps;
- base_sink_class->set_caps = QGstVideoRendererSink::set_caps;
- base_sink_class->propose_allocation = QGstVideoRendererSink::propose_allocation;
- base_sink_class->stop = QGstVideoRendererSink::stop;
- base_sink_class->unlock = QGstVideoRendererSink::unlock;
- base_sink_class->query = QGstVideoRendererSink::query;
-
- GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class);
- element_class->change_state = QGstVideoRendererSink::change_state;
- gst_element_class_set_metadata(element_class,
- "Qt built-in video renderer sink",
- "Sink/Video",
- "Qt default built-in video renderer sink",
- "The Qt Company");
-
- GObjectClass *object_class = reinterpret_cast<GObjectClass *>(g_class);
- object_class->finalize = QGstVideoRendererSink::finalize;
-}
-
-void QGstVideoRendererSink::base_init(gpointer g_class)
-{
- static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE(
- "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS(
- "video/x-raw, "
- "framerate = (fraction) [ 0, MAX ], "
- "width = (int) [ 1, MAX ], "
- "height = (int) [ 1, MAX ]"));
-
- gst_element_class_add_pad_template(
- GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template));
-}
-
-struct NullSurface : QAbstractVideoSurface
-{
- NullSurface(QObject *parent = nullptr) : QAbstractVideoSurface(parent) { }
-
- QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType) const override
- {
- return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_RGB32;
- }
-
- bool present(const QVideoFrame &) override
- {
- return true;
- }
-};
-
-void QGstVideoRendererSink::instance_init(GTypeInstance *instance, gpointer g_class)
-{
- Q_UNUSED(g_class);
- VO_SINK(instance);
-
- if (!current_surface) {
- qWarning() << "Using qtvideosink element without video surface";
- static NullSurface nullSurface;
- current_surface = &nullSurface;
- }
-
- sink->delegate = new QVideoSurfaceGstDelegate(current_surface);
- sink->delegate->moveToThread(current_surface->thread());
- current_surface = nullptr;
-}
-
-void QGstVideoRendererSink::finalize(GObject *object)
-{
- VO_SINK(object);
-
- delete sink->delegate;
-
- // Chain up
- G_OBJECT_CLASS(sink_parent_class)->finalize(object);
-}
-
-void QGstVideoRendererSink::handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d)
-{
- Q_UNUSED(o);
- Q_UNUSED(p);
- QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(d);
-
- gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
- g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, nullptr);
-
- if (!showPrerollFrame) {
- GstState state = GST_STATE_VOID_PENDING;
- GstClockTime timeout = 10000000; // 10 ms
- gst_element_get_state(GST_ELEMENT(sink), &state, nullptr, timeout);
- // show-preroll-frame being set to 'false' while in GST_STATE_PAUSED means
- // the QMediaPlayer was stopped from the paused state.
- // We need to flush the current frame.
- if (state == GST_STATE_PAUSED)
- sink->delegate->flush();
- }
-}
-
-GstStateChangeReturn QGstVideoRendererSink::change_state(
- GstElement *element, GstStateChange transition)
-{
- QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(element);
-
- gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default
- g_object_get(G_OBJECT(element), "show-preroll-frame", &showPrerollFrame, nullptr);
-
- // If show-preroll-frame is 'false' when transitioning from GST_STATE_PLAYING to
- // GST_STATE_PAUSED, it means the QMediaPlayer was stopped.
- // We need to flush the current frame.
- if (transition == GST_STATE_CHANGE_PLAYING_TO_PAUSED && !showPrerollFrame)
- sink->delegate->flush();
-
- return GST_ELEMENT_CLASS(sink_parent_class)->change_state(element, transition);
-}
-
-GstCaps *QGstVideoRendererSink::get_caps(GstBaseSink *base, GstCaps *filter)
-{
- VO_SINK(base);
-
- GstCaps *caps = sink->delegate->caps();
- GstCaps *unfiltered = caps;
- if (filter) {
- caps = gst_caps_intersect(unfiltered, filter);
- gst_caps_unref(unfiltered);
- }
-
- return caps;
-}
-
-gboolean QGstVideoRendererSink::set_caps(GstBaseSink *base, GstCaps *caps)
-{
- VO_SINK(base);
-
-#ifdef DEBUG_VIDEO_SURFACE_SINK
- qDebug() << "set_caps:";
- qDebug() << caps;
-#endif
-
- if (!caps) {
- sink->delegate->stop();
-
- return TRUE;
- } else if (sink->delegate->start(caps)) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-gboolean QGstVideoRendererSink::propose_allocation(GstBaseSink *base, GstQuery *query)
-{
- VO_SINK(base);
- return sink->delegate->proposeAllocation(query);
-}
-
-gboolean QGstVideoRendererSink::stop(GstBaseSink *base)
-{
- VO_SINK(base);
- sink->delegate->stop();
- return TRUE;
-}
-
-gboolean QGstVideoRendererSink::unlock(GstBaseSink *base)
-{
- VO_SINK(base);
- sink->delegate->unlock();
- return TRUE;
-}
-
-GstFlowReturn QGstVideoRendererSink::show_frame(GstVideoSink *base, GstBuffer *buffer)
-{
- VO_SINK(base);
- return sink->delegate->render(buffer);
-}
-
-gboolean QGstVideoRendererSink::query(GstBaseSink *base, GstQuery *query)
-{
- VO_SINK(base);
- if (sink->delegate->query(query))
- return TRUE;
-
- return GST_BASE_SINK_CLASS(sink_parent_class)->query(base, query);
-}
-
-QT_END_NAMESPACE