• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer base utils library codec-specific utility functions
2  * Copyright (C) 2010 Arun Raghavan <arun.raghavan@collabora.co.uk>
3  *               2013 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
4  *               2010 Collabora Multimedia
5  *               2010 Nokia Corporation
6  *               2013 Intel Corporation
7  *               2015 Sebastian Dröge <sebastian@centricular.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24 
25 /**
26  * SECTION:gstpbutilscodecutils
27  * @title: Codec utilities
28  * @short_description: Miscellaneous codec-specific utility functions
29  *
30  * Provides codec-specific ulility functions such as functions to provide the
31  * codec profile and level in human-readable string form from header data.
32  *
33  */
34 
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 
39 #include "pbutils.h"
40 #include <gst/base/base.h>
41 #include <gst/base/gstbitreader.h>
42 #include <gst/tag/tag.h>
43 
44 #include <string.h>
45 
46 #ifndef GST_DISABLE_GST_DEBUG
47 #define GST_CAT_DEFAULT gst_pb_utils_codec_utils_ensure_debug_category()
48 
49 static GstDebugCategory *
gst_pb_utils_codec_utils_ensure_debug_category(void)50 gst_pb_utils_codec_utils_ensure_debug_category (void)
51 {
52   static gsize cat_gonce = 0;
53 
54   if (g_once_init_enter (&cat_gonce)) {
55     GstDebugCategory *cat = NULL;
56 
57     GST_DEBUG_CATEGORY_INIT (cat, "codec-utils", 0,
58         "GstPbUtils codec helper functions");
59 
60     g_once_init_leave (&cat_gonce, (gsize) cat);
61   }
62 
63   return (GstDebugCategory *) cat_gonce;
64 }
65 #endif /* GST_DISABLE_GST_DEBUG */
66 
67 #define GST_SIMPLE_CAPS_HAS_NAME(caps,name) \
68     gst_structure_has_name(gst_caps_get_structure((caps),0),(name))
69 
70 #define GST_SIMPLE_CAPS_HAS_FIELD(caps,field) \
71     gst_structure_has_field(gst_caps_get_structure((caps),0),(field))
72 
73 static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
74   32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350
75 };
76 
77 static const gchar *
digit_to_string(guint digit)78 digit_to_string (guint digit)
79 {
80   static const char itoa[][2] = {
81     "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
82   };
83 
84   if (G_LIKELY (digit < 10))
85     return itoa[digit];
86   else
87     return NULL;
88 }
89 
90 /**
91  * gst_codec_utils_aac_get_sample_rate_from_index:
92  * @sr_idx: Sample rate index as from the AudioSpecificConfig (MPEG-4
93  *          container) or ADTS frame header
94  *
95  * Translates the sample rate index found in AAC headers to the actual sample
96  * rate.
97  *
98  * Returns: The sample rate if @sr_idx is valid, 0 otherwise.
99  */
100 guint
gst_codec_utils_aac_get_sample_rate_from_index(guint sr_idx)101 gst_codec_utils_aac_get_sample_rate_from_index (guint sr_idx)
102 {
103   if (G_LIKELY (sr_idx < G_N_ELEMENTS (aac_sample_rates)))
104     return aac_sample_rates[sr_idx];
105 
106   GST_WARNING ("Invalid sample rate index %u", sr_idx);
107   return 0;
108 }
109 
110 /**
111  * gst_codec_utils_aac_get_index_from_sample_rate:
112  * @rate: Sample rate
113  *
114  * Translates the sample rate to the index corresponding to it in AAC spec.
115  *
116  * Returns: The AAC index for this sample rate, -1 if the rate is not a
117  * valid AAC sample rate.
118  */
119 gint
gst_codec_utils_aac_get_index_from_sample_rate(guint rate)120 gst_codec_utils_aac_get_index_from_sample_rate (guint rate)
121 {
122   guint n;
123 
124   for (n = 0; n < G_N_ELEMENTS (aac_sample_rates); n++)
125     if (aac_sample_rates[n] == rate)
126       return n;
127 
128   GST_WARNING ("Invalid sample rate %u", rate);
129   return -1;
130 }
131 
132 static gboolean
gst_codec_utils_aac_get_audio_object_type(GstBitReader * br,guint8 * audio_object_type)133 gst_codec_utils_aac_get_audio_object_type (GstBitReader * br,
134     guint8 * audio_object_type)
135 {
136   guint8 aot;
137 
138   if (!gst_bit_reader_get_bits_uint8 (br, &aot, 5))
139     return FALSE;
140 
141   if (aot == 31) {
142     if (!gst_bit_reader_get_bits_uint8 (br, &aot, 6))
143       return FALSE;
144     aot += 32;
145   }
146 
147   *audio_object_type = aot;
148 
149   return TRUE;
150 }
151 
152 static gboolean
gst_codec_utils_aac_get_audio_sample_rate(GstBitReader * br,guint * sample_rate)153 gst_codec_utils_aac_get_audio_sample_rate (GstBitReader * br,
154     guint * sample_rate)
155 {
156   guint8 sampling_freq_index;
157   guint32 sampling_rate;
158 
159   if (!gst_bit_reader_get_bits_uint8 (br, &sampling_freq_index, 4))
160     return FALSE;
161 
162   if (sampling_freq_index == 0xf) {
163     if (!gst_bit_reader_get_bits_uint32 (br, &sampling_rate, 24))
164       return FALSE;
165   } else {
166     sampling_rate =
167         gst_codec_utils_aac_get_sample_rate_from_index (sampling_freq_index);
168     if (!sampling_rate)
169       return FALSE;
170   }
171 
172   *sample_rate = sampling_rate;
173 
174   return TRUE;
175 }
176 
177 static gboolean
gst_codec_utils_aac_get_audio_object_type_full(GstBitReader * br,guint8 * audio_object_type,guint8 * channel_config,guint * sample_rate)178 gst_codec_utils_aac_get_audio_object_type_full (GstBitReader * br,
179     guint8 * audio_object_type, guint8 * channel_config, guint * sample_rate)
180 {
181   guint8 aot, channels;
182   guint rate;
183 
184   if (!gst_codec_utils_aac_get_audio_object_type (br, &aot))
185     return FALSE;
186 
187   if (!gst_codec_utils_aac_get_audio_sample_rate (br, &rate))
188     return FALSE;
189 
190   if (!gst_bit_reader_get_bits_uint8 (br, &channels, 4))
191     return FALSE;
192 
193   /* 5 indicates SBR extension (i.e. HE-AAC) */
194   /* 29 indicates PS extension */
195   if (aot == 5 || aot == 29) {
196     if (!gst_codec_utils_aac_get_audio_sample_rate (br, &rate))
197       return FALSE;
198     if (!gst_codec_utils_aac_get_audio_object_type (br, &aot))
199       return FALSE;
200   }
201 
202   *audio_object_type = aot;
203   *sample_rate = rate;
204   *channel_config = channels;
205 
206   return TRUE;
207 }
208 
209 /**
210  * gst_codec_utils_aac_get_sample_rate:
211  * @audio_config: (array length=len): a pointer to the AudioSpecificConfig
212  *                as specified in the Elementary Stream Descriptor (esds)
213  *                in ISO/IEC 14496-1.
214  * @len: Length of @audio_config
215  *
216  * Translates the sample rate index found in AAC headers to the actual sample
217  * rate.
218  *
219  * Returns: The sample rate if sr_idx is valid, 0 otherwise.
220  *
221  * Since: 1.10
222  */
223 guint
gst_codec_utils_aac_get_sample_rate(const guint8 * audio_config,guint len)224 gst_codec_utils_aac_get_sample_rate (const guint8 * audio_config, guint len)
225 {
226   guint sample_rate = 0;
227   guint8 audio_object_type = 0, channel_config = 0;
228   GstBitReader br = GST_BIT_READER_INIT (audio_config, len);
229 
230   if (len < 2)
231     return 0;
232 
233   gst_codec_utils_aac_get_audio_object_type_full (&br, &audio_object_type,
234       &channel_config, &sample_rate);
235 
236   return sample_rate;
237 }
238 
239 /**
240  * gst_codec_utils_aac_get_channels:
241  * @audio_config: (array length=len): a pointer to the AudioSpecificConfig
242  *                as specified in the Elementary Stream Descriptor (esds)
243  *                in ISO/IEC 14496-1.
244  * @len: Length of @audio_config in bytes
245  *
246  * Returns the channels of the given AAC stream.
247  *
248  * Returns: The channels or 0 if the channel could not be determined.
249  *
250  * Since: 1.10
251  */
252 guint
gst_codec_utils_aac_get_channels(const guint8 * audio_config,guint len)253 gst_codec_utils_aac_get_channels (const guint8 * audio_config, guint len)
254 {
255   guint channels;
256 
257   if (len < 2)
258     return 0;
259 
260   channels = (audio_config[1] & 0x7f) >> 3;
261   if (channels > 0 && channels < 7)
262     return channels;
263   else if (channels == 7)
264     return 8;
265   else
266     return 0;
267 }
268 
269 /**
270  * gst_codec_utils_aac_get_profile:
271  * @audio_config: (array length=len): a pointer to the AudioSpecificConfig
272  *                as specified in the Elementary Stream Descriptor (esds)
273  *                in ISO/IEC 14496-1.
274  * @len: Length of @audio_config in bytes
275  *
276  * Returns the profile of the given AAC stream as a string. The profile is
277  * normally determined using the AudioObjectType field which is in the first
278  * 5 bits of @audio_config
279  *
280  * Returns: (nullable): The profile as a const string and %NULL if the profile could not be
281  * determined.
282  */
283 const gchar *
gst_codec_utils_aac_get_profile(const guint8 * audio_config,guint len)284 gst_codec_utils_aac_get_profile (const guint8 * audio_config, guint len)
285 {
286   const gchar *profile = NULL;
287   guint sample_rate;
288   guint8 audio_object_type, channel_config;
289   GstBitReader br = GST_BIT_READER_INIT (audio_config, len);
290 
291   if (len < 1)
292     return NULL;
293 
294   GST_MEMDUMP ("audio config", audio_config, len);
295 
296   if (!gst_codec_utils_aac_get_audio_object_type_full (&br, &audio_object_type,
297           &channel_config, &sample_rate)) {
298     return NULL;
299   }
300 
301   switch (audio_object_type) {
302     case 1:
303       profile = "main";
304       break;
305     case 2:
306       profile = "lc";
307       break;
308     case 3:
309       profile = "ssr";
310       break;
311     case 4:
312       profile = "ltp";
313       break;
314     default:
315       GST_DEBUG ("Invalid profile idx: %u", audio_object_type);
316       break;
317   }
318 
319   return profile;
320 }
321 
322 /**
323  * gst_codec_utils_aac_get_level:
324  * @audio_config: (array length=len): a pointer to the AudioSpecificConfig
325  *                as specified in the Elementary Stream Descriptor (esds)
326  *                in ISO/IEC 14496-1.
327  * @len: Length of @audio_config in bytes
328  *
329  * Determines the level of a stream as defined in ISO/IEC 14496-3. For AAC LC
330  * streams, the constraints from the AAC audio profile are applied. For AAC
331  * Main, LTP, SSR and others, the Main profile is used.
332  *
333  * The @audio_config parameter follows the following format, starting from the
334  * most significant bit of the first byte:
335  *
336  *   * Bit 0:4 contains the AudioObjectType (if this is 0x5, then the
337  *     real AudioObjectType is carried after the rate and channel data)
338  *   * Bit 5:8 contains the sample frequency index (if this is 0xf, then the
339  *     next 24 bits define the actual sample frequency, and subsequent
340  *     fields are appropriately shifted).
341  *   * Bit 9:12 contains the channel configuration
342  *
343  * Returns: (nullable): The level as a const string and %NULL if the level could not be
344  * determined.
345  */
346 const gchar *
gst_codec_utils_aac_get_level(const guint8 * audio_config,guint len)347 gst_codec_utils_aac_get_level (const guint8 * audio_config, guint len)
348 {
349   guint8 audio_object_type = 0xFF, channel_config = 0xFF;
350   guint rate;
351   /* Number of single channel elements, channel pair elements, low frequency
352    * elements, independently switched coupling channel elements, and
353    * dependently switched coupling channel elements.
354    *
355    * Note: The 2 CCE types are ignored for now as they require us to actually
356    * parse the first frame, and they are rarely found in actual streams.
357    */
358   int num_sce = 0, num_cpe = 0, num_lfe = 0, num_cce_indep = 0, num_cce_dep = 0;
359   int num_channels;
360   /* Processor and RAM Complexity Units (calculated and "reference" for single
361    * channel) */
362   int pcu = -1, rcu = -1, pcu_ref, rcu_ref;
363   int ret = -1;
364   GstBitReader br = GST_BIT_READER_INIT (audio_config, len);
365 
366   g_return_val_if_fail (audio_config != NULL, NULL);
367 
368   if (len < 2)
369     return NULL;
370 
371   GST_MEMDUMP ("audio config", audio_config, len);
372 
373   if (!gst_codec_utils_aac_get_audio_object_type_full (&br, &audio_object_type,
374           &channel_config, &rate)) {
375     return NULL;
376   }
377 
378   switch (channel_config) {
379     case 0:
380       /* Channel config is defined in the AudioObjectType's SpecificConfig,
381        * which requires some amount of digging through the headers. I only see
382        * this done in the MPEG conformance streams - FIXME */
383       GST_WARNING ("Found a stream with channel configuration in the "
384           "AudioSpecificConfig. Please file a bug with a link to the media if "
385           "possible.");
386       return NULL;
387     case 1:
388       /* front center */
389       num_sce = 1;
390       break;
391     case 2:
392       /* front left and right */
393       num_cpe = 1;
394       break;
395     case 3:
396       /* front left, right, and center */
397       num_sce = 1;
398       num_cpe = 1;
399       break;
400     case 4:
401       /* front left, right, and center; rear surround */
402       num_sce = 2;
403       num_cpe = 1;
404       break;
405     case 5:
406       /* front left, right, and center; rear left and right surround */
407       num_sce = 1;
408       num_cpe = 2;
409       break;
410     case 6:
411       /* front left, right, center and LFE; rear left and right surround */
412       num_sce = 1;
413       num_cpe = 2;
414       break;
415     case 7:
416     case 12:
417     case 14:
418       /* front left, right, center and LFE; outside front left and right;
419        * rear left and right surround */
420       num_sce = 1;
421       num_cpe = 3;
422       num_lfe = 1;
423       break;
424     case 11:
425       num_sce = 2;
426       num_cpe = 2;
427       num_lfe = 1;
428       break;
429     default:
430       GST_WARNING ("Unknown channel config in header: %d", channel_config);
431       return NULL;
432   }
433 
434   switch (audio_object_type) {
435     case 0:                    /* NULL */
436       GST_WARNING ("profile 0 is not a valid profile");
437       return NULL;
438     case 2:                    /* LC */
439       pcu_ref = 3;
440       rcu_ref = 3;
441       break;
442     case 3:                    /* SSR */
443       pcu_ref = 4;
444       rcu_ref = 3;
445       break;
446     case 4:                    /* LTP */
447       pcu_ref = 4;
448       rcu_ref = 4;
449       break;
450     case 1:                    /* Main */
451     default:
452       /* Other than a couple of ER profiles, Main is the worst-case */
453       pcu_ref = 5;
454       rcu_ref = 5;
455       break;
456   }
457 
458   /* "fs_ref" is 48000 Hz for AAC Main/LC/SSR/LTP. SBR's fs_ref is defined as
459    * 24000/48000 (in/out), for SBR streams. Actual support is a FIXME */
460 
461   pcu = ((float) rate / 48000) * pcu_ref *
462       ((2 * num_cpe) + num_sce + num_lfe + num_cce_indep + (0.3 * num_cce_dep));
463 
464   rcu = ((float) rcu_ref) * (num_sce + (0.5 * num_lfe) + (0.5 * num_cce_indep) +
465       (0.4 * num_cce_dep));
466 
467   if (num_cpe < 2)
468     rcu += (rcu_ref + (rcu_ref - 1)) * num_cpe;
469   else
470     rcu += (rcu_ref + (rcu_ref - 1) * ((2 * num_cpe) - 1));
471 
472   num_channels = num_sce + (2 * num_cpe);
473 
474   if (audio_object_type == 2) {
475     /* AAC LC => return the level as per the 'AAC Profile' */
476     if (num_channels <= 2 && rate <= 24000 && pcu <= 3 && rcu <= 5)
477       ret = 1;
478     else if (num_channels <= 2 && rate <= 48000 && pcu <= 6 && rcu <= 5)
479       ret = 2;
480     /* There is no level 3 for the AAC Profile */
481     else if (num_channels <= 5 && rate <= 48000 && pcu <= 19 && rcu <= 15)
482       ret = 4;
483     else if (num_channels <= 5 && rate <= 96000 && pcu <= 38 && rcu <= 15)
484       ret = 5;
485     else if (num_channels <= 7 && rate <= 48000 && pcu <= 25 && rcu <= 19)
486       ret = 6;
487     else if (num_channels <= 7 && rate <= 96000 && pcu <= 50 && rcu <= 19)
488       ret = 7;
489   } else {
490     /* Return the level as per the 'Main Profile' */
491     if (pcu < 40 && rcu < 20)
492       ret = 1;
493     else if (pcu < 80 && rcu < 64)
494       ret = 2;
495     else if (pcu < 160 && rcu < 128)
496       ret = 3;
497     else if (pcu < 320 && rcu < 256)
498       ret = 4;
499   }
500 
501   if (ret == -1) {
502     GST_WARNING ("couldn't determine level: profile=%u, rate=%u, "
503         "channel_config=%u, pcu=%d,rcu=%d", audio_object_type, rate,
504         channel_config, pcu, rcu);
505     return NULL;
506   } else {
507     return digit_to_string (ret);
508   }
509 }
510 
511 /**
512  * gst_codec_utils_aac_caps_set_level_and_profile:
513  * @caps: the #GstCaps to which level and profile fields are to be added
514  * @audio_config: (array length=len): a pointer to the AudioSpecificConfig
515  *                as specified in the Elementary Stream Descriptor (esds)
516  *                in ISO/IEC 14496-1. (See below for more details)
517  * @len: Length of @audio_config in bytes
518  *
519  * Sets the level and profile on @caps if it can be determined from
520  * @audio_config. See gst_codec_utils_aac_get_level() and
521  * gst_codec_utils_aac_get_profile() for more details on the parameters.
522  * @caps must be audio/mpeg caps with an "mpegversion" field of either 2 or 4.
523  * If mpegversion is 4, the "base-profile" field is also set in @caps.
524  *
525  * Returns: %TRUE if the level and profile could be set, %FALSE otherwise.
526  */
527 gboolean
gst_codec_utils_aac_caps_set_level_and_profile(GstCaps * caps,const guint8 * audio_config,guint len)528 gst_codec_utils_aac_caps_set_level_and_profile (GstCaps * caps,
529     const guint8 * audio_config, guint len)
530 {
531   GstStructure *s;
532   const gchar *level, *profile;
533   int mpegversion = 0;
534 
535   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
536   g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE);
537   g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_NAME (caps, "audio/mpeg"), FALSE);
538   g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_FIELD (caps, "mpegversion"), FALSE);
539   g_return_val_if_fail (audio_config != NULL, FALSE);
540 
541   s = gst_caps_get_structure (caps, 0);
542 
543   gst_structure_get_int (s, "mpegversion", &mpegversion);
544   g_return_val_if_fail (mpegversion == 2 || mpegversion == 4, FALSE);
545 
546   level = gst_codec_utils_aac_get_level (audio_config, len);
547 
548   if (level != NULL)
549     gst_structure_set (s, "level", G_TYPE_STRING, level, NULL);
550 
551   profile = gst_codec_utils_aac_get_profile (audio_config, len);
552 
553   if (profile != NULL) {
554     if (mpegversion == 4) {
555       gst_structure_set (s, "base-profile", G_TYPE_STRING, profile,
556           "profile", G_TYPE_STRING, profile, NULL);
557     } else {
558       gst_structure_set (s, "profile", G_TYPE_STRING, profile, NULL);
559     }
560   }
561 
562   GST_LOG ("profile : %s", (profile) ? profile : "---");
563   GST_LOG ("level   : %s", (level) ? level : "---");
564 
565   return (level != NULL && profile != NULL);
566 }
567 
568 /**
569  * gst_codec_utils_h264_get_profile:
570  * @sps: (array length=len): Pointer to the sequence parameter set for the stream.
571  * @len: Length of the data available in @sps.
572  *
573  * Converts the profile indication (profile_idc) in the stream's
574  * sequence parameter set into a string. The SPS is expected to have the
575  * following format, as defined in the H.264 specification. The SPS is viewed
576  * as a bitstream here, with bit 0 being the most significant bit of the first
577  * byte.
578  *
579  * * Bit 0:7   - Profile indication
580  * * Bit 8     - constraint_set0_flag
581  * * Bit 9     - constraint_set1_flag
582  * * Bit 10    - constraint_set2_flag
583  * * Bit 11    - constraint_set3_flag
584  * * Bit 12    - constraint_set3_flag
585  * * Bit 13:15 - Reserved
586  * * Bit 16:24 - Level indication
587  *
588  * Returns: (nullable): The profile as a const string, or %NULL if there is an error.
589  */
590 const gchar *
gst_codec_utils_h264_get_profile(const guint8 * sps,guint len)591 gst_codec_utils_h264_get_profile (const guint8 * sps, guint len)
592 {
593   const gchar *profile = NULL;
594   gint csf1, csf3, csf4, csf5;
595 
596   g_return_val_if_fail (sps != NULL, NULL);
597 
598   if (len < 2)
599     return NULL;
600 
601   GST_MEMDUMP ("SPS", sps, len);
602 
603   csf1 = (sps[1] & 0x40) >> 6;
604   csf3 = (sps[1] & 0x10) >> 4;
605   csf4 = (sps[1] & 0x08) >> 3;
606   csf5 = (sps[1] & 0x04) >> 2;
607 
608   switch (sps[0]) {
609     case 66:
610       if (csf1)
611         profile = "constrained-baseline";
612       else
613         profile = "baseline";
614       break;
615     case 77:
616       profile = "main";
617       break;
618     case 88:
619       profile = "extended";
620       break;
621     case 100:
622       if (csf4) {
623         if (csf5)
624           profile = "constrained-high";
625         else
626           profile = "progressive-high";
627       } else
628         profile = "high";
629       break;
630     case 110:
631       if (csf3)
632         profile = "high-10-intra";
633       else if (csf4)
634         profile = "progressive-high-10";
635       else
636         profile = "high-10";
637       break;
638     case 122:
639       if (csf3)
640         profile = "high-4:2:2-intra";
641       else
642         profile = "high-4:2:2";
643       break;
644     case 244:
645       if (csf3)
646         profile = "high-4:4:4-intra";
647       else
648         profile = "high-4:4:4";
649       break;
650     case 44:
651       profile = "cavlc-4:4:4-intra";
652       break;
653     case 118:
654       profile = "multiview-high";
655       break;
656     case 128:
657       profile = "stereo-high";
658       break;
659     case 83:
660       if (csf5)
661         profile = "scalable-constrained-baseline";
662       else
663         profile = "scalable-baseline";
664       break;
665     case 86:
666       if (csf3)
667         profile = "scalable-high-intra";
668       else if (csf5)
669         profile = "scalable-constrained-high";
670       else
671         profile = "scalable-high";
672       break;
673     default:
674       return NULL;
675   }
676 
677   return profile;
678 }
679 
680 /**
681  * gst_codec_utils_h264_get_level:
682  * @sps: (array length=len): Pointer to the sequence parameter set for the stream.
683  * @len: Length of the data available in @sps.
684  *
685  * Converts the level indication (level_idc) in the stream's
686  * sequence parameter set into a string. The SPS is expected to have the
687  * same format as for gst_codec_utils_h264_get_profile().
688  *
689  * Returns: (nullable): The level as a const string, or %NULL if there is an error.
690  */
691 const gchar *
gst_codec_utils_h264_get_level(const guint8 * sps,guint len)692 gst_codec_utils_h264_get_level (const guint8 * sps, guint len)
693 {
694   gint csf3;
695 
696   g_return_val_if_fail (sps != NULL, NULL);
697 
698   if (len < 3)
699     return NULL;
700 
701   GST_MEMDUMP ("SPS", sps, len);
702 
703   csf3 = (sps[1] & 0x10) >> 4;
704 
705   if (sps[2] == 0)
706     return NULL;
707   else if ((sps[2] == 11 && csf3) || sps[2] == 9)
708     return "1b";
709   else if (sps[2] % 10 == 0)
710     return digit_to_string (sps[2] / 10);
711   else {
712     switch (sps[2]) {
713       case 11:
714         return "1.1";
715       case 12:
716         return "1.2";
717       case 13:
718         return "1.3";
719       case 21:
720         return "2.1";
721       case 22:
722         return "2.2";
723       case 31:
724         return "3.1";
725       case 32:
726         return "3.2";
727       case 41:
728         return "4.1";
729       case 42:
730         return "4.2";
731       case 51:
732         return "5.1";
733       case 52:
734         return "5.2";
735       case 61:
736         return "6.1";
737       case 62:
738         return "6.2";
739       default:
740         return NULL;
741     }
742   }
743 }
744 
745 /**
746  * gst_codec_utils_h264_get_level_idc:
747  * @level: A level string from caps
748  *
749  * Transform a level string from the caps into the level_idc
750  *
751  * Returns: the level_idc or 0 if the level is unknown
752  */
753 guint8
gst_codec_utils_h264_get_level_idc(const gchar * level)754 gst_codec_utils_h264_get_level_idc (const gchar * level)
755 {
756   g_return_val_if_fail (level != NULL, 0);
757 
758   if (!strcmp (level, "1"))
759     return 10;
760   else if (!strcmp (level, "1b"))
761     return 9;
762   else if (!strcmp (level, "1.1"))
763     return 11;
764   else if (!strcmp (level, "1.2"))
765     return 12;
766   else if (!strcmp (level, "1.3"))
767     return 13;
768   else if (!strcmp (level, "2"))
769     return 20;
770   else if (!strcmp (level, "2.1"))
771     return 21;
772   else if (!strcmp (level, "2.2"))
773     return 22;
774   else if (!strcmp (level, "3"))
775     return 30;
776   else if (!strcmp (level, "3.1"))
777     return 31;
778   else if (!strcmp (level, "3.2"))
779     return 32;
780   else if (!strcmp (level, "4"))
781     return 40;
782   else if (!strcmp (level, "4.1"))
783     return 41;
784   else if (!strcmp (level, "4.2"))
785     return 42;
786   else if (!strcmp (level, "5"))
787     return 50;
788   else if (!strcmp (level, "5.1"))
789     return 51;
790   else if (!strcmp (level, "5.2"))
791     return 52;
792   else if (!strcmp (level, "6"))
793     return 60;
794   else if (!strcmp (level, "6.1"))
795     return 61;
796   else if (!strcmp (level, "6.2"))
797     return 62;
798 
799   GST_WARNING ("Invalid level %s", level);
800   return 0;
801 }
802 
803 /**
804  * gst_codec_utils_h264_caps_set_level_and_profile:
805  * @caps: the #GstCaps to which the level and profile are to be added
806  * @sps: (array length=len): Pointer to the sequence parameter set for the stream.
807  * @len: Length of the data available in @sps.
808  *
809  * Sets the level and profile in @caps if it can be determined from @sps. See
810  * gst_codec_utils_h264_get_level() and gst_codec_utils_h264_get_profile()
811  * for more details on the parameters.
812  *
813  * Returns: %TRUE if the level and profile could be set, %FALSE otherwise.
814  */
815 gboolean
gst_codec_utils_h264_caps_set_level_and_profile(GstCaps * caps,const guint8 * sps,guint len)816 gst_codec_utils_h264_caps_set_level_and_profile (GstCaps * caps,
817     const guint8 * sps, guint len)
818 {
819   const gchar *level, *profile;
820 
821   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
822   g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE);
823   g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_NAME (caps, "video/x-h264"), FALSE);
824   g_return_val_if_fail (sps != NULL, FALSE);
825 
826   level = gst_codec_utils_h264_get_level (sps, len);
827 
828   if (level != NULL)
829     gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
830 
831   profile = gst_codec_utils_h264_get_profile (sps, len);
832 
833   if (profile != NULL)
834     gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
835 
836   GST_LOG ("profile : %s", (profile) ? profile : "---");
837   GST_LOG ("level   : %s", (level) ? level : "---");
838 
839   return (level != NULL && profile != NULL);
840 }
841 
842 /**
843  * gst_codec_utils_h264_get_profile_flags_level:
844  * @codec_data: (array length=len): H264 AVCC extradata
845  * @len: length of @codec_data
846  * @profile: (optional) (out): return location for h264 profile_idc or %NULL
847  * @flags: (optional) (out): return location for h264 constraint set flags or %NULL
848  * @level: (optional) (out): return location h264 level_idc or %NULL
849  *
850  * Parses profile, flags, and level from a H264 AVCC extradata/sequence_header.
851  * These are most commonly retrieved from a video/x-h264 caps with a codec_data
852  * buffer.
853  *
854  * The format of H264 AVCC extradata/sequence_header is documented in the
855  * ITU-T H.264 specification section 7.3.2.1.1 as well as in ISO/IEC 14496-15
856  * section 5.3.3.1.2.
857  *
858  * Returns: %TRUE on success, %FALSE on failure
859  *
860  * Since: 1.20
861  */
862 gboolean
gst_codec_utils_h264_get_profile_flags_level(const guint8 * codec_data,guint len,guint8 * profile,guint8 * flags,guint8 * level)863 gst_codec_utils_h264_get_profile_flags_level (const guint8 * codec_data,
864     guint len, guint8 * profile, guint8 * flags, guint8 * level)
865 {
866   gboolean ret = FALSE;
867 
868   g_return_val_if_fail (codec_data != NULL, FALSE);
869 
870   if (len < 7) {
871     GST_WARNING ("avc codec data is too small");
872     goto done;
873   }
874   if (codec_data[0] != 1) {
875     GST_WARNING ("failed to parse avc codec version, must be 1");
876     goto done;
877   }
878 
879   if (profile) {
880     *profile = codec_data[1];
881   }
882   if (flags) {
883     *flags = codec_data[2];
884   }
885   if (level) {
886     *level = codec_data[3];
887   }
888 
889   ret = TRUE;
890 
891 done:
892   return ret;
893 }
894 
895 /* forked from gsth265parse.c */
896 typedef struct
897 {
898   const gchar *profile;
899 
900   guint8 max_14bit_constraint_flag;
901   guint8 max_12bit_constraint_flag;
902   guint8 max_10bit_constraint_flag;
903   guint8 max_8bit_constraint_flag;
904   guint8 max_422chroma_constraint_flag;
905   guint8 max_420chroma_constraint_flag;
906   guint8 max_monochrome_constraint_flag;
907   guint8 intra_constraint_flag;
908   guint8 one_picture_only_constraint_flag;
909   guint8 lower_bit_rate_constraint_flag;
910 
911   /* Tie breaker if more than one profiles are matching */
912   guint priority;
913 } GstH265ExtensionProfile;
914 
915 typedef struct
916 {
917   const GstH265ExtensionProfile *profile;
918   guint extra_constraints;
919 } H265ExtensionProfileMatch;
920 
921 static gint
sort_fre_profile_matches(H265ExtensionProfileMatch * a,H265ExtensionProfileMatch * b)922 sort_fre_profile_matches (H265ExtensionProfileMatch * a,
923     H265ExtensionProfileMatch * b)
924 {
925   gint d;
926 
927   d = a->extra_constraints - b->extra_constraints;
928   if (d)
929     return d;
930 
931   return b->profile->priority - a->profile->priority;
932 }
933 
934 static const gchar *
utils_get_extension_profile(const GstH265ExtensionProfile * profiles,guint num,GstH265ExtensionProfile * ext_profile)935 utils_get_extension_profile (const GstH265ExtensionProfile * profiles,
936     guint num, GstH265ExtensionProfile * ext_profile)
937 {
938   guint i;
939   const gchar *profile = NULL;
940   GList *cand = NULL;
941 
942   for (i = 0; i < num; i++) {
943     GstH265ExtensionProfile p = profiles[i];
944     guint extra_constraints = 0;
945     H265ExtensionProfileMatch *m;
946 
947     /* Filter out all the profiles having constraints not satisfied by
948      * @ext_profile.
949      * Then pick the one having the least extra constraints. This allow us
950      * to match the closet profile if bitstream contains not standard
951      * constraints. */
952     if (p.max_14bit_constraint_flag != ext_profile->max_14bit_constraint_flag) {
953       if (p.max_14bit_constraint_flag)
954         continue;
955       extra_constraints++;
956     }
957 
958     if (p.max_12bit_constraint_flag != ext_profile->max_12bit_constraint_flag) {
959       if (p.max_12bit_constraint_flag)
960         continue;
961       extra_constraints++;
962     }
963 
964     if (p.max_10bit_constraint_flag != ext_profile->max_10bit_constraint_flag) {
965       if (p.max_10bit_constraint_flag)
966         continue;
967       extra_constraints++;
968     }
969 
970     if (p.max_8bit_constraint_flag != ext_profile->max_8bit_constraint_flag) {
971       if (p.max_8bit_constraint_flag)
972         continue;
973       extra_constraints++;
974     }
975 
976     if (p.max_422chroma_constraint_flag !=
977         ext_profile->max_422chroma_constraint_flag) {
978       if (p.max_422chroma_constraint_flag)
979         continue;
980       extra_constraints++;
981     }
982 
983     if (p.max_420chroma_constraint_flag !=
984         ext_profile->max_420chroma_constraint_flag) {
985       if (p.max_420chroma_constraint_flag)
986         continue;
987       extra_constraints++;
988     }
989 
990     if (p.max_monochrome_constraint_flag !=
991         ext_profile->max_monochrome_constraint_flag) {
992       if (p.max_monochrome_constraint_flag)
993         continue;
994       extra_constraints++;
995     }
996 
997     if (p.intra_constraint_flag != ext_profile->intra_constraint_flag) {
998       if (p.intra_constraint_flag)
999         continue;
1000       extra_constraints++;
1001     }
1002 
1003     if (p.one_picture_only_constraint_flag !=
1004         ext_profile->one_picture_only_constraint_flag) {
1005       if (p.one_picture_only_constraint_flag)
1006         continue;
1007       extra_constraints++;
1008     }
1009 
1010     if (p.lower_bit_rate_constraint_flag
1011         && !ext_profile->lower_bit_rate_constraint_flag)
1012       continue;
1013 
1014     /* choose this one if all flags are matched */
1015     if (extra_constraints == 0) {
1016       profile = p.profile;
1017       break;
1018     }
1019 
1020     m = g_new0 (H265ExtensionProfileMatch, 1);
1021     m->profile = &profiles[i];
1022     m->extra_constraints = extra_constraints;
1023     cand = g_list_prepend (cand, m);
1024   }
1025 
1026   if (!profile && cand) {
1027     H265ExtensionProfileMatch *m;
1028 
1029     cand = g_list_sort (cand, (GCompareFunc) sort_fre_profile_matches);
1030     m = cand->data;
1031     profile = m->profile->profile;
1032   }
1033 
1034   if (cand)
1035     g_list_free_full (cand, g_free);
1036 
1037   return profile;
1038 }
1039 
1040 static const gchar *
utils_get_format_range_extension_profile(GstH265ExtensionProfile * ext_profile)1041 utils_get_format_range_extension_profile (GstH265ExtensionProfile * ext_profile)
1042 {
1043   static const GstH265ExtensionProfile profiles[] = {
1044     /* FIXME 2.0: Consider ':' separated subsampling notation for consistency
1045      * https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/merge_requests/23
1046      */
1047     /* Rec. ITU-T H.265 Table A.2 format range extensions profiles */
1048     /* *INDENT-OFF* */
1049     {"monochrome",                    0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0},
1050     {"monochrome-10",                 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1},
1051     {"monochrome-12",                 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 2},
1052     {"monochrome-16",                 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 3},
1053     {"main-12",                       0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 4},
1054     {"main-422-10",                   0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 5},
1055     {"main-422-12",                   0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 6},
1056     {"main-444",                      0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 7},
1057     {"main-444-10",                   0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 8},
1058     {"main-444-12",                   0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 9},
1059     {"main-intra",                    0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 10},
1060     {"main-10-intra",                 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 11},
1061     {"main-12-intra",                 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 12},
1062     {"main-422-10-intra",             0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 13},
1063     {"main-422-12-intra",             0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 14},
1064     {"main-444-intra",                0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 15},
1065     {"main-444-10-intra",             0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 16},
1066     {"main-444-12-intra",             0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 17},
1067     {"main-444-16-intra",             0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 18},
1068     {"main-444-still-picture",        0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 19},
1069     {"main-444-16-still-picture",     0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 20},
1070     /* *INDENT-ON* */
1071   };
1072 
1073   return utils_get_extension_profile (profiles, G_N_ELEMENTS (profiles),
1074       ext_profile);
1075 }
1076 
1077 static const gchar *
utils_get_3d_profile(GstH265ExtensionProfile * ext_profile)1078 utils_get_3d_profile (GstH265ExtensionProfile * ext_profile)
1079 {
1080   static const GstH265ExtensionProfile profiles[] = {
1081     /* Rec. ITU-T H.265 I.11.1 3D Main profile */
1082     /* *INDENT-OFF* */
1083     {"3d-main",                       0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0},
1084     /* *INDENT-ON* */
1085   };
1086 
1087   return utils_get_extension_profile (profiles, G_N_ELEMENTS (profiles),
1088       ext_profile);
1089 }
1090 
1091 static const gchar *
utils_get_multiview_profile(GstH265ExtensionProfile * ext_profile)1092 utils_get_multiview_profile (GstH265ExtensionProfile * ext_profile)
1093 {
1094   static const GstH265ExtensionProfile profiles[] = {
1095     /* Rec. ITU-T H.265 G.11.1 Multiview Main profile */
1096     /* *INDENT-OFF* */
1097     {"multiview-main",                0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0},
1098     /* *INDENT-ON* */
1099   };
1100 
1101   return utils_get_extension_profile (profiles, G_N_ELEMENTS (profiles),
1102       ext_profile);
1103 }
1104 
1105 static const gchar *
utils_get_scalable_profile(GstH265ExtensionProfile * ext_profile)1106 utils_get_scalable_profile (GstH265ExtensionProfile * ext_profile)
1107 {
1108   static const GstH265ExtensionProfile profiles[] = {
1109     /* Rec. ITU-T H.265 H.11.1 */
1110     /* *INDENT-OFF* */
1111     {"scalable-main",                 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0},
1112     {"scalable-main-10",              0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1},
1113     /* *INDENT-ON* */
1114   };
1115 
1116   return utils_get_extension_profile (profiles, G_N_ELEMENTS (profiles),
1117       ext_profile);
1118 }
1119 
1120 static const gchar *
utils_get_high_throughput_profile(GstH265ExtensionProfile * ext_profile)1121 utils_get_high_throughput_profile (GstH265ExtensionProfile * ext_profile)
1122 {
1123   static const GstH265ExtensionProfile profiles[] = {
1124     /* Rec. ITU-T H.265 Table A.3 high throughput profiles */
1125     /* *INDENT-OFF* */
1126     {"high-throughput-444",           1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0},
1127     {"high-throughput-444-10",        1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1},
1128     {"high-throughput-444-14",        1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2},
1129     {"high-throughput-444-16-intra",  0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 3},
1130     /* *INDENT-ON* */
1131   };
1132 
1133   return utils_get_extension_profile (profiles, G_N_ELEMENTS (profiles),
1134       ext_profile);
1135 }
1136 
1137 static const gchar *
utils_get_screen_content_coding_extensions_profile(GstH265ExtensionProfile * ext_profile)1138 utils_get_screen_content_coding_extensions_profile (GstH265ExtensionProfile *
1139     ext_profile)
1140 {
1141   static const GstH265ExtensionProfile profiles[] = {
1142     /* Rec. ITU-T H.265 Table A.5 screen content coding extensions profiles */
1143     /* *INDENT-OFF* */
1144     {"screen-extended-main",          1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0},
1145     {"screen-extended-main-10",       1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1},
1146     {"screen-extended-main-444",      1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 2},
1147     {"screen-extended-main-444-10",   1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 3},
1148     /* identical to screen-extended-main-444 */
1149     {"screen-extended-high-throughput-444",
1150                                       1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 4},
1151     /* identical to screen-extended-main-444-10 */
1152     {"screen-extended-high-throughput-444-10",
1153                                       1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 5},
1154     {"screen-extended-high-throughput-444-14",
1155                                       1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 6},
1156     /* *INDENT-ON* */
1157   };
1158 
1159   return utils_get_extension_profile (profiles, G_N_ELEMENTS (profiles),
1160       ext_profile);
1161 }
1162 
1163 static const gchar *
utils_get_scalable_format_range_extensions_profile(GstH265ExtensionProfile * ext_profile)1164 utils_get_scalable_format_range_extensions_profile (GstH265ExtensionProfile *
1165     ext_profile)
1166 {
1167   static const GstH265ExtensionProfile profiles[] = {
1168     /* Rec. ITU-T H.265 Table H.4 scalable range extensions profiles */
1169     /* *INDENT-OFF* */
1170     {"scalable-monochrome",           1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0},
1171     {"scalable-monochrome-12",        1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1},
1172     {"scalable-monochrome-16",        0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 2},
1173     {"scalable-main-444",             1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 3},
1174     /* *INDENT-ON* */
1175   };
1176 
1177   return utils_get_extension_profile (profiles, G_N_ELEMENTS (profiles),
1178       ext_profile);
1179 }
1180 
1181 /**
1182  * gst_codec_utils_h265_get_profile:
1183  * @profile_tier_level: (array length=len): Pointer to the profile_tier_level
1184  *   structure for the stream.
1185  * @len: Length of the data available in @profile_tier_level
1186  *
1187  * Converts the profile indication (general_profile_idc) in the stream's
1188  * profile_level_tier structure into a string. The profile_tier_level is
1189  * expected to have the following format, as defined in the H.265
1190  * specification. The profile_tier_level is viewed as a bitstream here,
1191  * with bit 0 being the most significant bit of the first byte.
1192  *
1193  * * Bit 0:1   - general_profile_space
1194  * * Bit 2     - general_tier_flag
1195  * * Bit 3:7   - general_profile_idc
1196  * * Bit 8:39  - gernal_profile_compatibility_flags
1197  * * Bit 40    - general_progressive_source_flag
1198  * * Bit 41    - general_interlaced_source_flag
1199  * * Bit 42    - general_non_packed_constraint_flag
1200  * * Bit 43    - general_frame_only_constraint_flag
1201  * * Bit 44:87 - See below
1202  * * Bit 88:95 - general_level_idc
1203  *
1204  * Returns: (nullable): The profile as a const string, or %NULL if there is an error.
1205  *
1206  * Since: 1.4
1207  */
1208 const gchar *
gst_codec_utils_h265_get_profile(const guint8 * profile_tier_level,guint len)1209 gst_codec_utils_h265_get_profile (const guint8 * profile_tier_level, guint len)
1210 {
1211   const gchar *profile = NULL;
1212   gint profile_idc;
1213   guint i;
1214   guint8 profile_compatibility_flags[32] = { 0, };
1215   GstBitReader br = GST_BIT_READER_INIT (profile_tier_level, len);
1216 
1217   g_return_val_if_fail (profile_tier_level != NULL, NULL);
1218 
1219   if (len < 2)
1220     return NULL;
1221 
1222   GST_MEMDUMP ("ProfileTierLevel", profile_tier_level, len);
1223 
1224   profile_idc = (profile_tier_level[0] & 0x1f);
1225 
1226   if (profile_idc == 1)
1227     profile = "main";
1228   else if (profile_idc == 2)
1229     profile = "main-10";
1230   else if (profile_idc == 3)
1231     profile = "main-still-picture";
1232 
1233   if (len > 4) {
1234     if (!gst_bit_reader_skip (&br, 8))
1235       return NULL;
1236 
1237     for (i = 0; i < 32; i++) {
1238       if (!gst_bit_reader_get_bits_uint8 (&br, &profile_compatibility_flags[i],
1239               1))
1240         return NULL;
1241     }
1242   }
1243 
1244   if (!profile) {
1245     if (profile_compatibility_flags[1])
1246       profile = "main";
1247     else if (profile_compatibility_flags[2])
1248       profile = "main-10";
1249     else if (profile_compatibility_flags[3])
1250       profile = "main-still-picture";
1251   }
1252 
1253   if (profile)
1254     return profile;
1255 
1256   if (profile_idc >= 4 && profile_idc <= 11 && len >= 11) {
1257     GstH265ExtensionProfile ext_profile = { 0, };
1258 
1259     /*
1260      * Bit 40 - general_progressive_source_flag
1261      * Bit 41 - general_interlaced_source_flag
1262      * Bit 42 - general_non_packed_constraint_flag
1263      * Bit 43 - general_frame_only_constraint_flag
1264      */
1265     if (!gst_bit_reader_skip (&br, 4))
1266       return NULL;
1267 
1268     /* Range extensions
1269      * profile_idc
1270      *   4 : Format range extensions profiles
1271      *   5 : High throughput profiles
1272      *   6 : Multiview main profile
1273      *   7 : Scalable main profiles
1274      *   8 : 3D Main profile
1275      *   9 : Screen content coding extensions profiles
1276      *  10 : Scalable format range extensions profiles
1277      *
1278      * Bit 44 - general_max_12bit_constraint_flag
1279      * Bit 45 - general_max_10bit_constraint_flag
1280      * Bit 46 - general_max_8bit_constraint_flag
1281      * Bit 47 - general_max_422chroma_constraint_flag
1282      * Bit 48 - general_max_420chroma_constraint_flag
1283      * Bit 49 - general_max_monochrome_constraint_flag
1284      * Bit 50 - general_intra_constraint_flag
1285      * Bit 51 - general_one_picture_only_constraint_flag
1286      * Bit 52 - general_lower_bit_rate_constraint_flag
1287      */
1288     if (!gst_bit_reader_get_bits_uint8 (&br,
1289             &ext_profile.max_12bit_constraint_flag, 1))
1290       return NULL;
1291 
1292     if (!gst_bit_reader_get_bits_uint8 (&br,
1293             &ext_profile.max_10bit_constraint_flag, 1))
1294       return NULL;
1295 
1296     if (!gst_bit_reader_get_bits_uint8 (&br,
1297             &ext_profile.max_8bit_constraint_flag, 1))
1298       return NULL;
1299 
1300     if (!gst_bit_reader_get_bits_uint8 (&br,
1301             &ext_profile.max_422chroma_constraint_flag, 1))
1302       return NULL;
1303 
1304     if (!gst_bit_reader_get_bits_uint8 (&br,
1305             &ext_profile.max_420chroma_constraint_flag, 1))
1306       return NULL;
1307 
1308     if (!gst_bit_reader_get_bits_uint8 (&br,
1309             &ext_profile.max_monochrome_constraint_flag, 1))
1310       return NULL;
1311 
1312     if (!gst_bit_reader_get_bits_uint8 (&br,
1313             &ext_profile.intra_constraint_flag, 1))
1314       return NULL;
1315 
1316     if (!gst_bit_reader_get_bits_uint8 (&br,
1317             &ext_profile.one_picture_only_constraint_flag, 1))
1318       return NULL;
1319 
1320     if (!gst_bit_reader_get_bits_uint8 (&br,
1321             &ext_profile.lower_bit_rate_constraint_flag, 1))
1322       return NULL;
1323 
1324     if (profile_idc == 5 || profile_idc == 9 ||
1325         profile_idc == 10 || profile_idc == 11 ||
1326         profile_compatibility_flags[5] || profile_compatibility_flags[9] ||
1327         profile_compatibility_flags[10] || profile_compatibility_flags[11]) {
1328       /* Bit 53 - general_max_14bit_constraint_flag */
1329       if (!gst_bit_reader_get_bits_uint8 (&br,
1330               &ext_profile.max_14bit_constraint_flag, 1))
1331         return NULL;
1332     }
1333 
1334     if (profile_idc == 4 || profile_compatibility_flags[4])
1335       return utils_get_format_range_extension_profile (&ext_profile);
1336 
1337     if (profile_idc == 5 || profile_compatibility_flags[5])
1338       return utils_get_high_throughput_profile (&ext_profile);
1339 
1340     if (profile_idc == 6 || profile_compatibility_flags[6])
1341       return utils_get_multiview_profile (&ext_profile);
1342 
1343     if (profile_idc == 7 || profile_compatibility_flags[7])
1344       return utils_get_scalable_profile (&ext_profile);
1345 
1346     if (profile_idc == 8 || profile_compatibility_flags[8])
1347       return utils_get_3d_profile (&ext_profile);
1348 
1349     if (profile_idc == 9 || profile_compatibility_flags[9] ||
1350         profile_idc == 11 || profile_compatibility_flags[11])
1351       return utils_get_screen_content_coding_extensions_profile (&ext_profile);
1352 
1353     if (profile_idc == 10 || profile_compatibility_flags[10])
1354       return utils_get_scalable_format_range_extensions_profile (&ext_profile);
1355   }
1356 
1357   return profile;
1358 }
1359 
1360 /**
1361  * gst_codec_utils_h265_get_tier:
1362  * @profile_tier_level: (array length=len): Pointer to the profile_tier_level
1363  *   for the stream.
1364  * @len: Length of the data available in @profile_tier_level.
1365  *
1366  * Converts the tier indication (general_tier_flag) in the stream's
1367  * profile_tier_level structure into a string. The profile_tier_level
1368  * is expected to have the same format as for gst_codec_utils_h264_get_profile().
1369  *
1370  * Returns: (nullable): The tier as a const string, or %NULL if there is an error.
1371  *
1372  * Since: 1.4
1373  */
1374 const gchar *
gst_codec_utils_h265_get_tier(const guint8 * profile_tier_level,guint len)1375 gst_codec_utils_h265_get_tier (const guint8 * profile_tier_level, guint len)
1376 {
1377   const gchar *tier = NULL;
1378   gint tier_flag = 0;
1379 
1380   g_return_val_if_fail (profile_tier_level != NULL, NULL);
1381 
1382   if (len < 1)
1383     return NULL;
1384 
1385   GST_MEMDUMP ("ProfileTierLevel", profile_tier_level, len);
1386 
1387   tier_flag = (profile_tier_level[0] & 0x20) >> 5;
1388 
1389   if (tier_flag)
1390     tier = "high";
1391   else
1392     tier = "main";
1393 
1394   return tier;
1395 }
1396 
1397 /**
1398  * gst_codec_utils_h265_get_level:
1399  * @profile_tier_level: (array length=len): Pointer to the profile_tier_level
1400  *   for the stream
1401  * @len: Length of the data available in @profile_tier_level.
1402  *
1403  * Converts the level indication (general_level_idc) in the stream's
1404  * profile_tier_level structure into a string. The profiel_tier_level is
1405  * expected to have the same format as for gst_codec_utils_h264_get_profile().
1406  *
1407  * Returns: (nullable): The level as a const string, or %NULL if there is an error.
1408  *
1409  * Since: 1.4
1410  */
1411 const gchar *
gst_codec_utils_h265_get_level(const guint8 * profile_tier_level,guint len)1412 gst_codec_utils_h265_get_level (const guint8 * profile_tier_level, guint len)
1413 {
1414   g_return_val_if_fail (profile_tier_level != NULL, NULL);
1415 
1416   if (len < 12)
1417     return NULL;
1418 
1419   GST_MEMDUMP ("ProfileTierLevel", profile_tier_level, len);
1420 
1421   if (profile_tier_level[11] == 0)
1422     return NULL;
1423   else if (profile_tier_level[11] % 30 == 0)
1424     return digit_to_string (profile_tier_level[11] / 30);
1425   else {
1426     switch (profile_tier_level[11]) {
1427       case 63:
1428         return "2.1";
1429         break;
1430       case 93:
1431         return "3.1";
1432         break;
1433       case 123:
1434         return "4.1";
1435         break;
1436       case 153:
1437         return "5.1";
1438         break;
1439       case 156:
1440         return "5.2";
1441         break;
1442       case 183:
1443         return "6.1";
1444         break;
1445       case 186:
1446         return "6.2";
1447         break;
1448       default:
1449         return NULL;
1450     }
1451   }
1452 }
1453 
1454 /**
1455  * gst_codec_utils_h265_get_level_idc:
1456  * @level: A level string from caps
1457  *
1458  * Transform a level string from the caps into the level_idc
1459  *
1460  * Returns: the level_idc or 0 if the level is unknown
1461  *
1462  * Since: 1.4
1463  */
1464 guint8
gst_codec_utils_h265_get_level_idc(const gchar * level)1465 gst_codec_utils_h265_get_level_idc (const gchar * level)
1466 {
1467   g_return_val_if_fail (level != NULL, 0);
1468 
1469   if (!strcmp (level, "1"))
1470     return 30;
1471   else if (!strcmp (level, "2"))
1472     return 60;
1473   else if (!strcmp (level, "2.1"))
1474     return 63;
1475   else if (!strcmp (level, "3"))
1476     return 90;
1477   else if (!strcmp (level, "3.1"))
1478     return 93;
1479   else if (!strcmp (level, "4"))
1480     return 120;
1481   else if (!strcmp (level, "4.1"))
1482     return 123;
1483   else if (!strcmp (level, "5"))
1484     return 150;
1485   else if (!strcmp (level, "5.1"))
1486     return 153;
1487   else if (!strcmp (level, "5.2"))
1488     return 156;
1489   else if (!strcmp (level, "6"))
1490     return 180;
1491   else if (!strcmp (level, "6.1"))
1492     return 183;
1493   else if (!strcmp (level, "6.2"))
1494     return 186;
1495 
1496   GST_WARNING ("Invalid level %s", level);
1497   return 0;
1498 }
1499 
1500 /**
1501  * gst_codec_utils_h265_caps_set_level_tier_and_profile:
1502  * @caps: the #GstCaps to which the level, tier and profile are to be added
1503  * @profile_tier_level: (array length=len): Pointer to the profile_tier_level
1504  *   struct
1505  * @len: Length of the data available in @profile_tier_level.
1506  *
1507  * Sets the level, tier and profile in @caps if it can be determined from
1508  * @profile_tier_level. See gst_codec_utils_h265_get_level(),
1509  * gst_codec_utils_h265_get_tier() and gst_codec_utils_h265_get_profile()
1510  * for more details on the parameters.
1511  *
1512  * Returns: %TRUE if the level, tier, profile could be set, %FALSE otherwise.
1513  *
1514  * Since: 1.4
1515  */
1516 gboolean
gst_codec_utils_h265_caps_set_level_tier_and_profile(GstCaps * caps,const guint8 * profile_tier_level,guint len)1517 gst_codec_utils_h265_caps_set_level_tier_and_profile (GstCaps * caps,
1518     const guint8 * profile_tier_level, guint len)
1519 {
1520   const gchar *level, *tier, *profile;
1521 
1522   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
1523   g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE);
1524   g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_NAME (caps, "video/x-h265"), FALSE);
1525   g_return_val_if_fail (profile_tier_level != NULL, FALSE);
1526 
1527   level = gst_codec_utils_h265_get_level (profile_tier_level, len);
1528   if (level != NULL)
1529     gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
1530 
1531   tier = gst_codec_utils_h265_get_tier (profile_tier_level, len);
1532   if (tier != NULL)
1533     gst_caps_set_simple (caps, "tier", G_TYPE_STRING, tier, NULL);
1534 
1535   profile = gst_codec_utils_h265_get_profile (profile_tier_level, len);
1536   if (profile != NULL)
1537     gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
1538 
1539   GST_LOG ("profile : %s", (profile) ? profile : "---");
1540   GST_LOG ("tier    : %s", (tier) ? tier : "---");
1541   GST_LOG ("level   : %s", (level) ? level : "---");
1542 
1543   return (level != NULL && tier != NULL && profile != NULL);
1544 }
1545 
1546 /**
1547  * gst_codec_utils_mpeg4video_get_profile:
1548  * @vis_obj_seq: (array length=len): Pointer to the visual object
1549  *   sequence for the stream.
1550  * @len: Length of the data available in @sps.
1551  *
1552  * Converts the profile indication in the stream's visual object sequence into
1553  * a string. @vis_obj_seq is expected to be the data following the visual
1554  * object sequence start code. Only the first byte
1555  * (profile_and_level_indication) is used.
1556  *
1557  * Returns: (nullable): The profile as a const string, or NULL if there is an error.
1558  */
1559 const gchar *
gst_codec_utils_mpeg4video_get_profile(const guint8 * vis_obj_seq,guint len)1560 gst_codec_utils_mpeg4video_get_profile (const guint8 * vis_obj_seq, guint len)
1561 {
1562   /* The profile/level codes are from 14496-2, table G-1, and the Wireshark
1563    * sources: epan/dissectors/packet-mp4ves.c */
1564 
1565   /* These are a direct mapping from the integer profile id -> string. Profiles
1566    * 0x6, 0xe and 0xf can correspond to more than one profile depending on the
1567    * second 4 bits of vis_obj_seq[0], so they are handled separately. */
1568   static const char *profiles[] = { "simple", "simple-scalable", "core",
1569     "main", "n-bit", "scalable", NULL, "basic-animated-texture", "hybrid",
1570     "advanced-real-time-simple", "core-scalable", "advanced-coding-efficiency",
1571     "advanced-core", "advanced-scalable-texture",
1572   };
1573   int profile_id, level_id;
1574 
1575   g_return_val_if_fail (vis_obj_seq != NULL, NULL);
1576 
1577   if (len < 1)
1578     return NULL;
1579 
1580   GST_MEMDUMP ("VOS", vis_obj_seq, len);
1581 
1582   profile_id = vis_obj_seq[0] >> 4;
1583   level_id = vis_obj_seq[0] & 0xf;
1584 
1585   GST_LOG ("profile_id = %d, level_id = %d", profile_id, level_id);
1586 
1587   if (profile_id != 6 && profile_id < 0xe)
1588     return profiles[profile_id];
1589 
1590   if (profile_id != 0xf && level_id == 0)
1591     return NULL;
1592 
1593   switch (profile_id) {
1594     case 0x6:
1595       if (level_id < 3)
1596         return "simple-face";
1597       else if (level_id < 5)
1598         return "simple-fba";
1599       break;
1600 
1601     case 0xe:
1602       if (level_id < 5)
1603         return "simple-studio";
1604       else if (level_id < 9)
1605         return "core-studio";
1606       break;
1607 
1608     case 0xf:
1609       if (level_id < 6)
1610         return "advanced-simple";
1611       else if (level_id > 7 && level_id < 0xe)
1612         return "fine-granularity-scalable";
1613       break;
1614   }
1615 
1616   return NULL;
1617 }
1618 
1619 /**
1620  * gst_codec_utils_mpeg4video_get_level:
1621  * @vis_obj_seq: (array length=len): Pointer to the visual object
1622  *   sequence for the stream.
1623  * @len: Length of the data available in @sps.
1624  *
1625  * Converts the level indication in the stream's visual object sequence into
1626  * a string. @vis_obj_seq is expected to be the data following the visual
1627  * object sequence start code. Only the first byte
1628  * (profile_and_level_indication) is used.
1629  *
1630  * Returns: (nullable): The level as a const string, or NULL if there is an error.
1631  */
1632 const gchar *
gst_codec_utils_mpeg4video_get_level(const guint8 * vis_obj_seq,guint len)1633 gst_codec_utils_mpeg4video_get_level (const guint8 * vis_obj_seq, guint len)
1634 {
1635   /* The profile/level codes are from 14496-2, table G-1, the Wireshark
1636    * sources: epan/dissectors/packet-mp4ves.c and the Xvid Sources:
1637    * src/xvid.h.
1638    * Levels 4a and 5 for SP were added in Amendment 2, level 6 in Amendment 4
1639    * (see Xvid sources vfw/config.c)
1640    *
1641    * Each profile has a different maximum level it defines. Some of them still
1642    * need special case handling, because not all levels start from 1, and the
1643    * Simple profile defines an intermediate level as well. */
1644   static const int level_max[] = { 6, 2, 2, 4, 2, 1, 2, 2, 2, 4, 3, 4, 2, 3, 4,
1645     5
1646   };
1647   int profile_id, level_id;
1648 
1649   g_return_val_if_fail (vis_obj_seq != NULL, NULL);
1650 
1651   if (len < 1)
1652     return NULL;
1653 
1654   GST_MEMDUMP ("VOS", vis_obj_seq, len);
1655 
1656   profile_id = vis_obj_seq[0] >> 4;
1657   level_id = vis_obj_seq[0] & 0xf;
1658 
1659   GST_LOG ("profile_id = %d, level_id = %d", profile_id, level_id);
1660 
1661   if (profile_id != 0xf && level_id == 0)
1662     return NULL;
1663 
1664   /* Let's do some validation of the level */
1665   switch (profile_id) {
1666     case 0x3:
1667       if (level_id == 1)
1668         return NULL;
1669       break;
1670 
1671     case 0x4:
1672       if (level_id != 2)
1673         return NULL;
1674       break;
1675 
1676     case 0x6:
1677       if (level_id > 5)
1678         return NULL;
1679       break;
1680 
1681     case 0xe:
1682       if (level_id > 9)
1683         return NULL;
1684       break;
1685 
1686     case 0xf:
1687       if (level_id == 6 || level_id == 7 || level_id > 0xd)
1688         return NULL;
1689       break;
1690   }
1691 
1692   if (profile_id == 0 && level_id == 8)
1693     /* Simple Profile / Level 0 */
1694     return "0";
1695   else if (profile_id == 0 && level_id == 9)
1696     /* Simple Profile / Level 0b */
1697     return "0b";
1698   else if (profile_id == 0 && level_id == 4)
1699     /* Simple Profile / Level 4a */
1700     return "4a";
1701   else if (profile_id == 0xf && level_id > 7)
1702     /* Fine Granularity Scalable Profile */
1703     return digit_to_string (level_id - 8);
1704   else if (level_id <= level_max[profile_id])
1705     /* Levels for all other cases */
1706     return digit_to_string (level_id);
1707 
1708   return NULL;
1709 }
1710 
1711 /**
1712  * gst_codec_utils_mpeg4video_caps_set_level_and_profile:
1713  * @caps: the #GstCaps to which the level and profile are to be added
1714  * @vis_obj_seq: (array length=len): Pointer to the visual object
1715  *   sequence for the stream.
1716  * @len: Length of the data available in @sps.
1717  *
1718  * Sets the level and profile in @caps if it can be determined from
1719  * @vis_obj_seq. See gst_codec_utils_mpeg4video_get_level() and
1720  * gst_codec_utils_mpeg4video_get_profile() for more details on the
1721  * parameters.
1722  *
1723  * Returns: %TRUE if the level and profile could be set, %FALSE otherwise.
1724  */
1725 gboolean
gst_codec_utils_mpeg4video_caps_set_level_and_profile(GstCaps * caps,const guint8 * vis_obj_seq,guint len)1726 gst_codec_utils_mpeg4video_caps_set_level_and_profile (GstCaps * caps,
1727     const guint8 * vis_obj_seq, guint len)
1728 {
1729   const gchar *profile, *level;
1730 
1731   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
1732   g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE);
1733   g_return_val_if_fail (vis_obj_seq != NULL, FALSE);
1734 
1735   profile = gst_codec_utils_mpeg4video_get_profile (vis_obj_seq, len);
1736 
1737   if (profile != NULL)
1738     gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
1739 
1740   level = gst_codec_utils_mpeg4video_get_level (vis_obj_seq, len);
1741 
1742   if (level != NULL)
1743     gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
1744 
1745   GST_LOG ("profile : %s", (profile) ? profile : "---");
1746   GST_LOG ("level   : %s", (level) ? level : "---");
1747 
1748   return (profile != NULL && level != NULL);
1749 }
1750 
1751 /**
1752  * gst_codec_utils_opus_parse_caps:
1753  * @caps: the #GstCaps to parse the data from
1754  * @rate: (optional) (out): the sample rate
1755  * @channels: (optional) (out): the number of channels
1756  * @channel_mapping_family: (optional) (out): the channel mapping family
1757  * @stream_count: (optional) (out): the number of independent streams
1758  * @coupled_count: (optional) (out): the number of stereo streams
1759  * @channel_mapping: (optional) (out) (array fixed-size=256): the mapping between the streams
1760  *
1761  * Parses Opus caps and fills the different fields with defaults if possible.
1762  *
1763  * Returns: %TRUE if parsing was successful, %FALSE otherwise.
1764  *
1765  * Since: 1.8
1766  */
1767 gboolean
gst_codec_utils_opus_parse_caps(GstCaps * caps,guint32 * rate,guint8 * channels,guint8 * channel_mapping_family,guint8 * stream_count,guint8 * coupled_count,guint8 channel_mapping[256])1768 gst_codec_utils_opus_parse_caps (GstCaps * caps,
1769     guint32 * rate,
1770     guint8 * channels,
1771     guint8 * channel_mapping_family,
1772     guint8 * stream_count, guint8 * coupled_count, guint8 channel_mapping[256])
1773 {
1774   GstStructure *s;
1775   gint c, f, sc, cc;
1776   const GValue *va, *v;
1777 
1778   g_return_val_if_fail (caps != NULL, FALSE);
1779   g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
1780   g_return_val_if_fail (!gst_caps_is_empty (caps), FALSE);
1781 
1782   s = gst_caps_get_structure (caps, 0);
1783 
1784   g_return_val_if_fail (gst_structure_has_name (s, "audio/x-opus"), FALSE);
1785   g_return_val_if_fail (gst_structure_has_field_typed (s,
1786           "channel-mapping-family", G_TYPE_INT), FALSE);
1787 
1788   if (rate) {
1789     gint r;
1790 
1791     if (gst_structure_get_int (s, "rate", &r))
1792       *rate = r;
1793     else
1794       *rate = 48000;
1795   }
1796 
1797   gst_structure_get_int (s, "channel-mapping-family", &f);
1798   if (channel_mapping_family)
1799     *channel_mapping_family = f;
1800 
1801   if (!gst_structure_get_int (s, "channels", &c) || c == 0) {
1802     if (f == 0)
1803       c = 2;
1804     else
1805       return FALSE;
1806   }
1807 
1808   if (channels)
1809     *channels = c;
1810 
1811   /* RTP mapping */
1812   if (f == 0) {
1813     if (c > 2)
1814       return FALSE;
1815 
1816     if (stream_count)
1817       *stream_count = 1;
1818     if (coupled_count)
1819       *coupled_count = c == 2 ? 1 : 0;
1820 
1821     if (channel_mapping) {
1822       channel_mapping[0] = 0;
1823       channel_mapping[1] = 1;
1824     }
1825 
1826     return TRUE;
1827   }
1828 
1829   if (!gst_structure_get_int (s, "stream-count", &sc))
1830     return FALSE;
1831   if (stream_count)
1832     *stream_count = sc;
1833 
1834   if (!gst_structure_get_int (s, "coupled-count", &cc))
1835     return FALSE;
1836   if (coupled_count)
1837     *coupled_count = cc;
1838 
1839   va = gst_structure_get_value (s, "channel-mapping");
1840   if (!va || !G_VALUE_HOLDS (va, GST_TYPE_ARRAY))
1841     return FALSE;
1842 
1843   if (gst_value_array_get_size (va) != c)
1844     return FALSE;
1845 
1846   if (channel_mapping) {
1847     gint i;
1848 
1849     for (i = 0; i < c; i++) {
1850       gint cm;
1851 
1852       v = gst_value_array_get_value (va, i);
1853 
1854       if (!G_VALUE_HOLDS (v, G_TYPE_INT))
1855         return FALSE;
1856 
1857       cm = g_value_get_int (v);
1858       if (cm < 0 || cm > 255)
1859         return FALSE;
1860 
1861       channel_mapping[i] = cm;
1862     }
1863   }
1864 
1865   return TRUE;
1866 }
1867 
1868 /**
1869  * gst_codec_utils_opus_create_caps:
1870  * @rate: the sample rate
1871  * @channels: the number of channels
1872  * @channel_mapping_family: the channel mapping family
1873  * @stream_count: the number of independent streams
1874  * @coupled_count: the number of stereo streams
1875  * @channel_mapping: (nullable) (array): the mapping between the streams
1876  *
1877  * Creates Opus caps from the given parameters.
1878  *
1879  * Returns: The #GstCaps, or %NULL if the parameters would lead to
1880  * invalid Opus caps.
1881  *
1882  * Since: 1.8
1883  */
1884 GstCaps *
gst_codec_utils_opus_create_caps(guint32 rate,guint8 channels,guint8 channel_mapping_family,guint8 stream_count,guint8 coupled_count,const guint8 * channel_mapping)1885 gst_codec_utils_opus_create_caps (guint32 rate,
1886     guint8 channels,
1887     guint8 channel_mapping_family,
1888     guint8 stream_count, guint8 coupled_count, const guint8 * channel_mapping)
1889 {
1890   GstCaps *caps = NULL;
1891   GValue va = G_VALUE_INIT;
1892   GValue v = G_VALUE_INIT;
1893   gint i;
1894 
1895   if (rate == 0)
1896     rate = 48000;
1897 
1898   if (channel_mapping_family == 0) {
1899     if (channels > 2) {
1900       GST_ERROR ("Invalid channels count for channel_mapping_family 0: %d",
1901           channels);
1902       goto done;
1903     }
1904 
1905     if (stream_count > 1) {
1906       GST_ERROR ("Invalid stream count for channel_mapping_family 0: %d",
1907           stream_count);
1908       goto done;
1909     }
1910 
1911     if (coupled_count > 1) {
1912       GST_ERROR ("Invalid coupled count for channel_mapping_family 0: %d",
1913           coupled_count);
1914       goto done;
1915     }
1916 
1917     if (channels == 0)
1918       channels = 2;
1919 
1920     if (stream_count == 0)
1921       stream_count = 1;
1922 
1923     if (coupled_count == 0)
1924       coupled_count = channels == 2 ? 1 : 0;
1925 
1926     return gst_caps_new_simple ("audio/x-opus",
1927         "rate", G_TYPE_INT, rate,
1928         "channels", G_TYPE_INT, channels,
1929         "channel-mapping-family", G_TYPE_INT, channel_mapping_family,
1930         "stream-count", G_TYPE_INT, stream_count,
1931         "coupled-count", G_TYPE_INT, coupled_count, NULL);
1932   }
1933 
1934   if (channels == 0) {
1935     GST_ERROR ("Invalid channels count: %d", channels);
1936     goto done;
1937   }
1938 
1939   if (stream_count == 0) {
1940     GST_ERROR ("Invalid stream count: %d", stream_count);
1941     goto done;
1942   }
1943 
1944   if (coupled_count > stream_count) {
1945     GST_ERROR ("Coupled count %d > stream count: %d", coupled_count,
1946         stream_count);
1947     goto done;
1948   }
1949 
1950   if (channel_mapping == NULL) {
1951     GST_ERROR
1952         ("A non NULL channel-mapping is needed for channel_mapping_family != 0");
1953     goto done;
1954   }
1955 
1956   caps = gst_caps_new_simple ("audio/x-opus",
1957       "rate", G_TYPE_INT, rate,
1958       "channels", G_TYPE_INT, channels,
1959       "channel-mapping-family", G_TYPE_INT, channel_mapping_family,
1960       "stream-count", G_TYPE_INT, stream_count,
1961       "coupled-count", G_TYPE_INT, coupled_count, NULL);
1962 
1963   g_value_init (&va, GST_TYPE_ARRAY);
1964   g_value_init (&v, G_TYPE_INT);
1965   for (i = 0; i < channels; i++) {
1966     g_value_set_int (&v, channel_mapping[i]);
1967     gst_value_array_append_value (&va, &v);
1968   }
1969   gst_structure_set_value (gst_caps_get_structure (caps, 0), "channel-mapping",
1970       &va);
1971   g_value_unset (&va);
1972   g_value_unset (&v);
1973 
1974 done:
1975   return caps;
1976 }
1977 
1978 /*
1979  * (really really) FIXME: move into core (dixit tpm)
1980  */
1981 /*
1982  * _gst_caps_set_buffer_array:
1983  * @caps: (transfer full): a #GstCaps
1984  * @field: field in caps to set
1985  * @buf: header buffers
1986  *
1987  * Adds given buffers to an array of buffers set as the given @field
1988  * on the given @caps.  List of buffer arguments must be NULL-terminated.
1989  *
1990  * Returns: (transfer full): input caps with a streamheader field added, or NULL
1991  *     if some error occurred
1992  */
1993 static GstCaps *
_gst_caps_set_buffer_array(GstCaps * caps,const gchar * field,GstBuffer * buf,...)1994 _gst_caps_set_buffer_array (GstCaps * caps, const gchar * field,
1995     GstBuffer * buf, ...)
1996 {
1997   GstStructure *structure = NULL;
1998   va_list va;
1999   GValue array = { 0 };
2000   GValue value = { 0 };
2001 
2002   g_return_val_if_fail (caps != NULL, NULL);
2003   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
2004   g_return_val_if_fail (field != NULL, NULL);
2005 
2006   caps = gst_caps_make_writable (caps);
2007   structure = gst_caps_get_structure (caps, 0);
2008 
2009   g_value_init (&array, GST_TYPE_ARRAY);
2010 
2011   va_start (va, buf);
2012   /* put buffers in a fixed list */
2013   while (buf) {
2014     g_assert (gst_buffer_is_writable (buf));
2015 
2016     /* mark buffer */
2017     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
2018 
2019     g_value_init (&value, GST_TYPE_BUFFER);
2020     buf = gst_buffer_copy (buf);
2021     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
2022     gst_value_set_buffer (&value, buf);
2023     gst_buffer_unref (buf);
2024     gst_value_array_append_value (&array, &value);
2025     g_value_unset (&value);
2026 
2027     buf = va_arg (va, GstBuffer *);
2028   }
2029   va_end (va);
2030 
2031   gst_structure_set_value (structure, field, &array);
2032   g_value_unset (&array);
2033 
2034   return caps;
2035 }
2036 
2037 /**
2038  * gst_codec_utils_opus_create_caps_from_header:
2039  * @header: OpusHead header
2040  * @comments: (nullable): Comment header or NULL
2041  *
2042  * Creates Opus caps from the given OpusHead @header and comment header
2043  * @comments.
2044  *
2045  * Returns: The #GstCaps.
2046  *
2047  * Since: 1.8
2048  */
2049 GstCaps *
gst_codec_utils_opus_create_caps_from_header(GstBuffer * header,GstBuffer * comments)2050 gst_codec_utils_opus_create_caps_from_header (GstBuffer * header,
2051     GstBuffer * comments)
2052 {
2053   GstCaps *caps;
2054   guint32 rate;
2055   guint8 channels;
2056   guint8 channel_mapping_family;
2057   guint8 stream_count;
2058   guint8 coupled_count;
2059   guint8 channel_mapping[256];
2060   GstBuffer *dummy_comments = NULL;
2061 
2062   g_return_val_if_fail (GST_IS_BUFFER (header), NULL);
2063   g_return_val_if_fail (comments == NULL || GST_IS_BUFFER (comments), NULL);
2064 
2065   if (!gst_codec_utils_opus_parse_header (header, &rate, &channels,
2066           &channel_mapping_family, &stream_count, &coupled_count,
2067           channel_mapping, NULL, NULL))
2068     return NULL;
2069 
2070   if (!(caps =
2071           gst_codec_utils_opus_create_caps (rate, channels,
2072               channel_mapping_family, stream_count, coupled_count,
2073               channel_mapping)))
2074     return NULL;
2075 
2076   if (!comments) {
2077     GstTagList *tags = gst_tag_list_new_empty ();
2078     dummy_comments =
2079         gst_tag_list_to_vorbiscomment_buffer (tags, (const guint8 *) "OpusTags",
2080         8, NULL);
2081     gst_tag_list_unref (tags);
2082   }
2083   _gst_caps_set_buffer_array (caps, "streamheader", header,
2084       comments ? comments : dummy_comments, NULL);
2085 
2086   if (dummy_comments)
2087     gst_buffer_unref (dummy_comments);
2088 
2089   return caps;
2090 }
2091 
2092 /**
2093  * gst_codec_utils_opus_create_header:
2094  * @rate: the sample rate
2095  * @channels: the number of channels
2096  * @channel_mapping_family: the channel mapping family
2097  * @stream_count: the number of independent streams
2098  * @coupled_count: the number of stereo streams
2099  * @channel_mapping: (nullable) (array): the mapping between the streams
2100  * @pre_skip: Pre-skip in 48kHz samples or 0
2101  * @output_gain: Output gain or 0
2102  *
2103  * Creates OpusHead header from the given parameters.
2104  *
2105  * Returns: The #GstBuffer containing the OpusHead.
2106  *
2107  * Since: 1.8
2108  */
2109 GstBuffer *
gst_codec_utils_opus_create_header(guint32 rate,guint8 channels,guint8 channel_mapping_family,guint8 stream_count,guint8 coupled_count,const guint8 * channel_mapping,guint16 pre_skip,gint16 output_gain)2110 gst_codec_utils_opus_create_header (guint32 rate,
2111     guint8 channels,
2112     guint8 channel_mapping_family,
2113     guint8 stream_count,
2114     guint8 coupled_count,
2115     const guint8 * channel_mapping, guint16 pre_skip, gint16 output_gain)
2116 {
2117   GstBuffer *buffer;
2118   GstByteWriter bw;
2119   gboolean hdl = TRUE;
2120 
2121   if (rate == 0)
2122     rate = 48000;
2123 
2124   if (channel_mapping_family == 0) {
2125     g_return_val_if_fail (channels <= 2, NULL);
2126     if (channels == 0)
2127       channels = 2;
2128 
2129     g_return_val_if_fail (stream_count == 0 || stream_count == 1, NULL);
2130     if (stream_count == 0)
2131       stream_count = 1;
2132 
2133     g_return_val_if_fail (coupled_count == 0 || coupled_count == 1, NULL);
2134     if (coupled_count == 0)
2135       coupled_count = channels == 2 ? 1 : 0;
2136 
2137     channel_mapping = NULL;
2138   } else {
2139     g_return_val_if_fail (channels > 0, NULL);
2140     g_return_val_if_fail (stream_count > 0, NULL);
2141     g_return_val_if_fail (coupled_count <= stream_count, NULL);
2142     g_return_val_if_fail (channel_mapping != NULL, NULL);
2143   }
2144 
2145   gst_byte_writer_init (&bw);
2146   /* See http://wiki.xiph.org/OggOpus */
2147   hdl &= gst_byte_writer_put_data (&bw, (const guint8 *) "OpusHead", 8);
2148   hdl &= gst_byte_writer_put_uint8 (&bw, 0x01); /* version number */
2149   hdl &= gst_byte_writer_put_uint8 (&bw, channels);
2150   hdl &= gst_byte_writer_put_uint16_le (&bw, pre_skip);
2151   hdl &= gst_byte_writer_put_uint32_le (&bw, rate);
2152   hdl &= gst_byte_writer_put_uint16_le (&bw, output_gain);
2153   hdl &= gst_byte_writer_put_uint8 (&bw, channel_mapping_family);
2154   if (channel_mapping_family > 0) {
2155     hdl &= gst_byte_writer_put_uint8 (&bw, stream_count);
2156     hdl &= gst_byte_writer_put_uint8 (&bw, coupled_count);
2157     hdl &= gst_byte_writer_put_data (&bw, channel_mapping, channels);
2158   }
2159 
2160   if (!hdl) {
2161     GST_WARNING ("Error creating header");
2162     gst_byte_writer_reset (&bw);
2163     return NULL;
2164   }
2165 
2166   buffer = gst_byte_writer_reset_and_get_buffer (&bw);
2167   GST_BUFFER_OFFSET (buffer) = 0;
2168   GST_BUFFER_OFFSET_END (buffer) = 0;
2169 
2170   return buffer;
2171 }
2172 
2173 /**
2174  * gst_codec_utils_opus_parse_header:
2175  * @header: the OpusHead #GstBuffer
2176  * @rate: (optional) (out): the sample rate
2177  * @channels: (optional) (out): the number of channels
2178  * @channel_mapping_family: (optional) (out): the channel mapping family
2179  * @stream_count: (optional) (out): the number of independent streams
2180  * @coupled_count: (optional) (out): the number of stereo streams
2181  * @channel_mapping: (optional) (out) (array fixed-size=256): the mapping between the streams
2182  * @pre_skip: (optional) (out): Pre-skip in 48kHz samples or 0
2183  * @output_gain: (optional) (out): Output gain or 0
2184  *
2185  * Parses the OpusHead header.
2186  *
2187  * Returns: %TRUE if parsing was successful, %FALSE otherwise.
2188  *
2189  * Since: 1.8
2190  */
2191 gboolean
gst_codec_utils_opus_parse_header(GstBuffer * header,guint32 * rate,guint8 * channels,guint8 * channel_mapping_family,guint8 * stream_count,guint8 * coupled_count,guint8 channel_mapping[256],guint16 * pre_skip,gint16 * output_gain)2192 gst_codec_utils_opus_parse_header (GstBuffer * header,
2193     guint32 * rate,
2194     guint8 * channels,
2195     guint8 * channel_mapping_family,
2196     guint8 * stream_count,
2197     guint8 * coupled_count,
2198     guint8 channel_mapping[256], guint16 * pre_skip, gint16 * output_gain)
2199 {
2200   GstByteReader br;
2201   GstMapInfo map;
2202   gboolean ret = TRUE;
2203   guint8 c, f, version;
2204 
2205   g_return_val_if_fail (GST_IS_BUFFER (header), FALSE);
2206   g_return_val_if_fail (gst_buffer_get_size (header) >= 19, FALSE);
2207 
2208   if (!gst_buffer_map (header, &map, GST_MAP_READ))
2209     return FALSE;
2210   gst_byte_reader_init (&br, map.data, map.size);
2211   /* See http://wiki.xiph.org/OggOpus */
2212   if (memcmp (gst_byte_reader_get_data_unchecked (&br, 8), "OpusHead", 8) != 0) {
2213     ret = FALSE;
2214     goto done;
2215   }
2216   version = gst_byte_reader_get_uint8_unchecked (&br);
2217   if (version == 0x00)
2218     GST_ERROR ("Opus Header version is wrong, should be 0x01 and not 0x00");
2219   else if (version != 0x01) {
2220     ret = FALSE;
2221     goto done;
2222   }
2223 
2224   c = gst_byte_reader_get_uint8_unchecked (&br);
2225   if (channels)
2226     *channels = c;
2227 
2228   if (pre_skip)
2229     *pre_skip = gst_byte_reader_get_uint16_le_unchecked (&br);
2230   else
2231     gst_byte_reader_skip_unchecked (&br, 2);
2232 
2233   if (rate)
2234     *rate = gst_byte_reader_get_uint32_le_unchecked (&br);
2235   else
2236     gst_byte_reader_skip_unchecked (&br, 4);
2237 
2238   if (output_gain)
2239     *output_gain = gst_byte_reader_get_uint16_le_unchecked (&br);
2240   else
2241     gst_byte_reader_skip_unchecked (&br, 2);
2242 
2243   f = gst_byte_reader_get_uint8_unchecked (&br);
2244   if (channel_mapping_family)
2245     *channel_mapping_family = f;
2246   if (f == 0 && c <= 2) {
2247     if (stream_count)
2248       *stream_count = 1;
2249     if (coupled_count)
2250       *coupled_count = c == 2 ? 1 : 0;
2251     if (channel_mapping) {
2252       channel_mapping[0] = 0;
2253       channel_mapping[1] = 1;
2254     }
2255 
2256     goto done;
2257   }
2258 
2259   if (gst_byte_reader_get_remaining (&br) < 2 + c) {
2260     ret = FALSE;
2261     goto done;
2262   }
2263 
2264   if (stream_count)
2265     *stream_count = gst_byte_reader_get_uint8_unchecked (&br);
2266   else
2267     gst_byte_reader_skip_unchecked (&br, 1);
2268 
2269   if (coupled_count)
2270     *coupled_count = gst_byte_reader_get_uint8_unchecked (&br);
2271   else
2272     gst_byte_reader_skip_unchecked (&br, 1);
2273 
2274   if (channel_mapping)
2275     memcpy (channel_mapping, gst_byte_reader_get_data_unchecked (&br, c), c);
2276 
2277 done:
2278   gst_buffer_unmap (header, &map);
2279 
2280   return ret;
2281 }
2282 
2283 static gboolean
h264_caps_structure_get_profile_flags_level(GstStructure * caps_st,guint8 * profile,guint8 * flags,guint8 * level)2284 h264_caps_structure_get_profile_flags_level (GstStructure * caps_st,
2285     guint8 * profile, guint8 * flags, guint8 * level)
2286 {
2287   const GValue *codec_data_value = NULL;
2288   GstBuffer *codec_data = NULL;
2289   GstMapInfo map;
2290   gboolean ret = FALSE;
2291   guint8 *data = NULL;
2292   gsize size;
2293 
2294   codec_data_value = gst_structure_get_value (caps_st, "codec_data");
2295   if (!codec_data_value) {
2296     GST_DEBUG
2297         ("video/x-h264 caps did not have codec_data set, cannot parse profile, flags and level");
2298     return FALSE;
2299   }
2300 
2301   codec_data = gst_value_get_buffer (codec_data_value);
2302   if (!gst_buffer_map (codec_data, &map, GST_MAP_READ)) {
2303     return FALSE;
2304   }
2305   data = map.data;
2306   size = map.size;
2307 
2308   if (!gst_codec_utils_h264_get_profile_flags_level (data, (guint) size,
2309           profile, flags, level)) {
2310     GST_WARNING
2311         ("Failed to parse profile, flags and level from h264 codec data");
2312     goto done;
2313   }
2314 
2315   ret = TRUE;
2316 
2317 done:
2318   gst_buffer_unmap (codec_data, &map);
2319 
2320   return ret;
2321 }
2322 
2323 static gboolean
aac_caps_structure_get_audio_object_type(GstStructure * caps_st,guint8 * audio_object_type)2324 aac_caps_structure_get_audio_object_type (GstStructure * caps_st,
2325     guint8 * audio_object_type)
2326 {
2327   gboolean ret = FALSE;
2328   const GValue *codec_data_value = NULL;
2329   GstBuffer *codec_data = NULL;
2330   GstMapInfo map;
2331   guint8 *data = NULL;
2332   gsize size;
2333   GstBitReader br;
2334 
2335   codec_data_value = gst_structure_get_value (caps_st, "codec_data");
2336   if (!codec_data_value) {
2337     GST_DEBUG
2338         ("audio/mpeg pad did not have codec_data set, cannot parse audio object type");
2339     return FALSE;
2340   }
2341 
2342   codec_data = gst_value_get_buffer (codec_data_value);
2343   if (!gst_buffer_map (codec_data, &map, GST_MAP_READ)) {
2344     return FALSE;
2345   }
2346   data = map.data;
2347   size = map.size;
2348 
2349   if (size < 2) {
2350     GST_WARNING ("aac codec data is too small");
2351     goto done;
2352   }
2353 
2354   gst_bit_reader_init (&br, data, size);
2355   ret = gst_codec_utils_aac_get_audio_object_type (&br, audio_object_type);
2356 
2357 done:
2358   gst_buffer_unmap (codec_data, &map);
2359 
2360   return ret;
2361 }
2362 
2363 static gboolean
hevc_caps_get_mime_codec(GstCaps * caps,gchar ** mime_codec)2364 hevc_caps_get_mime_codec (GstCaps * caps, gchar ** mime_codec)
2365 {
2366   GstStructure *caps_st = NULL;
2367   const GValue *codec_data_value = NULL;
2368   GstBuffer *codec_data = NULL;
2369   GstMapInfo map;
2370   gboolean ret = FALSE;
2371   const gchar *stream_format;
2372   guint8 *data = NULL;
2373   gsize size;
2374   guint16 profile_space;
2375   guint8 tier_flag;
2376   guint16 profile_idc;
2377   guint32 compat_flags;
2378   guchar constraint_indicator_flags[6];
2379   guint8 level_idc;
2380   guint32 compat_flag_parameter = 0;
2381   GString *codec_string;
2382   const guint8 *profile_tier_level;
2383   gint last_flag_index;
2384 
2385   caps_st = gst_caps_get_structure (caps, 0);
2386   codec_data_value = gst_structure_get_value (caps_st, "codec_data");
2387   stream_format = gst_structure_get_string (caps_st, "stream-format");
2388   if (!codec_data_value) {
2389     GST_DEBUG ("video/x-h265 caps did not have codec_data set, cannot parse");
2390     return FALSE;
2391   } else if (!stream_format) {
2392     GST_DEBUG
2393         ("video/x-h265 caps did not have stream-format set, cannot parse");
2394     return FALSE;
2395   }
2396 
2397   codec_data = gst_value_get_buffer (codec_data_value);
2398   if (!gst_buffer_map (codec_data, &map, GST_MAP_READ)) {
2399     return FALSE;
2400   }
2401   data = map.data;
2402   size = map.size;
2403 
2404   /* HEVCDecoderConfigurationRecord is at a minimum 23 bytes long */
2405   if (size < 23) {
2406     GST_DEBUG ("Incomplete HEVCDecoderConfigurationRecord");
2407     goto done;
2408   }
2409 
2410   if (!g_str_equal (stream_format, "hev1")
2411       && !g_str_equal (stream_format, "hvc1")) {
2412     GST_DEBUG ("Unknown stream-format %s", stream_format);
2413     goto done;
2414   }
2415 
2416   profile_tier_level = data + 1;
2417   profile_space = (profile_tier_level[0] & 0x11) >> 6;
2418   tier_flag = (profile_tier_level[0] & 0x001) >> 5;
2419   profile_idc = (profile_tier_level[0] & 0x1f);
2420 
2421   compat_flags = GST_READ_UINT32_BE (data + 2);
2422   for (unsigned i = 0; i < 6; ++i)
2423     constraint_indicator_flags[i] = GST_READ_UINT8 (data + 6 + i);
2424 
2425   level_idc = data[12];
2426 
2427   /* The 32 bits of the compat_flags, but in reverse bit order */
2428   compat_flags =
2429       ((compat_flags & 0xaaaaaaaa) >> 1) | ((compat_flags & 0x55555555) << 1);
2430   compat_flags =
2431       ((compat_flags & 0xcccccccc) >> 2) | ((compat_flags & 0x33333333) << 2);
2432   compat_flags =
2433       ((compat_flags & 0xf0f0f0f0) >> 4) | ((compat_flags & 0x0f0f0f0f) << 4);
2434   compat_flags =
2435       ((compat_flags & 0xff00ff00) >> 8) | ((compat_flags & 0x00ff00ff) << 8);
2436   compat_flag_parameter = (compat_flags >> 16) | (compat_flags << 16);
2437 
2438   codec_string = g_string_new (stream_format);
2439   codec_string = g_string_append_c (codec_string, '.');
2440   if (profile_space)
2441     codec_string = g_string_append_c (codec_string, 'A' + profile_space - 1);
2442   g_string_append_printf (codec_string, "%" G_GUINT16_FORMAT ".%X.%c%d",
2443       profile_idc, compat_flag_parameter, tier_flag ? 'H' : 'L', level_idc);
2444 
2445   /* Each of the 6 bytes of the constraint flags, starting from the byte containing the
2446    * progressive_source_flag, each encoded as a hexadecimal number, and the encoding
2447    * of each byte separated by a period; trailing bytes that are zero may be omitted.
2448    */
2449   last_flag_index = 5;
2450   while (last_flag_index >= 0
2451       && (int) (constraint_indicator_flags[last_flag_index]) == 0)
2452     --last_flag_index;
2453   for (gint i = 0; i <= last_flag_index; ++i) {
2454     g_string_append_printf (codec_string, ".%02X",
2455         constraint_indicator_flags[i]);
2456   }
2457 
2458   *mime_codec = g_string_free (codec_string, FALSE);
2459 
2460   ret = TRUE;
2461 
2462 done:
2463   gst_buffer_unmap (codec_data, &map);
2464   return ret;
2465 }
2466 
2467 /**
2468  * gst_codec_utils_caps_get_mime_codec:
2469  * @caps: A #GstCaps to convert to mime codec
2470  *
2471  * Converts @caps to a RFC 6381 compatible codec string if possible.
2472  *
2473  * Useful for providing the 'codecs' field inside the 'Content-Type' HTTP
2474  * header for containerized formats, such as mp4 or matroska.
2475  *
2476  * Registered codecs can be found at http://mp4ra.org/#/codecs
2477  *
2478  * Returns: (transfer full) (nullable): a RFC 6381 compatible codec string or %NULL
2479  *
2480  * Since: 1.20
2481  */
2482 gchar *
gst_codec_utils_caps_get_mime_codec(GstCaps * caps)2483 gst_codec_utils_caps_get_mime_codec (GstCaps * caps)
2484 {
2485   gchar *mime_codec = NULL;
2486   GstStructure *caps_st = NULL;
2487   const gchar *media_type = NULL;
2488 
2489   g_return_val_if_fail (caps != NULL, NULL);
2490   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
2491 
2492   caps_st = gst_caps_get_structure (caps, 0);
2493   if (caps_st == NULL) {
2494     GST_WARNING ("Failed to get structure from caps");
2495     goto done;
2496   }
2497 
2498   media_type = gst_structure_get_name (caps_st);
2499 
2500   if (g_strcmp0 (media_type, "video/x-h264") == 0) {
2501     /* avc1.AABBCC
2502      *   AA = profile
2503      *   BB = constraint set flags
2504      *   CC = level
2505      */
2506     guint8 profile = 0;
2507     guint8 flags = 0;
2508     guint8 level = 0;
2509 
2510     if (!h264_caps_structure_get_profile_flags_level (caps_st, &profile, &flags,
2511             &level)) {
2512       GST_DEBUG
2513           ("h264 caps did not contain 'codec_data', cannot determine detailed codecs info");
2514       mime_codec = g_strdup ("avc1");
2515     } else {
2516       mime_codec = g_strdup_printf ("avc1.%02X%02X%02X", profile, flags, level);
2517     }
2518   } else if (g_strcmp0 (media_type, "video/x-h265") == 0) {
2519     if (!hevc_caps_get_mime_codec (caps, &mime_codec)) {
2520       GST_DEBUG ("h265 caps parsing failed");
2521       mime_codec = g_strdup ("hev1");
2522     }
2523   } else if (g_strcmp0 (media_type, "video/x-av1") == 0) {
2524     /* TODO: Some browsers won't play the video unless more codec information is
2525      * available in the mime codec for av1. This is documented in
2526      * https://aomediacodec.github.io/av1-isobmff/#codecsparam */
2527     mime_codec = g_strdup ("av01");
2528   } else if (g_strcmp0 (media_type, "video/x-vp8") == 0) {
2529     /* TODO: most browsers won't play the video unless more codec information is
2530      * available in the mime codec for vp8. */
2531     mime_codec = g_strdup ("vp08");
2532   } else if (g_strcmp0 (media_type, "video/x-vp9") == 0) {
2533     /* TODO: most browsers won't play the video unless more codec information is
2534      * available in the mime codec for vp9. This is documented in
2535      * https://www.webmproject.org/vp9/mp4/ */
2536     mime_codec = g_strdup ("vp09");
2537   } else if (g_strcmp0 (media_type, "image/jpeg") == 0) {
2538     mime_codec = g_strdup ("mjpg");
2539   } else if (g_strcmp0 (media_type, "audio/mpeg") == 0) {
2540     guint8 audio_object_type = 0;
2541     if (aac_caps_structure_get_audio_object_type (caps_st, &audio_object_type)) {
2542       mime_codec = g_strdup_printf ("mp4a.40.%u", audio_object_type);
2543     } else {
2544       mime_codec = g_strdup ("mp4a.40");
2545     }
2546   } else if (g_strcmp0 (media_type, "audio/x-opus") == 0) {
2547     mime_codec = g_strdup ("opus");
2548   } else if (g_strcmp0 (media_type, "audio/x-mulaw") == 0) {
2549     mime_codec = g_strdup ("ulaw");
2550   } else if (g_strcmp0 (media_type, "audio/x-adpcm") == 0) {
2551     if (g_strcmp0 (gst_structure_get_string (caps_st, "layout"), "g726") == 0) {
2552       mime_codec = g_strdup ("g726");
2553     }
2554   }
2555 
2556 done:
2557   return mime_codec;
2558 }
2559