parsers: AAC - better handle SBR extension

This commit is contained in:
Jaroslav Kysela 2015-02-11 20:59:34 +01:00
parent f6537ab39f
commit 538e7acb56
6 changed files with 44 additions and 14 deletions

View file

@ -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) {

View file

@ -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;

View file

@ -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

View file

@ -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++;
}
}

View file

@ -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);
}
}
}

View file

@ -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;