Line data Source code
1 : /*
2 : * Copyright (C) 2022 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 "RialtoGStreamerMSEBaseSinkPrivate.h"
27 : #include "RialtoGStreamerMSEVideoSink.h"
28 : #include "RialtoGStreamerMSEVideoSinkPrivate.h"
29 :
30 : using namespace firebolt::rialto::client;
31 :
32 : GST_DEBUG_CATEGORY_STATIC(RialtoMSEVideoSinkDebug);
33 : #define GST_CAT_DEFAULT RialtoMSEVideoSinkDebug
34 :
35 : #define rialto_mse_video_sink_parent_class parent_class
36 244 : G_DEFINE_TYPE_WITH_CODE(RialtoMSEVideoSink, rialto_mse_video_sink, RIALTO_TYPE_MSE_BASE_SINK,
37 : G_ADD_PRIVATE(RialtoMSEVideoSink)
38 : GST_DEBUG_CATEGORY_INIT(RialtoMSEVideoSinkDebug, "rialtomsevideosink", 0,
39 : "rialto mse video sink"));
40 :
41 : enum
42 : {
43 : PROP_0,
44 : PROP_WINDOW_SET,
45 : PROP_MAX_VIDEO_WIDTH,
46 : PROP_MAX_VIDEO_HEIGHT,
47 : PROP_MAX_VIDEO_WIDTH_DEPRECATED,
48 : PROP_MAX_VIDEO_HEIGHT_DEPRECATED,
49 : PROP_FRAME_STEP_ON_PREROLL,
50 : PROP_IMMEDIATE_OUTPUT,
51 : PROP_SYNCMODE_STREAMING,
52 : PROP_SHOW_VIDEO_WINDOW,
53 : PROP_LAST
54 : };
55 :
56 116 : static GstStateChangeReturn rialto_mse_video_sink_change_state(GstElement *element, GstStateChange transition)
57 : {
58 116 : RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(element);
59 116 : RialtoMSEVideoSinkPrivate *priv = sink->priv;
60 116 : RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv;
61 :
62 116 : switch (transition)
63 : {
64 28 : case GST_STATE_CHANGE_READY_TO_PAUSED:
65 : {
66 : // Attach the media player client to media player manager.
67 : // maxWidth and maxHeight are used to set the video capabilities of the MediaPlayer.
68 : // If the mediaPlayer has already been created (ie. an audio sink on the same parent bus changed state first)
69 : // the video capabilities will NOT be set.
70 28 : if (!rialto_mse_base_sink_attach_to_media_client_and_set_streams_number(element, priv->maxWidth, priv->maxHeight))
71 : {
72 1 : return GST_STATE_CHANGE_FAILURE;
73 : }
74 :
75 27 : std::shared_ptr<GStreamerMSEMediaPlayerClient> client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
76 27 : if (!client)
77 : {
78 0 : GST_ERROR_OBJECT(sink, "MediaPlayerClient is nullptr");
79 0 : return GST_STATE_CHANGE_FAILURE;
80 : }
81 :
82 27 : std::unique_lock lock{priv->propertyMutex};
83 27 : if (priv->rectangleSettingQueued)
84 : {
85 1 : GST_DEBUG_OBJECT(sink, "Set queued video rectangle");
86 1 : priv->rectangleSettingQueued = false;
87 1 : client->setVideoRectangle(priv->videoRectangle);
88 : }
89 27 : break;
90 54 : }
91 88 : default:
92 88 : break;
93 : }
94 :
95 115 : GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
96 115 : if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE))
97 : {
98 0 : GST_WARNING_OBJECT(sink, "State change failed");
99 0 : return result;
100 : }
101 :
102 115 : return result;
103 : }
104 :
105 : static std::unique_ptr<firebolt::rialto::IMediaPipeline::MediaSource>
106 27 : rialto_mse_video_sink_create_media_source(RialtoMSEBaseSink *sink, GstCaps *caps)
107 : {
108 27 : GstStructure *structure = gst_caps_get_structure(caps, 0);
109 27 : const gchar *strct_name = gst_structure_get_name(structure);
110 :
111 27 : firebolt::rialto::SegmentAlignment alignment = rialto_mse_base_sink_get_segment_alignment(sink, structure);
112 27 : std::shared_ptr<firebolt::rialto::CodecData> codecData = rialto_mse_base_sink_get_codec_data(sink, structure);
113 27 : firebolt::rialto::StreamFormat format = rialto_mse_base_sink_get_stream_format(sink, structure);
114 :
115 27 : gint width = 0;
116 27 : gint height = 0;
117 27 : gst_structure_get_int(structure, "width", &width);
118 27 : gst_structure_get_int(structure, "height", &height);
119 :
120 27 : std::string mimeType;
121 27 : if (strct_name)
122 : {
123 27 : if (g_str_has_prefix(strct_name, "video/x-h264"))
124 : {
125 22 : mimeType = "video/h264";
126 : }
127 5 : else if (g_str_has_prefix(strct_name, "video/x-h265"))
128 : {
129 4 : mimeType = "video/h265";
130 :
131 4 : uint32_t dolbyVisionProfile = -1;
132 4 : if (rialto_mse_base_sink_get_dv_profile(sink, structure, dolbyVisionProfile))
133 : {
134 1 : return std::make_unique<firebolt::rialto::IMediaPipeline::MediaSourceVideoDolbyVision>(mimeType,
135 : dolbyVisionProfile,
136 1 : sink->priv->m_hasDrm,
137 : width, height,
138 : alignment, format,
139 1 : codecData);
140 : }
141 : }
142 : else
143 : {
144 1 : mimeType = strct_name;
145 : }
146 :
147 26 : GST_INFO_OBJECT(sink, "%s video media source created", mimeType.c_str());
148 52 : return std::make_unique<firebolt::rialto::IMediaPipeline::MediaSourceVideo>(mimeType, sink->priv->m_hasDrm,
149 : width, height, alignment, format,
150 26 : codecData);
151 : }
152 : else
153 : {
154 0 : GST_ERROR_OBJECT(sink,
155 : "Empty caps' structure name! Failed to set mime type when constructing video media source");
156 : }
157 :
158 0 : return nullptr;
159 27 : }
160 :
161 29 : static gboolean rialto_mse_video_sink_event(GstPad *pad, GstObject *parent, GstEvent *event)
162 : {
163 29 : RialtoMSEBaseSink *baseSink = RIALTO_MSE_BASE_SINK(parent);
164 29 : RialtoMSEBaseSinkPrivate *basePriv = baseSink->priv;
165 29 : switch (GST_EVENT_TYPE(event))
166 : {
167 28 : case GST_EVENT_CAPS:
168 : {
169 : GstCaps *caps;
170 28 : gst_event_parse_caps(event, &caps);
171 28 : if (basePriv->m_sourceAttached)
172 : {
173 1 : GST_INFO_OBJECT(baseSink, "Source already attached. Skip calling attachSource");
174 1 : break;
175 : }
176 :
177 27 : GST_INFO_OBJECT(baseSink, "Attaching VIDEO source with caps %" GST_PTR_FORMAT, caps);
178 :
179 : std::unique_ptr<firebolt::rialto::IMediaPipeline::MediaSource> vsource =
180 27 : rialto_mse_video_sink_create_media_source(baseSink, caps);
181 27 : if (vsource)
182 : {
183 27 : std::shared_ptr<GStreamerMSEMediaPlayerClient> client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
184 27 : if ((!client) || (!client->attachSource(vsource, baseSink)))
185 : {
186 1 : GST_ERROR_OBJECT(baseSink, "Failed to attach VIDEO source");
187 : }
188 : else
189 : {
190 26 : basePriv->m_sourceAttached = true;
191 :
192 : // check if READY -> PAUSED was requested before source was attached
193 26 : if (GST_STATE_NEXT(baseSink) == GST_STATE_PAUSED)
194 : {
195 26 : client->pause(basePriv->m_sourceId);
196 : }
197 26 : RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(parent);
198 26 : RialtoMSEVideoSinkPrivate *priv = sink->priv;
199 26 : std::unique_lock lock{priv->propertyMutex};
200 26 : if (priv->immediateOutputQueued)
201 : {
202 1 : GST_DEBUG_OBJECT(sink, "Set queued immediate-output");
203 1 : priv->immediateOutputQueued = false;
204 1 : if (!client->setImmediateOutput(basePriv->m_sourceId, priv->immediateOutput))
205 : {
206 0 : GST_ERROR_OBJECT(sink, "Could not set immediate-output");
207 : }
208 : }
209 26 : if (priv->syncmodeStreamingQueued)
210 : {
211 2 : GST_DEBUG_OBJECT(sink, "Set queued syncmode-streaming");
212 2 : priv->syncmodeStreamingQueued = false;
213 2 : if (!client->setStreamSyncMode(basePriv->m_sourceId, priv->syncmodeStreaming))
214 : {
215 1 : GST_ERROR_OBJECT(sink, "Could not set syncmode-streaming");
216 : }
217 : }
218 26 : if (priv->showVideoWindowQueued)
219 : {
220 1 : GST_DEBUG_OBJECT(sink, "Set queued show-video-window");
221 1 : priv->showVideoWindowQueued = false;
222 1 : client->setMute(priv->showVideoWindow, basePriv->m_sourceId);
223 : }
224 26 : }
225 27 : }
226 : else
227 : {
228 0 : GST_ERROR_OBJECT(baseSink, "Failed to create VIDEO source");
229 : }
230 :
231 27 : break;
232 : }
233 1 : default:
234 1 : break;
235 : }
236 :
237 29 : return rialto_mse_base_sink_event(pad, parent, event);
238 : }
239 :
240 14 : static void rialto_mse_video_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec)
241 : {
242 14 : RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(object);
243 14 : if (!sink)
244 : {
245 0 : GST_ERROR_OBJECT(object, "Sink not initalised");
246 0 : return;
247 : }
248 14 : RialtoMSEVideoSinkPrivate *priv = sink->priv;
249 14 : RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv;
250 14 : if (!priv || !basePriv)
251 : {
252 0 : GST_ERROR_OBJECT(object, "Private Sink not initalised");
253 0 : return;
254 : }
255 :
256 14 : switch (propId)
257 : {
258 5 : case PROP_WINDOW_SET:
259 : {
260 5 : std::unique_lock lock{priv->propertyMutex};
261 5 : auto client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
262 5 : if (!client)
263 : {
264 : // Return the default value and
265 : // queue a setting event (for the default value) so that it will become true when
266 : // the client connects...
267 2 : GST_DEBUG_OBJECT(object, "Return default rectangle setting, and queue an event to set the default upon "
268 : "client connect");
269 2 : priv->rectangleSettingQueued = true;
270 2 : g_value_set_string(value, priv->videoRectangle.c_str());
271 : }
272 : else
273 : {
274 3 : lock.unlock();
275 3 : g_value_set_string(value, client->getVideoRectangle().c_str());
276 : }
277 5 : break;
278 : }
279 1 : case PROP_MAX_VIDEO_WIDTH_DEPRECATED:
280 1 : GST_WARNING_OBJECT(object, "MaxVideoWidth property is deprecated. Use 'max-video-width' instead");
281 : case PROP_MAX_VIDEO_WIDTH:
282 : {
283 2 : g_value_set_uint(value, priv->maxWidth);
284 2 : break;
285 : }
286 1 : case PROP_MAX_VIDEO_HEIGHT_DEPRECATED:
287 1 : GST_WARNING_OBJECT(object, "MaxVideoHeight property is deprecated. Use 'max-video-height' instead");
288 : case PROP_MAX_VIDEO_HEIGHT:
289 : {
290 2 : g_value_set_uint(value, priv->maxHeight);
291 2 : break;
292 : }
293 1 : case PROP_FRAME_STEP_ON_PREROLL:
294 : {
295 1 : g_value_set_boolean(value, priv->stepOnPrerollEnabled);
296 1 : break;
297 : }
298 3 : case PROP_IMMEDIATE_OUTPUT:
299 : {
300 3 : std::unique_lock lock{priv->propertyMutex};
301 3 : auto client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
302 3 : if (!client)
303 : {
304 : // Return the default value and
305 : // queue a setting event (for the default value) so that it will become true when
306 : // the client connects...
307 1 : GST_DEBUG_OBJECT(object, "Return default immediate-output setting, and queue an event to set the default "
308 : "upon client connect");
309 1 : priv->immediateOutputQueued = true;
310 1 : g_value_set_boolean(value, priv->immediateOutput);
311 : }
312 : else
313 : {
314 2 : bool immediateOutput{priv->immediateOutput};
315 2 : lock.unlock();
316 2 : if (!client->getImmediateOutput(sink->parent.priv->m_sourceId, immediateOutput))
317 : {
318 1 : GST_ERROR_OBJECT(sink, "Could not get immediate-output");
319 : }
320 2 : g_value_set_boolean(value, immediateOutput);
321 : }
322 3 : break;
323 : }
324 1 : default:
325 1 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
326 1 : break;
327 : }
328 : }
329 :
330 20 : static void rialto_mse_video_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec)
331 : {
332 20 : RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(object);
333 20 : if (!sink)
334 : {
335 0 : GST_ERROR_OBJECT(object, "Sink not initalised");
336 0 : return;
337 : }
338 20 : RialtoMSEVideoSinkPrivate *priv = sink->priv;
339 20 : RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv;
340 20 : if (!priv || !basePriv)
341 : {
342 0 : GST_ERROR_OBJECT(object, "Private sink not initalised");
343 0 : return;
344 : }
345 :
346 20 : std::shared_ptr<GStreamerMSEMediaPlayerClient> client = basePriv->m_mediaPlayerManager.getMediaPlayerClient();
347 :
348 20 : switch (propId)
349 : {
350 4 : case PROP_WINDOW_SET:
351 : {
352 4 : const gchar *rectangle = g_value_get_string(value);
353 4 : if (!rectangle)
354 : {
355 1 : GST_WARNING_OBJECT(object, "Rectangle string not valid");
356 1 : break;
357 : }
358 6 : std::string videoRectangle{rectangle};
359 3 : std::unique_lock lock{priv->propertyMutex};
360 3 : priv->videoRectangle = videoRectangle;
361 3 : if (!client)
362 : {
363 2 : GST_DEBUG_OBJECT(object, "Rectangle setting enqueued");
364 2 : priv->rectangleSettingQueued = true;
365 : }
366 : else
367 : {
368 1 : lock.unlock();
369 1 : client->setVideoRectangle(videoRectangle);
370 : }
371 3 : break;
372 : }
373 1 : case PROP_MAX_VIDEO_WIDTH:
374 : case PROP_MAX_VIDEO_WIDTH_DEPRECATED:
375 1 : priv->maxWidth = g_value_get_uint(value);
376 1 : break;
377 1 : case PROP_MAX_VIDEO_HEIGHT:
378 : case PROP_MAX_VIDEO_HEIGHT_DEPRECATED:
379 1 : priv->maxHeight = g_value_get_uint(value);
380 1 : break;
381 4 : case PROP_FRAME_STEP_ON_PREROLL:
382 : {
383 4 : bool stepOnPrerollEnabled = g_value_get_boolean(value);
384 4 : if (client && stepOnPrerollEnabled && !priv->stepOnPrerollEnabled)
385 : {
386 2 : GST_INFO_OBJECT(object, "Frame stepping on preroll");
387 2 : client->renderFrame(RIALTO_MSE_BASE_SINK(sink));
388 : }
389 4 : priv->stepOnPrerollEnabled = stepOnPrerollEnabled;
390 4 : break;
391 : }
392 3 : case PROP_IMMEDIATE_OUTPUT:
393 : {
394 3 : bool immediateOutput = (g_value_get_boolean(value) != FALSE);
395 3 : std::unique_lock lock{priv->propertyMutex};
396 3 : priv->immediateOutput = immediateOutput;
397 3 : if (!client)
398 : {
399 1 : GST_DEBUG_OBJECT(sink, "Immediate output setting enqueued");
400 1 : priv->immediateOutputQueued = true;
401 : }
402 : else
403 : {
404 2 : lock.unlock();
405 2 : if (!client->setImmediateOutput(basePriv->m_sourceId, immediateOutput))
406 : {
407 1 : GST_ERROR_OBJECT(sink, "Could not set immediate-output");
408 : }
409 : }
410 3 : break;
411 : }
412 4 : case PROP_SYNCMODE_STREAMING:
413 : {
414 4 : bool syncmodeStreaming = (g_value_get_boolean(value) != FALSE);
415 4 : std::unique_lock lock{priv->propertyMutex};
416 4 : priv->syncmodeStreaming = syncmodeStreaming;
417 4 : if (!client)
418 : {
419 2 : GST_DEBUG_OBJECT(sink, "Syncmode streaming setting enqueued");
420 2 : priv->syncmodeStreamingQueued = true;
421 : }
422 : else
423 : {
424 2 : lock.unlock();
425 2 : if (!client->setStreamSyncMode(basePriv->m_sourceId, syncmodeStreaming))
426 : {
427 1 : GST_ERROR_OBJECT(sink, "Could not set syncmode-streaming");
428 : }
429 : }
430 4 : break;
431 : }
432 2 : case PROP_SHOW_VIDEO_WINDOW:
433 : {
434 2 : bool showVideoWindow = (g_value_get_boolean(value) == TRUE);
435 2 : std::unique_lock lock{priv->propertyMutex};
436 2 : priv->showVideoWindow = showVideoWindow;
437 2 : if (!client)
438 : {
439 1 : GST_DEBUG_OBJECT(sink, "Show video window setting enqueued");
440 1 : priv->showVideoWindowQueued = true;
441 : }
442 : else
443 : {
444 1 : lock.unlock();
445 1 : client->setMute(showVideoWindow, basePriv->m_sourceId);
446 : }
447 2 : break;
448 : }
449 1 : default:
450 1 : G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
451 1 : break;
452 : }
453 20 : }
454 :
455 1 : static void rialto_mse_video_sink_qos_handle(GstElement *element, uint64_t processed, uint64_t dropped)
456 : {
457 1 : GstBus *bus = gst_element_get_bus(element);
458 : /* Hardcode isLive to FALSE and set invalid timestamps */
459 1 : GstMessage *message = gst_message_new_qos(GST_OBJECT(element), FALSE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE,
460 : GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE);
461 :
462 1 : gst_message_set_qos_stats(message, GST_FORMAT_BUFFERS, processed, dropped);
463 1 : gst_bus_post(bus, message);
464 1 : gst_object_unref(bus);
465 : }
466 :
467 57 : static void rialto_mse_video_sink_init(RialtoMSEVideoSink *sink)
468 : {
469 57 : RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv;
470 :
471 57 : sink->priv = static_cast<RialtoMSEVideoSinkPrivate *>(rialto_mse_video_sink_get_instance_private(sink));
472 57 : new (sink->priv) RialtoMSEVideoSinkPrivate();
473 :
474 57 : if (!rialto_mse_base_sink_initialise_sinkpad(RIALTO_MSE_BASE_SINK(sink)))
475 : {
476 0 : GST_ERROR_OBJECT(sink, "Failed to initialise VIDEO sink. Sink pad initialisation failed.");
477 0 : return;
478 : }
479 :
480 57 : basePriv->m_mediaSourceType = firebolt::rialto::MediaSourceType::VIDEO;
481 57 : basePriv->m_isAsync = true;
482 57 : gst_pad_set_chain_function(basePriv->m_sinkPad, rialto_mse_base_sink_chain);
483 57 : gst_pad_set_event_function(basePriv->m_sinkPad, rialto_mse_video_sink_event);
484 :
485 114 : basePriv->m_callbacks.qosCallback = std::bind(rialto_mse_video_sink_qos_handle, GST_ELEMENT_CAST(sink),
486 57 : std::placeholders::_1, std::placeholders::_2);
487 : }
488 :
489 1 : static void rialto_mse_video_sink_class_init(RialtoMSEVideoSinkClass *klass)
490 : {
491 1 : GObjectClass *gobjectClass = G_OBJECT_CLASS(klass);
492 1 : GstElementClass *elementClass = GST_ELEMENT_CLASS(klass);
493 1 : gobjectClass->get_property = rialto_mse_video_sink_get_property;
494 1 : gobjectClass->set_property = rialto_mse_video_sink_set_property;
495 1 : elementClass->change_state = rialto_mse_video_sink_change_state;
496 :
497 1 : g_object_class_install_property(gobjectClass, PROP_WINDOW_SET,
498 : g_param_spec_string("rectangle", "rectangle", "Window Set Format: x,y,width,height",
499 : nullptr, GParamFlags(G_PARAM_READWRITE)));
500 :
501 1 : g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_WIDTH,
502 : g_param_spec_uint("max-video-width",
503 : "max video width", "Maximum width of video frames to be decoded. Should only be set for video only streams.",
504 : 0, 3840, DEFAULT_MAX_VIDEO_WIDTH, GParamFlags(G_PARAM_READWRITE)));
505 :
506 1 : g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_HEIGHT,
507 : g_param_spec_uint("max-video-height",
508 : "max video height", "Maximum height of video frames to be decoded. should only be set for video only streams.",
509 : 0, 2160, DEFAULT_MAX_VIDEO_HEIGHT, GParamFlags(G_PARAM_READWRITE)));
510 :
511 1 : g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_WIDTH_DEPRECATED,
512 : g_param_spec_uint("maxVideoWidth", "maxVideoWidth", "[DEPRECATED] Use max-video-width",
513 : 0, 3840, DEFAULT_MAX_VIDEO_WIDTH, GParamFlags(G_PARAM_READWRITE)));
514 :
515 1 : g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_HEIGHT_DEPRECATED,
516 : g_param_spec_uint("maxVideoHeight", "maxVideoHeight", "[DEPRECATED] max-video-height",
517 : 0, 2160, DEFAULT_MAX_VIDEO_HEIGHT, GParamFlags(G_PARAM_READWRITE)));
518 :
519 1 : g_object_class_install_property(gobjectClass, PROP_FRAME_STEP_ON_PREROLL,
520 : g_param_spec_boolean("frame-step-on-preroll", "frame step on preroll",
521 : "allow frame stepping on preroll into pause", FALSE,
522 : G_PARAM_READWRITE));
523 :
524 : std::unique_ptr<firebolt::rialto::IMediaPipelineCapabilities> mediaPlayerCapabilities =
525 1 : firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities();
526 1 : if (mediaPlayerCapabilities)
527 : {
528 : std::vector<std::string> supportedMimeTypes =
529 1 : mediaPlayerCapabilities->getSupportedMimeTypes(firebolt::rialto::MediaSourceType::VIDEO);
530 :
531 1 : rialto_mse_sink_setup_supported_caps(elementClass, supportedMimeTypes);
532 :
533 2 : const std::string kImmediateOutputPropertyName{"immediate-output"};
534 2 : const std::string kSyncmodeStreamingPropertyName{"syncmode-streaming"};
535 1 : const std::string kShowVideoWindowPropertyName{"show-video-window"};
536 : const std::vector<std::string> kPropertyNamesToSearch{kImmediateOutputPropertyName,
537 : kSyncmodeStreamingPropertyName,
538 5 : kShowVideoWindowPropertyName};
539 : std::vector<std::string> supportedProperties{
540 1 : mediaPlayerCapabilities->getSupportedProperties(firebolt::rialto::MediaSourceType::VIDEO,
541 1 : kPropertyNamesToSearch)};
542 :
543 4 : for (const auto &propertyName : supportedProperties)
544 : {
545 3 : if (kImmediateOutputPropertyName == propertyName)
546 : {
547 1 : g_object_class_install_property(gobjectClass, PROP_IMMEDIATE_OUTPUT,
548 : g_param_spec_boolean(kImmediateOutputPropertyName.c_str(),
549 : "immediate output", "immediate output", TRUE,
550 : GParamFlags(G_PARAM_READWRITE)));
551 : }
552 2 : else if (kSyncmodeStreamingPropertyName == propertyName)
553 : {
554 1 : g_object_class_install_property(gobjectClass, PROP_SYNCMODE_STREAMING,
555 : g_param_spec_boolean("syncmode-streaming", "Streaming Sync Mode",
556 : "Enable/disable OTT streaming sync mode", FALSE,
557 : G_PARAM_WRITABLE));
558 : }
559 1 : else if (kShowVideoWindowPropertyName == propertyName)
560 : {
561 1 : g_object_class_install_property(gobjectClass, PROP_SHOW_VIDEO_WINDOW,
562 : g_param_spec_boolean(kShowVideoWindowPropertyName.c_str(),
563 : "make video window visible",
564 : "true: visible, false: hidden", TRUE,
565 : G_PARAM_WRITABLE));
566 : }
567 : }
568 : }
569 : else
570 : {
571 0 : GST_ERROR("Failed to get supported mime types for VIDEO");
572 : }
573 :
574 1 : gst_element_class_set_details_simple(elementClass, "Rialto Video Sink", "Decoder/Video/Sink/Video",
575 : "Communicates with Rialto Server", "Sky");
576 2 : }
|