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