]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Let MPEG TS output muxer bypass internal remuxing if the source is MPEG TS and no...
authorAndreas Öman <andreas@lonelycoder.com>
Tue, 8 Jan 2008 09:46:40 +0000 (09:46 +0000)
committerAndreas Öman <andreas@lonelycoder.com>
Tue, 8 Jan 2008 09:46:40 +0000 (09:46 +0000)
pes.c
tsmux.c
tvhead.h

diff --git a/pes.c b/pes.c
index b981f608952f39f33cce2935dd85ab41fd4d5299..fdee1f4c05149732470d6a10591f541362aae1d1 100644 (file)
--- a/pes.c
+++ b/pes.c
@@ -84,6 +84,9 @@ pes_packet_input(th_transport_t *t, th_stream_t *st, uint8_t *buf, size_t len)
 
   avgstat_add(&st->st_rate, len, dispatch_clock);
 
+  if(LIST_FIRST(&t->tht_muxers) == NULL)
+    return 0; /* No muxers will take packet, so drop here*/
+
   if(len < 3)
     return -1;
 
diff --git a/tsmux.c b/tsmux.c
index b023dad227a3799d671110d18f803d762de205a9..4d174a20a3efb5fe2ee8d62a177949fc20abc650 100644 (file)
--- a/tsmux.c
+++ b/tsmux.c
@@ -624,6 +624,108 @@ ts_muxer_relock(th_muxer_t *tm, uint64_t pcr)
 }
 
 
+/**
+ * Push a MPEG TS packet to output, used in shortcut mode
+ */
+static void
+ts_muxer_raw_push_packet(th_muxer_t *tm, void *data, uint16_t pid)
+{
+  uint8_t *tsb;
+
+  tsb = tm->tm_packet + tm->tm_block_offset * 188;
+  tm->tm_block_offset++;
+
+  memcpy(tsb, data, 188);
+  
+  /* Set PID */
+
+  tsb[2] =                    pid;
+  tsb[1] = (tsb[1] & 0xf0) | (pid >> 8);
+  
+  if(tm->tm_block_offset == tm->tm_blocks_per_packet) {
+    tm->tm_callback(tm->tm_opaque, tm->tm_subscription, tm->tm_packet, 
+                   tm->tm_block_offset, AV_NOPTS_VALUE);
+    tm->tm_block_offset = 0;
+  }
+}
+
+/**
+ * Function for encapsulating a short table into a transport stream packet
+ */
+static void
+ts_muxer_raw_push_table(th_muxer_t *tm, void *table, int tlen, int cc, int pid)
+{
+  int pad;
+
+  uint8_t tsb0[188], *tsb;
+  tsb = tsb0;
+
+  pad = 184 - (tlen + 1);
+  
+  *tsb++ = 0x47;
+  *tsb++ = 0x40;
+  *tsb++ = 0;
+  *tsb++ = (cc & 0xf) | 0x30;
+  *tsb++ = --pad;
+  memset(tsb, 0, pad);
+  tsb += pad;
+  
+  *tsb++ = 0; /* Pointer field for tables */
+  memcpy(tsb, table, tlen);
+  ts_muxer_raw_push_packet(tm, tsb0, pid);
+}
+
+
+/**
+ * Periodic timer callback for generating PAT/PMT tables when in 
+ * shortcut mode
+ */
+static void
+ts_muxer_raw_table_generator(void *aux, int64_t now)
+{
+  th_muxer_t *tm = aux;
+  uint8_t table[180];
+  th_muxstream_t *tms;
+  int l;
+
+  /* rearm timer */
+  dtimer_arm_hires(&tm->tm_table_timer, ts_muxer_raw_table_generator,
+                  tm, now + 100000);
+
+  l = psi_build_pat(NULL, table, sizeof(table));
+  tms = tm->tm_pat;
+  tms->tms_cc++;
+  ts_muxer_raw_push_table(tm, table, l, tms->tms_cc, 0);
+
+  l = psi_build_pmt(tm, table, sizeof(table));
+  tms = tm->tm_pmt;
+  tms->tms_cc++;
+  ts_muxer_raw_push_table(tm, table, l, tms->tms_cc, 100);
+}
+
+
+
+/**
+ * Shortcutted MPEG TS input
+ */
+static void
+ts_muxer_raw_input(struct th_subscription *s, void *data, int len,
+                  th_stream_t *st, void *opaque)
+{
+  th_muxer_t *tm = s->ths_muxer;
+  th_muxstream_t *tms;
+
+  LIST_FOREACH(tms, &tm->tm_media_streams, tms_muxer_media_link)
+    if(tms->tms_stream == st)
+      break;
+
+  if(tms == NULL)
+    return; /* Unknown / non-mapped stream */
+  
+  ts_muxer_raw_push_packet(tm, data, tms->tms_index);
+}
+
+
 /*
  * pause playback
  */
@@ -649,6 +751,25 @@ ts_muxer_play(th_muxer_t *tm, int64_t toffset)
   th_muxstream_t *tms;
   th_stream_t *st;
   int64_t clk;
+  th_subscription_t *s = tm->tm_subscription;
+  
+  if(!(tm->tm_flags & TM_SEEKABLE) && 
+     s->ths_transport->tht_source_type == THT_MPEG_TS) {
+    /* We dont need to seek and source is MPEG TS, we can use a 
+       shortcut to avoid remuxing stream */
+
+    s->ths_raw_input = ts_muxer_raw_input;
+    dtimer_arm_hires(&tm->tm_table_timer, ts_muxer_raw_table_generator,
+                    tm, getclock_hires() + 100000);
+    return;
+  }
+
+  /* Use normal muxer */
+
+  if(!tm->tm_transport_linked) {
+    LIST_INSERT_HEAD(&s->ths_transport->tht_muxers, tm, tm_transport_link);
+    tm->tm_transport_linked = 1;
+  }
 
   switch(tm->tm_status) {
   case TM_IDLE:
@@ -771,15 +892,14 @@ ts_muxer_init(th_subscription_t *s, th_mux_output_t *cb, void *opaque,
   int offset;
 
   tm = calloc(1, sizeof(th_muxer_t));
-  LIST_INSERT_HEAD(&t->tht_muxers, tm, tm_transport_link);
   tm->tm_subscription = s;
 
   tm->tm_clockref = getclock_hires();
   tm->tm_blocks_per_packet = 7;
   tm->tm_callback = cb;
   tm->tm_opaque = opaque;
-  tm->tm_new_pkt = ts_encode_new_packet;
   tm->tm_flags = flags;
+  tm->tm_new_pkt = ts_encode_new_packet;
 
   tm->tm_packet = malloc(188 * tm->tm_blocks_per_packet);
 
@@ -853,11 +973,14 @@ ts_muxer_deinit(th_muxer_t *tm, th_subscription_t *s)
 {
   th_muxstream_t *tms;
 
+  s->ths_raw_input = NULL;
   s->ths_muxer = NULL;
 
-  LIST_REMOVE(tm, tm_transport_link);
+  if(tm->tm_transport_linked)
+    LIST_REMOVE(tm, tm_transport_link);
 
   dtimer_disarm(&tm->tm_timer);
+  dtimer_disarm(&tm->tm_table_timer);
     
   tms_destroy(tm->tm_pat);
   tms_destroy(tm->tm_pmt);
index 3611b2c199b40f8c68560ffd9ac46570ade0eb3e..d14c566d1d70625ef4906110d0d0e93ebccea54a 100644 (file)
--- a/tvhead.h
+++ b/tvhead.h
@@ -572,12 +572,14 @@ typedef struct th_muxer {
   th_mux_newpkt_t *tm_new_pkt;
 
   LIST_ENTRY(th_muxer) tm_transport_link;
+  int tm_transport_linked;
 
   int64_t tm_clockref;  /* Base clock ref */
   int64_t tm_pauseref;  /* Time when we were paused */
 
   int tm_flags;
-#define TM_HTSCLIENTMODE 0x1
+#define TM_HTSCLIENTMODE 0x1 /* Ugly workaround for now */
+#define TM_SEEKABLE      0x2 /* We need the pause / seek to work */
 
   int64_t tm_start_dts;
   int64_t tm_next_pat;
@@ -613,6 +615,8 @@ typedef struct th_muxer {
   int tm_drop_rate;
   int tm_drop_cnt;
 
+  dtimer_t tm_table_timer;
+  int tm_block_offset;
 } th_muxer_t;