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