268 lines
9.0 KiB
Diff
268 lines
9.0 KiB
Diff
From b2c850f295a0fe49310fb60784ac6af4a29bceae Mon Sep 17 00:00:00 2001
|
|
From: Lyon Wang <lyon.wang@nxp.com>
|
|
Date: Fri, 9 Jun 2017 16:53:11 +0800
|
|
Subject: [PATCH] gstaacparse: Fix adif aac file read channel/progile issue
|
|
|
|
- parser adif program_config_element() to get correct channel
|
|
- Fix aacparse src pad caps wrong profile for ADIF file
|
|
|
|
Upstream status: submitted.
|
|
Combined 2 bugzilla ticket:
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=783583
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=785476
|
|
|
|
Signed-off-by: Lyon Wang <lyon.wang@nxp.com>
|
|
---
|
|
gst/audioparsers/gstaacparse.c | 203 ++++++++++++++++++++++++++++++-----------
|
|
1 file changed, 152 insertions(+), 51 deletions(-)
|
|
|
|
diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c
|
|
index 16d66e2..e2c2bc9 100644
|
|
--- a/gst/audioparsers/gstaacparse.c
|
|
+++ b/gst/audioparsers/gstaacparse.c
|
|
@@ -85,6 +85,35 @@ static const gint loas_channels_table[16] = {
|
|
0, 0, 0, 7, 8, 0, 8, 0
|
|
};
|
|
|
|
+typedef struct
|
|
+{
|
|
+ guint32 num_ele;
|
|
+ guint32 ele_is_cpe[16];
|
|
+ guint32 ele_tag[16];
|
|
+} GstAacEleList;
|
|
+
|
|
+typedef struct
|
|
+{
|
|
+ guint32 present;
|
|
+ guint32 ele_tag;
|
|
+ guint32 pseudo_enab;
|
|
+} GstAacMIXdown;
|
|
+
|
|
+typedef struct
|
|
+{
|
|
+ guint32 profile;
|
|
+ guint32 sr_idx;
|
|
+ GstAacEleList front;
|
|
+ GstAacEleList side;
|
|
+ GstAacEleList back;
|
|
+ GstAacEleList data;
|
|
+ GstAacEleList lfe;
|
|
+ GstAacEleList coupling;
|
|
+ GstAacMIXdown mono_mix;
|
|
+ GstAacMIXdown stereo_mix;
|
|
+ GstAacMIXdown matrix_mix;
|
|
+} GstAacProgConfig;
|
|
+
|
|
static gboolean gst_aac_parse_start (GstBaseParse * parse);
|
|
static gboolean gst_aac_parse_stop (GstBaseParse * parse);
|
|
|
|
@@ -104,6 +133,9 @@ static gboolean gst_aac_parse_read_audio_specific_config (GstAacParse *
|
|
aacparse, GstBitReader * br, gint * object_type, gint * sample_rate,
|
|
gint * channels, gint * frame_samples);
|
|
|
|
+static gboolean gst_aac_parse_read_program_config_element (GstAacProgConfig *
|
|
+ progConfig, GstBitReader * br);
|
|
+
|
|
|
|
#define gst_aac_parse_parent_class parent_class
|
|
G_DEFINE_TYPE (GstAacParse, gst_aac_parse, GST_TYPE_BASE_PARSE);
|
|
@@ -844,6 +876,87 @@ gst_aac_parse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
|
|
*object = ((data[2] & 0xc0) >> 6) + 1;
|
|
}
|
|
|
|
+static void
|
|
+gst_aac_parse_get_ele_list (GstAacEleList * pList, gint32 cpe,
|
|
+ GstBitReader * br)
|
|
+{
|
|
+ guint32 count, num_elem;
|
|
+ num_elem = pList->num_ele;
|
|
+ for (count = 0; count < num_elem; count++) {
|
|
+ if (cpe) {
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(pList->ele_is_cpe[count]), 1);
|
|
+ } else {
|
|
+ pList->ele_is_cpe[count] = 0;
|
|
+ }
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(pList->ele_tag[count]), 4);
|
|
+ }
|
|
+}
|
|
+
|
|
+static gint32
|
|
+gst_aac_parse_get_config_channels (GstAacEleList * pList)
|
|
+{
|
|
+ guint32 count, num_elem, channels = 0;
|
|
+ num_elem = pList->num_ele;
|
|
+ for (count = 0; count < num_elem; count++) {
|
|
+ channels++;
|
|
+ if (pList->ele_is_cpe[count] == 1) {
|
|
+ /* CPE element channels++ */
|
|
+ channels++;
|
|
+ }
|
|
+ }
|
|
+ return channels;
|
|
+}
|
|
+
|
|
+/* Read program config element
|
|
+ISO/IEC 14496-3, 4.4.1.1 read program config element */
|
|
+static gboolean
|
|
+gst_aac_parse_read_program_config_element (GstAacProgConfig *
|
|
+ progConfig, GstBitReader * br)
|
|
+{
|
|
+ guint32 count = 0;
|
|
+ guint32 bytes = 0;
|
|
+
|
|
+ gst_bit_reader_skip (br, 4); //element_instance_tag
|
|
+
|
|
+ gst_bit_reader_get_bits_uint32 (br, &progConfig->profile, 2);
|
|
+ gst_bit_reader_get_bits_uint32 (br, &progConfig->sr_idx, 4);
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->front.num_ele), 4);
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->side.num_ele), 4);
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->back.num_ele), 4);
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->lfe.num_ele), 2);
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->data.num_ele), 3);
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->coupling.num_ele), 4);
|
|
+
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->mono_mix.present), 1);
|
|
+ if (progConfig->mono_mix.present) {
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->mono_mix.ele_tag), 4);
|
|
+ }
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->stereo_mix.present), 1);
|
|
+ if (progConfig->mono_mix.present) {
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->stereo_mix.ele_tag), 4);
|
|
+ }
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->matrix_mix.present), 1);
|
|
+ if (progConfig->mono_mix.present) {
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->matrix_mix.ele_tag), 2);
|
|
+ gst_bit_reader_get_bits_uint32 (br, &(progConfig->matrix_mix.pseudo_enab), 1);
|
|
+ }
|
|
+
|
|
+ gst_aac_parse_get_ele_list (&progConfig->front, 1, br);
|
|
+ gst_aac_parse_get_ele_list (&progConfig->side, 1, br);
|
|
+ gst_aac_parse_get_ele_list (&progConfig->back, 1, br);
|
|
+ gst_aac_parse_get_ele_list (&progConfig->data, 0, br);
|
|
+ gst_aac_parse_get_ele_list (&progConfig->lfe, 0, br);
|
|
+ gst_aac_parse_get_ele_list (&progConfig->coupling, 1, br);
|
|
+
|
|
+ gst_bit_reader_skip_to_byte (br); // byte_alignment
|
|
+
|
|
+ gst_bit_reader_get_bits_uint32 (br, &bytes, 8); //comment_field_bytes
|
|
+ for (count = 0; count < bytes; count++) {
|
|
+ gst_bit_reader_skip (br, 8); //skip comment data
|
|
+ }
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
/**
|
|
* gst_aac_parse_detect_stream:
|
|
* @aacparse: #GstAacParse.
|
|
@@ -973,68 +1086,56 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
|
|
return FALSE;
|
|
|
|
if (memcmp (data + i, "ADIF", 4) == 0) {
|
|
- const guint8 *adif;
|
|
- int skip_size = 0;
|
|
- int bitstream_type;
|
|
+ GstBitReader br;
|
|
+ guint8 u8 = 0;
|
|
+ guint8 bitstream_type = 0;
|
|
+ guint num_elems = 0;
|
|
+ guint bitrate = 0;
|
|
+ guint count;
|
|
int sr_idx;
|
|
GstCaps *sinkcaps;
|
|
-
|
|
+ GstAacProgConfig *progConfig;
|
|
aacparse->header_type = DSPAAC_HEADER_ADIF;
|
|
aacparse->mpegversion = 4;
|
|
-
|
|
- /* Skip the "ADIF" bytes */
|
|
- adif = data + i + 4;
|
|
-
|
|
- /* copyright string */
|
|
- if (adif[0] & 0x80)
|
|
- skip_size += 9; /* skip 9 bytes */
|
|
-
|
|
- bitstream_type = adif[0 + skip_size] & 0x10;
|
|
- aacparse->bitrate =
|
|
- ((unsigned int) (adif[0 + skip_size] & 0x0f) << 19) |
|
|
- ((unsigned int) adif[1 + skip_size] << 11) |
|
|
- ((unsigned int) adif[2 + skip_size] << 3) |
|
|
- ((unsigned int) adif[3 + skip_size] & 0xe0);
|
|
-
|
|
- /* CBR */
|
|
+ gst_bit_reader_init (&br, data + i, avail - i);
|
|
+ /* skip sync word (adif 4 byte ) */
|
|
+ gst_bit_reader_skip (&br, 32);
|
|
+ gst_bit_reader_get_bits_uint8 (&br, &u8, 1);
|
|
+ if (u8) {
|
|
+ gst_bit_reader_skip (&br, 72); //copyright_id
|
|
+ }
|
|
+ gst_bit_reader_skip (&br, 2); // original_copy and home
|
|
+ gst_bit_reader_get_bits_uint8 (&br, &bitstream_type, 1);
|
|
+ gst_bit_reader_get_bits_uint32 (&br, &bitrate, 23);
|
|
+ gst_bit_reader_get_bits_uint32 (&br, &num_elems, 4);
|
|
if (bitstream_type == 0) {
|
|
-#if 0
|
|
- /* Buffer fullness parsing. Currently not needed... */
|
|
- guint num_elems = 0;
|
|
- guint fullness = 0;
|
|
-
|
|
- num_elems = (adif[3 + skip_size] & 0x1e);
|
|
- GST_INFO ("ADIF num_config_elems: %d", num_elems);
|
|
-
|
|
- fullness = ((unsigned int) (adif[3 + skip_size] & 0x01) << 19) |
|
|
- ((unsigned int) adif[4 + skip_size] << 11) |
|
|
- ((unsigned int) adif[5 + skip_size] << 3) |
|
|
- ((unsigned int) (adif[6 + skip_size] & 0xe0) >> 5);
|
|
-
|
|
- GST_INFO ("ADIF buffer fullness: %d", fullness);
|
|
-#endif
|
|
- aacparse->object_type = ((adif[6 + skip_size] & 0x01) << 1) |
|
|
- ((adif[7 + skip_size] & 0x80) >> 7);
|
|
- sr_idx = (adif[7 + skip_size] & 0x78) >> 3;
|
|
+ gst_bit_reader_skip (&br, 20); //adif_buffer_fullness
|
|
}
|
|
- /* VBR */
|
|
- else {
|
|
- aacparse->object_type = (adif[4 + skip_size] & 0x18) >> 3;
|
|
- sr_idx = ((adif[4 + skip_size] & 0x07) << 1) |
|
|
- ((adif[5 + skip_size] & 0x80) >> 7);
|
|
+
|
|
+ progConfig =
|
|
+ (GstAacProgConfig *) g_malloc0 ((num_elems+1) * sizeof (GstAacProgConfig));
|
|
+ for ( count = 0; count < num_elems + 1; count++) {
|
|
+ gst_aac_parse_read_program_config_element (&progConfig[count], &br);
|
|
+ aacparse->channels +=
|
|
+ gst_aac_parse_get_config_channels (&(progConfig[count].front));
|
|
+ aacparse->channels +=
|
|
+ gst_aac_parse_get_config_channels (&(progConfig[count].side));
|
|
+ aacparse->channels +=
|
|
+ gst_aac_parse_get_config_channels (&(progConfig[count].back));
|
|
+ aacparse->channels +=
|
|
+ gst_aac_parse_get_config_channels (&(progConfig[count].lfe));
|
|
+ aacparse->channels +=
|
|
+ gst_aac_parse_get_config_channels (&(progConfig[count].coupling));
|
|
}
|
|
|
|
- /* FIXME: This gives totally wrong results. Duration calculation cannot
|
|
- be based on this */
|
|
+ aacparse->bitrate = (gint)bitrate;
|
|
+ aacparse->object_type = progConfig[0].profile + 1;
|
|
+ sr_idx = progConfig[0].sr_idx;
|
|
+ g_free(progConfig);
|
|
+
|
|
aacparse->sample_rate =
|
|
gst_codec_utils_aac_get_sample_rate_from_index (sr_idx);
|
|
|
|
- /* baseparse is not given any fps,
|
|
- * so it will give up on timestamps, seeking, etc */
|
|
-
|
|
- /* FIXME: Can we assume this? */
|
|
- aacparse->channels = 2;
|
|
-
|
|
GST_INFO ("ADIF: br=%d, samplerate=%d, objtype=%d",
|
|
aacparse->bitrate, aacparse->sample_rate, aacparse->object_type);
|
|
|
|
--
|
|
1.9.1
|
|
|