Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2022 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include <stdexcept>
21 :
22 : #include "GstSrc.h"
23 : #include "GstTextTrackSinkFactory.h"
24 : #include "RialtoServerLogging.h"
25 : #include <MediaCommon.h>
26 :
27 : static void gstRialtoSrcUriHandlerInit(gpointer gIface, gpointer ifaceData);
28 :
29 : static GstStaticPadTemplate rialto_src_template =
30 : GST_STATIC_PAD_TEMPLATE("src_%u", GST_PAD_SRC, GST_PAD_SOMETIMES, GST_STATIC_CAPS_ANY);
31 :
32 : GST_DEBUG_CATEGORY(rialto_gst_player_debug);
33 : #define GST_CAT_DEFAULT rialto_gst_player_debug
34 : #define gst_rialto_src_parent_class parent_class
35 : #define RIALTO_SRC_CATEGORY_INIT \
36 : GST_DEBUG_CATEGORY_INIT(rialto_gst_player_debug, "rialtosrc", 0, "Rialto source element");
37 14 : G_DEFINE_TYPE_WITH_CODE(GstRialtoSrc, gst_rialto_src, GST_TYPE_BIN,
38 : G_ADD_PRIVATE(GstRialtoSrc)
39 : G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, gstRialtoSrcUriHandlerInit)
40 : RIALTO_SRC_CATEGORY_INIT)
41 :
42 0 : static void gstRialtoSrcDispose(GObject *object)
43 : {
44 0 : GST_CALL_PARENT(G_OBJECT_CLASS, dispose, (object));
45 : }
46 :
47 0 : static void gstRialtoSrcFinalize(GObject *object)
48 : {
49 0 : GstRialtoSrc *src = GST_RIALTO_SRC(object);
50 0 : GstRialtoSrcPrivate *priv = src->priv;
51 0 : GST_OBJECT_LOCK(src);
52 0 : g_free(priv->uri);
53 0 : GST_OBJECT_UNLOCK(src);
54 0 : priv->~GstRialtoSrcPrivate();
55 0 : GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object));
56 : }
57 :
58 0 : static void gstRialtoSrcSetProperty(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
59 : {
60 0 : GST_CALL_PARENT(G_OBJECT_CLASS, set_property, (object, prop_id, value, pspec));
61 : }
62 :
63 0 : static void gstRialtoSrcGetProperty(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
64 : {
65 0 : GST_CALL_PARENT(G_OBJECT_CLASS, get_property, (object, prop_id, value, pspec));
66 : }
67 :
68 0 : static GstURIType gstRialtoSrcUriGetType(GType)
69 : {
70 0 : return GST_URI_SRC;
71 : }
72 :
73 0 : const gchar *const *gstRialtoSrcGetProtocols(GType)
74 : {
75 : static const char *protocols[] = {"rialto", 0};
76 0 : return protocols;
77 : }
78 :
79 0 : static gchar *gstRialtoSrcGetUri(GstURIHandler *handler)
80 : {
81 0 : GstRialtoSrc *src = GST_RIALTO_SRC(handler);
82 : gchar *ret;
83 0 : GST_OBJECT_LOCK(src);
84 0 : ret = g_strdup(src->priv->uri);
85 0 : GST_OBJECT_UNLOCK(src);
86 0 : return ret;
87 : }
88 :
89 0 : static gboolean gstRialtoSrcSetUri(GstURIHandler *handler, const gchar *uri, GError **error)
90 : {
91 0 : GstRialtoSrc *src = GST_RIALTO_SRC(handler);
92 0 : GstRialtoSrcPrivate *priv = src->priv;
93 0 : if (GST_STATE(src) >= GST_STATE_PAUSED)
94 : {
95 0 : GST_ERROR_OBJECT(src, "URI can only be set in states < PAUSED");
96 0 : return FALSE;
97 : }
98 0 : GST_OBJECT_LOCK(src);
99 0 : g_free(priv->uri);
100 0 : priv->uri = 0;
101 0 : if (!uri)
102 : {
103 0 : GST_OBJECT_UNLOCK(src);
104 0 : return TRUE;
105 : }
106 0 : priv->uri = g_strdup(uri);
107 0 : GST_OBJECT_UNLOCK(src);
108 0 : return TRUE;
109 : }
110 :
111 0 : static void gstRialtoSrcUriHandlerInit(gpointer gIface, gpointer)
112 : {
113 0 : GstURIHandlerInterface *iface = reinterpret_cast<GstURIHandlerInterface *>(gIface);
114 0 : iface->get_type = gstRialtoSrcUriGetType;
115 0 : iface->get_protocols = gstRialtoSrcGetProtocols;
116 0 : iface->get_uri = gstRialtoSrcGetUri;
117 0 : iface->set_uri = gstRialtoSrcSetUri;
118 : }
119 :
120 0 : static gboolean gstRialtoSrcQueryWithParent(GstPad *pad, GstObject *parent, GstQuery *query)
121 : {
122 0 : gboolean result = FALSE;
123 0 : switch (GST_QUERY_TYPE(query))
124 : {
125 : default:
126 : {
127 0 : GstPad *target = gst_ghost_pad_get_target(GST_GHOST_PAD_CAST(pad));
128 : // Forward the query to the proxy target pad.
129 0 : if (target)
130 0 : result = gst_pad_query(target, query);
131 0 : gst_object_unref(target);
132 0 : break;
133 : }
134 : }
135 0 : return result;
136 : }
137 :
138 0 : void gstRialtoSrcHandleMessage(GstBin *bin, GstMessage *message)
139 : {
140 0 : GstRialtoSrc *src = GST_RIALTO_SRC(GST_ELEMENT(bin));
141 0 : switch (GST_MESSAGE_TYPE(message))
142 : {
143 0 : case GST_MESSAGE_EOS:
144 : {
145 0 : gboolean emit_eos = TRUE;
146 0 : GstPad *pad = gst_element_get_static_pad(GST_ELEMENT(GST_MESSAGE_SRC(message)), "src");
147 0 : GST_DEBUG_OBJECT(src, "EOS received from %s", GST_MESSAGE_SRC_NAME(message));
148 0 : g_object_set_data(G_OBJECT(pad), "is-eos", GINT_TO_POINTER(1));
149 0 : gst_object_unref(pad);
150 0 : for (guint i = 0; i < src->priv->appsrc_count; i++)
151 : {
152 0 : gchar *name = g_strdup_printf("src_%u", i);
153 0 : GstPad *src_pad = gst_element_get_static_pad(GST_ELEMENT(src), name);
154 0 : GstPad *target = gst_ghost_pad_get_target(GST_GHOST_PAD_CAST(src_pad));
155 0 : gint is_eos = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(target), "is-eos"));
156 0 : gst_object_unref(target);
157 0 : gst_object_unref(src_pad);
158 0 : g_free(name);
159 0 : if (!is_eos)
160 : {
161 0 : emit_eos = FALSE;
162 0 : break;
163 : }
164 : }
165 0 : gst_message_unref(message);
166 0 : if (emit_eos)
167 : {
168 0 : GST_DEBUG_OBJECT(src, "All appsrc elements are EOS, emitting event now.");
169 0 : gst_element_send_event(GST_ELEMENT(bin), gst_event_new_eos());
170 : }
171 0 : break;
172 : }
173 0 : default:
174 0 : GST_BIN_CLASS(parent_class)->handle_message(bin, message);
175 0 : break;
176 : }
177 : }
178 :
179 0 : static void gstRialtoSrcDoAsyncStart(GstRialtoSrc *rialtoSrc)
180 : {
181 0 : GstRialtoSrcPrivate *privateData = rialtoSrc->priv;
182 0 : if (privateData->async_done)
183 : {
184 0 : GST_DEBUG_OBJECT(rialtoSrc, "Rialto src already done");
185 0 : return;
186 : }
187 :
188 0 : GstMessage *message = gst_message_new_async_start(GST_OBJECT(rialtoSrc));
189 0 : GstBin *bin = GST_BIN(rialtoSrc);
190 :
191 0 : privateData->async_start = TRUE;
192 0 : GST_BIN_CLASS(parent_class)->handle_message(bin, message);
193 : }
194 :
195 1 : static void gstRialtoSrcDoAsyncDone(GstRialtoSrc *rialtoSrc)
196 : {
197 1 : GstRialtoSrcPrivate *privateData = rialtoSrc->priv;
198 1 : if (!privateData->async_start)
199 : {
200 1 : GST_DEBUG_OBJECT(rialtoSrc, "Rialto src not started");
201 1 : return;
202 : }
203 :
204 0 : GstMessage *message = gst_message_new_async_done(GST_OBJECT(rialtoSrc), GST_CLOCK_TIME_NONE);
205 0 : GstBin *bin = GST_BIN(rialtoSrc);
206 :
207 0 : GST_BIN_CLASS(parent_class)->handle_message(bin, message);
208 :
209 0 : privateData->async_done = TRUE;
210 0 : privateData->async_start = FALSE;
211 : }
212 :
213 0 : static GstStateChangeReturn gstRialtoSrcChangeState(GstElement *element, GstStateChange transition)
214 : {
215 0 : GstRialtoSrc *rialtoSrc = GST_RIALTO_SRC(element);
216 0 : GstRialtoSrcPrivate *privateData = rialtoSrc->priv;
217 0 : GstStateChangeReturn status = GST_STATE_CHANGE_SUCCESS;
218 :
219 0 : if (transition == GST_STATE_CHANGE_READY_TO_PAUSED)
220 : {
221 0 : gstRialtoSrcDoAsyncStart(rialtoSrc);
222 : }
223 :
224 0 : status = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
225 0 : if (G_UNLIKELY(status == GST_STATE_CHANGE_FAILURE))
226 : {
227 0 : gstRialtoSrcDoAsyncDone(rialtoSrc);
228 0 : return status;
229 : }
230 :
231 0 : switch (transition)
232 : {
233 0 : case GST_STATE_CHANGE_READY_TO_PAUSED:
234 : {
235 0 : if (!privateData->async_done)
236 0 : status = GST_STATE_CHANGE_ASYNC;
237 0 : break;
238 : }
239 0 : case GST_STATE_CHANGE_PAUSED_TO_READY:
240 : {
241 0 : gstRialtoSrcDoAsyncDone(rialtoSrc);
242 0 : break;
243 : }
244 0 : default:
245 0 : break;
246 : }
247 :
248 0 : return status;
249 : }
250 :
251 0 : static void gst_rialto_src_init(GstRialtoSrc *src) // NOLINT(build/function_format)
252 : {
253 0 : GstRialtoSrcPrivate *priv = reinterpret_cast<GstRialtoSrcPrivate *>(gst_rialto_src_get_instance_private(src));
254 0 : src->priv = priv;
255 0 : src->priv->appsrc_count = 0;
256 0 : src->priv->async_start = FALSE;
257 0 : src->priv->async_done = FALSE;
258 0 : g_object_set(GST_BIN(src), "message-forward", TRUE, nullptr);
259 : }
260 :
261 0 : static void gst_rialto_src_class_init(GstRialtoSrcClass *klass) // NOLINT(build/function_format)
262 : {
263 0 : GObjectClass *oklass = G_OBJECT_CLASS(klass);
264 0 : GstElementClass *eklass = GST_ELEMENT_CLASS(klass);
265 0 : GstBinClass *bklass = GST_BIN_CLASS(klass);
266 0 : oklass->dispose = gstRialtoSrcDispose;
267 0 : oklass->finalize = gstRialtoSrcFinalize;
268 0 : oklass->set_property = gstRialtoSrcSetProperty;
269 0 : oklass->get_property = gstRialtoSrcGetProperty;
270 0 : GstPadTemplate *templ = gst_static_pad_template_get(&rialto_src_template);
271 0 : gst_element_class_add_pad_template(eklass, templ);
272 0 : gst_element_class_set_metadata(eklass, "Rialto source element", "Source",
273 : "Handles data incoming from the Rialto player", "POC <poc@sky.uk>");
274 0 : g_object_class_install_property(oklass, PROP_LOCATION,
275 : g_param_spec_string("location", "location", "Location to read from", 0,
276 : (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
277 0 : bklass->handle_message = GST_DEBUG_FUNCPTR(gstRialtoSrcHandleMessage);
278 0 : eklass->change_state = GST_DEBUG_FUNCPTR(gstRialtoSrcChangeState);
279 : }
280 :
281 : namespace firebolt::rialto::server
282 : {
283 : std::weak_ptr<IGstSrcFactory> GstSrcFactory::m_factory;
284 : std::weak_ptr<IGstSrc> GstSrcFactory::m_gstSrc;
285 : std::mutex GstSrcFactory::m_creationMutex;
286 :
287 3 : std::shared_ptr<IGstSrcFactory> IGstSrcFactory::getFactory()
288 : {
289 3 : std::shared_ptr<IGstSrcFactory> factory = GstSrcFactory::m_factory.lock();
290 :
291 3 : if (!factory)
292 : {
293 : try
294 : {
295 3 : factory = std::make_shared<GstSrcFactory>();
296 : }
297 0 : catch (const std::exception &e)
298 : {
299 0 : RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer src factory, reason: %s", e.what());
300 : }
301 :
302 3 : GstSrcFactory::m_factory = factory;
303 : }
304 :
305 3 : return factory;
306 : }
307 :
308 3 : std::shared_ptr<IGstSrc> GstSrcFactory::getGstSrc()
309 : {
310 3 : std::lock_guard<std::mutex> lock{m_creationMutex};
311 :
312 3 : std::shared_ptr<IGstSrc> gstSrc = GstSrcFactory::m_gstSrc.lock();
313 :
314 3 : if (!gstSrc)
315 : {
316 : try
317 : {
318 6 : gstSrc = std::make_shared<GstSrc>(firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(),
319 6 : firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory(),
320 9 : IGstDecryptorElementFactory::createFactory());
321 : }
322 0 : catch (const std::exception &e)
323 : {
324 0 : RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer src, reason: %s", e.what());
325 : }
326 :
327 3 : GstSrcFactory::m_gstSrc = gstSrc;
328 : }
329 :
330 6 : return gstSrc;
331 3 : }
332 :
333 17 : GstSrc::GstSrc(const std::shared_ptr<firebolt::rialto::wrappers::IGstWrapperFactory> &gstWrapperFactory,
334 : const std::shared_ptr<firebolt::rialto::wrappers::IGlibWrapperFactory> &glibWrapperFactory,
335 17 : const std::shared_ptr<IGstDecryptorElementFactory> &decryptorFactory)
336 17 : : m_decryptorFactory(decryptorFactory)
337 : {
338 17 : if ((!gstWrapperFactory) || (!(m_gstWrapper = gstWrapperFactory->getGstWrapper())))
339 : {
340 0 : throw std::runtime_error("Cannot create GstWrapper");
341 : }
342 17 : if ((!glibWrapperFactory) || (!(m_glibWrapper = glibWrapperFactory->getGlibWrapper())))
343 : {
344 0 : throw std::runtime_error("Cannot create GlibWrapper");
345 : }
346 17 : if (!m_decryptorFactory)
347 : {
348 0 : throw std::runtime_error("No decryptor factory provided");
349 : }
350 17 : }
351 :
352 4 : void GstSrc::initSrc()
353 : {
354 4 : GstElementFactory *src_factory = m_gstWrapper->gstElementFactoryFind("rialtosrc");
355 4 : if (!src_factory)
356 : {
357 3 : m_gstWrapper->gstElementRegister(0, "rialtosrc", GST_RANK_PRIMARY + 100, GST_RIALTO_TYPE_SRC);
358 : }
359 : else
360 : {
361 1 : m_gstWrapper->gstObjectUnref(src_factory);
362 1 : src_factory = nullptr;
363 : }
364 4 : }
365 :
366 6 : void GstSrc::setDefaultStreamFormatIfNeeded(GstElement *appSrc)
367 : {
368 6 : GstCaps *currentCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(appSrc));
369 6 : if (currentCaps)
370 : {
371 6 : GstStructure *structure = m_gstWrapper->gstCapsGetStructure(currentCaps, 0);
372 7 : if (structure && (m_gstWrapper->gstStructureHasName(structure, "video/x-h264") ||
373 1 : m_gstWrapper->gstStructureHasName(structure, "video/x-h265")))
374 : {
375 5 : bool hasStreamFormat = m_gstWrapper->gstStructureHasField(structure, "stream-format");
376 5 : bool hasCodecData = m_gstWrapper->gstStructureHasField(structure, "codec_data");
377 :
378 5 : if (!hasStreamFormat && !hasCodecData)
379 : {
380 3 : GstCaps *newCaps = m_gstWrapper->gstCapsCopy(currentCaps);
381 3 : if (newCaps)
382 : {
383 3 : m_gstWrapper->gstCapsSetSimple(newCaps, "stream-format", G_TYPE_STRING, "byte-stream", nullptr);
384 3 : m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(appSrc), newCaps);
385 3 : GST_INFO("Added stream-format=byte-stream to caps %" GST_PTR_FORMAT, newCaps);
386 3 : m_gstWrapper->gstCapsUnref(newCaps);
387 : }
388 : }
389 : }
390 : }
391 6 : m_gstWrapper->gstCapsUnref(currentCaps);
392 : }
393 :
394 9 : void GstSrc::setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo,
395 : GstAppSrcCallbacks *callbacks, gpointer userData, firebolt::rialto::MediaSourceType type)
396 : {
397 : // Configure and add appsrc
398 9 : m_glibWrapper->gObjectSet(streamInfo.appSrc, "block", FALSE, "format", GST_FORMAT_TIME, "stream-type",
399 : GST_APP_STREAM_TYPE_STREAM, "min-percent", 20, "handle-segment-change", TRUE, nullptr);
400 9 : m_gstWrapper->gstAppSrcSetCallbacks(GST_APP_SRC(streamInfo.appSrc), callbacks, userData, nullptr);
401 :
402 : const std::unordered_map<firebolt::rialto::MediaSourceType, uint32_t> queueSize =
403 : {{firebolt::rialto::MediaSourceType::VIDEO, 8 * 1024 * 1024},
404 : {firebolt::rialto::MediaSourceType::AUDIO, 512 * 1024},
405 18 : {firebolt::rialto::MediaSourceType::SUBTITLE, 256 * 1024}};
406 :
407 9 : auto sizeIt = queueSize.find(type);
408 9 : if (sizeIt != queueSize.end())
409 : {
410 9 : m_gstWrapper->gstAppSrcSetMaxBytes(GST_APP_SRC(streamInfo.appSrc), sizeIt->second);
411 : }
412 : else
413 : {
414 0 : GST_WARNING_OBJECT(source, "Could not find max-bytes value for appsrc");
415 : }
416 :
417 9 : m_gstWrapper->gstAppSrcSetStreamType(GST_APP_SRC(streamInfo.appSrc), GST_APP_STREAM_TYPE_SEEKABLE);
418 :
419 9 : GstRialtoSrc *src = GST_RIALTO_SRC(source);
420 9 : guint id = src->priv->appsrc_count;
421 9 : src->priv->appsrc_count++;
422 9 : gchar *name = m_glibWrapper->gStrdupPrintf("src_%u", id);
423 9 : m_gstWrapper->gstBinAdd(GST_BIN(source), streamInfo.appSrc);
424 :
425 9 : GstElement *src_elem = streamInfo.appSrc;
426 :
427 : // Configure and add decryptor
428 9 : if (streamInfo.hasDrm)
429 : {
430 : gchar *decryptorName =
431 16 : m_glibWrapper->gStrdupPrintf("rialtodecryptor%s_%u",
432 8 : (type == firebolt::rialto::MediaSourceType::VIDEO) ? "video" : "audio", id);
433 : GstElement *decryptor =
434 8 : m_decryptorFactory->createDecryptorElement(decryptorName, decryptionService, m_gstWrapper);
435 8 : m_glibWrapper->gFree(decryptorName);
436 8 : if (decryptor)
437 : {
438 7 : GST_DEBUG_OBJECT(src, "Injecting decryptor element %" GST_PTR_FORMAT, decryptor);
439 :
440 7 : m_gstWrapper->gstBinAdd(GST_BIN(source), decryptor);
441 7 : m_gstWrapper->gstElementSyncStateWithParent(decryptor);
442 7 : m_gstWrapper->gstElementLink(src_elem, decryptor);
443 7 : src_elem = decryptor;
444 : }
445 : else
446 : {
447 1 : GST_WARNING_OBJECT(src, "Could not create decryptor element");
448 : }
449 :
450 8 : if (type == firebolt::rialto::MediaSourceType::VIDEO)
451 : {
452 : // Configure and add payloader
453 7 : GstElement *payloader = createPayloader();
454 7 : if (payloader)
455 : {
456 : /*
457 : h264secparse and h265secparse have problems with parsing blank caps (with no stream-format nor
458 : codec_data defined). This is a workaround to set the stream-format to byte-stream if needed.
459 : */
460 6 : setDefaultStreamFormatIfNeeded(streamInfo.appSrc);
461 :
462 6 : if (GST_IS_BASE_TRANSFORM(payloader))
463 : {
464 0 : m_gstWrapper->gstBaseTransformSetInPlace(GST_BASE_TRANSFORM(payloader), TRUE);
465 : }
466 6 : m_gstWrapper->gstBinAdd(GST_BIN(source), payloader);
467 6 : m_gstWrapper->gstElementSyncStateWithParent(payloader);
468 6 : m_gstWrapper->gstElementLink(src_elem, payloader);
469 6 : src_elem = payloader;
470 : }
471 : else
472 : {
473 1 : GST_WARNING_OBJECT(src, "Could not create payloader element");
474 : }
475 : }
476 : }
477 :
478 : // Configure and add buffer queue
479 9 : GstElement *queue = m_gstWrapper->gstElementFactoryMake("queue", nullptr);
480 9 : if (queue)
481 : {
482 8 : m_glibWrapper->gObjectSet(G_OBJECT(queue), "max-size-buffers", 10, "max-size-bytes", 0, "max-size-time",
483 : (gint64)0, "silent", TRUE, nullptr);
484 8 : m_gstWrapper->gstBinAdd(GST_BIN(source), queue);
485 8 : m_gstWrapper->gstElementSyncStateWithParent(queue);
486 8 : m_gstWrapper->gstElementLink(src_elem, queue);
487 8 : src_elem = queue;
488 : }
489 : else
490 : {
491 1 : GST_WARNING_OBJECT(src, "Could not create buffer queue element");
492 : }
493 :
494 : // Setup pad
495 9 : GstPad *target = m_gstWrapper->gstElementGetStaticPad(src_elem, "src");
496 9 : GstPad *pad = m_gstWrapper->gstGhostPadNew(name, target);
497 9 : m_gstWrapper->gstPadSetQueryFunction(pad, gstRialtoSrcQueryWithParent);
498 9 : m_gstWrapper->gstPadSetActive(pad, TRUE);
499 :
500 9 : m_gstWrapper->gstElementAddPad(source, pad);
501 9 : GST_OBJECT_FLAG_SET(pad, GST_PAD_FLAG_NEED_PARENT);
502 :
503 9 : m_gstWrapper->gstElementSyncStateWithParent(streamInfo.appSrc);
504 :
505 9 : m_glibWrapper->gFree(name);
506 9 : m_gstWrapper->gstObjectUnref(target);
507 : }
508 :
509 1 : void GstSrc::allAppSrcsAdded(GstElement *element)
510 : {
511 1 : GstRialtoSrc *src = GST_RIALTO_SRC(element);
512 1 : m_gstWrapper->gstElementNoMorePads(element);
513 1 : gstRialtoSrcDoAsyncDone(src);
514 : }
515 :
516 7 : GstElement *GstSrc::createPayloader()
517 : {
518 : static GstElementFactory *factory = nullptr;
519 : static gsize init = 0;
520 7 : if (m_glibWrapper->gOnceInitEnter(&init))
521 : {
522 7 : factory = m_gstWrapper->gstElementFactoryFind("svppay");
523 7 : m_glibWrapper->gOnceInitLeave(&init, 1);
524 : }
525 7 : if (!factory)
526 : {
527 0 : GST_WARNING("svppay not found");
528 0 : return nullptr;
529 : }
530 7 : return m_gstWrapper->gstElementFactoryCreate(factory, nullptr);
531 : }
532 :
533 : }; // namespace firebolt::rialto::server
|