mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 03:00:35 +00:00
pbutils: add AAC profile detection to codec utils
This moves AAC profile detection to pbutils, and uses this in typefindfunctions. This will also be used in qtdemux. https://bugzilla.gnome.org/show_bug.cgi?id=617314 API: gst_codec_utils_aac_get_profile() API: codec_utils_aac_caps_set_level_and_profile()
This commit is contained in:
parent
c77f88cac6
commit
0cf81938a1
4 changed files with 97 additions and 26 deletions
|
@ -34,6 +34,12 @@
|
|||
|
||||
#include "pbutils.h"
|
||||
|
||||
#define GST_SIMPLE_CAPS_HAS_NAME(caps,name) \
|
||||
gst_structure_has_name(gst_caps_get_structure((caps),0),(name))
|
||||
|
||||
#define GST_SIMPLE_CAPS_HAS_FIELD(caps,field) \
|
||||
gst_structure_has_field(gst_caps_get_structure((caps),0),(field))
|
||||
|
||||
/**
|
||||
* gst_codec_utils_aac_get_sample_rate_from_index:
|
||||
* @sr_idx: Sample rate index as from the AudioSpecificConfig (MPEG-4
|
||||
|
@ -58,6 +64,50 @@ gst_codec_utils_aac_get_sample_rate_from_index (guint sr_idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_codec_utils_aac_get_profile:
|
||||
* @audio_config: a pointer to the AudioSpecificConfig as specified in the
|
||||
* Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see
|
||||
* below for a more details).
|
||||
* @len: Length of @audio_config in bytes
|
||||
*
|
||||
* Returns the profile of the given AAC stream as a string. The profile is
|
||||
* determined using the AudioObjectType field which is in the first 5 bits of
|
||||
* @audio_config.
|
||||
*
|
||||
* <note>
|
||||
* HE-AAC support has not yet been implemented.
|
||||
* </note>
|
||||
*
|
||||
* Returns: The profile as a const string and NULL if the profile could not be
|
||||
* determined.
|
||||
*/
|
||||
const gchar *
|
||||
gst_codec_utils_aac_get_profile (const guint8 * audio_config, guint len)
|
||||
{
|
||||
guint profile;
|
||||
|
||||
if (len < 1)
|
||||
return NULL;
|
||||
|
||||
profile = audio_config[0] >> 3;
|
||||
switch (profile) {
|
||||
case 1:
|
||||
return "main";
|
||||
case 2:
|
||||
return "lc";
|
||||
case 3:
|
||||
return "ssr";
|
||||
case 4:
|
||||
return "ltp";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GST_DEBUG ("Invalid profile idx: %u", profile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_codec_utils_aac_get_level:
|
||||
* @audio_config: a pointer to the AudioSpecificConfig as specified in the
|
||||
|
@ -246,33 +296,55 @@ gst_codec_utils_aac_get_level (const guint8 * audio_config, guint len)
|
|||
}
|
||||
|
||||
/**
|
||||
* gst_codec_utils_aac_caps_set_level:
|
||||
* @caps: the #GstCaps to which the level is to be added
|
||||
* gst_codec_utils_aac_caps_set_level_and_profile:
|
||||
* @caps: the #GstCaps to which level and profile fields are to be added
|
||||
* @audio_config: a pointer to the AudioSpecificConfig as specified in the
|
||||
* Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see
|
||||
* below for a more details).
|
||||
* @len: Length of @audio_config in bytes
|
||||
*
|
||||
* Sets the level in @caps if it can be determined from @audio_config. See
|
||||
* #gst_codec_utils_aac_get_level() for more details on the parameters.
|
||||
* Sets the level and profile on @caps if it can be determined from
|
||||
* @audio_config. See #gst_codec_utils_aac_get_level() and
|
||||
* gst_codec_utils_aac_get_profile() for more details on the parameters.
|
||||
* @caps must be audio/mpeg caps with an "mpegversion" field of either 2 or 4.
|
||||
* If mpegversion is 4, the <tt>base-profile</tt> field is also set in @caps.
|
||||
*
|
||||
* Returns: TRUE if the level could be set, FALSE otherwise.
|
||||
* Returns: TRUE if the level and profile could be set, FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
gst_codec_utils_aac_caps_set_level (GstCaps * caps,
|
||||
gst_codec_utils_aac_caps_set_level_and_profile (GstCaps * caps,
|
||||
const guint8 * audio_config, guint len)
|
||||
{
|
||||
const gchar *level;
|
||||
GstStructure *s;
|
||||
const gchar *level, *profile;
|
||||
int mpegversion = 0;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
|
||||
g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE);
|
||||
g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_NAME (caps, "audio/mpeg"), FALSE);
|
||||
g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_FIELD (caps, "mpegversion"), FALSE);
|
||||
g_return_val_if_fail (audio_config != NULL, FALSE);
|
||||
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
|
||||
gst_structure_get_int (s, "mpegversion", &mpegversion);
|
||||
g_return_val_if_fail (mpegversion == 2 || mpegversion == 4, FALSE);
|
||||
|
||||
level = gst_codec_utils_aac_get_level (audio_config, len);
|
||||
|
||||
if (!level)
|
||||
return FALSE;
|
||||
if (level != NULL)
|
||||
gst_structure_set (s, "level", G_TYPE_STRING, level, NULL);
|
||||
|
||||
gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
|
||||
profile = gst_codec_utils_aac_get_profile (audio_config, len);
|
||||
|
||||
return TRUE;
|
||||
if (profile != NULL) {
|
||||
if (mpegversion == 4) {
|
||||
gst_structure_set (s, "base-profile", G_TYPE_STRING, profile,
|
||||
"profile", G_TYPE_STRING, profile, NULL);
|
||||
} else {
|
||||
gst_structure_set (s, "profile", G_TYPE_STRING, profile, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (level != NULL && profile != NULL);
|
||||
}
|
||||
|
|
|
@ -30,12 +30,13 @@ G_BEGIN_DECLS
|
|||
|
||||
guint gst_codec_utils_aac_get_sample_rate_from_index (guint sr_idx);
|
||||
|
||||
const gchar * gst_codec_utils_aac_get_level (const guint8 * audio_config,
|
||||
guint len);
|
||||
const gchar * gst_codec_utils_aac_get_profile (const guint8 * audio_config, guint len);
|
||||
|
||||
gboolean gst_codec_utils_aac_caps_set_level (GstCaps * caps,
|
||||
const guint8 * audio_config,
|
||||
guint len);
|
||||
const gchar * gst_codec_utils_aac_get_level (const guint8 * audio_config, guint len);
|
||||
|
||||
gboolean gst_codec_utils_aac_caps_set_level_and_profile (GstCaps * caps,
|
||||
const guint8 * audio_config,
|
||||
guint len);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -660,7 +660,6 @@ static void
|
|||
aac_type_find (GstTypeFind * tf, gpointer unused)
|
||||
{
|
||||
/* LUT to convert the AudioObjectType from the ADTS header to a string */
|
||||
static const gchar profile_to_string[][5] = { "main", "lc", "ssr", "ltp" };
|
||||
DataScanCtx c = { 0, NULL, 0 };
|
||||
|
||||
while (c.offset < AAC_AMOUNT) {
|
||||
|
@ -693,11 +692,11 @@ aac_type_find (GstTypeFind * tf, gpointer unused)
|
|||
snc = GST_READ_UINT16_BE (c.data + len);
|
||||
if ((snc & 0xfff6) == 0xfff0) {
|
||||
GstCaps *caps;
|
||||
guint mpegversion, sample_freq_idx, channel_config, profile, rate;
|
||||
guint mpegversion, sample_freq_idx, channel_config, profile_idx, rate;
|
||||
guint8 audio_config[2];
|
||||
|
||||
mpegversion = (c.data[1] & 0x08) ? 2 : 4;
|
||||
profile = c.data[2] >> 6;
|
||||
profile_idx = c.data[2] >> 6;
|
||||
sample_freq_idx = ((c.data[2] & 0x3c) >> 2);
|
||||
channel_config = ((c.data[2] & 0x01) << 2) + (c.data[3] >> 6);
|
||||
|
||||
|
@ -713,13 +712,13 @@ aac_type_find (GstTypeFind * tf, gpointer unused)
|
|||
}
|
||||
|
||||
rate = gst_codec_utils_aac_get_sample_rate_from_index (sample_freq_idx);
|
||||
GST_LOG ("ADTS: profile=%u, rate=%u", profile, rate);
|
||||
GST_LOG ("ADTS: profile=%u, rate=%u", profile_idx, rate);
|
||||
|
||||
/* The ADTS frame header is slightly different from the
|
||||
* AudioSpecificConfig defined for the MPEG-4 container, so we just
|
||||
* construct enough of it for getting the level here. */
|
||||
/* ADTS counts profiles from 0 instead of 1 to save bits */
|
||||
audio_config[0] = (profile + 1) << 3;
|
||||
audio_config[0] = (profile_idx + 1) << 3;
|
||||
audio_config[0] |= (sample_freq_idx >> 1) & 0x7;
|
||||
audio_config[1] = (sample_freq_idx & 0x1) << 7;
|
||||
audio_config[1] |= (channel_config & 0xf) << 3;
|
||||
|
@ -727,11 +726,9 @@ aac_type_find (GstTypeFind * tf, gpointer unused)
|
|||
caps = gst_caps_new_simple ("audio/mpeg",
|
||||
"framed", G_TYPE_BOOLEAN, FALSE,
|
||||
"mpegversion", G_TYPE_INT, mpegversion,
|
||||
"stream-type", G_TYPE_STRING, "adts",
|
||||
"base-profile", G_TYPE_STRING, profile_to_string[profile],
|
||||
"profile", G_TYPE_STRING, profile_to_string[profile], NULL);
|
||||
"stream-type", G_TYPE_STRING, "adts", NULL);
|
||||
|
||||
gst_codec_utils_aac_caps_set_level (caps, audio_config, 2);
|
||||
gst_codec_utils_aac_caps_set_level_and_profile (caps, audio_config, 2);
|
||||
|
||||
/* add rate and number of channels if we can */
|
||||
if (channel_config != 0 && channel_config <= 7) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
EXPORTS
|
||||
gst_codec_utils_aac_caps_set_level
|
||||
gst_codec_utils_aac_caps_set_level_and_profile
|
||||
gst_codec_utils_aac_get_level
|
||||
gst_codec_utils_aac_get_profile
|
||||
gst_codec_utils_aac_get_sample_rate_from_index
|
||||
gst_discoverer_audio_info_get_bitrate
|
||||
gst_discoverer_audio_info_get_channels
|
||||
|
|
Loading…
Reference in a new issue