From 0cf81938a160a9c16dc4903766dbea76f166ffe5 Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Fri, 30 Apr 2010 15:12:04 +0530 Subject: [PATCH] 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() --- gst-libs/gst/pbutils/codec-utils.c | 94 ++++++++++++++++++++++++++++++++----- gst-libs/gst/pbutils/codec-utils.h | 11 +++-- gst/typefind/gsttypefindfunctions.c | 15 +++--- win32/common/libgstpbutils.def | 3 +- 4 files changed, 97 insertions(+), 26 deletions(-) diff --git a/gst-libs/gst/pbutils/codec-utils.c b/gst-libs/gst/pbutils/codec-utils.c index 18d91b6..412ca65 100644 --- a/gst-libs/gst/pbutils/codec-utils.c +++ b/gst-libs/gst/pbutils/codec-utils.c @@ -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 @@ -59,6 +65,50 @@ gst_codec_utils_aac_get_sample_rate_from_index (guint sr_idx) } /** + * 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. + * + * + * HE-AAC support has not yet been implemented. + * + * + * 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 * Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see @@ -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 base-profile 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); + + 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 TRUE; + return (level != NULL && profile != NULL); } diff --git a/gst-libs/gst/pbutils/codec-utils.h b/gst-libs/gst/pbutils/codec-utils.h index 0b54da2..2a83348 100644 --- a/gst-libs/gst/pbutils/codec-utils.h +++ b/gst-libs/gst/pbutils/codec-utils.h @@ -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 diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index d9a011e..81d21d0 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -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) { diff --git a/win32/common/libgstpbutils.def b/win32/common/libgstpbutils.def index 87ce127..81123d2 100644 --- a/win32/common/libgstpbutils.def +++ b/win32/common/libgstpbutils.def @@ -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 -- 2.7.4