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