3a88603548f837ba83c3721cdbe9e599d0bd404f
[platform/upstream/gst-plugins-base.git] / gst / encoding / gstencodebin.c
1 /* GStreamer encoding bin
2  * Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
3  *           (C) 2009 Nokia Corporation
4  *
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.
9  *
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.
14  *
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., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <string.h>
26 #include "gstencodebin.h"
27 #include "gstsmartencoder.h"
28 #include "gststreamsplitter.h"
29 #include "gststreamcombiner.h"
30 #include <gst/gst-i18n-plugin.h>
31
32 /**
33  * SECTION:element-encodebin
34  *
35  * EncodeBin provides a bin for encoding/muxing various streams according to
36  * a specified #GstEncodingProfile.
37  *
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.
43  *
44  * <refsect2>
45  * <title>Features</title>
46  * <itemizedlist>
47  * <listitem>
48  * Automatic encoder and muxer selection based on elements available on the
49  * system.
50  * </listitem>
51  * <listitem>
52  * Conversion of raw audio/video streams (scaling, framerate conversion,
53  * colorspace conversion, samplerate conversion) to conform to the profile
54  * output format.
55  * </listitem>
56  * <listitem>
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
60  * signal.
61  * </listitem>
62  * <listitem>
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.
66  * </listitem>
67  * <listitem>
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.
72  * </listitem>
73  * <listitem>
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.
78  * </listitem>
79  * <listitem>
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.
84  * </listitem>
85  * <listitem>
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
89  * framerate.
90  * </listitem>
91  * <listitem>
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.
96  * </listitem>
97  * <listitem>
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.
102  * </listitem>
103  * </itemizedlist>
104  * </refsect2>
105  */
106
107
108 /* TODO/FIXME
109  *
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
116  **/
117
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)
120
121 typedef enum
122 {
123   GST_ENCODEBIN_FLAG_NO_AUDIO_CONVERSION = (1 << 0),
124   GST_ENCODEBIN_FLAG_NO_VIDEO_CONVERSION = (1 << 1)
125 } GstEncodeBinFlags;
126
127 #define GST_TYPE_ENCODEBIN_FLAGS (gst_encodebin_flags_get_type())
128 GType gst_encodebin_flags_get_type (void);
129
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);
134
135 static GstStaticPadTemplate video_sink_template =
136 GST_STATIC_PAD_TEMPLATE ("video_%u",
137     GST_PAD_SINK,
138     GST_PAD_REQUEST,
139     GST_STATIC_CAPS_ANY);
140 static GstStaticPadTemplate audio_sink_template =
141 GST_STATIC_PAD_TEMPLATE ("audio_%u",
142     GST_PAD_SINK,
143     GST_PAD_REQUEST,
144     GST_STATIC_CAPS_ANY);
145 /* static GstStaticPadTemplate text_sink_template = */
146 /* GST_STATIC_PAD_TEMPLATE ("text_%u", */
147 /*     GST_PAD_SINK, */
148 /*     GST_PAD_REQUEST, */
149 /*     GST_STATIC_CAPS_ANY); */
150 static GstStaticPadTemplate private_sink_template =
151 GST_STATIC_PAD_TEMPLATE ("private_%u",
152     GST_PAD_SINK,
153     GST_PAD_REQUEST,
154     GST_STATIC_CAPS_ANY);
155
156 struct _GstEncodeBin
157 {
158   GstBin parent;
159
160   /* the profile field is only valid if it could be entirely setup */
161   GstEncodingProfile *profile;
162
163   GList *streams;               /* List of StreamGroup, not sorted */
164
165   GstElement *muxer;
166   /* Ghostpad with changing target */
167   GstPad *srcpad;
168
169   /* TRUE if in PAUSED/PLAYING */
170   gboolean active;
171
172   /* available muxers, encoders and parsers */
173   GList *muxers;
174   GList *formatters;
175   GList *encoders;
176   GList *parsers;
177
178   /* Increasing counter for unique pad name */
179   guint last_pad_id;
180
181   /* Cached caps for identification */
182   GstCaps *raw_video_caps;
183   GstCaps *raw_audio_caps;
184   /* GstCaps *raw_text_caps; */
185
186   guint queue_buffers_max;
187   guint queue_bytes_max;
188   guint64 queue_time_max;
189
190   guint64 tolerance;
191   gboolean avoid_reencoding;
192
193   GstEncodeBinFlags flags;
194 };
195
196 struct _GstEncodeBinClass
197 {
198   GstBinClass parent;
199
200   /* Action Signals */
201   GstPad *(*request_pad) (GstEncodeBin * encodebin, GstCaps * caps);
202   GstPad *(*request_profile_pad) (GstEncodeBin * encodebin,
203       const gchar * profilename);
204 };
205
206 typedef struct _StreamGroup StreamGroup;
207
208 struct _StreamGroup
209 {
210   GstEncodeBin *ebin;
211   GstEncodingProfile *profile;
212   GstPad *ghostpad;             /* Sink ghostpad */
213   GstElement *inqueue;          /* Queue just after the ghostpad */
214   GstElement *splitter;
215   GList *converters;            /* List of conversion GstElement */
216   GstElement *capsfilter;       /* profile->restriction (if non-NULL/ANY) */
217   GstElement *encoder;          /* Encoder (can be NULL) */
218   GstElement *fakesink;         /* Fakesink (can be NULL) */
219   GstElement *combiner;
220   GstElement *parser;
221   GstElement *smartencoder;
222   GstElement *outfilter;        /* Output capsfilter (streamprofile.format) */
223   GstElement *formatter;
224   GstElement *outqueue;         /* Queue just before the muxer */
225   gulong restriction_sid;
226 };
227
228 /* Default for queues (same defaults as queue element) */
229 #define DEFAULT_QUEUE_BUFFERS_MAX  200
230 #define DEFAULT_QUEUE_BYTES_MAX    10 * 1024 * 1024
231 #define DEFAULT_QUEUE_TIME_MAX     GST_SECOND
232 #define DEFAULT_AUDIO_JITTER_TOLERANCE 20 * GST_MSECOND
233 #define DEFAULT_AVOID_REENCODING   FALSE
234 #define DEFAULT_FLAGS              0
235
236 #define DEFAULT_RAW_CAPS                        \
237   "video/x-raw; "                               \
238   "audio/x-raw; "                               \
239   "text/x-raw; "                                \
240   "subpicture/x-dvd; "                  \
241   "subpicture/x-pgs"
242
243 /* Properties */
244 enum
245 {
246   PROP_0,
247   PROP_PROFILE,
248   PROP_QUEUE_BUFFERS_MAX,
249   PROP_QUEUE_BYTES_MAX,
250   PROP_QUEUE_TIME_MAX,
251   PROP_AUDIO_JITTER_TOLERANCE,
252   PROP_AVOID_REENCODING,
253   PROP_FLAGS,
254   PROP_LAST
255 };
256
257 /* Signals */
258 enum
259 {
260   SIGNAL_REQUEST_PAD,
261   SIGNAL_REQUEST_PROFILE_PAD,
262   LAST_SIGNAL
263 };
264
265 #define C_FLAGS(v) ((guint) v)
266
267 GType
268 gst_encodebin_flags_get_type (void)
269 {
270   static const GFlagsValue values[] = {
271     {C_FLAGS (GST_ENCODEBIN_FLAG_NO_AUDIO_CONVERSION), "Do not use audio "
272           "conversion elements", "no-audio-conversion"},
273     {C_FLAGS (GST_ENCODEBIN_FLAG_NO_VIDEO_CONVERSION), "Do not use video "
274           "conversion elements", "no-video-conversion"},
275     {0, NULL, NULL}
276   };
277   static volatile GType id = 0;
278
279   if (g_once_init_enter ((gsize *) & id)) {
280     GType _id;
281
282     _id = g_flags_register_static ("GstEncodeBinFlags", values);
283
284     g_once_init_leave ((gsize *) & id, _id);
285   }
286
287   return id;
288 }
289
290 static guint gst_encode_bin_signals[LAST_SIGNAL] = { 0 };
291
292 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
293
294 GST_DEBUG_CATEGORY_STATIC (gst_encode_bin_debug);
295 #define GST_CAT_DEFAULT gst_encode_bin_debug
296
297 G_DEFINE_TYPE (GstEncodeBin, gst_encode_bin, GST_TYPE_BIN);
298
299 static void gst_encode_bin_dispose (GObject * object);
300 static void gst_encode_bin_set_property (GObject * object, guint prop_id,
301     const GValue * value, GParamSpec * pspec);
302 static void gst_encode_bin_get_property (GObject * object, guint prop_id,
303     GValue * value, GParamSpec * pspec);
304 static GstStateChangeReturn gst_encode_bin_change_state (GstElement * element,
305     GstStateChange transition);
306
307 static GstPad *gst_encode_bin_request_new_pad (GstElement * element,
308     GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
309 static void gst_encode_bin_release_pad (GstElement * element, GstPad * pad);
310
311 static gboolean
312 gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile);
313 static void gst_encode_bin_tear_down_profile (GstEncodeBin * ebin);
314 static gboolean gst_encode_bin_setup_profile (GstEncodeBin * ebin,
315     GstEncodingProfile * profile);
316
317 static StreamGroup *_create_stream_group (GstEncodeBin * ebin,
318     GstEncodingProfile * sprof, const gchar * sinkpadname, GstCaps * sinkcaps);
319 static void stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup);
320 static void stream_group_free (GstEncodeBin * ebin, StreamGroup * sgroup);
321 static GstPad *gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin,
322     GstCaps * caps);
323 static GstPad *gst_encode_bin_request_profile_pad_signal (GstEncodeBin *
324     encodebin, const gchar * profilename);
325
326 static inline GstElement *_get_formatter (GstEncodeBin * ebin,
327     GstEncodingProfile * sprof);
328
329 static void
330 gst_encode_bin_class_init (GstEncodeBinClass * klass)
331 {
332   GObjectClass *gobject_klass;
333   GstElementClass *gstelement_klass;
334
335   gobject_klass = (GObjectClass *) klass;
336   gstelement_klass = (GstElementClass *) klass;
337
338   gobject_klass->dispose = gst_encode_bin_dispose;
339   gobject_klass->set_property = gst_encode_bin_set_property;
340   gobject_klass->get_property = gst_encode_bin_get_property;
341
342   /* Properties */
343
344   /**
345    * GstEncodeBin:profile:
346    *
347    * The #GstEncodingProfile to use. This property must be set before going
348    * to %GST_STATE_PAUSED or higher.
349    */
350   g_object_class_install_property (gobject_klass, PROP_PROFILE,
351       g_param_spec_object ("profile", "Profile",
352           "The GstEncodingProfile to use", GST_TYPE_ENCODING_PROFILE,
353           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
354
355   g_object_class_install_property (gobject_klass, PROP_QUEUE_BYTES_MAX,
356       g_param_spec_uint ("queue-bytes-max", "Max. size (kB)",
357           "Max. amount of data in the queue (bytes, 0=disable)",
358           0, G_MAXUINT, DEFAULT_QUEUE_BYTES_MAX,
359           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
360
361   g_object_class_install_property (gobject_klass, PROP_QUEUE_BUFFERS_MAX,
362       g_param_spec_uint ("queue-buffers-max", "Max. size (buffers)",
363           "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
364           DEFAULT_QUEUE_BUFFERS_MAX,
365           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
366
367   g_object_class_install_property (gobject_klass, PROP_QUEUE_TIME_MAX,
368       g_param_spec_uint64 ("queue-time-max", "Max. size (ns)",
369           "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
370           DEFAULT_QUEUE_TIME_MAX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
371
372   g_object_class_install_property (gobject_klass, PROP_AUDIO_JITTER_TOLERANCE,
373       g_param_spec_uint64 ("audio-jitter-tolerance", "Audio jitter tolerance",
374           "Amount of timestamp jitter/imperfection to allow on audio streams before inserting/dropping samples (ns)",
375           0, G_MAXUINT64, DEFAULT_AUDIO_JITTER_TOLERANCE,
376           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
377
378   g_object_class_install_property (gobject_klass, PROP_AVOID_REENCODING,
379       g_param_spec_boolean ("avoid-reencoding", "Avoid re-encoding",
380           "Whether to re-encode portions of compatible video streams that lay on segment boundaries",
381           DEFAULT_AVOID_REENCODING,
382           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
383
384   /**
385    * GstEncodeBin:flags
386    *
387    * Control the behaviour of encodebin.
388    */
389   g_object_class_install_property (gobject_klass, PROP_FLAGS,
390       g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
391           GST_TYPE_ENCODEBIN_FLAGS, DEFAULT_FLAGS,
392           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
393
394   /* Signals */
395   /**
396    * GstEncodeBin::request-pad
397    * @encodebin: a #GstEncodeBin instance
398    * @caps: a #GstCaps
399    *
400    * Use this method to request an unused sink request #GstPad that can take the
401    * provided @caps as input. You must release the pad with
402    * gst_element_release_request_pad() when you are done with it.
403    *
404    * Returns: A compatible #GstPad, or %NULL if no compatible #GstPad could be
405    * created or is available.
406    */
407   gst_encode_bin_signals[SIGNAL_REQUEST_PAD] =
408       g_signal_new ("request-pad", G_TYPE_FROM_CLASS (klass),
409       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstEncodeBinClass,
410           request_pad), NULL, NULL, g_cclosure_marshal_generic,
411       GST_TYPE_PAD, 1, GST_TYPE_CAPS);
412
413   /**
414    * GstEncodeBin::request-profile-pad
415    * @encodebin: a #GstEncodeBin instance
416    * @profilename: the name of a #GstEncodingProfile
417    *
418    * Use this method to request an unused sink request #GstPad from the profile
419    * @profilename. You must release the pad with
420    * gst_element_release_request_pad() when you are done with it.
421    *
422    * Returns: A compatible #GstPad, or %NULL if no compatible #GstPad could be
423    * created or is available.
424    */
425   gst_encode_bin_signals[SIGNAL_REQUEST_PROFILE_PAD] =
426       g_signal_new ("request-profile-pad", G_TYPE_FROM_CLASS (klass),
427       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstEncodeBinClass,
428           request_profile_pad), NULL, NULL, g_cclosure_marshal_generic,
429       GST_TYPE_PAD, 1, G_TYPE_STRING);
430
431   klass->request_pad = gst_encode_bin_request_pad_signal;
432   klass->request_profile_pad = gst_encode_bin_request_profile_pad_signal;
433
434   gst_element_class_add_pad_template (gstelement_klass,
435       gst_static_pad_template_get (&muxer_src_template));
436   gst_element_class_add_pad_template (gstelement_klass,
437       gst_static_pad_template_get (&video_sink_template));
438   gst_element_class_add_pad_template (gstelement_klass,
439       gst_static_pad_template_get (&audio_sink_template));
440   /* gst_element_class_add_pad_template (gstelement_klass, */
441   /*     gst_static_pad_template_get (&text_sink_template)); */
442   gst_element_class_add_pad_template (gstelement_klass,
443       gst_static_pad_template_get (&private_sink_template));
444
445   gstelement_klass->change_state =
446       GST_DEBUG_FUNCPTR (gst_encode_bin_change_state);
447   gstelement_klass->request_new_pad =
448       GST_DEBUG_FUNCPTR (gst_encode_bin_request_new_pad);
449   gstelement_klass->release_pad =
450       GST_DEBUG_FUNCPTR (gst_encode_bin_release_pad);
451
452   gst_element_class_set_static_metadata (gstelement_klass,
453       "Encoder Bin",
454       "Generic/Bin/Encoder",
455       "Convenience encoding/muxing element",
456       "Edward Hervey <edward.hervey@collabora.co.uk>");
457 }
458
459 static void
460 gst_encode_bin_dispose (GObject * object)
461 {
462   GstEncodeBin *ebin = (GstEncodeBin *) object;
463
464   if (ebin->muxers)
465     gst_plugin_feature_list_free (ebin->muxers);
466
467   if (ebin->formatters)
468     gst_plugin_feature_list_free (ebin->formatters);
469
470   if (ebin->encoders)
471     gst_plugin_feature_list_free (ebin->encoders);
472
473   if (ebin->parsers)
474     gst_plugin_feature_list_free (ebin->parsers);
475
476   gst_encode_bin_tear_down_profile (ebin);
477
478   if (ebin->raw_video_caps)
479     gst_caps_unref (ebin->raw_video_caps);
480   if (ebin->raw_audio_caps)
481     gst_caps_unref (ebin->raw_audio_caps);
482   /* if (ebin->raw_text_caps) */
483   /*   gst_caps_unref (ebin->raw_text_caps); */
484
485   G_OBJECT_CLASS (gst_encode_bin_parent_class)->dispose (object);
486 }
487
488 static void
489 gst_encode_bin_init (GstEncodeBin * encode_bin)
490 {
491   GstPadTemplate *tmpl;
492
493   encode_bin->muxers =
494       gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER,
495       GST_RANK_MARGINAL);
496
497   encode_bin->formatters =
498       gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_FORMATTER,
499       GST_RANK_SECONDARY);
500
501   encode_bin->encoders =
502       gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER,
503       GST_RANK_MARGINAL);
504
505   encode_bin->parsers =
506       gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_PARSER,
507       GST_RANK_MARGINAL);
508
509   encode_bin->raw_video_caps = gst_caps_from_string ("video/x-raw");
510   encode_bin->raw_audio_caps = gst_caps_from_string ("audio/x-raw");
511   /* encode_bin->raw_text_caps = */
512   /*     gst_caps_from_string ("text/x-raw"); */
513
514   encode_bin->queue_buffers_max = DEFAULT_QUEUE_BUFFERS_MAX;
515   encode_bin->queue_bytes_max = DEFAULT_QUEUE_BYTES_MAX;
516   encode_bin->queue_time_max = DEFAULT_QUEUE_TIME_MAX;
517   encode_bin->tolerance = DEFAULT_AUDIO_JITTER_TOLERANCE;
518   encode_bin->avoid_reencoding = DEFAULT_AVOID_REENCODING;
519   encode_bin->flags = DEFAULT_FLAGS;
520
521   tmpl = gst_static_pad_template_get (&muxer_src_template);
522   encode_bin->srcpad = gst_ghost_pad_new_no_target_from_template ("src", tmpl);
523   gst_object_unref (tmpl);
524   gst_pad_set_active (encode_bin->srcpad, TRUE);
525   gst_element_add_pad (GST_ELEMENT_CAST (encode_bin), encode_bin->srcpad);
526 }
527
528 static void
529 gst_encode_bin_set_property (GObject * object, guint prop_id,
530     const GValue * value, GParamSpec * pspec)
531 {
532   GstEncodeBin *ebin = (GstEncodeBin *) object;
533
534   switch (prop_id) {
535     case PROP_PROFILE:
536       gst_encode_bin_set_profile (ebin,
537           (GstEncodingProfile *) g_value_get_object (value));
538       break;
539     case PROP_QUEUE_BUFFERS_MAX:
540       ebin->queue_buffers_max = g_value_get_uint (value);
541       break;
542     case PROP_QUEUE_BYTES_MAX:
543       ebin->queue_bytes_max = g_value_get_uint (value);
544       break;
545     case PROP_QUEUE_TIME_MAX:
546       ebin->queue_time_max = g_value_get_uint64 (value);
547       break;
548     case PROP_AUDIO_JITTER_TOLERANCE:
549       ebin->tolerance = g_value_get_uint64 (value);
550       break;
551     case PROP_AVOID_REENCODING:
552       ebin->avoid_reencoding = g_value_get_boolean (value);
553       break;
554     case PROP_FLAGS:
555       ebin->flags = g_value_get_flags (value);
556       break;
557     default:
558       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
559       break;
560   }
561 }
562
563 static void
564 gst_encode_bin_get_property (GObject * object, guint prop_id,
565     GValue * value, GParamSpec * pspec)
566 {
567   GstEncodeBin *ebin = (GstEncodeBin *) object;
568
569   switch (prop_id) {
570     case PROP_PROFILE:
571       g_value_set_object (value, (GObject *) ebin->profile);
572       break;
573     case PROP_QUEUE_BUFFERS_MAX:
574       g_value_set_uint (value, ebin->queue_buffers_max);
575       break;
576     case PROP_QUEUE_BYTES_MAX:
577       g_value_set_uint (value, ebin->queue_bytes_max);
578       break;
579     case PROP_QUEUE_TIME_MAX:
580       g_value_set_uint64 (value, ebin->queue_time_max);
581       break;
582     case PROP_AUDIO_JITTER_TOLERANCE:
583       g_value_set_uint64 (value, ebin->tolerance);
584       break;
585     case PROP_AVOID_REENCODING:
586       g_value_set_boolean (value, ebin->avoid_reencoding);
587       break;
588     case PROP_FLAGS:
589       g_value_set_flags (value, ebin->flags);
590       break;
591     default:
592       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
593       break;
594   }
595 }
596
597 static inline gboolean
598 are_raw_caps (const GstCaps * caps)
599 {
600   GstCaps *raw = gst_static_caps_get (&default_raw_caps);
601
602   if (gst_caps_can_intersect (caps, raw)) {
603     gst_caps_unref (raw);
604     return TRUE;
605   }
606   gst_caps_unref (raw);
607   return FALSE;
608 }
609
610 /* Returns the number of time a given stream profile is currently used
611  * in encodebin */
612 static inline guint
613 stream_profile_used_count (GstEncodeBin * ebin, GstEncodingProfile * sprof)
614 {
615   guint nbprofused = 0;
616   GList *tmp;
617
618   for (tmp = ebin->streams; tmp; tmp = tmp->next) {
619     StreamGroup *sgroup = (StreamGroup *) tmp->data;
620
621     if (sgroup->profile == sprof)
622       nbprofused++;
623   }
624
625   return nbprofused;
626 }
627
628 static inline GstEncodingProfile *
629 next_unused_stream_profile (GstEncodeBin * ebin, GType ptype,
630     const gchar * name, GstCaps * caps)
631 {
632   GST_DEBUG_OBJECT (ebin, "ptype:%s, caps:%" GST_PTR_FORMAT,
633       g_type_name (ptype), caps);
634
635   if (G_UNLIKELY (ptype == G_TYPE_NONE && caps != NULL)) {
636     /* Identify the profile type based on raw caps */
637     if (gst_caps_can_intersect (ebin->raw_video_caps, caps))
638       ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
639     else if (gst_caps_can_intersect (ebin->raw_audio_caps, caps))
640       ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
641     /* else if (gst_caps_can_intersect (ebin->raw_text_caps, caps)) */
642     /*   ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
643     GST_DEBUG_OBJECT (ebin, "Detected profile type as being %s",
644         g_type_name (ptype));
645   }
646
647   if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
648     const GList *tmp;
649
650     if (name) {
651       /* If we have a name, try to find a profile with the same name */
652       tmp =
653           gst_encoding_container_profile_get_profiles
654           (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
655
656       for (; tmp; tmp = tmp->next) {
657         GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
658         const gchar *profilename = gst_encoding_profile_get_name (sprof);
659
660         if (profilename && !strcmp (name, profilename)) {
661           guint presence = gst_encoding_profile_get_presence (sprof);
662           GST_DEBUG ("Found profile matching the requested name");
663
664           if (presence == 0
665               || presence > stream_profile_used_count (ebin, sprof))
666             return sprof;
667
668           GST_WARNING ("Matching stream already used");
669           return NULL;
670         }
671       }
672       GST_DEBUG
673           ("No profiles matching requested pad name, carrying on with normal stream matching");
674     }
675
676     for (tmp =
677         gst_encoding_container_profile_get_profiles
678         (GST_ENCODING_CONTAINER_PROFILE (ebin->profile)); tmp;
679         tmp = tmp->next) {
680       GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
681
682       /* Pick an available Stream profile for which:
683        * * either it is of the compatible raw type,
684        * * OR we can pass it through directly without encoding
685        */
686       if (G_TYPE_FROM_INSTANCE (sprof) == ptype) {
687         guint presence = gst_encoding_profile_get_presence (sprof);
688         GST_DEBUG ("Found a stream profile with the same type");
689         if (presence == 0
690             || (presence > stream_profile_used_count (ebin, sprof)))
691           return sprof;
692       } else if (caps && ptype == G_TYPE_NONE) {
693         GstCaps *outcaps;
694         gboolean res;
695
696         outcaps = gst_encoding_profile_get_input_caps (sprof);
697         GST_DEBUG ("Unknown stream, seeing if it's compatible with %"
698             GST_PTR_FORMAT, outcaps);
699         res = gst_caps_can_intersect (outcaps, caps);
700         gst_caps_unref (outcaps);
701
702         if (res)
703           return sprof;
704       }
705     }
706   }
707
708   return NULL;
709 }
710
711 static GstPad *
712 request_pad_for_stream (GstEncodeBin * encodebin, GType ptype,
713     const gchar * name, GstCaps * caps)
714 {
715   StreamGroup *sgroup;
716   GstEncodingProfile *sprof;
717
718   GST_DEBUG_OBJECT (encodebin, "name:%s caps:%" GST_PTR_FORMAT, name, caps);
719
720   /* Figure out if we have a unused GstEncodingProfile we can use for
721    * these caps */
722   sprof = next_unused_stream_profile (encodebin, ptype, name, caps);
723
724   if (G_UNLIKELY (sprof == NULL))
725     goto no_stream_profile;
726
727   sgroup = _create_stream_group (encodebin, sprof, name, caps);
728   if (G_UNLIKELY (sgroup == NULL))
729     goto no_stream_group;
730
731   return sgroup->ghostpad;
732
733 no_stream_profile:
734   {
735     GST_WARNING_OBJECT (encodebin, "Couldn't find a compatible stream profile");
736     return NULL;
737   }
738
739 no_stream_group:
740   {
741     GST_WARNING_OBJECT (encodebin, "Couldn't create a StreamGroup");
742     return NULL;
743   }
744 }
745
746 static GstPad *
747 gst_encode_bin_request_new_pad (GstElement * element,
748     GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
749 {
750   GstEncodeBin *ebin = (GstEncodeBin *) element;
751   GstPad *res = NULL;
752
753   GST_DEBUG_OBJECT (element, "templ:%s, name:%s", templ->name_template, name);
754
755   /* Identify the stream group (if name or caps have been provided) */
756   if (caps != NULL || name != NULL) {
757     res = request_pad_for_stream (ebin, G_TYPE_NONE, name, (GstCaps *) caps);
758   }
759
760   if (res == NULL) {
761     GType ptype = G_TYPE_NONE;
762
763     if (!strcmp (templ->name_template, "video_%u"))
764       ptype = GST_TYPE_ENCODING_VIDEO_PROFILE;
765     else if (!strcmp (templ->name_template, "audio_%u"))
766       ptype = GST_TYPE_ENCODING_AUDIO_PROFILE;
767     /* else if (!strcmp (templ->name_template, "text_%u")) */
768     /*   ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */
769
770     /* FIXME : Check uniqueness of pad */
771     /* FIXME : Check that the requested number is the last one, and if not,
772      * update the last_pad_id variable so that we don't create a pad with
773      * the same name/number in the future */
774
775     res = request_pad_for_stream (ebin, ptype, name, NULL);
776   }
777
778   return res;
779 }
780
781 static GstPad *
782 gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin, GstCaps * caps)
783 {
784   GstPad *pad = request_pad_for_stream (encodebin, G_TYPE_NONE, NULL, caps);
785
786   return pad ? GST_PAD_CAST (gst_object_ref (pad)) : NULL;
787 }
788
789 static GstPad *
790 gst_encode_bin_request_profile_pad_signal (GstEncodeBin * encodebin,
791     const gchar * profilename)
792 {
793   GstPad *pad =
794       request_pad_for_stream (encodebin, G_TYPE_NONE, profilename, NULL);
795
796   return pad ? GST_PAD_CAST (gst_object_ref (pad)) : NULL;
797 }
798
799 static inline StreamGroup *
800 find_stream_group_from_pad (GstEncodeBin * ebin, GstPad * pad)
801 {
802   GList *tmp;
803
804   for (tmp = ebin->streams; tmp; tmp = tmp->next) {
805     StreamGroup *sgroup = (StreamGroup *) tmp->data;
806     if (G_UNLIKELY (sgroup->ghostpad == pad))
807       return sgroup;
808   }
809
810   return NULL;
811 }
812
813 static void
814 gst_encode_bin_release_pad (GstElement * element, GstPad * pad)
815 {
816   GstEncodeBin *ebin = (GstEncodeBin *) element;
817   StreamGroup *sgroup;
818
819   /* Find the associated StreamGroup */
820
821   sgroup = find_stream_group_from_pad (ebin, pad);
822   if (G_UNLIKELY (sgroup == NULL))
823     goto no_stream_group;
824
825   /* Release objects/data associated with the StreamGroup */
826   stream_group_remove (ebin, sgroup);
827
828   return;
829
830 no_stream_group:
831   {
832     GST_WARNING_OBJECT (ebin, "Couldn't find corresponding StreamGroup");
833     return;
834   }
835 }
836
837 /* Create a parser for the given stream profile */
838 static inline GstElement *
839 _get_parser (GstEncodeBin * ebin, GstEncodingProfile * sprof)
840 {
841   GList *parsers1, *parsers, *tmp;
842   GstElement *parser = NULL;
843   GstElementFactory *parserfact = NULL;
844   GstCaps *format;
845
846   format = gst_encoding_profile_get_format (sprof);
847
848   GST_DEBUG ("Getting list of parsers for format %" GST_PTR_FORMAT, format);
849
850   /* FIXME : requesting twice the parsers twice is a bit ugly, we should
851    * have a method to request on more than one condition */
852   parsers1 =
853       gst_element_factory_list_filter (ebin->parsers, format,
854       GST_PAD_SRC, FALSE);
855   parsers =
856       gst_element_factory_list_filter (parsers1, format, GST_PAD_SINK, FALSE);
857   gst_plugin_feature_list_free (parsers1);
858
859   if (G_UNLIKELY (parsers == NULL)) {
860     GST_DEBUG ("Couldn't find any compatible parsers");
861     goto beach;
862   }
863
864   for (tmp = parsers; tmp; tmp = tmp->next) {
865     /* FIXME : We're only picking the first one so far */
866     /* FIXME : signal the user if he wants this */
867     parserfact = (GstElementFactory *) tmp->data;
868     break;
869   }
870
871   if (parserfact)
872     parser = gst_element_factory_create (parserfact, NULL);
873
874   gst_plugin_feature_list_free (parsers);
875
876 beach:
877   if (format)
878     gst_caps_unref (format);
879
880   return parser;
881 }
882
883 static GstElement *
884 _create_element_and_set_preset (GstElementFactory * factory,
885     const gchar * preset, const gchar * name, const gchar * preset_name)
886 {
887   GstElement *res = NULL;
888
889   GST_DEBUG ("Creating element from factory %s (preset factory name: %s"
890       " preset name: %s)", GST_OBJECT_NAME (factory), preset, preset_name);
891
892   res = gst_element_factory_create (factory, name);
893
894   if (preset && GST_IS_PRESET (res)) {
895     if (preset_name == NULL ||
896         g_strcmp0 (GST_OBJECT_NAME (factory), preset_name) == 0) {
897
898       if (!gst_preset_load_preset (GST_PRESET (res), preset)) {
899         GST_WARNING ("Couldn't set preset [%s] on element [%s]",
900             preset, GST_OBJECT_NAME (factory));
901         gst_object_unref (res);
902         res = NULL;
903       }
904     } else {
905       GST_DEBUG ("Using a preset with no preset name, making use of the"
906           " proper element without setting any property");
907     }
908   } else if (preset_name && g_strcmp0 (GST_OBJECT_NAME (factory), preset_name)) {
909     gst_object_unref (res);
910     res = NULL;
911   }
912   /* Else we keep it */
913
914   return res;
915 }
916
917 /* Create the encoder for the given stream profile */
918 static inline GstElement *
919 _get_encoder (GstEncodeBin * ebin, GstEncodingProfile * sprof)
920 {
921   GList *encoders, *tmp;
922   GstElement *encoder = NULL;
923   GstElementFactory *encoderfact = NULL;
924   GstCaps *format;
925   const gchar *preset, *preset_name;
926
927   format = gst_encoding_profile_get_format (sprof);
928   preset = gst_encoding_profile_get_preset (sprof);
929   preset_name = gst_encoding_profile_get_preset_name (sprof);
930
931   GST_DEBUG ("Getting list of encoders for format %" GST_PTR_FORMAT, format);
932
933   /* If stream caps are raw, return identity */
934   if (G_UNLIKELY (are_raw_caps (format))) {
935     GST_DEBUG ("Stream format is raw, returning identity as the encoder");
936     encoder = gst_element_factory_make ("identity", NULL);
937     goto beach;
938   }
939
940   encoders =
941       gst_element_factory_list_filter (ebin->encoders, format,
942       GST_PAD_SRC, FALSE);
943
944   if (G_UNLIKELY (encoders == NULL)) {
945     GST_DEBUG ("Couldn't find any compatible encoders");
946     goto beach;
947   }
948
949   for (tmp = encoders; tmp; tmp = tmp->next) {
950     encoderfact = (GstElementFactory *) tmp->data;
951     if ((encoder = _create_element_and_set_preset (encoderfact, preset,
952                 NULL, preset_name)))
953       break;
954   }
955
956   gst_plugin_feature_list_free (encoders);
957
958 beach:
959   if (format)
960     gst_caps_unref (format);
961
962   return encoder;
963 }
964
965 static GstPad *
966 local_element_request_pad (GstElement * element, GstPadTemplate * templ,
967     const gchar * name, const GstCaps * caps)
968 {
969   GstPad *newpad = NULL;
970   GstElementClass *oclass;
971
972   oclass = GST_ELEMENT_GET_CLASS (element);
973
974   if (oclass->request_new_pad)
975     newpad = (oclass->request_new_pad) (element, templ, name, caps);
976
977   if (newpad)
978     gst_object_ref (newpad);
979
980   return newpad;
981 }
982
983 static GstPad *
984 gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
985 {
986   GstPad *ret = NULL;
987   GstPadPresence presence;
988
989   /* If this function is ever exported, we need check the validity of `element'
990    * and `templ', and to make sure the template actually belongs to the
991    * element. */
992
993   presence = GST_PAD_TEMPLATE_PRESENCE (templ);
994
995   switch (presence) {
996     case GST_PAD_ALWAYS:
997     case GST_PAD_SOMETIMES:
998       ret = gst_element_get_static_pad (element, templ->name_template);
999       if (!ret && presence == GST_PAD_ALWAYS)
1000         g_warning
1001             ("Element %s has an ALWAYS template %s, but no pad of the same name",
1002             GST_OBJECT_NAME (element), templ->name_template);
1003       break;
1004
1005     case GST_PAD_REQUEST:
1006       ret = gst_element_request_pad (element, templ, NULL, NULL);
1007       break;
1008   }
1009
1010   return ret;
1011 }
1012
1013 /* FIXME : Improve algorithm for finding compatible muxer sink pad */
1014 static inline GstPad *
1015 get_compatible_muxer_sink_pad (GstEncodeBin * ebin, GstElement * encoder,
1016     GstCaps * sinkcaps)
1017 {
1018   GstPad *sinkpad;
1019   GstPadTemplate *srctempl = NULL;
1020   GstPadTemplate *sinktempl;
1021
1022   if (encoder) {
1023     GstPad *srcpad;
1024     srcpad = gst_element_get_static_pad (encoder, "src");
1025
1026     srctempl = gst_pad_get_pad_template (srcpad);
1027
1028     GST_DEBUG_OBJECT (ebin,
1029         "Attempting to find pad from muxer %s compatible with %s:%s",
1030         GST_ELEMENT_NAME (ebin->muxer), GST_DEBUG_PAD_NAME (srcpad));
1031
1032     gst_object_unref (srcpad);
1033     sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl);
1034     gst_object_unref (srctempl);
1035   } else {
1036     srctempl =
1037         gst_pad_template_new ("whatever", GST_PAD_SRC, GST_PAD_ALWAYS,
1038         sinkcaps);
1039     g_assert (srctempl != NULL);
1040     sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl);
1041     g_object_unref (srctempl);
1042   }
1043
1044   if (G_UNLIKELY (sinktempl == NULL))
1045     goto no_template;
1046
1047   sinkpad = gst_element_get_pad_from_template (ebin->muxer, sinktempl);
1048
1049   return sinkpad;
1050
1051 no_template:
1052   {
1053     GST_WARNING_OBJECT (ebin, "No compatible pad available on muxer");
1054     return NULL;
1055   }
1056 }
1057
1058 static gboolean
1059 _has_class (GstElement * element, const gchar * classname)
1060 {
1061   GstElementClass *klass;
1062   const gchar *value;
1063
1064   klass = GST_ELEMENT_GET_CLASS (element);
1065   value = gst_element_class_get_metadata (klass, GST_ELEMENT_METADATA_KLASS);
1066   if (!value)
1067     return FALSE;
1068
1069   return strstr (value, classname) != NULL;
1070 }
1071
1072 static void
1073 _profile_restriction_caps_cb (GstEncodingProfile * profile,
1074     GParamSpec * arg G_GNUC_UNUSED, StreamGroup * group)
1075 {
1076   GstCaps *restriction = gst_encoding_profile_get_restriction (profile);
1077
1078   g_object_set (group->capsfilter, "caps", restriction, NULL);
1079 }
1080
1081 static void
1082 _post_missing_plugin_message (GstEncodeBin * ebin, GstEncodingProfile * prof)
1083 {
1084   GstCaps *format;
1085   format = gst_encoding_profile_get_format (prof);
1086
1087   GST_ERROR_OBJECT (ebin, "Couldn't create encoder for format %" GST_PTR_FORMAT,
1088       format);
1089   /* missing plugin support */
1090   gst_element_post_message (GST_ELEMENT_CAST (ebin),
1091       gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin), format));
1092   GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL),
1093       ("Couldn't create encoder for format %" GST_PTR_FORMAT, format));
1094
1095   gst_caps_unref (format);
1096 }
1097
1098 static GstPadProbeReturn
1099 _missing_plugin_probe (GstPad * pad, GstPadProbeInfo * info, gpointer udata)
1100 {
1101   StreamGroup *sgroup = udata;
1102   GstEncodeBin *ebin = sgroup->ebin;
1103
1104   _post_missing_plugin_message (ebin, sgroup->profile);
1105
1106   return GST_PAD_PROBE_OK;
1107 }
1108
1109 static void
1110 _set_up_fake_encoder_pad_probe (GstEncodeBin * ebin, StreamGroup * sgroup)
1111 {
1112   GstPad *pad = gst_element_get_static_pad (sgroup->fakesink, "sink");
1113
1114   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, _missing_plugin_probe,
1115       sgroup, NULL);
1116
1117   gst_object_unref (pad);
1118 }
1119
1120 /* FIXME : Add handling of streams that don't require conversion elements */
1121 /*
1122  * Create the elements, StreamGroup, add the sink pad, link it to the muxer
1123  *
1124  * sinkpadname: If non-NULL, that name will be assigned to the sink ghost pad
1125  * sinkcaps: If non-NULL will be used to figure out how to setup the group */
1126 static StreamGroup *
1127 _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof,
1128     const gchar * sinkpadname, GstCaps * sinkcaps)
1129 {
1130   StreamGroup *sgroup = NULL;
1131   GstPad *sinkpad, *srcpad, *muxerpad = NULL;
1132   /* Element we will link to the encoder */
1133   GstElement *last = NULL;
1134   GstElement *encoder = NULL;
1135   GList *tmp, *tosync = NULL;
1136   GstCaps *format, *restriction;
1137   const gchar *missing_element_name;
1138
1139   format = gst_encoding_profile_get_format (sprof);
1140   restriction = gst_encoding_profile_get_restriction (sprof);
1141
1142   GST_DEBUG ("Creating group. format %" GST_PTR_FORMAT ", for caps %"
1143       GST_PTR_FORMAT, format, sinkcaps);
1144   GST_DEBUG ("avoid_reencoding:%d", ebin->avoid_reencoding);
1145
1146   sgroup = g_slice_new0 (StreamGroup);
1147   sgroup->ebin = ebin;
1148   sgroup->profile = sprof;
1149
1150   /* NOTE for people reading this code:
1151    * 
1152    * We construct the group starting by the furthest downstream element
1153    * and making our way up adding/syncing/linking as we go.
1154    *
1155    * There are two parallel paths:
1156    * * One for raw data which goes through converters and encoders
1157    * * One for already encoded data
1158    */
1159
1160   /* Muxer.
1161    * If we are handling a container profile, figure out if the muxer has a
1162    * sinkpad compatible with the selected profile */
1163   if (ebin->muxer) {
1164     muxerpad = get_compatible_muxer_sink_pad (ebin, NULL, format);
1165     if (G_UNLIKELY (muxerpad == NULL))
1166       goto no_muxer_pad;
1167
1168   }
1169
1170   /* Output Queue.
1171    * We only use a 1buffer long queue here, the actual queueing will be done
1172    * in the input queue */
1173   last = sgroup->outqueue = gst_element_factory_make ("queue", NULL);
1174   g_object_set (sgroup->outqueue, "max-size-buffers", (guint32) 1,
1175       "max-size-bytes", (guint32) 0, "max-size-time", (guint64) 0,
1176       "silent", TRUE, NULL);
1177
1178   gst_bin_add (GST_BIN (ebin), sgroup->outqueue);
1179   tosync = g_list_append (tosync, sgroup->outqueue);
1180   srcpad = gst_element_get_static_pad (sgroup->outqueue, "src");
1181   if (muxerpad) {
1182     if (G_UNLIKELY (fast_pad_link (srcpad, muxerpad) != GST_PAD_LINK_OK)) {
1183       goto muxer_link_failure;
1184     }
1185     gst_object_unref (muxerpad);
1186   } else {
1187     gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), srcpad);
1188   }
1189   gst_object_unref (srcpad);
1190
1191   /* Check if we need a formatter
1192    * If we have no muxer or
1193    * if the muxer isn't a formatter and doesn't implement the tagsetter interface
1194    */
1195   if (!ebin->muxer || (!GST_IS_TAG_SETTER (ebin->muxer)
1196           && !_has_class (ebin->muxer, "Formatter"))) {
1197     sgroup->formatter = _get_formatter (ebin, sprof);
1198     if (sgroup->formatter) {
1199       GST_DEBUG ("Adding formatter for %" GST_PTR_FORMAT, format);
1200
1201       gst_bin_add (GST_BIN (ebin), sgroup->formatter);
1202       tosync = g_list_append (tosync, sgroup->formatter);
1203       if (G_UNLIKELY (!fast_element_link (sgroup->formatter, last)))
1204         goto formatter_link_failure;
1205       last = sgroup->formatter;
1206     }
1207   }
1208
1209
1210   /* Output capsfilter
1211    * This will receive the format caps from the streamprofile */
1212   GST_DEBUG ("Adding output capsfilter for %" GST_PTR_FORMAT, format);
1213   sgroup->outfilter = gst_element_factory_make ("capsfilter", NULL);
1214   g_object_set (sgroup->outfilter, "caps", format, NULL);
1215
1216   gst_bin_add (GST_BIN (ebin), sgroup->outfilter);
1217   tosync = g_list_append (tosync, sgroup->outfilter);
1218   if (G_UNLIKELY (!fast_element_link (sgroup->outfilter, last)))
1219     goto outfilter_link_failure;
1220   last = sgroup->outfilter;
1221
1222
1223   sgroup->parser = _get_parser (ebin, sprof);
1224
1225   if (sgroup->parser != NULL) {
1226     GST_DEBUG ("Got a parser %s", GST_ELEMENT_NAME (sgroup->parser));
1227     gst_bin_add (GST_BIN (ebin), sgroup->parser);
1228     tosync = g_list_append (tosync, sgroup->parser);
1229     if (G_UNLIKELY (!gst_element_link (sgroup->parser, last)))
1230       goto parser_link_failure;
1231     last = sgroup->parser;
1232   }
1233
1234   /* Stream combiner */
1235   sgroup->combiner = g_object_new (GST_TYPE_STREAM_COMBINER, NULL);
1236
1237   gst_bin_add (GST_BIN (ebin), sgroup->combiner);
1238   tosync = g_list_append (tosync, sgroup->combiner);
1239   if (G_UNLIKELY (!fast_element_link (sgroup->combiner, last)))
1240     goto combiner_link_failure;
1241
1242
1243   /* Stream splitter */
1244   sgroup->splitter = g_object_new (GST_TYPE_STREAM_SPLITTER, NULL);
1245
1246   gst_bin_add (GST_BIN (ebin), sgroup->splitter);
1247   tosync = g_list_append (tosync, sgroup->splitter);
1248
1249   /* Input queue
1250    * FIXME : figure out what max-size to use for the input queue */
1251   sgroup->inqueue = gst_element_factory_make ("queue", NULL);
1252   g_object_set (sgroup->inqueue, "max-size-buffers",
1253       (guint32) ebin->queue_buffers_max, "max-size-bytes",
1254       (guint32) ebin->queue_bytes_max, "max-size-time",
1255       (guint64) ebin->queue_time_max, "silent", TRUE, NULL);
1256
1257   gst_bin_add (GST_BIN (ebin), sgroup->inqueue);
1258   tosync = g_list_append (tosync, sgroup->inqueue);
1259   if (G_UNLIKELY (!fast_element_link (sgroup->inqueue, sgroup->splitter)))
1260     goto splitter_link_failure;
1261
1262   /* Expose input queue sink pad as ghostpad */
1263   sinkpad = gst_element_get_static_pad (sgroup->inqueue, "sink");
1264   if (sinkpadname == NULL) {
1265     gchar *pname =
1266         g_strdup_printf ("%s_%u", gst_encoding_profile_get_type_nick (sprof),
1267         ebin->last_pad_id++);
1268     GST_DEBUG ("Adding ghost pad %s", pname);
1269     sgroup->ghostpad = gst_ghost_pad_new (pname, sinkpad);
1270     g_free (pname);
1271   } else
1272     sgroup->ghostpad = gst_ghost_pad_new (sinkpadname, sinkpad);
1273   gst_object_unref (sinkpad);
1274
1275
1276   /* Path 1 : Already-encoded data */
1277   sinkpad =
1278       local_element_request_pad (sgroup->combiner, NULL, "passthroughsink",
1279       NULL);
1280   if (G_UNLIKELY (sinkpad == NULL))
1281     goto no_combiner_sinkpad;
1282
1283   if (ebin->avoid_reencoding) {
1284     GstCaps *tmpcaps;
1285
1286     GST_DEBUG ("Asked to use Smart Encoder");
1287     sgroup->smartencoder = g_object_new (GST_TYPE_SMART_ENCODER, NULL);
1288
1289     /* Check if stream format is compatible */
1290     srcpad = gst_element_get_static_pad (sgroup->smartencoder, "src");
1291     tmpcaps = gst_pad_query_caps (srcpad, NULL);
1292     if (!gst_caps_can_intersect (tmpcaps, format)) {
1293       GST_DEBUG ("We don't have a smart encoder for the stream format");
1294       gst_object_unref (sgroup->smartencoder);
1295       sgroup->smartencoder = NULL;
1296     } else {
1297       gst_bin_add ((GstBin *) ebin, sgroup->smartencoder);
1298       fast_pad_link (srcpad, sinkpad);
1299       tosync = g_list_append (tosync, sgroup->smartencoder);
1300       sinkpad = gst_element_get_static_pad (sgroup->smartencoder, "sink");
1301     }
1302     gst_caps_unref (tmpcaps);
1303     g_object_unref (srcpad);
1304   }
1305
1306   srcpad =
1307       local_element_request_pad (sgroup->splitter, NULL, "passthroughsrc",
1308       NULL);
1309   if (G_UNLIKELY (srcpad == NULL))
1310     goto no_splitter_srcpad;
1311
1312   /* Go straight to splitter */
1313   if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1314     goto passthrough_link_failure;
1315   g_object_unref (sinkpad);
1316   g_object_unref (srcpad);
1317
1318
1319   /* Path 2 : Conversion / Encoding */
1320
1321   /* 1. Create the encoder */
1322   GST_LOG ("Adding encoder");
1323   sgroup->encoder = _get_encoder (ebin, sprof);
1324   if (sgroup->encoder != NULL) {
1325     gst_bin_add ((GstBin *) ebin, sgroup->encoder);
1326     tosync = g_list_append (tosync, sgroup->encoder);
1327
1328     sinkpad =
1329         local_element_request_pad (sgroup->combiner, NULL, "encodingsink",
1330         NULL);
1331     if (G_UNLIKELY (sinkpad == NULL))
1332       goto no_combiner_sinkpad;
1333     srcpad = gst_element_get_static_pad (sgroup->encoder, "src");
1334     if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1335       goto encoder_link_failure;
1336     g_object_unref (sinkpad);
1337     g_object_unref (srcpad);
1338   } else if (gst_encoding_profile_get_preset (sgroup->profile)
1339       || gst_encoding_profile_get_preset_name (sgroup->profile)) {
1340     _post_missing_plugin_message (ebin, sprof);
1341     goto cleanup;
1342   } else {
1343     /* passthrough can still work, if we discover that *
1344      * encoding is required we post a missing plugin message */
1345   }
1346
1347
1348   /* 3. Create the conversion/restriction elements */
1349   /* 3.1. capsfilter */
1350   GST_LOG ("Adding capsfilter for restriction caps : %" GST_PTR_FORMAT,
1351       restriction);
1352
1353   last = sgroup->capsfilter = gst_element_factory_make ("capsfilter", NULL);
1354   if (restriction && !gst_caps_is_any (restriction))
1355     g_object_set (sgroup->capsfilter, "caps", restriction, NULL);
1356   gst_bin_add ((GstBin *) ebin, sgroup->capsfilter);
1357   tosync = g_list_append (tosync, sgroup->capsfilter);
1358   if (sgroup->encoder == NULL) {
1359     /* no encoder available but it might be possible to just do passthrough, so
1360      * let's just set up a fake pad to detect that encoding was attempted and
1361      * if so it posts the missing plugin message */
1362     sgroup->fakesink = gst_element_factory_make ("fakesink", NULL);
1363     g_object_set (sgroup->fakesink, "async", FALSE, NULL);
1364     gst_bin_add (GST_BIN_CAST (ebin), sgroup->fakesink);
1365     tosync = g_list_append (tosync, sgroup->fakesink);
1366     encoder = sgroup->fakesink;
1367
1368     _set_up_fake_encoder_pad_probe (ebin, sgroup);
1369   } else {
1370     encoder = sgroup->encoder;
1371   }
1372   fast_element_link (sgroup->capsfilter, encoder);
1373   sgroup->restriction_sid = g_signal_connect (sprof, "notify::restriction-caps",
1374       G_CALLBACK (_profile_restriction_caps_cb), sgroup);
1375
1376   /* 3.2. restriction elements */
1377   /* FIXME : Once we have properties for specific converters, use those */
1378   if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) {
1379     const gboolean native_video =
1380         ! !(ebin->flags & GST_ENCODEBIN_FLAG_NO_VIDEO_CONVERSION);
1381     GstElement *cspace = NULL, *scale, *vrate, *cspace2 = NULL;
1382
1383     GST_LOG ("Adding conversion elements for video stream");
1384
1385     if (!native_video) {
1386       cspace = gst_element_factory_make ("videoconvert", NULL);
1387       scale = gst_element_factory_make ("videoscale", NULL);
1388       if (!scale) {
1389         missing_element_name = "videoscale";
1390         goto missing_element;
1391       }
1392       /* 4-tap scaling and black borders */
1393       g_object_set (scale, "method", 2, "add-borders", TRUE, NULL);
1394       cspace2 = gst_element_factory_make ("videoconvert", NULL);
1395
1396       if (!cspace || !cspace2) {
1397         missing_element_name = "videoconvert";
1398         goto missing_element;
1399       }
1400
1401       gst_bin_add_many ((GstBin *) ebin, cspace, scale, cspace2, NULL);
1402       tosync = g_list_append (tosync, cspace);
1403       tosync = g_list_append (tosync, scale);
1404       tosync = g_list_append (tosync, cspace2);
1405
1406       sgroup->converters = g_list_prepend (sgroup->converters, cspace);
1407       sgroup->converters = g_list_prepend (sgroup->converters, scale);
1408       sgroup->converters = g_list_prepend (sgroup->converters, cspace2);
1409
1410       if (!fast_element_link (cspace, scale) ||
1411           !fast_element_link (scale, cspace2))
1412         goto converter_link_failure;
1413     }
1414
1415     if (!gst_encoding_video_profile_get_variableframerate
1416         (GST_ENCODING_VIDEO_PROFILE (sprof))) {
1417       vrate = gst_element_factory_make ("videorate", NULL);
1418       if (!vrate) {
1419         missing_element_name = "videorate";
1420         goto missing_element;
1421       }
1422
1423       gst_bin_add ((GstBin *) ebin, vrate);
1424       tosync = g_list_prepend (tosync, vrate);
1425       sgroup->converters = g_list_prepend (sgroup->converters, vrate);
1426
1427       if ((!native_video && !fast_element_link (cspace2, vrate))
1428           || !fast_element_link (vrate, last))
1429         goto converter_link_failure;
1430
1431       if (!native_video)
1432         last = cspace;
1433       else
1434         last = vrate;
1435     } else if (!native_video) {
1436       if (!fast_element_link (cspace2, last))
1437         goto converter_link_failure;
1438       last = cspace;
1439     }
1440
1441   } else if (GST_IS_ENCODING_AUDIO_PROFILE (sprof)
1442       && !(ebin->flags & GST_ENCODEBIN_FLAG_NO_AUDIO_CONVERSION)) {
1443     GstElement *aconv, *ares, *arate, *aconv2;
1444
1445     GST_LOG ("Adding conversion elements for audio stream");
1446
1447     arate = gst_element_factory_make ("audiorate", NULL);
1448     g_object_set (arate, "tolerance", (guint64) ebin->tolerance, NULL);
1449     if (!arate) {
1450       missing_element_name = "audiorate";
1451       goto missing_element;
1452     }
1453     aconv = gst_element_factory_make ("audioconvert", NULL);
1454     aconv2 = gst_element_factory_make ("audioconvert", NULL);
1455     ares = gst_element_factory_make ("audioresample", NULL);
1456     if (!aconv || !aconv2) {
1457       missing_element_name = "audioconvert";
1458       goto missing_element;
1459     }
1460     if (!ares) {
1461       missing_element_name = "audioresample";
1462       goto missing_element;
1463     }
1464
1465     gst_bin_add_many ((GstBin *) ebin, arate, aconv, ares, aconv2, NULL);
1466     tosync = g_list_append (tosync, arate);
1467     tosync = g_list_append (tosync, aconv);
1468     tosync = g_list_append (tosync, ares);
1469     tosync = g_list_append (tosync, aconv2);
1470     if (!fast_element_link (arate, aconv) ||
1471         !fast_element_link (aconv, ares) ||
1472         !fast_element_link (ares, aconv2) || !fast_element_link (aconv2, last))
1473       goto converter_link_failure;
1474
1475     sgroup->converters = g_list_prepend (sgroup->converters, arate);
1476     sgroup->converters = g_list_prepend (sgroup->converters, aconv);
1477     sgroup->converters = g_list_prepend (sgroup->converters, ares);
1478     sgroup->converters = g_list_prepend (sgroup->converters, aconv2);
1479
1480     last = arate;
1481   }
1482
1483   /* Link to stream splitter */
1484   sinkpad = gst_element_get_static_pad (last, "sink");
1485   srcpad =
1486       local_element_request_pad (sgroup->splitter, NULL, "encodingsrc", NULL);
1487   if (G_UNLIKELY (srcpad == NULL))
1488     goto no_splitter_srcpad;
1489   if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK))
1490     goto splitter_encoding_failure;
1491   g_object_unref (sinkpad);
1492   g_object_unref (srcpad);
1493
1494   /* End of Stream 2 setup */
1495
1496   /* Sync all elements to parent state */
1497   for (tmp = tosync; tmp; tmp = tmp->next)
1498     gst_element_sync_state_with_parent ((GstElement *) tmp->data);
1499   g_list_free (tosync);
1500
1501   /* Add ghostpad */
1502   GST_DEBUG ("Adding ghostpad %s:%s", GST_DEBUG_PAD_NAME (sgroup->ghostpad));
1503   gst_pad_set_active (sgroup->ghostpad, TRUE);
1504   gst_element_add_pad ((GstElement *) ebin, sgroup->ghostpad);
1505
1506   /* Add StreamGroup to our list of streams */
1507
1508   GST_DEBUG
1509       ("Done creating elements, adding StreamGroup to our controlled stream list");
1510
1511   ebin->streams = g_list_prepend (ebin->streams, sgroup);
1512
1513   if (format)
1514     gst_caps_unref (format);
1515   if (restriction)
1516     gst_caps_unref (restriction);
1517
1518   return sgroup;
1519
1520 splitter_encoding_failure:
1521   GST_ERROR_OBJECT (ebin, "Error linking splitter to encoding stream");
1522   goto cleanup;
1523
1524 no_muxer_pad:
1525   GST_ERROR_OBJECT (ebin,
1526       "Couldn't find a compatible muxer pad to link encoder to");
1527   goto cleanup;
1528
1529 missing_element:
1530   gst_element_post_message (GST_ELEMENT_CAST (ebin),
1531       gst_missing_element_message_new (GST_ELEMENT_CAST (ebin),
1532           missing_element_name));
1533   GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN,
1534       (_("Missing element '%s' - check your GStreamer installation."),
1535           missing_element_name), (NULL));
1536   goto cleanup;
1537
1538 encoder_link_failure:
1539   GST_ERROR_OBJECT (ebin, "Failed to link the encoder");
1540   goto cleanup;
1541
1542 muxer_link_failure:
1543   GST_ERROR_OBJECT (ebin, "Couldn't link encoder to muxer");
1544   goto cleanup;
1545
1546 formatter_link_failure:
1547   GST_ERROR_OBJECT (ebin, "Couldn't link output filter to output queue");
1548   goto cleanup;
1549
1550 outfilter_link_failure:
1551   GST_ERROR_OBJECT (ebin,
1552       "Couldn't link output filter to output queue/formatter");
1553   goto cleanup;
1554
1555 passthrough_link_failure:
1556   GST_ERROR_OBJECT (ebin, "Failed linking splitter in passthrough mode");
1557   goto cleanup;
1558
1559 no_splitter_srcpad:
1560   GST_ERROR_OBJECT (ebin, "Couldn't get a source pad from the splitter");
1561   goto cleanup;
1562
1563 no_combiner_sinkpad:
1564   GST_ERROR_OBJECT (ebin, "Couldn't get a sink pad from the combiner");
1565   goto cleanup;
1566
1567 splitter_link_failure:
1568   GST_ERROR_OBJECT (ebin, "Failure linking to the splitter");
1569   goto cleanup;
1570
1571 combiner_link_failure:
1572   GST_ERROR_OBJECT (ebin, "Failure linking to the combiner");
1573   goto cleanup;
1574
1575 parser_link_failure:
1576   GST_ERROR_OBJECT (ebin, "Failure linking the parser");
1577   goto cleanup;
1578
1579 converter_link_failure:
1580   GST_ERROR_OBJECT (ebin, "Failure linking the video converters");
1581   goto cleanup;
1582
1583 cleanup:
1584   /* FIXME : Actually properly cleanup everything */
1585   if (format)
1586     gst_caps_unref (format);
1587   if (restriction)
1588     gst_caps_unref (restriction);
1589   stream_group_free (ebin, sgroup);
1590   g_list_free (tosync);
1591   return NULL;
1592 }
1593
1594 static gboolean
1595 _gst_caps_match_foreach (GQuark field_id, const GValue * value, gpointer data)
1596 {
1597   GstStructure *structure = data;
1598   const GValue *other_value = gst_structure_id_get_value (structure, field_id);
1599
1600   if (G_UNLIKELY (other_value == NULL))
1601     return FALSE;
1602   if (gst_value_compare (value, other_value) == GST_VALUE_EQUAL) {
1603     return TRUE;
1604   }
1605
1606   return FALSE;
1607 }
1608
1609 /*
1610  * checks that there is at least one structure on caps_a that has
1611  * all its fields exactly the same as one structure on caps_b
1612  */
1613 static gboolean
1614 _gst_caps_match (const GstCaps * caps_a, const GstCaps * caps_b)
1615 {
1616   gint i, j;
1617   gboolean res = FALSE;
1618
1619   for (i = 0; i < gst_caps_get_size (caps_a); i++) {
1620     GstStructure *structure_a = gst_caps_get_structure (caps_a, i);
1621     for (j = 0; j < gst_caps_get_size (caps_b); j++) {
1622       GstStructure *structure_b = gst_caps_get_structure (caps_b, j);
1623
1624       res = gst_structure_foreach (structure_a, _gst_caps_match_foreach,
1625           structure_b);
1626       if (res)
1627         goto end;
1628     }
1629   }
1630 end:
1631   return res;
1632 }
1633
1634 static gboolean
1635 _factory_can_handle_caps (GstElementFactory * factory, const GstCaps * caps,
1636     GstPadDirection dir, gboolean exact)
1637 {
1638   const GList *templates;
1639
1640   templates = gst_element_factory_get_static_pad_templates (factory);
1641   while (templates) {
1642     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
1643
1644     if (template->direction == dir) {
1645       GstCaps *tmp = gst_static_caps_get (&template->static_caps);
1646
1647       if ((exact && _gst_caps_match (caps, tmp)) ||
1648           (!exact && gst_caps_can_intersect (tmp, caps))) {
1649         gst_caps_unref (tmp);
1650         return TRUE;
1651       }
1652       gst_caps_unref (tmp);
1653     }
1654     templates = g_list_next (templates);
1655   }
1656
1657   return FALSE;
1658 }
1659
1660 static inline GstElement *
1661 _get_formatter (GstEncodeBin * ebin, GstEncodingProfile * sprof)
1662 {
1663   GList *formatters, *tmpfmtr;
1664   GstElement *formatter = NULL;
1665   GstElementFactory *formatterfact = NULL;
1666   GstCaps *format;
1667   const gchar *preset, *preset_name;
1668
1669   format = gst_encoding_profile_get_format (sprof);
1670   preset = gst_encoding_profile_get_preset (sprof);
1671   preset_name = gst_encoding_profile_get_preset_name (sprof);
1672
1673   GST_DEBUG ("Getting list of formatters for format %" GST_PTR_FORMAT, format);
1674
1675   formatters =
1676       gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
1677       FALSE);
1678
1679   if (formatters == NULL)
1680     goto beach;
1681
1682   /* FIXME : signal the user if he wants this */
1683   for (tmpfmtr = formatters; tmpfmtr; tmpfmtr = tmpfmtr->next) {
1684     formatterfact = (GstElementFactory *) tmpfmtr->data;
1685
1686     GST_DEBUG_OBJECT (ebin, "Trying formatter %s",
1687         GST_OBJECT_NAME (formatterfact));
1688
1689     if ((formatter =
1690             _create_element_and_set_preset (formatterfact, preset,
1691                 NULL, preset_name)))
1692       break;
1693   }
1694
1695   gst_plugin_feature_list_free (formatters);
1696
1697 beach:
1698   if (format)
1699     gst_caps_unref (format);
1700   return formatter;
1701 }
1702
1703 static gint
1704 compare_elements (gconstpointer a, gconstpointer b, gpointer udata)
1705 {
1706   GstCaps *caps = udata;
1707   GstElementFactory *fac_a = (GstElementFactory *) a;
1708   GstElementFactory *fac_b = (GstElementFactory *) b;
1709
1710   /* FIXME not quite sure this is the best algorithm to order the elements
1711    * Some caps similarity comparison algorithm would fit better than going
1712    * boolean (equals/not equals).
1713    */
1714   gboolean equals_a = _factory_can_handle_caps (fac_a, caps, GST_PAD_SRC, TRUE);
1715   gboolean equals_b = _factory_can_handle_caps (fac_b, caps, GST_PAD_SRC, TRUE);
1716
1717   if (equals_a == equals_b) {
1718     return gst_plugin_feature_get_rank ((GstPluginFeature *) fac_b) -
1719         gst_plugin_feature_get_rank ((GstPluginFeature *) fac_a);
1720   } else if (equals_a) {
1721     return -1;
1722   } else if (equals_b) {
1723     return 1;
1724   }
1725   return 0;
1726 }
1727
1728 static inline GstElement *
1729 _get_muxer (GstEncodeBin * ebin)
1730 {
1731   GList *muxers, *formatters, *tmpmux;
1732   GstElement *muxer = NULL;
1733   GstElementFactory *muxerfact = NULL;
1734   const GList *tmp;
1735   GstCaps *format;
1736   const gchar *preset, *preset_name;
1737
1738   format = gst_encoding_profile_get_format (ebin->profile);
1739   preset = gst_encoding_profile_get_preset (ebin->profile);
1740   preset_name = gst_encoding_profile_get_preset_name (ebin->profile);
1741
1742   GST_DEBUG ("Getting list of muxers for format %" GST_PTR_FORMAT, format);
1743
1744   muxers =
1745       gst_element_factory_list_filter (ebin->muxers, format, GST_PAD_SRC, TRUE);
1746
1747   formatters =
1748       gst_element_factory_list_filter (ebin->formatters, format, GST_PAD_SRC,
1749       TRUE);
1750
1751   muxers = g_list_sort_with_data (muxers, compare_elements, (gpointer) format);
1752   formatters =
1753       g_list_sort_with_data (formatters, compare_elements, (gpointer) format);
1754
1755   muxers = g_list_concat (muxers, formatters);
1756
1757   if (muxers == NULL)
1758     goto beach;
1759
1760   /* FIXME : signal the user if he wants this */
1761   for (tmpmux = muxers; tmpmux; tmpmux = tmpmux->next) {
1762     gboolean cansinkstreams = TRUE;
1763     const GList *profiles =
1764         gst_encoding_container_profile_get_profiles
1765         (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
1766
1767     muxerfact = (GstElementFactory *) tmpmux->data;
1768
1769     GST_DEBUG ("Trying muxer %s", GST_OBJECT_NAME (muxerfact));
1770
1771     /* See if the muxer can sink all of our stream profile caps */
1772     for (tmp = profiles; tmp; tmp = tmp->next) {
1773       GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
1774       GstCaps *sformat = gst_encoding_profile_get_format (sprof);
1775
1776       if (!_factory_can_handle_caps (muxerfact, sformat, GST_PAD_SINK, FALSE)) {
1777         GST_DEBUG ("Skipping muxer because it can't sink caps %"
1778             GST_PTR_FORMAT, sformat);
1779         cansinkstreams = FALSE;
1780         if (sformat)
1781           gst_caps_unref (sformat);
1782         break;
1783       }
1784       if (sformat)
1785         gst_caps_unref (sformat);
1786     }
1787
1788     /* Only use a muxer than can use all streams and than can accept the
1789      * preset (which may be present or not) */
1790     if (cansinkstreams && (muxer =
1791             _create_element_and_set_preset (muxerfact, preset, "muxer",
1792                 preset_name)))
1793       break;
1794   }
1795
1796   gst_plugin_feature_list_free (muxers);
1797
1798 beach:
1799   if (format)
1800     gst_caps_unref (format);
1801   return muxer;
1802 }
1803
1804 static gboolean
1805 create_elements_and_pads (GstEncodeBin * ebin)
1806 {
1807   gboolean ret = TRUE;
1808   GstElement *muxer = NULL;
1809   GstPad *muxerpad;
1810   const GList *tmp, *profiles;
1811   GstEncodingProfile *sprof;
1812
1813   GST_DEBUG ("Current profile : %s",
1814       gst_encoding_profile_get_name (ebin->profile));
1815
1816   if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) {
1817     /* 1. Get the compatible muxer */
1818     muxer = _get_muxer (ebin);
1819     if (G_UNLIKELY (muxer == NULL))
1820       goto no_muxer;
1821
1822     /* Record the muxer */
1823     ebin->muxer = muxer;
1824     gst_bin_add ((GstBin *) ebin, muxer);
1825
1826     /* 2. Ghost the muxer source pad */
1827
1828     /* FIXME : We should figure out if it's a static/request/dyamic pad, 
1829      * but for the time being let's assume it's a static pad :) */
1830     muxerpad = gst_element_get_static_pad (muxer, "src");
1831     if (G_UNLIKELY (muxerpad == NULL))
1832       goto no_muxer_pad;
1833
1834     if (!gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), muxerpad))
1835       goto no_muxer_ghost_pad;
1836
1837     gst_object_unref (muxerpad);
1838     /* 3. Activate fixed presence streams */
1839     profiles =
1840         gst_encoding_container_profile_get_profiles
1841         (GST_ENCODING_CONTAINER_PROFILE (ebin->profile));
1842     for (tmp = profiles; tmp; tmp = tmp->next) {
1843       sprof = (GstEncodingProfile *) tmp->data;
1844
1845       GST_DEBUG ("Trying stream profile with presence %d",
1846           gst_encoding_profile_get_presence (sprof));
1847
1848       if (gst_encoding_profile_get_presence (sprof) != 0) {
1849         if (G_UNLIKELY (_create_stream_group (ebin, sprof, NULL, NULL) == NULL))
1850           goto stream_error;
1851       }
1852     }
1853     gst_element_sync_state_with_parent (muxer);
1854   } else {
1855     if (G_UNLIKELY (_create_stream_group (ebin, ebin->profile, NULL,
1856                 NULL) == NULL))
1857       goto stream_error;
1858   }
1859
1860   return ret;
1861
1862 no_muxer:
1863   {
1864     GstCaps *format = gst_encoding_profile_get_format (ebin->profile);
1865
1866     GST_WARNING ("No available muxer for %" GST_PTR_FORMAT, format);
1867     /* missing plugin support */
1868     gst_element_post_message (GST_ELEMENT_CAST (ebin),
1869         gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin), format));
1870     GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL),
1871         ("No available muxer for format %" GST_PTR_FORMAT, format));
1872     if (format)
1873       gst_caps_unref (format);
1874     return FALSE;
1875   }
1876
1877 no_muxer_pad:
1878   {
1879     GST_WARNING ("Can't get source pad from muxer (%s)",
1880         GST_ELEMENT_NAME (muxer));
1881     gst_bin_remove (GST_BIN (ebin), muxer);
1882     return FALSE;
1883   }
1884
1885 no_muxer_ghost_pad:
1886   {
1887     GST_WARNING ("Couldn't set %s:%s as source ghostpad target",
1888         GST_DEBUG_PAD_NAME (muxerpad));
1889     gst_bin_remove (GST_BIN (ebin), muxer);
1890     gst_object_unref (muxerpad);
1891     return FALSE;
1892   }
1893
1894 stream_error:
1895   {
1896     GST_WARNING ("Could not create Streams");
1897     if (muxer)
1898       gst_bin_remove (GST_BIN (ebin), muxer);
1899     ebin->muxer = NULL;
1900     return FALSE;
1901   }
1902 }
1903
1904 static void
1905 release_pads (const GValue * item, GstElement * elt)
1906 {
1907   GstPad *pad = g_value_get_object (item);
1908   GstPad *peer = NULL;
1909
1910   GST_DEBUG_OBJECT (elt, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1911
1912   /* Unlink from its peer pad */
1913   if ((peer = gst_pad_get_peer (pad))) {
1914     if (GST_PAD_DIRECTION (peer) == GST_PAD_SRC)
1915       gst_pad_unlink (peer, pad);
1916     else
1917       gst_pad_unlink (pad, peer);
1918     gst_object_unref (peer);
1919   }
1920
1921   /* Release it from the object */
1922   gst_element_release_request_pad (elt, pad);
1923 }
1924
1925 static void
1926 stream_group_free (GstEncodeBin * ebin, StreamGroup * sgroup)
1927 {
1928   GList *tmp;
1929   GstPad *tmppad;
1930   GstPad *pad;
1931
1932   GST_DEBUG_OBJECT (ebin, "Freeing StreamGroup %p", sgroup);
1933
1934   if (sgroup->restriction_sid != 0)
1935     g_signal_handler_disconnect (sgroup->profile, sgroup->restriction_sid);
1936
1937   if (ebin->muxer) {
1938     /* outqueue - Muxer */
1939     tmppad = gst_element_get_static_pad (sgroup->outqueue, "src");
1940     pad = gst_pad_get_peer (tmppad);
1941
1942     if (pad) {
1943       /* Remove muxer request sink pad */
1944       gst_pad_unlink (tmppad, pad);
1945       if (GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) ==
1946           GST_PAD_REQUEST)
1947         gst_element_release_request_pad (ebin->muxer, pad);
1948       gst_object_unref (pad);
1949     }
1950     gst_object_unref (tmppad);
1951   }
1952   if (sgroup->outqueue)
1953     gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
1954
1955   if (sgroup->formatter) {
1956     /* capsfilter - formatter - outqueue */
1957     gst_element_set_state (sgroup->formatter, GST_STATE_NULL);
1958     gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1959     gst_element_unlink (sgroup->formatter, sgroup->outqueue);
1960     gst_element_unlink (sgroup->outfilter, sgroup->formatter);
1961   } else {
1962     /* Capsfilter - outqueue */
1963     gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1964     gst_element_unlink (sgroup->outfilter, sgroup->outqueue);
1965   }
1966   gst_element_set_state (sgroup->outqueue, GST_STATE_NULL);
1967   gst_bin_remove (GST_BIN (ebin), sgroup->outqueue);
1968
1969   /* streamcombiner - parser - capsfilter */
1970   if (sgroup->parser) {
1971     gst_element_set_state (sgroup->parser, GST_STATE_NULL);
1972     gst_element_unlink (sgroup->parser, sgroup->outfilter);
1973     gst_element_unlink (sgroup->combiner, sgroup->parser);
1974     gst_bin_remove ((GstBin *) ebin, sgroup->parser);
1975   }
1976
1977   /* Sink Ghostpad */
1978   if (sgroup->ghostpad) {
1979     if (GST_PAD_PARENT (sgroup->ghostpad) != NULL)
1980       gst_element_remove_pad (GST_ELEMENT_CAST (ebin), sgroup->ghostpad);
1981     else
1982       gst_object_unref (sgroup->ghostpad);
1983   }
1984
1985   if (sgroup->inqueue)
1986     gst_element_set_state (sgroup->inqueue, GST_STATE_NULL);
1987
1988   if (sgroup->encoder)
1989     gst_element_set_state (sgroup->encoder, GST_STATE_NULL);
1990   if (sgroup->fakesink)
1991     gst_element_set_state (sgroup->fakesink, GST_STATE_NULL);
1992   if (sgroup->outfilter)
1993     gst_element_set_state (sgroup->outfilter, GST_STATE_NULL);
1994   if (sgroup->smartencoder)
1995     gst_element_set_state (sgroup->smartencoder, GST_STATE_NULL);
1996
1997   if (sgroup->capsfilter) {
1998     gst_element_set_state (sgroup->capsfilter, GST_STATE_NULL);
1999     if (sgroup->encoder)
2000       gst_element_unlink (sgroup->capsfilter, sgroup->encoder);
2001     else
2002       gst_element_unlink (sgroup->capsfilter, sgroup->fakesink);
2003     gst_bin_remove ((GstBin *) ebin, sgroup->capsfilter);
2004   }
2005
2006   for (tmp = sgroup->converters; tmp; tmp = tmp->next) {
2007     GstElement *elt = (GstElement *) tmp->data;
2008
2009     gst_element_set_state (elt, GST_STATE_NULL);
2010     gst_bin_remove ((GstBin *) ebin, elt);
2011   }
2012   if (sgroup->converters)
2013     g_list_free (sgroup->converters);
2014
2015   if (sgroup->combiner) {
2016     GstIterator *it = gst_element_iterate_sink_pads (sgroup->combiner);
2017     GstIteratorResult itret = GST_ITERATOR_OK;
2018
2019     while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
2020       itret =
2021           gst_iterator_foreach (it, (GstIteratorForeachFunction) release_pads,
2022           sgroup->combiner);
2023       gst_iterator_resync (it);
2024     }
2025     gst_iterator_free (it);
2026     gst_element_set_state (sgroup->combiner, GST_STATE_NULL);
2027     gst_bin_remove ((GstBin *) ebin, sgroup->combiner);
2028   }
2029
2030   if (sgroup->splitter) {
2031     GstIterator *it = gst_element_iterate_src_pads (sgroup->splitter);
2032     GstIteratorResult itret = GST_ITERATOR_OK;
2033     while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) {
2034       itret =
2035           gst_iterator_foreach (it, (GstIteratorForeachFunction) release_pads,
2036           sgroup->splitter);
2037       gst_iterator_resync (it);
2038     }
2039     gst_iterator_free (it);
2040
2041     gst_element_set_state (sgroup->splitter, GST_STATE_NULL);
2042     gst_bin_remove ((GstBin *) ebin, sgroup->splitter);
2043   }
2044
2045   if (sgroup->inqueue)
2046     gst_bin_remove ((GstBin *) ebin, sgroup->inqueue);
2047
2048   if (sgroup->encoder)
2049     gst_bin_remove ((GstBin *) ebin, sgroup->encoder);
2050
2051   if (sgroup->fakesink)
2052     gst_bin_remove ((GstBin *) ebin, sgroup->fakesink);
2053
2054   if (sgroup->smartencoder)
2055     gst_bin_remove ((GstBin *) ebin, sgroup->smartencoder);
2056
2057   if (sgroup->outfilter)
2058     gst_bin_remove ((GstBin *) ebin, sgroup->outfilter);
2059
2060   g_slice_free (StreamGroup, sgroup);
2061 }
2062
2063 static void
2064 stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup)
2065 {
2066   ebin->streams = g_list_remove (ebin->streams, sgroup);
2067
2068   stream_group_free (ebin, sgroup);
2069 }
2070
2071 static void
2072 gst_encode_bin_tear_down_profile (GstEncodeBin * ebin)
2073 {
2074   if (G_UNLIKELY (ebin->profile == NULL))
2075     return;
2076
2077   GST_DEBUG ("Tearing down profile %s",
2078       gst_encoding_profile_get_name (ebin->profile));
2079
2080   while (ebin->streams)
2081     stream_group_remove (ebin, (StreamGroup *) ebin->streams->data);
2082
2083   /* Set ghostpad target to NULL */
2084   gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), NULL);
2085
2086   /* Remove muxer if present */
2087   if (ebin->muxer) {
2088     gst_element_set_state (ebin->muxer, GST_STATE_NULL);
2089     gst_bin_remove (GST_BIN (ebin), ebin->muxer);
2090     ebin->muxer = NULL;
2091   }
2092
2093   /* free/clear profile */
2094   gst_encoding_profile_unref (ebin->profile);
2095   ebin->profile = NULL;
2096 }
2097
2098 static gboolean
2099 gst_encode_bin_setup_profile (GstEncodeBin * ebin, GstEncodingProfile * profile)
2100 {
2101   gboolean res;
2102
2103   g_return_val_if_fail (ebin->profile == NULL, FALSE);
2104
2105   GST_DEBUG ("Setting up profile %p:%s (type:%s)", profile,
2106       gst_encoding_profile_get_name (profile),
2107       gst_encoding_profile_get_type_nick (profile));
2108
2109   ebin->profile = profile;
2110   gst_object_ref (ebin->profile);
2111
2112   /* Create elements */
2113   res = create_elements_and_pads (ebin);
2114   if (res == FALSE)
2115     gst_encode_bin_tear_down_profile (ebin);
2116
2117   return res;
2118 }
2119
2120 static gboolean
2121 gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile)
2122 {
2123   g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
2124
2125   GST_DEBUG_OBJECT (ebin, "profile (%p) : %s", profile,
2126       gst_encoding_profile_get_name (profile));
2127
2128   if (G_UNLIKELY (ebin->active)) {
2129     GST_WARNING_OBJECT (ebin, "Element already active, can't change profile");
2130     return FALSE;
2131   }
2132
2133   /* If we're not active, we can deactivate the previous profile */
2134   if (ebin->profile) {
2135     gst_encode_bin_tear_down_profile (ebin);
2136   }
2137
2138   return gst_encode_bin_setup_profile (ebin, profile);
2139 }
2140
2141 static inline gboolean
2142 gst_encode_bin_activate (GstEncodeBin * ebin)
2143 {
2144   ebin->active = ebin->profile != NULL;
2145   return ebin->active;
2146 }
2147
2148 static void
2149 gst_encode_bin_deactivate (GstEncodeBin * ebin)
2150 {
2151   ebin->active = FALSE;
2152 }
2153
2154 static GstStateChangeReturn
2155 gst_encode_bin_change_state (GstElement * element, GstStateChange transition)
2156 {
2157   GstStateChangeReturn ret;
2158   GstEncodeBin *ebin = (GstEncodeBin *) element;
2159
2160   switch (transition) {
2161     case GST_STATE_CHANGE_READY_TO_PAUSED:
2162     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2163       if (!gst_encode_bin_activate (ebin)) {
2164         ret = GST_STATE_CHANGE_FAILURE;
2165         goto beach;
2166       }
2167       break;
2168     default:
2169       break;
2170   }
2171
2172   ret =
2173       GST_ELEMENT_CLASS (gst_encode_bin_parent_class)->change_state (element,
2174       transition);
2175   if (ret == GST_STATE_CHANGE_FAILURE)
2176     goto beach;
2177
2178   switch (transition) {
2179     case GST_STATE_CHANGE_PAUSED_TO_READY:
2180       gst_encode_bin_deactivate (ebin);
2181       break;
2182     default:
2183       break;
2184   }
2185
2186 beach:
2187   return ret;
2188 }
2189
2190
2191 static gboolean
2192 plugin_init (GstPlugin * plugin)
2193 {
2194   gboolean res;
2195
2196   GST_DEBUG_CATEGORY_INIT (gst_encode_bin_debug, "encodebin", 0, "encoder bin");
2197
2198 #ifdef ENABLE_NLS
2199   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
2200       LOCALEDIR);
2201   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
2202   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2203 #endif /* ENABLE_NLS */
2204
2205
2206   res = gst_element_register (plugin, "encodebin", GST_RANK_NONE,
2207       GST_TYPE_ENCODE_BIN);
2208
2209   return res;
2210 }
2211
2212 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2213     GST_VERSION_MINOR,
2214     encoding,
2215     "various encoding-related elements", plugin_init, VERSION, GST_LICENSE,
2216     GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)