From: Jaroslav Kysela Date: Tue, 6 Oct 2015 10:18:34 +0000 (+0200) Subject: SAT>IP Server: add rewrite PMT functionality, fixes #3001 X-Git-Tag: v4.2.1~1986 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6f5fc92abf3bb2cca8a0e2db24ab96fd111ef7bd;p=thirdparty%2Ftvheadend.git SAT>IP Server: add rewrite PMT functionality, fixes #3001 --- diff --git a/src/satip/rtp.c b/src/satip/rtp.c index dd4835bb0..1edf3dc6b 100644 --- a/src/satip/rtp.c +++ b/src/satip/rtp.c @@ -33,6 +33,13 @@ #define RTP_PAYLOAD (7*188+12) #define RTCP_PAYLOAD (1420) +typedef struct satip_rtp_table { + TAILQ_ENTRY(satip_rtp_table) link; + mpegts_psi_table_t tbl; + int pid; + int remove_mark; +} satip_rtp_table_t; + typedef struct satip_rtp_session { TAILQ_ENTRY(satip_rtp_session) link; pthread_t tid; @@ -48,6 +55,7 @@ typedef struct satip_rtp_session { int source; dvb_mux_conf_t dmc; mpegts_apids_t pids; + TAILQ_HEAD(, satip_rtp_table) pmt_tables; udp_multisend_t um; struct iovec *um_iovec; int um_packet; @@ -55,6 +63,8 @@ typedef struct satip_rtp_session { signal_status_t sig; int sig_lock; pthread_mutex_t lock; + uint8_t *table_data; + int table_data_len; } satip_rtp_session_t; static pthread_mutex_t satip_rtp_lock; @@ -62,6 +72,67 @@ static pthread_t satip_rtcp_tid; static int satip_rtcp_run; static TAILQ_HEAD(, satip_rtp_session) satip_rtp_sessions; +static void +satip_rtp_pmt_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len) +{ + satip_rtp_session_t *rtp; + uint8_t out[1024], *ob; + // uint16_t sid, pid; + int l, ol; + + memcpy(out, buf, ol = 3); + buf += ol; + len -= ol; + + // sid = (buf[0] << 8) | buf[1]; + l = (buf[7] & 0x0f) << 8 | buf[8]; + + if (l > len - 9) + return; + + rtp = (satip_rtp_session_t *)mt->mt_opaque; + + memcpy(out + ol, buf, 9); + + ol += 9; /* skip common descriptors */ + buf += 9 + l; + len -= 9 + l; + + /* no common descriptors */ + out[7+3] &= 0xf0; + out[8+3] = 0; + + while (len >= 5) { + //pid = (buf[1] & 0x1f) << 8 | buf[2]; + l = (buf[3] & 0xf) << 8 | buf[4]; + + if (l > len - 5) + return; + + if (sizeof(out) < ol + l + 5 + 4 /* crc */) { + tvherror("pass", "PMT entry too long (%i)", l); + return; + } + + memcpy(out + ol, buf, 5 + l); + ol += 5 + l; + + buf += 5 + l; + len -= 5 + l; + } + + /* update section length */ + out[1] = (out[1] & 0xf0) | ((ol + 4 - 3) >> 8); + out[2] = (ol + 4 - 3) & 0xff; + + ol = dvb_table_append_crc32(out, ol, sizeof(out)); + + if (ol > 0 && (l = dvb_table_remux(mt, out, ol, &ob)) > 0) { + rtp->table_data = ob; + rtp->table_data_len = l; + } +} + static void satip_rtp_header(satip_rtp_session_t *rtp) { @@ -112,12 +183,37 @@ satip_rtp_send(satip_rtp_session_t *rtp) return 0; } +static inline int +satip_rtp_append_data(satip_rtp_session_t *rtp, struct iovec **_v, uint8_t *data) +{ + struct iovec *v = *_v; + int r; + assert(v->iov_len + 188 <= RTP_PAYLOAD); + memcpy(v->iov_base + v->iov_len, data, 188); + v->iov_len += 188; + if (v->iov_len == RTP_PAYLOAD) { + if ((rtp->um_packet + 1) == RTP_PACKETS) { + r = satip_rtp_send(rtp); + if (r < 0) + return r; + } else { + rtp->um_packet++; + satip_rtp_header(rtp); + } + *_v = rtp->um_iovec + rtp->um_packet; + } else { + assert(v->iov_len < RTP_PAYLOAD); + } + return 0; +} + static int satip_rtp_loop(satip_rtp_session_t *rtp, uint8_t *data, int len) { int i, j, pid, last_pid = -1, r; mpegts_apid_t *pids = rtp->pids.pids; struct iovec *v = rtp->um_iovec + rtp->um_packet; + satip_rtp_table_t *tbl; assert((len % 188) == 0); if (len > 0) @@ -132,24 +228,27 @@ satip_rtp_loop(satip_rtp_session_t *rtp, uint8_t *data, int len) } continue; found: + TAILQ_FOREACH(tbl, &rtp->pmt_tables, link) + if (tbl->pid == pid) { + dvb_table_parse(&tbl->tbl, "-", data, 188, 1, 0, satip_rtp_pmt_cb); + if (rtp->table_data_len) { + for (i = 0; i < rtp->table_data_len; i += 188) { + r = satip_rtp_append_data(rtp, &v, data); + if (r < 0) + return r; + } + free(rtp->table_data); + rtp->table_data = NULL; + } + break; + } + if (tbl) + continue; last_pid = pid; } - assert(v->iov_len + 188 <= RTP_PAYLOAD); - memcpy(v->iov_base + v->iov_len, data, 188); - v->iov_len += 188; - if (v->iov_len == RTP_PAYLOAD) { - if ((rtp->um_packet + 1) == RTP_PACKETS) { - r = satip_rtp_send(rtp); - if (r < 0) - return r; - } else { - rtp->um_packet++; - satip_rtp_header(rtp); - } - v = rtp->um_iovec + rtp->um_packet; - } else { - assert(v->iov_len < RTP_PAYLOAD); - } + r = satip_rtp_append_data(rtp, &v, data); + if (r < 0) + return r; } return 0; } @@ -271,6 +370,7 @@ void satip_rtp_queue(void *id, th_subscription_t *subs, rtp->sq = sq; mpegts_pid_init(&rtp->pids); mpegts_pid_copy(&rtp->pids, pids); + TAILQ_INIT(&rtp->pmt_tables); udp_multisend_init(&rtp->um, RTP_PACKETS, RTP_PAYLOAD, &rtp->um_iovec); satip_rtp_header(rtp); rtp->frontend = frontend; @@ -306,9 +406,44 @@ void satip_rtp_update_pids(void *id, mpegts_apids_t *pids) pthread_mutex_unlock(&satip_rtp_lock); } +void satip_rtp_update_pmt_pids(void *id, mpegts_apids_t *pmt_pids) +{ + satip_rtp_session_t *rtp; + satip_rtp_table_t *tbl, *tbl_next; + int i, pid; + + pthread_mutex_lock(&satip_rtp_lock); + rtp = satip_rtp_find(id); + if (rtp) { + pthread_mutex_lock(&rtp->lock); + TAILQ_FOREACH(tbl, &rtp->pmt_tables, link) + if (!mpegts_pid_rexists(pmt_pids, tbl->pid)) + tbl->remove_mark = 1; + for (i = 0; i < pmt_pids->count; i++) { + pid = pmt_pids->pids[i].pid; + TAILQ_FOREACH(tbl, &rtp->pmt_tables, link) + if (tbl->pid == pid) + break; + if (!tbl) { + tbl = calloc(1, sizeof(*tbl)); + dvb_table_parse_init(&tbl->tbl, "satip-pmt", pid, rtp); + tbl->pid = pid; + } + } + for (tbl = TAILQ_FIRST(&rtp->pmt_tables); tbl; tbl = tbl_next){ + tbl_next = TAILQ_NEXT(tbl, link); + if (tbl->remove_mark) + TAILQ_REMOVE(&rtp->pmt_tables, tbl, link); + } + pthread_mutex_unlock(&rtp->lock); + } + pthread_mutex_unlock(&satip_rtp_lock); +} + void satip_rtp_close(void *id) { satip_rtp_session_t *rtp; + satip_rtp_table_t *tbl; streaming_queue_t *sq; pthread_mutex_lock(&satip_rtp_lock); @@ -324,6 +459,10 @@ void satip_rtp_close(void *id) pthread_join(rtp->tid, NULL); udp_multisend_free(&rtp->um); mpegts_pid_done(&rtp->pids); + while ((tbl = TAILQ_FIRST(&rtp->pmt_tables)) != NULL) { + dvb_table_parse_done(&tbl->tbl); + TAILQ_REMOVE(&rtp->pmt_tables, tbl, link); + } pthread_mutex_destroy(&rtp->lock); free(rtp); } else { diff --git a/src/satip/rtsp.c b/src/satip/rtsp.c index c730af208..dd951724a 100644 --- a/src/satip/rtsp.c +++ b/src/satip/rtsp.c @@ -70,6 +70,7 @@ static uint16_t stream_id; static char *rtsp_ip = NULL; static int rtsp_port = -1; static int rtsp_descramble = 1; +static int rtsp_rewrite_pmt = 0; static int rtsp_muxcnf = MUXCNF_AUTO; static void *rtsp_server = NULL; static TAILQ_HEAD(,session) rtsp_sessions; @@ -404,6 +405,8 @@ rtsp_manage_descramble(session_t *rs) idnode_set_t *found; mpegts_service_t *s, *snext; mpegts_service_t *master = (mpegts_service_t *)rs->subs->ths_raw_service; + slave_subscription_t *sub; + mpegts_apids_t pmt_pids; size_t si; int i, used = 0; @@ -450,6 +453,18 @@ rtsp_manage_descramble(session_t *rs) end: idnode_set_free(found); + + if (rtsp_rewrite_pmt) { + /* handle PMT rewrite */ + mpegts_pid_init(&pmt_pids); + LIST_FOREACH(sub, &rs->slaves, link) { + if ((s = sub->service) == NULL) continue; + if (s->s_pmt_pid <= 0 || s->s_pmt_pid >= 8191) continue; + mpegts_pid_add(&pmt_pids, s->s_pmt_pid, MPS_WEIGHT_PMT); + } + satip_rtp_update_pmt_pids((void *)(intptr_t)rs->stream, &pmt_pids); + mpegts_pid_done(&pmt_pids); + } } /* @@ -1521,7 +1536,7 @@ rtsp_close_sessions(void) * */ void satip_server_rtsp_init - (const char *bindaddr, int port, int descramble, int muxcnf) + (const char *bindaddr, int port, int descramble, int rewrite_pmt, int muxcnf) { static tcp_server_ops_t ops = { .start = rtsp_serve, @@ -1547,6 +1562,7 @@ void satip_server_rtsp_init rtsp_ip = strdup(bindaddr); rtsp_port = port; rtsp_descramble = descramble; + rtsp_rewrite_pmt = rewrite_pmt; rtsp_muxcnf = muxcnf; if (!rtsp_server) rtsp_server = tcp_server_create(bindaddr, port, &ops, NULL); diff --git a/src/satip/server.c b/src/satip/server.c index 38443aee2..d75f87649 100644 --- a/src/satip/server.c +++ b/src/satip/server.c @@ -601,6 +601,13 @@ const idclass_t satip_server_class = { .off = offsetof(struct satip_server_conf, satip_descramble), .group = 1, }, + { + .type = PT_BOOL, + .id = "satip_rewrite_pmt", + .name = N_("Rewrite PMT"), + .off = offsetof(struct satip_server_conf, satip_rewrite_pmt), + .group = 1, + }, { .type = PT_INT, .id = "satip_muxcnf", @@ -674,16 +681,17 @@ const idclass_t satip_server_class = { */ static void satip_server_save(void) { - int descramble, muxcnf; + int descramble, rewrite_pmt, muxcnf; config_save(); if (!satip_server_rtsp_port_locked) { satips_rtsp_port(0); if (satip_server_rtsp_port > 0) { descramble = satip_server_conf.satip_descramble; + rewrite_pmt = satip_server_conf.satip_rewrite_pmt; muxcnf = satip_server_conf.satip_muxcnf; pthread_mutex_unlock(&global_lock); - satip_server_rtsp_init(http_server_ip, satip_server_rtsp_port, descramble, muxcnf); + satip_server_rtsp_init(http_server_ip, satip_server_rtsp_port, descramble, rewrite_pmt, muxcnf); satip_server_info("re", descramble, muxcnf); satips_upnp_send_announce(); pthread_mutex_lock(&global_lock); @@ -705,7 +713,7 @@ void satip_server_init(int rtsp_port) { struct sockaddr_storage http; char http_ip[128]; - int descramble, muxcnf; + int descramble, rewrite_pmt, muxcnf; http_server_ip = NULL; satip_server_bootid = time(NULL); @@ -728,9 +736,10 @@ void satip_server_init(int rtsp_port) return; descramble = satip_server_conf.satip_descramble; + rewrite_pmt = satip_server_conf.satip_rewrite_pmt; muxcnf = satip_server_conf.satip_muxcnf; - satip_server_rtsp_init(http_server_ip, satip_server_rtsp_port, descramble, muxcnf); + satip_server_rtsp_init(http_server_ip, satip_server_rtsp_port, descramble, rewrite_pmt, muxcnf); satip_server_info("", descramble, muxcnf); } diff --git a/src/satip/server.h b/src/satip/server.h index 6494c039c..8b70b3929 100644 --- a/src/satip/server.h +++ b/src/satip/server.h @@ -40,6 +40,7 @@ struct satip_server_conf { int satip_rtsp; int satip_weight; int satip_descramble; + int satip_rewrite_pmt; int satip_muxcnf; int satip_dvbs; int satip_dvbs2; @@ -66,8 +67,10 @@ void satip_rtp_update(void *id, th_subscription_t *subs, streaming_queue_t *sq, int frontend, int source, dvb_mux_conf_t *dmc, - mpegts_apids_t *pids); + mpegts_apids_t *pids, + mpegts_apids_t *pmt_pids); void satip_rtp_update_pids(void *id, mpegts_apids_t *pids); +void satip_rtp_update_pmt_pids(void *id, mpegts_apids_t *pmt_pids); int satip_rtp_status(void *id, char *buf, int len); void satip_rtp_close(void *id); @@ -75,7 +78,7 @@ void satip_rtp_init(void); void satip_rtp_done(void); void satip_server_rtsp_init(const char *bindaddr, int port, - int descramble, int muxcnf); + int descramble, int rewrite_pmt, int muxcnf); void satip_server_rtsp_register(void); void satip_server_rtsp_done(void);