rtsp: Port to GIO
[platform/upstream/gstreamer.git] / gst-libs / gst / pbutils / encoding-profile.c
1 /* GStreamer encoding profiles library
2  * Copyright (C) 2009-2010 Edward Hervey <edward.hervey@collabora.co.uk>
3  *           (C) 2009-2010 Nokia Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * SECTION:encoding-profile
23  * @short_description: Encoding profile library
24  *
25  * <refsect2>
26  * <para>
27  * Functions to create and handle encoding profiles.
28  * </para>
29  * <para>
30  * Encoding profiles describe the media types and settings one wishes to use for
31  * an encoding process. The top-level profiles are commonly
32  * #GstEncodingContainerProfile(s) (which contains a user-readable name and
33  * description along with which container format to use). These, in turn,
34  * reference one or more #GstEncodingProfile(s) which indicate which encoding
35  * format should be used on each individual streams.
36  * </para>
37  * <para>
38  * #GstEncodingProfile(s) can be provided to the 'encodebin' element, which will take
39  * care of selecting and setting up the required elements to produce an output stream
40  * conforming to the specifications of the profile.
41  * </para>
42  * <para>
43  * Unlike other systems, the encoding profiles do not specify which #GstElement to use
44  * for the various encoding and muxing steps, but instead relies on specifying the format
45  * one wishes to use.
46  * </para>
47  * <para>
48  * Encoding profiles can be created at runtime by the application or loaded from (and saved
49  * to) file using the #GstEncodingTarget API.
50  * </para>
51  * </refsect2>
52  * <refsect2>
53  * <title>Example: Creating a profile</title>
54  * <para>
55  * |[
56  * #include <gst/pbutils/encoding-profile.h>
57  * ...
58  * GstEncodingProfile *
59  * create_ogg_theora_profile(void)
60  *{
61  *  GstEncodingContainerProfile *prof;
62  *  GstCaps *caps;
63  *
64  *  caps = gst_caps_from_string("application/ogg");
65  *  prof = gst_encoding_container_profile_new("Ogg audio/video",
66  *     "Standard OGG/THEORA/VORBIS",
67  *     caps, NULL);
68  *  gst_caps_unref (caps);
69  *
70  *  caps = gst_caps_from_string("video/x-theora");
71  *  gst_encoding_container_profile_add_profile(prof,
72  *       (GstEncodingProfile*) gst_encoding_video_profile_new(caps, NULL, NULL, 0));
73  *  gst_caps_unref (caps);
74  *
75  *  caps = gst_caps_from_string("audio/x-vorbis");
76  *  gst_encoding_container_profile_add_profile(prof,
77  *       (GstEncodingProfile*) gst_encoding_audio_profile_new(caps, NULL, NULL, 0));
78  *  gst_caps_unref (caps);
79  *
80  *  return (GstEncodingProfile*) prof;
81  *}
82  *
83  *
84  * ]|
85  * </para>
86  * </refsect2>
87  * <refsect2>
88  * <title>Example: Listing categories, targets and profiles</title>
89  * <para>
90  * |[
91  * #include <gst/pbutils/encoding-profile.h>
92  * ...
93  * GstEncodingProfile *prof;
94  * GList *categories, *tmpc;
95  * GList *targets, *tmpt;
96  * ...
97  * categories = gst_encoding_target_list_available_categories();
98  *
99  * ... Show available categories to user ...
100  *
101  * for (tmpc = categories; tmpc; tmpc = tmpc->next) {
102  *   gchar *category = (gchar *) tmpc->data;
103  *
104  *   ... and we can list all targets within that category ...
105  *   
106  *   targets = gst_encoding_target_list_all (category);
107  *
108  *   ... and show a list to our users ...
109  *
110  *   g_list_foreach (targets, (GFunc) gst_encoding_target_unref, NULL);
111  *   g_list_free (targets);
112  * }
113  *
114  * g_list_foreach (categories, (GFunc) g_free, NULL);
115  * g_list_free (categories);
116  *
117  * ...
118  * ]|
119  * </para>
120  * </refsect2>
121  *
122  * Since: 0.10.32
123  */
124
125 #ifdef HAVE_CONFIG_H
126 #  include "config.h"
127 #endif
128
129 #include "encoding-profile.h"
130 #include "encoding-target.h"
131
132 /* GstEncodingProfile API */
133
134 struct _GstEncodingProfile
135 {
136   GObject parent;
137
138   /*< public > */
139   gchar *name;
140   gchar *description;
141   GstCaps *format;
142   gchar *preset;
143   guint presence;
144   GstCaps *restriction;
145 };
146
147 static void string_to_profile_transform (const GValue * src_value,
148     GValue * dest_value);
149 static gboolean gst_encoding_profile_deserialize_valfunc (GValue * value,
150     const gchar * s);
151
152 static void gst_encoding_profile_class_init (GstEncodingProfileClass * klass);
153 static gpointer gst_encoding_profile_parent_class = NULL;
154
155 static void
156 gst_encoding_profile_class_intern_init (gpointer klass)
157 {
158   gst_encoding_profile_parent_class = g_type_class_peek_parent (klass);
159   gst_encoding_profile_class_init ((GstEncodingProfileClass *) klass);
160 }
161
162 GType
163 gst_encoding_profile_get_type (void)
164 {
165   static volatile gsize g_define_type_id__volatile = 0;
166
167   if (g_once_init_enter (&g_define_type_id__volatile)) {
168     GType g_define_type_id = g_type_register_static_simple (G_TYPE_OBJECT,
169         g_intern_static_string ("GstEncodingProfile"),
170         sizeof (GstEncodingProfileClass),
171         (GClassInitFunc) gst_encoding_profile_class_intern_init,
172         sizeof (GstEncodingProfile),
173         NULL,
174         (GTypeFlags) 0);
175     static GstValueTable gstvtable = {
176       G_TYPE_NONE,
177       (GstValueCompareFunc) NULL,
178       (GstValueSerializeFunc) NULL,
179       (GstValueDeserializeFunc) gst_encoding_profile_deserialize_valfunc
180     };
181
182     gstvtable.type = g_define_type_id;
183
184     /* Register a STRING=>PROFILE GValueTransformFunc */
185     g_value_register_transform_func (G_TYPE_STRING, g_define_type_id,
186         string_to_profile_transform);
187     /* Register gst-specific GValue functions */
188     gst_value_register (&gstvtable);
189
190     g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
191   }
192   return g_define_type_id__volatile;
193 }
194
195 static void
196 gst_encoding_profile_finalize (GObject * object)
197 {
198   GstEncodingProfile *prof = (GstEncodingProfile *) object;
199   if (prof->name)
200     g_free (prof->name);
201   if (prof->format)
202     gst_caps_unref (prof->format);
203   if (prof->preset)
204     g_free (prof->preset);
205   if (prof->description)
206     g_free (prof->description);
207   if (prof->restriction)
208     gst_caps_unref (prof->restriction);
209 }
210
211 static void
212 gst_encoding_profile_class_init (GObjectClass * klass)
213 {
214   klass->finalize = gst_encoding_profile_finalize;
215 }
216
217 /**
218  * gst_encoding_profile_get_name:
219  * @profile: a #GstEncodingProfile
220  *
221  * Since: 0.10.32
222  *
223  * Returns: the name of the profile, can be %NULL.
224  */
225 const gchar *
226 gst_encoding_profile_get_name (GstEncodingProfile * profile)
227 {
228   return profile->name;
229 }
230
231 /**
232  * gst_encoding_profile_get_description:
233  * @profile: a #GstEncodingProfile
234  *
235  * Since: 0.10.32
236  *
237  * Returns: the description of the profile, can be %NULL.
238  */
239 const gchar *
240 gst_encoding_profile_get_description (GstEncodingProfile * profile)
241 {
242   return profile->description;
243 }
244
245 /**
246  * gst_encoding_profile_get_format:
247  * @profile: a #GstEncodingProfile
248  *
249  * Since: 0.10.32
250  *
251  * Returns: (transfer full): the #GstCaps corresponding to the media format used
252  * in the profile. Unref after usage.
253  */
254 GstCaps *
255 gst_encoding_profile_get_format (GstEncodingProfile * profile)
256 {
257   return (profile->format ? gst_caps_ref (profile->format) : NULL);
258 }
259
260 /**
261  * gst_encoding_profile_get_preset:
262  * @profile: a #GstEncodingProfile
263  *
264  * Since: 0.10.32
265  *
266  * Returns: the name of the #GstPreset to be used in the profile.
267  */
268 const gchar *
269 gst_encoding_profile_get_preset (GstEncodingProfile * profile)
270 {
271   return profile->preset;
272 }
273
274 /**
275  * gst_encoding_profile_get_presence:
276  * @profile: a #GstEncodingProfile
277  *
278  * Since: 0.10.32
279  *
280  * Returns: The number of times the profile is used in its parent
281  * container profile. If 0, it is not a mandatory stream.
282  */
283 guint
284 gst_encoding_profile_get_presence (GstEncodingProfile * profile)
285 {
286   return profile->presence;
287 }
288
289 /**
290  * gst_encoding_profile_get_restriction:
291  * @profile: a #GstEncodingProfile
292  *
293  * Since: 0.10.32
294  *
295  * Returns: (transfer full): The restriction #GstCaps to apply before the encoder
296  * that will be used in the profile. The fields present in restriction caps are
297  * properties of the raw stream (that is before encoding), such as height and
298  * width for video and depth and sampling rate for audio. Does not apply to
299  * #GstEncodingContainerProfile (since there is no corresponding raw stream).
300  * Can be %NULL. Unref after usage.
301  */
302 GstCaps *
303 gst_encoding_profile_get_restriction (GstEncodingProfile * profile)
304 {
305   return (profile->restriction ? gst_caps_ref (profile->restriction) : NULL);
306 }
307
308 /**
309  * gst_encoding_profile_set_name:
310  * @profile: a #GstEncodingProfile
311  * @name: the name to set on the profile
312  *
313  * Set @name as the given name for the @profile. A copy of @name will be made
314  * internally.
315  *
316  * Since: 0.10.32
317  */
318 void
319 gst_encoding_profile_set_name (GstEncodingProfile * profile, const gchar * name)
320 {
321   if (profile->name)
322     g_free (profile->name);
323   profile->name = g_strdup (name);
324 }
325
326 /**
327  * gst_encoding_profile_set_description:
328  * @profile: a #GstEncodingProfile
329  * @description: the description to set on the profile
330  *
331  * Set @description as the given description for the @profile. A copy of
332  * @description will be made internally.
333  *
334  * Since: 0.10.32
335  */
336 void
337 gst_encoding_profile_set_description (GstEncodingProfile * profile,
338     const gchar * description)
339 {
340   if (profile->description)
341     g_free (profile->description);
342   profile->description = g_strdup (description);
343 }
344
345 /**
346  * gst_encoding_profile_set_format:
347  * @profile: a #GstEncodingProfile
348  * @format: the media format to use in the profile.
349  *
350  * Sets the media format used in the profile.
351  *
352  * Since: 0.10.32
353  */
354 void
355 gst_encoding_profile_set_format (GstEncodingProfile * profile, GstCaps * format)
356 {
357   if (profile->format)
358     gst_caps_unref (profile->format);
359   profile->format = gst_caps_ref (format);
360 }
361
362 /**
363  * gst_encoding_profile_set_preset:
364  * @profile: a #GstEncodingProfile
365  * @preset: the element preset to use
366  *
367  * Sets the preset to use for the profile.
368  *
369  * Since: 0.10.32
370  */
371 void
372 gst_encoding_profile_set_preset (GstEncodingProfile * profile,
373     const gchar * preset)
374 {
375   if (profile->preset)
376     g_free (profile->preset);
377   profile->preset = g_strdup (preset);
378 }
379
380 /**
381  * gst_encoding_profile_set_presence:
382  * @profile: a #GstEncodingProfile
383  * @presence: the number of time the profile can be used
384  *
385  * Set the number of time the profile is used in its parent
386  * container profile. If 0, it is not a mandatory stream
387  *
388  * Since: 0.10.32
389  */
390 void
391 gst_encoding_profile_set_presence (GstEncodingProfile * profile, guint presence)
392 {
393   profile->presence = presence;
394 }
395
396 /**
397  * gst_encoding_profile_set_restriction:
398  * @profile: a #GstEncodingProfile
399  * @restriction: the restriction to apply
400  *
401  * Set the restriction #GstCaps to apply before the encoder
402  * that will be used in the profile. See gst_encoding_profile_set_restriction()
403  * for more about restrictions. Does not apply to #GstEncodingContainerProfile.
404  *
405  * Since: 0.10.32
406  */
407 void
408 gst_encoding_profile_set_restriction (GstEncodingProfile * profile,
409     GstCaps * restriction)
410 {
411   if (profile->restriction)
412     gst_caps_unref (profile->restriction);
413   profile->restriction = restriction;
414 }
415
416 /* Container profiles */
417
418 struct _GstEncodingContainerProfile
419 {
420   GstEncodingProfile parent;
421
422   GList *encodingprofiles;
423 };
424
425 G_DEFINE_TYPE (GstEncodingContainerProfile, gst_encoding_container_profile,
426     GST_TYPE_ENCODING_PROFILE);
427
428 static void
429 gst_encoding_container_profile_init (GstEncodingContainerProfile * prof)
430 {
431   /* Nothing to initialize */
432 }
433
434 static void
435 gst_encoding_container_profile_finalize (GObject * object)
436 {
437   GstEncodingContainerProfile *prof = (GstEncodingContainerProfile *) object;
438
439   g_list_foreach (prof->encodingprofiles, (GFunc) g_object_unref, NULL);
440   g_list_free (prof->encodingprofiles);
441
442   G_OBJECT_CLASS (gst_encoding_container_profile_parent_class)->finalize
443       ((GObject *) prof);
444 }
445
446 static void
447 gst_encoding_container_profile_class_init (GObjectClass * klass)
448 {
449   klass->finalize = gst_encoding_container_profile_finalize;
450 }
451
452 /**
453  * gst_encoding_container_profile_get_profiles:
454  * @profile: a #GstEncodingContainerProfile
455  *
456  * Returns: (element-type GstPbutils.EncodingProfile) (transfer none):
457  * the list of contained #GstEncodingProfile.
458  */
459 const GList *
460 gst_encoding_container_profile_get_profiles (GstEncodingContainerProfile *
461     profile)
462 {
463   return profile->encodingprofiles;
464 }
465
466 /* Video profiles */
467
468 struct _GstEncodingVideoProfile
469 {
470   GstEncodingProfile parent;
471
472   guint pass;
473   gboolean variableframerate;
474 };
475
476 G_DEFINE_TYPE (GstEncodingVideoProfile, gst_encoding_video_profile,
477     GST_TYPE_ENCODING_PROFILE);
478
479 static void
480 gst_encoding_video_profile_init (GstEncodingVideoProfile * prof)
481 {
482   /* Nothing to initialize */
483 }
484
485 static void
486 gst_encoding_video_profile_class_init (GObjectClass * klass)
487 {
488 }
489
490 /**
491  * gst_encoding_video_profile_get_pass:
492  * @prof: a #GstEncodingVideoProfile
493  *
494  * Get the pass number if this is part of a multi-pass profile.
495  *
496  * Returns: The pass number. Starts at 1 for multi-pass. 0 if this is
497  * not a multi-pass profile
498  *
499  * Since: 0.10.32
500  */
501 guint
502 gst_encoding_video_profile_get_pass (GstEncodingVideoProfile * prof)
503 {
504   return prof->pass;
505 }
506
507 /**
508  * gst_encoding_video_profile_get_variableframerate:
509  * @prof: a #GstEncodingVideoProfile
510  *
511  * Since: 0.10.32
512  *
513  * Returns: Whether non-constant video framerate is allowed for encoding.
514  */
515 gboolean
516 gst_encoding_video_profile_get_variableframerate (GstEncodingVideoProfile *
517     prof)
518 {
519   return prof->variableframerate;
520 }
521
522 /**
523  * gst_encoding_video_profile_set_pass:
524  * @prof: a #GstEncodingVideoProfile
525  * @pass: the pass number for this profile
526  *
527  * Sets the pass number of this video profile. The first pass profile should have
528  * this value set to 1. If this video profile isn't part of a multi-pass profile,
529  * you may set it to 0 (the default value).
530  *
531  * Since: 0.10.32
532  */
533 void
534 gst_encoding_video_profile_set_pass (GstEncodingVideoProfile * prof, guint pass)
535 {
536   prof->pass = pass;
537 }
538
539 /**
540  * gst_encoding_video_profile_set_variableframerate:
541  * @prof: a #GstEncodingVideoProfile
542  * @variableframerate: a boolean
543  *
544  * If set to %TRUE, then the incoming stream will be allowed to have non-constant
545  * framerate. If set to %FALSE (default value), then the incoming stream will
546  * be normalized by dropping/duplicating frames in order to produce a
547  * constance framerate.
548  *
549  * Since: 0.10.32
550  */
551 void
552 gst_encoding_video_profile_set_variableframerate (GstEncodingVideoProfile *
553     prof, gboolean variableframerate)
554 {
555   prof->variableframerate = variableframerate;
556 }
557
558 /* Audio profiles */
559
560 struct _GstEncodingAudioProfile
561 {
562   GstEncodingProfile parent;
563 };
564
565 G_DEFINE_TYPE (GstEncodingAudioProfile, gst_encoding_audio_profile,
566     GST_TYPE_ENCODING_PROFILE);
567
568 static void
569 gst_encoding_audio_profile_init (GstEncodingAudioProfile * prof)
570 {
571   /* Nothing to initialize */
572 }
573
574 static void
575 gst_encoding_audio_profile_class_init (GObjectClass * klass)
576 {
577 }
578
579 static inline gboolean
580 _gst_caps_is_equal_safe (GstCaps * a, GstCaps * b)
581 {
582   if (a == b)
583     return TRUE;
584   if ((a == NULL) || (b == NULL))
585     return FALSE;
586   return gst_caps_is_equal (a, b);
587 }
588
589 static gint
590 _compare_container_encoding_profiles (GstEncodingContainerProfile * ca,
591     GstEncodingContainerProfile * cb)
592 {
593   GList *tmp;
594
595   if (g_list_length (ca->encodingprofiles) !=
596       g_list_length (cb->encodingprofiles))
597     return -1;
598
599   for (tmp = ca->encodingprofiles; tmp; tmp = tmp->next) {
600     GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data;
601     if (!gst_encoding_container_profile_contains_profile (ca, prof))
602       return -1;
603   }
604
605   return 0;
606 }
607
608 static gint
609 _compare_encoding_profiles (const GstEncodingProfile * a,
610     const GstEncodingProfile * b)
611 {
612   if ((G_TYPE_FROM_INSTANCE (a) != G_TYPE_FROM_INSTANCE (b)) ||
613       !_gst_caps_is_equal_safe (a->format, b->format) ||
614       (g_strcmp0 (a->preset, b->preset) != 0) ||
615       (g_strcmp0 (a->name, b->name) != 0) ||
616       (g_strcmp0 (a->description, b->description) != 0))
617     return -1;
618
619   if (GST_IS_ENCODING_CONTAINER_PROFILE (a))
620     return
621         _compare_container_encoding_profiles (GST_ENCODING_CONTAINER_PROFILE
622         (a), GST_ENCODING_CONTAINER_PROFILE (b));
623
624   if (GST_IS_ENCODING_VIDEO_PROFILE (a)) {
625     GstEncodingVideoProfile *va = (GstEncodingVideoProfile *) a;
626     GstEncodingVideoProfile *vb = (GstEncodingVideoProfile *) b;
627
628     if ((va->pass != vb->pass)
629         || (va->variableframerate != vb->variableframerate))
630       return -1;
631   }
632
633   return 0;
634 }
635
636 /**
637  * gst_encoding_container_profile_contains_profile:
638  * @container: a #GstEncodingContainerProfile
639  * @profile: a #GstEncodingProfile
640  *
641  * Checks if @container contains a #GstEncodingProfile identical to
642  * @profile.
643  *
644  * Since: 0.10.32
645  *
646  * Returns: %TRUE if @container contains a #GstEncodingProfile identical
647  * to @profile, else %FALSE.
648  */
649 gboolean
650 gst_encoding_container_profile_contains_profile (GstEncodingContainerProfile *
651     container, GstEncodingProfile * profile)
652 {
653   g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
654   g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
655
656   return (g_list_find_custom (container->encodingprofiles, profile,
657           (GCompareFunc) _compare_encoding_profiles) != NULL);
658 }
659
660 /**
661  * gst_encoding_container_profile_add_profile:
662  * @container: the #GstEncodingContainerProfile to use
663  * @profile: the #GstEncodingProfile to add.
664  *
665  * Add a #GstEncodingProfile to the list of profiles handled by @container.
666  * 
667  * No copy of @profile will be made, if you wish to use it elsewhere after this
668  * method you should increment its reference count.
669  *
670  * Since: 0.10.32
671  *
672  * Returns: %TRUE if the @stream was properly added, else %FALSE.
673  */
674 gboolean
675 gst_encoding_container_profile_add_profile (GstEncodingContainerProfile *
676     container, GstEncodingProfile * profile)
677 {
678   g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
679   g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
680
681   if (g_list_find_custom (container->encodingprofiles, profile,
682           (GCompareFunc) _compare_encoding_profiles)) {
683     GST_ERROR
684         ("Encoding profile already contains an identical GstEncodingProfile");
685     return FALSE;
686   }
687
688   container->encodingprofiles =
689       g_list_append (container->encodingprofiles, profile);
690
691   return TRUE;
692 }
693
694 static GstEncodingProfile *
695 common_creation (GType objtype, GstCaps * format, const gchar * preset,
696     const gchar * name, const gchar * description, GstCaps * restriction,
697     guint presence)
698 {
699   GstEncodingProfile *prof;
700
701   prof = (GstEncodingProfile *) g_object_new (objtype, NULL);
702
703   if (name)
704     prof->name = g_strdup (name);
705   if (description)
706     prof->description = g_strdup (description);
707   if (preset)
708     prof->preset = g_strdup (preset);
709   if (format)
710     prof->format = gst_caps_ref (format);
711   if (restriction)
712     prof->restriction = gst_caps_ref (restriction);
713   prof->presence = presence;
714
715   return prof;
716 }
717
718 /**
719  * gst_encoding_container_profile_new:
720  * @name: (allow-none): The name of the container profile, can be %NULL
721  * @description: (allow-none): The description of the container profile,
722  *     can be %NULL
723  * @format: The format to use for this profile
724  * @preset: (allow-none): The preset to use for this profile
725  *
726  * Creates a new #GstEncodingContainerProfile.
727  *
728  * Since: 0.10.32
729  *
730  * Returns: The newly created #GstEncodingContainerProfile.
731  */
732 GstEncodingContainerProfile *
733 gst_encoding_container_profile_new (const gchar * name,
734     const gchar * description, GstCaps * format, const gchar * preset)
735 {
736   g_return_val_if_fail (GST_IS_CAPS (format), NULL);
737
738   return (GstEncodingContainerProfile *)
739       common_creation (GST_TYPE_ENCODING_CONTAINER_PROFILE, format, preset,
740       name, description, NULL, 0);
741 }
742
743 /**
744  * gst_encoding_video_profile_new:
745  * @format: the #GstCaps
746  * @preset: (allow-none): the preset(s) to use on the encoder, can be #NULL
747  * @restriction: (allow-none) the #GstCaps used to restrict the input to the encoder, can be
748  * NULL. See gst_encoding_profile_get_restriction() for more details.
749  * @presence: the number of time this stream must be used. 0 means any number of
750  *  times (including never)
751  *
752  * Creates a new #GstEncodingVideoProfile
753  *
754  * All provided allocatable arguments will be internally copied, so can be
755  * safely freed/unreferenced after calling this method.
756  *
757  * If you wish to control the pass number (in case of multi-pass scenarios),
758  * please refer to the gst_encoding_video_profile_set_pass() documentation.
759  *
760  * If you wish to use/force a constant framerate please refer to the
761  * gst_encoding_video_profile_set_variableframerate() documentation.
762  *
763  * Since: 0.10.32
764  *
765  * Returns: the newly created #GstEncodingVideoProfile.
766  */
767 GstEncodingVideoProfile *
768 gst_encoding_video_profile_new (GstCaps * format, const gchar * preset,
769     GstCaps * restriction, guint presence)
770 {
771   return (GstEncodingVideoProfile *)
772       common_creation (GST_TYPE_ENCODING_VIDEO_PROFILE, format, preset, NULL,
773       NULL, restriction, presence);
774 }
775
776 /**
777  * gst_encoding_audio_profile_new:
778  * @format: the #GstCaps
779  * @preset: (allow-none): the preset(s) to use on the encoder, can be #NULL
780  * @restriction: (allow-none): the #GstCaps used to restrict the input to the encoder, can be
781  * NULL. See gst_encoding_profile_get_restriction() for more details.
782  * @presence: the number of time this stream must be used. 0 means any number of
783  *  times (including never)
784  *
785  * Creates a new #GstEncodingAudioProfile
786  *
787  * All provided allocatable arguments will be internally copied, so can be
788  * safely freed/unreferenced after calling this method.
789  *
790  * Since: 0.10.32
791  *
792  * Returns: the newly created #GstEncodingAudioProfile.
793  */
794 GstEncodingAudioProfile *
795 gst_encoding_audio_profile_new (GstCaps * format, const gchar * preset,
796     GstCaps * restriction, guint presence)
797 {
798   return (GstEncodingAudioProfile *)
799       common_creation (GST_TYPE_ENCODING_AUDIO_PROFILE, format, preset, NULL,
800       NULL, restriction, presence);
801 }
802
803
804 /**
805  * gst_encoding_profile_is_equal:
806  * @a: a #GstEncodingProfile
807  * @b: a #GstEncodingProfile
808  *
809  * Checks whether the two #GstEncodingProfile are equal
810  *
811  * Since: 0.10.32
812  *
813  * Returns: %TRUE if @a and @b are equal, else %FALSE.
814  */
815 gboolean
816 gst_encoding_profile_is_equal (GstEncodingProfile * a, GstEncodingProfile * b)
817 {
818   return (_compare_encoding_profiles (a, b) == 0);
819 }
820
821
822 /**
823  * gst_encoding_profile_get_input_caps:
824  * @profile: a #GstEncodingProfile
825  *
826  * Computes the full output caps that this @profile will be able to consume.
827  *
828  * Since: 0.10.32
829  *
830  * Returns: (transfer full): The full caps the given @profile can consume. Call
831  * gst_caps_unref() when you are done with the caps.
832  */
833 GstCaps *
834 gst_encoding_profile_get_input_caps (GstEncodingProfile * profile)
835 {
836   GstCaps *out, *tmp;
837   GList *ltmp;
838   GstStructure *st, *outst;
839   GQuark out_name;
840   guint i, len;
841   GstCaps *fcaps;
842
843   if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
844     GstCaps *res = gst_caps_new_empty ();
845
846     for (ltmp = GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles;
847         ltmp; ltmp = ltmp->next) {
848       GstEncodingProfile *sprof = (GstEncodingProfile *) ltmp->data;
849       gst_caps_merge (res, gst_encoding_profile_get_input_caps (sprof));
850     }
851     return res;
852   }
853
854   fcaps = profile->format;
855
856   /* fast-path */
857   if ((profile->restriction == NULL) || gst_caps_is_any (profile->restriction))
858     return gst_caps_ref (fcaps);
859
860   /* Combine the format with the restriction caps */
861   outst = gst_caps_get_structure (fcaps, 0);
862   out_name = gst_structure_get_name_id (outst);
863   tmp = gst_caps_new_empty ();
864   len = gst_caps_get_size (profile->restriction);
865
866   for (i = 0; i < len; i++) {
867     st = gst_structure_copy (gst_caps_get_structure (profile->restriction, i));
868     st->name = out_name;
869     gst_caps_append_structure (tmp, st);
870   }
871
872   out = gst_caps_intersect (tmp, fcaps);
873   gst_caps_unref (tmp);
874
875   return out;
876 }
877
878 /**
879  * gst_encoding_profile_get_type_nick:
880  * @profile: a #GstEncodingProfile
881  *
882  * Since: 0.10.32
883  *
884  * Returns: the human-readable name of the type of @profile.
885  */
886 const gchar *
887 gst_encoding_profile_get_type_nick (GstEncodingProfile * profile)
888 {
889   if (GST_IS_ENCODING_CONTAINER_PROFILE (profile))
890     return "container";
891   if (GST_IS_ENCODING_VIDEO_PROFILE (profile))
892     return "video";
893   if (GST_IS_ENCODING_AUDIO_PROFILE (profile))
894     return "audio";
895   return NULL;
896 }
897
898 /**
899  * gst_encoding_profile_find:
900  * @targetname: (transfer none): The name of the target
901  * @profilename: (transfer none): The name of the profile
902  * @category: (transfer none) (allow-none): The target category. Can be %NULL
903  *
904  * Find the #GstEncodingProfile with the specified name and category.
905  *
906  * Returns: (transfer full): The matching #GstEncodingProfile or %NULL.
907  *
908  * Since: 0.10.32
909  */
910 GstEncodingProfile *
911 gst_encoding_profile_find (const gchar * targetname, const gchar * profilename,
912     const gchar * category)
913 {
914   GstEncodingProfile *res = NULL;
915   GstEncodingTarget *target;
916
917   g_return_val_if_fail (targetname != NULL, NULL);
918   g_return_val_if_fail (profilename != NULL, NULL);
919
920   /* FIXME : how do we handle profiles named the same in several
921    * categories but of which only one has the required profile ? */
922   target = gst_encoding_target_load (targetname, category, NULL);
923   if (target) {
924     res = gst_encoding_target_get_profile (target, profilename);
925     gst_encoding_target_unref (target);
926   }
927
928   return res;
929 }
930
931 static GstEncodingProfile *
932 combo_search (const gchar * pname)
933 {
934   GstEncodingProfile *res;
935   gchar **split;
936
937   /* Splitup */
938   split = g_strsplit (pname, "/", 2);
939   if (g_strv_length (split) != 2)
940     return NULL;
941
942   res = gst_encoding_profile_find (split[0], split[1], NULL);
943
944   g_strfreev (split);
945
946   return res;
947 }
948
949 /* GValue transform function */
950 static void
951 string_to_profile_transform (const GValue * src_value, GValue * dest_value)
952 {
953   const gchar *profilename;
954   GstEncodingProfile *profile;
955
956   profilename = g_value_get_string (src_value);
957
958   profile = combo_search (profilename);
959
960   if (profile)
961     g_value_take_object (dest_value, (GObject *) profile);
962 }
963
964 static gboolean
965 gst_encoding_profile_deserialize_valfunc (GValue * value, const gchar * s)
966 {
967   GstEncodingProfile *profile;
968
969   profile = combo_search (s);
970
971   if (profile) {
972     g_value_take_object (value, (GObject *) profile);
973     return TRUE;
974   }
975
976   return FALSE;
977 }
978
979 /**
980  * gst_encoding_profile_from_discoverer:
981  * @info: (transfer none): The #GstDiscovererInfo to read from
982  *
983  * Creates a #GstEncodingProfile matching the formats from the given
984  * #GstEncodingProfile. Streams other than audio or video (eg,
985  * subtitles), are currently ignored.
986  *
987  * Returns: (transfer full): The new #GstEncodingProfile or %NULL.
988  *
989  * Since: 0.10.36
990  */
991 GstEncodingProfile *
992 gst_encoding_profile_from_discoverer (GstDiscovererInfo * info)
993 {
994   GstEncodingContainerProfile *profile;
995   GstDiscovererStreamInfo *sinfo;
996   GList *streams, *stream;
997   GstCaps *caps = NULL;
998
999   if (!info || gst_discoverer_info_get_result (info) != GST_DISCOVERER_OK)
1000     return NULL;
1001
1002   sinfo = gst_discoverer_info_get_stream_info (info);
1003   if (!sinfo)
1004     return NULL;
1005
1006   caps = gst_discoverer_stream_info_get_caps (sinfo);
1007   GST_LOG ("Container: %" GST_PTR_FORMAT "\n", caps);
1008   profile =
1009       gst_encoding_container_profile_new ("auto-generated",
1010       "Automatically generated from GstDiscovererInfo", caps, NULL);
1011   gst_caps_unref (caps);
1012   if (!profile) {
1013     GST_ERROR ("Failed to create container profile from caps %" GST_PTR_FORMAT,
1014         caps);
1015     return NULL;
1016   }
1017
1018   streams =
1019       gst_discoverer_container_info_get_streams (GST_DISCOVERER_CONTAINER_INFO
1020       (sinfo));
1021   for (stream = streams; stream; stream = stream->next) {
1022     GstEncodingProfile *sprofile = NULL;
1023     sinfo = (GstDiscovererStreamInfo *) stream->data;
1024     caps = gst_discoverer_stream_info_get_caps (sinfo);
1025     GST_LOG ("Stream: %" GST_PTR_FORMAT "\n", caps);
1026     if (GST_IS_DISCOVERER_AUDIO_INFO (sinfo)) {
1027       sprofile =
1028           (GstEncodingProfile *) gst_encoding_audio_profile_new (caps, NULL,
1029           NULL, 0);
1030     } else if (GST_IS_DISCOVERER_VIDEO_INFO (sinfo)) {
1031       sprofile =
1032           (GstEncodingProfile *) gst_encoding_video_profile_new (caps, NULL,
1033           NULL, 0);
1034     } else {
1035       /* subtitles or other ? ignore for now */
1036     }
1037     if (sprofile)
1038       gst_encoding_container_profile_add_profile (profile, sprofile);
1039     else
1040       GST_ERROR ("Failed to create stream profile from caps %" GST_PTR_FORMAT,
1041           caps);
1042     gst_caps_unref (caps);
1043   }
1044   gst_discoverer_stream_info_list_free (streams);
1045
1046   return (GstEncodingProfile *) profile;
1047 }