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