Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
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
5#include "qgst_debug_p.h"
6
7#include <QtCore/qdebug.h>
8
10
11namespace {
14
20
21} // namespace
22
23#define ST_SINK(s) QGstSubtitleSink *sink(reinterpret_cast<QGstSubtitleSink *>(s))
24
26{
27 gst_current_observer = observer;
28
29 QGstSubtitleSink *gstSink = reinterpret_cast<QGstSubtitleSink *>(
30 g_object_new(QGstSubtitleSink::get_type(), nullptr));
31
32 return QGstElement{
33 qGstCheckedCast<GstElement>(gstSink),
34 QGstElement::NeedsRef,
35 };
36}
37
38GType QGstSubtitleSink::get_type()
39{
40 // clang-format off
41 static constexpr GTypeInfo info =
42 {
43 sizeof(QGstSubtitleSinkClass), // class_size
44 base_init, // base_init
45 nullptr, // base_finalize
46 class_init, // class_init
47 nullptr, // class_finalize
48 nullptr, // class_data
49 sizeof(QGstSubtitleSink), // instance_size
50 0, // n_preallocs
51 instance_init, // instance_init
52 nullptr // value_table
53 };
54 // clang-format on
55
56 static const GType type = []() {
57 const auto result = g_type_register_static(
58 GST_TYPE_BASE_SINK, "QGstSubtitleSink", &info, GTypeFlags(0));
59 return result;
60 }();
61
62 return type;
63}
64
65void QGstSubtitleSink::class_init(gpointer g_class, gpointer class_data)
66{
67 Q_UNUSED(class_data);
68
69 gst_sink_parent_class = reinterpret_cast<GstBaseSinkClass *>(g_type_class_peek_parent(g_class));
70
71 GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(g_class);
72 base_sink_class->render = QGstSubtitleSink::render;
73 base_sink_class->get_caps = QGstSubtitleSink::get_caps;
74 base_sink_class->set_caps = QGstSubtitleSink::set_caps;
75 base_sink_class->propose_allocation = QGstSubtitleSink::propose_allocation;
76 base_sink_class->wait_event = QGstSubtitleSink::wait_event;
77
78 GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class);
79 element_class->change_state = QGstSubtitleSink::change_state;
80 gst_element_class_set_metadata(element_class,
81 "Qt built-in subtitle sink",
82 "Sink/Subtitle",
83 "Qt default built-in subtitle sink",
84 "The Qt Company");
85
86 GObjectClass *object_class = reinterpret_cast<GObjectClass *>(g_class);
87 object_class->finalize = QGstSubtitleSink::finalize;
88}
89
90void QGstSubtitleSink::base_init(gpointer g_class)
91{
92 static GstStaticPadTemplate sink_pad_template =
93 GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS("ANY"));
94
95 gst_element_class_add_pad_template(
96 GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template));
97}
98
99void QGstSubtitleSink::instance_init(GTypeInstance *instance, gpointer /*g_class*/)
100{
101 ST_SINK(instance);
102
103 Q_ASSERT(gst_current_observer);
104 sink->observer = gst_current_observer;
105 gst_current_observer = nullptr;
106}
107
108void QGstSubtitleSink::finalize(GObject *object)
109{
110 // Chain up
111 G_OBJECT_CLASS(gst_sink_parent_class)->finalize(object);
112}
113
114GstStateChangeReturn QGstSubtitleSink::change_state(GstElement *element, GstStateChange transition)
115{
116 return GST_ELEMENT_CLASS(gst_sink_parent_class)->change_state(element, transition);
117}
118
119GstCaps *QGstSubtitleSink::get_caps(GstBaseSink *base, GstCaps *filter)
120{
121 return gst_sink_parent_class->get_caps(base, filter);
122}
123
124gboolean QGstSubtitleSink::set_caps(GstBaseSink *base, GstCaps *caps)
125{
126 qDebug() << "set_caps:" << caps;
127 return gst_sink_parent_class->set_caps(base, caps);
128}
129
130gboolean QGstSubtitleSink::propose_allocation(GstBaseSink *base, GstQuery *query)
131{
132 return gst_sink_parent_class->propose_allocation(base, query);
133}
134
135GstFlowReturn QGstSubtitleSink::wait_event(GstBaseSink *base, GstEvent *event)
136{
137 GstFlowReturn retval = gst_sink_parent_class->wait_event(base, event);
138 ST_SINK(base);
139 if (event->type == GST_EVENT_GAP) {
140 // qDebug() << "gap, clearing subtitle";
141 sink->observer->updateSubtitle(QString());
142 }
143 return retval;
144}
145
146GstFlowReturn QGstSubtitleSink::render(GstBaseSink *base, GstBuffer *buffer)
147{
148 ST_SINK(base);
149 GstMemory *mem = gst_buffer_get_memory(buffer, 0);
150 GstMapInfo info;
151 QString subtitle;
152 if (gst_memory_map(mem, &info, GST_MAP_READ))
153 subtitle = QString::fromUtf8(reinterpret_cast<const char *>(info.data));
154 gst_memory_unmap(mem, &info);
155// qDebug() << "render" << buffer << subtitle;
156 sink->observer->updateSubtitle(subtitle);
157 return GST_FLOW_OK;
158}
159
160QT_END_NAMESPACE
static QGstElement createSink(QAbstractSubtitleObserver *observer)
Combined button and popup list for selecting options.
GstBaseSinkClass * gst_sink_parent_class
thread_local QAbstractSubtitleObserver * gst_current_observer
#define ST_SINK(s)