1 /* GStreamer encoding bin
2 * Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
3 * (C) 2009 Nokia Corporation
4 * (C) 2016 Jan Schmidt <jan@centricular.com>
5 * (C) 2020 Thibault saunier <tsaunier@igalia.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
28 #include "gstencodebin.h"
29 #include "gstsmartencoder.h"
30 #include "gststreamsplitter.h"
31 #include "gststreamcombiner.h"
32 #include <gst/gst-i18n-plugin.h>
35 * SECTION:element-encodebin
38 * EncodeBin provides a bin for encoding/muxing various streams according to
39 * a specified #GstEncodingProfile.
41 * Based on the profile that was set (via the #GstEncodeBaseBin:profile property),
42 * EncodeBin will internally select and configure the required elements
43 * (encoders, muxers, but also audio and video converters) so that you can
44 * provide it raw or pre-encoded streams of data in input and have your
45 * encoded/muxed/converted stream in output.
49 * * Automatic encoder and muxer selection based on elements available on the
52 * * Conversion of raw audio/video streams (scaling, framerate conversion,
53 * colorspace conversion, samplerate conversion) to conform to the profile
56 * * Variable number of streams. If the presence property for a stream encoding
57 * profile is 0, you can request any number of sink pads for it via the
58 * standard request pad gstreamer API or the #GstEncodeBaseBin::request-pad action
61 * * Avoid reencoding (passthrough). If the input stream is already encoded and is
62 * compatible with what the #GstEncodingProfile expects, then the stream won't
63 * be re-encoded but just passed through downstream to the muxer or the output.
65 * * Mix pre-encoded and raw streams as input. In addition to the passthrough
66 * feature above, you can feed both raw audio/video *AND* already-encoded data
67 * to a pad. #GstEncodeBaseBin will take care of passing through the compatible
68 * segments and re-encoding the segments of media that need encoding.
70 * * Standard behaviour is to use a #GstEncodingContainerProfile to have both
71 * encoding and muxing performed. But you can also provide a single stream
72 * profile (like #GstEncodingAudioProfile) to only have the encoding done and
73 * handle the encoded output yourself.
75 * * Audio imperfection corrections. Incoming audio streams can have non perfect
76 * timestamps (jitter), like the streams coming from ASF files. #GstEncodeBaseBin
77 * will automatically fix those imperfections for you. See
78 * #GstEncodeBaseBin:audio-jitter-tolerance for more details.
80 * * Variable or Constant video framerate. If your #GstEncodingVideoProfile has
81 * the variableframerate property deactivated (default), then the incoming
82 * raw video stream will be retimestampped in order to produce a constant
85 * * Cross-boundary re-encoding. When feeding compatible pre-encoded streams that
86 * fall on segment boundaries, and for supported formats (right now only H263),
87 * the GOP will be decoded/reencoded when needed to produce an encoded output
88 * that fits exactly within the request GstSegment.
90 * * Missing plugin support. If a #GstElement is missing to encode/mux to the
91 * request profile formats, a missing-plugin #GstMessage will be posted on the
92 * #GstBus, allowing systems that support the missing-plugin system to offer the
93 * user a way to install the missing element.
100 * Handling mp3!xing!idv3 and theora!ogg tagsetting scenarios:
101 * Once we have chosen a muxer:
102 * When a new stream is requested:
103 * If muxer isn't 'Formatter' OR doesn't have a TagSetter interface:
104 * Find a Formatter for the given stream (preferably with TagSetter)
105 * Insert that before muxer
108 #define fast_pad_link(a,b) gst_pad_link_full((a),(b),GST_PAD_LINK_CHECK_NOTHING)
109 #define fast_element_link(a,b) gst_element_link_pads_full((a),"src",(b),"sink",GST_PAD_LINK_CHECK_NOTHING)
111 #define GST_TYPE_ENCODEBIN_FLAGS (gst_encodebin_flags_get_type())
112 GType gst_encodebin_flags_get_type (void);
114 /* generic templates */
115 static GstStaticPadTemplate video_sink_template =
116 GST_STATIC_PAD_TEMPLATE ("video_%u",
119 GST_STATIC_CAPS_ANY);
120 static GstStaticPadTemplate audio_sink_template =
121 GST_STATIC_PAD_TEMPLATE ("audio_%u",
124 GST_STATIC_CAPS_ANY);
125 /* static GstStaticPadTemplate text_sink_template = */
126 /* GST_STATIC_PAD_TEMPLATE ("text_%u", */
128 /* GST_PAD_REQUEST, */
129 /* GST_STATIC_CAPS_ANY); */
130 static GstStaticPadTemplate private_sink_template =
131 GST_STATIC_PAD_TEMPLATE ("private_%u",
134 GST_STATIC_CAPS_ANY);
136 typedef struct _StreamGroup StreamGroup;
140 GstEncodeBaseBin *ebin;
141 GstEncodingProfile *profile;
142 GstPad *ghostpad; /* Sink ghostpad */
143 GstElement *identity; /* Identity just after the ghostpad */
144 GstElement *inqueue; /* Queue just after the identity */
145 GstElement *splitter;
146 GList *converters; /* List of conversion GstElement */
147 GstElement *capsfilter; /* profile->restriction (if non-NULL/ANY) */
148 gulong inputfilter_caps_sid;
149 GstElement *encoder; /* Encoder (can be NULL) */
150 GstElement *fakesink; /* Fakesink (can be NULL) */
151 GstElement *combiner;
153 GstElement *smartencoder;
154 GstElement *smart_capsfilter;
155 gulong smart_capsfilter_sid;
156 GstElement *outfilter; /* Output capsfilter (streamprofile.format) */
157 gulong outputfilter_caps_sid;
158 GstElement *formatter;
159 GstElement *outqueue; /* Queue just before the muxer */
160 gulong restriction_sid;
163 /* Default for queues (same defaults as queue element) */
164 #define DEFAULT_QUEUE_BUFFERS_MAX 200
165 #define DEFAULT_QUEUE_BYTES_MAX 10 * 1024 * 1024
166 #define DEFAULT_QUEUE_TIME_MAX GST_SECOND
167 #define DEFAULT_AUDIO_JITTER_TOLERANCE 20 * GST_MSECOND
168 #define DEFAULT_AVOID_REENCODING FALSE
169 #define DEFAULT_FLAGS 0
171 #define DEFAULT_RAW_CAPS \
175 "subpicture/x-dvd; " \
183 PROP_QUEUE_BUFFERS_MAX,
184 PROP_QUEUE_BYTES_MAX,
186 PROP_AUDIO_JITTER_TOLERANCE,
187 PROP_AVOID_REENCODING,
195 SIGNAL_REQUEST_PROFILE_PAD,
199 #define C_FLAGS(v) ((guint) v)
202 gst_encodebin_flags_get_type (void)
204 static const GFlagsValue values[] = {
205 {C_FLAGS (GST_ENCODEBIN_FLAG_NO_AUDIO_CONVERSION), "Do not use audio "
206 "conversion elements", "no-audio-conversion"},
207 {C_FLAGS (GST_ENCODEBIN_FLAG_NO_VIDEO_CONVERSION), "Do not use video "
208 "conversion elements", "no-video-conversion"},
213 if (g_once_init_enter ((gsize *) & id)) {
216 _id = g_flags_register_static ("GstEncodeBinFlags", values);
218 g_once_init_leave ((gsize *) & id, _id);
224 static guint gst_encode_base_bin_signals[LAST_SIGNAL] = { 0 };
226 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
228 GST_DEBUG_CATEGORY_STATIC (gst_encode_base_bin_debug);
229 #define GST_CAT_DEFAULT gst_encode_base_bin_debug
231 G_DEFINE_TYPE (GstEncodeBaseBin, gst_encode_base_bin, GST_TYPE_BIN);
233 static void gst_encode_base_bin_dispose (GObject * object);
234 static void gst_encode_base_bin_set_property (GObject * object, guint prop_id,
235 const GValue * value, GParamSpec * pspec);
236 static void gst_encode_base_bin_get_property (GObject * object, guint prop_id,
237 GValue * value, GParamSpec * pspec);
238 static GstStateChangeReturn gst_encode_base_bin_change_state (GstElement *
239 element, GstStateChange transition);
241 static GstPad *gst_encode_base_bin_request_new_pad (GstElement * element,
242 GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
243 static void gst_encode_base_bin_release_pad (GstElement * element,
247 gst_encode_base_bin_set_profile (GstEncodeBaseBin * ebin,
248 GstEncodingProfile * profile);
249 static void gst_encode_base_bin_tear_down_profile (GstEncodeBaseBin * ebin);
250 static gboolean gst_encode_base_bin_setup_profile (GstEncodeBaseBin * ebin,
251 GstEncodingProfile * profile);
253 static StreamGroup *_create_stream_group (GstEncodeBaseBin * ebin,
254 GstEncodingProfile * sprof, const gchar * sinkpadname, GstCaps * sinkcaps,
255 gboolean * encoder_not_found);
256 static void stream_group_remove (GstEncodeBaseBin * ebin, StreamGroup * sgroup);
257 static void stream_group_free (GstEncodeBaseBin * ebin, StreamGroup * sgroup);
258 static GstPad *gst_encode_base_bin_request_pad_signal (GstEncodeBaseBin *
259 encodebin, GstCaps * caps);
260 static GstPad *gst_encode_base_bin_request_profile_pad_signal (GstEncodeBaseBin
261 * encodebin, const gchar * profilename);
263 static inline GstElement *_get_formatter (GstEncodeBaseBin * ebin,
264 GstEncodingProfile * sprof);
265 static void _post_missing_plugin_message (GstEncodeBaseBin * ebin,
266 GstEncodingProfile * prof);
269 gst_encode_base_bin_class_init (GstEncodeBaseBinClass * klass)
271 GObjectClass *gobject_klass;
272 GstElementClass *gstelement_klass;
274 gobject_klass = (GObjectClass *) klass;
275 gstelement_klass = (GstElementClass *) klass;
277 GST_DEBUG_CATEGORY_INIT (gst_encode_base_bin_debug, "encodebasebin", 0,
279 gobject_klass->dispose = gst_encode_base_bin_dispose;
280 gobject_klass->set_property = gst_encode_base_bin_set_property;
281 gobject_klass->get_property = gst_encode_base_bin_get_property;
286 * GstEncodeBaseBin:profile:
288 * The #GstEncodingProfile to use. This property must be set before going
289 * to %GST_STATE_PAUSED or higher.
291 g_object_class_install_property (gobject_klass, PROP_PROFILE,
292 g_param_spec_object ("profile", "Profile",
293 "The GstEncodingProfile to use", GST_TYPE_ENCODING_PROFILE,
294 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
296 g_object_class_install_property (gobject_klass, PROP_QUEUE_BYTES_MAX,
297 g_param_spec_uint ("queue-bytes-max", "Max. size (kB)",
298 "Max. amount of data in the queue (bytes, 0=disable)",
299 0, G_MAXUINT, DEFAULT_QUEUE_BYTES_MAX,
300 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
302 g_object_class_install_property (gobject_klass, PROP_QUEUE_BUFFERS_MAX,
303 g_param_spec_uint ("queue-buffers-max", "Max. size (buffers)",
304 "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
305 DEFAULT_QUEUE_BUFFERS_MAX,
306 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
308 g_object_class_install_property (gobject_klass, PROP_QUEUE_TIME_MAX,
309 g_param_spec_uint64 ("queue-time-max", "Max. size (ns)",
310 "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
311 DEFAULT_QUEUE_TIME_MAX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
313 g_object_class_install_property (gobject_klass, PROP_AUDIO_JITTER_TOLERANCE,
314 g_param_spec_uint64 ("audio-jitter-tolerance", "Audio jitter tolerance",
315 "Amount of timestamp jitter/imperfection to allow on audio streams before inserting/dropping samples (ns)",
316 0, G_MAXUINT64, DEFAULT_AUDIO_JITTER_TOLERANCE,
317 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
319 g_object_class_install_property (gobject_klass, PROP_AVOID_REENCODING,
320 g_param_spec_boolean ("avoid-reencoding", "Avoid re-encoding",
321 "Whether to re-encode portions of compatible video streams that lay on segment boundaries",
322 DEFAULT_AVOID_REENCODING,
323 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
326 * GstEncodeBaseBin:flags
328 * Control the behaviour of encodebin.
330 g_object_class_install_property (gobject_klass, PROP_FLAGS,
331 g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
332 GST_TYPE_ENCODEBIN_FLAGS, DEFAULT_FLAGS,
333 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
337 * GstEncodeBaseBin::request-pad
338 * @encodebin: a #GstEncodeBaseBin instance
341 * Use this method to request an unused sink request #GstPad that can take the
342 * provided @caps as input. You must release the pad with
343 * gst_element_release_request_pad() when you are done with it.
345 * Returns: A compatible #GstPad, or %NULL if no compatible #GstPad could be
346 * created or is available.
348 gst_encode_base_bin_signals[SIGNAL_REQUEST_PAD] =
349 g_signal_new ("request-pad", G_TYPE_FROM_CLASS (klass),
350 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
351 G_STRUCT_OFFSET (GstEncodeBaseBinClass, request_pad), NULL, NULL, NULL,
352 GST_TYPE_PAD, 1, GST_TYPE_CAPS);
355 * GstEncodeBaseBin::request-profile-pad
356 * @encodebin: a #GstEncodeBaseBin instance
357 * @profilename: the name of a #GstEncodingProfile
359 * Use this method to request an unused sink request #GstPad from the profile
360 * @profilename. You must release the pad with
361 * gst_element_release_request_pad() when you are done with it.
363 * Returns: A compatible #GstPad, or %NULL if no compatible #GstPad could be
364 * created or is available.
366 gst_encode_base_bin_signals[SIGNAL_REQUEST_PROFILE_PAD] =
367 g_signal_new ("request-profile-pad", G_TYPE_FROM_CLASS (klass),
368 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
369 G_STRUCT_OFFSET (GstEncodeBaseBinClass, request_profile_pad), NULL, NULL,
370 NULL, GST_TYPE_PAD, 1, G_TYPE_STRING);
372 klass->request_pad = gst_encode_base_bin_request_pad_signal;
373 klass->request_profile_pad = gst_encode_base_bin_request_profile_pad_signal;
375 gst_element_class_add_static_pad_template (gstelement_klass,
376 &video_sink_template);
377 gst_element_class_add_static_pad_template (gstelement_klass,
378 &audio_sink_template);
379 /* gst_element_class_add_static_pad_template (gstelement_klass, &text_sink_template); */
380 gst_element_class_add_static_pad_template (gstelement_klass,
381 &private_sink_template);
383 gstelement_klass->change_state =
384 GST_DEBUG_FUNCPTR (gst_encode_base_bin_change_state);
385 gstelement_klass->request_new_pad =
386 GST_DEBUG_FUNCPTR (gst_encode_base_bin_request_new_pad);
387 gstelement_klass->release_pad =
388 GST_DEBUG_FUNCPTR (gst_encode_base_bin_release_pad);
390 gst_element_class_set_static_metadata (gstelement_klass,
392 "Generic/Bin/Encoder",
393 "Convenience encoding/muxing element",
394 "Edward Hervey <edward.hervey@collabora.co.uk>");
396 gst_type_mark_as_plugin_api (GST_TYPE_ENCODEBIN_FLAGS, 0);
397 gst_type_mark_as_plugin_api (GST_TYPE_ENCODE_BASE_BIN, 0);
401 gst_encode_base_bin_dispose (GObject * object)
403 GstEncodeBaseBin *ebin = (GstEncodeBaseBin *) object;
406 gst_plugin_feature_list_free (ebin->muxers);
409 if (ebin->formatters)
410 gst_plugin_feature_list_free (ebin->formatters);
411 ebin->formatters = NULL;
414 gst_plugin_feature_list_free (ebin->encoders);
415 ebin->encoders = NULL;
418 gst_plugin_feature_list_free (ebin->parsers);
419 ebin->parsers = NULL;
421 gst_encode_base_bin_tear_down_profile (ebin);
423 if (ebin->raw_video_caps)
424 gst_caps_unref (ebin->raw_video_caps);
425 ebin->raw_video_caps = NULL;
426 if (ebin->raw_audio_caps)
427 gst_caps_unref (ebin->raw_audio_caps);
428 ebin->raw_audio_caps = NULL;
429 /* if (ebin->raw_text_caps) */
430 /* gst_caps_unref (ebin->raw_text_caps); */
432 G_OBJECT_CLASS (gst_encode_base_bin_parent_class)->dispose (object);
436 gst_encode_base_bin_init (GstEncodeBaseBin * encode_bin)
439 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
442 encode_bin->formatters =
443 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_FORMATTER,
446 encode_bin->encoders =
447 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
450 encode_bin->parsers =
451 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_PARSER,
454 encode_bin->raw_video_caps = gst_caps_from_string ("video/x-raw");
455 encode_bin->raw_audio_caps = gst_caps_from_string ("audio/x-raw");
456 /* encode_bin->raw_text_caps = */
457 /* gst_caps_from_string ("text/x-raw"); */
459 encode_bin->queue_buffers_max = DEFAULT_QUEUE_BUFFERS_MAX;
460 encode_bin->queue_bytes_max = DEFAULT_QUEUE_BYTES_MAX;
461 encode_bin->queue_time_max = DEFAULT_QUEUE_TIME_MAX;
462 encode_bin->tolerance = DEFAULT_AUDIO_JITTER_TOLERANCE;
463 encode_bin->avoid_reencoding = DEFAULT_AVOID_REENCODING;
464 encode_bin->flags = DEFAULT_FLAGS;
468 gst_encode_base_bin_set_property (GObject * object, guint prop_id,
469 const GValue * value, GParamSpec * pspec)
471 GstEncodeBaseBin *ebin = (GstEncodeBaseBin *) object;
475 gst_encode_base_bin_set_profile (ebin,
476 (GstEncodingProfile *) g_value_get_object (value));
478 case PROP_QUEUE_BUFFERS_MAX:
479 ebin->queue_buffers_max = g_value_get_uint (value);
481 case PROP_QUEUE_BYTES_MAX:
482 ebin->queue_bytes_max = g_value_get_uint (value);
484 case PROP_QUEUE_TIME_MAX:
485 ebin->queue_time_max = g_value_get_uint64 (value);
487 case PROP_AUDIO_JITTER_TOLERANCE:
488 ebin->tolerance = g_value_get_uint64 (value);
490 case PROP_AVOID_REENCODING:
492 gboolean avoided_reencoding = ebin->avoid_reencoding;
493 ebin->avoid_reencoding = g_value_get_boolean (value);
494 if (ebin->avoid_reencoding != avoided_reencoding && ebin->profile)
495 gst_encode_base_bin_set_profile (ebin, gst_object_ref (ebin->profile));
500 ebin->flags = g_value_get_flags (value);
503 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
509 gst_encode_base_bin_get_property (GObject * object, guint prop_id,
510 GValue * value, GParamSpec * pspec)
512 GstEncodeBaseBin *ebin = (GstEncodeBaseBin *) object;
516 g_value_set_object (value, (GObject *) ebin->profile);
518 case PROP_QUEUE_BUFFERS_MAX:
519 g_value_set_uint (value, ebin->queue_buffers_max);
521 case PROP_QUEUE_BYTES_MAX:
522 g_value_set_uint (value, ebin->queue_bytes_max);
524 case PROP_QUEUE_TIME_MAX:
525 g_value_set_uint64 (value, ebin->queue_time_max);
527 case PROP_AUDIO_JITTER_TOLERANCE:
528 g_value_set_uint64 (value, ebin->tolerance);
530 case PROP_AVOID_REENCODING:
531 g_value_set_boolean (value, ebin->avoid_reencoding);
534 g_value_set_flags (value, ebin->flags);
537 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
542 static inline gboolean
543 are_raw_caps (const GstCaps * caps)
545 GstCaps *raw = gst_static_caps_get (&default_raw_caps);
546 gboolean res = gst_caps_can_intersect (caps, raw);
548 gst_caps_unref (raw);
552 /* Returns the number of time a given stream profile is currently used
555 stream_profile_used_count (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof)
557 guint nbprofused = 0;
560 for (tmp = ebin->streams; tmp; tmp = tmp->next) {
561 StreamGroup *sgroup = (StreamGroup *) tmp->data;
563 if (sgroup->profile == sprof)
570 static inline GstEncodingProfile *
571 next_unused_stream_profile (GstEncodeBaseBin * ebin, GType ptype,
572 const gchar * name, GstCaps * caps, GstEncodingProfile * previous_profile)
574 GST_DEBUG_OBJECT (ebin, "ptype:%s, caps:%" GST_PTR_FORMAT,
575 g_type_name (ptype), caps);
577 if (G_UNLIKELY (ptype == G_TYPE_NONE && caps != NULL)) {
578 /* Identify the profile type based on raw caps */
579 if (gst_caps_can_intersect (ebin->raw_video_caps, caps))
580 ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
581 else if (gst_caps_can_intersect (ebin->raw_audio_caps, caps))
582 ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
583 /* else if (gst_caps_can_intersect (ebin->raw_text_caps, caps)) */
584 /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
585 GST_DEBUG_OBJECT (ebin, "Detected profile type as being %s",
586 g_type_name (ptype));
589 if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
593 /* If we have a name, try to find a profile with the same name */
595 gst_encoding_container_profile_get_profiles
596 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
598 for (; tmp; tmp = tmp->next) {
599 GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
600 const gchar *profilename = gst_encoding_profile_get_name (sprof);
602 if (profilename && !strcmp (name, profilename)) {
603 guint presence = gst_encoding_profile_get_presence (sprof);
605 GST_DEBUG ("Found profile matching the requested name");
607 if (!gst_encoding_profile_is_enabled (sprof)) {
608 GST_INFO_OBJECT (ebin, "%p is disabled, not using it", sprof);
614 || presence > stream_profile_used_count (ebin, sprof))
617 GST_WARNING ("Matching stream already used");
622 ("No profiles matching requested pad name, carrying on with normal stream matching");
626 gst_encoding_container_profile_get_profiles
627 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile)); tmp;
629 GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
631 /* Pick an available Stream profile for which:
632 * * either it is of the compatible raw type,
633 * * OR we can pass it through directly without encoding
635 if (G_TYPE_FROM_INSTANCE (sprof) == ptype) {
636 guint presence = gst_encoding_profile_get_presence (sprof);
637 GST_DEBUG ("Found a stream profile with the same type");
638 if (!gst_encoding_profile_is_enabled (sprof)) {
639 GST_INFO_OBJECT (ebin, "%p is disabled, not using it", sprof);
640 } else if (presence == 0
641 || (presence > stream_profile_used_count (ebin, sprof))) {
643 if (sprof != previous_profile)
646 } else if (caps && ptype == G_TYPE_NONE) {
650 outcaps = gst_encoding_profile_get_input_caps (sprof);
651 GST_DEBUG ("Unknown stream, seeing if it's compatible with %"
652 GST_PTR_FORMAT, outcaps);
653 res = gst_caps_can_intersect (outcaps, caps);
654 gst_caps_unref (outcaps);
656 if (res && sprof != previous_profile)
666 request_pad_for_stream (GstEncodeBaseBin * encodebin, GType ptype,
667 const gchar * name, GstCaps * caps)
669 StreamGroup *sgroup = NULL;
670 GList *not_found_encoder_profs = NULL, *tmp;
671 GstEncodingProfile *sprof = NULL;
673 GST_DEBUG_OBJECT (encodebin, "name:%s caps:%" GST_PTR_FORMAT, name, caps);
675 while (sgroup == NULL) {
676 gboolean encoder_not_found = FALSE;
677 /* Figure out if we have a unused GstEncodingProfile we can use for
679 sprof = next_unused_stream_profile (encodebin, ptype, name, caps, sprof);
681 if (G_UNLIKELY (sprof == NULL))
682 goto no_stream_profile;
684 sgroup = _create_stream_group (encodebin, sprof, name, caps,
687 if (G_UNLIKELY (sgroup))
690 if (encoder_not_found) {
691 not_found_encoder_profs = g_list_prepend (not_found_encoder_profs, sprof);
693 GST_DEBUG ("Could not create an encoder for %s", name);
694 goto no_stream_group;
702 goto no_stream_group;
704 g_list_free (not_found_encoder_profs);
705 return sgroup->ghostpad;
709 GST_WARNING_OBJECT (encodebin, "Couldn't find a compatible stream profile");
715 for (tmp = not_found_encoder_profs; tmp; tmp = tmp->next)
716 _post_missing_plugin_message (encodebin, tmp->data);
717 g_list_free (not_found_encoder_profs);
719 GST_WARNING_OBJECT (encodebin, "Couldn't create a StreamGroup");
725 gst_encode_base_bin_request_new_pad (GstElement * element,
726 GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
728 GstEncodeBaseBin *ebin = (GstEncodeBaseBin *) element;
731 GST_DEBUG_OBJECT (element, "templ:%s, name:%s", templ->name_template, name);
733 /* Identify the stream group (if name or caps have been provided) */
734 if (caps != NULL || name != NULL) {
735 res = request_pad_for_stream (ebin, G_TYPE_NONE, name, (GstCaps *) caps);
739 GType ptype = G_TYPE_NONE;
741 if (!strcmp (templ->name_template, "video_%u"))
742 ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
743 else if (!strcmp (templ->name_template, "audio_%u"))
744 ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
745 /* else if (!strcmp (templ->name_template, "text_%u")) */
746 /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
748 /* FIXME : Check uniqueness of pad */
749 /* FIXME : Check that the requested number is the last one, and if not,
750 * update the last_pad_id variable so that we don't create a pad with
751 * the same name/number in the future */
753 res = request_pad_for_stream (ebin, ptype, name, NULL);
760 gst_encode_base_bin_request_pad_signal (GstEncodeBaseBin * encodebin,
763 GstPad *pad = request_pad_for_stream (encodebin, G_TYPE_NONE, NULL, caps);
765 return pad ? GST_PAD_CAST (gst_object_ref (pad)) : NULL;
769 gst_encode_base_bin_request_profile_pad_signal (GstEncodeBaseBin * encodebin,
770 const gchar * profilename)
773 request_pad_for_stream (encodebin, G_TYPE_NONE, profilename, NULL);
775 return pad ? GST_PAD_CAST (gst_object_ref (pad)) : NULL;
778 static inline StreamGroup *
779 find_stream_group_from_pad (GstEncodeBaseBin * ebin, GstPad * pad)
783 for (tmp = ebin->streams; tmp; tmp = tmp->next) {
784 StreamGroup *sgroup = (StreamGroup *) tmp->data;
785 if (G_UNLIKELY (sgroup->ghostpad == pad))
793 gst_encode_base_bin_release_pad (GstElement * element, GstPad * pad)
795 GstEncodeBaseBin *ebin = (GstEncodeBaseBin *) element;
798 /* Find the associated StreamGroup */
800 sgroup = find_stream_group_from_pad (ebin, pad);
801 if (G_UNLIKELY (sgroup == NULL))
802 goto no_stream_group;
804 /* Release objects/data associated with the StreamGroup */
805 stream_group_remove (ebin, sgroup);
811 GST_WARNING_OBJECT (ebin, "Couldn't find corresponding StreamGroup");
816 /* Create a parser for the given stream profile */
817 static inline GstElement *
818 _get_parser (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof,
819 GstElement * encoder)
821 GList *parsers1, *parsers, *tmp;
822 GstElement *parser = NULL;
823 GstElementFactory *parserfact = NULL;
824 GstCaps *format = NULL;
827 GstPadTemplate *template = gst_element_get_pad_template (encoder, "src");
830 format = gst_pad_template_get_caps (template);
833 if (!format || gst_caps_is_any (format)) {
834 gst_clear_caps (&format);
835 format = gst_encoding_profile_get_format (sprof);
838 GST_DEBUG ("Getting list of parsers for format %" GST_PTR_FORMAT, format);
840 /* FIXME : requesting twice the parsers twice is a bit ugly, we should
841 * have a method to request on more than one condition */
843 gst_element_factory_list_filter (ebin->parsers, format,
846 gst_element_factory_list_filter (parsers1, format, GST_PAD_SINK, FALSE);
847 gst_plugin_feature_list_free (parsers1);
849 if (G_UNLIKELY (parsers == NULL)) {
850 GST_DEBUG ("Couldn't find any compatible parsers");
854 for (tmp = parsers; tmp; tmp = tmp->next) {
855 /* FIXME : We're only picking the first one so far */
856 /* FIXME : signal the user if he wants this */
857 parserfact = (GstElementFactory *) tmp->data;
862 parser = gst_element_factory_create (parserfact, NULL);
864 gst_plugin_feature_list_free (parsers);
868 gst_caps_unref (format);
874 _set_properties (GQuark property_id, const GValue * value, GObject * element)
876 GST_DEBUG_OBJECT (element, "Setting %s", g_quark_to_string (property_id));
877 g_object_set_property (element, g_quark_to_string (property_id), value);
883 set_element_properties_from_encoding_profile (GstEncodingProfile * profile,
884 GParamSpec * arg G_GNUC_UNUSED, GstElement * element)
888 GstElementFactory *factory;
889 GstStructure *properties =
890 gst_encoding_profile_get_element_properties (profile);
895 if (!gst_structure_has_name (properties, "element-properties-map")) {
896 gst_structure_foreach (properties,
897 (GstStructureForeachFunc) _set_properties, element);
901 factory = gst_element_get_factory (element);
903 GST_INFO_OBJECT (profile, "No factory for underlying element, "
904 "not setting properties");
908 v = gst_structure_get_value (properties, "map");
909 for (i = 0; i < gst_value_list_get_size (v); i++) {
910 const GValue *map_value = gst_value_list_get_value (v, i);
911 const GstStructure *tmp_properties;
913 if (!GST_VALUE_HOLDS_STRUCTURE (map_value)) {
914 g_warning ("Invalid value type %s in the property map "
915 "(expected GstStructure)", G_VALUE_TYPE_NAME (map_value));
919 tmp_properties = gst_value_get_structure (map_value);
920 if (!gst_structure_has_name (tmp_properties, GST_OBJECT_NAME (factory))) {
921 GST_INFO_OBJECT (GST_OBJECT_PARENT (element),
922 "Ignoring values for %" GST_PTR_FORMAT, tmp_properties);
926 GST_DEBUG_OBJECT (GST_OBJECT_PARENT (element),
927 "Setting %" GST_PTR_FORMAT " on %" GST_PTR_FORMAT, tmp_properties,
929 gst_structure_foreach (tmp_properties,
930 (GstStructureForeachFunc) _set_properties, element);
934 GST_ERROR_OBJECT (GST_OBJECT_PARENT (element), "Unknown factory: %s",
935 GST_OBJECT_NAME (factory));
938 gst_structure_free (properties);
942 _create_element_and_set_preset (GstElementFactory * factory,
943 GstEncodingProfile * profile, const gchar * name)
945 GstElement *res = NULL;
947 const gchar *preset_name;
949 preset_name = gst_encoding_profile_get_preset_name (profile);
950 preset = gst_encoding_profile_get_preset (profile);
951 GST_DEBUG ("Creating element from factory %s (preset factory name: %s"
952 " preset name: %s)", GST_OBJECT_NAME (factory), preset_name, preset);
954 if (preset_name && g_strcmp0 (GST_OBJECT_NAME (factory), preset_name)) {
955 GST_DEBUG ("Got to use %s, not %s", preset_name, GST_OBJECT_NAME (factory));
959 res = gst_element_factory_create (factory, name);
961 if (preset && GST_IS_PRESET (res)) {
962 if (preset_name == NULL ||
963 g_strcmp0 (GST_OBJECT_NAME (factory), preset_name) == 0) {
965 if (!gst_preset_load_preset (GST_PRESET (res), preset)) {
966 GST_WARNING ("Couldn't set preset [%s] on element [%s]",
967 preset, GST_OBJECT_NAME (factory));
968 gst_object_unref (res);
972 GST_DEBUG ("Using a preset with no preset name, making use of the"
973 " proper element without setting any property");
976 /* Else we keep it */
978 set_element_properties_from_encoding_profile (profile, NULL, res);
980 g_signal_connect (profile, "notify::element-properties",
981 G_CALLBACK (set_element_properties_from_encoding_profile), res);
987 /* Create the encoder for the given stream profile */
988 static inline GstElement *
989 _get_encoder (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof)
991 GList *encoders, *tmp;
992 GstElement *encoder = NULL;
993 GstElementFactory *encoderfact = NULL;
996 format = gst_encoding_profile_get_format (sprof);
998 GST_DEBUG ("Getting list of encoders for format %" GST_PTR_FORMAT, format);
1000 /* If stream caps are raw, return identity */
1001 if (G_UNLIKELY (are_raw_caps (format))) {
1002 GST_DEBUG ("Stream format is raw, returning identity as the encoder");
1003 encoder = gst_element_factory_make ("identity", NULL);
1008 gst_element_factory_list_filter (ebin->encoders, format,
1009 GST_PAD_SRC, FALSE);
1011 if (G_UNLIKELY (encoders == NULL) && sprof == ebin->profile) {
1012 /* Special case: if the top-level profile is an encoder,
1013 * it could be listed in our muxers (for example wavenc)
1015 encoders = gst_element_factory_list_filter (ebin->muxers, format,
1016 GST_PAD_SRC, FALSE);
1019 if (G_UNLIKELY (encoders == NULL)) {
1020 GST_DEBUG ("Couldn't find any compatible encoders");
1024 for (tmp = encoders; tmp; tmp = tmp->next) {
1025 encoderfact = (GstElementFactory *) tmp->data;
1026 if ((encoder = _create_element_and_set_preset (encoderfact, sprof, NULL)))
1030 gst_plugin_feature_list_free (encoders);
1034 gst_caps_unref (format);
1040 local_element_request_pad (GstElement * element, GstPadTemplate * templ,
1041 const gchar * name, const GstCaps * caps)
1043 GstPad *newpad = NULL;
1044 GstElementClass *oclass;
1046 oclass = GST_ELEMENT_GET_CLASS (element);
1048 if (oclass->request_new_pad)
1049 newpad = (oclass->request_new_pad) (element, templ, name, caps);
1052 gst_object_ref (newpad);
1058 gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
1061 GstPadPresence presence;
1063 /* If this function is ever exported, we need check the validity of `element'
1064 * and `templ', and to make sure the template actually belongs to the
1067 presence = GST_PAD_TEMPLATE_PRESENCE (templ);
1070 case GST_PAD_ALWAYS:
1071 case GST_PAD_SOMETIMES:
1072 ret = gst_element_get_static_pad (element, templ->name_template);
1073 if (!ret && presence == GST_PAD_ALWAYS)
1075 ("Element %s has an ALWAYS template %s, but no pad of the same name",
1076 GST_OBJECT_NAME (element), templ->name_template);
1079 case GST_PAD_REQUEST:
1080 ret = gst_element_request_pad (element, templ, NULL, NULL);
1087 static inline GstPad *
1088 get_compatible_muxer_sink_pad (GstEncodeBaseBin * ebin,
1089 GstEncodingProfile * sprof, GstCaps * sinkcaps)
1092 GList *padl, *compatible_templates = NULL;
1094 GST_DEBUG_OBJECT (ebin, "Finding muxer pad for caps: %" GST_PTR_FORMAT,
1096 padl = gst_element_get_pad_template_list (ebin->muxer);
1097 for (; padl; padl = padl->next) {
1098 const gchar *type_name, *other_type_name;
1099 GstPadTemplate *padtempl = padl->data;
1101 if (padtempl->direction == GST_PAD_SRC)
1104 if (!gst_caps_can_intersect (GST_PAD_TEMPLATE_CAPS (padtempl), sinkcaps))
1107 if (!gst_caps_is_any (GST_PAD_TEMPLATE_CAPS (padtempl))) {
1108 compatible_templates = g_list_append (compatible_templates, padtempl);
1112 if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) {
1113 type_name = "video";
1114 other_type_name = "audio";
1115 } else if (GST_IS_ENCODING_AUDIO_PROFILE (sprof)) {
1116 type_name = "audio";
1117 other_type_name = "video";
1119 compatible_templates = g_list_prepend (compatible_templates, padtempl);
1123 if (strstr (padtempl->name_template, type_name) == padtempl->name_template)
1124 compatible_templates = g_list_prepend (compatible_templates, padtempl);
1125 else if (!strstr (padtempl->name_template, other_type_name))
1126 compatible_templates = g_list_append (compatible_templates, padtempl);
1128 GST_LOG_OBJECT (padtempl, "not compatible with %" GST_PTR_FORMAT, sprof);
1131 if (G_UNLIKELY (compatible_templates == NULL))
1134 for (padl = compatible_templates; padl; padl = padl->next) {
1135 sinkpad = gst_element_get_pad_from_template (ebin->muxer, padl->data);
1140 g_list_free (compatible_templates);
1142 GST_DEBUG_OBJECT (ebin, "Returning pad: %" GST_PTR_FORMAT, sinkpad);
1148 GST_WARNING_OBJECT (ebin, "No compatible pad available on muxer");
1154 _has_class (GstElement * element, const gchar * classname)
1156 GstElementClass *klass;
1159 klass = GST_ELEMENT_GET_CLASS (element);
1160 value = gst_element_class_get_metadata (klass, GST_ELEMENT_METADATA_KLASS);
1164 return strstr (value, classname) != NULL;
1168 _profile_restriction_caps_cb (GstEncodingProfile * profile,
1169 GParamSpec * arg G_GNUC_UNUSED, StreamGroup * group)
1171 GstCaps *restriction = gst_encoding_profile_get_restriction (profile);
1173 g_object_set (group->capsfilter, "caps", restriction, NULL);
1177 _capsfilter_force_format (GstPad * pad,
1178 GParamSpec * arg G_GNUC_UNUSED, StreamGroup * sgroup)
1181 GstElement *parent =
1182 GST_ELEMENT_CAST (gst_object_get_parent (GST_OBJECT (pad)));
1185 GST_DEBUG_OBJECT (pad, "Doesn't have a parent anymore");
1189 g_object_get (pad, "caps", &caps, NULL);
1190 caps = gst_caps_copy (caps);
1192 GST_INFO_OBJECT (pad, "Forcing caps to %" GST_PTR_FORMAT, caps);
1193 if (parent == sgroup->outfilter || parent == sgroup->smart_capsfilter) {
1194 /* outfilter and the smart encoder internal capsfilter need to always be
1195 * in sync so the caps match between the two */
1196 if (sgroup->smart_capsfilter) {
1197 GstStructure *structure = gst_caps_get_structure (caps, 0);
1199 /* Pick a stream format that allows for in-band SPS updates if none
1200 * specified by the user, and remove restrictions on fields that can be
1201 * updated by codec_data or in-band SPS
1203 if (gst_structure_has_name (structure, "video/x-h264") &&
1204 !gst_structure_has_field (structure, "stream_format")) {
1205 gst_structure_set (structure, "stream-format",
1206 G_TYPE_STRING, "avc3", NULL);
1208 gst_structure_remove_fields (structure, "codec_data", "profile",
1210 } else if (gst_structure_has_name (structure, "video/x-h265") &&
1211 !gst_structure_has_field (structure, "stream_format")) {
1212 gst_structure_set (structure, "stream-format",
1213 G_TYPE_STRING, "hev1", NULL);
1215 gst_structure_remove_fields (structure, "codec_data", "tier", "profile",
1219 /* For VP8 / VP9, streamheader in the caps is informative, and
1220 * not actually used by muxers, we can allow it to change */
1221 if (gst_structure_has_name (structure, "video/x-vp8") ||
1222 gst_structure_has_name (structure, "video/x-vp9")) {
1223 gst_structure_remove_field (structure, "streamheader");
1226 g_object_set (sgroup->smart_capsfilter, "caps", caps, NULL);
1228 g_signal_handler_disconnect (sgroup->smart_capsfilter->sinkpads->data,
1229 sgroup->smart_capsfilter_sid);
1230 sgroup->smart_capsfilter_sid = 0;
1233 if (sgroup->outfilter) {
1234 GstCaps *tmpcaps = gst_caps_copy (caps);
1235 g_object_set (sgroup->outfilter, "caps", tmpcaps, NULL);
1236 gst_caps_unref (tmpcaps);
1237 g_signal_handler_disconnect (sgroup->outfilter->sinkpads->data,
1238 sgroup->outputfilter_caps_sid);
1239 sgroup->outputfilter_caps_sid = 0;
1241 } else if (parent == sgroup->capsfilter) {
1242 g_object_set (parent, "caps", caps, NULL);
1243 g_signal_handler_disconnect (pad, sgroup->inputfilter_caps_sid);
1245 g_assert_not_reached ();
1248 gst_caps_unref (caps);
1249 gst_object_unref (parent);
1253 _set_group_caps_format (StreamGroup * sgroup, GstEncodingProfile * prof,
1256 g_object_set (sgroup->outfilter, "caps", format, NULL);
1258 if (!gst_encoding_profile_get_allow_dynamic_output (prof)) {
1259 if (!sgroup->outputfilter_caps_sid) {
1260 sgroup->outputfilter_caps_sid =
1261 g_signal_connect (sgroup->outfilter->sinkpads->data,
1262 "notify::caps", G_CALLBACK (_capsfilter_force_format), sgroup);
1268 _post_missing_plugin_message (GstEncodeBaseBin * ebin,
1269 GstEncodingProfile * prof)
1272 format = gst_encoding_profile_get_format (prof);
1274 GST_ERROR_OBJECT (ebin,
1275 "Couldn't create encoder with preset %s and preset name %s"
1276 " for format %" GST_PTR_FORMAT,
1277 GST_STR_NULL (gst_encoding_profile_get_preset (prof)),
1278 GST_STR_NULL (gst_encoding_profile_get_preset_name (prof)), format);
1280 /* missing plugin support */
1281 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1282 gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin), format));
1283 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN,
1284 ("Couldn't create encoder for format %" GST_PTR_FORMAT, format), (NULL));
1286 gst_caps_unref (format);
1289 static GstPadProbeReturn
1290 _missing_plugin_probe (GstPad * pad, GstPadProbeInfo * info, gpointer udata)
1292 StreamGroup *sgroup = udata;
1293 GstEncodeBaseBin *ebin = sgroup->ebin;
1295 _post_missing_plugin_message (ebin, sgroup->profile);
1297 return GST_PAD_PROBE_OK;
1301 _set_up_fake_encoder_pad_probe (GstEncodeBaseBin * ebin, StreamGroup * sgroup)
1303 GstPad *pad = gst_element_get_static_pad (sgroup->fakesink, "sink");
1305 gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, _missing_plugin_probe,
1308 gst_object_unref (pad);
1312 setup_smart_encoder (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof,
1313 StreamGroup * sgroup)
1315 GstElement *encoder = NULL, *parser = NULL;
1316 GstElement *reencoder_bin = NULL;
1317 GstElement *sinkelement, *convert = NULL;
1318 GstElement *smartencoder = g_object_new (GST_TYPE_SMART_ENCODER, NULL);
1319 GstPad *srcpad = gst_element_get_static_pad (smartencoder, "src");
1321 gst_caps_make_writable (gst_encoding_profile_get_format (sprof));
1322 GstCaps *tmpcaps = gst_pad_query_caps (srcpad, NULL);
1323 const gboolean native_video =
1324 ! !(ebin->flags & GST_ENCODEBIN_FLAG_NO_VIDEO_CONVERSION);
1325 GstStructure *structure = gst_caps_get_structure (format, 0);
1327 /* Check if stream format is compatible */
1328 if (!gst_caps_can_intersect (tmpcaps, format)) {
1329 GST_DEBUG_OBJECT (ebin,
1330 "We don't have a smart encoder for the stream format: %" GST_PTR_FORMAT,
1335 sinkelement = encoder = _get_encoder (ebin, sprof);
1337 GST_INFO_OBJECT (ebin, "No encoder found... not using smart rendering");
1341 parser = _get_parser (ebin, sprof, encoder);
1342 sgroup->smart_capsfilter = gst_element_factory_make ("capsfilter", NULL);
1343 reencoder_bin = gst_bin_new (NULL);
1345 /* Pick a stream format that allows for in-band SPS updates, and remove
1346 * restrictions on fields that can be updated by codec_data or in-band SPS
1348 if (gst_structure_has_name (structure, "video/x-h264")) {
1349 gst_structure_set (structure, "stream-format", G_TYPE_STRING, "avc3", NULL);
1351 gst_structure_remove_fields (structure, "codec_data", "profile",
1353 } else if (gst_structure_has_name (structure, "video/x-h265")) {
1354 gst_structure_set (structure, "stream-format", G_TYPE_STRING, "hev1", NULL);
1356 gst_structure_remove_fields (structure, "codec_data", "tier", "profile",
1360 /* For VP8 / VP9, streamheader in the caps is informative, and
1361 * not actually used by muxers, we can allow it to change */
1362 if (gst_structure_has_name (structure, "video/x-vp8") ||
1363 gst_structure_has_name (structure, "video/x-vp9")) {
1364 gst_structure_remove_field (structure, "streamheader");
1367 g_object_set (sgroup->smart_capsfilter, "caps", format, NULL);
1369 gst_bin_add_many (GST_BIN (reencoder_bin),
1370 gst_object_ref (encoder),
1371 parser ? gst_object_ref (parser) :
1372 gst_object_ref (sgroup->smart_capsfilter),
1373 parser ? gst_object_ref (sgroup->smart_capsfilter) : NULL, NULL);
1374 if (!native_video) {
1375 convert = gst_element_factory_make ("videoconvert", NULL);
1377 GST_ERROR_OBJECT (ebin, "`videoconvert` element missing");
1381 gst_bin_add (GST_BIN (reencoder_bin), gst_object_ref (convert));
1382 if (!gst_element_link (convert, sinkelement)) {
1383 GST_ERROR_OBJECT (ebin, "Can not link `videoconvert` to %" GST_PTR_FORMAT,
1387 sinkelement = convert;
1390 if (!gst_element_link_many (encoder,
1391 parser ? parser : sgroup->smart_capsfilter,
1392 parser ? sgroup->smart_capsfilter : NULL, NULL)) {
1393 GST_ERROR_OBJECT (ebin, "Can not link smart encoding elements");
1397 if (!gst_element_add_pad (reencoder_bin,
1398 gst_ghost_pad_new ("sink", sinkelement->sinkpads->data))) {
1399 GST_ERROR_OBJECT (ebin, "Can add smart encoding bin `srcpad`");
1403 if (!gst_element_add_pad (reencoder_bin,
1404 gst_ghost_pad_new ("src", sgroup->smart_capsfilter->srcpads->data))) {
1405 GST_ERROR_OBJECT (ebin, "Could not ghost smart encoder bin"
1406 " srcpad, not being smart.");
1410 if (!gst_encoding_profile_get_allow_dynamic_output (sprof)) {
1411 /* Enforce no dynamic output in the smart encoder */
1412 if (!sgroup->smart_capsfilter_sid) {
1413 sgroup->smart_capsfilter_sid =
1414 g_signal_connect (sgroup->smart_capsfilter->sinkpads->data,
1415 "notify::caps", G_CALLBACK (_capsfilter_force_format), sgroup);
1419 if (!gst_smart_encoder_set_encoder (GST_SMART_ENCODER (smartencoder),
1420 format, reencoder_bin)) {
1421 reencoder_bin = NULL; /* We do not own the ref anymore */
1422 GST_ERROR_OBJECT (ebin, "Could not set encoder to the smart encoder,"
1423 " disabling smartness");
1428 gst_caps_unref (tmpcaps);
1429 gst_caps_unref (format);
1430 gst_object_unref (srcpad);
1431 gst_clear_object (&encoder);
1432 gst_clear_object (&parser);
1433 gst_clear_object (&convert);
1435 return smartencoder;
1438 gst_clear_object (&smartencoder);
1439 gst_clear_object (&reencoder_bin);
1443 /* FIXME : Add handling of streams that don't require conversion elements */
1445 * Create the elements, StreamGroup, add the sink pad, link it to the muxer
1447 * sinkpadname: If non-NULL, that name will be assigned to the sink ghost pad
1448 * sinkcaps: If non-NULL will be used to figure out how to setup the group
1449 * encoder_not_found: If non NULL, set to TRUE if failure happened because
1450 * the encoder could not be found
1452 static StreamGroup *
1453 _create_stream_group (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof,
1454 const gchar * sinkpadname, GstCaps * sinkcaps, gboolean * encoder_not_found)
1456 StreamGroup *sgroup = NULL;
1457 GstPad *sinkpad, *srcpad = NULL, *muxerpad = NULL;
1458 /* Element we will link to the encoder */
1459 GstElement *last = NULL;
1460 GstElement *encoder = NULL;
1461 GList *tmp, *tosync = NULL;
1462 GstCaps *format, *restriction;
1463 const gchar *missing_element_name;
1465 format = gst_encoding_profile_get_format (sprof);
1466 restriction = gst_encoding_profile_get_restriction (sprof);
1468 GST_DEBUG ("Creating group. format %" GST_PTR_FORMAT ", for caps %"
1469 GST_PTR_FORMAT, format, sinkcaps);
1470 GST_DEBUG ("avoid_reencoding:%d", ebin->avoid_reencoding);
1472 sgroup = g_slice_new0 (StreamGroup);
1473 sgroup->ebin = ebin;
1474 sgroup->profile = sprof;
1476 /* NOTE for people reading this code:
1478 * We construct the group starting by the furthest downstream element
1479 * and making our way up adding/syncing/linking as we go.
1481 * There are two parallel paths:
1482 * * One for raw data which goes through converters and encoders
1483 * * One for already encoded data
1486 /* Put _get_encoder() before request pad from muxer as _get_encoder() may fail and
1487 * MOV/MP4 muxer don't support addition/removal of tracks at random times */
1488 sgroup->encoder = _get_encoder (ebin, sprof);
1489 if (!sgroup->encoder && (gst_encoding_profile_get_preset (sgroup->profile)
1490 || gst_encoding_profile_get_preset_name (sgroup->profile))) {
1492 if (!encoder_not_found)
1493 _post_missing_plugin_message (ebin, sprof);
1495 *encoder_not_found = TRUE;
1498 /* passthrough can still work, if we discover that *
1499 * encoding is required we post a missing plugin message */
1503 * If we are handling a container profile, figure out if the muxer has a
1504 * sinkpad compatible with the selected profile */
1506 muxerpad = get_compatible_muxer_sink_pad (ebin, sprof, format);
1507 if (G_UNLIKELY (muxerpad == NULL))
1513 * The actual queueing will be done in the input queue, but some queuing
1514 * after the encoder can be beneficial for encoding performance. */
1515 last = sgroup->outqueue = gst_element_factory_make ("queue", NULL);
1516 g_object_set (sgroup->outqueue, "max-size-buffers", (guint) 0,
1517 "max-size-bytes", (guint) 0, "max-size-time", (guint64) 3 * GST_SECOND,
1518 "silent", TRUE, NULL);
1520 gst_bin_add (GST_BIN (ebin), sgroup->outqueue);
1521 tosync = g_list_append (tosync, sgroup->outqueue);
1522 srcpad = gst_element_get_static_pad (sgroup->outqueue, "src");
1524 if (G_UNLIKELY (fast_pad_link (srcpad, muxerpad) != GST_PAD_LINK_OK)) {
1525 goto muxer_link_failure;
1527 gst_object_unref (muxerpad);
1529 gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), srcpad);
1531 gst_object_unref (srcpad);
1534 /* Check if we need a formatter
1535 * If we have no muxer or
1536 * if the muxer isn't a formatter and doesn't implement the tagsetter interface
1538 if (!ebin->muxer || (!GST_IS_TAG_SETTER (ebin->muxer)
1539 && !_has_class (ebin->muxer, "Formatter"))) {
1540 sgroup->formatter = _get_formatter (ebin, sprof);
1541 if (sgroup->formatter) {
1542 GST_DEBUG ("Adding formatter for %" GST_PTR_FORMAT, format);
1544 gst_bin_add (GST_BIN (ebin), sgroup->formatter);
1545 tosync = g_list_append (tosync, sgroup->formatter);
1546 if (G_UNLIKELY (!fast_element_link (sgroup->formatter, last)))
1547 goto formatter_link_failure;
1548 last = sgroup->formatter;
1553 /* Output capsfilter
1554 * This will receive the format caps from the streamprofile */
1555 GST_DEBUG ("Adding output capsfilter for %" GST_PTR_FORMAT, format);
1556 sgroup->outfilter = gst_element_factory_make ("capsfilter", NULL);
1557 _set_group_caps_format (sgroup, sprof, format);
1559 gst_bin_add (GST_BIN (ebin), sgroup->outfilter);
1560 tosync = g_list_append (tosync, sgroup->outfilter);
1561 if (G_UNLIKELY (!fast_element_link (sgroup->outfilter, last)))
1562 goto outfilter_link_failure;
1563 last = sgroup->outfilter;
1565 sgroup->parser = _get_parser (ebin, sgroup->profile, sgroup->encoder);
1566 if (sgroup->parser != NULL) {
1567 GST_DEBUG ("Got a parser %s", GST_ELEMENT_NAME (sgroup->parser));
1568 gst_bin_add (GST_BIN (ebin), sgroup->parser);
1569 tosync = g_list_append (tosync, sgroup->parser);
1570 if (G_UNLIKELY (!gst_element_link (sgroup->parser, last)))
1571 goto parser_link_failure;
1572 last = sgroup->parser;
1575 /* Stream combiner */
1576 sgroup->combiner = g_object_new (GST_TYPE_STREAM_COMBINER, NULL);
1578 gst_bin_add (GST_BIN (ebin), sgroup->combiner);
1579 tosync = g_list_append (tosync, sgroup->combiner);
1580 if (G_UNLIKELY (!fast_element_link (sgroup->combiner, last)))
1581 goto combiner_link_failure;
1584 /* Stream splitter */
1585 sgroup->splitter = g_object_new (GST_TYPE_STREAM_SPLITTER, NULL);
1587 gst_bin_add (GST_BIN (ebin), sgroup->splitter);
1588 tosync = g_list_append (tosync, sgroup->splitter);
1590 if (gst_encoding_profile_get_single_segment (sprof)) {
1592 if (!ebin->avoid_reencoding) {
1593 sgroup->identity = gst_element_factory_make ("identity", NULL);
1594 g_object_set (sgroup->identity, "single-segment", TRUE, NULL);
1595 gst_bin_add (GST_BIN (ebin), sgroup->identity);
1596 tosync = g_list_append (tosync, sgroup->identity);
1598 GST_INFO_OBJECT (ebin, "Single segment is not supported when avoiding"
1604 * FIXME : figure out what max-size to use for the input queue */
1605 sgroup->inqueue = gst_element_factory_make ("queue", NULL);
1606 g_object_set (sgroup->inqueue, "max-size-buffers",
1607 (guint) ebin->queue_buffers_max, "max-size-bytes",
1608 (guint) ebin->queue_bytes_max, "max-size-time",
1609 (guint64) ebin->queue_time_max, "silent", TRUE, NULL);
1611 gst_bin_add (GST_BIN (ebin), sgroup->inqueue);
1612 tosync = g_list_append (tosync, sgroup->inqueue);
1614 /* Expose input queue or identity sink pad as ghostpad */
1616 gst_element_get_static_pad (sgroup->identity ? sgroup->identity : sgroup->
1618 if (sinkpadname == NULL) {
1620 g_strdup_printf ("%s_%u", gst_encoding_profile_get_type_nick (sprof),
1621 ebin->last_pad_id++);
1622 GST_DEBUG ("Adding ghost pad %s", pname);
1623 sgroup->ghostpad = gst_ghost_pad_new (pname, sinkpad);
1626 sgroup->ghostpad = gst_ghost_pad_new (sinkpadname, sinkpad);
1627 gst_object_unref (sinkpad);
1629 if (sgroup->identity
1630 && G_UNLIKELY (!fast_element_link (sgroup->identity, sgroup->inqueue)))
1631 goto queue_link_failure;
1633 if (G_UNLIKELY (!fast_element_link (sgroup->inqueue, sgroup->splitter)))
1634 goto splitter_link_failure;
1637 /* Path 1 : Already-encoded data */
1639 local_element_request_pad (sgroup->combiner, NULL, "passthroughsink",
1641 if (G_UNLIKELY (sinkpad == NULL))
1642 goto no_combiner_sinkpad;
1644 if (ebin->avoid_reencoding) {
1645 GST_DEBUG ("Asked to use Smart Encoder");
1646 sgroup->smartencoder = setup_smart_encoder (ebin, sprof, sgroup);
1647 if (sgroup->smartencoder) {
1648 gst_bin_add ((GstBin *) ebin, sgroup->smartencoder);
1649 srcpad = gst_element_get_static_pad (sgroup->smartencoder, "src");
1650 fast_pad_link (srcpad, sinkpad);
1651 gst_object_unref (srcpad);
1652 tosync = g_list_append (tosync, sgroup->smartencoder);
1653 sinkpad = gst_element_get_static_pad (sgroup->smartencoder, "sink");
1658 local_element_request_pad (sgroup->splitter, NULL, "passthroughsrc",
1660 if (G_UNLIKELY (srcpad == NULL))
1661 goto no_splitter_srcpad;
1663 /* Go straight to splitter */
1664 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1665 goto passthrough_link_failure;
1666 gst_object_unref (sinkpad);
1667 gst_object_unref (srcpad);
1670 /* Path 2 : Conversion / Encoding */
1672 /* 1. Create the encoder */
1673 GST_LOG ("Adding encoder");
1674 if (sgroup->encoder) {
1675 gst_bin_add ((GstBin *) ebin, sgroup->encoder);
1676 tosync = g_list_append (tosync, sgroup->encoder);
1679 local_element_request_pad (sgroup->combiner, NULL, "encodingsink",
1681 if (G_UNLIKELY (sinkpad == NULL))
1682 goto no_combiner_sinkpad;
1683 srcpad = gst_element_get_static_pad (sgroup->encoder, "src");
1684 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1685 goto encoder_link_failure;
1686 gst_object_unref (sinkpad);
1687 gst_object_unref (srcpad);
1692 /* 3. Create the conversion/restriction elements */
1693 /* 3.1. capsfilter */
1694 GST_LOG ("Adding capsfilter for restriction caps : %" GST_PTR_FORMAT,
1697 last = sgroup->capsfilter = gst_element_factory_make ("capsfilter", NULL);
1698 if (restriction && !gst_caps_is_any (restriction))
1699 g_object_set (sgroup->capsfilter, "caps", restriction, NULL);
1701 if (!gst_encoding_profile_get_allow_dynamic_output (sprof)) {
1702 if (!sgroup->inputfilter_caps_sid) {
1703 sgroup->inputfilter_caps_sid =
1704 g_signal_connect (sgroup->capsfilter->sinkpads->data,
1705 "notify::caps", G_CALLBACK (_capsfilter_force_format), sgroup);
1709 gst_bin_add ((GstBin *) ebin, sgroup->capsfilter);
1710 tosync = g_list_append (tosync, sgroup->capsfilter);
1711 if (sgroup->encoder == NULL) {
1712 /* no encoder available but it might be possible to just do passthrough, so
1713 * let's just set up a fake pad to detect that encoding was attempted and
1714 * if so it posts the missing plugin message */
1715 sgroup->fakesink = gst_element_factory_make ("fakesink", NULL);
1716 g_object_set (sgroup->fakesink, "async", FALSE, NULL);
1717 gst_bin_add (GST_BIN_CAST (ebin), sgroup->fakesink);
1718 tosync = g_list_append (tosync, sgroup->fakesink);
1719 encoder = sgroup->fakesink;
1721 _set_up_fake_encoder_pad_probe (ebin, sgroup);
1723 encoder = sgroup->encoder;
1725 fast_element_link (sgroup->capsfilter, encoder);
1726 sgroup->restriction_sid = g_signal_connect (sprof, "notify::restriction-caps",
1727 G_CALLBACK (_profile_restriction_caps_cb), sgroup);
1729 /* 3.2. restriction elements */
1730 /* FIXME : Once we have properties for specific converters, use those */
1731 if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) {
1732 const gboolean native_video =
1733 ! !(ebin->flags & GST_ENCODEBIN_FLAG_NO_VIDEO_CONVERSION);
1734 GstElement *cspace = NULL, *scale, *vrate, *cspace2 = NULL;
1736 GST_LOG ("Adding conversion elements for video stream");
1738 if (!native_video) {
1739 cspace = gst_element_factory_make ("videoconvert", NULL);
1740 scale = gst_element_factory_make ("videoscale", NULL);
1742 missing_element_name = "videoscale";
1743 goto missing_element;
1745 /* 4-tap scaling and black borders */
1746 g_object_set (scale, "method", 2, "add-borders", TRUE, NULL);
1747 cspace2 = gst_element_factory_make ("videoconvert", NULL);
1749 if (!cspace || !cspace2) {
1750 missing_element_name = "videoconvert";
1751 goto missing_element;
1754 gst_bin_add_many ((GstBin *) ebin, cspace, scale, cspace2, NULL);
1755 tosync = g_list_append (tosync, cspace);
1756 tosync = g_list_append (tosync, scale);
1757 tosync = g_list_append (tosync, cspace2);
1759 sgroup->converters = g_list_prepend (sgroup->converters, cspace);
1760 sgroup->converters = g_list_prepend (sgroup->converters, scale);
1761 sgroup->converters = g_list_prepend (sgroup->converters, cspace2);
1763 if (!fast_element_link (cspace, scale) ||
1764 !fast_element_link (scale, cspace2))
1765 goto converter_link_failure;
1768 if (!gst_encoding_video_profile_get_variableframerate
1769 (GST_ENCODING_VIDEO_PROFILE (sprof))) {
1770 vrate = gst_element_factory_make ("videorate", NULL);
1772 missing_element_name = "videorate";
1773 goto missing_element;
1775 g_object_set (vrate, "skip-to-first", TRUE, NULL);
1777 gst_bin_add ((GstBin *) ebin, vrate);
1778 tosync = g_list_prepend (tosync, vrate);
1779 sgroup->converters = g_list_prepend (sgroup->converters, vrate);
1781 if ((!native_video && !fast_element_link (cspace2, vrate))
1782 || !fast_element_link (vrate, last))
1783 goto converter_link_failure;
1789 } else if (!native_video) {
1790 if (!fast_element_link (cspace2, last))
1791 goto converter_link_failure;
1795 } else if (GST_IS_ENCODING_AUDIO_PROFILE (sprof)
1796 && !(ebin->flags & GST_ENCODEBIN_FLAG_NO_AUDIO_CONVERSION)) {
1797 GstElement *aconv, *ares, *arate, *aconv2;
1799 GST_LOG ("Adding conversion elements for audio stream");
1801 arate = gst_element_factory_make ("audiorate", NULL);
1803 missing_element_name = "audiorate";
1804 goto missing_element;
1806 g_object_set (arate, "tolerance", (guint64) ebin->tolerance, NULL);
1807 g_object_set (arate, "skip-to-first", TRUE, NULL);
1809 aconv = gst_element_factory_make ("audioconvert", NULL);
1810 aconv2 = gst_element_factory_make ("audioconvert", NULL);
1811 ares = gst_element_factory_make ("audioresample", NULL);
1812 if (!aconv || !aconv2) {
1813 missing_element_name = "audioconvert";
1814 goto missing_element;
1817 missing_element_name = "audioresample";
1818 goto missing_element;
1821 gst_bin_add_many ((GstBin *) ebin, arate, aconv, ares, aconv2, NULL);
1822 tosync = g_list_append (tosync, arate);
1823 tosync = g_list_append (tosync, aconv);
1824 tosync = g_list_append (tosync, ares);
1825 tosync = g_list_append (tosync, aconv2);
1826 if (!fast_element_link (arate, aconv) ||
1827 !fast_element_link (aconv, ares) ||
1828 !fast_element_link (ares, aconv2) || !fast_element_link (aconv2, last))
1829 goto converter_link_failure;
1831 sgroup->converters = g_list_prepend (sgroup->converters, arate);
1832 sgroup->converters = g_list_prepend (sgroup->converters, aconv);
1833 sgroup->converters = g_list_prepend (sgroup->converters, ares);
1834 sgroup->converters = g_list_prepend (sgroup->converters, aconv2);
1839 /* Link to stream splitter */
1840 sinkpad = gst_element_get_static_pad (last, "sink");
1842 local_element_request_pad (sgroup->splitter, NULL, "encodingsrc", NULL);
1843 if (G_UNLIKELY (srcpad == NULL))
1844 goto no_splitter_srcpad;
1845 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1846 goto splitter_encoding_failure;
1847 gst_object_unref (sinkpad);
1848 gst_object_unref (srcpad);
1851 /* End of Stream 2 setup */
1853 /* Sync all elements to parent state */
1854 for (tmp = tosync; tmp; tmp = tmp->next)
1855 gst_element_sync_state_with_parent ((GstElement *) tmp->data);
1856 g_list_free (tosync);
1859 GST_DEBUG ("Adding ghostpad %s:%s", GST_DEBUG_PAD_NAME (sgroup->ghostpad));
1860 gst_pad_set_active (sgroup->ghostpad, TRUE);
1861 gst_element_add_pad ((GstElement *) ebin, sgroup->ghostpad);
1863 /* Add StreamGroup to our list of streams */
1866 ("Done creating elements, adding StreamGroup to our controlled stream list");
1868 ebin->streams = g_list_prepend (ebin->streams, sgroup);
1871 gst_caps_unref (format);
1873 gst_caps_unref (restriction);
1877 splitter_encoding_failure:
1878 GST_ERROR_OBJECT (ebin, "Error linking splitter to encoding stream");
1882 GST_ERROR_OBJECT (ebin,
1883 "Couldn't find a compatible muxer pad to link encoder to");
1887 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1888 gst_missing_element_message_new (GST_ELEMENT_CAST (ebin),
1889 missing_element_name));
1890 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN,
1891 (_("Missing element '%s' - check your GStreamer installation."),
1892 missing_element_name), (NULL));
1895 encoder_link_failure:
1896 GST_ERROR_OBJECT (ebin, "Failed to link the encoder");
1900 GST_ERROR_OBJECT (ebin, "Couldn't link encoder to muxer");
1903 formatter_link_failure:
1904 GST_ERROR_OBJECT (ebin, "Couldn't link output filter to output queue");
1907 outfilter_link_failure:
1908 GST_ERROR_OBJECT (ebin,
1909 "Couldn't link output filter to output queue/formatter");
1912 passthrough_link_failure:
1913 GST_ERROR_OBJECT (ebin, "Failed linking splitter in passthrough mode");
1917 GST_ERROR_OBJECT (ebin, "Couldn't get a source pad from the splitter");
1920 no_combiner_sinkpad:
1921 GST_ERROR_OBJECT (ebin, "Couldn't get a sink pad from the combiner");
1924 splitter_link_failure:
1925 GST_ERROR_OBJECT (ebin, "Failure linking to the splitter");
1929 GST_ERROR_OBJECT (ebin, "Failure linking to the inqueue");
1932 combiner_link_failure:
1933 GST_ERROR_OBJECT (ebin, "Failure linking to the combiner");
1936 parser_link_failure:
1937 GST_ERROR_OBJECT (ebin, "Failure linking the parser");
1940 converter_link_failure:
1941 GST_ERROR_OBJECT (ebin, "Failure linking the video converters");
1945 /* FIXME : Actually properly cleanup everything */
1947 gst_caps_unref (format);
1949 gst_caps_unref (restriction);
1951 gst_object_unref (srcpad);
1952 stream_group_free (ebin, sgroup);
1953 g_list_free (tosync);
1958 _gst_caps_match_foreach (GQuark field_id, const GValue * value, gpointer data)
1960 GstStructure *structure = data;
1961 const GValue *other_value = gst_structure_id_get_value (structure, field_id);
1963 if (G_UNLIKELY (other_value == NULL))
1965 if (gst_value_compare (value, other_value) == GST_VALUE_EQUAL) {
1973 * checks that there is at least one structure on caps_a that has
1974 * all its fields exactly the same as one structure on caps_b
1977 _gst_caps_match (const GstCaps * caps_a, const GstCaps * caps_b)
1980 gboolean res = FALSE;
1982 for (i = 0; i < gst_caps_get_size (caps_a); i++) {
1983 GstStructure *structure_a = gst_caps_get_structure (caps_a, i);
1984 for (j = 0; j < gst_caps_get_size (caps_b); j++) {
1985 GstStructure *structure_b = gst_caps_get_structure (caps_b, j);
1987 res = gst_structure_foreach (structure_a, _gst_caps_match_foreach,
1998 _factory_can_handle_caps (GstElementFactory * factory, const GstCaps * caps,
1999 GstPadDirection dir, gboolean exact)
2001 const GList *templates;
2003 templates = gst_element_factory_get_static_pad_templates (factory);
2005 GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
2007 if (template->direction == dir) {
2008 GstCaps *tmp = gst_static_caps_get (&template->static_caps);
2010 if ((exact && _gst_caps_match (caps, tmp)) ||
2011 (!exact && gst_caps_can_intersect (tmp, caps))) {
2012 gst_caps_unref (tmp);
2015 gst_caps_unref (tmp);
2017 templates = g_list_next (templates);
2023 static inline GstElement *
2024 _get_formatter (GstEncodeBaseBin * ebin, GstEncodingProfile * sprof)
2026 GList *formatters, *tmpfmtr;
2027 GstElement *formatter = NULL;
2028 GstElementFactory *formatterfact = NULL;
2030 format = gst_encoding_profile_get_format (sprof);
2032 GST_DEBUG ("Getting list of formatters for format %" GST_PTR_FORMAT, format);
2035 gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
2038 if (formatters == NULL)
2041 /* FIXME : signal the user if he wants this */
2042 for (tmpfmtr = formatters; tmpfmtr; tmpfmtr = tmpfmtr->next) {
2043 formatterfact = (GstElementFactory *) tmpfmtr->data;
2045 GST_DEBUG_OBJECT (ebin, "Trying formatter %s",
2046 GST_OBJECT_NAME (formatterfact));
2049 _create_element_and_set_preset (formatterfact, sprof, NULL)))
2053 gst_plugin_feature_list_free (formatters);
2057 gst_caps_unref (format);
2062 compare_elements (gconstpointer a, gconstpointer b, gpointer udata)
2064 GstCaps *caps = udata;
2065 GstElementFactory *fac_a = (GstElementFactory *) a;
2066 GstElementFactory *fac_b = (GstElementFactory *) b;
2068 /* FIXME not quite sure this is the best algorithm to order the elements
2069 * Some caps similarity comparison algorithm would fit better than going
2070 * boolean (equals/not equals).
2072 gboolean equals_a = _factory_can_handle_caps (fac_a, caps, GST_PAD_SRC, TRUE);
2073 gboolean equals_b = _factory_can_handle_caps (fac_b, caps, GST_PAD_SRC, TRUE);
2075 if (equals_a == equals_b) {
2076 return gst_plugin_feature_get_rank ((GstPluginFeature *) fac_b) -
2077 gst_plugin_feature_get_rank ((GstPluginFeature *) fac_a);
2078 } else if (equals_a) {
2080 } else if (equals_b) {
2086 static inline GstElement *
2087 _get_muxer (GstEncodeBaseBin * ebin)
2089 GList *muxers = NULL, *formatters, *tmpmux;
2090 GstElement *muxer = NULL;
2091 GstElementFactory *muxerfact = NULL;
2094 const gchar *preset_name;
2096 format = gst_encoding_profile_get_format (ebin->profile);
2097 preset_name = gst_encoding_profile_get_preset_name (ebin->profile);
2099 GST_DEBUG_OBJECT (ebin, "Getting list of muxers for format %" GST_PTR_FORMAT,
2103 GstElementFactory *f =
2104 (GstElementFactory *) gst_registry_find_feature (gst_registry_get (),
2106 GST_TYPE_ELEMENT_FACTORY);
2109 muxers = g_list_append (muxers, f);
2112 gst_element_factory_list_filter (ebin->muxers, format, GST_PAD_SRC,
2118 gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
2121 muxers = g_list_sort_with_data (muxers, compare_elements, (gpointer) format);
2123 g_list_sort_with_data (formatters, compare_elements, (gpointer) format);
2125 muxers = g_list_concat (muxers, formatters);
2130 /* FIXME : signal the user if he wants this */
2131 for (tmpmux = muxers; tmpmux; tmpmux = tmpmux->next) {
2132 gboolean cansinkstreams = TRUE;
2133 const GList *profiles =
2134 gst_encoding_container_profile_get_profiles
2135 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
2137 muxerfact = (GstElementFactory *) tmpmux->data;
2139 GST_DEBUG_OBJECT (ebin, "Trying muxer %s", GST_OBJECT_NAME (muxerfact));
2141 /* See if the muxer can sink all of our stream profile caps */
2142 for (tmp = profiles; tmp; tmp = tmp->next) {
2143 GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
2144 GstCaps *sformat = gst_encoding_profile_get_format (sprof);
2146 if (!_factory_can_handle_caps (muxerfact, sformat, GST_PAD_SINK, FALSE)) {
2147 GST_ERROR ("Skipping muxer because it can't sink caps %"
2148 GST_PTR_FORMAT, sformat);
2149 cansinkstreams = FALSE;
2151 gst_caps_unref (sformat);
2155 gst_caps_unref (sformat);
2158 /* Only use a muxer than can use all streams and than can accept the
2159 * preset (which may be present or not) */
2160 if (cansinkstreams && (muxer =
2161 _create_element_and_set_preset (muxerfact, ebin->profile, "muxer")))
2165 gst_plugin_feature_list_free (muxers);
2169 gst_caps_unref (format);
2174 create_elements_and_pads (GstEncodeBaseBin * ebin)
2176 gboolean ret = TRUE;
2177 GstElement *muxer = NULL;
2179 const GList *tmp, *profiles;
2180 GstEncodingProfile *sprof;
2182 GST_DEBUG ("Current profile : %s",
2183 gst_encoding_profile_get_name (ebin->profile));
2185 if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
2186 /* Get the compatible muxer */
2187 muxer = _get_muxer (ebin);
2188 if (G_UNLIKELY (muxer == NULL))
2191 /* Record the muxer */
2192 ebin->muxer = muxer;
2193 gst_bin_add ((GstBin *) ebin, muxer);
2195 /* If the subclass exposes a static sourcepad, ghost the muxer
2196 * output, otherwise expose the muxer srcpad if it has one,
2197 * do not expose any srcpad if we are dealing with a muxing sink. */
2198 /* FIXME : We should figure out if it's a static/request/dynamic pad,
2199 * but for the time being let's assume it's a static pad :) */
2200 muxerpad = gst_element_get_static_pad (muxer, "src");
2202 if (G_UNLIKELY (muxerpad == NULL))
2204 if (!gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), muxerpad))
2205 goto no_muxer_ghost_pad;
2207 gst_object_unref (muxerpad);
2208 } else if (muxerpad) {
2209 GstPadTemplate *template =
2210 gst_element_get_pad_template (GST_ELEMENT (ebin), "src_%u");
2214 GST_OBJECT_LOCK (ebin);
2215 name = g_strdup_printf ("src_%u", GST_ELEMENT (ebin)->numsrcpads);
2216 GST_OBJECT_UNLOCK (ebin);
2218 pad = gst_ghost_pad_new_from_template (name, muxerpad, template);
2221 goto no_muxer_ghost_pad;
2223 gst_element_add_pad (GST_ELEMENT (ebin), pad);
2226 /* Activate fixed presence streams */
2228 gst_encoding_container_profile_get_profiles
2229 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
2230 for (tmp = profiles; tmp; tmp = tmp->next) {
2231 sprof = (GstEncodingProfile *) tmp->data;
2233 GST_DEBUG ("Trying stream profile with presence %d",
2234 gst_encoding_profile_get_presence (sprof));
2236 if (gst_encoding_profile_get_presence (sprof) != 0 &&
2237 gst_encoding_profile_is_enabled (sprof)) {
2238 if (G_UNLIKELY (_create_stream_group (ebin, sprof, NULL, NULL,
2243 gst_element_sync_state_with_parent (muxer);
2245 if (G_UNLIKELY (_create_stream_group (ebin, ebin->profile, NULL,
2246 NULL, NULL) == NULL))
2254 GstCaps *format = gst_encoding_profile_get_format (ebin->profile);
2256 GST_WARNING ("No available muxer for %" GST_PTR_FORMAT, format);
2257 /* missing plugin support */
2258 gst_element_post_message (GST_ELEMENT_CAST (ebin),
2259 gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin), format));
2260 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN,
2261 ("No available muxer for format %" GST_PTR_FORMAT, format), (NULL));
2263 gst_caps_unref (format);
2269 GST_WARNING ("Can't get source pad from muxer (%s)",
2270 GST_ELEMENT_NAME (muxer));
2271 gst_bin_remove (GST_BIN (ebin), muxer);
2277 GST_WARNING ("Couldn't set %s:%s as source ghostpad target",
2278 GST_DEBUG_PAD_NAME (muxerpad));
2279 gst_bin_remove (GST_BIN (ebin), muxer);
2280 gst_object_unref (muxerpad);
2286 GST_WARNING ("Could not create Streams");
2288 gst_bin_remove (GST_BIN (ebin), muxer);
2295 release_pads (const GValue * item, GstElement * elt)
2297 GstPad *pad = g_value_get_object (item);
2298 GstPad *peer = NULL;
2300 GST_DEBUG_OBJECT (elt, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
2302 /* Unlink from its peer pad */
2303 if ((peer = gst_pad_get_peer (pad))) {
2304 if (GST_PAD_DIRECTION (peer) == GST_PAD_SRC)
2305 gst_pad_unlink (peer, pad);
2307 gst_pad_unlink (pad, peer);
2308 gst_object_unref (peer);
2311 /* Release it from the object */
2312 gst_element_release_request_pad (elt, pad);
2316 stream_group_free (GstEncodeBaseBin * ebin, StreamGroup * sgroup)
2322 GST_DEBUG_OBJECT (ebin, "Freeing StreamGroup %p", sgroup);
2324 if (sgroup->restriction_sid != 0)
2325 g_signal_handler_disconnect (sgroup->profile, sgroup->restriction_sid);
2327 if (sgroup->outqueue) {
2329 /* outqueue - Muxer */
2330 tmppad = gst_element_get_static_pad (sgroup->outqueue, "src");
2331 pad = gst_pad_get_peer (tmppad);
2334 /* Remove muxer request sink pad */
2335 gst_pad_unlink (tmppad, pad);
2336 if (GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) ==
2338 gst_element_release_request_pad (ebin->muxer, pad);
2339 gst_object_unref (pad);
2341 gst_object_unref (tmppad);
2343 gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
2346 if (sgroup->formatter) {
2347 /* capsfilter - formatter - outqueue */
2348 gst_element_set_state (sgroup->formatter, GST_STATE_NULL);
2349 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
2350 gst_element_unlink (sgroup->formatter, sgroup->outqueue);
2351 gst_element_unlink (sgroup->outfilter, sgroup->formatter);
2352 } else if (sgroup->outfilter) {
2353 /* Capsfilter - outqueue */
2354 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
2355 gst_element_unlink (sgroup->outfilter, sgroup->outqueue);
2358 if (sgroup->outqueue) {
2359 gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
2360 gst_bin_remove (GST_BIN (ebin), sgroup->outqueue);
2363 /* streamcombiner - parser - capsfilter */
2364 if (sgroup->parser) {
2365 gst_element_set_state (sgroup->parser, GST_STATE_NULL);
2366 gst_element_unlink (sgroup->parser, sgroup->outfilter);
2367 gst_element_unlink (sgroup->combiner, sgroup->parser);
2368 gst_bin_remove ((GstBin *) ebin, sgroup->parser);
2372 if (sgroup->ghostpad) {
2373 if (GST_PAD_PARENT (sgroup->ghostpad) != NULL)
2374 gst_element_remove_pad (GST_ELEMENT_CAST (ebin), sgroup->ghostpad);
2376 gst_object_unref (sgroup->ghostpad);
2379 if (sgroup->inqueue)
2380 gst_element_set_state (sgroup->inqueue, GST_STATE_NULL);
2382 if (sgroup->encoder) {
2383 gst_element_set_state (sgroup->encoder, GST_STATE_NULL);
2384 g_signal_handlers_disconnect_by_func (sgroup->profile,
2385 set_element_properties_from_encoding_profile, sgroup->encoder);
2387 if (sgroup->fakesink)
2388 gst_element_set_state (sgroup->fakesink, GST_STATE_NULL);
2389 if (sgroup->outfilter) {
2390 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
2392 if (sgroup->outputfilter_caps_sid) {
2393 g_signal_handler_disconnect (sgroup->outfilter->sinkpads->data,
2394 sgroup->outputfilter_caps_sid);
2395 sgroup->outputfilter_caps_sid = 0;
2398 if (sgroup->smartencoder)
2399 gst_element_set_state (sgroup->smartencoder, GST_STATE_NULL);
2400 gst_clear_object (&sgroup->smart_capsfilter);
2402 if (sgroup->capsfilter) {
2403 gst_element_set_state (sgroup->capsfilter, GST_STATE_NULL);
2404 if (sgroup->encoder)
2405 gst_element_unlink (sgroup->capsfilter, sgroup->encoder);
2407 gst_element_unlink (sgroup->capsfilter, sgroup->fakesink);
2409 gst_bin_remove ((GstBin *) ebin, sgroup->capsfilter);
2412 for (tmp = sgroup->converters; tmp; tmp = tmp->next) {
2413 GstElement *elt = (GstElement *) tmp->data;
2415 gst_element_set_state (elt, GST_STATE_NULL);
2416 gst_bin_remove ((GstBin *) ebin, elt);
2418 if (sgroup->converters)
2419 g_list_free (sgroup->converters);
2421 if (sgroup->combiner) {
2422 GstIterator *it = gst_element_iterate_sink_pads (sgroup->combiner);
2423 GstIteratorResult itret = GST_ITERATOR_OK;
2425 while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
2427 gst_iterator_foreach (it, (GstIteratorForeachFunction) release_pads,
2429 gst_iterator_resync (it);
2431 gst_iterator_free (it);
2432 gst_element_set_state (sgroup->combiner, GST_STATE_NULL);
2433 gst_bin_remove ((GstBin *) ebin, sgroup->combiner);
2436 if (sgroup->splitter) {
2437 GstIterator *it = gst_element_iterate_src_pads (sgroup->splitter);
2438 GstIteratorResult itret = GST_ITERATOR_OK;
2439 while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
2441 gst_iterator_foreach (it, (GstIteratorForeachFunction) release_pads,
2443 gst_iterator_resync (it);
2445 gst_iterator_free (it);
2447 gst_element_set_state (sgroup->splitter, GST_STATE_NULL);
2448 gst_bin_remove ((GstBin *) ebin, sgroup->splitter);
2451 if (sgroup->inqueue)
2452 gst_bin_remove ((GstBin *) ebin, sgroup->inqueue);
2454 if (sgroup->encoder)
2455 gst_bin_remove ((GstBin *) ebin, sgroup->encoder);
2457 if (sgroup->fakesink)
2458 gst_bin_remove ((GstBin *) ebin, sgroup->fakesink);
2460 if (sgroup->smartencoder)
2461 gst_bin_remove ((GstBin *) ebin, sgroup->smartencoder);
2463 if (sgroup->outfilter)
2464 gst_bin_remove ((GstBin *) ebin, sgroup->outfilter);
2466 g_slice_free (StreamGroup, sgroup);
2470 stream_group_remove (GstEncodeBaseBin * ebin, StreamGroup * sgroup)
2472 ebin->streams = g_list_remove (ebin->streams, sgroup);
2474 stream_group_free (ebin, sgroup);
2478 gst_encode_base_bin_tear_down_profile (GstEncodeBaseBin * ebin)
2480 GstElement *element = GST_ELEMENT (ebin);
2482 if (G_UNLIKELY (ebin->profile == NULL))
2485 GST_DEBUG ("Tearing down profile %s",
2486 gst_encoding_profile_get_name (ebin->profile));
2488 while (ebin->streams)
2489 stream_group_remove (ebin, (StreamGroup *) ebin->streams->data);
2492 /* Set ghostpad target to NULL */
2493 gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), NULL);
2496 /* Remove muxer if present */
2498 g_signal_handlers_disconnect_by_func (ebin->profile,
2499 set_element_properties_from_encoding_profile, ebin->muxer);
2500 gst_element_set_state (ebin->muxer, GST_STATE_NULL);
2501 gst_bin_remove (GST_BIN (ebin), ebin->muxer);
2505 if (!element->srcpads) {
2506 while (element->srcpads)
2507 gst_element_remove_pad (element, element->srcpads->data);
2510 /* free/clear profile */
2511 gst_encoding_profile_unref (ebin->profile);
2512 ebin->profile = NULL;
2516 gst_encode_base_bin_setup_profile (GstEncodeBaseBin * ebin,
2517 GstEncodingProfile * profile)
2521 g_return_val_if_fail (ebin->profile == NULL, FALSE);
2523 GST_DEBUG ("Setting up profile %p:%s (type:%s)", profile,
2524 gst_encoding_profile_get_name (profile),
2525 gst_encoding_profile_get_type_nick (profile));
2527 ebin->profile = profile;
2528 gst_object_ref (ebin->profile);
2530 /* Create elements */
2531 res = create_elements_and_pads (ebin);
2533 gst_encode_base_bin_tear_down_profile (ebin);
2539 gst_encode_base_bin_set_profile (GstEncodeBaseBin * ebin,
2540 GstEncodingProfile * profile)
2542 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
2544 GST_DEBUG_OBJECT (ebin, "profile (%p) : %s", profile,
2545 gst_encoding_profile_get_name (profile));
2547 if (G_UNLIKELY (ebin->active)) {
2548 GST_WARNING_OBJECT (ebin, "Element already active, can't change profile");
2552 /* If we're not active, we can deactivate the previous profile */
2553 if (ebin->profile) {
2554 gst_encode_base_bin_tear_down_profile (ebin);
2557 return gst_encode_base_bin_setup_profile (ebin, profile);
2560 static inline gboolean
2561 gst_encode_base_bin_activate (GstEncodeBaseBin * ebin)
2563 ebin->active = ebin->profile != NULL;
2564 return ebin->active;
2568 gst_encode_base_bin_deactivate (GstEncodeBaseBin * ebin)
2572 for (tmp = ebin->streams; tmp; tmp = tmp->next) {
2573 StreamGroup *sgroup = tmp->data;
2574 GstCaps *format = gst_encoding_profile_get_format (sgroup->profile);
2576 _set_group_caps_format (sgroup, sgroup->profile, format);
2579 gst_caps_unref (format);
2582 ebin->active = FALSE;
2585 static GstStateChangeReturn
2586 gst_encode_base_bin_change_state (GstElement * element,
2587 GstStateChange transition)
2589 GstStateChangeReturn ret;
2590 GstEncodeBaseBin *ebin = (GstEncodeBaseBin *) element;
2592 switch (transition) {
2593 case GST_STATE_CHANGE_READY_TO_PAUSED:
2594 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2595 if (!gst_encode_base_bin_activate (ebin)) {
2596 ret = GST_STATE_CHANGE_FAILURE;
2605 GST_ELEMENT_CLASS (gst_encode_base_bin_parent_class)->change_state
2606 (element, transition);
2607 if (ret == GST_STATE_CHANGE_FAILURE)
2610 switch (transition) {
2611 case GST_STATE_CHANGE_PAUSED_TO_READY:
2612 gst_encode_base_bin_deactivate (ebin);