]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mpegts tsfile: lots of reworking to get psi processing working
authorAdam Sutton <dev@adamsutton.me.uk>
Thu, 9 May 2013 15:33:53 +0000 (16:33 +0100)
committerAdam Sutton <dev@adamsutton.me.uk>
Thu, 9 May 2013 15:33:53 +0000 (16:33 +0100)
17 files changed:
Makefile
configure
src/input/mpegts.h
src/input/mpegts/dvb.h
src/input/mpegts/dvb_charset.c [moved from src/input/mpegts/linuxdvb/dvb_charset.c with 100% similarity]
src/input/mpegts/dvb_charset.h [moved from src/input/mpegts/linuxdvb/dvb_charset.h with 100% similarity]
src/input/mpegts/dvb_charset_tables.h [moved from src/input/mpegts/linuxdvb/dvb_charset_tables.h with 100% similarity]
src/input/mpegts/dvb_psi.c [moved from src/input/mpegts/psi.c with 64% similarity]
src/input/mpegts/dvb_support.c [moved from src/input/mpegts/linuxdvb/dvb_support.c with 65% similarity]
src/input/mpegts/dvb_support.h [moved from src/input/mpegts/linuxdvb/dvb_support.h with 100% similarity]
src/input/mpegts/mpegts_input.c
src/input/mpegts/mpegts_network.c
src/input/mpegts/mpegts_table.c
src/input/mpegts/psi.h
src/input/mpegts/tsdemux.c
src/input/mpegts/tsfile/tsfile_input.c
src/service.h

index 52040f1bf327bf9377a34db471c2b6290802d7b6..a56545b27b6df9a0f52008732bdc646ccf9d5c2a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -153,7 +153,8 @@ SRCS-$(CONFIG_MPEGTS) += \
   src/input/mpegts/mpegts_mux.c \
   src/input/mpegts/mpegts_service.c \
   src/input/mpegts/mpegts_table.c \
-       src/input/mpegts/psi.c \
+       src/input/mpegts/dvb_support.c \
+       src/input/mpegts/dvb_psi.c \
        src/input/mpegts/tsdemux.c \
 
 # MPEGTS EPG
index ddae4e051edba96ef6a9113c3a6aff7f8a31fefb..e1dcbb7518ca44b2a45d20f1dcbc3d918e8faf47 100755 (executable)
--- a/configure
+++ b/configure
@@ -82,6 +82,11 @@ else
   die "SSL development support not found"
 fi
 
+#
+# DVB API
+#
+check_cc_header 'linux/dvb/version' dvbapi
+
 #
 # Gzip
 #
index 1752c37c3bde06455043fd7a8eb87f81b9d69086..b8ccf357fbb77080b74bbc0adee3f24b41d79ebc 100644 (file)
 #define __TVH_MPEGTS_H__
 
 #include "service.h"
-#include "src/input/mpegts/psi.h"
+#include "mpegts/dvb.h"
 
-#define MPEGTS_ONID_NONE 0xFFFF
-#define MPEGTS_TSID_NONE 0xFFFF
+#define MPEGTS_ONID_NONE        0xFFFF
+#define MPEGTS_TSID_NONE        0xFFFF
+#define MPEGTS_PSI_SECTION_SIZE 5000
 
 /* Types */
 typedef struct mpegts_table         mpegts_table_t;
+typedef struct mpegts_psi_section   mpegts_psi_section_t;
 typedef struct mpegts_network       mpegts_network_t;
 typedef struct mpegts_mux           mpegts_mux_t;
 typedef struct mpegts_service       mpegts_service_t;
@@ -45,9 +47,19 @@ TAILQ_HEAD(mpegts_table_feed_queue, mpegts_table_feed);
  * SI processing
  * *************************************************************************/
 
-typedef int (*mpegts_table_callback)
+typedef int (*mpegts_table_callback_t)
   ( mpegts_table_t*, const uint8_t *buf, int len, int tableid );
 
+typedef void (*mpegts_psi_section_callback_t)
+  ( const uint8_t *tsb, size_t len, void *opaque );
+
+struct mpegts_psi_section
+{
+  int     ps_offset;
+  int     ps_lock;
+  uint8_t ps_data[MPEGTS_PSI_SECTION_SIZE];
+};
+
 struct mpegts_table
 {
   /**
@@ -79,7 +91,7 @@ struct mpegts_table
   char *mt_name;
 
   void *mt_opaque;
-  mpegts_table_callback mt_callback;
+  mpegts_table_callback_t mt_callback;
 
 
   // TODO: remind myself of what each field is for
@@ -94,8 +106,7 @@ struct mpegts_table
   int mt_destroyed; // Refcounting
   int mt_refcount;
 
-  psi_section_t mt_sect; // Manual reassembly
-
+  mpegts_psi_section_t mt_sect;
 };
 
 /**
@@ -110,6 +121,12 @@ struct mpegts_table_feed {
   mpegts_mux_t *mtf_mux;
 };
 
+/*
+ * Assemble SI section
+ */
+void mpegts_psi_section_reassemble
+  ( mpegts_psi_section_t *ps, const uint8_t *tsb, int crc,
+    mpegts_psi_section_callback_t cb, void *opaque );
 
 /* **************************************************************************
  * Logical network
@@ -149,7 +166,7 @@ struct mpegts_network
    * Functions
    */
   mpegts_mux_t*     (*mn_create_mux)
-    (mpegts_mux_t*, uint16_t onid, uint16_t tsid, void *aux);
+    (mpegts_mux_t*, uint16_t onid, uint16_t tsid, dvb_mux_conf_t *conf);
   mpegts_service_t* (*mn_create_service)
     (mpegts_mux_t*, uint16_t sid, uint16_t pmt_pid);
 
@@ -161,6 +178,8 @@ struct mpegts_network
   int dn_fe_type;  // Frontend types for this network (FE_QPSK, etc)
 #endif
 
+  uint32_t mn_nid; // limit scope of scanning
+
 #if 0 // TODO: FIXME CONFIG
   uint32_t dn_disable_pmt_monitor;
   uint32_t dn_autodiscovery;
@@ -470,7 +489,7 @@ void mpegts_table_release
   (mpegts_table_t *mt);
 void mpegts_table_add
   (mpegts_mux_t *mm, int tableid, int mask,
-   mpegts_table_callback callback, void *opaque,
+   mpegts_table_callback_t callback, void *opaque,
    const char *name, int flags, int pid);
 void mpegts_table_flush_all
   (mpegts_mux_t *mm);
index 1b679452b961a5581afbfc31afbeadfc7796b69c..750ddc677764bcfd1e05d23a4d3cb8b95924e6f2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  TV Input - Linux DVB interface - Support
+ *  Tvheadend - DVB support routines and defines
  *  Copyright (C) 2007 Andreas Öman
  *
  *  This program is free software: you can redistribute it and/or modify
  * EN 300 468 - V1.7.1
  */
 
-#ifndef DVB_SUPPORT_H
-#define DVB_SUPPORT_H
+#ifndef __TVH_DVB_SUPPORT_H__
+#define __TVH_DVB_SUPPORT_H__
 
-#define DVB_DESC_VIDEO_STREAM 0x02
-#define DVB_DESC_REGISTRATION 0x05
-#define DVB_DESC_CA           0x09
-#define DVB_DESC_LANGUAGE     0x0a
+struct mpegts_table;
+
+/* Defaults */
+
+
+/* Tables */
+
+#define DVB_PAT_BASE                  0x00
+#define DVB_PAT_MASK                  0x00
+
+#define DVB_PMT_BASE                  0x02
+#define DVB_PMT_MASK                  0xFF
+
+#define DVB_NIT_BASE                  0x00
+#define DVB_NIT_MASK                  0x00
+
+#define DVB_SDT_BASE                  0x40
+#define DVB_SDT_MASK                  0xF8
+
+#define DVB_BAT_BASE                  0x48
+#define DVB_BAT_MASK                  0xF8
+
+#define DVB_TELETEXT_BASE             0x2000
+
+/* Descriptors */
+
+#define DVB_DESC_VIDEO_STREAM         0x02
+#define DVB_DESC_REGISTRATION         0x05
+#define DVB_DESC_CA                   0x09
+#define DVB_DESC_LANGUAGE             0x0A
 
 /* Descriptors defined in EN 300 468 */
 
-#define DVB_DESC_NETWORK_NAME 0x40
-#define DVB_DESC_SERVICE_LIST 0x41
-#define DVB_DESC_SAT          0x43
-#define DVB_DESC_CABLE        0x44
-#define DVB_DESC_SHORT_EVENT  0x4d
-#define DVB_DESC_EXT_EVENT    0x4e
-#define DVB_DESC_SERVICE      0x48
-#define DVB_DESC_COMPONENT    0x50
-#define DVB_DESC_CONTENT      0x54
-#define DVB_DESC_PARENTAL_RAT 0x55
-#define DVB_DESC_TELETEXT     0x56
-#define DVB_DESC_SUBTITLE     0x59
-#define DVB_DESC_TERR         0x5a
-#define DVB_DESC_AC3          0x6a
-#define DVB_DESC_DEF_AUTHORITY 0x73
-#define DVB_DESC_CRID         0x76
-#define DVB_DESC_EAC3         0x7a
-#define DVB_DESC_AAC          0x7c
-#define DVB_DESC_LOCAL_CHAN   0x83
+#define DVB_DESC_NETWORK_NAME         0x40
+#define DVB_DESC_SERVICE_LIST         0x41
+#define DVB_DESC_SAT_DEL              0x43
+#define DVB_DESC_CABLE_DEL            0x44
+#define DVB_DESC_SHORT_EVENT          0x4D
+#define DVB_DESC_EXT_EVENT            0x4E
+#define DVB_DESC_SERVICE              0x48
+#define DVB_DESC_COMPONENT            0x50
+#define DVB_DESC_CONTENT              0x54
+#define DVB_DESC_PARENTAL_RAT         0x55
+#define DVB_DESC_TELETEXT             0x56
+#define DVB_DESC_SUBTITLE             0x59
+#define DVB_DESC_TERR_DEL             0x5A
+#define DVB_DESC_MULTI_NETWORK_NAME   0x5B
+#define DVB_DESC_AC3                  0x6A
+#define DVB_DESC_DEF_AUTHORITY        0x73
+#define DVB_DESC_CRID                 0x76
+#define DVB_DESC_EAC3                 0x7A
+#define DVB_DESC_AAC                  0x7C
+#define DVB_DESC_LOCAL_CHAN           0x83
+
+/* String Extraction */
 
 typedef struct dvb_string_conv
 {
@@ -60,21 +89,118 @@ typedef struct dvb_string_conv
                     const uint8_t* src, size_t srclen );
 } dvb_string_conv_t;
 
-int dvb_get_string(char *dst, size_t dstlen, const uint8_t *src, 
-                  const size_t srclen, const char *dvb_charset,
-       dvb_string_conv_t *conv);
+int dvb_get_string
+  (char *dst, size_t dstlen, const uint8_t *src, const size_t srclen,
+   const char *dvb_charset, dvb_string_conv_t *conv);
 
-int dvb_get_string_with_len(char *dst, size_t dstlen, 
-                           const uint8_t *buf, size_t buflen, const char *dvb_charset,
-          dvb_string_conv_t *conv);
+int dvb_get_string_with_len
+  (char *dst, size_t dstlen, const uint8_t *buf, size_t buflen,
+   const char *dvb_charset, dvb_string_conv_t *conv);
+
+/* Conversion */
 
 #define bcdtoint(i) ((((i & 0xf0) >> 4) * 10) + (i & 0x0f))
 
 time_t dvb_convert_date(uint8_t *dvb_buf);
 
-const char *dvb_polarisation_to_str(int pol);
-const char *dvb_polarisation_to_str_long(int pol);
-
 void atsc_utf16_to_utf8(uint8_t *src, int len, char *buf, int buflen);
 
+/*
+ * PSI processing
+ */
+
+#define FOREACH_DVB_LOOP0(ptr,len,off,min,inc,llen) \
+  for ( llen = (ptr[off] & 0xF) << 8 | ptr[off+1],\
+        ptr += off + 2,\
+        len -= off + 2;\
+        (llen > min);\
+        ptr += inc, llen -= inc + min )\
+    if      (llen > len)       return -1;\
+    else
+
+#define FOREACH_DVB_LOOP(ptr,len,off,min,llen)\
+  FOREACH_DVB_LOOP0(ptr,len,off,min,0,llen)
+
+#define FOREACH_DVB_DESC(ptr,len,off,llen,dtag,dlen) \
+  FOREACH_DVB_LOOP0(ptr,len,off,2,dlen,llen)\
+    if      (!(dtag = *ptr++)) return -1;\
+    else if ((dlen = *ptr++) > llen - 2) return -1;\
+    else
+
+/* PSI descriptors */
+
+
+/* PSI table callbacks */
+
+int dvb_pat_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_pmt_callback  
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tabelid);
+int dvb_nit_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_bat_callback  
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_sdt_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+int dvb_tdt_callback
+  (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
+
+/*
+ * Delivery systems and DVB API wrappers
+ *
+ * Note: although these are really only useful for linuxDVB, they are
+ *       used in mpegts so that tsfile can be used to debug issues
+ */
+#if ENABLE_DVBAPI
+
+#include <linux/dvb/version.h>
+#include <linux/dvb/frontend.h>
+
+typedef struct dvb_frontend_parameters dvb_frontend_parameters_t;
+
+typedef enum polarisation {
+       POLARISATION_HORIZONTAL     = 0x00,
+       POLARISATION_VERTICAL       = 0x01,
+       POLARISATION_CIRCULAR_LEFT  = 0x02,
+       POLARISATION_CIRCULAR_RIGHT = 0x03
+} polarisation_t;
+
+typedef struct dvb_mux_conf
+{
+  dvb_frontend_parameters_t dmc_fe_params;
+  
+  // Additional DVB-S fields
+  polarisation_t            dmc_fe_polarisation;
+  int                       dmc_fe_orbital_pos;
+  char                      dmc_fe_orbital_dir;
+#if DVB_API_VERSION >= 5
+  fe_modulation_t           dmc_fe_modulation;
+  fe_delivery_system_t      dmc_fe_delsys;
+  fe_rolloff_t              dmc_fe_rolloff;
+#endif
+} dvb_mux_conf_t;
+
+/* conversion routines */
+const char *dvb_rolloff2str ( int rolloff );
+const char *dvb_delsys2str  ( int delsys );
+const char *dvb_fec2str     ( int fec );
+const char *dvb_qam2str     ( int qam );
+const char *dvb_bw2str      ( int bw );
+const char *dvb_mode2str    ( int mode );
+const char *dvb_guard2str   ( int guard );
+const char *dvb_hier2str    ( int hier );
+const char *dvb_pol2str     ( int pol );
+
+int dvb_str2rolloff ( const char *str );
+int dvb_str2delsys  ( const char *str );
+int dvb_str2fec     ( const char *str );
+int dvb_str2qam     ( const char *str );
+int dvb_str2bw      ( const char *str );
+int dvb_str2mode    ( const char *str );
+int dvb_str2guard   ( const char *str );
+int dvb_str2hier    ( const char *str );
+int dvb_str2pol     ( const char *str );
+
+#endif /* ENABLE_DVBAPI */
+
 #endif /* DVB_SUPPORT_H */
similarity index 64%
rename from src/input/mpegts/psi.c
rename to src/input/mpegts/dvb_psi.c
index e3c1b2724c6da46bf859a580787e576c7a1975fe..dee7adf76c2674998a4fd036a64d3172f7ce2432 100644 (file)
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "tvheadend.h"
+#include "input/mpegts.h"
+#include "dvb.h"
+#include "tsdemux.h"
+#include "parsers.h"
+#include "lang_codes.h"
+
 #include <assert.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <linux/dvb/version.h>
+#include <linux/dvb/frontend.h>
 
-#include "tvheadend.h"
-#include "psi.h"
-#include "dvb.h"
-#include "tsdemux.h"
-#include "parsers.h"
-#include "parsers/parser_teletext.h" // TODO: only for PID
-#include "lang_codes.h"
+static int
+psi_parse_pmt(mpegts_service_t *t, const uint8_t *ptr, int len, int chksvcid,
+        int delete);
 
-static void
-psi_table_add_pmt(mpegts_mux_t *dm, int pmt_pid);
+/* **************************************************************************
+ * Descriptors
+ * *************************************************************************/
+
+#if ENABLE_DVBAPI
+
+/**
+ * Tables for delivery descriptor parsing
+ */
+static const fe_code_rate_t fec_tab [16] = {
+  FEC_AUTO, FEC_1_2, FEC_2_3, FEC_3_4,
+  FEC_5_6, FEC_7_8, FEC_8_9, 
+#if DVB_API_VERSION >= 5
+  FEC_3_5,
+#else
+  FEC_NONE,
+#endif
+  FEC_4_5, 
+#if DVB_API_VERSION >= 5
+  FEC_9_10,
+#else
+  FEC_NONE,
+#endif
+  FEC_NONE, FEC_NONE,
+  FEC_NONE, FEC_NONE, FEC_NONE, FEC_NONE
+};
+
+/*
+ * Satellite delivery descriptor
+ */
+static mpegts_mux_t *
+dvb_desc_sat_del
+  (mpegts_mux_t *mm, uint16_t onid, uint16_t tsid,
+   const uint8_t *ptr, int len )
+{
+  int frequency, symrate;
+  dvb_mux_conf_t dmc;
+
+  /* Not enough data */
+  if(len < 11) return NULL;
+
+  /* Extract data */
+  frequency = 
+    (bcdtoint(ptr[0]) * 1000000 + bcdtoint(ptr[1]) * 10000 + 
+     bcdtoint(ptr[2]) * 100     + bcdtoint(ptr[3])) * 10;
+  symrate =
+    bcdtoint(ptr[7]) * 100000 + bcdtoint(ptr[8]) * 1000 + 
+    bcdtoint(ptr[9]) * 10     + (ptr[10] >> 4);
+  if (!frequency) {
+    tvhlog(LOG_WARNING, "nit", "dvb-s frequency error");
+    return NULL;
+  }
+  if (!symrate) {
+    tvhlog(LOG_WARNING, "nit", "dvb-s symbol rate error");
+    return NULL;
+  }
+
+  memset(&dmc, 0, sizeof(dmc));
+  dmc.dmc_fe_params.inversion = INVERSION_AUTO;
+  dmc.dmc_fe_params.frequency = frequency * 10;
+  dmc.dmc_fe_orbital_pos      = bcdtoint(ptr[4]) * 100 + bcdtoint(ptr[5]);
+  dmc.dmc_fe_orbital_dir      = (ptr[6] & 0x80) ? 'E' : 'W';
+  dmc.dmc_fe_polarisation     = (ptr[6] >> 5) & 0x03;
+
+  dmc.dmc_fe_params.u.qpsk.symbol_rate = symrate * 100;
+  dmc.dmc_fe_params.u.qpsk.fec_inner   = fec_tab[ptr[10] & 0x0f];
+  
+#if DVB_API_VERSION >= 5
+  static int mtab[4] = {
+    0, QPSK, PSK_8, QAM_16
+  };
+  static int rtab[4] = {
+    ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO
+  };
+  dmc.dmc_fe_delsys     = (ptr[6] & 0x4) ? SYS_DVBS2 : SYS_DVBS;
+  dmc.dmc_fe_modulation = mtab[ptr[6] & 0x3];
+  dmc.dmc_fe_rolloff    = rtab[(ptr[6] >> 3) & 0x3];
+  if (dmc.dmc_fe_delsys == SYS_DVBS &&
+      dmc.dmc_fe_rolloff != ROLLOFF_35) {
+    tvhlog(LOG_WARNING, "nit", "dvb-s rolloff error");
+    return NULL;
+  }
+#endif
+
+  /* Debug */
+  const char *pol = dvb_pol2str(dmc.dmc_fe_polarisation);
+  tvhtrace("nit", "    dvb-s%c pos %d%c freq %d %c sym %d fec %s"
+#if DVB_API_VERSION >= 5
+           " mod %s roff %s"
+#endif
+           ,
+           (ptr[6] & 0x4) ? '2' : ' ',
+           dmc.dmc_fe_orbital_pos, dmc.dmc_fe_orbital_dir,
+           dmc.dmc_fe_params.frequency,
+           pol ? pol[0] : 'X',
+           symrate,
+           dvb_fec2str(dmc.dmc_fe_params.u.qpsk.fec_inner),
+#if DVB_API_VERSION >= 5
+           dvb_qam2str(dmc.dmc_fe_modulation),
+           dvb_rolloff2str(dmc.dmc_fe_rolloff)
+#endif
+          );
+
+  /* Create */
+  return mm->mm_network->mn_create_mux(mm, onid, tsid, &dmc);
+}
+
+/*
+ * Cable delivery descriptor
+ */
+static mpegts_mux_t *
+dvb_desc_cable_del
+  (mpegts_mux_t *mm, uint16_t onid, uint16_t tsid,
+   const uint8_t *ptr, int len )
+{
+  int frequency, symrate;
+  dvb_mux_conf_t dmc;
+
+  static const fe_modulation_t qtab [6] = {
+        QAM_AUTO, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256
+  };
+
+  /* Not enough data */
+  if(len < 11) return NULL;
+
+  /* Extract data */
+  frequency  =
+    bcdtoint(ptr[0]) * 1000000 + bcdtoint(ptr[1]) * 10000 + 
+    bcdtoint(ptr[2]) * 100     + bcdtoint(ptr[3]);
+  symrate    =
+    bcdtoint(ptr[7]) * 100000 + bcdtoint(ptr[8]) * 1000 + 
+    bcdtoint(ptr[9]) * 10     + (ptr[10] >> 4);
+  if (!frequency) {
+    tvhlog(LOG_WARNING, "nit", "dvb-c frequency error");
+    return NULL;
+  }
+  if (!symrate) {
+    tvhlog(LOG_WARNING, "nit", "dvb-c symbol rate error");
+    return NULL;
+  }
+
+  memset(&dmc, 0, sizeof(dmc));
+  dmc.dmc_fe_params.inversion = INVERSION_AUTO;
+  dmc.dmc_fe_params.frequency = frequency * 100;
+
+  dmc.dmc_fe_params.u.qam.symbol_rate  = symrate * 100;
+  if((ptr[6] & 0x0f) >= sizeof(qtab))
+    dmc.dmc_fe_params.u.qam.modulation = QAM_AUTO;
+  else
+    dmc.dmc_fe_params.u.qam.modulation = qtab[ptr[6] & 0x0f];
+  dmc.dmc_fe_params.u.qam.fec_inner    = fec_tab[ptr[10] & 0x07];
+
+  /* Debug */
+  tvhtrace("nit", "    dvb-c freq %d sym %d mod %s fec %s",
+           frequency, 
+           symrate,
+           dvb_qam2str(dmc.dmc_fe_params.u.qam.modulation),
+           dvb_fec2str(dmc.dmc_fe_params.u.qam.fec_inner));
+
+  /* Create */
+  return mm->mm_network->mn_create_mux(mm, onid, tsid, &dmc);
+}
+
+/*
+ * Terrestrial delivery descriptor
+ */
+static mpegts_mux_t *
+dvb_desc_terr_del
+  (mpegts_mux_t *mm, uint16_t onid, uint16_t tsid,
+   const uint8_t *ptr, int len )
+{
+  static const fe_bandwidth_t btab [8] = {
+    BANDWIDTH_8_MHZ, BANDWIDTH_7_MHZ, BANDWIDTH_6_MHZ, BANDWIDTH_AUTO, 
+    BANDWIDTH_AUTO,  BANDWIDTH_AUTO,  BANDWIDTH_AUTO,  BANDWIDTH_AUTO
+  };  
+  static const fe_modulation_t ctab [4] = {
+    QPSK, QAM_16, QAM_64, QAM_AUTO
+  };
+  static const fe_guard_interval_t gtab [4] = {
+    GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_4
+  };
+  static const fe_transmit_mode_t ttab [4] = {
+    TRANSMISSION_MODE_2K,
+    TRANSMISSION_MODE_8K,
+#if DVB_API_VERSION >= 5
+    TRANSMISSION_MODE_4K, 
+#else
+    TRANSMISSION_MODE_AUTO,
+#endif
+    TRANSMISSION_MODE_AUTO
+};
+  static const fe_hierarchy_t htab [8] = {
+    HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, HIERARCHY_4,
+    HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, HIERARCHY_4
+  };
+
+  int frequency;
+  dvb_mux_conf_t dmc;
+
+  /* Not enough data */
+  if (len < 11) return NULL;
+
+  /* Extract data */
+  frequency     = ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]);
+  if (!frequency) {
+    tvhlog(LOG_WARNING, "nit", "dvb-c frequency error");
+    return NULL;
+  }
+
+  memset(&dmc, 0, sizeof(dmc));
+  dmc.dmc_fe_params.frequency = frequency * 10;
+
+  dmc.dmc_fe_params.u.ofdm.bandwidth             = btab[(ptr[4] >> 5) & 0x7];
+  dmc.dmc_fe_params.u.ofdm.constellation         = ctab[(ptr[5] >> 6) & 0x3];
+  dmc.dmc_fe_params.u.ofdm.hierarchy_information = htab[(ptr[5] >> 3) & 0x3];
+  dmc.dmc_fe_params.u.ofdm.code_rate_HP          = fec_tab[(ptr[5] + 1) & 0x7];
+  dmc.dmc_fe_params.u.ofdm.code_rate_LP          = fec_tab[((ptr[6] + 1) >> 5) & 0x7];
+  dmc.dmc_fe_params.u.ofdm.guard_interval        = gtab[(ptr[6] >> 3) & 0x3];
+  dmc.dmc_fe_params.u.ofdm.transmission_mode     = ttab[(ptr[6] >> 1) & 0x3];
+
+  /* Debug */
+  tvhtrace("nit", "    dvb-t freq %d bw %s cons %s hier %s code_rate %s %s guard %s trans %s",
+           frequency,
+           dvb_bw2str(dmc.dmc_fe_params.u.ofdm.bandwidth),
+           dvb_qam2str(dmc.dmc_fe_params.u.ofdm.constellation),
+           dvb_hier2str(dmc.dmc_fe_params.u.ofdm.hierarchy_information),
+           dvb_fec2str(dmc.dmc_fe_params.u.ofdm.code_rate_HP),
+           dvb_fec2str(dmc.dmc_fe_params.u.ofdm.code_rate_LP),
+           dvb_guard2str(dmc.dmc_fe_params.u.ofdm.guard_interval),
+           dvb_mode2str(dmc.dmc_fe_params.u.ofdm.transmission_mode));
+  
+  /* Create */
+  return mm->mm_network->mn_create_mux(mm, onid, tsid, &dmc);
+}
+#endif /* ENABLE_DVBAPI */
+
+/* **************************************************************************
+ * Tables
+ * *************************************************************************/
 
 /*
  * PAT processing
  */
 
 int
-psi_pat_callback
+dvb_pat_callback
   (mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
 {
   uint16_t sid, pid, tsid;
+  uint16_t nit_pid = 0x10;
   mpegts_mux_t          *mm  = mt->mt_mux;
-  tvhtrace("pat", "tableid %d len %d", tableid, len);
+  tvhtrace("pat", "tableid %02X len %d", tableid, len);
   tvhlog_hexdump("pat", ptr, len);
 
   /* Not enough data */
@@ -70,27 +314,32 @@ psi_pat_callback
 
     /* NIT PID */
     if (sid == 0) {
-      tvhtrace("pat", "NIT on PID %04X (%d)", pid, pid);
-#if TODO_FIXME
-      if (pid != 0x10 && pid != 0x00)
-        mpegts_table_add(mm, 0, 0, psi_nit_callback, NULL, "nit",
-                         TDT_CRC | TDT_QUICKREQ, pid)
-#endif
+      if (pid) {
+        tvhtrace("pat", "NIT on PID %04X (%d)", pid, pid);
+        nit_pid = pid;
+      }
 
     /* Service */
     } else if (pid) {
-      int save = 0;
       tvhtrace("pat", "SID %04X (%d) on PID %04X (%d)", sid, sid, pid, pid);
+#if 0
+      int save = 0;
       if (mpegts_service_find(mm, sid, pid, NULL, &save))
         if (save)
-          psi_table_add_pmt(mm, pid);
-      // TODO: FIXME: make PMT monitoring optional
+          mpegts_table_add(mm, DVB_PMT_BASE, DVB_PMT_MASK, dvb_pmt_callback,
+                           NULL, "pmt", MT_CRC | MT_QUICKREQ, pid);
+#endif
     }
 
     /* Next */
     ptr += 4;
     len -= 4;
   }
+
+  /* Install NIT monitor */
+  mpegts_table_add(mm, DVB_NIT_BASE, DVB_NIT_MASK, dvb_nit_callback,
+                   NULL, "nit", MT_CRC | MT_QUICKREQ, nit_pid);
+
   return 0;
 }
 
@@ -98,13 +347,13 @@ psi_pat_callback
  * PMT processing
  */
 
-static int
-psi_pmt_callback
+int
+dvb_pmt_callback
   (mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
 {
   mpegts_mux_t *mm = mt->mt_mux;
   mpegts_service_t *s;
-  tvhtrace("pmt", "tableid %d len %d", tableid, len);
+  tvhtrace("pmt", "tableid %02X len %d", tableid, len);
   tvhlog_hexdump("pmt", ptr, len);
 
   LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link) {
@@ -126,114 +375,100 @@ psi_pmt_callback
   return 0;
 }
 
-static void
-psi_table_add_pmt(mpegts_mux_t *mm, int pmt_pid)
-{
-  char pmtname[100];
-  snprintf(pmtname, sizeof(pmtname), "PMT(%d)", pmt_pid);
-  mpegts_table_add(mm, 0x2, 0xff, psi_pmt_callback, NULL, pmtname,
-                   MT_CRC | MT_QUICKREQ, pmt_pid);
-}
-
-#if 0
-void
-dvb_table_rem_pmt(dvb_mux_t *dm, int pmt_pid)
-{
-  th_dvb_mux_instance_t *tdmi = dm->dm_current_tdmi;
-  th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
-  th_dvb_table_t *tdt = NULL;
-  LIST_FOREACH(tdt, &dm->dm_tables, tdt_link)
-    if (tdt->tdt_pid == pmt_pid && tdt->tdt_callback == dvb_pmt_callback)
-      break;
-  if (tdt)
-    dvb_tdt_destroy(tda, tdmi, tdt);
-}
-#endif
-
-
 /*
- * Section assembly
+ * NIT processing
  */
-
-static int
-psi_section_reassemble0(psi_section_t *ps, const uint8_t *data, 
-      int len, int start, int crc,
-      section_handler_t *cb, void *opaque)
+int
+dvb_nit_callback
+  (mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
 {
-  int excess, tsize;
+  int i;
+  uint8_t  dlen, dtag, stype;
+  uint16_t llen, dllen;
+  uint16_t nid, onid, tsid, sid;
+  mpegts_mux_t     *mm = mt->mt_mux, *mux;
+  mpegts_network_t *mn = mm->mm_network;
+  char name[256];
+
+  tvhtrace("nit", "tableid %02X len %d", tableid, len);
+  tvhlog_hexdump("nit", ptr, len);
+
+  /* Not long enough */
+  if (len < 7)
+    return -1;
 
-  if(start) {
-    // Payload unit start indicator
-    ps->ps_offset = 0;
-    ps->ps_lock = 1;
-  }
+  /* Ignore "next" */
+  if (!(ptr[2] & 0x01))
+    return -1;
 
-  if(!ps->ps_lock)
+  /* Specific NID */
+  nid = (ptr[0] << 8) | ptr[1];
+  if (mn->mn_nid) {
+    if (mn->mn_nid != nid)
+      return -1;
+  
+  /* Only use "this" network */
+  } else if (tableid != 0x40) {
     return -1;
+  }
 
-  memcpy(ps->ps_data + ps->ps_offset, data, len);
-  ps->ps_offset += len;
+  /* Network Descriptors */
+  *name = 0;
+  FOREACH_DVB_DESC(ptr, len, 5, llen, dtag, dlen) {
+    tvhtrace("nit", "  dtag %02X dlen %d", dtag, dlen);
 
-  if(ps->ps_offset < 3) {
-    /* We don't know the total length yet */
-    return len;
+    switch (dtag) {
+      case DVB_DESC_NETWORK_NAME:
+        if (dvb_get_string(name, sizeof(name), ptr, dlen, NULL, NULL))
+          return -1;
+        break;
+      case DVB_DESC_MULTI_NETWORK_NAME:
+        // TODO: implement this?
+        break;
+    }
   }
-
-  tsize = 3 + (((ps->ps_data[1] & 0xf) << 8) | ps->ps_data[2]);
-  if(ps->ps_offset < tsize)
-    return len; // Not there yet
   
-  excess = ps->ps_offset - tsize;
+  tvhtrace("nit", "network %04X (%d) [%s]", nid, nid, name);
+  // TODO: set network name
 
-  if(crc && tvh_crc32(ps->ps_data, tsize, 0xffffffff))
-    return -1;
+  /* Transport length */
+  FOREACH_DVB_LOOP(ptr, len, 0, 6, llen) {
+    mux   = NULL;
+    tsid  = (ptr[0] << 8) | ptr[1];
+    onid  = (ptr[2] << 8) | ptr[3];
 
-  ps->ps_offset = 0;
-  if (cb)
-    cb(ps->ps_data, tsize - (crc ? 4 : 0), opaque);
-  return len - excess;
-}
+    tvhtrace("nit", "  onid %04X (%d) tsid %04X (%d)", onid, onid, tsid, tsid);
 
+    FOREACH_DVB_DESC(ptr, len, 4, dllen, dtag, dlen) {
+      tvhtrace("nit", "    dtag %02X dlen %d", dtag, dlen);
+      //tvhlog_hexdump("nit", ptr, dlen);
 
-/**
- *
- */
-void
-psi_section_reassemble(psi_section_t *ps, const uint8_t *tsb, int crc,
-           section_handler_t *cb, void *opaque)
-{
-  int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
-  int pusi = tsb[1] & 0x40;
-  int r;
-
-  if(off >= 188) {
-    ps->ps_lock = 0;
-    return;
-  }
-  
-  if(pusi) {
-    int len = tsb[off++];
-    if(len > 0) {
-      if(len > 188 - off) {
-        ps->ps_lock = 0;
-        return;
+      switch (dtag) {
+        case DVB_DESC_SAT_DEL:
+          mux = dvb_desc_sat_del(mm, onid, tsid, ptr, dlen);
+          break;
+        case DVB_DESC_CABLE_DEL:
+          mux = dvb_desc_cable_del(mm, onid, tsid, ptr, dlen);
+          break;
+        case DVB_DESC_TERR_DEL:
+          mux = dvb_desc_terr_del(mm, onid, tsid, ptr, dlen);
+          break;
+        case DVB_DESC_LOCAL_CHAN:
+          break;
+        case DVB_DESC_SERVICE_LIST:
+          for (i = 0; i < dlen; i += 3) {
+            sid   = (ptr[i] << 8) | ptr[i+1];
+            stype = ptr[i+2];
+            tvhtrace("nit", "    service %04X (%d) type %d", sid, sid, stype);
+            if (mux)
+              mux->mm_network->mn_create_service(mux, sid, 0);
+          }
+          break;
       }
-      psi_section_reassemble0(ps, tsb + off, len, 0, crc, cb, opaque);
-      off += len;
     }
   }
 
-  while(off < 188) {
-    r = psi_section_reassemble0(ps, tsb + off, 188 - off, pusi, crc,
-        cb, opaque);
-    if(r < 0) {
-      ps->ps_lock = 0;
-      break;
-    }
-    off += r;
-    pusi = 0;
-  }
+  return 0;
 }
 
 /**
@@ -367,7 +602,7 @@ psi_desc_teletext(mpegts_service_t *t, const uint8_t *ptr, int size,
 
       // We put the teletext subtitle driven streams on a list of pids
       // higher than normal MPEG TS (0x2000 ++)
-      int pid = PID_TELETEXT_BASE + page;
+      int pid = DVB_TELETEXT_BASE + page;
     
       if((st = service_stream_find((service_t*)t, pid)) == NULL) {
         r |= PMT_UPDATE_NEW_STREAM;
@@ -723,6 +958,7 @@ psi_parse_pmt(mpegts_service_t *t, const uint8_t *ptr, int len, int chksvcid,
   return 0;
 }
 
+#if 0
 /**
  * Store service settings into message
  */
@@ -936,3 +1172,4 @@ psi_load_service_settings(htsmsg_t *m, mpegts_service_t *t)
   }
   sort_pids(t);
 }
+#endif
similarity index 65%
rename from src/input/mpegts/linuxdvb/dvb_support.c
rename to src/input/mpegts/dvb_support.c
index fc58cfc74c0b830788d54edeefdb434d2e099396..f342e9544603c891fe72222c09419aa39d052c07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  TV Input - DVB - Support functions
+ *  TV Input - DVB - Support/Conversion functions
  *  Copyright (C) 2007 Andreas Öman
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -16,8 +16,6 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <pthread.h>
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
@@ -31,7 +29,6 @@
 #include <linux/dvb/frontend.h>
 
 #include "tvheadend.h"
-#include "dvb_support.h"
 #include "dvb.h"
 #include "dvb_charset_tables.h"
 
@@ -196,7 +193,9 @@ static inline size_t dvb_convert(int conv,
  */
 
 int
-dvb_get_string(char *dst, size_t dstlen, const uint8_t *src, size_t srclen, const char *dvb_charset, dvb_string_conv_t *conv)
+dvb_get_string
+  (char *dst, size_t dstlen, const uint8_t *src, size_t srclen, 
+   const char *dvb_charset, dvb_string_conv_t *conv)
 {
   int ic;
   size_t len, outlen;
@@ -327,10 +326,6 @@ atsc_utf16_to_utf8(uint8_t *src, int len, char *buf, int buflen)
   *buf = 0;
 }
 
-
-
-
-
 /*
  * DVB time and date functions
  */
@@ -375,105 +370,140 @@ dvb_convert_date(uint8_t *dvb_buf)
   return (timegm(&dvb_time));
 }
 
-/**
- *
+/*
+ * DVB API helpers
  */
-static struct strtab adaptertype[] = {
-  { "DVB-S",  FE_QPSK },
-  { "DVB-C",  FE_QAM },
-  { "DVB-T",  FE_OFDM },
-  { "ATSC",   FE_ATSC },
+#if ENABLE_DVBAPI
+
+#define dvb_str2val(p)\
+const char *dvb_##p##2str (int p)         { return val2str(p, p##tab); }\
+int         dvb_str2##p   (const char *p) { return str2val(p, p##tab); }
+
+static struct strtab rollofftab[] = {
+#if DVB_API_VERSION >= 5
+  { "ROLLOFF_35",           ROLLOFF_35 },
+  { "ROLLOFF_20",           ROLLOFF_20 },
+  { "ROLLOFF_25",           ROLLOFF_25 },
+  { "ROLLOFF_AUTO",         ROLLOFF_AUTO }
+#endif
 };
+dvb_str2val(rolloff);
+
+static struct strtab delsystab[] = {
+#if DVB_API_VERSION >= 5
+  { "SYS_UNDEFINED",        SYS_UNDEFINED },
+  { "SYS_DVBC_ANNEX_AC",    SYS_DVBC_ANNEX_AC },
+  { "SYS_DVBC_ANNEX_B",     SYS_DVBC_ANNEX_B },
+  { "SYS_DVBT",             SYS_DVBT },
+  { "SYS_DSS",              SYS_DSS },
+  { "SYS_DVBS",             SYS_DVBS },
+  { "SYS_DVBS2",            SYS_DVBS2 },
+  { "SYS_DVBH",             SYS_DVBH },
+  { "SYS_ISDBT",            SYS_ISDBT },
+  { "SYS_ISDBS",            SYS_ISDBS },
+  { "SYS_ISDBC",            SYS_ISDBC },
+  { "SYS_ATSC",             SYS_ATSC },
+  { "SYS_ATSCMH",           SYS_ATSCMH },
+  { "SYS_DMBTH",            SYS_DMBTH },
+  { "SYS_CMMB",             SYS_CMMB },
+  { "SYS_DAB",              SYS_DAB }
+#endif
+};
+dvb_str2val(delsys);
+
+static struct strtab fectab[] = {
+  { "NONE",                 FEC_NONE },
+  { "1/2",                  FEC_1_2 },
+  { "2/3",                  FEC_2_3 },
+  { "3/4",                  FEC_3_4 },
+  { "4/5",                  FEC_4_5 },
+  { "5/6",                  FEC_5_6 },
+  { "6/7",                  FEC_6_7 },
+  { "7/8",                  FEC_7_8 },
+  { "8/9",                  FEC_8_9 },
+  { "AUTO",                 FEC_AUTO },
+#if DVB_API_VERSION >= 5
+  { "3/5",                  FEC_3_5 },
+  { "9/10",                 FEC_9_10 }
+#endif
+};
+dvb_str2val(fec);
+
+static struct strtab qamtab[] = {
+  { "QPSK",                 QPSK },
+  { "QAM16",                QAM_16 },
+  { "QAM32",                QAM_32 },
+  { "QAM64",                QAM_64 },
+  { "QAM128",               QAM_128 },
+  { "QAM256",               QAM_256 },
+  { "AUTO",                 QAM_AUTO },
+  { "8VSB",                 VSB_8 },
+  { "16VSB",                VSB_16 },
+#if DVB_API_VERSION >= 5
+  { "PSK_8",                PSK_8 },
+  { "APSK_16",              APSK_16 },
+  { "APSK_32",              APSK_32 },
+  { "DQPSK",                DQPSK }
+#endif
+};
+dvb_str2val(qam);
+
+static struct strtab bwtab[] = {
+  { "8MHz",                 BANDWIDTH_8_MHZ },
+  { "7MHz",                 BANDWIDTH_7_MHZ },
+  { "6MHz",                 BANDWIDTH_6_MHZ },
+  { "AUTO",                 BANDWIDTH_AUTO },
+#if DVB_API_VERSION >= 5
+  { "5MHz",                 BANDWIDTH_5_MHZ },
+  { "10MHz",                BANDWIDTH_10_MHZ },
+  { "1712kHz",              BANDWIDTH_1_712_MHZ},
+#endif
+};
+dvb_str2val(bw);
+
+static struct strtab modetab[] = {
+  { "2k",                   TRANSMISSION_MODE_2K },
+  { "8k",                   TRANSMISSION_MODE_8K },
+  { "AUTO",                 TRANSMISSION_MODE_AUTO },
+#if DVB_API_VERSION >= 5
+  { "1k",                   TRANSMISSION_MODE_1K },
+  { "2k",                   TRANSMISSION_MODE_16K },
+  { "32k",                  TRANSMISSION_MODE_32K },
+#endif
+};
+dvb_str2val(mode);
+
+static struct strtab guardtab[] = {
+  { "1/32",                 GUARD_INTERVAL_1_32 },
+  { "1/16",                 GUARD_INTERVAL_1_16 },
+  { "1/8",                  GUARD_INTERVAL_1_8 },
+  { "1/4",                  GUARD_INTERVAL_1_4 },
+  { "AUTO",                 GUARD_INTERVAL_AUTO },
+#if DVB_API_VERSION >= 5
+  { "1/128",                GUARD_INTERVAL_1_128 },
+  { "19/128",               GUARD_INTERVAL_19_128 },
+  { "19/256",               GUARD_INTERVAL_19_256},
+#endif
+};
+dvb_str2val(guard);
+
+static struct strtab hiertab[] = {
+  { "NONE",                 HIERARCHY_NONE },
+  { "1",                    HIERARCHY_1 },
+  { "2",                    HIERARCHY_2 },
+  { "4",                    HIERARCHY_4 },
+  { "AUTO",                 HIERARCHY_AUTO }
+};
+dvb_str2val(hier);
 
+static struct strtab poltab[] = {
+  { "Vertical",             POLARISATION_VERTICAL },
+  { "Horizontal",           POLARISATION_HORIZONTAL },
+  { "Left",                 POLARISATION_CIRCULAR_LEFT },
+  { "Right",                POLARISATION_CIRCULAR_RIGHT },
+};
+dvb_str2val(pol);
 
-int
-dvb_str_to_adaptertype(const char *str)
-{
-  return str2val(str, adaptertype);
-}
-
-const char *
-dvb_adaptertype_to_str(int type)
-{
-  return val2str(type, adaptertype) ?: "invalid";
-}
-
-const char *
-dvb_polarisation_to_str(int pol)
-{
-  switch(pol) {
-  case POLARISATION_VERTICAL:       return "V";
-  case POLARISATION_HORIZONTAL:     return "H";
-  case POLARISATION_CIRCULAR_LEFT:  return "L";
-  case POLARISATION_CIRCULAR_RIGHT: return "R";
-  default:                          return "X";
-  }
-}
-
-const char *
-dvb_polarisation_to_str_long(int pol)
-{
-  switch(pol) {
-  case POLARISATION_VERTICAL:        return "Vertical";
-  case POLARISATION_HORIZONTAL:      return "Horizontal";
-  case POLARISATION_CIRCULAR_LEFT:   return "Left";
-  case POLARISATION_CIRCULAR_RIGHT:  return "Right";
-  default:                           return "??";
-  }
-}
-
-
-/**
- *
- */
-static void
-nicenum(char *x, size_t siz, unsigned int v, const char *postfix)
-{
-  if(v < 1000)
-    snprintf(x, siz, "%d%s", v, postfix);
-  else if(v < 1000000)
-    snprintf(x, siz, "%d,%03d%s", v / 1000, v % 1000, postfix);
-  else if(v < 1000000000)
-    snprintf(x, siz, "%d,%03d,%03d%s",
-            v / 1000000, (v % 1000000) / 1000, v % 1000, postfix);
-  else
-    snprintf(x, siz, "%d,%03d,%03d,%03d%s",
-            v / 1000000000, (v % 1000000000) / 1000000,
-            (v % 1000000) / 1000, v % 1000, postfix);
-}
-
-
-/**
- *
- */
-const char *
-dvb_mux_nicefreq(const dvb_mux_t *dm)
-{
-  static char ret[100];
-  int f = dm->dm_conf.dmc_fe_params.frequency;
-  nicenum(ret, sizeof(ret), dm->dm_dn->dn_fe_type == FE_QPSK ? f : f / 1000,
-          " kHz");
-  return ret;
-}
-
-
-/**
- *
- */
-const char *
-dvb_mux_nicename(const dvb_mux_t *dm)
-{
-  static char ret[100];
-  const char *n = dm->dm_network_name;
-
-  snprintf(ret, sizeof(ret), "%s%s%s%s%s",
-           n ?: "",
-           n ? ": " : "",
-           dvb_mux_nicefreq(dm),
-           dm->dm_dn->dn_fe_type == FE_QPSK ? " " : "",
-           dm->dm_dn->dn_fe_type == FE_QPSK ?
-           dvb_polarisation_to_str_long(dm->dm_conf.dmc_polarisation) : 
-           "");
-  return ret;
-}
+#undef dvb_str2val
 
+#endif /* ENABLE_DVBAPI */
index 47f502bb7e8652eff5a2c8b6edbbd02ad1cf1dca..955e166de39dd935304a52ff760ff4b69e51e330 100644 (file)
@@ -151,8 +151,8 @@ mpegts_input_table_dispatch ( mpegts_mux_t *mm, mpegts_table_feed_t *mtf )
   for (i = 0; i < len; i++) {
     mt = vec[i];
     if (!mt->mt_destroyed && mt->mt_pid == pid)
-      psi_section_reassemble(&mt->mt_sect, mtf->mtf_tsb, 0,
-                             mpegts_table_dispatch, mt);
+      mpegts_psi_section_reassemble(&mt->mt_sect, mtf->mtf_tsb, 0,
+                                    mpegts_table_dispatch, mt);
     mpegts_table_release(mt);
   }
 }
index 70b7c5afb047633ce3b3ac0ce823fd10aa3534ab..5c7f42274f5d42921e246bdce743321be232639d 100644 (file)
@@ -30,7 +30,7 @@ const idclass_t mpegts_network_class =
 
 static mpegts_mux_t *
 mpegts_network_create_mux
-  ( mpegts_mux_t *mm, uint16_t sid, uint16_t tsid, void *aux )
+  ( mpegts_mux_t *mm, uint16_t sid, uint16_t tsid, dvb_mux_conf_t *aux )
 {
   return NULL;
 }
index bec3235d60366d3e5b49b9d2b371e06ecc90015a..7efc79fd34ede900694110dab3c4a7714218d036 100644 (file)
@@ -115,7 +115,7 @@ mpegts_table_destroy ( mpegts_table_t *mt )
 void
 mpegts_table_add
   ( mpegts_mux_t *mm, int tableid, int mask,
-    mpegts_table_callback callback, void *opaque,
+    mpegts_table_callback_t callback, void *opaque,
     const char *name, int flags, int pid )
 {
   mpegts_table_t *mt;
@@ -160,6 +160,94 @@ mpegts_table_flush_all ( mpegts_mux_t *mm )
     mpegts_table_destroy(mt);
 }
 
+/*
+ * Section assembly
+ */
+static int
+mpegts_psi_section_reassemble0
+  ( mpegts_psi_section_t *ps, const uint8_t *data, 
+    int len, int start, int crc,
+    mpegts_psi_section_callback_t cb, void *opaque)
+{
+  int excess, tsize;
+
+  if(start) {
+    // Payload unit start indicator
+    ps->ps_offset = 0;
+    ps->ps_lock = 1;
+  }
+
+  if(!ps->ps_lock)
+    return -1;
+
+  memcpy(ps->ps_data + ps->ps_offset, data, len);
+  ps->ps_offset += len;
+
+  if(ps->ps_offset < 3) {
+    /* We don't know the total length yet */
+    return len;
+  }
+
+  tsize = 3 + (((ps->ps_data[1] & 0xf) << 8) | ps->ps_data[2]);
+  if(ps->ps_offset < tsize)
+    return len; // Not there yet
+  
+  excess = ps->ps_offset - tsize;
+
+  if(crc && tvh_crc32(ps->ps_data, tsize, 0xffffffff))
+    return -1;
+
+  ps->ps_offset = 0;
+  if (cb)
+    cb(ps->ps_data, tsize - (crc ? 4 : 0), opaque);
+  return len - excess;
+}
+
+
+/**
+ *
+ */
+void
+mpegts_psi_section_reassemble
+  (mpegts_psi_section_t *ps, const uint8_t *tsb, int crc,
+   mpegts_psi_section_callback_t cb, void *opaque)
+{
+  int off  = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
+  int pusi = tsb[1] & 0x40;
+  int r;
+
+  if(off >= 188) {
+    ps->ps_lock = 0;
+    return;
+  }
+  
+  if(pusi) {
+    int len = tsb[off++];
+    if(len > 0) {
+      if(len > 188 - off) {
+        ps->ps_lock = 0;
+        return;
+      }
+      mpegts_psi_section_reassemble0(ps, tsb + off, len, 0, crc, cb, opaque);
+      off += len;
+    }
+  }
+
+  while(off < 188) {
+    r = mpegts_psi_section_reassemble0(ps, tsb + off, 188 - off, pusi, crc,
+        cb, opaque);
+    if(r < 0) {
+      ps->ps_lock = 0;
+      break;
+    }
+    off += r;
+    pusi = 0;
+  }
+}
+
+
+
 /******************************************************************************
  * Editor Configuration
  *
index c896496b0290cb59bbcc351f94a6ad5aceac7bda..3e28807df120576a450a9218b9ab51044d67a83d 100644 (file)
 struct mpegts_service;
 struct mpegts_table;
 
-typedef void (section_handler_t)(const uint8_t *data, size_t len, void *opaque);
-
-typedef struct psi_section {
-  int ps_offset;
-  int ps_lock;
-  uint8_t ps_data[PSI_SECTION_SIZE];
-} psi_section_t;
-
-
-void psi_section_reassemble(psi_section_t *ps, const uint8_t *tsb, int crc,
-                           section_handler_t *cb, void *opaque);
-
 int psi_parse_pmt
   (struct mpegts_service *t, const uint8_t *ptr, int len, int chksvcid,
    int delete);
index b8e250d006cfa4bf26d39fcf84d0ecd36f7eafb1..bf0fa07a057ee823eb9703750c5f2dc83bd61a76 100644 (file)
@@ -48,6 +48,7 @@ static void ts_remux(mpegts_service_t *t, const uint8_t *tsb);
 /**
  * Code for dealing with a complete section
  */
+#if TODO_MOVE_THIS
 static void
 got_section(const uint8_t *data, size_t len, void *opaque)
 {
@@ -65,6 +66,7 @@ got_section(const uint8_t *data, size_t len, void *opaque)
 #endif
   }
 }
+#endif
 
 
 /**
@@ -108,11 +110,14 @@ ts_recv_packet0(mpegts_service_t *t, elementary_stream_t *st, const uint8_t *tsb
 
   case SCT_CA:
   case SCT_PMT:
+#if TODO_MOVE_THIS
+    break; // TODO: we should not receive these
     if(st->es_section == NULL)
       st->es_section = calloc(1, sizeof(struct psi_section));
 
     psi_section_reassemble(st->es_section, tsb, st->es_section_docrc,
                           got_section, st);
+#endif
     break;
 
   default:
index 17a610a318b043b4445aa06b316d0b15752a217c..b2fa979add761ea638f17344648334c84873eb90 100644 (file)
@@ -20,7 +20,7 @@
 #include "tvheadend.h"
 #include "tsfile_private.h"
 #include "input.h"
-#include "input/mpegts/psi.h"
+#include "input/mpegts/dvb.h"
 
 #include <sys/epoll.h>
 #include <sys/types.h>
@@ -213,8 +213,8 @@ tsfile_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *t )
   LIST_INSERT_HEAD(&mi->mi_mux_active, t, mmi_active_link);
 
   /* Install table handlers */
-  mpegts_table_add(mm, 0x0, 0xff, psi_pat_callback, NULL, "pat",
-                   MT_QUICKREQ| MT_CRC, 0);
+  mpegts_table_add(mm, DVB_PAT_BASE, DVB_PAT_MASK, dvb_pat_callback,
+                   NULL, "pat", MT_QUICKREQ| MT_CRC, 0);
 #if 0
   mpegts_table_add(mm, 0x1, 0xff, dvb_cat_callback, NULL, "cat",
                    MT_CRC, 1);
index 9958bdc4fd54f3bff1c194c1408369b10fa423b8..36761789fef7f02eb16ec62d43d63ebc09815086 100644 (file)
@@ -58,13 +58,6 @@ typedef struct elementary_stream {
   int es_demuxer_fd;
   int es_peak_presentation_delay; /* Max seen diff. of DTS and PTS */
 
-  struct psi_section *es_section;
-  int es_section_docrc;           /* Set if we should verify CRC on tables */
-#ifdef TODO_CAN_THIS_BE_REMOVED
-  pid_section_callback_t *es_got_section;
-#endif
-  void *es_got_section_opaque;
-
   /* PCR recovery */
 
   int es_pcr_recovery_fails;
@@ -322,14 +315,6 @@ typedef struct service {
   struct in6_addr s_iptv_group6;
   uint16_t s_iptv_port;
   int s_iptv_fd;
-
-  /**
-   * For per-transport PAT/PMT parsers, allocated on demand
-   * Free'd by transport_destroy
-   */
-  struct psi_section *s_pat_section;
-  struct psi_section *s_pmt_section;
-  // Note: are the above still required!
 #endif
 
   /**