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)
123 GST_ENC_FLAG_NO_AUDIO_CONVERSION = (1 << 0),
124 GST_ENC_FLAG_NO_VIDEO_CONVERSION = (1 << 1)
127 #define GST_TYPE_ENC_FLAGS (gst_enc_flags_get_type())
128 GType gst_enc_flags_get_type (void);
130 /* generic templates */
131 static GstStaticPadTemplate muxer_src_template =
132 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
133 GST_STATIC_CAPS_ANY);
135 static GstStaticPadTemplate video_sink_template =
136 GST_STATIC_PAD_TEMPLATE ("video_%d",
139 GST_STATIC_CAPS_ANY);
140 static GstStaticPadTemplate audio_sink_template =
141 GST_STATIC_PAD_TEMPLATE ("audio_%d",
144 GST_STATIC_CAPS_ANY);
145 /* static GstStaticPadTemplate text_sink_template = */
146 /* GST_STATIC_PAD_TEMPLATE ("text_%d", */
148 /* GST_PAD_REQUEST, */
149 /* GST_STATIC_CAPS_ANY); */
150 static GstStaticPadTemplate private_sink_template =
151 GST_STATIC_PAD_TEMPLATE ("private_%d",
154 GST_STATIC_CAPS_ANY);
160 /* the profile field is only valid if it could be entirely setup */
161 GstEncodingProfile *profile;
163 GList *streams; /* List of StreamGroup, not sorted */
166 /* Ghostpad with changing target */
169 /* TRUE if in PAUSED/PLAYING */
172 /* available muxers, encoders and parsers */
178 /* Increasing counter for unique pad name */
181 /* Cached caps for identification */
182 GstCaps *raw_video_caps;
183 GstCaps *raw_audio_caps;
184 /* GstCaps *raw_text_caps; */
186 guint queue_buffers_max;
187 guint queue_bytes_max;
188 guint64 queue_time_max;
191 gboolean avoid_reencoding;
196 struct _GstEncodeBinClass
201 GstPad *(*request_pad) (GstEncodeBin * encodebin, GstCaps * caps);
204 typedef struct _StreamGroup StreamGroup;
209 GstEncodingProfile *profile;
210 GstPad *ghostpad; /* Sink ghostpad */
211 GstElement *inqueue; /* Queue just after the ghostpad */
212 GstElement *splitter;
213 GList *converters; /* List of conversion GstElement */
214 GstElement *capsfilter; /* profile->restriction (if non-NULL/ANY) */
215 GstElement *encoder; /* Encoder (can be NULL) */
216 GstElement *combiner;
218 GstElement *smartencoder;
219 GstElement *outfilter; /* Output capsfilter (streamprofile.format) */
220 GstElement *formatter;
221 GstElement *outqueue; /* Queue just before the muxer */
224 /* Default for queues (same defaults as queue element) */
225 #define DEFAULT_QUEUE_BUFFERS_MAX 200
226 #define DEFAULT_QUEUE_BYTES_MAX 10 * 1024 * 1024
227 #define DEFAULT_QUEUE_TIME_MAX GST_SECOND
228 #define DEFAULT_AUDIO_JITTER_TOLERANCE 20 * GST_MSECOND
229 #define DEFAULT_AVOID_REENCODING FALSE
230 #define DEFAULT_FLAGS 0
232 #define DEFAULT_RAW_CAPS \
233 "video/x-raw-yuv; " \
234 "video/x-raw-rgb; " \
235 "video/x-raw-gray; " \
236 "audio/x-raw-int; " \
237 "audio/x-raw-float; " \
239 "text/x-pango-markup; " \
240 "video/x-dvd-subpicture; " \
248 PROP_QUEUE_BUFFERS_MAX,
249 PROP_QUEUE_BYTES_MAX,
251 PROP_AUDIO_JITTER_TOLERANCE,
252 PROP_AVOID_REENCODING,
264 #define C_FLAGS(v) ((guint) v)
267 gst_enc_flags_get_type (void)
269 static const GFlagsValue values[] = {
270 {C_FLAGS (GST_ENC_FLAG_NO_AUDIO_CONVERSION), "Do not use audio conversion "
271 "elements", "no-audio-conversion"},
272 {C_FLAGS (GST_ENC_FLAG_NO_VIDEO_CONVERSION), "Do not use video conversion "
273 "elements", "no-video-conversion"},
276 static volatile GType id = 0;
278 if (g_once_init_enter ((gsize *) & id)) {
281 _id = g_flags_register_static ("GstEncFlags", values);
283 g_once_init_leave ((gsize *) & id, _id);
289 static guint gst_encode_bin_signals[LAST_SIGNAL] = { 0 };
291 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
293 GST_DEBUG_CATEGORY_STATIC (gst_encode_bin_debug);
294 #define GST_CAT_DEFAULT gst_encode_bin_debug
296 G_DEFINE_TYPE (GstEncodeBin, gst_encode_bin, GST_TYPE_BIN);
298 static void gst_encode_bin_dispose (GObject * object);
299 static void gst_encode_bin_set_property (GObject * object, guint prop_id,
300 const GValue * value, GParamSpec * pspec);
301 static void gst_encode_bin_get_property (GObject * object, guint prop_id,
302 GValue * value, GParamSpec * pspec);
303 static GstStateChangeReturn gst_encode_bin_change_state (GstElement * element,
304 GstStateChange transition);
306 static GstPad *gst_encode_bin_request_new_pad (GstElement * element,
307 GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
308 static void gst_encode_bin_release_pad (GstElement * element, GstPad * pad);
311 gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile);
312 static void gst_encode_bin_tear_down_profile (GstEncodeBin * ebin);
313 static gboolean gst_encode_bin_setup_profile (GstEncodeBin * ebin,
314 GstEncodingProfile * profile);
316 static StreamGroup *_create_stream_group (GstEncodeBin * ebin,
317 GstEncodingProfile * sprof, const gchar * sinkpadname, GstCaps * sinkcaps);
318 static void stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup);
319 static GstPad *gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin,
322 static inline GstElement *_get_formatter (GstEncodeBin * ebin,
323 GstEncodingProfile * sprof);
326 gst_encode_bin_class_init (GstEncodeBinClass * klass)
328 GObjectClass *gobject_klass;
329 GstElementClass *gstelement_klass;
331 gobject_klass = (GObjectClass *) klass;
332 gstelement_klass = (GstElementClass *) klass;
334 gobject_klass->dispose = gst_encode_bin_dispose;
335 gobject_klass->set_property = gst_encode_bin_set_property;
336 gobject_klass->get_property = gst_encode_bin_get_property;
341 * GstEncodeBin:profile:
343 * The #GstEncodingProfile to use. This property must be set before going
344 * to %GST_STATE_PAUSED or higher.
346 g_object_class_install_property (gobject_klass, PROP_PROFILE,
347 gst_param_spec_mini_object ("profile", "Profile",
348 "The GstEncodingProfile to use", GST_TYPE_ENCODING_PROFILE,
349 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
351 g_object_class_install_property (gobject_klass, PROP_QUEUE_BYTES_MAX,
352 g_param_spec_uint ("queue-bytes-max", "Max. size (kB)",
353 "Max. amount of data in the queue (bytes, 0=disable)",
354 0, G_MAXUINT, DEFAULT_QUEUE_BYTES_MAX,
355 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
357 g_object_class_install_property (gobject_klass, PROP_QUEUE_BUFFERS_MAX,
358 g_param_spec_uint ("queue-buffers-max", "Max. size (buffers)",
359 "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
360 DEFAULT_QUEUE_BUFFERS_MAX,
361 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
363 g_object_class_install_property (gobject_klass, PROP_QUEUE_TIME_MAX,
364 g_param_spec_uint64 ("queue-time-max", "Max. size (ns)",
365 "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
366 DEFAULT_QUEUE_TIME_MAX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
368 g_object_class_install_property (gobject_klass, PROP_AUDIO_JITTER_TOLERANCE,
369 g_param_spec_uint64 ("audio-jitter-tolerance", "Audio jitter tolerance",
370 "Amount of timestamp jitter/imperfection to allow on audio streams before inserting/dropping samples (ns)",
371 0, G_MAXUINT64, DEFAULT_AUDIO_JITTER_TOLERANCE,
372 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
374 g_object_class_install_property (gobject_klass, PROP_AVOID_REENCODING,
375 g_param_spec_boolean ("avoid-reencoding", "Avoid re-encoding",
376 "Whether to re-encode portions of compatible video streams that lay on segment boundaries",
377 DEFAULT_AVOID_REENCODING,
378 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
383 * Control the behaviour of encodebin.
385 g_object_class_install_property (gobject_klass, PROP_FLAGS,
386 g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
387 GST_TYPE_ENC_FLAGS, DEFAULT_FLAGS,
388 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
392 * GstEncodeBin::request-pad
393 * @encodebin: a #GstEncodeBin instance
396 * Use this method to request an unused sink request #GstPad that can take the
397 * provided @caps as input. You must release the pad with
398 * gst_element_release_request_pad() when you are done with it.
400 * Returns: A compatible #GstPad, or %NULL if no compatible #GstPad could be
401 * created or is available.
403 gst_encode_bin_signals[SIGNAL_REQUEST_PAD] =
404 g_signal_new ("request-pad", G_TYPE_FROM_CLASS (klass),
405 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstEncodeBinClass,
406 request_pad), NULL, NULL, gst_encode_marshal_OBJECT__BOXED,
407 GST_TYPE_PAD, 1, GST_TYPE_CAPS);
409 klass->request_pad = gst_encode_bin_request_pad_signal;
411 gst_element_class_add_static_pad_template (gstelement_klass,
412 &muxer_src_template);
413 gst_element_class_add_static_pad_template (gstelement_klass,
414 &video_sink_template);
415 gst_element_class_add_static_pad_template (gstelement_klass,
416 &audio_sink_template);
417 /* gst_element_class_add_static_pad_template (gstelement_klass, */
418 /* &text_sink_template); */
419 gst_element_class_add_static_pad_template (gstelement_klass,
420 &private_sink_template);
422 gstelement_klass->change_state =
423 GST_DEBUG_FUNCPTR (gst_encode_bin_change_state);
424 gstelement_klass->request_new_pad_full =
425 GST_DEBUG_FUNCPTR (gst_encode_bin_request_new_pad);
426 gstelement_klass->release_pad =
427 GST_DEBUG_FUNCPTR (gst_encode_bin_release_pad);
429 gst_element_class_set_details_simple (gstelement_klass,
431 "Generic/Bin/Encoder",
432 "Convenience encoding/muxing element",
433 "Edward Hervey <edward.hervey@collabora.co.uk>");
437 gst_encode_bin_dispose (GObject * object)
439 GstEncodeBin *ebin = (GstEncodeBin *) object;
442 gst_plugin_feature_list_free (ebin->muxers);
444 if (ebin->formatters)
445 gst_plugin_feature_list_free (ebin->formatters);
448 gst_plugin_feature_list_free (ebin->encoders);
451 gst_plugin_feature_list_free (ebin->parsers);
453 gst_encode_bin_tear_down_profile (ebin);
455 if (ebin->raw_video_caps)
456 gst_caps_unref (ebin->raw_video_caps);
457 if (ebin->raw_audio_caps)
458 gst_caps_unref (ebin->raw_audio_caps);
459 /* if (ebin->raw_text_caps) */
460 /* gst_caps_unref (ebin->raw_text_caps); */
462 G_OBJECT_CLASS (gst_encode_bin_parent_class)->dispose (object);
466 gst_encode_bin_init (GstEncodeBin * encode_bin)
468 GstPadTemplate *tmpl;
471 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
474 encode_bin->formatters =
475 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_FORMATTER,
478 encode_bin->encoders =
479 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
482 encode_bin->parsers =
483 gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_PARSER,
486 encode_bin->raw_video_caps =
487 gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray");
488 encode_bin->raw_audio_caps =
489 gst_caps_from_string ("audio/x-raw-int;audio/x-raw-float");
490 /* encode_bin->raw_text_caps = */
491 /* gst_caps_from_string ("text/plain;text/x-pango-markup"); */
493 encode_bin->queue_buffers_max = DEFAULT_QUEUE_BUFFERS_MAX;
494 encode_bin->queue_bytes_max = DEFAULT_QUEUE_BYTES_MAX;
495 encode_bin->queue_time_max = DEFAULT_QUEUE_TIME_MAX;
496 encode_bin->tolerance = DEFAULT_AUDIO_JITTER_TOLERANCE;
497 encode_bin->avoid_reencoding = DEFAULT_AVOID_REENCODING;
498 encode_bin->flags = DEFAULT_FLAGS;
500 tmpl = gst_static_pad_template_get (&muxer_src_template);
501 encode_bin->srcpad = gst_ghost_pad_new_no_target_from_template ("src", tmpl);
502 gst_object_unref (tmpl);
503 gst_element_add_pad (GST_ELEMENT_CAST (encode_bin), encode_bin->srcpad);
507 gst_encode_bin_set_property (GObject * object, guint prop_id,
508 const GValue * value, GParamSpec * pspec)
510 GstEncodeBin *ebin = (GstEncodeBin *) object;
514 gst_encode_bin_set_profile (ebin,
515 (GstEncodingProfile *) gst_value_get_mini_object (value));
517 case PROP_QUEUE_BUFFERS_MAX:
518 ebin->queue_buffers_max = g_value_get_uint (value);
520 case PROP_QUEUE_BYTES_MAX:
521 ebin->queue_bytes_max = g_value_get_uint (value);
523 case PROP_QUEUE_TIME_MAX:
524 ebin->queue_time_max = g_value_get_uint64 (value);
526 case PROP_AUDIO_JITTER_TOLERANCE:
527 ebin->tolerance = g_value_get_uint64 (value);
529 case PROP_AVOID_REENCODING:
530 ebin->avoid_reencoding = g_value_get_boolean (value);
533 ebin->flags = g_value_get_flags (value);
536 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
542 gst_encode_bin_get_property (GObject * object, guint prop_id,
543 GValue * value, GParamSpec * pspec)
545 GstEncodeBin *ebin = (GstEncodeBin *) object;
549 gst_value_set_mini_object (value, (GstMiniObject *) ebin->profile);
551 case PROP_QUEUE_BUFFERS_MAX:
552 g_value_set_uint (value, ebin->queue_buffers_max);
554 case PROP_QUEUE_BYTES_MAX:
555 g_value_set_uint (value, ebin->queue_bytes_max);
557 case PROP_QUEUE_TIME_MAX:
558 g_value_set_uint64 (value, ebin->queue_time_max);
560 case PROP_AUDIO_JITTER_TOLERANCE:
561 g_value_set_uint64 (value, ebin->tolerance);
563 case PROP_AVOID_REENCODING:
564 g_value_set_boolean (value, ebin->avoid_reencoding);
567 g_value_set_flags (value, ebin->flags);
570 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
575 static inline gboolean
576 are_raw_caps (const GstCaps * caps)
578 GstCaps *raw = gst_static_caps_get (&default_raw_caps);
580 if (gst_caps_can_intersect (caps, raw)) {
581 gst_caps_unref (raw);
584 gst_caps_unref (raw);
588 /* Returns the number of time a given stream profile is currently used
591 stream_profile_used_count (GstEncodeBin * ebin, GstEncodingProfile * sprof)
593 guint nbprofused = 0;
596 for (tmp = ebin->streams; tmp; tmp = tmp->next) {
597 StreamGroup *sgroup = (StreamGroup *) tmp->data;
599 if (sgroup->profile == sprof)
606 static inline GstEncodingProfile *
607 next_unused_stream_profile (GstEncodeBin * ebin, GType ptype, GstCaps * caps)
609 GST_DEBUG_OBJECT (ebin, "ptype:%s, caps:%" GST_PTR_FORMAT,
610 g_type_name (ptype), caps);
612 if (G_UNLIKELY (ptype == G_TYPE_NONE && caps != NULL)) {
613 /* Identify the profile type based on raw caps */
614 if (gst_caps_can_intersect (ebin->raw_video_caps, caps))
615 ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
616 else if (gst_caps_can_intersect (ebin->raw_audio_caps, caps))
617 ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
618 /* else if (gst_caps_can_intersect (ebin->raw_text_caps, caps)) */
619 /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
620 GST_DEBUG_OBJECT (ebin, "Detected profile type as being %s",
621 g_type_name (ptype));
624 if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
628 gst_encoding_container_profile_get_profiles
629 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile)); tmp;
631 GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
633 /* Pick an available Stream profile for which:
634 * * either it is of the compatibly raw type,
635 * * OR we can pass it through directly without encoding
637 if (G_TYPE_FROM_INSTANCE (sprof) == ptype) {
638 guint presence = gst_encoding_profile_get_presence (sprof);
639 GST_DEBUG ("Found a stream profile with the same type");
641 || (presence > stream_profile_used_count (ebin, sprof)))
643 } else if ((caps != NULL) && (ptype == G_TYPE_NONE)) {
647 outcaps = gst_encoding_profile_get_input_caps (sprof);
648 GST_DEBUG ("Unknown stream, seeing if it's compatible with %"
649 GST_PTR_FORMAT, outcaps);
650 res = gst_caps_can_intersect (outcaps, caps);
651 gst_caps_unref (outcaps);
663 request_pad_for_stream (GstEncodeBin * encodebin, GType ptype,
664 const gchar * name, GstCaps * caps)
667 GstEncodingProfile *sprof;
669 GST_DEBUG_OBJECT (encodebin, "name:%s caps:%" GST_PTR_FORMAT, name, caps);
671 /* Figure out if we have a unused GstEncodingProfile we can use for
673 sprof = next_unused_stream_profile (encodebin, ptype, caps);
675 if (G_UNLIKELY (sprof == NULL))
676 goto no_stream_profile;
678 sgroup = _create_stream_group (encodebin, sprof, name, caps);
679 if (G_UNLIKELY (sgroup == NULL))
680 goto no_stream_group;
682 return sgroup->ghostpad;
686 GST_WARNING_OBJECT (encodebin, "Couldn't find a compatible stream profile");
692 GST_WARNING_OBJECT (encodebin, "Couldn't create a StreamGroup");
698 gst_encode_bin_request_new_pad (GstElement * element,
699 GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
701 GstEncodeBin *ebin = (GstEncodeBin *) element;
704 GST_DEBUG_OBJECT (element, "templ:%s, name:%s", templ->name_template, name);
706 /* Identify the stream group */
708 res = request_pad_for_stream (ebin, G_TYPE_NONE, name, (GstCaps *) caps);
712 GType ptype = G_TYPE_NONE;
714 if (!strcmp (templ->name_template, "video_%d"))
715 ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
716 else if (!strcmp (templ->name_template, "audio_%d"))
717 ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
718 /* else if (!strcmp (templ->name_template, "text_%d")) */
719 /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
721 /* FIXME : Check uniqueness of pad */
722 /* FIXME : Check that the requested number is the last one, and if not,
723 * update the last_pad_id variable so that we don't create a pad with
724 * the same name/number in the future */
726 res = request_pad_for_stream (ebin, ptype, name, NULL);
733 gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin, GstCaps * caps)
735 GstPad *pad = request_pad_for_stream (encodebin, G_TYPE_NONE, NULL, caps);
737 return pad ? GST_PAD_CAST (gst_object_ref (pad)) : NULL;
740 static inline StreamGroup *
741 find_stream_group_from_pad (GstEncodeBin * ebin, GstPad * pad)
745 for (tmp = ebin->streams; tmp; tmp = tmp->next) {
746 StreamGroup *sgroup = (StreamGroup *) tmp->data;
747 if (G_UNLIKELY (sgroup->ghostpad == pad))
755 gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
757 GstEncodeBin *ebin = (GstEncodeBin *) element;
760 /* Find the associated StreamGroup */
762 sgroup = find_stream_group_from_pad (ebin, pad);
763 if (G_UNLIKELY (sgroup == NULL))
764 goto no_stream_group;
766 /* Release objects/data associated with the StreamGroup */
767 stream_group_remove (ebin, sgroup);
773 GST_WARNING_OBJECT (ebin, "Couldn't find corresponding StreamGroup");
778 /* Create a parser for the given stream profile */
779 static inline GstElement *
780 _get_parser (GstEncodeBin * ebin, GstEncodingProfile * sprof)
782 GList *parsers1, *parsers, *tmp;
783 GstElement *parser = NULL;
784 GstElementFactory *parserfact = NULL;
785 const GstCaps *format;
787 format = gst_encoding_profile_get_format (sprof);
789 GST_DEBUG ("Getting list of parsers for format %" GST_PTR_FORMAT, format);
791 /* FIXME : requesting twice the parsers twice is a bit ugly, we should
792 * have a method to request on more than one condition */
794 gst_element_factory_list_filter (ebin->parsers, format,
797 gst_element_factory_list_filter (parsers1, format, GST_PAD_SINK, FALSE);
798 gst_plugin_feature_list_free (parsers1);
800 if (G_UNLIKELY (parsers == NULL)) {
801 GST_DEBUG ("Couldn't find any compatible parsers");
805 for (tmp = parsers; tmp; tmp = tmp->next) {
806 /* FIXME : We're only picking the first one so far */
807 /* FIXME : signal the user if he wants this */
808 parserfact = (GstElementFactory *) tmp->data;
813 parser = gst_element_factory_create (parserfact, NULL);
815 gst_plugin_feature_list_free (parsers);
821 _create_element_and_set_preset (GstElementFactory * factory,
822 const gchar * preset, const gchar * name)
824 GstElement *res = NULL;
826 GST_DEBUG ("Creating element from factory %s",
827 GST_PLUGIN_FEATURE_NAME (factory));
828 res = gst_element_factory_create (factory, name);
829 if (preset && GST_IS_PRESET (res) &&
830 !gst_preset_load_preset (GST_PRESET (res), preset)) {
831 GST_WARNING ("Couldn't set preset [%s] on element [%s]",
832 preset, GST_PLUGIN_FEATURE_NAME (factory));
833 gst_object_unref (res);
840 /* Create the encoder for the given stream profile */
841 static inline GstElement *
842 _get_encoder (GstEncodeBin * ebin, GstEncodingProfile * sprof)
844 GList *encoders, *tmp;
845 GstElement *encoder = NULL;
846 GstElementFactory *encoderfact = NULL;
847 const GstCaps *format;
850 format = gst_encoding_profile_get_format (sprof);
851 preset = gst_encoding_profile_get_preset (sprof);
853 GST_DEBUG ("Getting list of encoders for format %" GST_PTR_FORMAT, format);
855 /* If stream caps are raw, return identity */
856 if (G_UNLIKELY (are_raw_caps (format))) {
857 GST_DEBUG ("Stream format is raw, returning identity as the encoder");
858 encoder = gst_element_factory_make ("identity", NULL);
863 gst_element_factory_list_filter (ebin->encoders, format,
866 if (G_UNLIKELY (encoders == NULL)) {
867 GST_DEBUG ("Couldn't find any compatible encoders");
871 for (tmp = encoders; tmp; tmp = tmp->next) {
872 encoderfact = (GstElementFactory *) tmp->data;
873 if ((encoder = _create_element_and_set_preset (encoderfact, preset, NULL)))
877 gst_plugin_feature_list_free (encoders);
884 local_element_request_pad (GstElement * element, GstPadTemplate * templ,
887 GstPad *newpad = NULL;
888 GstElementClass *oclass;
890 oclass = GST_ELEMENT_GET_CLASS (element);
892 if (oclass->request_new_pad)
893 newpad = (oclass->request_new_pad) (element, templ, name);
896 gst_object_ref (newpad);
902 gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
905 GstPadPresence presence;
907 /* If this function is ever exported, we need check the validity of `element'
908 * and `templ', and to make sure the template actually belongs to the
911 presence = GST_PAD_TEMPLATE_PRESENCE (templ);
915 case GST_PAD_SOMETIMES:
916 ret = gst_element_get_static_pad (element, templ->name_template);
917 if (!ret && presence == GST_PAD_ALWAYS)
919 ("Element %s has an ALWAYS template %s, but no pad of the same name",
920 GST_OBJECT_NAME (element), templ->name_template);
923 case GST_PAD_REQUEST:
924 ret = gst_element_request_pad (element, templ, NULL, NULL);
931 /* FIXME : Improve algorithm for finding compatible muxer sink pad */
932 static inline GstPad *
933 get_compatible_muxer_sink_pad (GstEncodeBin * ebin, GstElement * encoder,
934 const GstCaps * sinkcaps)
937 GstPadTemplate *srctempl = NULL;
938 GstPadTemplate *sinktempl;
942 srcpad = gst_element_get_static_pad (encoder, "src");
944 srctempl = gst_pad_get_pad_template (srcpad);
946 GST_DEBUG_OBJECT (ebin,
947 "Attempting to find pad from muxer %s compatible with %s:%s",
948 GST_ELEMENT_NAME (ebin->muxer), GST_DEBUG_PAD_NAME (srcpad));
950 gst_object_unref (srcpad);
951 sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl);
954 gst_pad_template_new ("whatever", GST_PAD_SRC, GST_PAD_ALWAYS,
955 gst_caps_copy (sinkcaps));
956 g_assert (srctempl != NULL);
957 sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl);
958 g_object_unref (srctempl);
961 if (G_UNLIKELY (sinktempl == NULL))
964 sinkpad = gst_element_get_pad_from_template (ebin->muxer, sinktempl);
970 GST_WARNING_OBJECT (ebin, "No compatible pad available on muxer");
976 _has_class (GstElement * element, const gchar * classname)
978 GstElementClass *klass;
980 klass = GST_ELEMENT_GET_CLASS (element);
982 return strstr (klass->details.klass, classname) != NULL;
985 /* FIXME : Add handling of streams that don't need encoding */
986 /* FIXME : Add handling of streams that don't require conversion elements */
988 * Create the elements, StreamGroup, add the sink pad, link it to the muxer
990 * sinkpadname: If non-NULL, that name will be assigned to the sink ghost pad
991 * sinkcaps: If non-NULL will be used to figure out how to setup the group */
993 _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
994 const gchar * sinkpadname, GstCaps * sinkcaps)
996 StreamGroup *sgroup = NULL;
997 GstPad *sinkpad, *srcpad, *muxerpad = NULL;
998 /* Element we will link to the encoder */
999 GstElement *last = NULL;
1000 GList *tmp, *tosync = NULL;
1001 const GstCaps *format;
1002 const GstCaps *restriction;
1003 const gchar *missing_element_name;
1005 format = gst_encoding_profile_get_format (sprof);
1006 restriction = gst_encoding_profile_get_restriction (sprof);
1008 GST_DEBUG ("Creating group. format %" GST_PTR_FORMAT ", for caps %"
1009 GST_PTR_FORMAT, format, sinkcaps);
1010 GST_DEBUG ("avoid_reencoding:%d", ebin->avoid_reencoding);
1012 sgroup = g_slice_new0 (StreamGroup);
1013 sgroup->ebin = ebin;
1014 sgroup->profile = sprof;
1016 /* NOTE for people reading this code:
1018 * We construct the group starting by the furthest downstream element
1019 * and making our way up adding/syncing/linking as we go.
1021 * There are two parallel paths:
1022 * * One for raw data which goes through converters and encoders
1023 * * One for already encoded data
1026 /* Exception to the rule above:
1027 * We check if we have an available encoder so we can abort early */
1028 /* FIXME : What if we only want to do passthrough ??? */
1029 GST_LOG ("Checking for encoder availability");
1030 sgroup->encoder = _get_encoder (ebin, sprof);
1031 if (G_UNLIKELY (sgroup->encoder == NULL))
1035 * If we are handling a container profile, figure out if the muxer has a
1036 * sinkpad compatible with the selected profile */
1038 muxerpad = get_compatible_muxer_sink_pad (ebin, NULL, format);
1039 if (G_UNLIKELY (muxerpad == NULL))
1045 * We only use a 1buffer long queue here, the actual queueing will be done
1046 * in the input queue */
1047 last = sgroup->outqueue = gst_element_factory_make ("queue", NULL);
1048 g_object_set (sgroup->outqueue, "max-size-buffers", (guint32) 1,
1049 "max-size-bytes", (guint32) 0, "max-size-time", (guint64) 0,
1050 "silent", TRUE, NULL);
1052 gst_bin_add (GST_BIN (ebin), sgroup->outqueue);
1053 tosync = g_list_append (tosync, sgroup->outqueue);
1054 srcpad = gst_element_get_static_pad (sgroup->outqueue, "src");
1056 if (G_UNLIKELY (fast_pad_link (srcpad, muxerpad) != GST_PAD_LINK_OK)) {
1057 goto muxer_link_failure;
1059 gst_object_unref (muxerpad);
1061 gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), srcpad);
1063 gst_object_unref (srcpad);
1065 /* Check if we need a formatter
1066 * If we have no muxer or
1067 * if the muxer isn't a formatter and doesn't implement the tagsetter interface
1070 || (!gst_element_implements_interface (ebin->muxer, GST_TYPE_TAG_SETTER)
1071 && !_has_class (ebin->muxer, "Formatter"))) {
1072 sgroup->formatter = _get_formatter (ebin, sprof);
1073 if (sgroup->formatter) {
1074 GST_DEBUG ("Adding formatter for %" GST_PTR_FORMAT, format);
1076 gst_bin_add (GST_BIN (ebin), sgroup->formatter);
1077 tosync = g_list_append (tosync, sgroup->formatter);
1078 if (G_UNLIKELY (!fast_element_link (sgroup->formatter, last)))
1079 goto formatter_link_failure;
1080 last = sgroup->formatter;
1085 /* Output capsfilter
1086 * This will receive the format caps from the streamprofile */
1087 GST_DEBUG ("Adding output capsfilter for %" GST_PTR_FORMAT, format);
1088 sgroup->outfilter = gst_element_factory_make ("capsfilter", NULL);
1089 g_object_set (sgroup->outfilter, "caps", format, NULL);
1091 gst_bin_add (GST_BIN (ebin), sgroup->outfilter);
1092 tosync = g_list_append (tosync, sgroup->outfilter);
1093 if (G_UNLIKELY (!fast_element_link (sgroup->outfilter, last)))
1094 goto outfilter_link_failure;
1095 last = sgroup->outfilter;
1098 sgroup->parser = _get_parser (ebin, sprof);
1100 if (sgroup->parser != NULL) {
1101 GST_DEBUG ("Got a parser %s", GST_ELEMENT_NAME (sgroup->parser));
1102 gst_bin_add (GST_BIN (ebin), sgroup->parser);
1103 tosync = g_list_append (tosync, sgroup->parser);
1104 if (G_UNLIKELY (!gst_element_link (sgroup->parser, last)))
1105 goto parser_link_failure;
1106 last = sgroup->parser;
1109 /* Stream combiner */
1110 sgroup->combiner = g_object_new (GST_TYPE_STREAM_COMBINER, NULL);
1112 gst_bin_add (GST_BIN (ebin), sgroup->combiner);
1113 tosync = g_list_append (tosync, sgroup->combiner);
1114 if (G_UNLIKELY (!fast_element_link (sgroup->combiner, last)))
1115 goto combiner_link_failure;
1118 /* Stream splitter */
1119 sgroup->splitter = g_object_new (GST_TYPE_STREAM_SPLITTER, NULL);
1121 gst_bin_add (GST_BIN (ebin), sgroup->splitter);
1122 tosync = g_list_append (tosync, sgroup->splitter);
1125 * FIXME : figure out what max-size to use for the input queue */
1126 sgroup->inqueue = gst_element_factory_make ("queue", NULL);
1127 g_object_set (sgroup->inqueue, "max-size-buffers",
1128 (guint32) ebin->queue_buffers_max, "max-size-bytes",
1129 (guint32) ebin->queue_bytes_max, "max-size-time",
1130 (guint64) ebin->queue_time_max, "silent", TRUE, NULL);
1132 gst_bin_add (GST_BIN (ebin), sgroup->inqueue);
1133 tosync = g_list_append (tosync, sgroup->inqueue);
1134 if (G_UNLIKELY (!fast_element_link (sgroup->inqueue, sgroup->splitter)))
1135 goto splitter_link_failure;
1137 /* Expose input queue sink pad as ghostpad */
1138 sinkpad = gst_element_get_static_pad (sgroup->inqueue, "sink");
1139 if (sinkpadname == NULL) {
1141 g_strdup_printf ("%s_%d", gst_encoding_profile_get_type_nick (sprof),
1142 ebin->last_pad_id++);
1143 GST_DEBUG ("Adding ghost pad %s", pname);
1144 sgroup->ghostpad = gst_ghost_pad_new (pname, sinkpad);
1147 sgroup->ghostpad = gst_ghost_pad_new (sinkpadname, sinkpad);
1148 gst_object_unref (sinkpad);
1151 /* Path 1 : Already-encoded data */
1153 local_element_request_pad (sgroup->combiner, NULL, "passthroughsink");
1154 if (G_UNLIKELY (sinkpad == NULL))
1155 goto no_combiner_sinkpad;
1157 if (ebin->avoid_reencoding) {
1160 GST_DEBUG ("Asked to use Smart Encoder");
1161 sgroup->smartencoder = g_object_new (GST_TYPE_SMART_ENCODER, NULL);
1163 /* Check if stream format is compatible */
1164 srcpad = gst_element_get_static_pad (sgroup->smartencoder, "src");
1165 tmpcaps = gst_pad_get_caps_reffed (srcpad);
1166 if (!gst_caps_can_intersect (tmpcaps, format)) {
1167 GST_DEBUG ("We don't have a smart encoder for the stream format");
1168 gst_object_unref (sgroup->smartencoder);
1169 sgroup->smartencoder = NULL;
1171 gst_bin_add ((GstBin *) ebin, sgroup->smartencoder);
1172 fast_pad_link (srcpad, sinkpad);
1173 tosync = g_list_append (tosync, sgroup->smartencoder);
1174 sinkpad = gst_element_get_static_pad (sgroup->smartencoder, "sink");
1176 gst_caps_unref (tmpcaps);
1177 g_object_unref (srcpad);
1180 srcpad = local_element_request_pad (sgroup->splitter, NULL, "passthroughsrc");
1181 if (G_UNLIKELY (srcpad == NULL))
1182 goto no_splitter_srcpad;
1184 /* Go straight to splitter */
1185 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1186 goto passthrough_link_failure;
1187 g_object_unref (sinkpad);
1188 g_object_unref (srcpad);
1191 /* Path 2 : Conversion / Encoding */
1193 /* 1. Create the encoder */
1194 GST_LOG ("Adding encoder");
1195 last = sgroup->encoder;
1196 gst_bin_add ((GstBin *) ebin, sgroup->encoder);
1197 tosync = g_list_append (tosync, sgroup->encoder);
1199 sinkpad = local_element_request_pad (sgroup->combiner, NULL, "encodingsink");
1200 if (G_UNLIKELY (sinkpad == NULL))
1201 goto no_combiner_sinkpad;
1202 srcpad = gst_element_get_static_pad (sgroup->encoder, "src");
1203 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1204 goto encoder_link_failure;
1205 g_object_unref (sinkpad);
1206 g_object_unref (srcpad);
1209 /* 3. Create the conversion/restriction elements */
1210 /* 3.1. capsfilter */
1211 if (restriction && !gst_caps_is_any (restriction)) {
1212 GST_LOG ("Adding capsfilter for restriction caps : %" GST_PTR_FORMAT,
1215 last = sgroup->capsfilter = gst_element_factory_make ("capsfilter", NULL);
1216 g_object_set (sgroup->capsfilter, "caps", restriction, NULL);
1217 gst_bin_add ((GstBin *) ebin, sgroup->capsfilter);
1218 tosync = g_list_append (tosync, sgroup->capsfilter);
1219 fast_element_link (sgroup->capsfilter, sgroup->encoder);
1222 /* 3.2. restriction elements */
1223 /* FIXME : Once we have properties for specific converters, use those */
1224 if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) {
1225 const gboolean native_video =
1226 ! !(ebin->flags & GST_ENC_FLAG_NO_VIDEO_CONVERSION);
1227 GstElement *cspace = NULL, *scale, *vrate, *cspace2 = NULL;
1229 GST_LOG ("Adding conversion elements for video stream");
1231 if (!native_video) {
1232 cspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
1233 scale = gst_element_factory_make ("videoscale", NULL);
1235 missing_element_name = "videoscale";
1236 goto missing_element;
1238 /* 4-tap scaling and black borders */
1239 g_object_set (scale, "method", 2, "add-borders", TRUE, NULL);
1240 cspace2 = gst_element_factory_make ("ffmpegcolorspace", NULL);
1242 if (!cspace || !cspace2) {
1243 missing_element_name = "ffmpegcolorspace";
1244 goto missing_element;
1247 gst_bin_add_many ((GstBin *) ebin, cspace, scale, cspace2, NULL);
1248 tosync = g_list_append (tosync, cspace);
1249 tosync = g_list_append (tosync, scale);
1250 tosync = g_list_append (tosync, cspace2);
1252 sgroup->converters = g_list_prepend (sgroup->converters, cspace);
1253 sgroup->converters = g_list_prepend (sgroup->converters, scale);
1254 sgroup->converters = g_list_prepend (sgroup->converters, cspace2);
1256 if (!fast_element_link (cspace, scale) ||
1257 !fast_element_link (scale, cspace2))
1258 goto converter_link_failure;
1261 if (!gst_encoding_video_profile_get_variableframerate
1262 (GST_ENCODING_VIDEO_PROFILE (sprof))) {
1263 vrate = gst_element_factory_make ("videorate", NULL);
1265 missing_element_name = "videorate";
1266 goto missing_element;
1269 gst_bin_add ((GstBin *) ebin, vrate);
1270 tosync = g_list_prepend (tosync, vrate);
1271 sgroup->converters = g_list_prepend (sgroup->converters, vrate);
1273 if ((!native_video && !fast_element_link (cspace2, vrate))
1274 || !fast_element_link (vrate, last))
1275 goto converter_link_failure;
1281 } else if (!native_video) {
1282 if (!fast_element_link (cspace2, last))
1283 goto converter_link_failure;
1287 } else if (GST_IS_ENCODING_AUDIO_PROFILE (sprof)
1288 && !(ebin->flags & GST_ENC_FLAG_NO_AUDIO_CONVERSION)) {
1289 GstElement *aconv, *ares, *arate, *aconv2;
1291 GST_LOG ("Adding conversion elements for audio stream");
1293 arate = gst_element_factory_make ("audiorate", NULL);
1294 g_object_set (arate, "tolerance", (guint64) ebin->tolerance, NULL);
1296 missing_element_name = "audiorate";
1297 goto missing_element;
1299 aconv = gst_element_factory_make ("audioconvert", NULL);
1300 aconv2 = gst_element_factory_make ("audioconvert", NULL);
1301 ares = gst_element_factory_make ("audioresample", NULL);
1302 if (!aconv || !aconv2) {
1303 missing_element_name = "audioconvert";
1304 goto missing_element;
1307 missing_element_name = "audioresample";
1308 goto missing_element;
1311 gst_bin_add_many ((GstBin *) ebin, arate, aconv, ares, aconv2, NULL);
1312 tosync = g_list_append (tosync, arate);
1313 tosync = g_list_append (tosync, aconv);
1314 tosync = g_list_append (tosync, ares);
1315 tosync = g_list_append (tosync, aconv2);
1316 if (!fast_element_link (arate, aconv) ||
1317 !fast_element_link (aconv, ares) ||
1318 !fast_element_link (ares, aconv2) || !fast_element_link (aconv2, last))
1319 goto converter_link_failure;
1321 sgroup->converters = g_list_prepend (sgroup->converters, arate);
1322 sgroup->converters = g_list_prepend (sgroup->converters, aconv);
1323 sgroup->converters = g_list_prepend (sgroup->converters, ares);
1324 sgroup->converters = g_list_prepend (sgroup->converters, aconv2);
1329 /* Link to stream splitter */
1330 sinkpad = gst_element_get_static_pad (last, "sink");
1331 srcpad = local_element_request_pad (sgroup->splitter, NULL, "encodingsrc");
1332 if (G_UNLIKELY (srcpad == NULL))
1333 goto no_splitter_srcpad;
1334 if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1335 goto splitter_encoding_failure;
1336 g_object_unref (sinkpad);
1337 g_object_unref (srcpad);
1339 /* End of Stream 2 setup */
1341 /* Sync all elements to parent state */
1342 for (tmp = tosync; tmp; tmp = tmp->next)
1343 gst_element_sync_state_with_parent ((GstElement *) tmp->data);
1344 g_list_free (tosync);
1347 GST_DEBUG ("Adding ghostpad %s:%s", GST_DEBUG_PAD_NAME (sgroup->ghostpad));
1348 gst_pad_set_active (sgroup->ghostpad, TRUE);
1349 gst_element_add_pad ((GstElement *) ebin, sgroup->ghostpad);
1351 /* Add StreamGroup to our list of streams */
1354 ("Done creating elements, adding StreamGroup to our controlled stream list");
1356 ebin->streams = g_list_prepend (ebin->streams, sgroup);
1360 splitter_encoding_failure:
1361 GST_ERROR_OBJECT (ebin, "Error linking splitter to encoding stream");
1365 GST_ERROR_OBJECT (ebin, "Couldn't create encoder for format %" GST_PTR_FORMAT,
1367 /* missing plugin support */
1368 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1369 gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin), format));
1370 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL),
1371 ("Couldn't create encoder for format %" GST_PTR_FORMAT, format));
1375 GST_ERROR_OBJECT (ebin,
1376 "Couldn't find a compatible muxer pad to link encoder to");
1380 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1381 gst_missing_element_message_new (GST_ELEMENT_CAST (ebin),
1382 missing_element_name));
1383 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN,
1384 (_("Missing element '%s' - check your GStreamer installation."),
1385 missing_element_name), (NULL));
1388 encoder_link_failure:
1389 GST_ERROR_OBJECT (ebin, "Failed to link the encoder");
1393 GST_ERROR_OBJECT (ebin, "Couldn't link encoder to muxer");
1396 formatter_link_failure:
1397 GST_ERROR_OBJECT (ebin, "Couldn't link output filter to output queue");
1400 outfilter_link_failure:
1401 GST_ERROR_OBJECT (ebin,
1402 "Couldn't link output filter to output queue/formatter");
1405 passthrough_link_failure:
1406 GST_ERROR_OBJECT (ebin, "Failed linking splitter in passthrough mode");
1410 GST_ERROR_OBJECT (ebin, "Couldn't get a source pad from the splitter");
1413 no_combiner_sinkpad:
1414 GST_ERROR_OBJECT (ebin, "Couldn't get a sink pad from the combiner");
1417 splitter_link_failure:
1418 GST_ERROR_OBJECT (ebin, "Failure linking to the splitter");
1421 combiner_link_failure:
1422 GST_ERROR_OBJECT (ebin, "Failure linking to the combiner");
1425 parser_link_failure:
1426 GST_ERROR_OBJECT (ebin, "Failure linking the parser");
1429 converter_link_failure:
1430 GST_ERROR_OBJECT (ebin, "Failure linking the video converters");
1434 /* FIXME : Actually properly cleanup everything */
1435 g_slice_free (StreamGroup, sgroup);
1440 _gst_caps_match_foreach (GQuark field_id, const GValue * value, gpointer data)
1442 GstStructure *structure = data;
1443 const GValue *other_value = gst_structure_id_get_value (structure, field_id);
1445 if (G_UNLIKELY (other_value == NULL))
1447 if (gst_value_compare (value, other_value) == GST_VALUE_EQUAL) {
1455 * checks that there is at least one structure on caps_a that has
1456 * all its fields exactly the same as one structure on caps_b
1459 _gst_caps_match (const GstCaps * caps_a, const GstCaps * caps_b)
1462 gboolean res = FALSE;
1464 for (i = 0; i < gst_caps_get_size (caps_a); i++) {
1465 GstStructure *structure_a = gst_caps_get_structure (caps_a, i);
1466 for (j = 0; j < gst_caps_get_size (caps_b); j++) {
1467 GstStructure *structure_b = gst_caps_get_structure (caps_b, j);
1469 res = gst_structure_foreach (structure_a, _gst_caps_match_foreach,
1480 _factory_can_handle_caps (GstElementFactory * factory, const GstCaps * caps,
1481 GstPadDirection dir, gboolean exact)
1483 GList *templates = factory->staticpadtemplates;
1486 GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
1488 if (template->direction == dir) {
1489 GstCaps *tmp = gst_static_caps_get (&template->static_caps);
1491 if ((exact && _gst_caps_match (caps, tmp)) ||
1492 (!exact && gst_caps_can_intersect (tmp, caps))) {
1493 gst_caps_unref (tmp);
1496 gst_caps_unref (tmp);
1498 templates = g_list_next (templates);
1504 static inline GstElement *
1505 _get_formatter (GstEncodeBin * ebin, GstEncodingProfile * sprof)
1507 GList *formatters, *tmpfmtr;
1508 GstElement *formatter = NULL;
1509 GstElementFactory *formatterfact = NULL;
1510 const GstCaps *format;
1511 const gchar *preset;
1513 format = gst_encoding_profile_get_format (sprof);
1514 preset = gst_encoding_profile_get_preset (sprof);
1516 GST_DEBUG ("Getting list of formatters for format %" GST_PTR_FORMAT, format);
1519 gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
1522 if (formatters == NULL)
1525 /* FIXME : signal the user if he wants this */
1526 for (tmpfmtr = formatters; tmpfmtr; tmpfmtr = tmpfmtr->next) {
1527 formatterfact = (GstElementFactory *) tmpfmtr->data;
1529 GST_DEBUG_OBJECT (ebin, "Trying formatter %s",
1530 GST_PLUGIN_FEATURE_NAME (formatterfact));
1533 _create_element_and_set_preset (formatterfact, preset, NULL)))
1537 gst_plugin_feature_list_free (formatters);
1544 compare_elements (gconstpointer a, gconstpointer b, gpointer udata)
1546 GstCaps *caps = udata;
1547 GstElementFactory *fac_a = (GstElementFactory *) a;
1548 GstElementFactory *fac_b = (GstElementFactory *) b;
1550 /* FIXME not quite sure this is the best algorithm to order the elements
1551 * Some caps similarity comparison algorithm would fit better than going
1552 * boolean (equals/not equals).
1554 gboolean equals_a = _factory_can_handle_caps (fac_a, caps, GST_PAD_SRC, TRUE);
1555 gboolean equals_b = _factory_can_handle_caps (fac_b, caps, GST_PAD_SRC, TRUE);
1557 if (equals_a == equals_b) {
1558 return gst_plugin_feature_get_rank ((GstPluginFeature *) fac_b) -
1559 gst_plugin_feature_get_rank ((GstPluginFeature *) fac_a);
1560 } else if (equals_a) {
1562 } else if (equals_b) {
1568 static inline GstElement *
1569 _get_muxer (GstEncodeBin * ebin)
1571 GList *muxers, *formatters, *tmpmux;
1572 GstElement *muxer = NULL;
1573 GstElementFactory *muxerfact = NULL;
1575 const GstCaps *format;
1576 const gchar *preset;
1578 format = gst_encoding_profile_get_format (ebin->profile);
1579 preset = gst_encoding_profile_get_preset (ebin->profile);
1581 GST_DEBUG ("Getting list of muxers for format %" GST_PTR_FORMAT, format);
1584 gst_element_factory_list_filter (ebin->muxers, format, GST_PAD_SRC, TRUE);
1587 gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
1590 muxers = g_list_sort_with_data (muxers, compare_elements, (gpointer) format);
1592 g_list_sort_with_data (formatters, compare_elements, (gpointer) format);
1594 muxers = g_list_concat (muxers, formatters);
1599 /* FIXME : signal the user if he wants this */
1600 for (tmpmux = muxers; tmpmux; tmpmux = tmpmux->next) {
1601 gboolean cansinkstreams = TRUE;
1602 const GList *profiles =
1603 gst_encoding_container_profile_get_profiles
1604 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
1606 muxerfact = (GstElementFactory *) tmpmux->data;
1608 GST_DEBUG ("Trying muxer %s", GST_PLUGIN_FEATURE_NAME (muxerfact));
1610 /* See if the muxer can sink all of our stream profile caps */
1611 for (tmp = profiles; tmp; tmp = tmp->next) {
1612 GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
1614 if (!_factory_can_handle_caps (muxerfact,
1615 gst_encoding_profile_get_format (sprof), GST_PAD_SINK, FALSE)) {
1616 GST_DEBUG ("Skipping muxer because it can't sink caps %"
1617 GST_PTR_FORMAT, gst_encoding_profile_get_format (sprof));
1618 cansinkstreams = FALSE;
1623 /* Only use a muxer than can use all streams and than can accept the
1624 * preset (which may be present or not) */
1625 if (cansinkstreams && (muxer =
1626 _create_element_and_set_preset (muxerfact, preset, "muxer")))
1630 gst_plugin_feature_list_free (muxers);
1637 create_elements_and_pads (GstEncodeBin * ebin)
1639 gboolean ret = TRUE;
1640 GstElement *muxer = NULL;
1642 const GList *tmp, *profiles;
1643 GstEncodingProfile *sprof;
1645 GST_DEBUG ("Current profile : %s",
1646 gst_encoding_profile_get_name (ebin->profile));
1648 if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
1649 /* 1. Get the compatible muxer */
1650 muxer = _get_muxer (ebin);
1651 if (G_UNLIKELY (muxer == NULL))
1654 /* Record the muxer */
1655 ebin->muxer = muxer;
1656 gst_bin_add ((GstBin *) ebin, muxer);
1658 /* 2. Ghost the muxer source pad */
1660 /* FIXME : We should figure out if it's a static/request/dyamic pad,
1661 * but for the time being let's assume it's a static pad :) */
1662 muxerpad = gst_element_get_static_pad (muxer, "src");
1663 if (G_UNLIKELY (muxerpad == NULL))
1666 if (!gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), muxerpad))
1667 goto no_muxer_ghost_pad;
1669 gst_object_unref (muxerpad);
1670 /* 3. Activate fixed presence streams */
1672 gst_encoding_container_profile_get_profiles
1673 (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
1674 for (tmp = profiles; tmp; tmp = tmp->next) {
1675 sprof = (GstEncodingProfile *) tmp->data;
1677 GST_DEBUG ("Trying stream profile with presence %d",
1678 gst_encoding_profile_get_presence (sprof));
1680 if (gst_encoding_profile_get_presence (sprof) != 0) {
1681 if (G_UNLIKELY (_create_stream_group (ebin, sprof, NULL, NULL) == NULL))
1686 if (G_UNLIKELY (_create_stream_group (ebin, ebin->profile, NULL,
1695 GST_WARNING ("No available muxer for %" GST_PTR_FORMAT,
1696 gst_encoding_profile_get_format (ebin->profile));
1697 /* missing plugin support */
1698 gst_element_post_message (GST_ELEMENT_CAST (ebin),
1699 gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin),
1700 gst_encoding_profile_get_format (ebin->profile)));
1701 GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL),
1702 ("No available muxer for format %" GST_PTR_FORMAT,
1703 gst_encoding_profile_get_format (ebin->profile)));
1709 GST_WARNING ("Can't get source pad from muxer (%s)",
1710 GST_ELEMENT_NAME (muxer));
1711 gst_bin_remove (GST_BIN (ebin), muxer);
1717 GST_WARNING ("Couldn't set %s:%s as source ghostpad target",
1718 GST_DEBUG_PAD_NAME (muxerpad));
1719 gst_bin_remove (GST_BIN (ebin), muxer);
1720 gst_object_unref (muxerpad);
1726 GST_WARNING ("Could not create Streams");
1728 gst_bin_remove (GST_BIN (ebin), muxer);
1735 release_pads (GstPad * pad, GstElement * elt)
1737 GstPad *peer = NULL;
1739 GST_DEBUG_OBJECT (elt, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1741 /* Unlink from its peer pad */
1742 if ((peer = gst_pad_get_peer (pad))) {
1743 if (GST_PAD_DIRECTION (peer) == GST_PAD_SRC)
1744 gst_pad_unlink (peer, pad);
1746 gst_pad_unlink (pad, peer);
1747 gst_object_unref (peer);
1750 /* Release it from the object */
1751 gst_element_release_request_pad (elt, pad);
1753 /* And remove the reference added by the iterator */
1754 gst_object_unref (pad);
1758 stream_group_free (GstEncodeBin * ebin, StreamGroup * sgroup)
1764 GST_DEBUG_OBJECT (ebin, "Freeing StreamGroup %p", sgroup);
1767 /* outqueue - Muxer */
1768 tmppad = gst_element_get_static_pad (sgroup->outqueue, "src");
1769 pad = gst_pad_get_peer (tmppad);
1771 /* Remove muxer request sink pad */
1772 gst_pad_unlink (tmppad, pad);
1773 gst_element_release_request_pad (ebin->muxer, pad);
1774 gst_object_unref (tmppad);
1775 gst_object_unref (pad);
1777 if (sgroup->outqueue)
1778 gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
1780 if (sgroup->formatter) {
1781 /* capsfilter - formatter - outqueue */
1782 gst_element_set_state (sgroup->formatter, GST_STATE_NULL);
1783 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1784 gst_element_unlink (sgroup->formatter, sgroup->outqueue);
1785 gst_element_unlink (sgroup->outfilter, sgroup->formatter);
1787 /* Capsfilter - outqueue */
1788 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1789 gst_element_unlink (sgroup->outfilter, sgroup->outqueue);
1791 gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
1792 gst_bin_remove (GST_BIN (ebin), sgroup->outqueue);
1794 /* streamcombiner - parser - capsfilter */
1795 if (sgroup->parser) {
1796 gst_element_set_state (sgroup->parser, GST_STATE_NULL);
1797 gst_element_unlink (sgroup->parser, sgroup->outfilter);
1798 gst_element_unlink (sgroup->combiner, sgroup->parser);
1799 gst_bin_remove ((GstBin *) ebin, sgroup->parser);
1803 if (sgroup->ghostpad)
1804 gst_element_remove_pad (GST_ELEMENT_CAST (ebin), sgroup->ghostpad);
1806 if (sgroup->inqueue)
1807 gst_element_set_state (sgroup->inqueue, GST_STATE_NULL);
1809 if (sgroup->encoder)
1810 gst_element_set_state (sgroup->encoder, GST_STATE_NULL);
1811 if (sgroup->outfilter)
1812 gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1813 if (sgroup->smartencoder)
1814 gst_element_set_state (sgroup->smartencoder, GST_STATE_NULL);
1816 if (sgroup->capsfilter) {
1817 gst_element_set_state (sgroup->capsfilter, GST_STATE_NULL);
1818 gst_element_unlink (sgroup->capsfilter, sgroup->encoder);
1819 gst_bin_remove ((GstBin *) ebin, sgroup->capsfilter);
1822 for (tmp = sgroup->converters; tmp; tmp = tmp->next) {
1823 GstElement *elt = (GstElement *) tmp->data;
1825 gst_element_set_state (elt, GST_STATE_NULL);
1826 gst_bin_remove ((GstBin *) ebin, elt);
1828 if (sgroup->converters)
1829 g_list_free (sgroup->converters);
1831 if (sgroup->combiner) {
1832 GstIterator *it = gst_element_iterate_sink_pads (sgroup->combiner);
1833 GstIteratorResult itret = GST_ITERATOR_OK;
1835 while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
1836 itret = gst_iterator_foreach (it, (GFunc) release_pads, sgroup->combiner);
1837 gst_iterator_resync (it);
1839 gst_iterator_free (it);
1840 gst_element_set_state (sgroup->combiner, GST_STATE_NULL);
1841 gst_bin_remove ((GstBin *) ebin, sgroup->combiner);
1844 if (sgroup->splitter) {
1845 GstIterator *it = gst_element_iterate_src_pads (sgroup->splitter);
1846 GstIteratorResult itret = GST_ITERATOR_OK;
1847 while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
1848 itret = gst_iterator_foreach (it, (GFunc) release_pads, sgroup->splitter);
1849 gst_iterator_resync (it);
1851 gst_iterator_free (it);
1853 gst_element_set_state (sgroup->splitter, GST_STATE_NULL);
1854 gst_bin_remove ((GstBin *) ebin, sgroup->splitter);
1857 if (sgroup->inqueue)
1858 gst_bin_remove ((GstBin *) ebin, sgroup->inqueue);
1860 if (sgroup->encoder)
1861 gst_bin_remove ((GstBin *) ebin, sgroup->encoder);
1863 if (sgroup->smartencoder)
1864 gst_bin_remove ((GstBin *) ebin, sgroup->smartencoder);
1866 if (sgroup->outfilter)
1867 gst_bin_remove ((GstBin *) ebin, sgroup->outfilter);
1869 g_slice_free (StreamGroup, sgroup);
1873 stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup)
1875 ebin->streams = g_list_remove (ebin->streams, sgroup);
1877 stream_group_free (ebin, sgroup);
1881 gst_encode_bin_tear_down_profile (GstEncodeBin * ebin)
1883 if (G_UNLIKELY (ebin->profile == NULL))
1886 GST_DEBUG ("Tearing down profile %s",
1887 gst_encoding_profile_get_name (ebin->profile));
1889 while (ebin->streams)
1890 stream_group_remove (ebin, (StreamGroup *) ebin->streams->data);
1892 /* Set ghostpad target to NULL */
1893 gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), NULL);
1895 /* Remove muxer if present */
1897 gst_element_set_state (ebin->muxer, GST_STATE_NULL);
1898 gst_bin_remove (GST_BIN (ebin), ebin->muxer);
1902 /* free/clear profile */
1903 gst_encoding_profile_unref (ebin->profile);
1904 ebin->profile = NULL;
1908 gst_encode_bin_setup_profile (GstEncodeBin * ebin, GstEncodingProfile * profile)
1912 g_return_val_if_fail (ebin->profile == NULL, FALSE);
1914 GST_DEBUG ("Setting up profile %s (type:%s)",
1915 gst_encoding_profile_get_name (profile),
1916 gst_encoding_profile_get_type_nick (profile));
1918 ebin->profile = profile;
1919 gst_mini_object_ref ((GstMiniObject *) ebin->profile);
1921 /* Create elements */
1922 res = create_elements_and_pads (ebin);
1924 gst_encode_bin_tear_down_profile (ebin);
1930 gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile)
1932 g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
1934 GST_DEBUG_OBJECT (ebin, "profile : %s",
1935 gst_encoding_profile_get_name (profile));
1937 if (G_UNLIKELY (ebin->active)) {
1938 GST_WARNING_OBJECT (ebin, "Element already active, can't change profile");
1942 /* If we're not active, we can deactivate the previous profile */
1943 if (ebin->profile) {
1944 gst_encode_bin_tear_down_profile (ebin);
1947 return gst_encode_bin_setup_profile (ebin, profile);
1950 static inline gboolean
1951 gst_encode_bin_activate (GstEncodeBin * ebin)
1953 ebin->active = ebin->profile != NULL;
1954 return ebin->active;
1958 gst_encode_bin_deactivate (GstEncodeBin * ebin)
1960 ebin->active = FALSE;
1963 static GstStateChangeReturn
1964 gst_encode_bin_change_state (GstElement * element, GstStateChange transition)
1966 GstStateChangeReturn ret;
1967 GstEncodeBin *ebin = (GstEncodeBin *) element;
1969 switch (transition) {
1970 case GST_STATE_CHANGE_READY_TO_PAUSED:
1971 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1972 if (!gst_encode_bin_activate (ebin)) {
1973 ret = GST_STATE_CHANGE_FAILURE;
1982 GST_ELEMENT_CLASS (gst_encode_bin_parent_class)->change_state (element,
1984 if (ret == GST_STATE_CHANGE_FAILURE)
1987 switch (transition) {
1988 case GST_STATE_CHANGE_PAUSED_TO_READY:
1989 gst_encode_bin_deactivate (ebin);
2001 plugin_init (GstPlugin * plugin)
2005 GST_DEBUG_CATEGORY_INIT (gst_encode_bin_debug, "encodebin", 0, "encoder bin");
2008 GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
2010 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
2011 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2012 #endif /* ENABLE_NLS */
2015 res = gst_element_register (plugin, "encodebin", GST_RANK_NONE,
2016 GST_TYPE_ENCODE_BIN);
2021 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2024 "various encoding-related elements", plugin_init, VERSION, GST_LICENSE,
2025 GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)