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