int configured;
int audio_mux_version_A;
+ int aot;
int frame_length_type;
int sample_rate_index;
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);
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;
}
/**
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;
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)
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);
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);
parse_aac(service_t *t, elementary_stream_t *st, const uint8_t *data,
int len, int start)
{
- int l, muxlen, p;
+ int l, muxlen, p, hdr = 0;
th_pkt_t *pkt;
-
- if(start) {
- /* Payload unit start */
- st->es_parser_state = 1;
- st->es_parser_ptr = 0;
- sbuf_reset(&st->es_buf, 4000);
+ int64_t olddts = PTS_UNSET, oldpts = PTS_UNSET;
+ int64_t newdts = PTS_UNSET, newpts = PTS_UNSET;
+
+ if(st->es_parser_state == 0) {
+ if (start) {
+ /* Payload unit start */
+ st->es_parser_state = 1;
+ st->es_parser_ptr = 0;
+ sbuf_reset(&st->es_buf, 4000);
+ } else {
+ return;
+ }
}
- if(st->es_parser_state == 0)
- return;
-
- sbuf_append(&st->es_buf, data, len);
-
- if(st->es_parser_ptr == 0) {
+ if(start) {
int hlen;
- if(st->es_buf.sb_ptr < 9)
+ if(len < 9)
return;
- hlen = parse_pes_header(t, st,
- st->es_buf.sb_data + 6, st->es_buf.sb_ptr - 6);
+ olddts = st->es_curdts;
+ oldpts = st->es_curpts;
+ hlen = parse_pes_header(t, st, data + 6, len - 6);
+ if (hlen >= 0 && st->es_buf.sb_ptr) {
+ newdts = st->es_curdts;
+ newpts = st->es_curpts;
+ st->es_curdts = olddts;
+ st->es_curpts = oldpts;
+ }
+
if(hlen < 0)
return;
- st->es_parser_ptr += 6 + hlen;
+
+ data += 6 + hlen;
+ len -= 6 + hlen;
}
- p = st->es_parser_ptr;
+ sbuf_append(&st->es_buf, data, len);
+
+ p = 0;
while((l = st->es_buf.sb_ptr - p) > 3) {
const uint8_t *d = st->es_buf.sb_data + p;
st->es_buf.sb_err = 0;
}
+ if (hdr && newdts != PTS_UNSET) {
+ st->es_curdts = newdts;
+ st->es_curpts = newpts;
+ }
p += muxlen + 3;
/* ADTS */
- } else if(d[0] == 0xff && (d[1] & 0xf0) == 0xf0) {
+ } else if(p == 0 && d[0] == 0xff && (d[1] & 0xf0) == 0xf0) {
if (l < 7)
break;
+
muxlen = ((uint16_t)(d[3] & 0x03) << 11) | ((uint16_t)d[4] << 3) | (d[5] >> 5);
if (l < muxlen)
break;
sbuf_append(&st->es_buf_a, d, muxlen);
parse_mp4a_data(t, st, 1);
+ if (hdr && newdts != PTS_UNSET) {
+ st->es_curdts = newdts;
+ st->es_curpts = newpts;
+ }
p += muxlen;
/* Wrong bytestream */
}
}
- st->es_parser_ptr = p;
+ if (hdr && newdts != PTS_UNSET) {
+ st->es_curdts = newdts;
+ st->es_curpts = newpts;
+ }
+ if (p > 0)
+ sbuf_cut(&st->es_buf, p);
}
return 1;
}
-
const static int mpa_br[16] = {
0, 32, 48, 56,
64, 80, 96, 112,
pts = getpts(buf);
dts = getpts(buf + 5);
-
d = (pts - dts) & PTS_MASK;
if(d > 180000) // More than two seconds of PTS/DTS delta, probably corrupt
pts = dts = PTS_UNSET;
init_wbits(&bs, pktbuf_ptr(pb), 56);
put_bits(&bs, 0xfff, 12); // Sync marker
- put_bits(&bs, 1, 1); // ID 0 = MPEG 4, 1 = MPEG 2
+ put_bits(&bs, 0, 1); // ID 0 = MPEG 4, 1 = MPEG 2
put_bits(&bs, 0, 2); // Layer
put_bits(&bs, 1, 1); // Protection absent
- put_bits(&bs, 2, 2); // AOT, 2 = AAC LC (for MPEG 2 bit)
+ put_bits(&bs, 1, 2); // AOT, 1 = AAC LC
put_bits(&bs, sri, 4);
put_bits(&bs, 1, 1); // Private bit
put_bits(&bs, channels, 3);
put_bits(&bs, 1, 1); // Copyright identification bit
put_bits(&bs, 1, 1); // Copyright identification start
put_bits(&bs, pktbuf_len(pb), 13);
- put_bits(&bs, 0, 11); // Buffer fullness
+ put_bits(&bs, 0x7ff, 11); // Buffer fullness
put_bits(&bs, 0, 2); // RDB in frame
}