Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qgstsubtitlesink.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QDebug>
5#include <QThread>
6#include <QEvent>
7
10#include "qgstutils_p.h"
11
13
14static GstBaseSinkClass *gst_sink_parent_class;
16
17#define ST_SINK(s) QGstSubtitleSink *sink(reinterpret_cast<QGstSubtitleSink *>(s))
18
20{
22
23 QGstSubtitleSink *gstSink = reinterpret_cast<QGstSubtitleSink *>(
24 g_object_new(QGstSubtitleSink::get_type(), nullptr));
25 g_object_set(gstSink, "async", false, nullptr);
26
27 return gstSink;
28}
29
30GType QGstSubtitleSink::get_type()
31{
32 static const GTypeInfo info =
33 {
34 sizeof(QGstSubtitleSinkClass), // class_size
35 base_init, // base_init
36 nullptr, // base_finalize
37 class_init, // class_init
38 nullptr, // class_finalize
39 nullptr, // class_data
40 sizeof(QGstSubtitleSink), // instance_size
41 0, // n_preallocs
42 instance_init, // instance_init
43 nullptr // value_table
44 };
45
46 static const GType type = []() {
47 const auto result = g_type_register_static(
48 GST_TYPE_BASE_SINK, "QGstSubtitleSink", &info, GTypeFlags(0));
49
50 // Register the sink type to be used in custom piplines.
51 // When surface is ready the sink can be used.
52 gst_element_register(nullptr, "qtsubtitlesink", GST_RANK_PRIMARY, result);
53
54 return result;
55 }();
56
57 return type;
58}
59
60void QGstSubtitleSink::class_init(gpointer g_class, gpointer class_data)
61{
62 Q_UNUSED(class_data);
63
64 gst_sink_parent_class = reinterpret_cast<GstBaseSinkClass *>(g_type_class_peek_parent(g_class));
65
66 GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class);
67 base_sink_class->render = QGstSubtitleSink::render;
68 base_sink_class->get_caps = QGstSubtitleSink::get_caps;
69 base_sink_class->set_caps = QGstSubtitleSink::set_caps;
70 base_sink_class->propose_allocation = QGstSubtitleSink::propose_allocation;
71 base_sink_class->wait_event = QGstSubtitleSink::wait_event;
72
73 GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class);
74 element_class->change_state = QGstSubtitleSink::change_state;
75 gst_element_class_set_metadata(element_class,
76 "Qt built-in subtitle sink",
77 "Sink/Subtitle",
78 "Qt default built-in subtitle sink",
79 "The Qt Company");
80
81 GObjectClass *object_class = reinterpret_cast<GObjectClass *>(g_class);
82 object_class->finalize = QGstSubtitleSink::finalize;
83}
84
85void QGstSubtitleSink::base_init(gpointer g_class)
86{
87 static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE(
88 "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("ANY"));
89
90 gst_element_class_add_pad_template(
91 GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template));
92}
93
94void QGstSubtitleSink::instance_init(GTypeInstance *instance, gpointer g_class)
95{
96 Q_UNUSED(g_class);
97 ST_SINK(instance);
98
100 sink->sink = gst_current_sink;
101 gst_current_sink = nullptr;
102}
103
104void QGstSubtitleSink::finalize(GObject *object)
105{
106 // Chain up
107 G_OBJECT_CLASS(gst_sink_parent_class)->finalize(object);
108}
109
110GstStateChangeReturn QGstSubtitleSink::change_state(GstElement *element, GstStateChange transition)
111{
112 return GST_ELEMENT_CLASS(gst_sink_parent_class)->change_state(element, transition);
113}
114
115GstCaps *QGstSubtitleSink::get_caps(GstBaseSink *base, GstCaps *filter)
116{
117 return gst_sink_parent_class->get_caps(base, filter);
118}
119
120gboolean QGstSubtitleSink::set_caps(GstBaseSink *base, GstCaps *caps)
121{
122 qDebug() << "set_caps:" << QGstCaps::toString(caps);
123 return gst_sink_parent_class->set_caps(base, caps);
124}
125
126gboolean QGstSubtitleSink::propose_allocation(GstBaseSink *base, GstQuery *query)
127{
128 return gst_sink_parent_class->propose_allocation(base, query);
129}
130
131GstFlowReturn QGstSubtitleSink::wait_event(GstBaseSink *base, GstEvent *event)
132{
133 GstFlowReturn retval = gst_sink_parent_class->wait_event(base, event);
134 ST_SINK(base);
135 if (event->type == GST_EVENT_GAP) {
136// qDebug() << "gap, clearing subtitle";
137 sink->sink->setSubtitleText(QString());
138 }
139 return retval;
140}
141
142GstFlowReturn QGstSubtitleSink::render(GstBaseSink *base, GstBuffer *buffer)
143{
144 ST_SINK(base);
145 GstMemory *mem = gst_buffer_get_memory(buffer, 0);
146 GstMapInfo info;
147 QString subtitle;
148 if (gst_memory_map(mem, &info, GST_MAP_READ))
149 subtitle = QString::fromUtf8(info.data);
150 gst_memory_unmap(mem, &info);
151// qDebug() << "render" << buffer << subtitle;
152 sink->sink->setSubtitleText(subtitle);
153 return GST_FLOW_OK;
154}
155
QByteArray toString() const
Definition qgst_p.h:199
static QGstSubtitleSink * createSink(QGstreamerVideoSink *sink)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
Combined button and popup list for selecting options.
static thread_local QGstreamerVideoSink * gst_current_sink
#define ST_SINK(s)
static QT_BEGIN_NAMESPACE GstBaseSinkClass * gst_sink_parent_class
#define qDebug
[1]
Definition qlogging.h:160
GLenum GLuint buffer
GLenum type
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
struct _cl_event * event
GLenum query
GLsizei GLenum GLboolean sink
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_UNUSED(x)
QFileInfo info(fileName)
[8]