#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
}
/**
+ * 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
* Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see
}
/**
- * 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);
+
+ 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);
}
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) {
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);
}
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;
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) {