From d6a148de430b9eacfab45763457e5cd1d739805d Mon Sep 17 00:00:00 2001
From: cuchac <cuchac@email.cz>
Date: Tue, 29 May 2012 16:13:39 +0200
Subject: [PATCH] Fix missing PAT/PMT packets in MPEG TS

---
 src/dvr/dvr_rec.c |   43 +++++++++++++++++++++++++-------
 src/dvr/mkts.c    |   68 +++++++++++++++++++++-------------------------------
 src/dvr/mkts.h    |   11 +++++++-
 src/rawtsinput.c  |    2 -
 src/webui/webui.c |   50 ++++++++++++++-------------------------
 5 files changed, 88 insertions(+), 86 deletions(-)

diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c
index dd67abf..db0fd8d 100755
--- a/src/dvr/dvr_rec.c
+++ b/src/dvr/dvr_rec.c
@@ -421,29 +421,33 @@ dvr_thread(void *aux)
   dvr_entry_t *de = aux;
   streaming_queue_t *sq = &de->de_sq;
   streaming_message_t *sm;
+  dvr_config_t *cfg = dvr_config_find_by_name_default(de->de_config_name);
+  streaming_tsbuf_t pat_pmt_tsbuf;
+  struct mk_ts_pat_pmt pat_pmt_buf;
+  int ts_packets_cnt = 1000;
   int run = 1;
 
   pthread_mutex_lock(&sq->sq_mutex);
-
   while(run) {
     sm = TAILQ_FIRST(&sq->sq_queue);
     if(sm == NULL) {
       pthread_cond_wait(&sq->sq_cond, &sq->sq_mutex);
       continue;
     }
-    
+
     TAILQ_REMOVE(&sq->sq_queue, sm, sm_link);
 
     pthread_mutex_unlock(&sq->sq_mutex);
 
     switch(sm->sm_type) {
+
     case SMT_PACKET:
       if(dispatch_clock > de->de_start - (60 * de->de_start_extra)) {
-	dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
-	if(de->de_mkmux != NULL) {
-	  mk_mux_write_pkt(de->de_mkmux, sm->sm_data);
-	  sm->sm_data = NULL;
-	}
+      dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
+        if(de->de_mkmux != NULL) {
+          mk_mux_write_pkt(de->de_mkmux, sm->sm_data);
+          sm->sm_data = NULL;
+        }
       }
       break;
 
@@ -452,6 +456,15 @@ dvr_thread(void *aux)
       dvr_rec_set_state(de, DVR_RS_WAIT_PROGRAM_START, 0);
       dvr_rec_start(de, sm->sm_data);
       pthread_mutex_unlock(&global_lock);
+
+      if (strcmp(cfg->dvr_format, "mpegts") == 0) {
+        struct streaming_start *ss = sm->sm_data;
+        run = mk_ts_build_pat_pmt(&pat_pmt_buf, ss, de->de_s->ths_service->s_pmt_pid, de->de_s->ths_service->s_pcr_pid);
+
+        pat_pmt_tsbuf.ts_data = (uint8_t *)&pat_pmt_buf;
+        pat_pmt_tsbuf.ts_cnt = 2;
+      }
+
       break;
 
     case SMT_STOP:
@@ -523,9 +536,19 @@ dvr_thread(void *aux)
 
     case SMT_MPEGTS:
       if(dispatch_clock > de->de_start - (60 * de->de_start_extra)) {
-    	dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
-    	if(de->de_mkts != NULL)
-    	  mk_ts_write(de->de_mkts, (streaming_tsbuf_t *)sm->sm_data);
+        dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
+
+        if(de->de_mkts != NULL) {
+          streaming_tsbuf_t *tsbuf = sm->sm_data;
+
+          ts_packets_cnt += tsbuf->ts_cnt;
+          if(ts_packets_cnt >= 1000) {
+            ts_packets_cnt = 0;
+            mk_ts_write(de->de_mkts, &pat_pmt_tsbuf);
+          }
+
+          mk_ts_write(de->de_mkts, tsbuf);
+        }
       }
       break;
 
diff --git a/src/dvr/mkts.c b/src/dvr/mkts.c
index e162d6e..566995e 100644
--- a/src/dvr/mkts.c
+++ b/src/dvr/mkts.c
@@ -42,12 +42,11 @@ struct mk_ts {
  */
 mk_ts_t *
 mk_ts_create(const char *filename,
-		  const struct streaming_start *ss,
-	      const struct dvr_entry *de)
+             const struct streaming_start *ss,
+             const struct dvr_entry *de)
 {
   mk_ts_t *mkr;
   int fd;
-  dvr_config_t *cfg = dvr_config_find_by_name_default(de->de_config_name);
 
   fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0777);
   if(fd == -1)
@@ -58,46 +57,35 @@ mk_ts_create(const char *filename,
   mkr->fd = fd;
   mkr->title = strdup(de->de_title);
 
-  // XXX Code from webui.c, it doesn't work with HD stream (H264+EAC3) and XBMC
-  if (strcmp(cfg->dvr_format, "mpegts") == 0) {
-        streaming_tsbuf_t tsbuf;
-        struct {
-          uint8_t pat_ts[188];
-          uint8_t pmt_ts[188];
-        } s;
-	int pcrpid = ss->ss_pcr_pid;
-	int pmtpid = 0x0fff;
-
-	tsbuf.ts_cnt = 2;
-	tsbuf.ts_data = (uint8_t *)&s;
-
-	//Build PAT
-	memset(s.pat_ts, 0xff, 188);
-	psi_build_pat(NULL, s.pat_ts+5, 183, pmtpid);
-	s.pat_ts[0] = 0x47;
-	s.pat_ts[1] = 0x40;
-	s.pat_ts[2] = 0x00;
-	s.pat_ts[3] = 0x10;
-	s.pat_ts[4] = 0x00;
-
-	//Build PMT
-	memset(s.pmt_ts, 0xff, 188);
-	psi_build_pmt(ss, s.pmt_ts+5, 183, pcrpid);
-	s.pmt_ts[0] = 0x47;
-	s.pmt_ts[1] = 0x40 | (pmtpid >> 8);
-	s.pmt_ts[2] = pmtpid;
-	s.pmt_ts[3] = 0x10;
-	s.pmt_ts[4] = 0x00;
-
-	//Write PAT+PMT
-	mk_ts_write(mkr, &tsbuf);
-	if(mkr->error)
-	  return NULL;
-  }
-
   return mkr;
 }
 
+int mk_ts_build_pat_pmt(struct mk_ts_pat_pmt* buffer, const struct streaming_start* ss, int pmt_pid, int pcr_pid)
+{
+  int pmtpid = 0x0fff; //pmt_pid
+  int pcrpid = pcr_pid;
+  
+  //Build PAT
+  memset(buffer->pat_ts, 0xff, 188);
+  psi_build_pat(NULL, buffer->pat_ts+5, 183, pmtpid);
+  buffer->pat_ts[0] = 0x47;
+  buffer->pat_ts[1] = 0x40;
+  buffer->pat_ts[2] = 0x00;
+  buffer->pat_ts[3] = 0x10;
+  buffer->pat_ts[4] = 0x00;
+  
+  //Build PMT
+  memset(buffer->pmt_ts, 0xff, 188);
+  psi_build_pmt(ss, buffer->pmt_ts+5, 183, pcrpid);
+  buffer->pmt_ts[0] = 0x47;
+  buffer->pmt_ts[1] = 0x40 | (pmtpid >> 8);
+  buffer->pmt_ts[2] = pmtpid;
+  buffer->pmt_ts[3] = 0x10;
+  buffer->pmt_ts[4] = 0x00;
+  
+  return 1;
+}
+
 /**
  *
  */
diff --git a/src/dvr/mkts.h b/src/dvr/mkts.h
index 4b74b44..3cc04f5 100644
--- a/src/dvr/mkts.h
+++ b/src/dvr/mkts.h
@@ -18,12 +18,19 @@
 
 typedef struct mk_ts mk_ts_t;
 
+struct mk_ts_pat_pmt {
+  uint8_t pat_ts[188];
+  uint8_t pmt_ts[188];
+};
+
 struct streaming_start;
 struct dvr_entry;
 
 mk_ts_t *mk_ts_create(const char *filename,
-			const struct streaming_start *ss,
-			const struct dvr_entry *de);
+                      const struct streaming_start *ss,
+                      const struct dvr_entry *de);
+
+int mk_ts_build_pat_pmt(struct mk_ts_pat_pmt* buffer, const struct streaming_start* ss, int pmt_pid, int pcr_pid);
 
 void mk_ts_write(mk_ts_t *mkr, const streaming_tsbuf_t *tsbuf);
 
diff --git a/src/rawtsinput.c b/src/rawtsinput.c
index 24a71d3..4409c83 100644
--- a/src/rawtsinput.c
+++ b/src/rawtsinput.c
@@ -257,8 +257,6 @@ process_ts_packet(rawts_t *rt, uint8_t *tsb)
 	  struct timespec slp;
 	  int64_t delta = pcr - t->s_pcr_last;
 
-	  
-
 	  if(delta > 90000)
 	    delta = 90000;
 	  delta *= 11;
diff --git a/src/webui/webui.c b/src/webui/webui.c
index bfdf744..4bd4fd4 100644
--- a/src/webui/webui.c
+++ b/src/webui/webui.c
@@ -34,6 +34,7 @@
 #include "http.h"
 #include "webui.h"
 #include "dvr/dvr.h"
+#include "dvr/mkts.h"
 #include "dvr/mkmux.h"
 #include "filebundle.h"
 #include "psi.h"
@@ -131,10 +132,12 @@ static void
 http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t *s)
 {
   streaming_message_t *sm;
-  int run = 1;
   mk_mux_t *mkm = NULL;
-  uint32_t event_id = 0;
+  struct mk_ts_pat_pmt pat_pmt_buf;
+  int ts_packets_cnt = 1000;
+  int run = 1;
   int timeouts = 0;
+  uint32_t event_id = 0;
 
   if (s->ths_flags & SUBSCRIPTION_RAW_MPEGTS)
     http_output_content(hc, "video/mp2t");
@@ -177,6 +180,7 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t
     timeouts = 0; //Reset timeout counter
 
     switch(sm->sm_type) {
+
     case SMT_PACKET: {
       if(!mkm)
         break;
@@ -196,42 +200,14 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t
     }
 
     case SMT_START:
-
       tvhlog(LOG_DEBUG, "webui",  "Start streaming %s", hc->hc_url_orig);
-
       if (s->ths_flags & SUBSCRIPTION_RAW_MPEGTS) {
-
         struct streaming_start *ss = sm->sm_data;
-        uint8_t pat_ts[188];
-        uint8_t pmt_ts[188];  
-        int pcrpid = ss->ss_pcr_pid;
-        int pmtpid = 0x0fff;
-
-        //Send PAT
-        memset(pat_ts, 0xff, 188);
-        psi_build_pat(NULL, pat_ts+5, 183, pmtpid);
-        pat_ts[0] = 0x47;
-        pat_ts[1] = 0x40;
-        pat_ts[2] = 0x00;
-        pat_ts[3] = 0x10;
-        pat_ts[4] = 0x00;
-        run = (write(hc->hc_fd, pat_ts, 188) == 188);
-
+        run = mk_ts_build_pat_pmt(&pat_pmt_buf, ss, s->ths_service->s_pmt_pid, s->ths_service->s_pcr_pid);
         if(!run)
           break;
 
-        //Send PMT
-        memset(pmt_ts, 0xff, 188);
-        psi_build_pmt(ss, pmt_ts+5, 183, pcrpid);
-        pmt_ts[0] = 0x47;
-        pmt_ts[1] = 0x40 | (pmtpid >> 8);
-        pmt_ts[2] = pmtpid;
-        pmt_ts[3] = 0x10;
-        pmt_ts[4] = 0x00;
-        run = (write(hc->hc_fd, pmt_ts, 188) == 188);
-
       } else {
-
         if(mkm)
           break;
 
@@ -241,7 +217,6 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t
           http_output_content(hc, "video/x-matroska");
 
         mkm = mk_mux_stream_create(hc->hc_fd, sm->sm_data, s->ths_channel);
-
       }
       break;
 
@@ -261,6 +236,17 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq, th_subscription_t
       if (s->ths_flags & SUBSCRIPTION_RAW_MPEGTS) {
         streaming_tsbuf_t *tsbuf = sm->sm_data;
         uint32_t size = tsbuf->ts_cnt * 188;
+
+        ts_packets_cnt += tsbuf->ts_cnt;
+        if (ts_packets_cnt >= 1000) {
+          ts_packets_cnt = 0;
+          run = write(hc->hc_fd, pat_pmt_buf.pat_ts, 188) == 188;
+          run = write(hc->hc_fd, pat_pmt_buf.pmt_ts, 188) == 188;
+        }
+
+        if(!run)
+          break;
+
         run = (write(hc->hc_fd, tsbuf->ts_data, size) == size);
       }
       break;
-- 
1.7.3.4

