diff --git a/gst-libs/gst/pbutils/codec-utils.c b/gst-libs/gst/pbutils/codec-utils.c
index 18d91b6889..412ca6595b 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
@@ -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.
+ *
+ *
+ * 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
@@ -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);
- 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);
}
diff --git a/gst-libs/gst/pbutils/codec-utils.h b/gst-libs/gst/pbutils/codec-utils.h
index 0b54da28cc..2a83348bb8 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 d9a011ee3e..81d21d06f6 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 87ce1279fc..81123d2555 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