tizen 2.3 release
[framework/multimedia/gst-plugins-base0.10.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   GstMiniObject 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 =
169         g_type_register_static_simple (GST_TYPE_MINI_OBJECT,
170         g_intern_static_string ("GstEncodingProfile"),
171         sizeof (GstEncodingProfileClass),
172         (GClassInitFunc) gst_encoding_profile_class_intern_init,
173         sizeof (GstEncodingProfile),
174         NULL,
175         (GTypeFlags) 0);
176     static GstValueTable gstvtable = {
177       G_TYPE_NONE,
178       (GstValueCompareFunc) NULL,
179       (GstValueSerializeFunc) NULL,
180       (GstValueDeserializeFunc) gst_encoding_profile_deserialize_valfunc
181     };
182
183     gstvtable.type = g_define_type_id;
184
185     /* Register a STRING=>PROFILE GValueTransformFunc */
186     g_value_register_transform_func (G_TYPE_STRING, g_define_type_id,
187         string_to_profile_transform);
188     /* Register gst-specific GValue functions */
189     gst_value_register (&gstvtable);
190
191     g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
192   }
193   return g_define_type_id__volatile;
194 }
195
196 static void
197 gst_encoding_profile_finalize (GstEncodingProfile * prof)
198 {
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 (GstMiniObjectClass * klass)
213 {
214   klass->finalize =
215       (GstMiniObjectFinalizeFunction) gst_encoding_profile_finalize;
216 }
217
218 /**
219  * gst_encoding_profile_get_name:
220  * @profile: a #GstEncodingProfile
221  *
222  * Since: 0.10.32
223  *
224  * Returns: the name of the profile, can be %NULL.
225  */
226 const gchar *
227 gst_encoding_profile_get_name (GstEncodingProfile * profile)
228 {
229   return profile->name;
230 }
231
232 /**
233  * gst_encoding_profile_get_description:
234  * @profile: a #GstEncodingProfile
235  *
236  * Since: 0.10.32
237  *
238  * Returns: the description of the profile, can be %NULL.
239  */
240 const gchar *
241 gst_encoding_profile_get_description (GstEncodingProfile * profile)
242 {
243   return profile->description;
244 }
245
246 /**
247  * gst_encoding_profile_get_format:
248  * @profile: a #GstEncodingProfile
249  *
250  * Since: 0.10.32
251  *
252  * Returns: the #GstCaps corresponding to the media format used in the profile.
253  */
254 const GstCaps *
255 gst_encoding_profile_get_format (GstEncodingProfile * profile)
256 {
257   return profile->format;
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: 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.
301  */
302 const GstCaps *
303 gst_encoding_profile_get_restriction (GstEncodingProfile * profile)
304 {
305   return profile->restriction;
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 @description will be made
332  * 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 (GstEncodingContainerProfile * prof)
436 {
437   g_list_foreach (prof->encodingprofiles, (GFunc) gst_mini_object_unref, NULL);
438   g_list_free (prof->encodingprofiles);
439
440   GST_MINI_OBJECT_CLASS (gst_encoding_container_profile_parent_class)->finalize
441       ((GstMiniObject *) prof);
442 }
443
444 static void
445 gst_encoding_container_profile_class_init (GstMiniObjectClass * klass)
446 {
447   klass->finalize =
448       (GstMiniObjectFinalizeFunction) gst_encoding_container_profile_finalize;
449 }
450
451 const GList *
452 gst_encoding_container_profile_get_profiles (GstEncodingContainerProfile *
453     profile)
454 {
455   return profile->encodingprofiles;
456 }
457
458 /* Video profiles */
459
460 struct _GstEncodingVideoProfile
461 {
462   GstEncodingProfile parent;
463
464   guint pass;
465   gboolean variableframerate;
466 };
467
468 G_DEFINE_TYPE (GstEncodingVideoProfile, gst_encoding_video_profile,
469     GST_TYPE_ENCODING_PROFILE);
470
471 static void
472 gst_encoding_video_profile_init (GstEncodingVideoProfile * prof)
473 {
474   /* Nothing to initialize */
475 }
476
477 static void
478 gst_encoding_video_profile_class_init (GstMiniObjectClass * klass)
479 {
480 }
481
482 /**
483  * gst_encoding_video_profile_get_pass:
484  * @prof: a #GstEncodingVideoProfile
485  *
486  * Since: 0.10.32
487  *
488  * Returns: The pass number if this is part of a multi-pass profile. Starts at
489  * 1 for multi-pass. 0 if this is not a multi-pass profile
490  **/
491 guint
492 gst_encoding_video_profile_get_pass (GstEncodingVideoProfile * prof)
493 {
494   return prof->pass;
495 }
496
497 /**
498  * gst_encoding_video_profile_get_variableframerate:
499  * @prof: a #GstEncodingVideoProfile
500  *
501  * Since: 0.10.32
502  *
503  * Returns: Whether non-constant video framerate is allowed for encoding.
504  */
505 gboolean
506 gst_encoding_video_profile_get_variableframerate (GstEncodingVideoProfile *
507     prof)
508 {
509   return prof->variableframerate;
510 }
511
512 /**
513  * gst_encoding_video_profile_set_pass:
514  * @prof: a #GstEncodingVideoProfile
515  * @pass: the pass number for this profile
516  *
517  * Sets the pass number of this video profile. The first pass profile should have
518  * this value set to 1. If this video profile isn't part of a multi-pass profile,
519  * you may set it to 0 (the default value).
520  *
521  * Since: 0.10.32
522  */
523 void
524 gst_encoding_video_profile_set_pass (GstEncodingVideoProfile * prof, guint pass)
525 {
526   prof->pass = pass;
527 }
528
529 /**
530  * gst_encoding_video_profile_set_variableframerate:
531  * @prof: a #GstEncodingVideoProfile
532  * @variableframerate: a boolean
533  *
534  * If set to %TRUE, then the incoming stream will be allowed to have non-constant
535  * framerate. If set to %FALSE (default value), then the incoming stream will
536  * be normalized by dropping/duplicating frames in order to produce a
537  * constance framerate.
538  *
539  * Since: 0.10.32
540  */
541 void
542 gst_encoding_video_profile_set_variableframerate (GstEncodingVideoProfile *
543     prof, gboolean variableframerate)
544 {
545   prof->variableframerate = variableframerate;
546 }
547
548 /* Audio profiles */
549
550 struct _GstEncodingAudioProfile
551 {
552   GstEncodingProfile parent;
553 };
554
555 G_DEFINE_TYPE (GstEncodingAudioProfile, gst_encoding_audio_profile,
556     GST_TYPE_ENCODING_PROFILE);
557
558 static void
559 gst_encoding_audio_profile_init (GstEncodingAudioProfile * prof)
560 {
561   /* Nothing to initialize */
562 }
563
564 static void
565 gst_encoding_audio_profile_class_init (GstMiniObjectClass * klass)
566 {
567 }
568
569 static inline gboolean
570 _gst_caps_is_equal_safe (GstCaps * a, GstCaps * b)
571 {
572   if (a == b)
573     return TRUE;
574   if ((a == NULL) || (b == NULL))
575     return FALSE;
576   return gst_caps_is_equal (a, b);
577 }
578
579 static gint
580 _compare_container_encoding_profiles (GstEncodingContainerProfile * ca,
581     GstEncodingContainerProfile * cb)
582 {
583   GList *tmp;
584
585   if (g_list_length (ca->encodingprofiles) !=
586       g_list_length (cb->encodingprofiles))
587     return -1;
588
589   for (tmp = ca->encodingprofiles; tmp; tmp = tmp->next) {
590     GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data;
591     if (!gst_encoding_container_profile_contains_profile (ca, prof))
592       return -1;
593   }
594
595   return 0;
596 }
597
598 static gint
599 _compare_encoding_profiles (const GstEncodingProfile * a,
600     const GstEncodingProfile * b)
601 {
602   if ((G_TYPE_FROM_INSTANCE (a) != G_TYPE_FROM_INSTANCE (b)) ||
603       !_gst_caps_is_equal_safe (a->format, b->format) ||
604       (g_strcmp0 (a->preset, b->preset) != 0) ||
605       (g_strcmp0 (a->name, b->name) != 0) ||
606       (g_strcmp0 (a->description, b->description) != 0))
607     return -1;
608
609   if (GST_IS_ENCODING_CONTAINER_PROFILE (a))
610     return
611         _compare_container_encoding_profiles (GST_ENCODING_CONTAINER_PROFILE
612         (a), GST_ENCODING_CONTAINER_PROFILE (b));
613
614   if (GST_IS_ENCODING_VIDEO_PROFILE (a)) {
615     GstEncodingVideoProfile *va = (GstEncodingVideoProfile *) a;
616     GstEncodingVideoProfile *vb = (GstEncodingVideoProfile *) b;
617
618     if ((va->pass != vb->pass)
619         || (va->variableframerate != vb->variableframerate))
620       return -1;
621   }
622
623   return 0;
624 }
625
626 /**
627  * gst_encoding_container_profile_contains_profile:
628  * @container: a #GstEncodingContainerProfile
629  * @profile: a #GstEncodingProfile
630  *
631  * Checks if @container contains a #GstEncodingProfile identical to
632  * @profile.
633  *
634  * Since: 0.10.32
635  *
636  * Returns: %TRUE if @container contains a #GstEncodingProfile identical
637  * to @profile, else %FALSE.
638  */
639 gboolean
640 gst_encoding_container_profile_contains_profile (GstEncodingContainerProfile *
641     container, GstEncodingProfile * profile)
642 {
643   g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
644   g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
645
646   return (g_list_find_custom (container->encodingprofiles, profile,
647           (GCompareFunc) _compare_encoding_profiles) != NULL);
648 }
649
650 /**
651  * gst_encoding_container_profile_add_profile:
652  * @container: the #GstEncodingContainerProfile to use
653  * @profile: the #GstEncodingProfile to add.
654  *
655  * Add a #GstEncodingProfile to the list of profiles handled by @container.
656  * 
657  * No copy of @profile will be made, if you wish to use it elsewhere after this
658  * method you should increment its reference count.
659  *
660  * Since: 0.10.32
661  *
662  * Returns: %TRUE if the @stream was properly added, else %FALSE.
663  */
664 gboolean
665 gst_encoding_container_profile_add_profile (GstEncodingContainerProfile *
666     container, GstEncodingProfile * profile)
667 {
668   g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
669   g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
670
671   if (g_list_find_custom (container->encodingprofiles, profile,
672           (GCompareFunc) _compare_encoding_profiles)) {
673     GST_ERROR
674         ("Encoding profile already contains an identical GstEncodingProfile");
675     return FALSE;
676   }
677
678   container->encodingprofiles =
679       g_list_append (container->encodingprofiles, profile);
680
681   return TRUE;
682 }
683
684 static GstEncodingProfile *
685 common_creation (GType objtype, GstCaps * format, const gchar * preset,
686     const gchar * name, const gchar * description, GstCaps * restriction,
687     guint presence)
688 {
689   GstEncodingProfile *prof;
690
691   prof = (GstEncodingProfile *) gst_mini_object_new (objtype);
692
693   if (name)
694     prof->name = g_strdup (name);
695   if (description)
696     prof->description = g_strdup (description);
697   if (preset)
698     prof->preset = g_strdup (preset);
699   if (format)
700     prof->format = gst_caps_ref (format);
701   if (restriction)
702     prof->restriction = gst_caps_ref (restriction);
703   prof->presence = presence;
704
705   return prof;
706 }
707
708 /**
709  * gst_encoding_container_profile_new:
710  * @name: The name of the container profile, can be %NULL
711  * @description: The description of the container profile, can be %NULL
712  * @format: The format to use for this profile
713  * @preset: The preset to use for this profile
714  *
715  * Creates a new #GstEncodingContainerProfile.
716  *
717  * Since: 0.10.32
718  *
719  * Returns: The newly created #GstEncodingContainerProfile.
720  */
721 GstEncodingContainerProfile *
722 gst_encoding_container_profile_new (const gchar * name,
723     const gchar * description, GstCaps * format, const gchar * preset)
724 {
725   g_return_val_if_fail (GST_IS_CAPS (format), NULL);
726
727   return (GstEncodingContainerProfile *)
728       common_creation (GST_TYPE_ENCODING_CONTAINER_PROFILE, format, preset,
729       name, description, NULL, 0);
730 }
731
732 /**
733  * gst_encoding_video_profile_new:
734  * @format: the #GstCaps
735  * @preset: the preset(s) to use on the encoder, can be #NULL
736  * @restriction: the #GstCaps used to restrict the input to the encoder, can be
737  * NULL. See gst_encoding_profile_get_restriction() for more details.
738  * @presence: the number of time this stream must be used. 0 means any number of
739  *  times (including never)
740  *
741  * Creates a new #GstEncodingVideoProfile
742  *
743  * All provided allocatable arguments will be internally copied, so can be
744  * safely freed/unreferenced after calling this method.
745  *
746  * If you wish to control the pass number (in case of multi-pass scenarios),
747  * please refer to the gst_encoding_video_profile_set_pass() documentation.
748  *
749  * If you wish to use/force a constant framerate please refer to the
750  * gst_encoding_video_profile_set_variableframerate() documentation.
751  *
752  * Since: 0.10.32
753  *
754  * Returns: the newly created #GstEncodingVideoProfile.
755  */
756 GstEncodingVideoProfile *
757 gst_encoding_video_profile_new (GstCaps * format, const gchar * preset,
758     GstCaps * restriction, guint presence)
759 {
760   return (GstEncodingVideoProfile *)
761       common_creation (GST_TYPE_ENCODING_VIDEO_PROFILE, format, preset, NULL,
762       NULL, restriction, presence);
763 }
764
765 /**
766  * gst_encoding_audio_profile_new:
767  * @format: the #GstCaps
768  * @preset: the preset(s) to use on the encoder, can be #NULL
769  * @restriction: the #GstCaps used to restrict the input to the encoder, can be
770  * NULL. See gst_encoding_profile_get_restriction() for more details.
771  * @presence: the number of time this stream must be used. 0 means any number of
772  *  times (including never)
773  *
774  * Creates a new #GstEncodingAudioProfile
775  *
776  * All provided allocatable arguments will be internally copied, so can be
777  * safely freed/unreferenced after calling this method.
778  *
779  * Since: 0.10.32
780  *
781  * Returns: the newly created #GstEncodingAudioProfile.
782  */
783 GstEncodingAudioProfile *
784 gst_encoding_audio_profile_new (GstCaps * format, const gchar * preset,
785     GstCaps * restriction, guint presence)
786 {
787   return (GstEncodingAudioProfile *)
788       common_creation (GST_TYPE_ENCODING_AUDIO_PROFILE, format, preset, NULL,
789       NULL, restriction, presence);
790 }
791
792
793 /**
794  * gst_encoding_profile_is_equal:
795  * @a: a #GstEncodingProfile
796  * @b: a #GstEncodingProfile
797  *
798  * Checks whether the two #GstEncodingProfile are equal
799  *
800  * Since: 0.10.32
801  *
802  * Returns: %TRUE if @a and @b are equal, else %FALSE.
803  */
804 gboolean
805 gst_encoding_profile_is_equal (GstEncodingProfile * a, GstEncodingProfile * b)
806 {
807   return (_compare_encoding_profiles (a, b) == 0);
808 }
809
810
811 /**
812  * gst_encoding_profile_get_input_caps:
813  * @profile: a #GstEncodingProfile
814  *
815  * Computes the full output caps that this @profile will be able to consume.
816  *
817  * Since: 0.10.32
818  *
819  * Returns: The full caps the given @profile can consume. Call gst_caps_unref()
820  * when you are done with the caps.
821  */
822 GstCaps *
823 gst_encoding_profile_get_input_caps (GstEncodingProfile * profile)
824 {
825   GstCaps *out, *tmp;
826   GList *ltmp;
827   GstStructure *st, *outst;
828   GQuark out_name;
829   guint i, len;
830   const GstCaps *fcaps;
831
832   if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
833     GstCaps *res = gst_caps_new_empty ();
834
835     for (ltmp = GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles;
836         ltmp; ltmp = ltmp->next) {
837       GstEncodingProfile *sprof = (GstEncodingProfile *) ltmp->data;
838       gst_caps_merge (res, gst_encoding_profile_get_input_caps (sprof));
839     }
840     return res;
841   }
842
843   fcaps = profile->format;
844
845   /* fast-path */
846   if ((profile->restriction == NULL) || gst_caps_is_any (profile->restriction))
847     return gst_caps_copy (fcaps);
848
849   /* Combine the format with the restriction caps */
850   outst = gst_caps_get_structure (fcaps, 0);
851   out_name = gst_structure_get_name_id (outst);
852   tmp = gst_caps_new_empty ();
853   len = gst_caps_get_size (profile->restriction);
854
855   for (i = 0; i < len; i++) {
856     st = gst_structure_copy (gst_caps_get_structure (profile->restriction, i));
857     st->name = out_name;
858     gst_caps_append_structure (tmp, st);
859   }
860
861   out = gst_caps_intersect (tmp, fcaps);
862   gst_caps_unref (tmp);
863
864   return out;
865 }
866
867 /**
868  * gst_encoding_profile_get_type_nick:
869  * @profile: a #GstEncodingProfile
870  *
871  * Since: 0.10.32
872  *
873  * Returns: the human-readable name of the type of @profile.
874  */
875 const gchar *
876 gst_encoding_profile_get_type_nick (GstEncodingProfile * profile)
877 {
878   if (GST_IS_ENCODING_CONTAINER_PROFILE (profile))
879     return "container";
880   if (GST_IS_ENCODING_VIDEO_PROFILE (profile))
881     return "video";
882   if (GST_IS_ENCODING_AUDIO_PROFILE (profile))
883     return "audio";
884   return NULL;
885 }
886
887 /**
888  * gst_encoding_profile_find:
889  * @targetname: (transfer none): The name of the target
890  * @profilename: (transfer none): The name of the profile
891  * @category: (transfer none) (allow-none): The target category. Can be %NULL
892  *
893  * Find the #GstEncodingProfile with the specified name and category.
894  *
895  * Returns: (transfer full): The matching #GstEncodingProfile or %NULL.
896  *
897  * Since: 0.10.32
898  */
899 GstEncodingProfile *
900 gst_encoding_profile_find (const gchar * targetname, const gchar * profilename,
901     const gchar * category)
902 {
903   GstEncodingProfile *res = NULL;
904   GstEncodingTarget *target;
905
906   g_return_val_if_fail (targetname != NULL, NULL);
907   g_return_val_if_fail (profilename != NULL, NULL);
908
909   /* FIXME : how do we handle profiles named the same in several
910    * categories but of which only one has the required profile ? */
911   target = gst_encoding_target_load (targetname, category, NULL);
912   if (target) {
913     res = gst_encoding_target_get_profile (target, profilename);
914     gst_encoding_target_unref (target);
915   }
916
917   return res;
918 }
919
920 static GstEncodingProfile *
921 combo_search (const gchar * pname)
922 {
923   GstEncodingProfile *res;
924   gchar **split;
925
926   /* Splitup */
927   split = g_strsplit (pname, "/", 2);
928   if (g_strv_length (split) != 2)
929     return NULL;
930
931   res = gst_encoding_profile_find (split[0], split[1], NULL);
932
933   g_strfreev (split);
934
935   return res;
936 }
937
938 /* GValue transform function */
939 static void
940 string_to_profile_transform (const GValue * src_value, GValue * dest_value)
941 {
942   const gchar *profilename;
943   GstEncodingProfile *profile;
944
945   profilename = g_value_get_string (src_value);
946
947   profile = combo_search (profilename);
948
949   if (profile)
950     gst_value_take_mini_object (dest_value, (GstMiniObject *) profile);
951 }
952
953 static gboolean
954 gst_encoding_profile_deserialize_valfunc (GValue * value, const gchar * s)
955 {
956   GstEncodingProfile *profile;
957
958   profile = combo_search (s);
959
960   if (profile) {
961     gst_value_take_mini_object (value, (GstMiniObject *) profile);
962     return TRUE;
963   }
964
965   return FALSE;
966 }
967
968 /**
969  * gst_encoding_profile_from_discoverer:
970  * @info: (transfer none): The #GstDiscovererInfo to read from
971  *
972  * Creates a #GstEncodingProfile matching the formats from the given
973  * #GstEncodingProfile. Streams other than audio or video (eg,
974  * subtitles), are currently ignored.
975  *
976  * Returns: (transfer full): The new #GstEncodingProfile or %NULL.
977  *
978  * Since: 0.10.36
979  */
980 GstEncodingProfile *
981 gst_encoding_profile_from_discoverer (GstDiscovererInfo * info)
982 {
983   GstEncodingContainerProfile *profile;
984   GstDiscovererStreamInfo *sinfo;
985   GList *streams, *stream;
986   GstCaps *caps = NULL;
987
988   if (!info || gst_discoverer_info_get_result (info) != GST_DISCOVERER_OK)
989     return NULL;
990
991   sinfo = gst_discoverer_info_get_stream_info (info);
992   if (!sinfo)
993     return NULL;
994
995   caps = gst_discoverer_stream_info_get_caps (sinfo);
996   GST_LOG ("Container: %" GST_PTR_FORMAT "\n", caps);
997   profile =
998       gst_encoding_container_profile_new ("auto-generated",
999       "Automatically generated from GstDiscovererInfo", caps, NULL);
1000   gst_caps_unref (caps);
1001   if (!profile) {
1002     GST_ERROR ("Failed to create container profile from caps %" GST_PTR_FORMAT,
1003         caps);
1004     return NULL;
1005   }
1006
1007   streams =
1008       gst_discoverer_container_info_get_streams (GST_DISCOVERER_CONTAINER_INFO
1009       (sinfo));
1010   for (stream = streams; stream; stream = stream->next) {
1011     GstEncodingProfile *sprofile = NULL;
1012     sinfo = (GstDiscovererStreamInfo *) stream->data;
1013     caps = gst_discoverer_stream_info_get_caps (sinfo);
1014     GST_LOG ("Stream: %" GST_PTR_FORMAT "\n", caps);
1015     if (GST_IS_DISCOVERER_AUDIO_INFO (sinfo)) {
1016       sprofile =
1017           (GstEncodingProfile *) gst_encoding_audio_profile_new (caps, NULL,
1018           NULL, 0);
1019     } else if (GST_IS_DISCOVERER_VIDEO_INFO (sinfo)) {
1020       sprofile =
1021           (GstEncodingProfile *) gst_encoding_video_profile_new (caps, NULL,
1022           NULL, 0);
1023     } else {
1024       /* subtitles or other ? ignore for now */
1025     }
1026     if (sprofile)
1027       gst_encoding_container_profile_add_profile (profile, sprofile);
1028     else
1029       GST_ERROR ("Failed to create stream profile from caps %" GST_PTR_FORMAT,
1030           caps);
1031     gst_caps_unref (caps);
1032   }
1033   gst_discoverer_stream_info_list_free (streams);
1034
1035   return (GstEncodingProfile *) profile;
1036 }