From ae0b0965d6bba74c9036ea11feffb7d5bcceee58 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Fri, 31 Aug 2012 23:12:07 +0100 Subject: [PATCH] Fix dvr input if sync is lost, also minor efficiency improvement. --- src/dvb/dvb_adapter.c | 60 +++++++++++++++++++++++++++++++++---------- src/tsdemux.c | 15 +++++++++++ src/tsdemux.h | 2 ++ 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index 9e714e93..5557a4fe 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -701,7 +701,7 @@ static void * dvb_adapter_input_dvr(void *aux) { th_dvb_adapter_t *tda = aux; - int fd, i, r, efd, nfds; + int fd, i, r, c, efd, nfds; uint8_t tsb[188 * 10]; service_t *t; struct epoll_event ev; @@ -720,34 +720,68 @@ dvb_adapter_input_dvr(void *aux) ev.data.fd = tda->tda_dvr_pipe[0]; epoll_ctl(efd, EPOLL_CTL_ADD, tda->tda_dvr_pipe[0], &ev); - while(1){ + r = i = 0; + while(1) { /* Wait for input */ nfds = epoll_wait(efd, &ev, 1, -1); if (nfds < 1) continue; if (ev.data.fd != fd) break; - r = read(fd, tsb, sizeof(tsb)); + c = read(fd, tsb+r, sizeof(tsb)-r); + if (c < 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + else + break; + } + r += c; + + /* not enough data */ + if (r < 188) continue; pthread_mutex_lock(&tda->tda_delivery_mutex); - - for(i = 0; i < r; i += 188) { - LIST_FOREACH(t, &tda->tda_transports, s_active_link) - if(t->s_dvb_mux_instance == tda->tda_mux_current) - ts_recv_packet1(t, tsb + i, NULL); - } + /* debug */ if(tda->tda_dump_fd != -1) { if(write(tda->tda_dump_fd, tsb, r) != r) { tvhlog(LOG_ERR, "dvb", - "\"%s\" unable to write to mux dump file -- %s", - tda->tda_identifier, strerror(errno)); - close(tda->tda_dump_fd); - tda->tda_dump_fd = -1; + "\"%s\" unable to write to mux dump file -- %s", + tda->tda_identifier, strerror(errno)); + close(tda->tda_dump_fd); + tda->tda_dump_fd = -1; + } + } + + /* find mux */ + LIST_FOREACH(t, &tda->tda_transports, s_active_link) + if(t->s_dvb_mux_instance == tda->tda_mux_current) + break; + + /* Process */ + while (r >= 188) { + + /* sync */ + if (tsb[i] == 0x47) { + if(t) ts_recv_packet1(t, tsb + i, NULL); + i += 188; + r -= 188; + + /* no sync */ + } else { + tvhlog(LOG_DEBUG, "dvb", "\"%s\" ts sync lost", tda->tda_identifier); + if (ts_resync(tsb, &r, &i)) break; + tvhlog(LOG_DEBUG, "dvb", "\"%s\" ts sync found", tda->tda_identifier); } } pthread_mutex_unlock(&tda->tda_delivery_mutex); + + /* reset buffer */ + if (r && r < i) { + memcpy(tsb, tsb+i, r); + i = 0; + } } close(efd); diff --git a/src/tsdemux.c b/src/tsdemux.c index afd0eded..89e016a5 100644 --- a/src/tsdemux.c +++ b/src/tsdemux.c @@ -286,3 +286,18 @@ ts_remux(service_t *t, const uint8_t *src) sm.sm_data = tsb; streaming_pad_deliver(&t->s_streaming_pad, &sm); } + +/* + * Attempt to re-sync a ts stream (3 valid sync's in a row) + */ +int +ts_resync ( const uint8_t *tsb, int *len, int *idx ) +{ + int err = 1; + while (err && (*len > 376)) { + (*idx)++; (*len)--; + err = (tsb[*idx] != 0x47) || (tsb[*idx+188] != 0x47) || + (tsb[*idx+376] != 0x47); + } + return err; +} diff --git a/src/tsdemux.h b/src/tsdemux.h index 77f1b4dd..61e088fe 100644 --- a/src/tsdemux.h +++ b/src/tsdemux.h @@ -19,6 +19,8 @@ #ifndef TSDEMUX_H #define TSDEMUX_H +int ts_resync ( const uint8_t *tsb, int *len, int *idx ); + void ts_recv_packet1(struct service *t, const uint8_t *tsb, int64_t *pcrp); void ts_recv_packet2(struct service *t, const uint8_t *tsb);