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 \
221 "video/x-raw-yuv; " \
222 "video/x-raw-rgb; " \
223 "video/x-raw-gray; " \
224 "audio/x-raw-int; " \
225 "audio/x-raw-float; " \
227 "text/x-pango-markup; " \
228 "video/x-dvd-subpicture; " \
236 PROP_QUEUE_BUFFERS_MAX,
237 PROP_QUEUE_BYTES_MAX,
239 PROP_AUDIO_JITTER_TOLERANCE,
240 PROP_AVOID_REENCODING,
251 static guint gst_encode_bin_signals[LAST_SIGNAL] = { 0 };
253 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
255 GST_DEBUG_CATEGORY_STATIC (gst_encode_bin_debug);
256 #define GST_CAT_DEFAULT gst_encode_bin_debug
258 G_DEFINE_TYPE (GstEncodeBin, gst_encode_bin, GST_TYPE_BIN);
260 static void gst_encode_bin_dispose (GObject * object);
261 static void gst_encode_bin_set_property (GObject * object, guint prop_id,
262 const GValue * value, GParamSpec * pspec);
263 static void gst_encode_bin_get_property (GObject * object, guint prop_id,
264 GValue * value, GParamSpec * pspec);
265 static GstStateChangeReturn gst_encode_bin_change_state (GstElement * element,
266 GstStateChange transition);
268 static GstPad *gst_encode_bin_request_new_pad (GstElement * element,
269 GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
270 static void gst_encode_bin_release_pad (GstElement * element, GstPad * pad);
273 gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile);
274 static void gst_encode_bin_tear_down_profile (GstEncodeBin * ebin);
275 static gboolean gst_encode_bin_setup_profile (GstEncodeBin * ebin,
276 GstEncodingProfile * profile);
278 static StreamGroup *_create_stream_group (GstEncodeBin * ebin,
279 GstEncodingProfile * sprof, const gchar * sinkpadname, GstCaps * sinkcaps);
280 static void stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup);
281 static GstPad *gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin,
284 static inline GstElement *_get_formatter (GstEncodeBin * ebin,
285 GstEncodingProfile * sprof);
288 gst_encode_bin_class_init (GstEncodeBinClass * klass)
290 GObjectClass *gobject_klass;
291 GstElementClass *gstelement_klass;
293 gobject_klass = (GObjectClass *) klass;
294 gstelement_klass = (GstElementClass *) klass;
296 gobject_klass->dispose = gst_encode_bin_dispose;
297 gobject_klass->set_property = gst_encode_bin_set_property;
298 gobject_klass->get_property = gst_encode_bin_get_property;
303 * GstEncodeBin:profile:
305 * The #GstEncodingProfile to use. This property must be set before going
306 * to %GST_STATE_PAUSED or higher.
308 g_object_class_install_property (gobject_klass, PROP_PROFILE,
309 g_param_spec_object ("profile", "Profile",
310 "The GstEncodingProfile to use", GST_TYPE_ENCODING_PROFILE,
311 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
313 g_object_class_install_property (gobject_klass, PROP_QUEUE_BUFFERS_MAX,
314 g_param_spec_uint ("queue-bytes-max", "Max. size (kB)",
315 "Max. amount of data in the queue (bytes, 0=disable)",
316 0, G_MAXUINT, DEFAULT_QUEUE_BYTES_MAX,
317 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
319 g_object_class_install_property (gobject_klass, PROP_QUEUE_BYTES_MAX,
320 g_param_spec_uint ("queue-buffers-max", "Max. size (buffers)",
321 "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
322 DEFAULT_QUEUE_BUFFERS_MAX,
323 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
325 g_object_class_install_property (gobject_klass, PROP_QUEUE_TIME_MAX,
326 g_param_spec_uint64 ("queue-time-max", "Max. size (ns)",
327 "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
328 DEFAULT_QUEUE_TIME_MAX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
330 g_object_class_install_property (gobject_klass, PROP_AUDIO_JITTER_TOLERANCE,
331 g_param_spec_uint64 ("audio-jitter-tolerance", "Audio jitter tolerance",
332 "Amount of timestamp jitter/imperfection to allow on audio streams before inserting/dropping samples (ns)",
333 0, G_MAXUINT64, DEFAULT_AUDIO_JITTER_TOLERANCE,
334 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
336 g_object_class_install_property (gobject_klass, PROP_AVOID_REENCODING,
337 g_param_spec_boolean ("avoid-reencoding", "Avoid re-encoding",
338 "Whether to re-encode portions of compatible video streams that lay on segment boundaries",
339 DEFAULT_AVOID_REENCODING,
340 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
344 * GstEncodeBin::request-pad
345 * @encodebin: a #GstEncodeBin instance
348 * Use this method to request an unused sink request #GstPad that can take the
349 * provided @caps as input. You must release the pad with
350 * gst_element_release_request_pad() when you are done with it.
352 * Returns: A compatible #GstPad, or %NULL if no compatible #GstPad could be
353 * created or is available.
355 gst_encode_bin_signals[SIGNAL_REQUEST_PAD] =
356 g_signal_new ("request-pad", G_TYPE_FROM_CLASS (klass),
357 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstEncodeBinClass,
358 request_pad), NULL, NULL, gst_encode_marshal_OBJECT__BOXED,
359 GST_TYPE_PAD, 1, GST_TYPE_CAPS);
361 klass->request_pad = gst_encode_bin_request_pad_signal;
363 gst_element_class_add_pad_template (gstelement_klass,
364 gst_static_pad_template_get (&muxer_src_template));
365 gst_element_class_add_pad_template (gstelement_klass,
366 gst_static_pad_template_get (&video_sink_template));
367 gst_element_class_add_pad_template (gstelement_klass,
368 gst_static_pad_template_get (&audio_sink_template));
369 /* gst_element_class_add_pad_template (gstelement_klass, */
370 /* gst_static_pad_template_get (&text_sink_template)); */
371 gst_element_class_add_pad_template (gstelement_klass,
372 gst_static_pad_template_get (&private_sink_template));
374 gstelement_klass->change_state =
375 GST_DEBUG_FUNCPTR (gst_encode_bin_change_state);
376 gstelement_klass->request_new_pad =
377 GST_DEBUG_FUNCPTR (gst_encode_bin_request_new_pad);
378 gstelement_klass->release_pad =
379 GST_DEBUG_FUNCPTR (gst_encode_bin_release_pad);
381 gst_element_class_set_details_simple (gstelement_klass,
383 "Generic/Bin/Encoder",
384 "Convenience encoding/muxing element",
385 "Edward Hervey <edward.hervey@collabora.co.uk>");
389 gst_encode_bin_dispose (GObject * object)
391 GstEncodeBin *ebin = (GstEncodeBin *) object;
394 gst_plugin_feature_list_free (ebin->muxers);
396 if (ebin->formatters)
397 gst_plugin_feature_list_free (ebin->formatters);
400 gst_plugin_feature_list_free (ebin->encoders);
403 gst_plugin_feature_list_free (ebin->parsers);
405 gst_encode_bin_tear_down_profile (ebin);
407 if (ebin->raw_video_caps)
408 gst_caps_unref (ebin->raw_video_caps);
409 if (ebin->raw_audio_caps)
410 gst_caps_unref (ebin->raw_audio_caps);
411 /* if (ebin->raw_text_caps) */
412 /* gst_caps_unref (ebin->raw_text_caps); */
414 G_OBJECT_CLASS (gst_encode_bin_parent_class)->dispose (object);
418 gst_encode_bin_init (GstEncodeBin * encode_bin)
420 GstPadTemplate *tmpl;
423 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
426 encode_bin->formatters =
427 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_FORMATTER,
430 encode_bin->encoders =
431 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
434 encode_bin->parsers =
435 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_PARSER,
438 encode_bin->raw_video_caps =
439 gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray");
440 encode_bin->raw_audio_caps =
441 gst_caps_from_string ("audio/x-raw-int;audio/x-raw-float");
442 /* encode_bin->raw_text_caps = */
443 /* gst_caps_from_string ("text/plain;text/x-pango-markup"); */
445 encode_bin->queue_buffers_max = DEFAULT_QUEUE_BUFFERS_MAX;
446 encode_bin->queue_bytes_max = DEFAULT_QUEUE_BYTES_MAX;
447 encode_bin->queue_time_max = DEFAULT_QUEUE_TIME_MAX;
448 encode_bin->tolerance = DEFAULT_AUDIO_JITTER_TOLERANCE;
449 encode_bin->avoid_reencoding = DEFAULT_AVOID_REENCODING;
451 tmpl = gst_static_pad_template_get (&muxer_src_template);
452 encode_bin->srcpad = gst_ghost_pad_new_no_target_from_template ("src", tmpl);
453 gst_object_unref (tmpl);
454 gst_element_add_pad (GST_ELEMENT_CAST (encode_bin), encode_bin->srcpad);
458 gst_encode_bin_set_property (GObject * object, guint prop_id,
459 const GValue * value, GParamSpec * pspec)
461 GstEncodeBin *ebin = (GstEncodeBin *) object;
465 gst_encode_bin_set_profile (ebin,
466 (GstEncodingProfile *) g_value_get_object (value));
468 case PROP_QUEUE_BUFFERS_MAX:
469 ebin->queue_buffers_max = g_value_get_uint (value);
471 case PROP_QUEUE_BYTES_MAX:
472 ebin->queue_bytes_max = g_value_get_uint (value);
474 case PROP_QUEUE_TIME_MAX:
475 ebin->queue_time_max = g_value_get_uint64 (value);
477 case PROP_AUDIO_JITTER_TOLERANCE:
478 ebin->tolerance = g_value_get_uint64 (value);
480 case PROP_AVOID_REENCODING:
481 ebin->avoid_reencoding = g_value_get_boolean (value);
484 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
490 gst_encode_bin_get_property (GObject * object, guint prop_id,
491 GValue * value, GParamSpec * pspec)
493 GstEncodeBin *ebin = (GstEncodeBin *) object;
497 g_value_set_object (value, (GObject *) ebin->profile);
499 case PROP_QUEUE_BUFFERS_MAX:
500 g_value_set_uint (value, ebin->queue_buffers_max);
502 case PROP_QUEUE_BYTES_MAX:
503 g_value_set_uint (value, ebin->queue_bytes_max);
505 case PROP_QUEUE_TIME_MAX:
506 g_value_set_uint64 (value, ebin->queue_time_max);
508 case PROP_AUDIO_JITTER_TOLERANCE:
509 g_value_set_uint64 (value, ebin->tolerance);
511 case PROP_AVOID_REENCODING:
512 g_value_set_boolean (value, ebin->avoid_reencoding);
515 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
520 static inline gboolean
521 are_raw_caps (const GstCaps * caps)
523 GstCaps *raw = gst_static_caps_get (&default_raw_caps);
525 if (gst_caps_can_intersect (caps, raw)) {
526 gst_caps_unref (raw);
529 gst_caps_unref (raw);
533 /* Returns the number of time a given stream profile is currently used
536 stream_profile_used_count (GstEncodeBin * ebin, GstEncodingProfile * sprof)
538 guint nbprofused = 0;
541 for (tmp = ebin->streams; tmp; tmp = tmp->next) {
542 StreamGroup *sgroup = (StreamGroup *) tmp->data;
544 if (sgroup->profile == sprof)
551 static inline GstEncodingProfile *
552 next_unused_stream_profile (GstEncodeBin * ebin, GType ptype, GstCaps * caps)
554 GST_DEBUG_OBJECT (ebin, "ptype:%s, caps:%" GST_PTR_FORMAT,
555 g_type_name (ptype), caps);
557 if (G_UNLIKELY (ptype == G_TYPE_NONE && caps != NULL)) {
558 /* Identify the profile type based on raw caps */
559 if (gst_caps_can_intersect (ebin->raw_video_caps, caps))
560 ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
561 else if (gst_caps_can_intersect (ebin->raw_audio_caps, caps))
562 ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
563 /* else if (gst_caps_can_intersect (ebin->raw_text_caps, caps)) */
564 /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
565 GST_DEBUG_OBJECT (ebin, "Detected profile type as being %s",
566 g_type_name (ptype));
569 if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
573 gst_encoding_container_profile_get_profiles
574 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile)); tmp;
576 GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
578 /* Pick an available Stream profile for which:
579 * * either it is of the compatibly raw type,
580 * * OR we can pass it through directly without encoding
582 if (G_TYPE_FROM_INSTANCE (sprof) == ptype) {
583 guint presence = gst_encoding_profile_get_presence (sprof);
584 GST_DEBUG ("Found a stream profile with the same type");
586 || (presence > stream_profile_used_count (ebin, sprof)))
588 } else if ((caps != NULL) && (ptype == G_TYPE_NONE)) {
592 outcaps = gst_encoding_profile_get_input_caps (sprof);
593 GST_DEBUG ("Unknown stream, seeing if it's compatible with %"
594 GST_PTR_FORMAT, outcaps);
595 res = gst_caps_can_intersect (outcaps, caps);
596 gst_caps_unref (outcaps);
608 request_pad_for_stream (GstEncodeBin * encodebin, GType ptype,
609 const gchar * name, GstCaps * caps)
612 GstEncodingProfile *sprof;
614 GST_DEBUG_OBJECT (encodebin, "name:%s caps:%" GST_PTR_FORMAT, name, caps);
616 /* Figure out if we have a unused GstEncodingProfile we can use for
618 sprof = next_unused_stream_profile (encodebin, ptype, caps);
620 if (G_UNLIKELY (sprof == NULL))
621 goto no_stream_profile;
623 sgroup = _create_stream_group (encodebin, sprof, name, caps);
624 if (G_UNLIKELY (sgroup == NULL))
625 goto no_stream_group;
627 return sgroup->ghostpad;
631 GST_WARNING_OBJECT (encodebin, "Couldn't find a compatible stream profile");
637 GST_WARNING_OBJECT (encodebin, "Couldn't create a StreamGroup");
643 gst_encode_bin_request_new_pad (GstElement * element,
644 GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
646 GstEncodeBin *ebin = (GstEncodeBin *) element;
649 GST_DEBUG_OBJECT (element, "templ:%s, name:%s", templ->name_template, name);
651 /* Identify the stream group */
653 res = request_pad_for_stream (ebin, G_TYPE_NONE, name, (GstCaps *) caps);
657 GType ptype = G_TYPE_NONE;
659 if (!strcmp (templ->name_template, "video_%d"))
660 ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
661 else if (!strcmp (templ->name_template, "audio_%d"))
662 ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
663 /* else if (!strcmp (templ->name_template, "text_%d")) */
664 /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
666 /* FIXME : Check uniqueness of pad */
667 /* FIXME : Check that the requested number is the last one, and if not,
668 * update the last_pad_id variable so that we don't create a pad with
669 * the same name/number in the future */
671 res = request_pad_for_stream (ebin, ptype, name, NULL);
678 gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin, GstCaps * caps)
680 GstPad *pad = request_pad_for_stream (encodebin, G_TYPE_NONE, NULL, caps);
682 return pad ? GST_PAD_CAST (gst_object_ref (pad)) : NULL;
685 static inline StreamGroup *
686 find_stream_group_from_pad (GstEncodeBin * ebin, GstPad * pad)
690 for (tmp = ebin->streams; tmp; tmp = tmp->next) {
691 StreamGroup *sgroup = (StreamGroup *) tmp->data;
692 if (G_UNLIKELY (sgroup->ghostpad == pad))
700 gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
702 GstEncodeBin *ebin = (GstEncodeBin *) element;
705 /* Find the associated StreamGroup */
707 sgroup = find_stream_group_from_pad (ebin, pad);
708 if (G_UNLIKELY (sgroup == NULL))
709 goto no_stream_group;
711 /* Release objects/data associated with the StreamGroup */
712 stream_group_remove (ebin, sgroup);
718 GST_WARNING_OBJECT (ebin, "Couldn't find corresponding StreamGroup");
723 /* Create a parser for the given stream profile */
724 static inline GstElement *
725 _get_parser (GstEncodeBin * ebin, GstEncodingProfile * sprof)
727 GList *parsers1, *parsers, *tmp;
728 GstElement *parser = NULL;
729 GstElementFactory *parserfact = NULL;
730 const GstCaps *format;
732 format = gst_encoding_profile_get_format (sprof);
734 GST_DEBUG ("Getting list of parsers for format %" GST_PTR_FORMAT, format);
736 /* FIXME : requesting twice the parsers twice is a bit ugly, we should
737 * have a method to request on more than one condition */
739 gst_element_factory_list_filter (ebin->parsers, format,
742 gst_element_factory_list_filter (parsers1, format, GST_PAD_SINK, FALSE);
743 gst_plugin_feature_list_free (parsers1);
745 if (G_UNLIKELY (parsers == NULL)) {
746 GST_DEBUG ("Couldn't find any compatible parsers");
750 for (tmp = parsers; tmp; tmp = tmp->next) {
751 /* FIXME : We're only picking the first one so far */
752 /* FIXME : signal the user if he wants this */
753 parserfact = (GstElementFactory *) tmp->data;
758 parser = gst_element_factory_create (parserfact, NULL);
760 gst_plugin_feature_list_free (parsers);
766 _create_element_and_set_preset (GstElementFactory * factory,
767 const gchar * preset, const gchar * name)
769 GstElement *res = NULL;
771 GST_DEBUG ("Creating element from factory %s", GST_OBJECT_NAME (factory));
772 res = gst_element_factory_create (factory, name);
773 if (preset && GST_IS_PRESET (res) &&
774 !gst_preset_load_preset (GST_PRESET (res), preset)) {
775 GST_WARNING ("Couldn't set preset [%s] on element [%s]",
776 preset, GST_OBJECT_NAME (factory));
777 gst_object_unref (res);
784 /* Create the encoder for the given stream profile */
785 static inline GstElement *
786 _get_encoder (GstEncodeBin * ebin, GstEncodingProfile * sprof)
788 GList *encoders, *tmp;
789 GstElement *encoder = NULL;
790 GstElementFactory *encoderfact = NULL;
791 const GstCaps *format;
794 format = gst_encoding_profile_get_format (sprof);
795 preset = gst_encoding_profile_get_preset (sprof);
797 GST_DEBUG ("Getting list of encoders for format %" GST_PTR_FORMAT, format);
799 /* If stream caps are raw, return identity */
800 if (G_UNLIKELY (are_raw_caps (format))) {
801 GST_DEBUG ("Stream format is raw, returning identity as the encoder");
802 encoder = gst_element_factory_make ("identity", NULL);
807 gst_element_factory_list_filter (ebin->encoders, format,
810 if (G_UNLIKELY (encoders == NULL)) {
811 GST_DEBUG ("Couldn't find any compatible encoders");
815 for (tmp = encoders; tmp; tmp = tmp->next) {
816 encoderfact = (GstElementFactory *) tmp->data;
817 if ((encoder = _create_element_and_set_preset (encoderfact, preset, NULL)))
821 gst_plugin_feature_list_free (encoders);
828 local_element_request_pad (GstElement * element, GstPadTemplate * templ,
829 const gchar * name, const GstCaps * caps)
831 GstPad *newpad = NULL;
832 GstElementClass *oclass;
834 oclass = GST_ELEMENT_GET_CLASS (element);
836 if (oclass->request_new_pad)
837 newpad = (oclass->request_new_pad) (element, templ, name, caps);
840 gst_object_ref (newpad);
846 gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
849 GstPadPresence presence;
851 /* If this function is ever exported, we need check the validity of `element'
852 * and `templ', and to make sure the template actually belongs to the
855 presence = GST_PAD_TEMPLATE_PRESENCE (templ);
859 case GST_PAD_SOMETIMES:
860 ret = gst_element_get_static_pad (element, templ->name_template);
861 if (!ret && presence == GST_PAD_ALWAYS)
863 ("Element %s has an ALWAYS template %s, but no pad of the same name",
864 GST_OBJECT_NAME (element), templ->name_template);
867 case GST_PAD_REQUEST:
868 ret = gst_element_request_pad (element, templ, NULL, NULL);
875 /* FIXME : Improve algorithm for finding compatible muxer sink pad */
876 static inline GstPad *
877 get_compatible_muxer_sink_pad (GstEncodeBin * ebin, GstElement * encoder,
881 GstPadTemplate *srctempl = NULL;
882 GstPadTemplate *sinktempl;
886 srcpad = gst_element_get_static_pad (encoder, "src");
888 srctempl = gst_pad_get_pad_template (srcpad);
890 GST_DEBUG_OBJECT (ebin,
891 "Attempting to find pad from muxer %s compatible with %s:%s",
892 GST_ELEMENT_NAME (ebin->muxer), GST_DEBUG_PAD_NAME (srcpad));
894 gst_object_unref (srcpad);
895 sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl);
896 gst_object_unref (srctempl);
899 gst_pad_template_new ("whatever", GST_PAD_SRC, GST_PAD_ALWAYS,
901 g_assert (srctempl != NULL);
902 sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl);
903 g_object_unref (srctempl);
906 if (G_UNLIKELY (sinktempl == NULL))
909 sinkpad = gst_element_get_pad_from_template (ebin->muxer, sinktempl);
915 GST_WARNING_OBJECT (ebin, "No compatible pad available on muxer");
921 _has_class (GstElement * element, const gchar * classname)
923 GstElementClass *klass;
926 klass = GST_ELEMENT_GET_CLASS (element);
927 value = gst_element_class_get_metadata (klass, GST_ELEMENT_METADATA_KLASS);
929 return strstr (value, classname) != NULL;
932 /* FIXME : Add handling of streams that don't need encoding */
933 /* FIXME : Add handling of streams that don't require conversion elements */
935 * Create the elements, StreamGroup, add the sink pad, link it to the muxer
937 * sinkpadname: If non-NULL, that name will be assigned to the sink ghost pad
938 * sinkcaps: If non-NULL will be used to figure out how to setup the group */
940 _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
941 const gchar * sinkpadname, GstCaps * sinkcaps)
943 StreamGroup *sgroup = NULL;
944 GstPad *sinkpad, *srcpad, *muxerpad = NULL;
945 /* Element we will link to the encoder */
946 GstElement *last = NULL;
947 GList *tmp, *tosync = NULL;
948 GstCaps *format, *restriction;
949 const gchar *missing_element_name;
951 format = gst_encoding_profile_get_format (sprof);
952 restriction = gst_encoding_profile_get_restriction (sprof);
954 GST_DEBUG ("Creating group. format %" GST_PTR_FORMAT ", for caps %"
955 GST_PTR_FORMAT, format, sinkcaps);
956 GST_DEBUG ("avoid_reencoding:%d", ebin->avoid_reencoding);
958 sgroup = g_slice_new0 (StreamGroup);
960 sgroup->profile = sprof;
962 /* NOTE for people reading this code:
964 * We construct the group starting by the furthest downstream element
965 * and making our way up adding/syncing/linking as we go.
967 * There are two parallel paths:
968 * * One for raw data which goes through converters and encoders
969 * * One for already encoded data
972 /* Exception to the rule above:
973 * We check if we have an available encoder so we can abort early */
974 /* FIXME : What if we only want to do passthrough ??? */
975 GST_LOG ("Checking for encoder availability");
976 sgroup->encoder = _get_encoder (ebin, sprof);
977 if (G_UNLIKELY (sgroup->encoder == NULL))
981 * If we are handling a container profile, figure out if the muxer has a
982 * sinkpad compatible with the selected profile */
984 muxerpad = get_compatible_muxer_sink_pad (ebin, NULL, format);
985 if (G_UNLIKELY (muxerpad == NULL))
991 * We only use a 1buffer long queue here, the actual queueing will be done
992 * in the input queue */
993 last = sgroup->outqueue = gst_element_factory_make ("queue", NULL);
994 g_object_set (sgroup->outqueue, "max-size-buffers", (guint32) 1,
995 "max-size-bytes", (guint32) 0, "max-size-time", (guint64) 0, NULL);
997 gst_bin_add (GST_BIN (ebin), sgroup->outqueue);
998 tosync = g_list_append (tosync, sgroup->outqueue);
999 srcpad = gst_element_get_static_pad (sgroup->outqueue, "src");
1001 if (G_UNLIKELY (fast_pad_link (srcpad, muxerpad) != GST_PAD_LINK_OK)) {
1002 goto muxer_link_failure;
1004 gst_object_unref (muxerpad);
1006 gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), srcpad);
1008 gst_object_unref (srcpad);
1010 /* Check if we need a formatter
1011 * If we have no muxer or
1012 * if the muxer isn't a formatter and doesn't implement the tagsetter interface
1015 || (!gst_element_implements_interface (ebin->muxer, GST_TYPE_TAG_SETTER)
1016 || !_has_class (ebin->muxer, "Formatter"))) {
1017 sgroup->formatter = _get_formatter (ebin, sprof);
1018 if (sgroup->formatter) {
1019 GST_DEBUG ("Adding formatter for %" GST_PTR_FORMAT, format);
1021 gst_bin_add (GST_BIN (ebin), sgroup->formatter);
1022 tosync = g_list_append (tosync, sgroup->formatter);
1023 if (G_UNLIKELY (!fast_element_link (sgroup->formatter, last)))
1024 goto formatter_link_failure;
1025 last = sgroup->formatter;
1030 /* Output capsfilter
1031 * This will receive the format caps from the streamprofile */
1032 GST_DEBUG ("Adding output capsfilter for %" GST_PTR_FORMAT, format);
1033 sgroup->outfilter = gst_element_factory_make ("capsfilter", NULL);
1034 g_object_set (sgroup->outfilter, "caps", format, NULL);
1036 gst_bin_add (GST_BIN (ebin), sgroup->outfilter);
1037 tosync = g_list_append (tosync, sgroup->outfilter);
1038 if (G_UNLIKELY (!fast_element_link (sgroup->outfilter, last)))
1039 goto outfilter_link_failure;
1040 last = sgroup->outfilter;
1045 * The usage of parsers in encoding/muxing scenarios is
1046 * just too undefined to just use as-is.
1048 * Take the use-case where you want to re-mux a stream of type
1049 * "my/media". You create a StreamEncodingProfile with that type
1050 * as the target (as-is). And you use decodebin2/uridecodebin
1053 * * demuxer exposes "my/media"
1054 * * a parser is available for "my/media" which has a source pad
1055 * caps of "my/media,parsed=True"
1056 * * decodebin2/uridecodebin exposes a new pad with the parsed caps
1057 * * You request a new stream from encodebin, which will match the
1058 * streamprofile and creates a group (i.e. going through this method)
1059 * There is a matching parser (the same used in the decoder) whose
1060 * source pad caps intersects with the stream profile caps, you
1061 * therefore use it...
1062 * * ... but that parser has a "my/media,parsed=False" sink pad caps
1063 * * ... and you can't link your decodebin pad to encodebin.
1065 * In the end, it comes down to parsers only taking into account the
1066 * decoding use-cases.
1068 * One way to solve that might be to :
1069 * * Make parsers sink pad caps be "framed={False,True}" and the
1070 * source pad caps be "framed=True"
1071 * * Modify decodebin2 accordingly to avoid looping and chaining
1072 * an infinite number of parsers
1074 * Another way would be to have "well-known" caps properties to specify
1075 * whether a stream has been parsed or not.
1076 * * currently we fail. aacparse uses 'framed' and mp3parse uses 'parsed'
1078 /* FIXME : Re-enable once parser situation is un-$#*@(%$#ed */
1081 * FIXME : identify smart parsers (used for re-encoding) */
1082 sgroup->parser = _get_parser (ebin, sprof);
1084 if (sgroup->parser != NULL) {
1085 GST_DEBUG ("Got a parser %s", GST_ELEMENT_NAME (sgroup->parser));
1086 gst_bin_add (GST_BIN (ebin), sgroup->parser);
1087 tosync = g_list_append (tosync, sgroup->parser);
1088 if (G_UNLIKELY (!gst_element_link (sgroup->parser, last)))
1089 goto parser_link_failure;
1090 last = sgroup->parser;
1094 /* Stream combiner */
1095 sgroup->combiner = g_object_new (GST_TYPE_STREAM_COMBINER, NULL);
1097 gst_bin_add (GST_BIN (ebin), sgroup->combiner);
1098 tosync = g_list_append (tosync, sgroup->combiner);
1099 if (G_UNLIKELY (!fast_element_link (sgroup->combiner, last)))
1100 goto combiner_link_failure;
1103 /* Stream splitter */
1104 sgroup->splitter = g_object_new (GST_TYPE_STREAM_SPLITTER, NULL);
1106 gst_bin_add (GST_BIN (ebin), sgroup->splitter);
1107 tosync = g_list_append (tosync, sgroup->splitter);
1110 * FIXME : figure out what max-size to use for the input queue */
1111 sgroup->inqueue = gst_element_factory_make ("queue", NULL);
1112 g_object_set (sgroup->inqueue, "max-size-buffers",
1113 (guint32) ebin->queue_buffers_max, "max-size-bytes",
1114 (guint32) ebin->queue_bytes_max, "max-size-time",
1115 (guint64) ebin->queue_time_max, NULL);
1117 gst_bin_add (GST_BIN (ebin), sgroup->inqueue);
1118 tosync = g_list_append (tosync, sgroup->inqueue);
1119 if (G_UNLIKELY (!fast_element_link (sgroup->inqueue, sgroup->splitter)))
1120 goto splitter_link_failure;
1122 /* Expose input queue sink pad as ghostpad */
1123 sinkpad = gst_element_get_static_pad (sgroup->inqueue, "sink");
1124 if (sinkpadname == NULL) {
1126 g_strdup_printf ("%s_%d", gst_encoding_profile_get_type_nick (sprof),
1127 ebin->last_pad_id++);
1128 GST_DEBUG ("Adding ghost pad %s", pname);
1129 sgroup->ghostpad = gst_ghost_pad_new (pname, sinkpad);
1132 sgroup->ghostpad = gst_ghost_pad_new (sinkpadname, sinkpad);
1133 gst_object_unref (sinkpad);
1136 /* Path 1 : Already-encoded data */
1138 local_element_request_pad (sgroup->combiner, NULL, "passthroughsink",
1140 if (G_UNLIKELY (sinkpad == NULL))
1141 goto no_combiner_sinkpad;
1143 if (ebin->avoid_reencoding) {
1146 GST_DEBUG ("Asked to use Smart Encoder");
1147 sgroup->smartencoder = g_object_new (GST_TYPE_SMART_ENCODER, NULL);
1149 /* Check if stream format is compatible */
1150 srcpad = gst_element_get_static_pad (sgroup->smartencoder, "src");
1151 tmpcaps = gst_pad_get_caps (srcpad, NULL);
1152 if (!gst_caps_can_intersect (tmpcaps, format)) {
1153 GST_DEBUG ("We don't have a smart encoder for the stream format");
1154 gst_object_unref (sgroup->smartencoder);
1155 sgroup->smartencoder = NULL;
1157 gst_bin_add ((GstBin *) ebin, sgroup->smartencoder);
1158 fast_pad_link (srcpad, sinkpad);
1159 tosync = g_list_append (tosync, sgroup->smartencoder);
1160 sinkpad = gst_element_get_static_pad (sgroup->smartencoder, "sink");
1162 gst_caps_unref (tmpcaps);
1163 g_object_unref (srcpad);
1167 local_element_request_pad (sgroup->splitter, NULL, "passthroughsrc",
1169 if (G_UNLIKELY (srcpad == NULL))
1170 goto no_splitter_srcpad;
1172 /* Go straight to splitter */
1173 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1174 goto passthrough_link_failure;
1175 g_object_unref (sinkpad);
1176 g_object_unref (srcpad);
1179 /* Path 2 : Conversion / Encoding */
1181 /* 1. Create the encoder */
1182 GST_LOG ("Adding encoder");
1183 last = sgroup->encoder;
1184 gst_bin_add ((GstBin *) ebin, sgroup->encoder);
1185 tosync = g_list_append (tosync, sgroup->encoder);
1188 local_element_request_pad (sgroup->combiner, NULL, "encodingsink", NULL);
1189 if (G_UNLIKELY (sinkpad == NULL))
1190 goto no_combiner_sinkpad;
1191 srcpad = gst_element_get_static_pad (sgroup->encoder, "src");
1192 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1193 goto encoder_link_failure;
1194 g_object_unref (sinkpad);
1195 g_object_unref (srcpad);
1198 /* 3. Create the conversion/restriction elements */
1199 /* 3.1. capsfilter */
1200 if (restriction && !gst_caps_is_any (restriction)) {
1201 GST_LOG ("Adding capsfilter for restriction caps : %" GST_PTR_FORMAT,
1204 last = sgroup->capsfilter = gst_element_factory_make ("capsfilter", NULL);
1205 g_object_set (sgroup->capsfilter, "caps", restriction, NULL);
1206 gst_bin_add ((GstBin *) ebin, sgroup->capsfilter);
1207 tosync = g_list_append (tosync, sgroup->capsfilter);
1208 fast_element_link (sgroup->capsfilter, sgroup->encoder);
1211 /* 3.2. restriction elements */
1212 /* FIXME : Once we have properties for specific converters, use those */
1213 if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) {
1214 GstElement *cspace, *scale, *vrate, *cspace2;
1216 GST_LOG ("Adding conversion elements for video stream");
1218 cspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
1219 scale = gst_element_factory_make ("videoscale", NULL);
1221 missing_element_name = "videoscale";
1222 goto missing_element;
1224 /* 4-tap scaling and black borders */
1225 g_object_set (scale, "method", 2, "add-borders", TRUE, NULL);
1226 cspace2 = gst_element_factory_make ("ffmpegcolorspace", NULL);
1228 if (!cspace || !cspace2) {
1229 missing_element_name = "ffmpegcolorspace";
1230 goto missing_element;
1233 gst_bin_add_many ((GstBin *) ebin, cspace, scale, cspace2, NULL);
1234 tosync = g_list_append (tosync, cspace);
1235 tosync = g_list_append (tosync, scale);
1236 tosync = g_list_append (tosync, cspace2);
1238 sgroup->converters = g_list_prepend (sgroup->converters, cspace);
1239 sgroup->converters = g_list_prepend (sgroup->converters, scale);
1240 sgroup->converters = g_list_prepend (sgroup->converters, cspace2);
1242 if (!fast_element_link (cspace, scale) ||
1243 !fast_element_link (scale, cspace2))
1244 goto converter_link_failure;
1246 if (!gst_encoding_video_profile_get_variableframerate
1247 (GST_ENCODING_VIDEO_PROFILE (sprof))) {
1248 vrate = gst_element_factory_make ("videorate", NULL);
1250 missing_element_name = "videorate";
1251 goto missing_element;
1254 gst_bin_add ((GstBin *) ebin, vrate);
1255 tosync = g_list_prepend (tosync, vrate);
1256 sgroup->converters = g_list_prepend (sgroup->converters, vrate);
1257 if (!fast_element_link (cspace2, vrate) ||
1258 !fast_element_link (vrate, last))
1259 goto converter_link_failure;
1260 } else if (!fast_element_link (cspace2, last))
1261 goto converter_link_failure;
1265 } else if (GST_IS_ENCODING_AUDIO_PROFILE (sprof)) {
1266 GstElement *aconv, *ares, *arate, *aconv2;
1268 GST_LOG ("Adding conversion elements for audio stream");
1270 arate = gst_element_factory_make ("audiorate", NULL);
1271 g_object_set (arate, "tolerance", (guint64) ebin->tolerance, NULL);
1273 missing_element_name = "audiorate";
1274 goto missing_element;
1276 aconv = gst_element_factory_make ("audioconvert", NULL);
1277 aconv2 = gst_element_factory_make ("audioconvert", NULL);
1278 ares = gst_element_factory_make ("audioresample", NULL);
1279 if (!aconv || !aconv2) {
1280 missing_element_name = "audioconvert";
1281 goto missing_element;
1284 missing_element_name = "audioresample";
1285 goto missing_element;
1288 gst_bin_add_many ((GstBin *) ebin, arate, aconv, ares, aconv2, NULL);
1289 tosync = g_list_append (tosync, arate);
1290 tosync = g_list_append (tosync, aconv);
1291 tosync = g_list_append (tosync, ares);
1292 tosync = g_list_append (tosync, aconv2);
1293 if (!fast_element_link (arate, aconv) ||
1294 !fast_element_link (aconv, ares) ||
1295 !fast_element_link (ares, aconv2) || !fast_element_link (aconv2, last))
1296 goto converter_link_failure;
1298 sgroup->converters = g_list_prepend (sgroup->converters, arate);
1299 sgroup->converters = g_list_prepend (sgroup->converters, aconv);
1300 sgroup->converters = g_list_prepend (sgroup->converters, ares);
1301 sgroup->converters = g_list_prepend (sgroup->converters, aconv2);
1306 /* Link to stream splitter */
1307 sinkpad = gst_element_get_static_pad (last, "sink");
1309 local_element_request_pad (sgroup->splitter, NULL, "encodingsrc", NULL);
1310 if (G_UNLIKELY (srcpad == NULL))
1311 goto no_splitter_srcpad;
1312 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1313 goto splitter_encoding_failure;
1314 g_object_unref (sinkpad);
1315 g_object_unref (srcpad);
1317 /* End of Stream 2 setup */
1319 /* Sync all elements to parent state */
1320 for (tmp = tosync; tmp; tmp = tmp->next)
1321 gst_element_sync_state_with_parent ((GstElement *) tmp->data);
1322 g_list_free (tosync);
1325 GST_DEBUG ("Adding ghostpad %s:%s", GST_DEBUG_PAD_NAME (sgroup->ghostpad));
1326 gst_pad_set_active (sgroup->ghostpad, TRUE);
1327 gst_element_add_pad ((GstElement *) ebin, sgroup->ghostpad);
1329 /* Add StreamGroup to our list of streams */
1332 ("Done creating elements, adding StreamGroup to our controlled stream list");
1334 ebin->streams = g_list_prepend (ebin->streams, sgroup);
1337 gst_caps_unref (format);
1339 gst_caps_unref (restriction);
1343 splitter_encoding_failure:
1344 GST_ERROR_OBJECT (ebin, "Error linking splitter to encoding stream");
1348 GST_ERROR_OBJECT (ebin, "Couldn't create encoder for format %" GST_PTR_FORMAT,
1350 /* missing plugin support */
1351 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1352 gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin), format));
1353 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL),
1354 ("Couldn't create encoder for format %" GST_PTR_FORMAT, format));
1358 GST_ERROR_OBJECT (ebin,
1359 "Couldn't find a compatible muxer pad to link encoder to");
1363 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1364 gst_missing_element_message_new (GST_ELEMENT_CAST (ebin),
1365 missing_element_name));
1366 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN,
1367 (_("Missing element '%s' - check your GStreamer installation."),
1368 missing_element_name), (NULL));
1371 encoder_link_failure:
1372 GST_ERROR_OBJECT (ebin, "Failed to link the encoder");
1376 GST_ERROR_OBJECT (ebin, "Couldn't link encoder to muxer");
1379 formatter_link_failure:
1380 GST_ERROR_OBJECT (ebin, "Couldn't link output filter to output queue");
1383 outfilter_link_failure:
1384 GST_ERROR_OBJECT (ebin,
1385 "Couldn't link output filter to output queue/formatter");
1388 passthrough_link_failure:
1389 GST_ERROR_OBJECT (ebin, "Failed linking splitter in passthrough mode");
1393 GST_ERROR_OBJECT (ebin, "Couldn't get a source pad from the splitter");
1396 no_combiner_sinkpad:
1397 GST_ERROR_OBJECT (ebin, "Couldn't get a sink pad from the combiner");
1400 splitter_link_failure:
1401 GST_ERROR_OBJECT (ebin, "Failure linking to the splitter");
1404 combiner_link_failure:
1405 GST_ERROR_OBJECT (ebin, "Failure linking to the combiner");
1409 parser_link_failure:
1410 GST_ERROR_OBJECT (ebin, "Failure linking the parser");
1414 converter_link_failure:
1415 GST_ERROR_OBJECT (ebin, "Failure linking the video converters");
1419 /* FIXME : Actually properly cleanup everything */
1421 gst_caps_unref (format);
1423 gst_caps_unref (restriction);
1424 g_slice_free (StreamGroup, sgroup);
1429 _factory_can_sink_caps (GstElementFactory * factory, const GstCaps * caps)
1431 GList *templates = factory->staticpadtemplates;
1434 GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
1436 if (template->direction == GST_PAD_SINK) {
1437 GstCaps *tmp = gst_static_caps_get (&template->static_caps);
1439 if (gst_caps_can_intersect (tmp, caps)) {
1440 gst_caps_unref (tmp);
1443 gst_caps_unref (tmp);
1445 templates = g_list_next (templates);
1451 static inline GstElement *
1452 _get_formatter (GstEncodeBin * ebin, GstEncodingProfile * sprof)
1454 GList *formatters, *tmpfmtr;
1455 GstElement *formatter = NULL;
1456 GstElementFactory *formatterfact = NULL;
1457 const GstCaps *format;
1458 const gchar *preset;
1460 format = gst_encoding_profile_get_format (sprof);
1461 preset = gst_encoding_profile_get_preset (sprof);
1463 GST_DEBUG ("Getting list of formatters for format %" GST_PTR_FORMAT, format);
1466 gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
1469 if (formatters == NULL)
1472 /* FIXME : signal the user if he wants this */
1473 for (tmpfmtr = formatters; tmpfmtr; tmpfmtr = tmpfmtr->next) {
1474 formatterfact = (GstElementFactory *) tmpfmtr->data;
1476 GST_DEBUG_OBJECT (ebin, "Trying formatter %s",
1477 GST_OBJECT_NAME (formatterfact));
1480 _create_element_and_set_preset (formatterfact, preset, NULL)))
1484 gst_plugin_feature_list_free (formatters);
1490 static inline GstElement *
1491 _get_muxer (GstEncodeBin * ebin)
1493 GList *muxers, *formatters, *tmpmux;
1494 GstElement *muxer = NULL;
1495 GstElementFactory *muxerfact = NULL;
1497 const GstCaps *format;
1498 const gchar *preset;
1500 format = gst_encoding_profile_get_format (ebin->profile);
1501 preset = gst_encoding_profile_get_preset (ebin->profile);
1503 GST_DEBUG ("Getting list of muxers for format %" GST_PTR_FORMAT, format);
1506 gst_element_factory_list_filter (ebin->muxers, format, GST_PAD_SRC, TRUE);
1509 gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
1512 muxers = g_list_concat (muxers, formatters);
1517 /* FIXME : signal the user if he wants this */
1518 for (tmpmux = muxers; tmpmux; tmpmux = tmpmux->next) {
1519 gboolean cansinkstreams = TRUE;
1520 const GList *profiles =
1521 gst_encoding_container_profile_get_profiles
1522 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
1524 muxerfact = (GstElementFactory *) tmpmux->data;
1526 GST_DEBUG ("Trying muxer %s", GST_OBJECT_NAME (muxerfact));
1528 /* See if the muxer can sink all of our stream profile caps */
1529 for (tmp = profiles; tmp; tmp = tmp->next) {
1530 GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
1532 if (!_factory_can_sink_caps (muxerfact,
1533 gst_encoding_profile_get_format (sprof))) {
1534 GST_DEBUG ("Skipping muxer because it can't sink caps %" GST_PTR_FORMAT,
1535 gst_encoding_profile_get_format (sprof));
1536 cansinkstreams = FALSE;
1541 /* Only use a muxer than can use all streams and than can accept the
1542 * preset (which may be present or not) */
1543 if (cansinkstreams && (muxer =
1544 _create_element_and_set_preset (muxerfact, preset, "muxer")))
1548 gst_plugin_feature_list_free (muxers);
1555 create_elements_and_pads (GstEncodeBin * ebin)
1557 gboolean ret = TRUE;
1558 GstElement *muxer = NULL;
1560 const GList *tmp, *profiles;
1561 GstEncodingProfile *sprof;
1563 GST_DEBUG ("Current profile : %s",
1564 gst_encoding_profile_get_name (ebin->profile));
1566 if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
1567 /* 1. Get the compatible muxer */
1568 muxer = _get_muxer (ebin);
1569 if (G_UNLIKELY (muxer == NULL))
1572 /* Record the muxer */
1573 ebin->muxer = muxer;
1574 gst_bin_add ((GstBin *) ebin, muxer);
1576 /* 2. Ghost the muxer source pad */
1578 /* FIXME : We should figure out if it's a static/request/dyamic pad,
1579 * but for the time being let's assume it's a static pad :) */
1580 muxerpad = gst_element_get_static_pad (muxer, "src");
1581 if (G_UNLIKELY (muxerpad == NULL))
1584 if (!gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), muxerpad))
1585 goto no_muxer_ghost_pad;
1587 gst_object_unref (muxerpad);
1588 /* 3. Activate fixed presence streams */
1590 gst_encoding_container_profile_get_profiles
1591 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
1592 for (tmp = profiles; tmp; tmp = tmp->next) {
1593 sprof = (GstEncodingProfile *) tmp->data;
1595 GST_DEBUG ("Trying stream profile with presence %d",
1596 gst_encoding_profile_get_presence (sprof));
1598 if (gst_encoding_profile_get_presence (sprof) != 0) {
1599 if (G_UNLIKELY (_create_stream_group (ebin, sprof, NULL, NULL) == NULL))
1604 if (G_UNLIKELY (_create_stream_group (ebin, ebin->profile, NULL,
1613 GST_WARNING ("No available muxer for %" GST_PTR_FORMAT,
1614 gst_encoding_profile_get_format (ebin->profile));
1615 /* missing plugin support */
1616 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1617 gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin),
1618 gst_encoding_profile_get_format (ebin->profile)));
1619 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL),
1620 ("No available muxer for format %" GST_PTR_FORMAT,
1621 gst_encoding_profile_get_format (ebin->profile)));
1627 GST_WARNING ("Can't get source pad from muxer (%s)",
1628 GST_ELEMENT_NAME (muxer));
1629 gst_bin_remove (GST_BIN (ebin), muxer);
1635 GST_WARNING ("Couldn't set %s:%s as source ghostpad target",
1636 GST_DEBUG_PAD_NAME (muxerpad));
1637 gst_bin_remove (GST_BIN (ebin), muxer);
1638 gst_object_unref (muxerpad);
1644 GST_WARNING ("Could not create Streams");
1646 gst_bin_remove (GST_BIN (ebin), muxer);
1653 release_pads (const GValue * item, GstElement * elt)
1655 GstPad *pad = g_value_get_object (item);
1656 GstPad *peer = NULL;
1658 GST_DEBUG_OBJECT (elt, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1660 /* Unlink from its peer pad */
1661 if ((peer = gst_pad_get_peer (pad))) {
1662 if (GST_PAD_DIRECTION (peer) == GST_PAD_SRC)
1663 gst_pad_unlink (peer, pad);
1665 gst_pad_unlink (pad, peer);
1666 gst_object_unref (peer);
1669 /* Release it from the object */
1670 gst_element_release_request_pad (elt, pad);
1674 stream_group_free (GstEncodeBin * ebin, StreamGroup * sgroup)
1680 GST_DEBUG_OBJECT (ebin, "Freeing StreamGroup %p", sgroup);
1683 /* outqueue - Muxer */
1684 tmppad = gst_element_get_static_pad (sgroup->outqueue, "src");
1685 pad = gst_pad_get_peer (tmppad);
1687 /* Remove muxer request sink pad */
1688 gst_pad_unlink (tmppad, pad);
1689 gst_element_release_request_pad (ebin->muxer, pad);
1690 gst_object_unref (tmppad);
1691 gst_object_unref (pad);
1693 if (sgroup->outqueue)
1694 gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
1696 if (sgroup->formatter) {
1697 /* capsfilter - formatter - outqueue */
1698 gst_element_set_state (sgroup->formatter, GST_STATE_NULL);
1699 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1700 gst_element_unlink (sgroup->formatter, sgroup->outqueue);
1701 gst_element_unlink (sgroup->outfilter, sgroup->formatter);
1703 /* Capsfilter - outqueue */
1704 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1705 gst_element_unlink (sgroup->outfilter, sgroup->outqueue);
1707 gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
1708 gst_bin_remove (GST_BIN (ebin), sgroup->outqueue);
1710 /* streamcombiner - parser - capsfilter */
1711 if (sgroup->parser) {
1712 gst_element_set_state (sgroup->parser, GST_STATE_NULL);
1713 gst_element_unlink (sgroup->parser, sgroup->outfilter);
1714 gst_element_unlink (sgroup->combiner, sgroup->parser);
1715 gst_bin_remove ((GstBin *) ebin, sgroup->parser);
1719 if (sgroup->ghostpad)
1720 gst_element_remove_pad (GST_ELEMENT_CAST (ebin), sgroup->ghostpad);
1722 if (sgroup->inqueue)
1723 gst_element_set_state (sgroup->inqueue, GST_STATE_NULL);
1725 if (sgroup->encoder)
1726 gst_element_set_state (sgroup->encoder, GST_STATE_NULL);
1727 if (sgroup->outfilter)
1728 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1729 if (sgroup->smartencoder)
1730 gst_element_set_state (sgroup->smartencoder, GST_STATE_NULL);
1732 if (sgroup->capsfilter) {
1733 gst_element_set_state (sgroup->capsfilter, GST_STATE_NULL);
1734 gst_element_unlink (sgroup->capsfilter, sgroup->encoder);
1735 gst_bin_remove ((GstBin *) ebin, sgroup->capsfilter);
1738 for (tmp = sgroup->converters; tmp; tmp = tmp->next) {
1739 GstElement *elt = (GstElement *) tmp->data;
1741 gst_element_set_state (elt, GST_STATE_NULL);
1742 gst_bin_remove ((GstBin *) ebin, elt);
1744 if (sgroup->converters)
1745 g_list_free (sgroup->converters);
1747 if (sgroup->combiner) {
1748 GstIterator *it = gst_element_iterate_sink_pads (sgroup->combiner);
1749 GstIteratorResult itret = GST_ITERATOR_OK;
1751 while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
1753 gst_iterator_foreach (it, (GstIteratorForeachFunction) release_pads,
1755 gst_iterator_resync (it);
1757 gst_iterator_free (it);
1758 gst_element_set_state (sgroup->combiner, GST_STATE_NULL);
1759 gst_bin_remove ((GstBin *) ebin, sgroup->combiner);
1762 if (sgroup->splitter) {
1763 GstIterator *it = gst_element_iterate_src_pads (sgroup->splitter);
1764 GstIteratorResult itret = GST_ITERATOR_OK;
1765 while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
1767 gst_iterator_foreach (it, (GstIteratorForeachFunction) release_pads,
1769 gst_iterator_resync (it);
1771 gst_iterator_free (it);
1773 gst_element_set_state (sgroup->splitter, GST_STATE_NULL);
1774 gst_bin_remove ((GstBin *) ebin, sgroup->splitter);
1777 if (sgroup->inqueue)
1778 gst_bin_remove ((GstBin *) ebin, sgroup->inqueue);
1780 if (sgroup->encoder)
1781 gst_bin_remove ((GstBin *) ebin, sgroup->encoder);
1783 if (sgroup->smartencoder)
1784 gst_bin_remove ((GstBin *) ebin, sgroup->smartencoder);
1786 if (sgroup->outfilter)
1787 gst_bin_remove ((GstBin *) ebin, sgroup->outfilter);
1789 g_slice_free (StreamGroup, sgroup);
1793 stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup)
1795 ebin->streams = g_list_remove (ebin->streams, sgroup);
1797 stream_group_free (ebin, sgroup);
1801 gst_encode_bin_tear_down_profile (GstEncodeBin * ebin)
1803 if (G_UNLIKELY (ebin->profile == NULL))
1806 GST_DEBUG ("Tearing down profile %s",
1807 gst_encoding_profile_get_name (ebin->profile));
1809 while (ebin->streams)
1810 stream_group_remove (ebin, (StreamGroup *) ebin->streams->data);
1812 /* Set ghostpad target to NULL */
1813 gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), NULL);
1815 /* Remove muxer if present */
1817 gst_element_set_state (ebin->muxer, GST_STATE_NULL);
1818 gst_bin_remove (GST_BIN (ebin), ebin->muxer);
1822 /* free/clear profile */
1823 gst_encoding_profile_unref (ebin->profile);
1824 ebin->profile = NULL;
1828 gst_encode_bin_setup_profile (GstEncodeBin * ebin, GstEncodingProfile * profile)
1832 g_return_val_if_fail (ebin->profile == NULL, FALSE);
1834 GST_DEBUG ("Setting up profile %s (type:%s)",
1835 gst_encoding_profile_get_name (profile),
1836 gst_encoding_profile_get_type_nick (profile));
1838 ebin->profile = profile;
1839 gst_mini_object_ref ((GstMiniObject *) ebin->profile);
1841 /* Create elements */
1842 res = create_elements_and_pads (ebin);
1844 gst_encode_bin_tear_down_profile (ebin);
1850 gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile)
1852 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
1854 GST_DEBUG_OBJECT (ebin, "profile : %s",
1855 gst_encoding_profile_get_name (profile));
1857 if (G_UNLIKELY (ebin->active)) {
1858 GST_WARNING_OBJECT (ebin, "Element already active, can't change profile");
1862 /* If we're not active, we can deactivate the previous profile */
1863 if (ebin->profile) {
1864 gst_encode_bin_tear_down_profile (ebin);
1867 return gst_encode_bin_setup_profile (ebin, profile);
1870 static inline gboolean
1871 gst_encode_bin_activate (GstEncodeBin * ebin)
1873 ebin->active = ebin->profile != NULL;
1874 return ebin->active;
1878 gst_encode_bin_deactivate (GstEncodeBin * ebin)
1880 ebin->active = FALSE;
1883 static GstStateChangeReturn
1884 gst_encode_bin_change_state (GstElement * element, GstStateChange transition)
1886 GstStateChangeReturn ret;
1887 GstEncodeBin *ebin = (GstEncodeBin *) element;
1889 switch (transition) {
1890 case GST_STATE_CHANGE_READY_TO_PAUSED:
1891 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1892 if (!gst_encode_bin_activate (ebin)) {
1893 ret = GST_STATE_CHANGE_FAILURE;
1902 GST_ELEMENT_CLASS (gst_encode_bin_parent_class)->change_state (element,
1904 if (ret == GST_STATE_CHANGE_FAILURE)
1907 switch (transition) {
1908 case GST_STATE_CHANGE_PAUSED_TO_READY:
1909 gst_encode_bin_deactivate (ebin);
1921 plugin_init (GstPlugin * plugin)
1925 GST_DEBUG_CATEGORY_INIT (gst_encode_bin_debug, "encodebin", 0, "encoder bin");
1928 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
1930 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1931 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1932 #endif /* ENABLE_NLS */
1935 res = gst_element_register (plugin, "encodebin", GST_RANK_NONE,
1936 GST_TYPE_ENCODE_BIN);
1941 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1944 "various encoding-related elements", plugin_init, VERSION, GST_LICENSE,
1945 GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)