diff --git a/cwc.c b/cwc.c index f537f537..8a30ace2 100644 --- a/cwc.c +++ b/cwc.c @@ -716,7 +716,7 @@ cwc_descramble(th_descrambler_t *td, th_transport_t *t, struct th_stream *st, if(r == 0) break; for(i = 0; i < r; i++) { - ts_recv_packet(t, (t0[1] & 0x1f) << 8 | t0[2], t0, 0); + ts_recv_packet2(t, t0); t0 += 188; } } diff --git a/dvb_dvr.c b/dvb_dvr.c index 2d4f3936..f36aceeb 100644 --- a/dvb_dvr.c +++ b/dvb_dvr.c @@ -68,13 +68,11 @@ dvb_dvr_init(th_dvb_adapter_t *tda) static void dvb_dvr_process_packets(th_dvb_adapter_t *tda, uint8_t *tsb, int r) { - int pid; th_transport_t *t; while(r >= 188) { - pid = (tsb[1] & 0x1f) << 8 | tsb[2]; LIST_FOREACH(t, &tda->tda_transports, tht_adapter_link) - ts_recv_packet(t, pid, tsb, 1); + ts_recv_packet1(t, tsb); r -= 188; tsb += 188; } diff --git a/iptv_input.c b/iptv_input.c index c0711f1b..eadf3741 100644 --- a/iptv_input.c +++ b/iptv_input.c @@ -55,14 +55,13 @@ iptv_fd_callback(int events, void *opaque, int fd) { th_transport_t *t = opaque; uint8_t buf[2000]; - int r, pid; + int r; uint8_t *tsb = buf; r = read(fd, buf, sizeof(buf)); while(r >= 188) { - pid = (tsb[1] & 0x1f) << 8 | tsb[2]; - ts_recv_packet(t, pid, tsb, 1); + ts_recv_packet1(t, tsb); r -= 188; tsb += 188; } diff --git a/tsdemux.c b/tsdemux.c index 5a4f04fc..1ed44058 100644 --- a/tsdemux.c +++ b/tsdemux.c @@ -70,42 +70,22 @@ got_section(th_transport_t *t, th_stream_t *st) -/* - * Process transport stream packets +/** + * Continue processing of transport stream packets */ -void -ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int dodescramble) +static void +ts_recv_packet0(th_transport_t *t, th_stream_t *st, uint8_t *tsb) { - th_stream_t *st = NULL; th_subscription_t *s; - int cc, err = 0, afc, afl = 0; - int len, pusi; - th_descrambler_t *td; - - LIST_FOREACH(st, &t->tht_streams, st_link) - if(st->st_pid == pid) - break; - - if(st == NULL) - return; - - if(((tsb[3] >> 6) & 3) && dodescramble) - LIST_FOREACH(td, &t->tht_descramblers, td_transport_link) - if(td->td_descramble(td, t, st, tsb)) - return; - - avgstat_add(&t->tht_rate, 188, dispatch_clock); - if((tsb[3] >> 6) & 3) - return; /* channel is encrypted */ - + int off, len, pusi, cc, err = 0; LIST_FOREACH(s, &t->tht_subscriptions, ths_transport_link) if(s->ths_raw_input != NULL) s->ths_raw_input(s, tsb, 188, st, s->ths_opaque); - afc = (tsb[3] >> 4) & 3; + /* Check CC */ - if(afc & 1) { + if(tsb[3] & 0x10) { cc = tsb[3] & 0xf; if(st->st_cc_valid && cc != st->st_cc) { /* Incorrect CC */ @@ -117,38 +97,33 @@ ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int dodescramble) st->st_cc = (cc + 1) & 0xf; } - - if(afc & 2) - afl = tsb[4] + 1; - + off = tsb[3] & 0x20 ? tsb[4] + 5 : 4; pusi = tsb[1] & 0x40; - afl += 4; - switch(st->st_type) { case HTSTV_TABLE: if(st->st_section == NULL) st->st_section = calloc(1, sizeof(struct psi_section)); - if(err || afl >= 188) { + if(err || off >= 188) { st->st_section->ps_offset = -1; /* hold parser until next pusi */ break; } if(pusi) { - len = tsb[afl++]; + len = tsb[off++]; if(len > 0) { - if(len > 188 - afl) + if(len > 188 - off) break; - if(!psi_section_reassemble(st->st_section, tsb + afl, len, 0, + if(!psi_section_reassemble(st->st_section, tsb + off, len, 0, st->st_section_docrc)) got_section(t, st); - afl += len; + off += len; } } - if(!psi_section_reassemble(st->st_section, tsb + afl, 188 - afl, pusi, + if(!psi_section_reassemble(st->st_section, tsb + off, 188 - off, pusi, st->st_section_docrc)) got_section(t, st); break; @@ -158,10 +133,110 @@ ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int dodescramble) break; default: - if(afl > 188) + if(off > 188) break; - parse_raw_mpeg(t, st, tsb + afl, 188 - afl, pusi, err); + parse_raw_mpeg(t, st, tsb + off, 188 - off, pusi, err); break; } } + + +/** + * Process transport stream packets, extract PCR and optionally descramble + */ +static void +ts_extract_pcr(th_transport_t *t, th_stream_t *st, uint8_t *tsb) +{ + int64_t real = getclock_hires(); + int64_t pcr; + + pcr = tsb[6] << 25; + pcr |= tsb[7] << 17; + pcr |= tsb[8] << 9; + pcr |= tsb[9] << 1; + pcr |= (tsb[10] >> 7) & 0x01; + + pcr = av_rescale_q(pcr, st->st_tb, AV_TIME_BASE_Q); + + + { + static int64_t pcr0; + static int64_t real0, dv; + + int64_t pcr_d, real_d, dx; + + pcr_d = pcr - pcr0; + real_d = real - real0; + + dx = pcr_d - real_d; + + if(real0 && dx > -1000000LL && dx < 1000000LL) + dv += dx; +#if 0 + printf("B: realtime = %-12lld pcr = %-12lld delta = %lld\n", + real_d, pcr_d, dv / 1000); +#endif + pcr0 = pcr; + real0 = real; + } +} + +/** + * Process transport stream packets, extract PCR and optionally descramble + */ +void +ts_recv_packet1(th_transport_t *t, uint8_t *tsb) +{ + th_stream_t *st; + int pid; + th_descrambler_t *td; + + pid = (tsb[1] & 0x1f) << 8 | tsb[2]; + + LIST_FOREACH(st, &t->tht_streams, st_link) + if(st->st_pid == pid) + break; + + if(st == NULL) + return; + + avgstat_add(&t->tht_rate, 188, dispatch_clock); + + /* Extract PCR */ + if(tsb[3] & 0x20 && tsb[4] > 0 && tsb[5] & 0x10) + ts_extract_pcr(t, st, tsb); + + + if(tsb[3] & 0xc0) { + /* scrambled stream */ + LIST_FOREACH(td, &t->tht_descramblers, td_transport_link) + if(td->td_descramble(td, t, st, tsb)) + break; + + return; + } + + ts_recv_packet0(t, st, tsb); +} + + +/* + * Process transport stream packets, simple version + */ +void +ts_recv_packet2(th_transport_t *t, uint8_t *tsb) +{ + th_stream_t *st; + int pid; + + pid = (tsb[1] & 0x1f) << 8 | tsb[2]; + LIST_FOREACH(st, &t->tht_streams, st_link) + if(st->st_pid == pid) + break; + + if(st == NULL) + return; + + ts_recv_packet0(t, st, tsb); +} diff --git a/tsdemux.h b/tsdemux.h index acce4320..108dfcd5 100644 --- a/tsdemux.h +++ b/tsdemux.h @@ -19,6 +19,8 @@ #ifndef TSDEMUX_H #define TSDEMUX_H -void ts_recv_packet(th_transport_t *t, int pid, uint8_t *tsb, int doplugin); +void ts_recv_packet1(th_transport_t *t, uint8_t *tsb); + +void ts_recv_packet2(th_transport_t *t, uint8_t *tsb); #endif /* TSDEMUX_H */