Line data Source code
1 : /*
2 : * Copyright (C) 2024 Sky UK
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Lesser General Public
6 : * License as published by the Free Software Foundation;
7 : * version 2.1 of the License.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Lesser General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public
15 : * License along with this library; if not, write to the Free Software
16 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 : */
18 :
19 : #include <gst/gst.h>
20 : #include <inttypes.h>
21 : #include <stdint.h>
22 :
23 : #include "GStreamerEMEUtils.h"
24 : #include "GStreamerMSEUtils.h"
25 : #include "IMediaPipelineCapabilities.h"
26 : #include "PullModeSubtitlePlaybackDelegate.h"
27 : #include "RialtoGStreamerMSEBaseSinkPrivate.h"
28 : #include "RialtoGStreamerMSESubtitleSink.h"
29 :
30 : using namespace firebolt::rialto::client;
31 :
32 : GST_DEBUG_CATEGORY_STATIC(RialtoMSESubtitleSinkDebug);
33 : #define GST_CAT_DEFAULT RialtoMSESubtitleSinkDebug
34 :
35 : #define rialto_mse_subtitle_sink_parent_class parent_class
36 65 : G_DEFINE_TYPE_WITH_CODE(RialtoMSESubtitleSink, rialto_mse_subtitle_sink, RIALTO_TYPE_MSE_BASE_SINK,
37 : GST_DEBUG_CATEGORY_INIT(RialtoMSESubtitleSinkDebug, "rialtomsesubtitlesink", 0,
38 : "rialto mse subtitle sink"));
39 :
40 : enum
41 : {
42 : PROP_0,
43 : PROP_MUTE,
44 : PROP_TEXT_TRACK_IDENTIFIER,
45 : PROP_WINDOW_ID,
46 : PROP_ASYNC,
47 : PROP_LAST
48 : };
49 :
50 62 : static GstStateChangeReturn rialto_mse_subtitle_sink_change_state(GstElement *element, GstStateChange transition)
51 : {
52 62 : RialtoMSESubtitleSink *sink = RIALTO_MSE_SUBTITLE_SINK(element);
53 :
54 62 : if (GST_STATE_CHANGE_NULL_TO_READY == transition)
55 : {
56 20 : GST_INFO_OBJECT(sink, "RialtoMSESubtitleSink state change to READY. Initializing delegate");
57 20 : auto delegate = std::make_shared<PullModeSubtitlePlaybackDelegate>(element);
58 20 : delegate->createControlBackend();
59 20 : rialto_mse_base_sink_initialise_delegate(RIALTO_MSE_BASE_SINK(sink), delegate);
60 : }
61 :
62 62 : GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
63 62 : if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE))
64 : {
65 1 : GST_WARNING_OBJECT(sink, "State change failed");
66 1 : return result;
67 : }
68 :
69 61 : return result;
70 : }
71 :
72 7 : static void rialto_mse_subtitle_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec)
73 : {
74 7 : switch (propId)
75 : {
76 2 : case PROP_MUTE:
77 : {
78 2 : g_value_set_boolean(value, FALSE); // Set default value first
79 2 : rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Mute, value);
80 2 : break;
81 : }
82 2 : case PROP_TEXT_TRACK_IDENTIFIER:
83 : {
84 2 : g_value_set_string(value, ""); // Set default value first
85 2 : rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object),
86 2 : IPlaybackDelegate::Property::TextTrackIdentifier, value);
87 2 : break;
88 : }
89 1 : case PROP_WINDOW_ID:
90 : {
91 1 : g_value_set_uint(value, 0); // Set default value first
92 1 : rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowId,
93 : value);
94 1 : break;
95 : }
96 1 : case PROP_ASYNC:
97 : {
98 1 : g_value_set_boolean(value, FALSE); // Set default value first
99 1 : rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Async, value);
100 1 : break;
101 : }
102 1 : default:
103 1 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
104 1 : break;
105 : }
106 7 : }
107 :
108 10 : static void rialto_mse_subtitle_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec)
109 : {
110 10 : switch (propId)
111 : {
112 3 : case PROP_MUTE:
113 3 : rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Mute, value);
114 3 : break;
115 4 : case PROP_TEXT_TRACK_IDENTIFIER:
116 : {
117 4 : rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object),
118 4 : IPlaybackDelegate::Property::TextTrackIdentifier, value);
119 4 : break;
120 : }
121 1 : case PROP_WINDOW_ID:
122 : {
123 1 : rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowId,
124 : value);
125 1 : break;
126 : }
127 1 : case PROP_ASYNC:
128 : {
129 1 : rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Async, value);
130 1 : break;
131 : }
132 1 : default:
133 1 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
134 1 : break;
135 : }
136 10 : }
137 :
138 20 : static void rialto_mse_subtitle_sink_init(RialtoMSESubtitleSink *sink)
139 : {
140 20 : RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv;
141 :
142 20 : if (!rialto_mse_base_sink_initialise_sinkpad(RIALTO_MSE_BASE_SINK(sink)))
143 : {
144 0 : GST_ERROR_OBJECT(sink, "Failed to initialise SUBTITLE sink. Sink pad initialisation failed.");
145 0 : return;
146 : }
147 :
148 20 : gst_pad_set_chain_function(basePriv->m_sinkPad, rialto_mse_base_sink_chain);
149 20 : gst_pad_set_event_function(basePriv->m_sinkPad, rialto_mse_base_sink_event);
150 : }
151 :
152 1 : static void rialto_mse_subtitle_sink_class_init(RialtoMSESubtitleSinkClass *klass)
153 : {
154 1 : GObjectClass *gobjectClass = G_OBJECT_CLASS(klass);
155 1 : GstElementClass *elementClass = GST_ELEMENT_CLASS(klass);
156 1 : gobjectClass->get_property = rialto_mse_subtitle_sink_get_property;
157 1 : gobjectClass->set_property = rialto_mse_subtitle_sink_set_property;
158 1 : elementClass->change_state = rialto_mse_subtitle_sink_change_state;
159 :
160 1 : g_object_class_install_property(gobjectClass, PROP_MUTE,
161 : g_param_spec_boolean("mute", "Mute", "Mute subtitles", FALSE, G_PARAM_READWRITE));
162 :
163 1 : g_object_class_install_property(gobjectClass, PROP_TEXT_TRACK_IDENTIFIER,
164 : g_param_spec_string("text-track-identifier", "Text Track Identifier",
165 : "Identifier of text track. Valid input for service is "
166 : "\"CC[1-4]\", \"TEXT[1-4]\", \"SERVICE[1-64]\"",
167 : nullptr, GParamFlags(G_PARAM_READWRITE)));
168 :
169 1 : g_object_class_install_property(gobjectClass, PROP_WINDOW_ID,
170 : g_param_spec_uint("window-id", "Window ID", "Id of window (placeholder)", 0, 256, 0,
171 : GParamFlags(G_PARAM_READWRITE)));
172 :
173 1 : g_object_class_install_property(gobjectClass, PROP_ASYNC,
174 : g_param_spec_boolean("async", "Async", "Asynchronous mode", FALSE, G_PARAM_READWRITE));
175 :
176 : std::unique_ptr<firebolt::rialto::IMediaPipelineCapabilities> mediaPlayerCapabilities =
177 1 : firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities();
178 1 : if (mediaPlayerCapabilities)
179 : {
180 : std::vector<std::string> supportedMimeTypes =
181 1 : mediaPlayerCapabilities->getSupportedMimeTypes(firebolt::rialto::MediaSourceType::SUBTITLE);
182 :
183 1 : rialto_mse_sink_setup_supported_caps(elementClass, supportedMimeTypes);
184 : }
185 : else
186 : {
187 0 : GST_ERROR("Failed to get supported mime types for Subtitle");
188 : }
189 :
190 1 : gst_element_class_set_details_simple(elementClass, "Rialto Subtitle Sink", "Parser/Subtitle/Sink/Subtitle",
191 : "Communicates with Rialto Server", "Sky");
192 : }
|