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