mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
pbutils: add codec-specific utility functions for AAC
This allows us to add generic codec-specific functionality, like extracting profile/level data from headers, without having to duplicate code across demuxers and typefindfunctions. As a starting point, this moves over AAC level extraction code from typefindfunctions, so it can be reused in qtdemux, etc. https://bugzilla.gnome.org/show_bug.cgi?id=617314 API: gst_codec_utils_aac_get_sample_rate_from_index() API: gst_codec_utils_aac_get_level()
This commit is contained in:
parent
78b2ab608b
commit
c77f88cac6
8 changed files with 320 additions and 215 deletions
|
@ -2,6 +2,7 @@ lib_LTLIBRARIES = libgstpbutils-@GST_MAJORMINOR@.la
|
|||
|
||||
headers_pbutils = \
|
||||
pbutils.h \
|
||||
codec-utils.h \
|
||||
descriptions.h \
|
||||
install-plugins.h \
|
||||
missing-plugins.h \
|
||||
|
@ -27,6 +28,7 @@ built_headers_configure = \
|
|||
libgstpbutils_@GST_MAJORMINOR@_la_SOURCES = \
|
||||
gstpluginsbaseversion.c \
|
||||
pbutils.c \
|
||||
codec-utils.c \
|
||||
descriptions.c \
|
||||
install-plugins.c \
|
||||
missing-plugins.c \
|
||||
|
|
278
gst-libs/gst/pbutils/codec-utils.c
Normal file
278
gst-libs/gst/pbutils/codec-utils.c
Normal file
|
@ -0,0 +1,278 @@
|
|||
/* GStreamer base utils library codec-specific utility functions
|
||||
* Copyright (C) 2010 Arun Raghavan <arun.raghavan@collabora.co.uk>
|
||||
* 2010 Collabora Multimedia
|
||||
* 2010 Nokia Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gstpbutilscodecutils
|
||||
* @short_description: Miscellaneous codec-specific utility functions
|
||||
*
|
||||
* <refsect2>
|
||||
* <para>
|
||||
* Provides numerous codec-specific ulility functions such as functions to
|
||||
* provide the codec profile and level in human-readable string form from
|
||||
* header data.
|
||||
* </para>
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
#include "pbutils.h"
|
||||
|
||||
/**
|
||||
* gst_codec_utils_aac_get_sample_rate_from_index:
|
||||
* @sr_idx: Sample rate index as from the AudioSpecificConfig (MPEG-4
|
||||
* container) or ADTS frame header
|
||||
*
|
||||
* Translates the sample rate index found in AAC headers to the actual sample
|
||||
* rate.
|
||||
*
|
||||
* Returns: The sample rate if @sr_idx is valid, 0 otherwise.
|
||||
*/
|
||||
guint
|
||||
gst_codec_utils_aac_get_sample_rate_from_index (guint sr_idx)
|
||||
{
|
||||
static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
|
||||
32000, 24000, 22050, 16000, 12000, 11025, 8000
|
||||
};
|
||||
|
||||
if (G_LIKELY (sr_idx < G_N_ELEMENTS (aac_sample_rates)))
|
||||
return aac_sample_rates[sr_idx];
|
||||
|
||||
GST_WARNING ("Invalid sample rate index %u", sr_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* below for a more detailed description).
|
||||
* @len: Length of @audio_config in bytes
|
||||
*
|
||||
* Determines the level of a stream as defined in ISO/IEC 14496-3. For AAC LC
|
||||
* streams, the constraints from the AAC audio profile are applied. For AAC
|
||||
* Main, LTP, SSR and others, the Main profile is used.
|
||||
*
|
||||
* The @audio_config parameter follows the following format, starting from the
|
||||
* most significant bit of the first byte:
|
||||
*
|
||||
* Bit 0:4 contains the AudioObjectType
|
||||
* Bit 5:8 contains the sample frequency index (if this is 0xf, then the next
|
||||
* 24 bits define the actual sample frequency, and subsequent fields
|
||||
* are appropriately shifted).
|
||||
* Bit 9:12 contains the channel configuration
|
||||
*
|
||||
* <note>
|
||||
* HE-AAC support has not yet been implemented.
|
||||
* </note>
|
||||
*
|
||||
* Returns: The level as a const string and NULL if the level could not be
|
||||
* determined.
|
||||
*/
|
||||
const gchar *
|
||||
gst_codec_utils_aac_get_level (const guint8 * audio_config, guint len)
|
||||
{
|
||||
int profile, sr_idx, channel_config, rate;
|
||||
/* Number of single channel elements, channel pair elements, low frequency
|
||||
* elements, independently switched coupling channel elements, and
|
||||
* dependently switched coupling channel elements.
|
||||
*
|
||||
* Note: The 2 CCE types are ignored for now as they require us to actually
|
||||
* parse the first frame, and they are rarely found in actual streams.
|
||||
*/
|
||||
int num_sce = 0, num_cpe = 0, num_lfe = 0, num_cce_indep = 0, num_cce_dep = 0;
|
||||
int num_channels;
|
||||
/* Processor and RAM Complexity Units (calculated and "reference" for single
|
||||
* channel) */
|
||||
int pcu, rcu, pcu_ref, rcu_ref;
|
||||
int ret = -1;
|
||||
|
||||
g_return_val_if_fail (audio_config != NULL, NULL);
|
||||
|
||||
if (len < 2)
|
||||
return NULL;
|
||||
|
||||
profile = audio_config[0] >> 3;
|
||||
/* FIXME: add support for sr_idx = 0xf */
|
||||
sr_idx = ((audio_config[0] & 0x7) << 1) | ((audio_config[1] & 0x80) >> 7);
|
||||
rate = gst_codec_utils_aac_get_sample_rate_from_index (sr_idx);
|
||||
channel_config = (audio_config[1] & 0x7f) >> 3;
|
||||
|
||||
if (rate == 0)
|
||||
return NULL;
|
||||
|
||||
switch (channel_config) {
|
||||
case 0:
|
||||
/* Channel config is defined in the AudioObjectType's SpecificConfig,
|
||||
* which requires some amount of digging through the headers. I only see
|
||||
* this done in the MPEG conformance streams - FIXME */
|
||||
GST_WARNING ("Found a stream with channel configuration in the "
|
||||
"AudioSpecificConfig. Please file a bug with a link to the media if "
|
||||
"possible.");
|
||||
return NULL;
|
||||
case 1:
|
||||
/* front center */
|
||||
num_sce = 1;
|
||||
break;
|
||||
case 2:
|
||||
/* front left and right */
|
||||
num_cpe = 1;
|
||||
break;
|
||||
case 3:
|
||||
/* front left, right, and center */
|
||||
num_sce = 1;
|
||||
num_cpe = 1;
|
||||
break;
|
||||
case 4:
|
||||
/* front left, right, and center; rear surround */
|
||||
num_sce = 2;
|
||||
num_cpe = 1;
|
||||
break;
|
||||
case 5:
|
||||
/* front left, right, and center; rear left and right surround */
|
||||
num_sce = 1;
|
||||
num_cpe = 2;
|
||||
break;
|
||||
case 6:
|
||||
/* front left, right, center and LFE; rear left and right surround */
|
||||
num_sce = 1;
|
||||
num_cpe = 2;
|
||||
break;
|
||||
case 7:
|
||||
/* front left, right, center and LFE; outside front left and right;
|
||||
* rear left and right surround */
|
||||
num_sce = 1;
|
||||
num_cpe = 3;
|
||||
num_lfe = 1;
|
||||
break;
|
||||
default:
|
||||
GST_WARNING ("Unknown channel config in header: %d", channel_config);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (profile) {
|
||||
case 0: /* NULL */
|
||||
GST_WARNING ("profile 0 is not a valid profile");
|
||||
return NULL;
|
||||
case 2: /* LC */
|
||||
pcu_ref = 3;
|
||||
rcu_ref = 3;
|
||||
break;
|
||||
case 3: /* SSR */
|
||||
pcu_ref = 4;
|
||||
rcu_ref = 3;
|
||||
break;
|
||||
case 4: /* LTP */
|
||||
pcu_ref = 4;
|
||||
rcu_ref = 4;
|
||||
break;
|
||||
case 1: /* Main */
|
||||
default:
|
||||
/* Other than a couple of ER profiles, Main is the worst-case */
|
||||
pcu_ref = 5;
|
||||
rcu_ref = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
/* "fs_ref" is 48000 Hz for AAC Main/LC/SSR/LTP. SBR's fs_ref is defined as
|
||||
* 24000/48000 (in/out), for SBR streams. Actual support is a FIXME */
|
||||
|
||||
pcu = ((float) rate / 48000) * pcu_ref *
|
||||
((2 * num_cpe) + num_sce + num_lfe + num_cce_indep + (0.3 * num_cce_dep));
|
||||
|
||||
rcu = ((float) rcu_ref) * (num_sce + (0.5 * num_lfe) + (0.5 * num_cce_indep) +
|
||||
(0.4 * num_cce_dep));
|
||||
|
||||
if (num_cpe < 2)
|
||||
rcu += (rcu_ref + (rcu_ref - 1)) * num_cpe;
|
||||
else
|
||||
rcu += (rcu_ref + (rcu_ref - 1) * ((2 * num_cpe) - 1));
|
||||
|
||||
num_channels = num_sce + (2 * num_cpe) + num_lfe;
|
||||
|
||||
if (profile == 2) {
|
||||
/* AAC LC => return the level as per the 'AAC Profile' */
|
||||
if (num_channels <= 2 && rate <= 24000 && pcu <= 3 && rcu <= 5)
|
||||
ret = 1;
|
||||
else if (num_channels <= 2 && rate <= 48000 && pcu <= 6 && rcu <= 5)
|
||||
ret = 2;
|
||||
/* There is no level 3 for the AAC Profile */
|
||||
else if (num_channels <= 5 && rate <= 48000 && pcu <= 19 && rcu <= 15)
|
||||
ret = 4;
|
||||
else if (num_channels <= 5 && rate <= 96000 && pcu <= 38 && rcu <= 15)
|
||||
ret = 5;
|
||||
} else {
|
||||
/* Return the level as per the 'Main Profile' */
|
||||
if (pcu < 40 && rcu < 20)
|
||||
ret = 1;
|
||||
else if (pcu < 80 && rcu < 64)
|
||||
ret = 2;
|
||||
else if (pcu < 160 && rcu < 128)
|
||||
ret = 3;
|
||||
else if (pcu < 320 && rcu < 256)
|
||||
ret = 4;
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
GST_WARNING ("couldn't determine level: profile=%u, rate=%u, "
|
||||
"channel_config=%u, pcu=%d,rcu=%d", profile, rate, channel_config, pcu,
|
||||
rcu);
|
||||
return NULL;
|
||||
} else {
|
||||
/* For fast and convenient int -> string conversion */
|
||||
static const char itoa[][2] = {
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||
};
|
||||
|
||||
g_assert (ret < G_N_ELEMENTS (itoa));
|
||||
return itoa[ret];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_codec_utils_aac_caps_set_level:
|
||||
* @caps: the #GstCaps to which the level is 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.
|
||||
*
|
||||
* Returns: TRUE if the level could be set, FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
gst_codec_utils_aac_caps_set_level (GstCaps * caps,
|
||||
const guint8 * audio_config, guint len)
|
||||
{
|
||||
const gchar *level;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
|
||||
g_return_val_if_fail (audio_config != NULL, FALSE);
|
||||
|
||||
level = gst_codec_utils_aac_get_level (audio_config, len);
|
||||
|
||||
if (!level)
|
||||
return FALSE;
|
||||
|
||||
gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2010 Nokia Corporation
|
||||
* Copyright (C) 2010 Collabora Multimedia
|
||||
/* GStreamer base utils library codec-specific utility functions
|
||||
* Copyright (C) 2010 Arun Raghavan <arun.raghavan@collabora.co.uk>
|
||||
*
|
||||
* gstaacutil.h: collection of AAC helper utilities
|
||||
* 2010 Collabora Multimedia
|
||||
* 2010 Nokia Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
|
@ -21,23 +19,24 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_AAC_UTIL_H__
|
||||
#define __GST_AAC_UTIL_H__
|
||||
#ifndef __GST_PB_UTILS_CODEC_UTILS_H__
|
||||
#define __GST_PB_UTILS_CODEC_UTILS_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* FIXME: This file is duplicated in gst-plugins-* wherever needed, so if you
|
||||
* update this file, please find all other instances and update them as well.
|
||||
* This less-than-optimal setup is being used till there is a standard location
|
||||
* for such common functionality.
|
||||
*/
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gint gst_aac_level_from_header (guint profile,
|
||||
guint sample_freq_idx,
|
||||
guint channel_config);
|
||||
/* AAC */
|
||||
|
||||
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);
|
||||
|
||||
gboolean gst_codec_utils_aac_caps_set_level (GstCaps * caps,
|
||||
const guint8 * audio_config,
|
||||
guint len);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_AAC_UTIL_H__*/
|
||||
#endif /* __GST_PB_UTILS_CODEC_UTILS_H__ */
|
|
@ -26,6 +26,7 @@
|
|||
#include <gst/pbutils/descriptions.h>
|
||||
#include <gst/pbutils/missing-plugins.h>
|
||||
#include <gst/pbutils/install-plugins.h>
|
||||
#include <gst/pbutils/codec-utils.h>
|
||||
#include <gst/pbutils/pbutils-enumtypes.h>
|
||||
#include <gst/pbutils/pbutils-marshal.h>
|
||||
#include <gst/pbutils/gstdiscoverer.h>
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
plugin_LTLIBRARIES = libgsttypefindfunctions.la
|
||||
|
||||
libgsttypefindfunctions_la_SOURCES = gsttypefindfunctions.c gstaacutil.c
|
||||
libgsttypefindfunctions_la_CFLAGS = $(GST_CFLAGS) $(GIO_CFLAGS)
|
||||
libgsttypefindfunctions_la_SOURCES = gsttypefindfunctions.c
|
||||
libgsttypefindfunctions_la_CFLAGS = \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(GST_CFLAGS) $(GIO_CFLAGS)
|
||||
libgsttypefindfunctions_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgsttypefindfunctions_la_LIBADD = $(GST_LIBS) $(GIO_LIBS)
|
||||
libgsttypefindfunctions_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
libgsttypefindfunctions_la_LIBADD = \
|
||||
$(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \
|
||||
$(GST_LIBS) $(GIO_LIBS)
|
||||
|
||||
noinst_HEADERS = gstaacutil.h
|
||||
libgsttypefindfunctions_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2010 Nokia Corporation
|
||||
* Copyright (C) 2010 Collabora Multimedia
|
||||
* Copyright (C) 2010 Arun Raghavan <arun.raghavan@collabora.co.uk>
|
||||
*
|
||||
* gstaacutil.c: collection of AAC helper utilities
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "gstaacutil.h"
|
||||
|
||||
/* FIXME: This file is duplicated in gst-plugins-* wherever needed, so if you
|
||||
* update this file, please find all other instances and update them as well.
|
||||
* This less-than-optimal setup is being used till there is a standard location
|
||||
* for such common functionality.
|
||||
*/
|
||||
|
||||
/* Determines the level of a stream as defined in ISO/IEC 14496-3. The
|
||||
* sample_frequency_index and channel_configuration must be got from the ESDS
|
||||
* for MP4 files and the ADTS header for ADTS streams.
|
||||
*
|
||||
* For AAC LC streams, we assume that apply the constraints from the AAC audio
|
||||
* profile. For AAC Main/LTP/SSR/..., we use the Main profile.
|
||||
*
|
||||
* FIXME: HE-AAC support is TBD.
|
||||
*
|
||||
* Returns -1 if the level could not be determined.
|
||||
*/
|
||||
gint
|
||||
gst_aac_level_from_header (guint profile, guint rate, guint channel_config)
|
||||
{
|
||||
/* Number of single channel elements, channel pair elements, low frequency
|
||||
* elements, independently switched coupling channel elements, and
|
||||
* dependently switched coupling channel elements.
|
||||
*
|
||||
* Note: The 2 CCE types are ignored for now as they require us to actually
|
||||
* parse the first frame, and they are rarely found in actual streams.
|
||||
*/
|
||||
int num_sce = 0, num_cpe = 0, num_lfe = 0, num_cce_indep = 0, num_cce_dep = 0;
|
||||
int num_channels;
|
||||
/* Processor and RAM Complexity Units (calculated and "reference" for single
|
||||
* channel) */
|
||||
int pcu, rcu, pcu_ref, rcu_ref;
|
||||
|
||||
switch (channel_config) {
|
||||
case 0:
|
||||
/* Channel config is defined in the AudioObjectType's SpecificConfig,
|
||||
* which requires some amount of digging through the headers. I only see
|
||||
* this done in the MPEG conformance streams - FIXME */
|
||||
GST_WARNING ("Found a stream with channel configuration in the "
|
||||
"AudioSpecificConfig. Please file a bug with a link to the media if "
|
||||
"possible.");
|
||||
return -1;
|
||||
case 1:
|
||||
/* front center */
|
||||
num_sce = 1;
|
||||
break;
|
||||
case 2:
|
||||
/* front left and right */
|
||||
num_cpe = 1;
|
||||
break;
|
||||
case 3:
|
||||
/* front left, right, and center */
|
||||
num_sce = 1;
|
||||
num_cpe = 1;
|
||||
break;
|
||||
case 4:
|
||||
/* front left, right, and center; rear surround */
|
||||
num_sce = 2;
|
||||
num_cpe = 1;
|
||||
break;
|
||||
case 5:
|
||||
/* front left, right, and center; rear left and right surround */
|
||||
num_sce = 1;
|
||||
num_cpe = 2;
|
||||
break;
|
||||
case 6:
|
||||
/* front left, right, center and LFE; rear left and right surround */
|
||||
num_sce = 1;
|
||||
num_cpe = 2;
|
||||
break;
|
||||
case 7:
|
||||
/* front left, right, center and LFE; outside front left and right;
|
||||
* rear left and right surround */
|
||||
num_sce = 1;
|
||||
num_cpe = 3;
|
||||
num_lfe = 1;
|
||||
break;
|
||||
default:
|
||||
GST_WARNING ("Unknown channel config in header: %d", channel_config);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (profile) {
|
||||
case 0: /* NULL */
|
||||
GST_WARNING ("profile 0 is not a valid profile");
|
||||
return -1;
|
||||
case 2: /* LC */
|
||||
pcu_ref = 3;
|
||||
rcu_ref = 3;
|
||||
break;
|
||||
case 3: /* SSR */
|
||||
pcu_ref = 4;
|
||||
rcu_ref = 3;
|
||||
break;
|
||||
case 4: /* LTP */
|
||||
pcu_ref = 4;
|
||||
rcu_ref = 4;
|
||||
break;
|
||||
case 1: /* Main */
|
||||
default:
|
||||
/* Other than a couple of ER profiles, Main is the worst-case */
|
||||
pcu_ref = 5;
|
||||
rcu_ref = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
/* "fs_ref" is 48000 Hz for AAC Main/LC/SSR/LTP. SBR's fs_ref is defined as
|
||||
* 24000/48000 (in/out), for SBR streams. Actual support is a FIXME */
|
||||
|
||||
pcu = ((float) rate / 48000) * pcu_ref *
|
||||
((2 * num_cpe) + num_sce + num_lfe + num_cce_indep + (0.3 * num_cce_dep));
|
||||
|
||||
rcu = ((float) rcu_ref) * (num_sce + (0.5 * num_lfe) + (0.5 * num_cce_indep) +
|
||||
(0.4 * num_cce_dep));
|
||||
|
||||
if (num_cpe < 2)
|
||||
rcu += (rcu_ref + (rcu_ref - 1)) * num_cpe;
|
||||
else
|
||||
rcu += (rcu_ref + (rcu_ref - 1) * ((2 * num_cpe) - 1));
|
||||
|
||||
num_channels = num_sce + (2 * num_cpe) + num_lfe;
|
||||
|
||||
if (profile == 2) {
|
||||
/* AAC LC => return the level as per the 'AAC Profile' */
|
||||
if (num_channels <= 2 && rate <= 24000 && pcu <= 3 && rcu <= 5)
|
||||
return 1;
|
||||
if (num_channels <= 2 && rate <= 48000 && pcu <= 6 && rcu <= 5)
|
||||
return 2;
|
||||
/* There is no level 3 for the AAC Profile */
|
||||
if (num_channels <= 5 && rate <= 48000 && pcu <= 19 && rcu <= 15)
|
||||
return 4;
|
||||
if (num_channels <= 5 && rate <= 96000 && pcu <= 38 && rcu <= 15)
|
||||
return 5;
|
||||
} else {
|
||||
/* Return the level as per the 'Main Profile' */
|
||||
if (pcu < 40 && rcu < 20)
|
||||
return 1;
|
||||
if (pcu < 80 && rcu < 64)
|
||||
return 2;
|
||||
if (pcu < 160 && rcu < 128)
|
||||
return 3;
|
||||
if (pcu < 320 && rcu < 256)
|
||||
return 4;
|
||||
}
|
||||
|
||||
GST_WARNING ("couldn't determine level: profile=%u,rate=%u,channel_config=%u,"
|
||||
"pcu=%d,rcu=%d", profile, rate, channel_config, pcu, rcu);
|
||||
return -1;
|
||||
}
|
|
@ -40,7 +40,7 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "gstaacutil.h"
|
||||
#include <gst/pbutils/pbutils.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (type_find_debug);
|
||||
#define GST_CAT_DEFAULT type_find_debug
|
||||
|
@ -661,9 +661,6 @@ 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" };
|
||||
static const guint sample_freq[] = { 96000, 88200, 64000, 48000, 44100,
|
||||
32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350
|
||||
};
|
||||
DataScanCtx c = { 0, NULL, 0 };
|
||||
|
||||
while (c.offset < AAC_AMOUNT) {
|
||||
|
@ -697,7 +694,7 @@ aac_type_find (GstTypeFind * tf, gpointer unused)
|
|||
if ((snc & 0xfff6) == 0xfff0) {
|
||||
GstCaps *caps;
|
||||
guint mpegversion, sample_freq_idx, channel_config, profile, rate;
|
||||
gint level;
|
||||
guint8 audio_config[2];
|
||||
|
||||
mpegversion = (c.data[1] & 0x08) ? 2 : 4;
|
||||
profile = c.data[2] >> 6;
|
||||
|
@ -715,11 +712,17 @@ aac_type_find (GstTypeFind * tf, gpointer unused)
|
|||
goto next;
|
||||
}
|
||||
|
||||
rate = sample_freq[sample_freq_idx];
|
||||
rate = gst_codec_utils_aac_get_sample_rate_from_index (sample_freq_idx);
|
||||
GST_LOG ("ADTS: profile=%u, rate=%u", profile, 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 */
|
||||
level = gst_aac_level_from_header (profile + 1, rate, channel_config);
|
||||
audio_config[0] = (profile + 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,
|
||||
|
@ -728,15 +731,7 @@ aac_type_find (GstTypeFind * tf, gpointer unused)
|
|||
"base-profile", G_TYPE_STRING, profile_to_string[profile],
|
||||
"profile", G_TYPE_STRING, profile_to_string[profile], NULL);
|
||||
|
||||
if (level != -1) {
|
||||
gchar level_str[16];
|
||||
|
||||
/* we use a string here because h.264 levels are also strings and
|
||||
* there aren't a lot of levels, so it's not too awkward to not use
|
||||
* and integer here and keep the field type consistent with h.264 */
|
||||
g_snprintf (level_str, sizeof (level_str), "%d", level);
|
||||
gst_caps_set_simple (caps, "level", G_TYPE_STRING, level_str, NULL);
|
||||
}
|
||||
gst_codec_utils_aac_caps_set_level (caps, audio_config, 2);
|
||||
|
||||
/* add rate and number of channels if we can */
|
||||
if (channel_config != 0 && channel_config <= 7) {
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
EXPORTS
|
||||
gst_codec_utils_aac_caps_set_level
|
||||
gst_codec_utils_aac_get_level
|
||||
gst_codec_utils_aac_get_sample_rate_from_index
|
||||
gst_discoverer_audio_info_get_bitrate
|
||||
gst_discoverer_audio_info_get_channels
|
||||
gst_discoverer_audio_info_get_depth
|
||||
|
|
Loading…
Reference in a new issue