Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
12
13static GstBaseSinkClass *gst_sink_parent_class;
15
16#define ST_SINK(s) QGstSubtitleSink *sink(reinterpret_cast<QGstSubtitleSink *>(s))
17
19{
21
22 QGstSubtitleSink *gstSink = reinterpret_cast<QGstSubtitleSink *>(
23 g_object_new(QGstSubtitleSink::get_type(), nullptr));
24 g_object_set(gstSink, "async", false, nullptr);
25
26 return gstSink;
27}
28
29GType QGstSubtitleSink::get_type()
30{
31 static const GTypeInfo info =
32 {
33 sizeof(QGstSubtitleSinkClass), // class_size
34 base_init, // base_init
35 nullptr, // base_finalize
36 class_init, // class_init
37 nullptr, // class_finalize
38 nullptr, // class_data
39 sizeof(QGstSubtitleSink), // instance_size
40 0, // n_preallocs
41 instance_init, // instance_init
42 nullptr // value_table
43 };
44
45 static const GType type = []() {
46 const auto result = g_type_register_static(
47 GST_TYPE_BASE_SINK, "QGstSubtitleSink", &info, GTypeFlags(0));
48
49 // Register the sink type to be used in custom piplines.
50 // When surface is ready the sink can be used.
51 gst_element_register(nullptr, "qtsubtitlesink", GST_RANK_PRIMARY, result);
52
53 return result;
54 }();
55
56 return type;
57}
58
59void QGstSubtitleSink::class_init(gpointer g_class, gpointer class_data)
60{
61 Q_UNUSED(class_data);
62
63 gst_sink_parent_class = reinterpret_cast<GstBaseSinkClass *>(g_type_class_peek_parent(g_class));
64
65 GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class);
66 base_sink_class->render = QGstSubtitleSink::render;
67 base_sink_class->get_caps = QGstSubtitleSink::get_caps;
68 base_sink_class->set_caps = QGstSubtitleSink::set_caps;
69 base_sink_class->propose_allocation = QGstSubtitleSink::propose_allocation;
70 base_sink_class->wait_event = QGstSubtitleSink::wait_event;
71
72 GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class);
73 element_class->change_state = QGstSubtitleSink::change_state;
74 gst_element_class_set_metadata(element_class,
75 "Qt built-in subtitle sink",
76 "Sink/Subtitle",
77 "Qt default built-in subtitle sink",
78 "The Qt Company");
79
80 GObjectClass *object_class = reinterpret_cast<GObjectClass *>(g_class);
81 object_class->finalize = QGstSubtitleSink::finalize;
82}
83
84void QGstSubtitleSink::base_init(gpointer g_class)
85{
86 static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE(
87 "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("ANY"));
88
89 gst_element_class_add_pad_template(
90 GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template));
91}
92
93void QGstSubtitleSink::instance_init(GTypeInstance *instance, gpointer g_class)
94{
95 Q_UNUSED(g_class);
96 ST_SINK(instance);
97
99 sink->sink = gst_current_sink;
100 gst_current_sink = nullptr;
101}
102
103void QGstSubtitleSink::finalize(GObject *object)
104{
105 // Chain up
106 G_OBJECT_CLASS(gst_sink_parent_class)->finalize(object);
107}
108
109GstStateChangeReturn QGstSubtitleSink::change_state(GstElement *element, GstStateChange transition)
110{
111 return GST_ELEMENT_CLASS(gst_sink_parent_class)->change_state(element, transition);
112}
113
114GstCaps *QGstSubtitleSink::get_caps(GstBaseSink *base, GstCaps *filter)
115{
116 return gst_sink_parent_class->get_caps(base, filter);
117}
118
119gboolean QGstSubtitleSink::set_caps(GstBaseSink *base, GstCaps *caps)
120{
121 qDebug() << "set_caps:" << caps;
122 return gst_sink_parent_class->set_caps(base, caps);
123}
124
125gboolean QGstSubtitleSink::propose_allocation(GstBaseSink *base, GstQuery *query)
126{
127 return gst_sink_parent_class->propose_allocation(base, query);
128}
129
130GstFlowReturn QGstSubtitleSink::wait_event(GstBaseSink *base, GstEvent *event)
131{
132 GstFlowReturn retval = gst_sink_parent_class->wait_event(base, event);
133 ST_SINK(base);
134 if (event->type == GST_EVENT_GAP) {
135// qDebug() << "gap, clearing subtitle";
136 sink->sink->setSubtitleText(QString());
137 }
138 return retval;
139}
140
141GstFlowReturn QGstSubtitleSink::render(GstBaseSink *base, GstBuffer *buffer)
142{
143 ST_SINK(base);
144 GstMemory *mem = gst_buffer_get_memory(buffer, 0);
145 GstMapInfo info;
146 QString subtitle;
147 if (gst_memory_map(mem, &info, GST_MAP_READ))
148 subtitle = QString::fromUtf8(reinterpret_cast<const char *>(info.data));
149 gst_memory_unmap(mem, &info);
150// qDebug() << "render" << buffer << subtitle;
151 sink->sink->setSubtitleText(subtitle);
152 return GST_FLOW_OK;
153}
154
static QGstSubtitleSink * createSink(QGstreamerVideoSink *sink)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
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:164
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)
static const uint base
Definition qurlidna.cpp:20
QHostInfo info
[0]