Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2
[mafwsubrenderer] / gst-plugins-base-subtitles0.10 / gst-libs / gst / pbutils / codec-utils.c
1 /* GStreamer base utils library codec-specific utility functions
2  * Copyright (C) 2010 Arun Raghavan <arun.raghavan@collabora.co.uk>
3  *               2010 Collabora Multimedia
4  *               2010 Nokia Corporation
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:gstpbutilscodecutils
24  * @short_description: Miscellaneous codec-specific utility functions
25  *
26  * <refsect2>
27  * <para>
28  * Provides codec-specific ulility functions such as functions to provide the
29  * codec profile and level in human-readable string form from header data.
30  * </para>
31  * </refsect2>
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include "pbutils.h"
39
40 #define GST_SIMPLE_CAPS_HAS_NAME(caps,name) \
41     gst_structure_has_name(gst_caps_get_structure((caps),0),(name))
42
43 #define GST_SIMPLE_CAPS_HAS_FIELD(caps,field) \
44     gst_structure_has_field(gst_caps_get_structure((caps),0),(field))
45
46 static const gchar *
47 digit_to_string (guint digit)
48 {
49   static const char itoa[][2] = {
50     "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
51   };
52
53   if (G_LIKELY (digit < 10))
54     return itoa[digit];
55   else
56     return NULL;
57 }
58
59 /**
60  * gst_codec_utils_aac_get_sample_rate_from_index:
61  * @sr_idx: Sample rate index as from the AudioSpecificConfig (MPEG-4
62  *          container) or ADTS frame header
63  *
64  * Translates the sample rate index found in AAC headers to the actual sample
65  * rate.
66  *
67  * Returns: The sample rate if @sr_idx is valid, 0 otherwise.
68  *
69  * Since: 0.10.31
70  */
71 guint
72 gst_codec_utils_aac_get_sample_rate_from_index (guint sr_idx)
73 {
74   static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
75     32000, 24000, 22050, 16000, 12000, 11025, 8000
76   };
77
78   if (G_LIKELY (sr_idx < G_N_ELEMENTS (aac_sample_rates)))
79     return aac_sample_rates[sr_idx];
80
81   GST_WARNING ("Invalid sample rate index %u", sr_idx);
82   return 0;
83 }
84
85 /**
86  * gst_codec_utils_aac_get_profile:
87  * @audio_config: a pointer to the AudioSpecificConfig as specified in the
88  *                Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see
89  *                gst_codec_utils_aac_get_level() for a more details).
90  * @len: Length of @audio_config in bytes
91  *
92  * Returns the profile of the given AAC stream as a string. The profile is
93  * determined using the AudioObjectType field which is in the first 5 bits of
94  * @audio_config.
95  *
96  * <note>
97  * HE-AAC support has not yet been implemented.
98  * </note>
99  *
100  * Returns: The profile as a const string and %NULL if the profile could not be
101  * determined.
102  *
103  * Since: 0.10.31
104  */
105 const gchar *
106 gst_codec_utils_aac_get_profile (const guint8 * audio_config, guint len)
107 {
108   guint profile;
109
110   if (len < 1)
111     return NULL;
112
113   GST_MEMDUMP ("audio config", audio_config, len);
114
115   profile = audio_config[0] >> 3;
116   switch (profile) {
117     case 1:
118       return "main";
119     case 2:
120       return "lc";
121     case 3:
122       return "ssr";
123     case 4:
124       return "ltp";
125     default:
126       break;
127   }
128
129   GST_DEBUG ("Invalid profile idx: %u", profile);
130   return NULL;
131 }
132
133 /**
134  * gst_codec_utils_aac_get_level:
135  * @audio_config: a pointer to the AudioSpecificConfig as specified in the
136  *                Elementary Stream Descriptor (esds) in ISO/IEC 14496-1.
137  * @len: Length of @audio_config in bytes
138  *
139  * Determines the level of a stream as defined in ISO/IEC 14496-3. For AAC LC
140  * streams, the constraints from the AAC audio profile are applied. For AAC
141  * Main, LTP, SSR and others, the Main profile is used.
142  *
143  * The @audio_config parameter follows the following format, starting from the
144  * most significant bit of the first byte:
145  *
146  * <itemizedlist>
147  *   <listitem><para>
148  *     Bit 0:4 contains the AudioObjectType
149  *   </para></listitem>
150  *   <listitem><para>
151  *     Bit 5:8 contains the sample frequency index (if this is 0xf, then the
152  *             next 24 bits define the actual sample frequency, and subsequent
153  *             fields are appropriately shifted).
154  *    </para></listitem>
155  *   <listitem><para>
156  *     Bit 9:12 contains the channel configuration
157  *   </para></listitem>
158  * </itemizedlist>
159  *
160  * <note>
161  * HE-AAC support has not yet been implemented.
162  * </note>
163  *
164  * Returns: The level as a const string and %NULL if the level could not be
165  * determined.
166  *
167  * Since: 0.10.31
168  */
169 const gchar *
170 gst_codec_utils_aac_get_level (const guint8 * audio_config, guint len)
171 {
172   int profile, sr_idx, channel_config, rate;
173   /* Number of single channel elements, channel pair elements, low frequency
174    * elements, independently switched coupling channel elements, and
175    * dependently switched coupling channel elements.
176    *
177    * Note: The 2 CCE types are ignored for now as they require us to actually
178    * parse the first frame, and they are rarely found in actual streams.
179    */
180   int num_sce = 0, num_cpe = 0, num_lfe = 0, num_cce_indep = 0, num_cce_dep = 0;
181   int num_channels;
182   /* Processor and RAM Complexity Units (calculated and "reference" for single
183    * channel) */
184   int pcu, rcu, pcu_ref, rcu_ref;
185   int ret = -1;
186
187   g_return_val_if_fail (audio_config != NULL, NULL);
188
189   if (len < 2)
190     return NULL;
191
192   GST_MEMDUMP ("audio config", audio_config, len);
193
194   profile = audio_config[0] >> 3;
195   /* FIXME: add support for sr_idx = 0xf */
196   sr_idx = ((audio_config[0] & 0x7) << 1) | ((audio_config[1] & 0x80) >> 7);
197   rate = gst_codec_utils_aac_get_sample_rate_from_index (sr_idx);
198   channel_config = (audio_config[1] & 0x7f) >> 3;
199
200   if (rate == 0)
201     return NULL;
202
203   switch (channel_config) {
204     case 0:
205       /* Channel config is defined in the AudioObjectType's SpecificConfig,
206        * which requires some amount of digging through the headers. I only see
207        * this done in the MPEG conformance streams - FIXME */
208       GST_WARNING ("Found a stream with channel configuration in the "
209           "AudioSpecificConfig. Please file a bug with a link to the media if "
210           "possible.");
211       return NULL;
212     case 1:
213       /* front center */
214       num_sce = 1;
215       break;
216     case 2:
217       /* front left and right */
218       num_cpe = 1;
219       break;
220     case 3:
221       /* front left, right, and center */
222       num_sce = 1;
223       num_cpe = 1;
224       break;
225     case 4:
226       /* front left, right, and center; rear surround */
227       num_sce = 2;
228       num_cpe = 1;
229       break;
230     case 5:
231       /* front left, right, and center; rear left and right surround */
232       num_sce = 1;
233       num_cpe = 2;
234       break;
235     case 6:
236       /* front left, right, center and LFE; rear left and right surround */
237       num_sce = 1;
238       num_cpe = 2;
239       break;
240     case 7:
241       /* front left, right, center and LFE; outside front left and right;
242        * rear left and right surround */
243       num_sce = 1;
244       num_cpe = 3;
245       num_lfe = 1;
246       break;
247     default:
248       GST_WARNING ("Unknown channel config in header: %d", channel_config);
249       return NULL;
250   }
251
252   switch (profile) {
253     case 0:                    /* NULL */
254       GST_WARNING ("profile 0 is not a valid profile");
255       return NULL;
256     case 2:                    /* LC */
257       pcu_ref = 3;
258       rcu_ref = 3;
259       break;
260     case 3:                    /* SSR */
261       pcu_ref = 4;
262       rcu_ref = 3;
263       break;
264     case 4:                    /* LTP */
265       pcu_ref = 4;
266       rcu_ref = 4;
267       break;
268     case 1:                    /* Main */
269     default:
270       /* Other than a couple of ER profiles, Main is the worst-case */
271       pcu_ref = 5;
272       rcu_ref = 5;
273       break;
274   }
275
276   /* "fs_ref" is 48000 Hz for AAC Main/LC/SSR/LTP. SBR's fs_ref is defined as
277    * 24000/48000 (in/out), for SBR streams. Actual support is a FIXME */
278
279   pcu = ((float) rate / 48000) * pcu_ref *
280       ((2 * num_cpe) + num_sce + num_lfe + num_cce_indep + (0.3 * num_cce_dep));
281
282   rcu = ((float) rcu_ref) * (num_sce + (0.5 * num_lfe) + (0.5 * num_cce_indep) +
283       (0.4 * num_cce_dep));
284
285   if (num_cpe < 2)
286     rcu += (rcu_ref + (rcu_ref - 1)) * num_cpe;
287   else
288     rcu += (rcu_ref + (rcu_ref - 1) * ((2 * num_cpe) - 1));
289
290   num_channels = num_sce + (2 * num_cpe) + num_lfe;
291
292   if (profile == 2) {
293     /* AAC LC => return the level as per the 'AAC Profile' */
294     if (num_channels <= 2 && rate <= 24000 && pcu <= 3 && rcu <= 5)
295       ret = 1;
296     else if (num_channels <= 2 && rate <= 48000 && pcu <= 6 && rcu <= 5)
297       ret = 2;
298     /* There is no level 3 for the AAC Profile */
299     else if (num_channels <= 5 && rate <= 48000 && pcu <= 19 && rcu <= 15)
300       ret = 4;
301     else if (num_channels <= 5 && rate <= 96000 && pcu <= 38 && rcu <= 15)
302       ret = 5;
303   } else {
304     /* Return the level as per the 'Main Profile' */
305     if (pcu < 40 && rcu < 20)
306       ret = 1;
307     else if (pcu < 80 && rcu < 64)
308       ret = 2;
309     else if (pcu < 160 && rcu < 128)
310       ret = 3;
311     else if (pcu < 320 && rcu < 256)
312       ret = 4;
313   }
314
315   if (ret == -1) {
316     GST_WARNING ("couldn't determine level: profile=%u, rate=%u, "
317         "channel_config=%u, pcu=%d,rcu=%d", profile, rate, channel_config, pcu,
318         rcu);
319     return NULL;
320   } else {
321     return digit_to_string (ret);
322   }
323 }
324
325 /**
326  * gst_codec_utils_aac_caps_set_level_and_profile:
327  * @caps: the #GstCaps to which level and profile fields are to be added
328  * @audio_config: a pointer to the AudioSpecificConfig as specified in the
329  *                Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see
330  *                below for a more details).
331  * @len: Length of @audio_config in bytes
332  *
333  * Sets the level and profile on @caps if it can be determined from
334  * @audio_config. See gst_codec_utils_aac_get_level() and
335  * gst_codec_utils_aac_get_profile() for more details on the parameters.
336  * @caps must be audio/mpeg caps with an "mpegversion" field of either 2 or 4.
337  * If mpegversion is 4, the "base-profile" field is also set in @caps.
338  *
339  * Returns: %TRUE if the level and profile could be set, %FALSE otherwise.
340  *
341  * Since: 0.10.31
342  */
343 gboolean
344 gst_codec_utils_aac_caps_set_level_and_profile (GstCaps * caps,
345     const guint8 * audio_config, guint len)
346 {
347   GstStructure *s;
348   const gchar *level, *profile;
349   int mpegversion = 0;
350
351   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
352   g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE);
353   g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_NAME (caps, "audio/mpeg"), FALSE);
354   g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_FIELD (caps, "mpegversion"), FALSE);
355   g_return_val_if_fail (audio_config != NULL, FALSE);
356
357   s = gst_caps_get_structure (caps, 0);
358
359   gst_structure_get_int (s, "mpegversion", &mpegversion);
360   g_return_val_if_fail (mpegversion == 2 || mpegversion == 4, FALSE);
361
362   level = gst_codec_utils_aac_get_level (audio_config, len);
363
364   if (level != NULL)
365     gst_structure_set (s, "level", G_TYPE_STRING, level, NULL);
366
367   profile = gst_codec_utils_aac_get_profile (audio_config, len);
368
369   if (profile != NULL) {
370     if (mpegversion == 4) {
371       gst_structure_set (s, "base-profile", G_TYPE_STRING, profile,
372           "profile", G_TYPE_STRING, profile, NULL);
373     } else {
374       gst_structure_set (s, "profile", G_TYPE_STRING, profile, NULL);
375     }
376   }
377
378   GST_LOG ("profile : %s", (profile) ? profile : "---");
379   GST_LOG ("level   : %s", (level) ? level : "---");
380
381   return (level != NULL && profile != NULL);
382 }
383
384 /**
385  * gst_codec_utils_h264_get_profile:
386  * @sps: Pointer to the sequence parameter set for the stream.
387  * @len: Length of the data available in @sps.
388  *
389  * Converts the profile indication (profile_idc) in the stream's
390  * sequence parameter set into a string. The SPS is expected to have the
391  * following format, as defined in the H.264 specification. The SPS is viewed
392  * as a bitstream here, with bit 0 being the most significant bit of the first
393  * byte.
394  *
395  * <itemizedlist>
396  * <listitem><para>Bit 0:7   - Profile indication</para></listitem>
397  * <listitem><para>Bit 8     - constraint_set0_flag</para></listitem>
398  * <listitem><para>Bit 9     - constraint_set1_flag</para></listitem>
399  * <listitem><para>Bit 10    - constraint_set2_flag</para></listitem>
400  * <listitem><para>Bit 11    - constraint_set3_flag</para></listitem>
401  * <listitem><para>Bit 12    - constraint_set3_flag</para></listitem>
402  * <listitem><para>Bit 13:15 - Reserved</para></listitem>
403  * <listitem><para>Bit 16:24 - Level indication</para></listitem>
404  * </itemizedlist>
405  *
406  * Returns: The profile as a const string, or %NULL if there is an error.
407  *
408  * Since: 0.10.31
409  */
410 const gchar *
411 gst_codec_utils_h264_get_profile (const guint8 * sps, guint len)
412 {
413   const gchar *profile = NULL;
414   gint csf1, csf3;
415
416   g_return_val_if_fail (sps != NULL, NULL);
417
418   if (len < 2)
419     return NULL;
420
421   GST_MEMDUMP ("SPS", sps, len);
422
423   csf1 = (sps[1] & 0x40) >> 6;
424   csf3 = (sps[1] & 0x10) >> 4;
425
426   switch (sps[0]) {
427     case 66:
428       if (csf1)
429         profile = "constrained-baseline";
430       else
431         profile = "baseline";
432       break;
433     case 77:
434       profile = "main";
435       break;
436     case 88:
437       profile = "extended";
438       break;
439     case 100:
440       profile = "high";
441       break;
442     case 110:
443       if (csf3)
444         profile = "high-10-intra";
445       else
446         profile = "high-10";
447       break;
448     case 122:
449       if (csf3)
450         profile = "high-4:2:2-intra";
451       else
452         profile = "high-4:2:2";
453       break;
454     case 244:
455       if (csf3)
456         profile = "high-4:4:4-intra";
457       else
458         profile = "high-4:4:4";
459       break;
460     case 44:
461       profile = "cavlc-4:4:4-intra";
462       break;
463     default:
464       return NULL;
465   }
466
467   return profile;
468 }
469
470 /**
471  * gst_codec_utils_h264_get_level:
472  * @sps: Pointer to the sequence parameter set for the stream.
473  * @len: Length of the data available in @sps.
474  *
475  * Converts the level indication (level_idc) in the stream's
476  * sequence parameter set into a string. The SPS is expected to have the
477  * same format as for gst_codec_utils_h264_get_profile().
478  *
479  * Returns: The level as a const string, or %NULL if there is an error.
480  *
481  * Since: 0.10.31
482  */
483 const gchar *
484 gst_codec_utils_h264_get_level (const guint8 * sps, guint len)
485 {
486   gint csf3;
487
488   g_return_val_if_fail (sps != NULL, NULL);
489
490   if (len < 3)
491     return NULL;
492
493   GST_MEMDUMP ("SPS", sps, len);
494
495   csf3 = (sps[1] & 0x10) >> 4;
496
497   if (sps[2] == 11 && csf3)
498     return "1b";
499   else if (sps[2] % 10 == 0)
500     return digit_to_string (sps[2] / 10);
501   else {
502     switch (sps[2]) {
503       case 11:
504         return "1.1";
505       case 12:
506         return "1.2";
507       case 13:
508         return "1.3";
509       case 21:
510         return "2.1";
511       case 22:
512         return "2.2";
513       case 31:
514         return "3.1";
515       case 32:
516         return "3.2";
517       case 41:
518         return "4.1";
519       case 42:
520         return "4.2";
521       case 51:
522         return "5.1";
523       default:
524         return NULL;
525     }
526   }
527 }
528
529 /**
530  * gst_codec_utils_h264_caps_set_level_and_profile:
531  * @caps: the #GstCaps to which the level and profile are to be added
532  * @sps: Pointer to the sequence parameter set for the stream.
533  * @len: Length of the data available in @sps.
534  *
535  * Sets the level and profile in @caps if it can be determined from @sps. See
536  * gst_codec_utils_h264_get_level() and gst_codec_utils_h264_get_profile()
537  * for more details on the parameters.
538  *
539  * Returns: %TRUE if the level and profile could be set, %FALSE otherwise.
540  *
541  * Since: 0.10.31
542  */
543 gboolean
544 gst_codec_utils_h264_caps_set_level_and_profile (GstCaps * caps,
545     const guint8 * sps, guint len)
546 {
547   const gchar *level, *profile;
548
549   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
550   g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE);
551   g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_NAME (caps, "video/x-h264"), FALSE);
552   g_return_val_if_fail (sps != NULL, FALSE);
553
554   level = gst_codec_utils_h264_get_level (sps, len);
555
556   if (level != NULL)
557     gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
558
559   profile = gst_codec_utils_h264_get_profile (sps, len);
560
561   if (profile != NULL)
562     gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
563
564   GST_LOG ("profile : %s", (profile) ? profile : "---");
565   GST_LOG ("level   : %s", (level) ? level : "---");
566
567   return (level != NULL && profile != NULL);
568 }
569
570 /**
571  * gst_codec_utils_mpeg4video_get_profile:
572  * @vis_obj_seq: Pointer to the visual object sequence for the stream.
573  * @len: Length of the data available in @sps.
574  *
575  * Converts the profile indication in the stream's visual object sequence into
576  * a string. @vis_obj_seq is expected to be the data following the visual
577  * object sequence start code. Only the first byte
578  * (profile_and_level_indication) is used.
579  *
580  * Returns: The profile as a const string, or NULL if there is an error.
581  *
582  * Since: 0.10.31
583  */
584 const gchar *
585 gst_codec_utils_mpeg4video_get_profile (const guint8 * vis_obj_seq, guint len)
586 {
587   /* The profile/level codes are from 14496-2, table G-1, and the Wireshark
588    * sources: epan/dissectors/packet-mp4ves.c */
589
590   /* These are a direct mapping from the integer profile id -> string. Profiles
591    * 0x6, 0xe and 0xf can correspond to more than one profile depending on the
592    * second 4 bits of vis_obj_seq[0], so they are handled separately. */
593   static const char *profiles[] = { "simple", "simple-scalable", "core",
594     "main", "n-bit", "scalable", NULL, "basic-animated-texture", "hybrid",
595     "advanced-real-time-simple", "core-scalable", "advanced-coding-efficiency",
596     "advanced-core", "advanced-scalable-texture",
597   };
598   int profile_id, level_id;
599
600   g_return_val_if_fail (vis_obj_seq != NULL, NULL);
601
602   if (len < 1)
603     return NULL;
604
605   GST_MEMDUMP ("VOS", vis_obj_seq, len);
606
607   profile_id = vis_obj_seq[0] >> 4;
608   level_id = vis_obj_seq[0] & 0xf;
609
610   GST_LOG ("profile_id = %d, level_id = %d", profile_id, level_id);
611
612   if (profile_id != 6 && profile_id < 0xe)
613     return profiles[profile_id];
614
615   if (profile_id != 0xf && level_id == 0)
616     return NULL;
617
618   switch (profile_id) {
619     case 0x6:
620       if (level_id < 3)
621         return "simple-face";
622       else if (level_id < 5)
623         return "simple-fba";
624       break;
625
626     case 0xe:
627       if (level_id < 5)
628         return "simple-studio";
629       else if (level_id < 9)
630         return "core-studio";
631       break;
632
633     case 0xf:
634       if (level_id < 6)
635         return "advanced-simple";
636       else if (level_id > 7 && level_id < 0xe)
637         return "fine-granularity-scalable";
638       break;
639   }
640
641   return NULL;
642 }
643
644 /**
645  * gst_codec_utils_mpeg4video_get_level:
646  * @vis_obj_seq: Pointer to the visual object sequence for the stream.
647  * @len: Length of the data available in @sps.
648  *
649  * Converts the level indication in the stream's visual object sequence into
650  * a string. @vis_obj_seq is expected to be the data following the visual
651  * object sequence start code. Only the first byte
652  * (profile_and_level_indication) is used.
653  *
654  * Returns: The level as a const string, or NULL if there is an error.
655  *
656  * Since: 0.10.31
657  */
658 const gchar *
659 gst_codec_utils_mpeg4video_get_level (const guint8 * vis_obj_seq, guint len)
660 {
661   /* The profile/level codes are from 14496-2, table G-1, and the Wireshark
662    * sources: epan/dissectors/packet-mp4ves.c
663    *
664    * Each profile has a different maximum level it defines. Some of them still
665    * need special case handling, because not all levels start from 1, and the
666    * Simple profile defines an intermediate level as well. */
667   static const int level_max[] = { 3, 2, 2, 4, 2, 1, 2, 2, 2, 4, 3, 4, 2, 3, 4,
668     5
669   };
670   int profile_id, level_id;
671
672   g_return_val_if_fail (vis_obj_seq != NULL, NULL);
673
674   if (len < 1)
675     return NULL;
676
677   GST_MEMDUMP ("VOS", vis_obj_seq, len);
678
679   profile_id = vis_obj_seq[0] >> 4;
680   level_id = vis_obj_seq[0] & 0xf;
681
682   GST_LOG ("profile_id = %d, level_id = %d", profile_id, level_id);
683
684   if (profile_id != 0xf && level_id == 0)
685     return NULL;
686
687   /* Let's do some validation of the level */
688   switch (profile_id) {
689     case 0x3:
690       if (level_id == 1)
691         return NULL;
692       break;
693
694     case 0x4:
695       if (level_id != 2)
696         return NULL;
697       break;
698
699     case 0x6:
700       if (level_id > 5)
701         return NULL;
702       break;
703
704     case 0xe:
705       if (level_id > 9)
706         return NULL;
707       break;
708
709     case 0xf:
710       if (level_id == 7 && level_id > 0xd)
711         return NULL;
712       break;
713   }
714
715   if (profile_id == 0 && level_id == 8)
716     /* Simple Profile / Level 0 */
717     return "0";
718   else if (profile_id == 0 && level_id == 9)
719     /* Simple Profile / Level 0b */
720     return "0b";
721   else if (level_id <= level_max[profile_id])
722     /* Levels for all other cases */
723     return digit_to_string (level_id);
724
725   return NULL;
726 }
727
728 /**
729  * gst_codec_utils_mpeg4video_caps_set_level_and_profile:
730  * @caps: the #GstCaps to which the level and profile are to be added
731  * @vis_obj_seq: Pointer to the visual object sequence for the stream.
732  * @len: Length of the data available in @sps.
733  *
734  * Sets the level and profile in @caps if it can be determined from
735  * @vis_obj_seq. See gst_codec_utils_mpeg4video_get_level() and
736  * gst_codec_utils_mpeg4video_get_profile() for more details on the
737  * parameters.
738  *
739  * Returns: %TRUE if the level and profile could be set, %FALSE otherwise.
740  *
741  * Since: 0.10.31
742  */
743 gboolean
744 gst_codec_utils_mpeg4video_caps_set_level_and_profile (GstCaps * caps,
745     const guint8 * vis_obj_seq, guint len)
746 {
747   const gchar *profile, *level;
748
749   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
750   g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE);
751   g_return_val_if_fail (vis_obj_seq != NULL, FALSE);
752
753   profile = gst_codec_utils_mpeg4video_get_profile (vis_obj_seq, len);
754
755   if (profile != NULL)
756     gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
757
758   level = gst_codec_utils_mpeg4video_get_level (vis_obj_seq, len);
759
760   if (level != NULL)
761     gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
762
763   GST_LOG ("profile : %s", (profile) ? profile : "---");
764   GST_LOG ("level   : %s", (level) ? level : "---");
765
766   return (profile != NULL && level != NULL);
767 }