From 538e7acb569fd0bac1f9a1e29ff5398156ceccc3 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 11 Feb 2015 20:59:34 +0100 Subject: [PATCH] parsers: AAC - better handle SBR extension --- src/muxer/tvh/mkmux.c | 4 ++++ src/packet.h | 1 + src/parsers/parser_latm.c | 43 +++++++++++++++++++++++++----------- src/parsers/parsers.c | 1 + src/plumbing/globalheaders.c | 8 ++++++- src/streaming.h | 1 + 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/muxer/tvh/mkmux.c b/src/muxer/tvh/mkmux.c index 5f091939..87c0800c 100644 --- a/src/muxer/tvh/mkmux.c +++ b/src/muxer/tvh/mkmux.c @@ -57,6 +57,7 @@ typedef struct mk_track { uint8_t channels; uint8_t sri; + uint8_t ext_sri; uint16_t aspect_num; uint16_t aspect_den; @@ -432,6 +433,8 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss) htsbuf_queue_t *au = htsbuf_queue_alloc(0); ebml_append_float(au, 0xb5, sri_to_rate(ssc->ssc_sri)); + if (ssc->ssc_ext_sri) + ebml_append_float(au, 0x78b5, sri_to_rate(ssc->ssc_ext_sri - 1)); ebml_append_uint(au, 0x9f, ssc->ssc_channels); if (bit_depth) ebml_append_uint(au, 0x6264, bit_depth); @@ -1215,6 +1218,7 @@ mk_mux_write_pkt(mk_mux_t *mkm, th_pkt_t *pkt) pkt->pkt_sri) { mark = 1; t->sri = pkt->pkt_sri; + t->ext_sri = pkt->pkt_ext_sri; } if(pkt->pkt_commercial != t->commercial && pkt->pkt_commercial != COMMERCIAL_UNKNOWN) { diff --git a/src/packet.h b/src/packet.h index 33b4720a..30d64649 100644 --- a/src/packet.h +++ b/src/packet.h @@ -59,6 +59,7 @@ typedef struct th_pkt { uint8_t pkt_channels; uint8_t pkt_sri; + uint8_t pkt_ext_sri; uint8_t pkt_err; uint16_t pkt_aspect_num; diff --git a/src/parsers/parser_latm.c b/src/parsers/parser_latm.c index b54170ff..7d013fd8 100644 --- a/src/parsers/parser_latm.c +++ b/src/parsers/parser_latm.c @@ -43,7 +43,8 @@ typedef struct latm_private { int aot; int frame_length_type; - int sample_rate_index; + int sri; + int ext_sri; int channel_config; } latm_private_t; @@ -95,25 +96,40 @@ static int read_audio_specific_config(elementary_stream_t *st, latm_private_t *latm, bitstream_t *bs) { - int aot, sr; + int aot, sr, sri; if ((bs->offset % 8) != 0) return -1; aot = read_aot(bs); - sr = read_sr(bs, &latm->sample_rate_index); + sr = read_sr(bs, &latm->sri); latm->channel_config = read_bits(bs, 4); + if (sr < 7350 || sr > 96000 || + latm->channel_config == 0 || latm->channel_config > 7) + return -1; + st->es_frame_duration = 1024 * 90000 / sr; + latm->ext_sri = 0; if (aot == AOT_SBR || (aot == AOT_PS && !(show_bits(bs, 3) & 3 && !(show_bits(bs, 9) & 0x3f)))) { - sr = read_sr(bs, &latm->sample_rate_index); - aot = read_aot(bs); // this is the main object type (i.e. non-extended) + sr = read_sr(bs, &latm->ext_sri); + if (sr < 7350 || sr > 96000) + return -1; + latm->ext_sri++; // zero means "not set" + aot = read_aot(bs); // this is the main object type (i.e. non-extended) + } + + /* it's really unusual to use lower sample rates than 32000Hz */ + /* for the professional broadcasting, assume the SBR extension */ + if (aot == AOT_AAC_LC && latm->ext_sri == 0 && sr <= 24000) { + sri = rate_to_sri(sr * 2); + if (sri < 0) + return -1; + latm->ext_sri = sri + 1; } - if (sr == 0 || latm->channel_config == 0) - return -1; if (aot != AOT_AAC_MAIN && aot != AOT_AAC_LC && aot != AOT_AAC_SSR && aot != AOT_AAC_LTP) return -1; @@ -121,10 +137,10 @@ read_audio_specific_config(elementary_stream_t *st, latm_private_t *latm, if (read_bits1(bs)) // framelen_flag return -1; - if (read_bits1(bs)) // depends_on_coder + if (read_bits1(bs)) // depends_on_coder skip_bits(bs, 14); - if (read_bits1(bs)) // ext_flag + if (read_bits1(bs)) // ext_flag skip_bits(bs, 1); // ext3_flag return 0; } @@ -250,9 +266,10 @@ parse_latm_audio_mux_element(service_t *t, elementary_stream_t *st, th_pkt_t *pkt = pkt_alloc(NULL, slot_len + 7, st->es_curdts, st->es_curdts); pkt->pkt_commercial = t->s_tt_commercial_advice; - pkt->pkt_duration = st->es_frame_duration; - pkt->pkt_sri = latm->sample_rate_index; - pkt->pkt_channels = latm->channel_config == 7 ? 8 : latm->channel_config; + pkt->pkt_duration = st->es_frame_duration; + pkt->pkt_sri = latm->sri + 1; + pkt->pkt_ext_sri = latm->ext_sri; + pkt->pkt_channels = latm->channel_config == 7 ? 8 : latm->channel_config; /* 7 bytes of ADTS header */ init_wbits(&out, pktbuf_ptr(pkt->pkt_payload), 7 * 8); @@ -262,7 +279,7 @@ parse_latm_audio_mux_element(service_t *t, elementary_stream_t *st, put_bits(&out, 0, 2); // Layer put_bits(&out, 1, 1); // Protection absent put_bits(&out, adts_aot(latm->aot), 2); - put_bits(&out, latm->sample_rate_index, 4); + put_bits(&out, latm->sri, 4); put_bits(&out, 1, 1); // Private bit put_bits(&out, latm->channel_config, 3); put_bits(&out, 1, 1); // Original diff --git a/src/parsers/parsers.c b/src/parsers/parsers.c index bb1b1af8..082804d9 100644 --- a/src/parsers/parsers.c +++ b/src/parsers/parsers.c @@ -314,6 +314,7 @@ parse_aac(service_t *t, elementary_stream_t *st, const uint8_t *data, /* Wrong bytestream */ } else { + tvhtrace("parser", "AAC skip byte %02x", d[0]); p++; } } diff --git a/src/plumbing/globalheaders.c b/src/plumbing/globalheaders.c index f50132e9..f330de6d 100644 --- a/src/plumbing/globalheaders.c +++ b/src/plumbing/globalheaders.c @@ -86,6 +86,7 @@ apply_header(streaming_start_component_t *ssc, th_pkt_t *pkt) if(SCT_ISAUDIO(ssc->ssc_type) && !ssc->ssc_channels && !ssc->ssc_sri) { ssc->ssc_channels = pkt->pkt_channels; ssc->ssc_sri = pkt->pkt_sri; + ssc->ssc_ext_sri = pkt->pkt_ext_sri; } if(SCT_ISVIDEO(ssc->ssc_type)) { @@ -105,12 +106,17 @@ apply_header(streaming_start_component_t *ssc, th_pkt_t *pkt) } if (ssc->ssc_type == SCT_MP4A || ssc->ssc_type == SCT_AAC) { - ssc->ssc_gh = pktbuf_alloc(NULL, 2); + ssc->ssc_gh = pktbuf_alloc(NULL, pkt->pkt_ext_sri ? 5 : 2); uint8_t *d = pktbuf_ptr(ssc->ssc_gh); const int profile = 2; /* AAC LC */ d[0] = (profile << 3) | ((pkt->pkt_sri & 0xe) >> 1); d[1] = ((pkt->pkt_sri & 0x1) << 7) | (pkt->pkt_channels << 3); + if (pkt->pkt_ext_sri) { /* SBR extension */ + d[2] = 0x56; + d[3] = 0xe5; + d[4] = 0x80 | ((pkt->pkt_ext_sri - 1) << 3); + } } } diff --git a/src/streaming.h b/src/streaming.h index c7c5f0e2..2328ba5f 100644 --- a/src/streaming.h +++ b/src/streaming.h @@ -36,6 +36,7 @@ typedef struct streaming_start_component { int16_t ssc_aspect_num; int16_t ssc_aspect_den; uint8_t ssc_sri; + uint8_t ssc_ext_sri; uint8_t ssc_channels; uint8_t ssc_disabled;