Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
parsers: improve AAC/LATM parser
  • Loading branch information
perexg committed Feb 11, 2015
1 parent cd1f081 commit cc1fbb0
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 103 deletions.
39 changes: 16 additions & 23 deletions src/parsers/bitstream.c
Expand Up @@ -40,23 +40,10 @@ init_wbits(bitstream_t *bs, uint8_t *data, int bits)
bs->len = bits;
}

void
skip_bits(bitstream_t *bs, int num)
{
bs->offset += num;
}

int
bs_eof(const bitstream_t *bs)
{
return bs->offset >= bs->len;
}


unsigned int
read_bits(bitstream_t *bs, int num)
{
int r = 0;
unsigned int r = 0;

while(num > 0) {
if(bs->offset >= bs->len)
Expand All @@ -73,9 +60,22 @@ read_bits(bitstream_t *bs, int num)
}

unsigned int
read_bits1(bitstream_t *bs)
show_bits(bitstream_t *bs, int num)
{
return read_bits(bs, 1);
unsigned int r = 0, offset = bs->offset;

while(num > 0) {
if(offset >= bs->len)
return 0;

num--;

if(bs->rdata[offset / 8] & (1 << (7 - (offset & 7))))
r |= 1 << num;

offset++;
}
return r;
}

unsigned int
Expand Down Expand Up @@ -106,13 +106,6 @@ read_golomb_se(bitstream_t *bs)
}


unsigned int
remaining_bits(bitstream_t *bs)
{
return bs->len - bs->offset;
}


void
put_bits(bitstream_t *bs, int val, int num)
{
Expand Down
14 changes: 10 additions & 4 deletions src/parsers/bitstream.h
Expand Up @@ -26,24 +26,30 @@ typedef struct bitstream {
int len;
} bitstream_t;

void skip_bits(bitstream_t *bs, int num);
static inline void skip_bits(bitstream_t *bs, int num)
{ bs->offset += num; }

void init_rbits(bitstream_t *bs, const uint8_t *data, int bits);

void init_wbits(bitstream_t *bs, uint8_t *data, int bits);

unsigned int read_bits(bitstream_t *gb, int num);

unsigned int read_bits1(bitstream_t *gb);
unsigned int show_bits(bitstream_t *gb, int num);

static inline unsigned int read_bits1(bitstream_t *gb)
{ return read_bits(gb, 1); }

unsigned int read_golomb_ue(bitstream_t *gb);

signed int read_golomb_se(bitstream_t *gb);

unsigned int remaining_bits(bitstream_t *gb);
static inline unsigned int remaining_bits(bitstream_t *gb)
{ return gb->len - gb->offset; }

void put_bits(bitstream_t *bs, int val, int num);

int bs_eof(const bitstream_t *bs);
static inline int bs_eof(const bitstream_t *bs)
{ return bs->offset >= bs->len; }

#endif /* BITSTREAM_H_ */
138 changes: 88 additions & 50 deletions src/parsers/parser_latm.c
Expand Up @@ -40,6 +40,7 @@ typedef struct latm_private {

int configured;
int audio_mux_version_A;
int aot;
int frame_length_type;

int sample_rate_index;
Expand All @@ -55,74 +56,110 @@ latm_get_value(bitstream_t *bs)
return read_bits(bs, read_bits(bs, 2) * 8);
}

#define AOT_AAC_MAIN 1
#define AOT_AAC_LC 2
#define AOT_AAC_SSR 3
#define AOT_AAC_LTP 4
#define AOT_SBR 5
#define AOT_PS 26
#define AOT_ESCAPE 28

static void
static inline int adts_aot(int aot)
{
switch (aot) {
case AOT_AAC_MAIN: return 0;
case AOT_AAC_LC : return 1;
case AOT_AAC_SSR : return 2;
default: return 3; /* reserved or LTP */
}
}

static inline int read_aot(bitstream_t *bs)
{
int aot = read_bits(bs, 5);
if (aot == AOT_ESCAPE)
aot = read_bits(bs, 6);
return aot;
}

static inline int read_sr(bitstream_t *bs, int *sri)
{
*sri = read_bits(bs, 4);
if (*sri == 0x0f)
return read_bits(bs, 24);
else
return sri_to_rate(*sri);
}

static int
read_audio_specific_config(elementary_stream_t *st, latm_private_t *latm,
bitstream_t *bs)
{
int aot, sr;

aot = read_bits(bs, 5);

latm->sample_rate_index = read_bits(bs, 4);

if(latm->sample_rate_index == 0xf)
sr = read_bits(bs, 24);
else
sr = sri_to_rate(latm->sample_rate_index);
if ((bs->offset % 8) != 0)
return -1;

if(sr == 0)
return;
aot = read_aot(bs);
sr = read_sr(bs, &latm->sample_rate_index);
latm->channel_config = read_bits(bs, 4);

st->es_frame_duration = 1024 * 90000 / sr;

latm->channel_config = read_bits(bs, 4);

if (aot == 5) { // AOT_SBR
if (read_bits(bs, 4) == 0xf) { // extensionSamplingFrequencyIndex
skip_bits(bs, 24);
}
aot = read_bits(bs, 5); // this is the main object type (i.e. non-extended)
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)
}

if(aot != 2)
return;
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;
latm->aot = aot;

skip_bits(bs, 1); //framelen_flag
if(read_bits1(bs)) // depends_on_coder
if (read_bits1(bs)) // framelen_flag
return -1;
if (read_bits1(bs)) // depends_on_coder
skip_bits(bs, 14);

if(read_bits(bs, 1)) // ext_flag
if (read_bits1(bs)) // ext_flag
skip_bits(bs, 1); // ext3_flag
return 0;
}


static void
static int
read_stream_mux_config(elementary_stream_t *st, latm_private_t *latm, bitstream_t *bs)
{
int audio_mux_version = read_bits(bs, 1);
int audio_mux_version = read_bits1(bs);
latm->audio_mux_version_A = 0;
if(audio_mux_version) // audioMuxVersion
latm->audio_mux_version_A = read_bits(bs, 1);
if(audio_mux_version) // audioMuxVersion
latm->audio_mux_version_A = read_bits1(bs);

if(latm->audio_mux_version_A)
return;
return 0;

if(audio_mux_version)
latm_get_value(bs); // taraFullness
latm_get_value(bs); // taraFullness

skip_bits(bs, 1); // allStreamSameTimeFraming = 1
skip_bits(bs, 6); // numSubFrames = 0
skip_bits(bs, 4); // numPrograms = 0

// for each program (which there is only on in DVB)
skip_bits(bs, 3); // numLayer = 0
if (read_bits(bs, 4)) // numPrograms = 0
return -1;

// for each program (only one in DVB)
if (read_bits(bs, 3)) // numLayer = 0
return -1;

// for each layer (which there is only on in DVB)
if(!audio_mux_version)
read_audio_specific_config(st, latm, bs);
else {
return;
// for each layer (which there is only one in DVB)
if(!audio_mux_version) {
if (read_audio_specific_config(st, latm, bs) < 0)
return -1;
} else {
return -1;
#if 0 // see bellow (look for dead code)
uint32_t ascLen = latm_get_value(bs);
abort(); // ascLen -= read_audio_specific_config(filter, gb);
Expand Down Expand Up @@ -150,24 +187,25 @@ read_stream_mux_config(elementary_stream_t *st, latm_private_t *latm, bitstream_
break;
}

if(read_bits(bs, 1)) { // other data?
if(read_bits1(bs)) { // other data?
#if 0 // coverity - dead code - see above
if(audio_mux_version)
latm_get_value(bs); // other_data_bits
latm_get_value(bs); // other_data_bits
else
#endif
{
int esc;
do {
esc = read_bits(bs, 1);
esc = read_bits1(bs);
skip_bits(bs, 8);
} while (esc);
}
}

if(read_bits(bs, 1)) // crc present?
skip_bits(bs, 8); // config_crc
if(read_bits1(bs)) // crc present?
skip_bits(bs, 8); // config_crc
latm->configured = 1;
return 0;
}

/**
Expand All @@ -188,7 +226,8 @@ parse_latm_audio_mux_element(service_t *t, elementary_stream_t *st,
latm = st->es_priv = calloc(1, sizeof(latm_private_t));

if(!read_bits1(&bs))
read_stream_mux_config(st, latm, &bs);
if (read_stream_mux_config(st, latm, &bs) < 0)
return NULL;

if(!latm->configured)
return NULL;
Expand All @@ -202,8 +241,7 @@ parse_latm_audio_mux_element(service_t *t, elementary_stream_t *st,
slot_len += tmp;
} while (tmp == 255);


if(slot_len * 8 > remaining_bits(&bs))
if (slot_len * 8 > remaining_bits(&bs))
return NULL;

if(st->es_curdts == PTS_UNSET)
Expand All @@ -214,16 +252,16 @@ parse_latm_audio_mux_element(service_t *t, elementary_stream_t *st,
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;
pkt->pkt_channels = latm->channel_config == 7 ? 8 : latm->channel_config;

/* 7 bytes of ADTS header */
init_wbits(&out, pktbuf_ptr(pkt->pkt_payload), 56);
init_wbits(&out, pktbuf_ptr(pkt->pkt_payload), 7 * 8);

put_bits(&out, 0xfff, 12); // Sync marker
put_bits(&out, 1, 1); // ID 0 = MPEG 4, 1 = MPEG 2
put_bits(&out, 0, 1); // ID 0 = MPEG 4, 1 = MPEG 2
put_bits(&out, 0, 2); // Layer
put_bits(&out, 1, 1); // Protection absent
put_bits(&out, 2, 2); // AOT, 2 = AAC LC (for MPEG 2 bit)
put_bits(&out, adts_aot(latm->aot), 2);
put_bits(&out, latm->sample_rate_index, 4);
put_bits(&out, 1, 1); // Private bit
put_bits(&out, latm->channel_config, 3);
Expand All @@ -233,7 +271,7 @@ parse_latm_audio_mux_element(service_t *t, elementary_stream_t *st,
put_bits(&out, 1, 1); // Copyright identification bit
put_bits(&out, 1, 1); // Copyright identification start
put_bits(&out, slot_len + 7, 13);
put_bits(&out, 0, 11); // Buffer fullness
put_bits(&out, 0x7ff, 11); // Buffer fullness
put_bits(&out, 0, 2); // RDB in frame

assert(remaining_bits(&out) == 0);
Expand Down

0 comments on commit cc1fbb0

Please sign in to comment.