1 /* GStreamer encoding bin
2 * Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
3 * (C) 2009 Nokia Corporation
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
26 #include "gstencodebin.h"
27 #include "gstsmartencoder.h"
28 #include "gststreamsplitter.h"
29 #include "gststreamcombiner.h"
30 #include <gst/gst-i18n-plugin.h>
33 * SECTION:element-encodebin
35 * EncodeBin provides a bin for encoding/muxing various streams according to
36 * a specified #GstEncodingProfile.
38 * Based on the profile that was set (via the #GstEncodeBin:profile property),
39 * EncodeBin will internally select and configure the required elements
40 * (encoders, muxers, but also audio and video converters) so that you can
41 * provide it raw or pre-encoded streams of data in input and have your
42 * encoded/muxed/converted stream in output.
45 * <title>Features</title>
48 * 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
57 * Variable number of streams. If the presence property for a stream encoding
58 * profile is 0, you can request any number of sink pads for it via the
59 * standard request pad gstreamer API or the #GstEncodeBin::request-pad action
63 * Avoid reencoding (passthrough). If the input stream is already encoded and is
64 * compatible with what the #GstEncodingProfile expects, then the stream won't
65 * be re-encoded but just passed through downstream to the muxer or the output.
68 * Mix pre-encoded and raw streams as input. In addition to the passthrough
69 * feature above, you can feed both raw audio/video *AND* already-encoded data
70 * to a pad. #GstEncodeBin will take care of passing through the compatible
71 * segments and re-encoding the segments of media that need encoding.
74 * Standard behaviour is to use a #GstEncodingContainerProfile to have both
75 * encoding and muxing performed. But you can also provide a single stream
76 * profile (like #GstEncodingAudioProfile) to only have the encoding done and
77 * handle the encoded output yourself.
80 * Audio imperfection corrections. Incoming audio streams can have non perfect
81 * timestamps (jitter), like the streams coming from ASF files. #GstEncodeBin
82 * will automatically fix those imperfections for you. See
83 * #GstEncodeBin:audio-jitter-tolerance for more details.
86 * Variable or Constant video framerate. If your #GstEncodingVideoProfile has
87 * the variableframerate property deactivated (default), then the incoming
88 * raw video stream will be retimestampped in order to produce a constant
92 * Cross-boundary re-encoding. When feeding compatible pre-encoded streams that
93 * fall on segment boundaries, and for supported formats (right now only H263),
94 * the GOP will be decoded/reencoded when needed to produce an encoded output
95 * that fits exactly within the request GstSegment.
98 * Missing plugin support. If a #GstElement is missing to encode/mux to the
99 * request profile formats, a missing-plugin #GstMessage will be posted on the
100 * #GstBus, allowing systems that support the missing-plugin system to offer the
101 * user a way to install the missing element.
110 * Handling mp3!xing!idv3 and theora!ogg tagsetting scenarios:
111 * Once we have chosen a muxer:
112 * When a new stream is requested:
113 * If muxer isn't 'Formatter' OR doesn't have a TagSetter interface:
114 * Find a Formatter for the given stream (preferably with TagSetter)
115 * Insert that before muxer
118 #define fast_pad_link(a,b) gst_pad_link_full((a),(b),GST_PAD_LINK_CHECK_NOTHING)
119 #define fast_element_link(a,b) gst_element_link_pads_full((a),"src",(b),"sink",GST_PAD_LINK_CHECK_NOTHING)
121 /* generic templates */
122 static GstStaticPadTemplate muxer_src_template =
123 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
124 GST_STATIC_CAPS_ANY);
126 static GstStaticPadTemplate video_sink_template =
127 GST_STATIC_PAD_TEMPLATE ("video_%d",
130 GST_STATIC_CAPS_ANY);
131 static GstStaticPadTemplate audio_sink_template =
132 GST_STATIC_PAD_TEMPLATE ("audio_%d",
135 GST_STATIC_CAPS_ANY);
136 /* static GstStaticPadTemplate text_sink_template = */
137 /* GST_STATIC_PAD_TEMPLATE ("text_%d", */
139 /* GST_PAD_REQUEST, */
140 /* GST_STATIC_CAPS_ANY); */
141 static GstStaticPadTemplate private_sink_template =
142 GST_STATIC_PAD_TEMPLATE ("private_%d",
145 GST_STATIC_CAPS_ANY);
151 /* the profile field is only valid if it could be entirely setup */
152 GstEncodingProfile *profile;
154 GList *streams; /* List of StreamGroup, not sorted */
157 /* Ghostpad with changing target */
160 /* TRUE if in PAUSED/PLAYING */
163 /* available muxers, encoders and parsers */
169 /* Increasing counter for unique pad name */
172 /* Cached caps for identification */
173 GstCaps *raw_video_caps;
174 GstCaps *raw_audio_caps;
175 /* GstCaps *raw_text_caps; */
177 guint queue_buffers_max;
178 guint queue_bytes_max;
179 guint64 queue_time_max;
182 gboolean avoid_reencoding;
185 struct _GstEncodeBinClass
190 GstPad *(*request_pad) (GstEncodeBin * encodebin, GstCaps * caps);
193 typedef struct _StreamGroup StreamGroup;
198 GstEncodingProfile *profile;
199 GstPad *ghostpad; /* Sink ghostpad */
200 GstElement *inqueue; /* Queue just after the ghostpad */
201 GstElement *splitter;
202 GList *converters; /* List of conversion GstElement */
203 GstElement *capsfilter; /* profile->restriction (if non-NULL/ANY) */
204 GstElement *encoder; /* Encoder (can be NULL) */
205 GstElement *combiner;
207 GstElement *smartencoder;
208 GstElement *outfilter; /* Output capsfilter (streamprofile.format) */
209 GstElement *formatter;
210 GstElement *outqueue; /* Queue just before the muxer */
213 /* Default for queues (same defaults as queue element) */
214 #define DEFAULT_QUEUE_BUFFERS_MAX 200
215 #define DEFAULT_QUEUE_BYTES_MAX 10 * 1024 * 1024
216 #define DEFAULT_QUEUE_TIME_MAX GST_SECOND
217 #define DEFAULT_AUDIO_JITTER_TOLERANCE 20 * GST_MSECOND
218 #define DEFAULT_AVOID_REENCODING FALSE
220 #define DEFAULT_RAW_CAPS \
222 "audio/x-raw-int; " \
223 "audio/x-raw-float; " \
225 "text/x-pango-markup; " \
226 "video/x-dvd-subpicture; " \
234 PROP_QUEUE_BUFFERS_MAX,
235 PROP_QUEUE_BYTES_MAX,
237 PROP_AUDIO_JITTER_TOLERANCE,
238 PROP_AVOID_REENCODING,
249 static guint gst_encode_bin_signals[LAST_SIGNAL] = { 0 };
251 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
253 GST_DEBUG_CATEGORY_STATIC (gst_encode_bin_debug);
254 #define GST_CAT_DEFAULT gst_encode_bin_debug
256 G_DEFINE_TYPE (GstEncodeBin, gst_encode_bin, GST_TYPE_BIN);
258 static void gst_encode_bin_dispose (GObject * object);
259 static void gst_encode_bin_set_property (GObject * object, guint prop_id,
260 const GValue * value, GParamSpec * pspec);
261 static void gst_encode_bin_get_property (GObject * object, guint prop_id,
262 GValue * value, GParamSpec * pspec);
263 static GstStateChangeReturn gst_encode_bin_change_state (GstElement * element,
264 GstStateChange transition);
266 static GstPad *gst_encode_bin_request_new_pad (GstElement * element,
267 GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
268 static void gst_encode_bin_release_pad (GstElement * element, GstPad * pad);
271 gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile);
272 static void gst_encode_bin_tear_down_profile (GstEncodeBin * ebin);
273 static gboolean gst_encode_bin_setup_profile (GstEncodeBin * ebin,
274 GstEncodingProfile * profile);
276 static StreamGroup *_create_stream_group (GstEncodeBin * ebin,
277 GstEncodingProfile * sprof, const gchar * sinkpadname, GstCaps * sinkcaps);
278 static void stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup);
279 static GstPad *gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin,
282 static inline GstElement *_get_formatter (GstEncodeBin * ebin,
283 GstEncodingProfile * sprof);
286 gst_encode_bin_class_init (GstEncodeBinClass * klass)
288 GObjectClass *gobject_klass;
289 GstElementClass *gstelement_klass;
291 gobject_klass = (GObjectClass *) klass;
292 gstelement_klass = (GstElementClass *) klass;
294 gobject_klass->dispose = gst_encode_bin_dispose;
295 gobject_klass->set_property = gst_encode_bin_set_property;
296 gobject_klass->get_property = gst_encode_bin_get_property;
301 * GstEncodeBin:profile:
303 * The #GstEncodingProfile to use. This property must be set before going
304 * to %GST_STATE_PAUSED or higher.
306 g_object_class_install_property (gobject_klass, PROP_PROFILE,
307 g_param_spec_object ("profile", "Profile",
308 "The GstEncodingProfile to use", GST_TYPE_ENCODING_PROFILE,
309 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
311 g_object_class_install_property (gobject_klass, PROP_QUEUE_BUFFERS_MAX,
312 g_param_spec_uint ("queue-bytes-max", "Max. size (kB)",
313 "Max. amount of data in the queue (bytes, 0=disable)",
314 0, G_MAXUINT, DEFAULT_QUEUE_BYTES_MAX,
315 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
317 g_object_class_install_property (gobject_klass, PROP_QUEUE_BYTES_MAX,
318 g_param_spec_uint ("queue-buffers-max", "Max. size (buffers)",
319 "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
320 DEFAULT_QUEUE_BUFFERS_MAX,
321 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
323 g_object_class_install_property (gobject_klass, PROP_QUEUE_TIME_MAX,
324 g_param_spec_uint64 ("queue-time-max", "Max. size (ns)",
325 "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
326 DEFAULT_QUEUE_TIME_MAX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
328 g_object_class_install_property (gobject_klass, PROP_AUDIO_JITTER_TOLERANCE,
329 g_param_spec_uint64 ("audio-jitter-tolerance", "Audio jitter tolerance",
330 "Amount of timestamp jitter/imperfection to allow on audio streams before inserting/dropping samples (ns)",
331 0, G_MAXUINT64, DEFAULT_AUDIO_JITTER_TOLERANCE,
332 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
334 g_object_class_install_property (gobject_klass, PROP_AVOID_REENCODING,
335 g_param_spec_boolean ("avoid-reencoding", "Avoid re-encoding",
336 "Whether to re-encode portions of compatible video streams that lay on segment boundaries",
337 DEFAULT_AVOID_REENCODING,
338 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
342 * GstEncodeBin::request-pad
343 * @encodebin: a #GstEncodeBin instance
346 * Use this method to request an unused sink request #GstPad that can take the
347 * provided @caps as input. You must release the pad with
348 * gst_element_release_request_pad() when you are done with it.
350 * Returns: A compatible #GstPad, or %NULL if no compatible #GstPad could be
351 * created or is available.
353 gst_encode_bin_signals[SIGNAL_REQUEST_PAD] =
354 g_signal_new ("request-pad", G_TYPE_FROM_CLASS (klass),
355 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstEncodeBinClass,
356 request_pad), NULL, NULL, gst_encode_marshal_OBJECT__BOXED,
357 GST_TYPE_PAD, 1, GST_TYPE_CAPS);
359 klass->request_pad = gst_encode_bin_request_pad_signal;
361 gst_element_class_add_pad_template (gstelement_klass,
362 gst_static_pad_template_get (&muxer_src_template));
363 gst_element_class_add_pad_template (gstelement_klass,
364 gst_static_pad_template_get (&video_sink_template));
365 gst_element_class_add_pad_template (gstelement_klass,
366 gst_static_pad_template_get (&audio_sink_template));
367 /* gst_element_class_add_pad_template (gstelement_klass, */
368 /* gst_static_pad_template_get (&text_sink_template)); */
369 gst_element_class_add_pad_template (gstelement_klass,
370 gst_static_pad_template_get (&private_sink_template));
372 gstelement_klass->change_state =
373 GST_DEBUG_FUNCPTR (gst_encode_bin_change_state);
374 gstelement_klass->request_new_pad =
375 GST_DEBUG_FUNCPTR (gst_encode_bin_request_new_pad);
376 gstelement_klass->release_pad =
377 GST_DEBUG_FUNCPTR (gst_encode_bin_release_pad);
379 gst_element_class_set_details_simple (gstelement_klass,
381 "Generic/Bin/Encoder",
382 "Convenience encoding/muxing element",
383 "Edward Hervey <edward.hervey@collabora.co.uk>");
387 gst_encode_bin_dispose (GObject * object)
389 GstEncodeBin *ebin = (GstEncodeBin *) object;
392 gst_plugin_feature_list_free (ebin->muxers);
394 if (ebin->formatters)
395 gst_plugin_feature_list_free (ebin->formatters);
398 gst_plugin_feature_list_free (ebin->encoders);
401 gst_plugin_feature_list_free (ebin->parsers);
403 gst_encode_bin_tear_down_profile (ebin);
405 if (ebin->raw_video_caps)
406 gst_caps_unref (ebin->raw_video_caps);
407 if (ebin->raw_audio_caps)
408 gst_caps_unref (ebin->raw_audio_caps);
409 /* if (ebin->raw_text_caps) */
410 /* gst_caps_unref (ebin->raw_text_caps); */
412 G_OBJECT_CLASS (gst_encode_bin_parent_class)->dispose (object);
416 gst_encode_bin_init (GstEncodeBin * encode_bin)
418 GstPadTemplate *tmpl;
421 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
424 encode_bin->formatters =
425 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_FORMATTER,
428 encode_bin->encoders =
429 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
432 encode_bin->parsers =
433 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_PARSER,
436 encode_bin->raw_video_caps = gst_caps_from_string ("video/x-raw");
437 encode_bin->raw_audio_caps =
438 gst_caps_from_string ("audio/x-raw-int;audio/x-raw-float");
439 /* encode_bin->raw_text_caps = */
440 /* gst_caps_from_string ("text/plain;text/x-pango-markup"); */
442 encode_bin->queue_buffers_max = DEFAULT_QUEUE_BUFFERS_MAX;
443 encode_bin->queue_bytes_max = DEFAULT_QUEUE_BYTES_MAX;
444 encode_bin->queue_time_max = DEFAULT_QUEUE_TIME_MAX;
445 encode_bin->tolerance = DEFAULT_AUDIO_JITTER_TOLERANCE;
446 encode_bin->avoid_reencoding = DEFAULT_AVOID_REENCODING;
448 tmpl = gst_static_pad_template_get (&muxer_src_template);
449 encode_bin->srcpad = gst_ghost_pad_new_no_target_from_template ("src", tmpl);
450 gst_object_unref (tmpl);
451 gst_element_add_pad (GST_ELEMENT_CAST (encode_bin), encode_bin->srcpad);
455 gst_encode_bin_set_property (GObject * object, guint prop_id,
456 const GValue * value, GParamSpec * pspec)
458 GstEncodeBin *ebin = (GstEncodeBin *) object;
462 gst_encode_bin_set_profile (ebin,
463 (GstEncodingProfile *) g_value_get_object (value));
465 case PROP_QUEUE_BUFFERS_MAX:
466 ebin->queue_buffers_max = g_value_get_uint (value);
468 case PROP_QUEUE_BYTES_MAX:
469 ebin->queue_bytes_max = g_value_get_uint (value);
471 case PROP_QUEUE_TIME_MAX:
472 ebin->queue_time_max = g_value_get_uint64 (value);
474 case PROP_AUDIO_JITTER_TOLERANCE:
475 ebin->tolerance = g_value_get_uint64 (value);
477 case PROP_AVOID_REENCODING:
478 ebin->avoid_reencoding = g_value_get_boolean (value);
481 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
487 gst_encode_bin_get_property (GObject * object, guint prop_id,
488 GValue * value, GParamSpec * pspec)
490 GstEncodeBin *ebin = (GstEncodeBin *) object;
494 g_value_set_object (value, (GObject *) ebin->profile);
496 case PROP_QUEUE_BUFFERS_MAX:
497 g_value_set_uint (value, ebin->queue_buffers_max);
499 case PROP_QUEUE_BYTES_MAX:
500 g_value_set_uint (value, ebin->queue_bytes_max);
502 case PROP_QUEUE_TIME_MAX:
503 g_value_set_uint64 (value, ebin->queue_time_max);
505 case PROP_AUDIO_JITTER_TOLERANCE:
506 g_value_set_uint64 (value, ebin->tolerance);
508 case PROP_AVOID_REENCODING:
509 g_value_set_boolean (value, ebin->avoid_reencoding);
512 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
517 static inline gboolean
518 are_raw_caps (const GstCaps * caps)
520 GstCaps *raw = gst_static_caps_get (&default_raw_caps);
522 if (gst_caps_can_intersect (caps, raw)) {
523 gst_caps_unref (raw);
526 gst_caps_unref (raw);
530 /* Returns the number of time a given stream profile is currently used
533 stream_profile_used_count (GstEncodeBin * ebin, GstEncodingProfile * sprof)
535 guint nbprofused = 0;
538 for (tmp = ebin->streams; tmp; tmp = tmp->next) {
539 StreamGroup *sgroup = (StreamGroup *) tmp->data;
541 if (sgroup->profile == sprof)
548 static inline GstEncodingProfile *
549 next_unused_stream_profile (GstEncodeBin * ebin, GType ptype, GstCaps * caps)
551 GST_DEBUG_OBJECT (ebin, "ptype:%s, caps:%" GST_PTR_FORMAT,
552 g_type_name (ptype), caps);
554 if (G_UNLIKELY (ptype == G_TYPE_NONE && caps != NULL)) {
555 /* Identify the profile type based on raw caps */
556 if (gst_caps_can_intersect (ebin->raw_video_caps, caps))
557 ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
558 else if (gst_caps_can_intersect (ebin->raw_audio_caps, caps))
559 ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
560 /* else if (gst_caps_can_intersect (ebin->raw_text_caps, caps)) */
561 /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
562 GST_DEBUG_OBJECT (ebin, "Detected profile type as being %s",
563 g_type_name (ptype));
566 if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
570 gst_encoding_container_profile_get_profiles
571 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile)); tmp;
573 GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
575 /* Pick an available Stream profile for which:
576 * * either it is of the compatibly raw type,
577 * * OR we can pass it through directly without encoding
579 if (G_TYPE_FROM_INSTANCE (sprof) == ptype) {
580 guint presence = gst_encoding_profile_get_presence (sprof);
581 GST_DEBUG ("Found a stream profile with the same type");
583 || (presence > stream_profile_used_count (ebin, sprof)))
585 } else if ((caps != NULL) && (ptype == G_TYPE_NONE)) {
589 outcaps = gst_encoding_profile_get_input_caps (sprof);
590 GST_DEBUG ("Unknown stream, seeing if it's compatible with %"
591 GST_PTR_FORMAT, outcaps);
592 res = gst_caps_can_intersect (outcaps, caps);
593 gst_caps_unref (outcaps);
605 request_pad_for_stream (GstEncodeBin * encodebin, GType ptype,
606 const gchar * name, GstCaps * caps)
609 GstEncodingProfile *sprof;
611 GST_DEBUG_OBJECT (encodebin, "name:%s caps:%" GST_PTR_FORMAT, name, caps);
613 /* Figure out if we have a unused GstEncodingProfile we can use for
615 sprof = next_unused_stream_profile (encodebin, ptype, caps);
617 if (G_UNLIKELY (sprof == NULL))
618 goto no_stream_profile;
620 sgroup = _create_stream_group (encodebin, sprof, name, caps);
621 if (G_UNLIKELY (sgroup == NULL))
622 goto no_stream_group;
624 return sgroup->ghostpad;
628 GST_WARNING_OBJECT (encodebin, "Couldn't find a compatible stream profile");
634 GST_WARNING_OBJECT (encodebin, "Couldn't create a StreamGroup");
640 gst_encode_bin_request_new_pad (GstElement * element,
641 GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
643 GstEncodeBin *ebin = (GstEncodeBin *) element;
646 GST_DEBUG_OBJECT (element, "templ:%s, name:%s", templ->name_template, name);
648 /* Identify the stream group */
650 res = request_pad_for_stream (ebin, G_TYPE_NONE, name, (GstCaps *) caps);
654 GType ptype = G_TYPE_NONE;
656 if (!strcmp (templ->name_template, "video_%d"))
657 ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
658 else if (!strcmp (templ->name_template, "audio_%d"))
659 ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
660 /* else if (!strcmp (templ->name_template, "text_%d")) */
661 /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
663 /* FIXME : Check uniqueness of pad */
664 /* FIXME : Check that the requested number is the last one, and if not,
665 * update the last_pad_id variable so that we don't create a pad with
666 * the same name/number in the future */
668 res = request_pad_for_stream (ebin, ptype, name, NULL);
675 gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin, GstCaps * caps)
677 GstPad *pad = request_pad_for_stream (encodebin, G_TYPE_NONE, NULL, caps);
679 return pad ? GST_PAD_CAST (gst_object_ref (pad)) : NULL;
682 static inline StreamGroup *
683 find_stream_group_from_pad (GstEncodeBin * ebin, GstPad * pad)
687 for (tmp = ebin->streams; tmp; tmp = tmp->next) {
688 StreamGroup *sgroup = (StreamGroup *) tmp->data;
689 if (G_UNLIKELY (sgroup->ghostpad == pad))
697 gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
699 GstEncodeBin *ebin = (GstEncodeBin *) element;
702 /* Find the associated StreamGroup */
704 sgroup = find_stream_group_from_pad (ebin, pad);
705 if (G_UNLIKELY (sgroup == NULL))
706 goto no_stream_group;
708 /* Release objects/data associated with the StreamGroup */
709 stream_group_remove (ebin, sgroup);
715 GST_WARNING_OBJECT (ebin, "Couldn't find corresponding StreamGroup");
720 /* Create a parser for the given stream profile */
721 static inline GstElement *
722 _get_parser (GstEncodeBin * ebin, GstEncodingProfile * sprof)
724 GList *parsers1, *parsers, *tmp;
725 GstElement *parser = NULL;
726 GstElementFactory *parserfact = NULL;
727 const GstCaps *format;
729 format = gst_encoding_profile_get_format (sprof);
731 GST_DEBUG ("Getting list of parsers for format %" GST_PTR_FORMAT, format);
733 /* FIXME : requesting twice the parsers twice is a bit ugly, we should
734 * have a method to request on more than one condition */
736 gst_element_factory_list_filter (ebin->parsers, format,
739 gst_element_factory_list_filter (parsers1, format, GST_PAD_SINK, FALSE);
740 gst_plugin_feature_list_free (parsers1);
742 if (G_UNLIKELY (parsers == NULL)) {
743 GST_DEBUG ("Couldn't find any compatible parsers");
747 for (tmp = parsers; tmp; tmp = tmp->next) {
748 /* FIXME : We're only picking the first one so far */
749 /* FIXME : signal the user if he wants this */
750 parserfact = (GstElementFactory *) tmp->data;
755 parser = gst_element_factory_create (parserfact, NULL);
757 gst_plugin_feature_list_free (parsers);
763 _create_element_and_set_preset (GstElementFactory * factory,
764 const gchar * preset, const gchar * name)
766 GstElement *res = NULL;
768 GST_DEBUG ("Creating element from factory %s", GST_OBJECT_NAME (factory));
769 res = gst_element_factory_create (factory, name);
770 if (preset && GST_IS_PRESET (res) &&
771 !gst_preset_load_preset (GST_PRESET (res), preset)) {
772 GST_WARNING ("Couldn't set preset [%s] on element [%s]",
773 preset, GST_OBJECT_NAME (factory));
774 gst_object_unref (res);
781 /* Create the encoder for the given stream profile */
782 static inline GstElement *
783 _get_encoder (GstEncodeBin * ebin, GstEncodingProfile * sprof)
785 GList *encoders, *tmp;
786 GstElement *encoder = NULL;
787 GstElementFactory *encoderfact = NULL;
788 const GstCaps *format;
791 format = gst_encoding_profile_get_format (sprof);
792 preset = gst_encoding_profile_get_preset (sprof);
794 GST_DEBUG ("Getting list of encoders for format %" GST_PTR_FORMAT, format);
796 /* If stream caps are raw, return identity */
797 if (G_UNLIKELY (are_raw_caps (format))) {
798 GST_DEBUG ("Stream format is raw, returning identity as the encoder");
799 encoder = gst_element_factory_make ("identity", NULL);
804 gst_element_factory_list_filter (ebin->encoders, format,
807 if (G_UNLIKELY (encoders == NULL)) {
808 GST_DEBUG ("Couldn't find any compatible encoders");
812 for (tmp = encoders; tmp; tmp = tmp->next) {
813 encoderfact = (GstElementFactory *) tmp->data;
814 if ((encoder = _create_element_and_set_preset (encoderfact, preset, NULL)))
818 gst_plugin_feature_list_free (encoders);
825 local_element_request_pad (GstElement * element, GstPadTemplate * templ,
826 const gchar * name, const GstCaps * caps)
828 GstPad *newpad = NULL;
829 GstElementClass *oclass;
831 oclass = GST_ELEMENT_GET_CLASS (element);
833 if (oclass->request_new_pad)
834 newpad = (oclass->request_new_pad) (element, templ, name, caps);
837 gst_object_ref (newpad);
843 gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
846 GstPadPresence presence;
848 /* If this function is ever exported, we need check the validity of `element'
849 * and `templ', and to make sure the template actually belongs to the
852 presence = GST_PAD_TEMPLATE_PRESENCE (templ);
856 case GST_PAD_SOMETIMES:
857 ret = gst_element_get_static_pad (element, templ->name_template);
858 if (!ret && presence == GST_PAD_ALWAYS)
860 ("Element %s has an ALWAYS template %s, but no pad of the same name",
861 GST_OBJECT_NAME (element), templ->name_template);
864 case GST_PAD_REQUEST:
865 ret = gst_element_request_pad (element, templ, NULL, NULL);
872 /* FIXME : Improve algorithm for finding compatible muxer sink pad */
873 static inline GstPad *
874 get_compatible_muxer_sink_pad (GstEncodeBin * ebin, GstElement * encoder,
878 GstPadTemplate *srctempl = NULL;
879 GstPadTemplate *sinktempl;
883 srcpad = gst_element_get_static_pad (encoder, "src");
885 srctempl = gst_pad_get_pad_template (srcpad);
887 GST_DEBUG_OBJECT (ebin,
888 "Attempting to find pad from muxer %s compatible with %s:%s",
889 GST_ELEMENT_NAME (ebin->muxer), GST_DEBUG_PAD_NAME (srcpad));
891 gst_object_unref (srcpad);
892 sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl);
893 gst_object_unref (srctempl);
896 gst_pad_template_new ("whatever", GST_PAD_SRC, GST_PAD_ALWAYS,
898 g_assert (srctempl != NULL);
899 sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl);
900 g_object_unref (srctempl);
903 if (G_UNLIKELY (sinktempl == NULL))
906 sinkpad = gst_element_get_pad_from_template (ebin->muxer, sinktempl);
912 GST_WARNING_OBJECT (ebin, "No compatible pad available on muxer");
918 _has_class (GstElement * element, const gchar * classname)
920 GstElementClass *klass;
923 klass = GST_ELEMENT_GET_CLASS (element);
924 value = gst_element_class_get_metadata (klass, GST_ELEMENT_METADATA_KLASS);
926 return strstr (value, classname) != NULL;
929 /* FIXME : Add handling of streams that don't need encoding */
930 /* FIXME : Add handling of streams that don't require conversion elements */
932 * Create the elements, StreamGroup, add the sink pad, link it to the muxer
934 * sinkpadname: If non-NULL, that name will be assigned to the sink ghost pad
935 * sinkcaps: If non-NULL will be used to figure out how to setup the group */
937 _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
938 const gchar * sinkpadname, GstCaps * sinkcaps)
940 StreamGroup *sgroup = NULL;
941 GstPad *sinkpad, *srcpad, *muxerpad = NULL;
942 /* Element we will link to the encoder */
943 GstElement *last = NULL;
944 GList *tmp, *tosync = NULL;
945 GstCaps *format, *restriction;
946 const gchar *missing_element_name;
948 format = gst_encoding_profile_get_format (sprof);
949 restriction = gst_encoding_profile_get_restriction (sprof);
951 GST_DEBUG ("Creating group. format %" GST_PTR_FORMAT ", for caps %"
952 GST_PTR_FORMAT, format, sinkcaps);
953 GST_DEBUG ("avoid_reencoding:%d", ebin->avoid_reencoding);
955 sgroup = g_slice_new0 (StreamGroup);
957 sgroup->profile = sprof;
959 /* NOTE for people reading this code:
961 * We construct the group starting by the furthest downstream element
962 * and making our way up adding/syncing/linking as we go.
964 * There are two parallel paths:
965 * * One for raw data which goes through converters and encoders
966 * * One for already encoded data
969 /* Exception to the rule above:
970 * We check if we have an available encoder so we can abort early */
971 /* FIXME : What if we only want to do passthrough ??? */
972 GST_LOG ("Checking for encoder availability");
973 sgroup->encoder = _get_encoder (ebin, sprof);
974 if (G_UNLIKELY (sgroup->encoder == NULL))
978 * If we are handling a container profile, figure out if the muxer has a
979 * sinkpad compatible with the selected profile */
981 muxerpad = get_compatible_muxer_sink_pad (ebin, NULL, format);
982 if (G_UNLIKELY (muxerpad == NULL))
988 * We only use a 1buffer long queue here, the actual queueing will be done
989 * in the input queue */
990 last = sgroup->outqueue = gst_element_factory_make ("queue", NULL);
991 g_object_set (sgroup->outqueue, "max-size-buffers", (guint32) 1,
992 "max-size-bytes", (guint32) 0, "max-size-time", (guint64) 0, NULL);
994 gst_bin_add (GST_BIN (ebin), sgroup->outqueue);
995 tosync = g_list_append (tosync, sgroup->outqueue);
996 srcpad = gst_element_get_static_pad (sgroup->outqueue, "src");
998 if (G_UNLIKELY (fast_pad_link (srcpad, muxerpad) != GST_PAD_LINK_OK)) {
999 goto muxer_link_failure;
1001 gst_object_unref (muxerpad);
1003 gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), srcpad);
1005 gst_object_unref (srcpad);
1007 /* Check if we need a formatter
1008 * If we have no muxer or
1009 * if the muxer isn't a formatter and doesn't implement the tagsetter interface
1012 || (!gst_element_implements_interface (ebin->muxer, GST_TYPE_TAG_SETTER)
1013 || !_has_class (ebin->muxer, "Formatter"))) {
1014 sgroup->formatter = _get_formatter (ebin, sprof);
1015 if (sgroup->formatter) {
1016 GST_DEBUG ("Adding formatter for %" GST_PTR_FORMAT, format);
1018 gst_bin_add (GST_BIN (ebin), sgroup->formatter);
1019 tosync = g_list_append (tosync, sgroup->formatter);
1020 if (G_UNLIKELY (!fast_element_link (sgroup->formatter, last)))
1021 goto formatter_link_failure;
1022 last = sgroup->formatter;
1027 /* Output capsfilter
1028 * This will receive the format caps from the streamprofile */
1029 GST_DEBUG ("Adding output capsfilter for %" GST_PTR_FORMAT, format);
1030 sgroup->outfilter = gst_element_factory_make ("capsfilter", NULL);
1031 g_object_set (sgroup->outfilter, "caps", format, NULL);
1033 gst_bin_add (GST_BIN (ebin), sgroup->outfilter);
1034 tosync = g_list_append (tosync, sgroup->outfilter);
1035 if (G_UNLIKELY (!fast_element_link (sgroup->outfilter, last)))
1036 goto outfilter_link_failure;
1037 last = sgroup->outfilter;
1042 * The usage of parsers in encoding/muxing scenarios is
1043 * just too undefined to just use as-is.
1045 * Take the use-case where you want to re-mux a stream of type
1046 * "my/media". You create a StreamEncodingProfile with that type
1047 * as the target (as-is). And you use decodebin2/uridecodebin
1050 * * demuxer exposes "my/media"
1051 * * a parser is available for "my/media" which has a source pad
1052 * caps of "my/media,parsed=True"
1053 * * decodebin2/uridecodebin exposes a new pad with the parsed caps
1054 * * You request a new stream from encodebin, which will match the
1055 * streamprofile and creates a group (i.e. going through this method)
1056 * There is a matching parser (the same used in the decoder) whose
1057 * source pad caps intersects with the stream profile caps, you
1058 * therefore use it...
1059 * * ... but that parser has a "my/media,parsed=False" sink pad caps
1060 * * ... and you can't link your decodebin pad to encodebin.
1062 * In the end, it comes down to parsers only taking into account the
1063 * decoding use-cases.
1065 * One way to solve that might be to :
1066 * * Make parsers sink pad caps be "framed={False,True}" and the
1067 * source pad caps be "framed=True"
1068 * * Modify decodebin2 accordingly to avoid looping and chaining
1069 * an infinite number of parsers
1071 * Another way would be to have "well-known" caps properties to specify
1072 * whether a stream has been parsed or not.
1073 * * currently we fail. aacparse uses 'framed' and mp3parse uses 'parsed'
1075 /* FIXME : Re-enable once parser situation is un-$#*@(%$#ed */
1078 * FIXME : identify smart parsers (used for re-encoding) */
1079 sgroup->parser = _get_parser (ebin, sprof);
1081 if (sgroup->parser != NULL) {
1082 GST_DEBUG ("Got a parser %s", GST_ELEMENT_NAME (sgroup->parser));
1083 gst_bin_add (GST_BIN (ebin), sgroup->parser);
1084 tosync = g_list_append (tosync, sgroup->parser);
1085 if (G_UNLIKELY (!gst_element_link (sgroup->parser, last)))
1086 goto parser_link_failure;
1087 last = sgroup->parser;
1091 /* Stream combiner */
1092 sgroup->combiner = g_object_new (GST_TYPE_STREAM_COMBINER, NULL);
1094 gst_bin_add (GST_BIN (ebin), sgroup->combiner);
1095 tosync = g_list_append (tosync, sgroup->combiner);
1096 if (G_UNLIKELY (!fast_element_link (sgroup->combiner, last)))
1097 goto combiner_link_failure;
1100 /* Stream splitter */
1101 sgroup->splitter = g_object_new (GST_TYPE_STREAM_SPLITTER, NULL);
1103 gst_bin_add (GST_BIN (ebin), sgroup->splitter);
1104 tosync = g_list_append (tosync, sgroup->splitter);
1107 * FIXME : figure out what max-size to use for the input queue */
1108 sgroup->inqueue = gst_element_factory_make ("queue", NULL);
1109 g_object_set (sgroup->inqueue, "max-size-buffers",
1110 (guint32) ebin->queue_buffers_max, "max-size-bytes",
1111 (guint32) ebin->queue_bytes_max, "max-size-time",
1112 (guint64) ebin->queue_time_max, NULL);
1114 gst_bin_add (GST_BIN (ebin), sgroup->inqueue);
1115 tosync = g_list_append (tosync, sgroup->inqueue);
1116 if (G_UNLIKELY (!fast_element_link (sgroup->inqueue, sgroup->splitter)))
1117 goto splitter_link_failure;
1119 /* Expose input queue sink pad as ghostpad */
1120 sinkpad = gst_element_get_static_pad (sgroup->inqueue, "sink");
1121 if (sinkpadname == NULL) {
1123 g_strdup_printf ("%s_%d", gst_encoding_profile_get_type_nick (sprof),
1124 ebin->last_pad_id++);
1125 GST_DEBUG ("Adding ghost pad %s", pname);
1126 sgroup->ghostpad = gst_ghost_pad_new (pname, sinkpad);
1129 sgroup->ghostpad = gst_ghost_pad_new (sinkpadname, sinkpad);
1130 gst_object_unref (sinkpad);
1133 /* Path 1 : Already-encoded data */
1135 local_element_request_pad (sgroup->combiner, NULL, "passthroughsink",
1137 if (G_UNLIKELY (sinkpad == NULL))
1138 goto no_combiner_sinkpad;
1140 if (ebin->avoid_reencoding) {
1143 GST_DEBUG ("Asked to use Smart Encoder");
1144 sgroup->smartencoder = g_object_new (GST_TYPE_SMART_ENCODER, NULL);
1146 /* Check if stream format is compatible */
1147 srcpad = gst_element_get_static_pad (sgroup->smartencoder, "src");
1148 tmpcaps = gst_pad_get_caps (srcpad, NULL);
1149 if (!gst_caps_can_intersect (tmpcaps, format)) {
1150 GST_DEBUG ("We don't have a smart encoder for the stream format");
1151 gst_object_unref (sgroup->smartencoder);
1152 sgroup->smartencoder = NULL;
1154 gst_bin_add ((GstBin *) ebin, sgroup->smartencoder);
1155 fast_pad_link (srcpad, sinkpad);
1156 tosync = g_list_append (tosync, sgroup->smartencoder);
1157 sinkpad = gst_element_get_static_pad (sgroup->smartencoder, "sink");
1159 gst_caps_unref (tmpcaps);
1160 g_object_unref (srcpad);
1164 local_element_request_pad (sgroup->splitter, NULL, "passthroughsrc",
1166 if (G_UNLIKELY (srcpad == NULL))
1167 goto no_splitter_srcpad;
1169 /* Go straight to splitter */
1170 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1171 goto passthrough_link_failure;
1172 g_object_unref (sinkpad);
1173 g_object_unref (srcpad);
1176 /* Path 2 : Conversion / Encoding */
1178 /* 1. Create the encoder */
1179 GST_LOG ("Adding encoder");
1180 last = sgroup->encoder;
1181 gst_bin_add ((GstBin *) ebin, sgroup->encoder);
1182 tosync = g_list_append (tosync, sgroup->encoder);
1185 local_element_request_pad (sgroup->combiner, NULL, "encodingsink", NULL);
1186 if (G_UNLIKELY (sinkpad == NULL))
1187 goto no_combiner_sinkpad;
1188 srcpad = gst_element_get_static_pad (sgroup->encoder, "src");
1189 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1190 goto encoder_link_failure;
1191 g_object_unref (sinkpad);
1192 g_object_unref (srcpad);
1195 /* 3. Create the conversion/restriction elements */
1196 /* 3.1. capsfilter */
1197 if (restriction && !gst_caps_is_any (restriction)) {
1198 GST_LOG ("Adding capsfilter for restriction caps : %" GST_PTR_FORMAT,
1201 last = sgroup->capsfilter = gst_element_factory_make ("capsfilter", NULL);
1202 g_object_set (sgroup->capsfilter, "caps", restriction, NULL);
1203 gst_bin_add ((GstBin *) ebin, sgroup->capsfilter);
1204 tosync = g_list_append (tosync, sgroup->capsfilter);
1205 fast_element_link (sgroup->capsfilter, sgroup->encoder);
1208 /* 3.2. restriction elements */
1209 /* FIXME : Once we have properties for specific converters, use those */
1210 if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) {
1211 GstElement *cspace, *scale, *vrate, *cspace2;
1213 GST_LOG ("Adding conversion elements for video stream");
1215 cspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
1216 scale = gst_element_factory_make ("videoscale", NULL);
1218 missing_element_name = "videoscale";
1219 goto missing_element;
1221 /* 4-tap scaling and black borders */
1222 g_object_set (scale, "method", 2, "add-borders", TRUE, NULL);
1223 cspace2 = gst_element_factory_make ("ffmpegcolorspace", NULL);
1225 if (!cspace || !cspace2) {
1226 missing_element_name = "ffmpegcolorspace";
1227 goto missing_element;
1230 gst_bin_add_many ((GstBin *) ebin, cspace, scale, cspace2, NULL);
1231 tosync = g_list_append (tosync, cspace);
1232 tosync = g_list_append (tosync, scale);
1233 tosync = g_list_append (tosync, cspace2);
1235 sgroup->converters = g_list_prepend (sgroup->converters, cspace);
1236 sgroup->converters = g_list_prepend (sgroup->converters, scale);
1237 sgroup->converters = g_list_prepend (sgroup->converters, cspace2);
1239 if (!fast_element_link (cspace, scale) ||
1240 !fast_element_link (scale, cspace2))
1241 goto converter_link_failure;
1243 if (!gst_encoding_video_profile_get_variableframerate
1244 (GST_ENCODING_VIDEO_PROFILE (sprof))) {
1245 vrate = gst_element_factory_make ("videorate", NULL);
1247 missing_element_name = "videorate";
1248 goto missing_element;
1251 gst_bin_add ((GstBin *) ebin, vrate);
1252 tosync = g_list_prepend (tosync, vrate);
1253 sgroup->converters = g_list_prepend (sgroup->converters, vrate);
1254 if (!fast_element_link (cspace2, vrate) ||
1255 !fast_element_link (vrate, last))
1256 goto converter_link_failure;
1257 } else if (!fast_element_link (cspace2, last))
1258 goto converter_link_failure;
1262 } else if (GST_IS_ENCODING_AUDIO_PROFILE (sprof)) {
1263 GstElement *aconv, *ares, *arate, *aconv2;
1265 GST_LOG ("Adding conversion elements for audio stream");
1267 arate = gst_element_factory_make ("audiorate", NULL);
1268 g_object_set (arate, "tolerance", (guint64) ebin->tolerance, NULL);
1270 missing_element_name = "audiorate";
1271 goto missing_element;
1273 aconv = gst_element_factory_make ("audioconvert", NULL);
1274 aconv2 = gst_element_factory_make ("audioconvert", NULL);
1275 ares = gst_element_factory_make ("audioresample", NULL);
1276 if (!aconv || !aconv2) {
1277 missing_element_name = "audioconvert";
1278 goto missing_element;
1281 missing_element_name = "audioresample";
1282 goto missing_element;
1285 gst_bin_add_many ((GstBin *) ebin, arate, aconv, ares, aconv2, NULL);
1286 tosync = g_list_append (tosync, arate);
1287 tosync = g_list_append (tosync, aconv);
1288 tosync = g_list_append (tosync, ares);
1289 tosync = g_list_append (tosync, aconv2);
1290 if (!fast_element_link (arate, aconv) ||
1291 !fast_element_link (aconv, ares) ||
1292 !fast_element_link (ares, aconv2) || !fast_element_link (aconv2, last))
1293 goto converter_link_failure;
1295 sgroup->converters = g_list_prepend (sgroup->converters, arate);
1296 sgroup->converters = g_list_prepend (sgroup->converters, aconv);
1297 sgroup->converters = g_list_prepend (sgroup->converters, ares);
1298 sgroup->converters = g_list_prepend (sgroup->converters, aconv2);
1303 /* Link to stream splitter */
1304 sinkpad = gst_element_get_static_pad (last, "sink");
1306 local_element_request_pad (sgroup->splitter, NULL, "encodingsrc", NULL);
1307 if (G_UNLIKELY (srcpad == NULL))
1308 goto no_splitter_srcpad;
1309 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1310 goto splitter_encoding_failure;
1311 g_object_unref (sinkpad);
1312 g_object_unref (srcpad);
1314 /* End of Stream 2 setup */
1316 /* Sync all elements to parent state */
1317 for (tmp = tosync; tmp; tmp = tmp->next)
1318 gst_element_sync_state_with_parent ((GstElement *) tmp->data);
1319 g_list_free (tosync);
1322 GST_DEBUG ("Adding ghostpad %s:%s", GST_DEBUG_PAD_NAME (sgroup->ghostpad));
1323 gst_pad_set_active (sgroup->ghostpad, TRUE);
1324 gst_element_add_pad ((GstElement *) ebin, sgroup->ghostpad);
1326 /* Add StreamGroup to our list of streams */
1329 ("Done creating elements, adding StreamGroup to our controlled stream list");
1331 ebin->streams = g_list_prepend (ebin->streams, sgroup);
1334 gst_caps_unref (format);
1336 gst_caps_unref (restriction);
1340 splitter_encoding_failure:
1341 GST_ERROR_OBJECT (ebin, "Error linking splitter to encoding stream");
1345 GST_ERROR_OBJECT (ebin, "Couldn't create encoder for format %" GST_PTR_FORMAT,
1347 /* missing plugin support */
1348 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1349 gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin), format));
1350 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL),
1351 ("Couldn't create encoder for format %" GST_PTR_FORMAT, format));
1355 GST_ERROR_OBJECT (ebin,
1356 "Couldn't find a compatible muxer pad to link encoder to");
1360 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1361 gst_missing_element_message_new (GST_ELEMENT_CAST (ebin),
1362 missing_element_name));
1363 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN,
1364 (_("Missing element '%s' - check your GStreamer installation."),
1365 missing_element_name), (NULL));
1368 encoder_link_failure:
1369 GST_ERROR_OBJECT (ebin, "Failed to link the encoder");
1373 GST_ERROR_OBJECT (ebin, "Couldn't link encoder to muxer");
1376 formatter_link_failure:
1377 GST_ERROR_OBJECT (ebin, "Couldn't link output filter to output queue");
1380 outfilter_link_failure:
1381 GST_ERROR_OBJECT (ebin,
1382 "Couldn't link output filter to output queue/formatter");
1385 passthrough_link_failure:
1386 GST_ERROR_OBJECT (ebin, "Failed linking splitter in passthrough mode");
1390 GST_ERROR_OBJECT (ebin, "Couldn't get a source pad from the splitter");
1393 no_combiner_sinkpad:
1394 GST_ERROR_OBJECT (ebin, "Couldn't get a sink pad from the combiner");
1397 splitter_link_failure:
1398 GST_ERROR_OBJECT (ebin, "Failure linking to the splitter");
1401 combiner_link_failure:
1402 GST_ERROR_OBJECT (ebin, "Failure linking to the combiner");
1406 parser_link_failure:
1407 GST_ERROR_OBJECT (ebin, "Failure linking the parser");
1411 converter_link_failure:
1412 GST_ERROR_OBJECT (ebin, "Failure linking the video converters");
1416 /* FIXME : Actually properly cleanup everything */
1418 gst_caps_unref (format);
1420 gst_caps_unref (restriction);
1421 g_slice_free (StreamGroup, sgroup);
1426 _factory_can_sink_caps (GstElementFactory * factory, const GstCaps * caps)
1428 GList *templates = factory->staticpadtemplates;
1431 GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
1433 if (template->direction == GST_PAD_SINK) {
1434 GstCaps *tmp = gst_static_caps_get (&template->static_caps);
1436 if (gst_caps_can_intersect (tmp, caps)) {
1437 gst_caps_unref (tmp);
1440 gst_caps_unref (tmp);
1442 templates = g_list_next (templates);
1448 static inline GstElement *
1449 _get_formatter (GstEncodeBin * ebin, GstEncodingProfile * sprof)
1451 GList *formatters, *tmpfmtr;
1452 GstElement *formatter = NULL;
1453 GstElementFactory *formatterfact = NULL;
1454 const GstCaps *format;
1455 const gchar *preset;
1457 format = gst_encoding_profile_get_format (sprof);
1458 preset = gst_encoding_profile_get_preset (sprof);
1460 GST_DEBUG ("Getting list of formatters for format %" GST_PTR_FORMAT, format);
1463 gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
1466 if (formatters == NULL)
1469 /* FIXME : signal the user if he wants this */
1470 for (tmpfmtr = formatters; tmpfmtr; tmpfmtr = tmpfmtr->next) {
1471 formatterfact = (GstElementFactory *) tmpfmtr->data;
1473 GST_DEBUG_OBJECT (ebin, "Trying formatter %s",
1474 GST_OBJECT_NAME (formatterfact));
1477 _create_element_and_set_preset (formatterfact, preset, NULL)))
1481 gst_plugin_feature_list_free (formatters);
1487 static inline GstElement *
1488 _get_muxer (GstEncodeBin * ebin)
1490 GList *muxers, *formatters, *tmpmux;
1491 GstElement *muxer = NULL;
1492 GstElementFactory *muxerfact = NULL;
1494 const GstCaps *format;
1495 const gchar *preset;
1497 format = gst_encoding_profile_get_format (ebin->profile);
1498 preset = gst_encoding_profile_get_preset (ebin->profile);
1500 GST_DEBUG ("Getting list of muxers for format %" GST_PTR_FORMAT, format);
1503 gst_element_factory_list_filter (ebin->muxers, format, GST_PAD_SRC, TRUE);
1506 gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
1509 muxers = g_list_concat (muxers, formatters);
1514 /* FIXME : signal the user if he wants this */
1515 for (tmpmux = muxers; tmpmux; tmpmux = tmpmux->next) {
1516 gboolean cansinkstreams = TRUE;
1517 const GList *profiles =
1518 gst_encoding_container_profile_get_profiles
1519 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
1521 muxerfact = (GstElementFactory *) tmpmux->data;
1523 GST_DEBUG ("Trying muxer %s", GST_OBJECT_NAME (muxerfact));
1525 /* See if the muxer can sink all of our stream profile caps */
1526 for (tmp = profiles; tmp; tmp = tmp->next) {
1527 GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
1529 if (!_factory_can_sink_caps (muxerfact,
1530 gst_encoding_profile_get_format (sprof))) {
1531 GST_DEBUG ("Skipping muxer because it can't sink caps %" GST_PTR_FORMAT,
1532 gst_encoding_profile_get_format (sprof));
1533 cansinkstreams = FALSE;
1538 /* Only use a muxer than can use all streams and than can accept the
1539 * preset (which may be present or not) */
1540 if (cansinkstreams && (muxer =
1541 _create_element_and_set_preset (muxerfact, preset, "muxer")))
1545 gst_plugin_feature_list_free (muxers);
1552 create_elements_and_pads (GstEncodeBin * ebin)
1554 gboolean ret = TRUE;
1555 GstElement *muxer = NULL;
1557 const GList *tmp, *profiles;
1558 GstEncodingProfile *sprof;
1560 GST_DEBUG ("Current profile : %s",
1561 gst_encoding_profile_get_name (ebin->profile));
1563 if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
1564 /* 1. Get the compatible muxer */
1565 muxer = _get_muxer (ebin);
1566 if (G_UNLIKELY (muxer == NULL))
1569 /* Record the muxer */
1570 ebin->muxer = muxer;
1571 gst_bin_add ((GstBin *) ebin, muxer);
1573 /* 2. Ghost the muxer source pad */
1575 /* FIXME : We should figure out if it's a static/request/dyamic pad,
1576 * but for the time being let's assume it's a static pad :) */
1577 muxerpad = gst_element_get_static_pad (muxer, "src");
1578 if (G_UNLIKELY (muxerpad == NULL))
1581 if (!gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), muxerpad))
1582 goto no_muxer_ghost_pad;
1584 gst_object_unref (muxerpad);
1585 /* 3. Activate fixed presence streams */
1587 gst_encoding_container_profile_get_profiles
1588 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
1589 for (tmp = profiles; tmp; tmp = tmp->next) {
1590 sprof = (GstEncodingProfile *) tmp->data;
1592 GST_DEBUG ("Trying stream profile with presence %d",
1593 gst_encoding_profile_get_presence (sprof));
1595 if (gst_encoding_profile_get_presence (sprof) != 0) {
1596 if (G_UNLIKELY (_create_stream_group (ebin, sprof, NULL, NULL) == NULL))
1601 if (G_UNLIKELY (_create_stream_group (ebin, ebin->profile, NULL,
1610 GST_WARNING ("No available muxer for %" GST_PTR_FORMAT,
1611 gst_encoding_profile_get_format (ebin->profile));
1612 /* missing plugin support */
1613 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1614 gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin),
1615 gst_encoding_profile_get_format (ebin->profile)));
1616 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL),
1617 ("No available muxer for format %" GST_PTR_FORMAT,
1618 gst_encoding_profile_get_format (ebin->profile)));
1624 GST_WARNING ("Can't get source pad from muxer (%s)",
1625 GST_ELEMENT_NAME (muxer));
1626 gst_bin_remove (GST_BIN (ebin), muxer);
1632 GST_WARNING ("Couldn't set %s:%s as source ghostpad target",
1633 GST_DEBUG_PAD_NAME (muxerpad));
1634 gst_bin_remove (GST_BIN (ebin), muxer);
1635 gst_object_unref (muxerpad);
1641 GST_WARNING ("Could not create Streams");
1643 gst_bin_remove (GST_BIN (ebin), muxer);
1650 release_pads (const GValue * item, GstElement * elt)
1652 GstPad *pad = g_value_get_object (item);
1653 GstPad *peer = NULL;
1655 GST_DEBUG_OBJECT (elt, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1657 /* Unlink from its peer pad */
1658 if ((peer = gst_pad_get_peer (pad))) {
1659 if (GST_PAD_DIRECTION (peer) == GST_PAD_SRC)
1660 gst_pad_unlink (peer, pad);
1662 gst_pad_unlink (pad, peer);
1663 gst_object_unref (peer);
1666 /* Release it from the object */
1667 gst_element_release_request_pad (elt, pad);
1671 stream_group_free (GstEncodeBin * ebin, StreamGroup * sgroup)
1677 GST_DEBUG_OBJECT (ebin, "Freeing StreamGroup %p", sgroup);
1680 /* outqueue - Muxer */
1681 tmppad = gst_element_get_static_pad (sgroup->outqueue, "src");
1682 pad = gst_pad_get_peer (tmppad);
1684 /* Remove muxer request sink pad */
1685 gst_pad_unlink (tmppad, pad);
1686 gst_element_release_request_pad (ebin->muxer, pad);
1687 gst_object_unref (tmppad);
1688 gst_object_unref (pad);
1690 if (sgroup->outqueue)
1691 gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
1693 if (sgroup->formatter) {
1694 /* capsfilter - formatter - outqueue */
1695 gst_element_set_state (sgroup->formatter, GST_STATE_NULL);
1696 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1697 gst_element_unlink (sgroup->formatter, sgroup->outqueue);
1698 gst_element_unlink (sgroup->outfilter, sgroup->formatter);
1700 /* Capsfilter - outqueue */
1701 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1702 gst_element_unlink (sgroup->outfilter, sgroup->outqueue);
1704 gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
1705 gst_bin_remove (GST_BIN (ebin), sgroup->outqueue);
1707 /* streamcombiner - parser - capsfilter */
1708 if (sgroup->parser) {
1709 gst_element_set_state (sgroup->parser, GST_STATE_NULL);
1710 gst_element_unlink (sgroup->parser, sgroup->outfilter);
1711 gst_element_unlink (sgroup->combiner, sgroup->parser);
1712 gst_bin_remove ((GstBin *) ebin, sgroup->parser);
1716 if (sgroup->ghostpad)
1717 gst_element_remove_pad (GST_ELEMENT_CAST (ebin), sgroup->ghostpad);
1719 if (sgroup->inqueue)
1720 gst_element_set_state (sgroup->inqueue, GST_STATE_NULL);
1722 if (sgroup->encoder)
1723 gst_element_set_state (sgroup->encoder, GST_STATE_NULL);
1724 if (sgroup->outfilter)
1725 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1726 if (sgroup->smartencoder)
1727 gst_element_set_state (sgroup->smartencoder, GST_STATE_NULL);
1729 if (sgroup->capsfilter) {
1730 gst_element_set_state (sgroup->capsfilter, GST_STATE_NULL);
1731 gst_element_unlink (sgroup->capsfilter, sgroup->encoder);
1732 gst_bin_remove ((GstBin *) ebin, sgroup->capsfilter);
1735 for (tmp = sgroup->converters; tmp; tmp = tmp->next) {
1736 GstElement *elt = (GstElement *) tmp->data;
1738 gst_element_set_state (elt, GST_STATE_NULL);
1739 gst_bin_remove ((GstBin *) ebin, elt);
1741 if (sgroup->converters)
1742 g_list_free (sgroup->converters);
1744 if (sgroup->combiner) {
1745 GstIterator *it = gst_element_iterate_sink_pads (sgroup->combiner);
1746 GstIteratorResult itret = GST_ITERATOR_OK;
1748 while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
1750 gst_iterator_foreach (it, (GstIteratorForeachFunction) release_pads,
1752 gst_iterator_resync (it);
1754 gst_iterator_free (it);
1755 gst_element_set_state (sgroup->combiner, GST_STATE_NULL);
1756 gst_bin_remove ((GstBin *) ebin, sgroup->combiner);
1759 if (sgroup->splitter) {
1760 GstIterator *it = gst_element_iterate_src_pads (sgroup->splitter);
1761 GstIteratorResult itret = GST_ITERATOR_OK;
1762 while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
1764 gst_iterator_foreach (it, (GstIteratorForeachFunction) release_pads,
1766 gst_iterator_resync (it);
1768 gst_iterator_free (it);
1770 gst_element_set_state (sgroup->splitter, GST_STATE_NULL);
1771 gst_bin_remove ((GstBin *) ebin, sgroup->splitter);
1774 if (sgroup->inqueue)
1775 gst_bin_remove ((GstBin *) ebin, sgroup->inqueue);
1777 if (sgroup->encoder)
1778 gst_bin_remove ((GstBin *) ebin, sgroup->encoder);
1780 if (sgroup->smartencoder)
1781 gst_bin_remove ((GstBin *) ebin, sgroup->smartencoder);
1783 if (sgroup->outfilter)
1784 gst_bin_remove ((GstBin *) ebin, sgroup->outfilter);
1786 g_slice_free (StreamGroup, sgroup);
1790 stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup)
1792 ebin->streams = g_list_remove (ebin->streams, sgroup);
1794 stream_group_free (ebin, sgroup);
1798 gst_encode_bin_tear_down_profile (GstEncodeBin * ebin)
1800 if (G_UNLIKELY (ebin->profile == NULL))
1803 GST_DEBUG ("Tearing down profile %s",
1804 gst_encoding_profile_get_name (ebin->profile));
1806 while (ebin->streams)
1807 stream_group_remove (ebin, (StreamGroup *) ebin->streams->data);
1809 /* Set ghostpad target to NULL */
1810 gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), NULL);
1812 /* Remove muxer if present */
1814 gst_element_set_state (ebin->muxer, GST_STATE_NULL);
1815 gst_bin_remove (GST_BIN (ebin), ebin->muxer);
1819 /* free/clear profile */
1820 gst_encoding_profile_unref (ebin->profile);
1821 ebin->profile = NULL;
1825 gst_encode_bin_setup_profile (GstEncodeBin * ebin, GstEncodingProfile * profile)
1829 g_return_val_if_fail (ebin->profile == NULL, FALSE);
1831 GST_DEBUG ("Setting up profile %s (type:%s)",
1832 gst_encoding_profile_get_name (profile),
1833 gst_encoding_profile_get_type_nick (profile));
1835 ebin->profile = profile;
1836 gst_mini_object_ref ((GstMiniObject *) ebin->profile);
1838 /* Create elements */
1839 res = create_elements_and_pads (ebin);
1841 gst_encode_bin_tear_down_profile (ebin);
1847 gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile)
1849 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
1851 GST_DEBUG_OBJECT (ebin, "profile : %s",
1852 gst_encoding_profile_get_name (profile));
1854 if (G_UNLIKELY (ebin->active)) {
1855 GST_WARNING_OBJECT (ebin, "Element already active, can't change profile");
1859 /* If we're not active, we can deactivate the previous profile */
1860 if (ebin->profile) {
1861 gst_encode_bin_tear_down_profile (ebin);
1864 return gst_encode_bin_setup_profile (ebin, profile);
1867 static inline gboolean
1868 gst_encode_bin_activate (GstEncodeBin * ebin)
1870 ebin->active = ebin->profile != NULL;
1871 return ebin->active;
1875 gst_encode_bin_deactivate (GstEncodeBin * ebin)
1877 ebin->active = FALSE;
1880 static GstStateChangeReturn
1881 gst_encode_bin_change_state (GstElement * element, GstStateChange transition)
1883 GstStateChangeReturn ret;
1884 GstEncodeBin *ebin = (GstEncodeBin *) element;
1886 switch (transition) {
1887 case GST_STATE_CHANGE_READY_TO_PAUSED:
1888 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1889 if (!gst_encode_bin_activate (ebin)) {
1890 ret = GST_STATE_CHANGE_FAILURE;
1899 GST_ELEMENT_CLASS (gst_encode_bin_parent_class)->change_state (element,
1901 if (ret == GST_STATE_CHANGE_FAILURE)
1904 switch (transition) {
1905 case GST_STATE_CHANGE_PAUSED_TO_READY:
1906 gst_encode_bin_deactivate (ebin);
1918 plugin_init (GstPlugin * plugin)
1922 GST_DEBUG_CATEGORY_INIT (gst_encode_bin_debug, "encodebin", 0, "encoder bin");
1925 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
1927 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1928 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1929 #endif /* ENABLE_NLS */
1932 res = gst_element_register (plugin, "encodebin", GST_RANK_NONE,
1933 GST_TYPE_ENCODE_BIN);
1938 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1941 "various encoding-related elements", plugin_init, VERSION, GST_LICENSE,
1942 GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)