Merge pull request #41 from mikrohard/master
Parsing support for AAC streams inside mp4a containers.
This commit is contained in:
commit
fdf89b2768
7 changed files with 106 additions and 8 deletions
|
@ -215,6 +215,7 @@ mk_build_tracks(mk_mux_t *mkm, const struct streaming_start *ss)
|
|||
codec_id = "A_EAC3";
|
||||
break;
|
||||
|
||||
case SCT_MP4A:
|
||||
case SCT_AAC:
|
||||
tracktype = 2;
|
||||
codec_id = "A_AAC";
|
||||
|
@ -252,6 +253,7 @@ mk_build_tracks(mk_mux_t *mkm, const struct streaming_start *ss)
|
|||
switch(ssc->ssc_type) {
|
||||
case SCT_H264:
|
||||
case SCT_MPEG2VIDEO:
|
||||
case SCT_MP4A:
|
||||
case SCT_AAC:
|
||||
if(ssc->ssc_gh)
|
||||
ebml_append_bin(t, 0x63a2,
|
||||
|
@ -723,7 +725,7 @@ mk_write_frame_i(mk_mux_t *mkm, mk_track *t, th_pkt_t *pkt)
|
|||
data = pktbuf_ptr(pkt->pkt_payload);
|
||||
len = pktbuf_len(pkt->pkt_payload);
|
||||
|
||||
if(t->type == SCT_AAC) {
|
||||
if(t->type == SCT_AAC || t->type == SCT_MP4A) {
|
||||
// Skip ADTS header
|
||||
if(len < 7)
|
||||
return;
|
||||
|
|
|
@ -113,6 +113,9 @@ static int parse_ac3(service_t *t, elementary_stream_t *st, size_t len,
|
|||
static int parse_eac3(service_t *t, elementary_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset);
|
||||
|
||||
static int parse_mp4a(service_t *t, elementary_stream_t *st, size_t ilen,
|
||||
uint32_t next_startcode, int sc_offset);
|
||||
|
||||
static void parser_deliver(service_t *t, elementary_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
static int parse_pes_header(service_t *t, elementary_stream_t *st,
|
||||
|
@ -150,6 +153,10 @@ parse_mpeg_ts(service_t *t, elementary_stream_t *st, const uint8_t *data,
|
|||
parse_sc(t, st, data, len, parse_eac3);
|
||||
break;
|
||||
|
||||
case SCT_MP4A:
|
||||
parse_sc(t, st, data, len, parse_mp4a);
|
||||
break;
|
||||
|
||||
case SCT_DVBSUB:
|
||||
parse_subtitles(t, st, data, len, start);
|
||||
break;
|
||||
|
@ -263,9 +270,6 @@ parse_aac(service_t *t, elementary_stream_t *st, const uint8_t *data,
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generic video parser
|
||||
*
|
||||
|
@ -429,7 +433,80 @@ makeapkt(service_t *t, elementary_stream_t *st, const void *buf,
|
|||
st->es_curdts = PTS_UNSET;
|
||||
st->es_nextdts = dts + duration;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse AAC MP4A
|
||||
*/
|
||||
|
||||
static const int aac_sample_rates[12] =
|
||||
{
|
||||
96000,
|
||||
88200,
|
||||
64000,
|
||||
48000,
|
||||
44100,
|
||||
32000,
|
||||
24000,
|
||||
22050,
|
||||
16000,
|
||||
12000,
|
||||
11025,
|
||||
8000
|
||||
};
|
||||
|
||||
/**
|
||||
* Inspect ADTS header
|
||||
*/
|
||||
static int
|
||||
mp4a_valid_frame(const uint8_t *buf)
|
||||
{
|
||||
return (buf[0] == 0xff) && ((buf[1] & 0xf6) == 0xf0);
|
||||
}
|
||||
|
||||
static int parse_mp4a(service_t *t, elementary_stream_t *st, size_t ilen,
|
||||
uint32_t next_startcode, int sc_offset)
|
||||
{
|
||||
int i, len;
|
||||
const uint8_t *buf;
|
||||
|
||||
if((i = depacketize(t, st, ilen, next_startcode, sc_offset)) != 0)
|
||||
return i;
|
||||
|
||||
again:
|
||||
buf = st->es_buf_a.sb_data;
|
||||
len = st->es_buf_a.sb_ptr;
|
||||
|
||||
for(i = 0; i < len - 6; i++) {
|
||||
const uint8_t *p = buf + i;
|
||||
if(mp4a_valid_frame(p)) {
|
||||
|
||||
int fsize = ((p[3] & 0x03) << 11) | (p[4] << 3) | ((p[5] & 0xe0) >> 5);
|
||||
int sr_index = (p[2] & 0x3c) >> 2;
|
||||
int sr = aac_sample_rates[sr_index];
|
||||
|
||||
|
||||
if(sr && fsize) {
|
||||
int duration = 90000 * 1024 / sr;
|
||||
int64_t dts = st->es_curdts;
|
||||
int sri = rate_to_sri(sr);
|
||||
|
||||
if(dts == PTS_UNSET)
|
||||
dts = st->es_nextdts;
|
||||
|
||||
if(dts != PTS_UNSET && len >= i + fsize + 6 &&
|
||||
mp4a_valid_frame(p + fsize)) {
|
||||
|
||||
int channels = ((p[2] & 0x01) << 2) | ((p[3] & 0xc0) >> 6);
|
||||
|
||||
makeapkt(t, st, p, fsize, dts, duration, channels, sri);
|
||||
sbuf_cut(&st->es_buf_a, i + fsize);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
const static int mpa_br[16] = {
|
||||
|
|
|
@ -79,6 +79,7 @@ apply_header(streaming_start_component_t *ssc, th_pkt_t *pkt)
|
|||
return;
|
||||
|
||||
switch(ssc->ssc_type) {
|
||||
case SCT_MP4A:
|
||||
case SCT_AAC:
|
||||
ssc->ssc_gh = pktbuf_alloc(NULL, 2);
|
||||
d = pktbuf_ptr(ssc->ssc_gh);
|
||||
|
@ -122,6 +123,7 @@ header_complete(streaming_start_component_t *ssc, int not_so_picky)
|
|||
if(ssc->ssc_gh == NULL &&
|
||||
(ssc->ssc_type == SCT_H264 ||
|
||||
ssc->ssc_type == SCT_MPEG2VIDEO ||
|
||||
ssc->ssc_type == SCT_MP4A ||
|
||||
ssc->ssc_type == SCT_AAC))
|
||||
return 0;
|
||||
return 1;
|
||||
|
|
17
src/psi.c
17
src/psi.c
|
@ -519,6 +519,10 @@ psi_parse_pmt(service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
case 0x81:
|
||||
hts_stream_type = SCT_AC3;
|
||||
break;
|
||||
|
||||
case 0x0f:
|
||||
hts_stream_type = SCT_MP4A;
|
||||
break;
|
||||
|
||||
case 0x11:
|
||||
hts_stream_type = SCT_AAC;
|
||||
|
@ -568,7 +572,9 @@ psi_parse_pmt(service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
break;
|
||||
|
||||
case DVB_DESC_AAC:
|
||||
if(estype == 0x11)
|
||||
if(estype == 0x0f)
|
||||
hts_stream_type = SCT_MP4A;
|
||||
else if(estype == 0x11)
|
||||
hts_stream_type = SCT_AAC;
|
||||
break;
|
||||
|
||||
|
@ -592,7 +598,6 @@ psi_parse_pmt(service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
}
|
||||
len -= dlen; ptr += dlen; dllen -= dlen;
|
||||
}
|
||||
|
||||
|
||||
if(hts_stream_type == SCT_UNKNOWN && estype == 0x06 &&
|
||||
pid == 3401 && t->s_dvb_service_id == 10510) {
|
||||
|
@ -607,6 +612,11 @@ psi_parse_pmt(service_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
st = service_stream_create(t, pid, hts_stream_type);
|
||||
}
|
||||
|
||||
// Jernej: I don't know why. But it seems that sometimes the stream is created with a wrong es_type??
|
||||
if(st->es_type != hts_stream_type) {
|
||||
st->es_type = hts_stream_type;
|
||||
}
|
||||
|
||||
st->es_delete_me = 0;
|
||||
|
||||
if(st->es_position != position) {
|
||||
|
@ -736,6 +746,7 @@ psi_build_pmt(streaming_start_t *ss, uint8_t *buf0, int maxlen, int pcrpid)
|
|||
c = 0x06;
|
||||
break;
|
||||
|
||||
case SCT_MP4A:
|
||||
case SCT_AAC:
|
||||
c = 0x11;
|
||||
break;
|
||||
|
@ -764,6 +775,7 @@ psi_build_pmt(streaming_start_t *ss, uint8_t *buf0, int maxlen, int pcrpid)
|
|||
|
||||
switch(ssc->ssc_type) {
|
||||
case SCT_MPEG2AUDIO:
|
||||
case SCT_MP4A:
|
||||
case SCT_AAC:
|
||||
buf[0] = DVB_DESC_LANGUAGE;
|
||||
buf[1] = 4;
|
||||
|
@ -886,6 +898,7 @@ static struct strtab streamtypetab[] = {
|
|||
{ "MPEGTS", SCT_MPEGTS },
|
||||
{ "TEXTSUB", SCT_TEXTSUB },
|
||||
{ "EAC3", SCT_EAC3 },
|
||||
{ "AAC", SCT_MP4A },
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -605,6 +605,7 @@ service_stream_create(service_t *t, int pid,
|
|||
|
||||
st = calloc(1, sizeof(elementary_stream_t));
|
||||
st->es_index = idx + 1;
|
||||
|
||||
st->es_type = type;
|
||||
|
||||
TAILQ_INSERT_TAIL(&t->s_components, st, es_link);
|
||||
|
@ -854,6 +855,7 @@ service_build_stream_start(service_t *t)
|
|||
streaming_start_component_t *ssc = &ss->ss_components[n++];
|
||||
ssc->ssc_index = st->es_index;
|
||||
ssc->ssc_type = st->es_type;
|
||||
|
||||
memcpy(ssc->ssc_lang, st->es_lang, 4);
|
||||
ssc->ssc_composition_id = st->es_composition_id;
|
||||
ssc->ssc_ancillary_id = st->es_ancillary_id;
|
||||
|
|
|
@ -163,11 +163,12 @@ typedef enum {
|
|||
SCT_MPEGTS,
|
||||
SCT_TEXTSUB,
|
||||
SCT_EAC3,
|
||||
SCT_MP4A,
|
||||
} streaming_component_type_t;
|
||||
|
||||
#define SCT_ISVIDEO(t) ((t) == SCT_MPEG2VIDEO || (t) == SCT_H264)
|
||||
#define SCT_ISAUDIO(t) ((t) == SCT_MPEG2AUDIO || (t) == SCT_AC3 || \
|
||||
(t) == SCT_AAC)
|
||||
(t) == SCT_AAC || (t) == SCT_MP4A)
|
||||
|
||||
/**
|
||||
* The signal status of a tuner
|
||||
|
|
|
@ -1189,6 +1189,7 @@ extjs_servicedetails(http_connection_t *hc,
|
|||
break;
|
||||
|
||||
case SCT_AC3:
|
||||
case SCT_MP4A:
|
||||
case SCT_AAC:
|
||||
case SCT_MPEG2AUDIO:
|
||||
htsmsg_add_str(c, "details", st->es_lang);
|
||||
|
|
Loading…
Add table
Reference in a new issue