diff --git a/src/capmt.c b/src/capmt.c index 3e008766..c7c29359 100644 --- a/src/capmt.c +++ b/src/capmt.c @@ -410,7 +410,7 @@ capmt_thread(void *aux) */ static void capmt_table_input(struct th_descrambler *td, struct th_transport *t, - struct th_stream *st, uint8_t *data, int len) + struct th_stream *st, const uint8_t *data, int len) { capmt_transport_t *ct = (capmt_transport_t *)td; capmt_t *capmt = ct->ct_capmt; @@ -572,7 +572,8 @@ capmt_table_input(struct th_descrambler *td, struct th_transport *t, * */ static int -capmt_descramble(th_descrambler_t *td, th_transport_t *t, struct th_stream *st, uint8_t *tsb) +capmt_descramble(th_descrambler_t *td, th_transport_t *t, struct th_stream *st, + const uint8_t *tsb) { capmt_transport_t *ct = (capmt_transport_t *)td; int r, i; diff --git a/src/cwc.c b/src/cwc.c index 1252401a..cefdb4c2 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -1045,7 +1045,7 @@ cwc_emm(uint8_t *data, int len) */ static void cwc_table_input(struct th_descrambler *td, struct th_transport *t, - struct th_stream *st, uint8_t *data, int len) + struct th_stream *st, const uint8_t *data, int len) { cwc_transport_t *ct = (cwc_transport_t *)td; uint16_t sid = t->tht_dvb_service_id; @@ -1130,7 +1130,7 @@ cwc_table_input(struct th_descrambler *td, struct th_transport *t, */ static int cwc_descramble(th_descrambler_t *td, th_transport_t *t, struct th_stream *st, - uint8_t *tsb) + const uint8_t *tsb) { cwc_transport_t *ct = (cwc_transport_t *)td; int r, i; diff --git a/src/iptv_input.c b/src/iptv_input.c index adc10e7c..3664bdba 100644 --- a/src/iptv_input.c +++ b/src/iptv_input.c @@ -55,7 +55,7 @@ static struct th_transport_list iptv_active_transports; /* Currently enabled */ * PAT parser. We only parse a single program. CRC has already been verified */ static void -iptv_got_pat(const uint8_t *ptr, int len, void *aux) +iptv_got_pat(const uint8_t *ptr, size_t len, void *aux) { th_transport_t *t = aux; uint16_t prognum, pmt; @@ -77,7 +77,7 @@ iptv_got_pat(const uint8_t *ptr, int len, void *aux) * PMT parser. CRC has already been verified */ static void -iptv_got_pmt(const uint8_t *ptr, int len, void *aux) +iptv_got_pmt(const uint8_t *ptr, size_t len, void *aux) { th_transport_t *t = aux; @@ -94,7 +94,7 @@ iptv_got_pmt(const uint8_t *ptr, int len, void *aux) * Handle a single TS packet for the given IPTV transport */ static void -iptv_ts_input(th_transport_t *t, uint8_t *tsb) +iptv_ts_input(th_transport_t *t, const uint8_t *tsb) { uint16_t pid = ((tsb[1] & 0x1f) << 8) | tsb[2]; @@ -102,13 +102,13 @@ iptv_ts_input(th_transport_t *t, uint8_t *tsb) if(t->tht_pat_section == NULL) t->tht_pat_section = calloc(1, sizeof(psi_section_t)); - psi_rawts_table_parser(t->tht_pat_section, tsb, iptv_got_pat, t); + psi_section_reassemble(t->tht_pat_section, tsb, 1, iptv_got_pat, t); } else if(pid == t->tht_pmt_pid) { if(t->tht_pmt_section == NULL) t->tht_pmt_section = calloc(1, sizeof(psi_section_t)); - psi_rawts_table_parser(t->tht_pmt_section, tsb, iptv_got_pmt, t); + psi_section_reassemble(t->tht_pmt_section, tsb, 1, iptv_got_pmt, t); } else { ts_recv_packet1(t, tsb, NULL); diff --git a/src/parsers.c b/src/parsers.c index 08c9df1c..ca6389ed 100644 --- a/src/parsers.c +++ b/src/parsers.c @@ -80,20 +80,20 @@ typedef int (vparser_t)(th_transport_t *t, th_stream_t *st, size_t len, typedef void (aparser_t)(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt); -static void parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data, +static void parse_video(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, vparser_t *vp); static void parse_audio_with_lavc(th_transport_t *t, th_stream_t *st, - uint8_t *data, int len, aparser_t *ap); + const uint8_t *data, int len, aparser_t *ap); -static void parse_audio(th_transport_t *t, th_stream_t *st, uint8_t *data, +static void parse_audio(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, int start, aparser_t *vp); -static void parse_aac(th_transport_t *t, th_stream_t *st, uint8_t *data, +static void parse_aac(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, int start); -static void parse_subtitles(th_transport_t *t, th_stream_t *st, uint8_t *data, - int len, int start); +static void parse_subtitles(th_transport_t *t, th_stream_t *st, + const uint8_t *data, int len, int start); static void parse_mpegaudio(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt); @@ -115,7 +115,7 @@ static void parser_compute_duration(th_transport_t *t, th_stream_t *st, * Parse raw mpeg data */ void -parse_mpeg_ts(th_transport_t *t, th_stream_t *st, uint8_t *data, +parse_mpeg_ts(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, int start, int err) { switch(st->st_type) { @@ -191,7 +191,7 @@ parse_mpeg_ps(th_transport_t *t, th_stream_t *st, uint8_t *data, int len) * Parse AAC LATM */ static void -parse_aac(th_transport_t *t, th_stream_t *st, uint8_t *data, +parse_aac(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, int start) { int l, muxlen, p; @@ -268,7 +268,7 @@ parse_aac(th_transport_t *t, th_stream_t *st, uint8_t *data, * derive further information. */ static void -parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data, int len, +parse_video(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, vparser_t *vp) { uint32_t sc; @@ -329,7 +329,7 @@ parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data, int len, * We then trust ffmpeg to parse and extract packets for use */ static void -parse_audio(th_transport_t *t, th_stream_t *st, uint8_t *data, +parse_audio(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, int start, aparser_t *ap) { int hlen; @@ -378,7 +378,7 @@ parse_audio(th_transport_t *t, th_stream_t *st, uint8_t *data, * Use libavcodec's parsers for audio parsing */ static void -parse_audio_with_lavc(th_transport_t *t, th_stream_t *st, uint8_t *data, +parse_audio_with_lavc(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, aparser_t *ap) { uint8_t *outbuf; @@ -846,7 +846,7 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len, * http://broadcasting.ru/pdf-standard-specifications/subtitling/dvb-sub/en300743.v1.2.1.pdf */ static void -parse_subtitles(th_transport_t *t, th_stream_t *st, uint8_t *data, +parse_subtitles(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, int start) { th_pkt_t *pkt; diff --git a/src/parsers.h b/src/parsers.h index f8ea2e90..9863b0c4 100644 --- a/src/parsers.h +++ b/src/parsers.h @@ -21,7 +21,7 @@ #include "packet.h" -void parse_mpeg_ts(th_transport_t *t, th_stream_t *st, uint8_t *data, +void parse_mpeg_ts(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len, int start, int err); void parse_mpeg_ps(th_transport_t *t, th_stream_t *st, uint8_t *data, int len); diff --git a/src/psi.c b/src/psi.c index 58c48e49..6cb7b4d6 100644 --- a/src/psi.c +++ b/src/psi.c @@ -32,64 +32,85 @@ #include "tsdemux.h" #include "parsers.h" -int -psi_section_reassemble(psi_section_t *ps, uint8_t *data, int len, - int start, int chkcrc) +static int +psi_section_reassemble0(psi_section_t *ps, const uint8_t *data, + int len, int start, int crc, + section_handler_t *cb, void *opaque) { - int remain, a, tsize; + int excess, tsize, s; - if(start) + if(start) { + // Payload unit start indicator ps->ps_offset = 0; + ps->ps_lock = 1; + } - if(ps->ps_offset < 0) + if(!ps->ps_lock) return -1; - remain = PSI_SECTION_SIZE - ps->ps_offset; + memcpy(ps->ps_data + ps->ps_offset, data, len); + ps->ps_offset += len; - a = FFMAX(0, FFMIN(remain, len)); + if(ps->ps_offset < 3) { + /* We don't know the total length yet */ + return len; + } - memcpy(ps->ps_data + ps->ps_offset, data, a); - ps->ps_offset += a; tsize = 3 + (((ps->ps_data[1] & 0xf) << 8) | ps->ps_data[2]); + if(ps->ps_offset < tsize) + return len; // Not there yet + + excess = ps->ps_offset - tsize; + + if(crc && psi_crc32(ps->ps_data, tsize)) return -1; - if(chkcrc && psi_crc32(ps->ps_data, tsize)) - return -1; + s = tsize - (crc ? 4 : 0); - ps->ps_offset = tsize - (chkcrc ? 4 : 0); - return 0; + cb(ps->ps_data, s, opaque); + return len - excess; } /** - * TS table parser + * */ void -psi_rawts_table_parser(psi_section_t *section, uint8_t *tsb, - void (*gotsection)(const uint8_t *data, int len, - void *opauqe), void *opaque) +psi_section_reassemble(psi_section_t *ps, const uint8_t *tsb, int crc, + section_handler_t *cb, void *opaque) { - int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4; + int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4; int pusi = tsb[1] & 0x40; - int len; + int r; - if(off >= 188) + if(off >= 188) { + ps->ps_lock = 0; return; - + } + if(pusi) { - len = tsb[off++]; + int len = tsb[off++]; if(len > 0) { - if(len > 188 - off) + if(len > 188 - off) { + ps->ps_lock = 0; return; - if(!psi_section_reassemble(section, tsb + off, len, 0, 1)) - gotsection(section->ps_data, section->ps_offset, opaque); + } + psi_section_reassemble0(ps, tsb + off, len, 0, crc, cb, opaque); off += len; } } - - if(!psi_section_reassemble(section, tsb + off, 188 - off, pusi, 1)) - gotsection(section->ps_data, section->ps_offset, opaque); + + while(off < 188 && tsb[off] != 0xff) { + r = psi_section_reassemble0(ps, tsb + off, 188 - off, pusi, crc, + cb, opaque); + if(r < 0) { + ps->ps_lock = 0; + break; + } + off += r; + pusi = 0; + } } diff --git a/src/psi.h b/src/psi.h index 6cb66f50..401f005a 100644 --- a/src/psi.h +++ b/src/psi.h @@ -22,16 +22,19 @@ #include "htsmsg.h" #include "streaming.h" -#define PSI_SECTION_SIZE 4096 +#define PSI_SECTION_SIZE 5000 + +typedef void (section_handler_t)(const uint8_t *data, size_t len, void *opaque); typedef struct psi_section { int ps_offset; + int ps_lock; uint8_t ps_data[PSI_SECTION_SIZE]; } psi_section_t; -int psi_section_reassemble(psi_section_t *ps, uint8_t *data, int len, - int pusi, int chkcrc); +void psi_section_reassemble(psi_section_t *ps, const uint8_t *tsb, int crc, + section_handler_t *cb, void *opaque); int psi_parse_pat(th_transport_t *t, uint8_t *ptr, int len, pid_section_callback_t *pmt_callback); @@ -50,8 +53,4 @@ const char *psi_caid2name(uint16_t caid); void psi_load_transport_settings(htsmsg_t *m, th_transport_t *t); void psi_save_transport_settings(htsmsg_t *m, th_transport_t *t); -void psi_rawts_table_parser(psi_section_t *section, uint8_t *tsb, - void (*gotsection)(const uint8_t *data, int len, - void *opauqe), void *opaque); - #endif /* PSI_H_ */ diff --git a/src/rawtsinput.c b/src/rawtsinput.c index b2062e3f..8ee5c67e 100644 --- a/src/rawtsinput.c +++ b/src/rawtsinput.c @@ -147,7 +147,7 @@ rawts_transport_add(rawts_t *rt, uint16_t sid, int pmt_pid) static void got_pmt(struct th_transport *t, th_stream_t *st, - uint8_t *table, int table_len) + const uint8_t *table, int table_len) { if(table[0] != 2) return; @@ -163,12 +163,11 @@ got_pmt(struct th_transport *t, th_stream_t *st, * */ static void -got_pat(rawts_t *rt) +got_pat(const uint8_t *ptr, size_t len, void *opaque) { + rawts_t *rt = opaque; th_transport_t *t; th_stream_t *st; - int len = rt->rt_pat.ps_offset; - uint8_t *ptr = rt->rt_pat.ps_data; uint16_t prognum; uint16_t pid; @@ -209,28 +208,9 @@ got_pat(rawts_t *rt) * */ static void -rawts_pat(rawts_t *rt, uint8_t *tsb) +rawts_pat(rawts_t *rt, const uint8_t *tsb) { - int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4; - int pusi = tsb[1] & 0x40; - int len; - - if(off >= 188) - return; - - if(pusi) { - len = tsb[off++]; - if(len > 0) { - if(len > 188 - off) - return; - if(!psi_section_reassemble(&rt->rt_pat, tsb + off, len, 0, 1)) - got_pat(rt); - off += len; - } - } - - if(!psi_section_reassemble(&rt->rt_pat, tsb + off, 188 - off, pusi, 1)) - got_pat(rt); + psi_section_reassemble(&rt->rt_pat, tsb, 1, got_pat, rt); } diff --git a/src/teletext.c b/src/teletext.c index e72938dc..f1b51157 100644 --- a/src/teletext.c +++ b/src/teletext.c @@ -306,10 +306,11 @@ tt_decode_line(th_transport_t *t, th_stream_t *st, uint8_t *buf) * */ void -teletext_input(th_transport_t *t, th_stream_t *st, uint8_t *tsb) +teletext_input(th_transport_t *t, th_stream_t *st, const uint8_t *tsb) { int i, j; - uint8_t *x, buf[42]; + const uint8_t *x; + uint8_t buf[42]; x = tsb + 4; for(i = 0; i < 4; i++) { diff --git a/src/teletext.h b/src/teletext.h index fe225152..e826aea2 100644 --- a/src/teletext.h +++ b/src/teletext.h @@ -19,6 +19,6 @@ #ifndef TELETEXT_H #define TELETEXT_H -void teletext_input(th_transport_t *t, th_stream_t *st, uint8_t *tsb); +void teletext_input(th_transport_t *t, th_stream_t *st, const uint8_t *tsb); #endif /* TELETEXT_H */ diff --git a/src/transports.c b/src/transports.c index 5da375d0..55a45da2 100644 --- a/src/transports.c +++ b/src/transports.c @@ -698,6 +698,7 @@ transport_stream_create(th_transport_t *t, int pid, st->st_type = type; LIST_INSERT_HEAD(&t->tht_components, st, st_link); + st->st_transport = t; st->st_pid = pid; st->st_demuxer_fd = -1; diff --git a/src/tsdemux.c b/src/tsdemux.c index 3beb76b8..a8f5cb01 100644 --- a/src/tsdemux.c +++ b/src/tsdemux.c @@ -50,17 +50,17 @@ static void ts_remux(th_transport_t *t, const uint8_t *tsb); * Code for dealing with a complete section */ static void -got_section(th_transport_t *t, th_stream_t *st) +got_section(const uint8_t *data, size_t len, void *opaque) { th_descrambler_t *td; + th_stream_t *st = opaque; + th_transport_t *t = st->st_transport; if(st->st_type == SCT_CA) { LIST_FOREACH(td, &t->tht_descramblers, td_transport_link) - td->td_table(td, t, st, - st->st_section->ps_data, st->st_section->ps_offset); + td->td_table(td, t, st, data, len); } else if(st->st_got_section != NULL) { - st->st_got_section(t, st, st->st_section->ps_data, - st->st_section->ps_offset); + st->st_got_section(t, st, data, len); } } @@ -69,9 +69,9 @@ got_section(th_transport_t *t, th_stream_t *st) * Continue processing of transport stream packets */ static void -ts_recv_packet0(th_transport_t *t, th_stream_t *st, uint8_t *tsb) +ts_recv_packet0(th_transport_t *t, th_stream_t *st, const uint8_t *tsb) { - int off, len, pusi, cc, err = 0; + int off, pusi, cc, err = 0; transport_set_streaming_status_flags(t, TSS_MUX_PACKETS); @@ -105,26 +105,8 @@ ts_recv_packet0(th_transport_t *t, th_stream_t *st, uint8_t *tsb) if(st->st_section == NULL) st->st_section = calloc(1, sizeof(struct psi_section)); - if(err || off >= 188) { - st->st_section->ps_offset = -1; /* hold parser until next pusi */ - break; - } - - if(pusi) { - len = tsb[off++]; - if(len > 0) { - if(len > 188 - off) - break; - if(!psi_section_reassemble(st->st_section, tsb + off, len, 0, - st->st_section_docrc)) - got_section(t, st); - off += len; - } - } - - if(!psi_section_reassemble(st->st_section, tsb + off, 188 - off, pusi, - st->st_section_docrc)) - got_section(t, st); + psi_section_reassemble(st->st_section, tsb, st->st_section_docrc, + got_section, st); break; case SCT_TELETEXT: @@ -150,7 +132,7 @@ static const AVRational mpeg_tc = {1, 90000}; * than the stream PCR */ static void -ts_extract_pcr(th_transport_t *t, th_stream_t *st, uint8_t *tsb, +ts_extract_pcr(th_transport_t *t, th_stream_t *st, const uint8_t *tsb, int64_t *pcrp) { int64_t real, pcr, d; @@ -200,7 +182,7 @@ ts_extract_pcr(th_transport_t *t, th_stream_t *st, uint8_t *tsb, * Process transport stream packets, extract PCR and optionally descramble */ void -ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp) +ts_recv_packet1(th_transport_t *t, const uint8_t *tsb, int64_t *pcrp) { th_stream_t *st; int pid, n, m, r; @@ -273,7 +255,7 @@ ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp) * Process transport stream packets, simple version */ void -ts_recv_packet2(th_transport_t *t, uint8_t *tsb) +ts_recv_packet2(th_transport_t *t, const uint8_t *tsb) { th_stream_t *st; int pid = (tsb[1] & 0x1f) << 8 | tsb[2]; diff --git a/src/tsdemux.h b/src/tsdemux.h index d6b9c428..17e4176f 100644 --- a/src/tsdemux.h +++ b/src/tsdemux.h @@ -19,8 +19,8 @@ #ifndef TSDEMUX_H #define TSDEMUX_H -void ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp); +void ts_recv_packet1(th_transport_t *t, const uint8_t *tsb, int64_t *pcrp); -void ts_recv_packet2(th_transport_t *t, uint8_t *tsb); +void ts_recv_packet2(th_transport_t *t, const uint8_t *tsb); #endif /* TSDEMUX_H */ diff --git a/src/tvhead.h b/src/tvhead.h index a5e05b1d..184cf3a3 100644 --- a/src/tvhead.h +++ b/src/tvhead.h @@ -253,10 +253,11 @@ typedef struct th_descrambler { LIST_ENTRY(th_descrambler) td_transport_link; void (*td_table)(struct th_descrambler *d, struct th_transport *t, - struct th_stream *st, uint8_t *section, int section_len); + struct th_stream *st, + const uint8_t *section, int section_len); int (*td_descramble)(struct th_descrambler *d, struct th_transport *t, - struct th_stream *st, uint8_t *tsb); + struct th_stream *st, const uint8_t *tsb); void (*td_stop)(struct th_descrambler *d); @@ -269,7 +270,7 @@ typedef struct th_descrambler { */ typedef void (pid_section_callback_t)(struct th_transport *t, struct th_stream *pi, - uint8_t *section, int section_len); + const uint8_t *section, int section_len); /* * Stream, one media component for a transport. @@ -279,7 +280,8 @@ typedef void (pid_section_callback_t)(struct th_transport *t, typedef struct th_stream { LIST_ENTRY(th_stream) st_link; - + struct th_transport *st_transport; + streaming_component_type_t st_type; int st_index;