aacparse: streamline and improve AudioSpecificConfig parsing

AudioSpecifigConfig is used in a variety of AAC streams but was
being parsed differently. Instead, make everyone use the same parsing.

* Remove unused 'bits' field (it was always set to 0 if present)
* Add proper GAConfig parsing (to know the  number of samples per frame
  if present).

Fixes wrong rate/channels configuration in streams coming from qtdemux

https://bugzilla.gnome.org/show_bug.cgi?id=780966
This commit is contained in:
Edward Hervey 2017-04-06 12:01:00 +02:00 committed by Edward Hervey
parent 3342d86d9b
commit 9a066e548d

View file

@ -100,6 +100,11 @@ static GstFlowReturn gst_aac_parse_pre_push_frame (GstBaseParse * parse,
static gboolean gst_aac_parse_src_event (GstBaseParse * parse, static gboolean gst_aac_parse_src_event (GstBaseParse * parse,
GstEvent * event); GstEvent * event);
static gboolean gst_aac_parse_read_audio_specific_config (GstAacParse *
aacparse, GstBitReader * br, gint * object_type, gint * sample_rate,
gint * channels, gint * frame_samples);
#define gst_aac_parse_parent_class parent_class #define gst_aac_parse_parent_class parent_class
G_DEFINE_TYPE (GstAacParse, gst_aac_parse, GST_TYPE_BASE_PARSE); G_DEFINE_TYPE (GstAacParse, gst_aac_parse, GST_TYPE_BASE_PARSE);
@ -308,25 +313,17 @@ gst_aac_parse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
if (buf && gst_buffer_get_size (buf) >= 2) { if (buf && gst_buffer_get_size (buf) >= 2) {
GstMapInfo map; GstMapInfo map;
guint sr_idx; GstBitReader br;
if (!gst_buffer_map (buf, &map, GST_MAP_READ)) if (!gst_buffer_map (buf, &map, GST_MAP_READ))
return FALSE; return FALSE;
gst_bit_reader_init (&br, map.data, map.size);
gst_aac_parse_read_audio_specific_config (aacparse, &br,
&aacparse->object_type, &aacparse->sample_rate, &aacparse->channels,
&aacparse->frame_samples);
sr_idx = ((map.data[0] & 0x07) << 1) | ((map.data[1] & 0x80) >> 7);
aacparse->object_type = (map.data[0] & 0xf8) >> 3;
aacparse->sample_rate =
gst_codec_utils_aac_get_sample_rate_from_index (sr_idx);
aacparse->channels = (map.data[1] & 0x78) >> 3;
if (aacparse->channels == 7)
aacparse->channels = 8;
else if (aacparse->channels == 11)
aacparse->channels = 7;
else if (aacparse->channels == 12 || aacparse->channels == 14)
aacparse->channels = 8;
aacparse->header_type = DSPAAC_HEADER_NONE; aacparse->header_type = DSPAAC_HEADER_NONE;
aacparse->mpegversion = 4; aacparse->mpegversion = 4;
aacparse->frame_samples = (map.data[1] & 4) ? 960 : 1024;
gst_buffer_unmap (buf, &map); gst_buffer_unmap (buf, &map);
GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d, " GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d, "
@ -540,8 +537,9 @@ gst_aac_parse_get_audio_sample_rate (GstAacParse * aacparse, GstBitReader * br,
/* See table 1.13 in ISO/IEC 14496-3 */ /* See table 1.13 in ISO/IEC 14496-3 */
static gboolean static gboolean
gst_aac_parse_read_loas_audio_specific_config (GstAacParse * aacparse, gst_aac_parse_read_audio_specific_config (GstAacParse * aacparse,
GstBitReader * br, gint * sample_rate, gint * channels, guint32 * bits) GstBitReader * br, gint * object_type, gint * sample_rate, gint * channels,
gint * frame_samples)
{ {
guint8 audio_object_type; guint8 audio_object_type;
guint8 G_GNUC_UNUSED extension_audio_object_type; guint8 G_GNUC_UNUSED extension_audio_object_type;
@ -550,6 +548,8 @@ gst_aac_parse_read_loas_audio_specific_config (GstAacParse * aacparse,
if (!gst_aac_parse_get_audio_object_type (aacparse, br, &audio_object_type)) if (!gst_aac_parse_get_audio_object_type (aacparse, br, &audio_object_type))
return FALSE; return FALSE;
if (object_type)
*object_type = audio_object_type;
if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate)) if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
return FALSE; return FALSE;
@ -573,7 +573,8 @@ gst_aac_parse_read_loas_audio_specific_config (GstAacParse * aacparse,
} }
GST_LOG_OBJECT (aacparse, GST_LOG_OBJECT (aacparse,
"Audio object type 5 or 29, so rereading sampling rate..."); "Audio object type 5 or 29, so rereading sampling rate (was %d)...",
*sample_rate);
if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate)) if (!gst_aac_parse_get_audio_sample_rate (aacparse, br, sample_rate))
return FALSE; return FALSE;
@ -595,15 +596,23 @@ gst_aac_parse_read_loas_audio_specific_config (GstAacParse * aacparse,
extension_audio_object_type = 0; extension_audio_object_type = 0;
} }
GST_INFO_OBJECT (aacparse, "Found LOAS config: %d Hz, %d channels", GST_INFO_OBJECT (aacparse, "Parsed AudioSpecificConfig: %d Hz, %d channels",
*sample_rate, *channels); *sample_rate, *channels);
if (frame_samples && audio_object_type == 23) {
guint8 frame_flag;
/* Read the Decoder Configuration (GASpecificConfig) if present */
/* We only care about the first bit to know what the number of samples
* in a frame is */
if (!gst_bit_reader_get_bits_uint8 (br, &frame_flag, 1))
return FALSE;
*frame_samples = frame_flag ? 960 : 1024;
}
/* There's LOTS of stuff next, but we ignore it for now as we have /* There's LOTS of stuff next, but we ignore it for now as we have
what we want (sample rate and number of channels */ what we want (sample rate and number of channels */
GST_DEBUG_OBJECT (aacparse, GST_DEBUG_OBJECT (aacparse,
"Need more code to parse humongous LOAS data, currently ignored"); "Need more code to parse humongous LOAS data, currently ignored");
if (bits)
*bits = 0;
aacparse->last_parsed_channels = *channels; aacparse->last_parsed_channels = *channels;
return TRUE; return TRUE;
} }
@ -687,17 +696,16 @@ gst_aac_parse_read_loas_config (GstAacParse * aacparse, const guint8 * data,
} }
if (!use_same_config) { if (!use_same_config) {
if (v == 0) { if (v == 0) {
if (!gst_aac_parse_read_loas_audio_specific_config (aacparse, &br, if (!gst_aac_parse_read_audio_specific_config (aacparse, &br, NULL,
sample_rate, channels, NULL)) sample_rate, channels, NULL))
return FALSE; return FALSE;
} else { } else {
guint32 bits, asc_len; guint32 asc_len;
if (!gst_aac_parse_latm_get_value (aacparse, &br, &asc_len)) if (!gst_aac_parse_latm_get_value (aacparse, &br, &asc_len))
return FALSE; return FALSE;
if (!gst_aac_parse_read_loas_audio_specific_config (aacparse, &br, if (!gst_aac_parse_read_audio_specific_config (aacparse, &br, NULL,
sample_rate, channels, &bits)) sample_rate, channels, NULL))
return FALSE; return FALSE;
asc_len -= bits;
if (!gst_bit_reader_skip (&br, asc_len)) if (!gst_bit_reader_skip (&br, asc_len))
return FALSE; return FALSE;
} }