]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Missed in last commit
authorAndreas Öman <andreas@lonelycoder.com>
Mon, 29 Nov 2010 20:07:07 +0000 (20:07 +0000)
committerAndreas Öman <andreas@lonelycoder.com>
Mon, 29 Nov 2010 20:07:07 +0000 (20:07 +0000)
src/service.h [new file with mode: 0644]

diff --git a/src/service.h b/src/service.h
new file mode 100644 (file)
index 0000000..0153bdf
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ *  Tvheadend
+ *  Copyright (C) 2010 Andreas Öman
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SERVICE_H__
+#define SERVICE_H__
+
+#define PID_TELETEXT_BASE 0x2000
+
+#include "htsmsg.h"
+
+
+
+/**
+ * Descrambler superclass
+ *
+ * Created/Destroyed on per-transport basis upon transport start/stop
+ */
+typedef struct th_descrambler {
+  LIST_ENTRY(th_descrambler) td_service_link;
+
+  void (*td_table)(struct th_descrambler *d, struct service *t,
+                  struct th_stream *st, 
+                  const uint8_t *section, int section_len);
+
+  int (*td_descramble)(struct th_descrambler *d, struct service *t,
+                      struct th_stream *st, const uint8_t *tsb);
+
+  void (*td_stop)(struct th_descrambler *d);
+
+} th_descrambler_t;
+
+
+/*
+ * Section callback, called when a PSI table is fully received
+ */
+typedef void (pid_section_callback_t)(struct service *t,
+                                     struct th_stream *pi,
+                                     const uint8_t *section, int section_len);
+
+
+LIST_HEAD(caid_list, caid);
+/**
+ *
+ */
+typedef struct caid {
+  LIST_ENTRY(caid) link;
+
+  uint8_t delete_me;
+  uint16_t caid;
+  uint32_t providerid;
+
+} caid_t;
+
+/*
+ * Stream, one media component for a service.
+ *
+ * XXX: This should be renamed to 'elementary_stream' or something
+ */
+typedef struct th_stream {
+
+  TAILQ_ENTRY(th_stream) st_link;
+  int st_position;
+  struct service *st_service;
+
+  streaming_component_type_t st_type;
+  int st_index;
+
+  uint16_t st_aspect_num;
+  uint16_t st_aspect_den;
+
+  char st_lang[4];           /* ISO 639 3-letter language code */
+  uint16_t st_composition_id;
+  uint16_t st_ancillary_id;
+
+  int16_t st_pid;
+  uint16_t st_parent_pid;    /* For subtitle streams originating from 
+                               a teletext stream. this is the pid
+                               of the teletext stream */
+
+  uint8_t st_cc;             /* Last CC */
+  uint8_t st_cc_valid;       /* Is CC valid at all? */
+
+  avgstat_t st_cc_errors;
+  avgstat_t st_rate;
+
+  int st_demuxer_fd;
+  int st_peak_presentation_delay; /* Max seen diff. of DTS and PTS */
+
+  struct psi_section *st_section;
+  int st_section_docrc;           /* Set if we should verify CRC on tables */
+  pid_section_callback_t *st_got_section;
+  void *st_got_section_opaque;
+
+  /* PCR recovery */
+
+  int st_pcr_recovery_fails;
+  int64_t st_pcr_real_last;     /* realtime clock when we saw last PCR */
+  int64_t st_pcr_last;          /* PCR clock when we saw last PCR */
+  int64_t st_pcr_drift;
+
+  /* For service stream packet reassembly */
+
+  sbuf_t st_buf;
+
+  uint32_t st_startcond;
+  uint32_t st_startcode;
+  uint32_t st_startcode_offset;
+  int st_parser_state;
+  int st_parser_ptr;
+  void *st_priv;          /* Parser private data */
+
+  sbuf_t st_buf_ps;       // program stream reassembly (analogue adapters)
+  sbuf_t st_buf_a;        // Audio packet reassembly
+
+  uint8_t *st_global_data;
+  int st_global_data_len;
+  int st_incomplete;
+  int st_ssc_intercept;
+  int st_ssc_ptr;
+  uint8_t st_ssc_buf[32];
+
+  struct th_pkt *st_curpkt;
+  int64_t st_curpts;
+  int64_t st_curdts;
+  int64_t st_prevdts;
+  int64_t st_nextdts;
+  int st_frame_duration;
+  int st_width;
+  int st_height;
+
+  int st_meta_change;
+
+  /* CA ID's on this stream */
+  struct caid_list st_caids;
+
+  int st_vbv_size;        /* Video buffer size (in bytes) */
+  int st_vbv_delay;       /* -1 if CBR */
+
+  /* */
+
+  int st_delete_me;      /* Temporary flag for deleting streams */
+
+  /* Error log limiters */
+
+  loglimiter_t st_loglimit_cc;
+  loglimiter_t st_loglimit_pes;
+  
+  char *st_nicename;
+
+  /* Teletext subtitle */ 
+  char st_blank; // Last subtitle was blank
+
+
+} th_stream_t;
+
+
+/**
+ *
+ */
+typedef struct service {
+
+  LIST_ENTRY(service) s_hash_link;
+
+  enum {
+    SERVICE_TYPE_DVB,
+    SERVICE_TYPE_IPTV,
+    SERVICE_TYPE_V4L,
+  } s_type;
+
+  enum {
+    /**
+     * Transport is idle.
+     */
+    SERVICE_IDLE,
+
+    /**
+     * Transport producing output
+     */
+    SERVICE_RUNNING,
+
+    /**
+     * Destroyed, but pointer is till valid. 
+     * This would be the case if transport_destroy() did not actually free 
+     * the transport because there are references held to it.
+     *
+     * Reference counts can be used so that code can hold a pointer to 
+     * a transport without having the global lock.
+     *
+     * Note: No fields in the transport may be accessed without the
+     * global lock held. Thus, the global_lock must be reaquired and
+     * then s_status must be checked. If it is ZOMBIE the code must
+     * just drop the refcount and pretend that the transport never
+     * was there in the first place.
+     */
+    SERVICE_ZOMBIE, 
+  } s_status;
+
+  /**
+   * Refcount, operated using atomic.h ops.
+   */ 
+  int s_refcount;
+
+  /**
+   *
+   */
+  int s_flags;
+
+#define S_DEBUG 0x1
+
+  /**
+   * Source type is used to determine if an output requesting
+   * MPEG-TS can shortcut all the parsing and remuxing.
+   */ 
+  enum {
+    S_MPEG_TS,
+    S_OTHER,
+  } s_source_type;
+
+  /**
+   * PID carrying the programs PCR.
+   * XXX: We don't support transports that does not carry
+   * the PCR in one of the content streams.
+   */
+  uint16_t s_pcr_pid;
+
+  /**
+   * PID for the PMT of this MPEG-TS stream.
+   */
+  uint16_t s_pmt_pid;
+
+  /**
+   * Set if transport is enabled (the default).  If disabled it should
+   * not be considered when chasing for available transports during
+   * subscription scheduling.
+   */
+  int s_enabled;
+
+  /**
+   * Last PCR seen, we use it for a simple clock for rawtsinput.c
+   */
+  int64_t s_pcr_last;
+  int64_t s_pcr_last_realtime;
+  
+  LIST_ENTRY(service) s_group_link;
+
+  LIST_ENTRY(service) s_active_link;
+
+  LIST_HEAD(, th_subscription) s_subscriptions;
+
+  int (*s_start_feed)(struct service *t, unsigned int weight,
+                       int force_start);
+
+  void (*s_refresh_feed)(struct service *t);
+
+  void (*s_stop_feed)(struct service *t);
+
+  void (*s_config_save)(struct service *t);
+
+  void (*s_setsourceinfo)(struct service *t, struct source_info *si);
+
+  int (*s_quality_index)(struct service *t);
+
+  int (*s_grace_period)(struct service *t);
+
+  void (*s_dtor)(struct service *t);
+
+  /*
+   * Per source type structs
+   */
+  struct th_dvb_mux_instance *s_dvb_mux_instance;
+
+  /**
+   * Unique identifer (used for storing on disk, etc)
+   */
+  char *s_identifier;
+
+  /**
+   * Name usable for displaying to user
+   */
+  char *s_nicename;
+
+  /**
+   * Service ID according to EN 300 468
+   */
+  uint16_t s_dvb_service_id;
+
+  uint16_t s_channel_number;
+
+  /**
+   * Service name (eg. DVB service name as specified by EN 300 468)
+   */
+  char *s_svcname;
+
+  /**
+   * Provider name (eg. DVB provider name as specified by EN 300 468)
+   */
+  char *s_provider;
+
+  enum {
+    /* Service types defined in EN 300 468 */
+
+    ST_SDTV       = 0x1,    /* SDTV (MPEG2) */
+    ST_RADIO      = 0x2,
+    ST_HDTV       = 0x11,   /* HDTV (MPEG2) */
+    ST_AC_SDTV    = 0x16,   /* Advanced codec SDTV */
+    ST_AC_HDTV    = 0x19,   /* Advanced codec HDTV */
+  } s_servicetype;
+
+
+  /**
+   * Teletext...
+   */
+  th_commercial_advice_t s_tt_commercial_advice;
+  int s_tt_rundown_content_length;
+  time_t s_tt_clock;   /* Network clock as determined by teletext decoder */
+  /**
+   * Channel mapping
+   */
+  LIST_ENTRY(service) s_ch_link;
+  struct channel *s_ch;
+
+  /**
+   * Service probe, see serviceprobe.c for details
+   */
+  int s_sp_onqueue;
+  TAILQ_ENTRY(service) s_sp_link;
+
+  /**
+   * Pending save.
+   *
+   * transport_request_save() will enqueue the transport here.
+   * We need to do this if we don't hold the global lock.
+   * This happens when we update PMT from within the TS stream itself.
+   * Then we hold the stream mutex, and thus, can not obtain the global lock
+   * as it would cause lock inversion.
+   */
+  int s_ps_onqueue;
+  TAILQ_ENTRY(service) s_ps_link;
+
+  /**
+   * Timer which is armed at transport start. Once it fires
+   * it will check if any packets has been parsed. If not the status
+   * will be set to TRANSPORT_STATUS_NO_INPUT
+   */
+  gtimer_t s_receive_timer;
+
+  /**
+   * IPTV members
+   */
+  char *s_iptv_iface;
+  struct in_addr s_iptv_group;
+  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;
+
+  /**
+   * V4l members
+   */
+
+  struct v4l_adapter *s_v4l_adapter;
+  int s_v4l_frequency; // In Hz
+  
+
+  /*********************************************************
+   *
+   * Streaming part of transport
+   *
+   * All access to fields below this must be protected with
+   * s_stream_mutex held.
+   *
+   * Note: Code holding s_stream_mutex should _never_ 
+   * acquire global_lock while already holding s_stream_mutex.
+   *
+   */
+
+  /**
+   * Mutex to be held during streaming.
+   * This mutex also protects all th_stream_t instances for this
+   * transport.
+   */
+  pthread_mutex_t s_stream_mutex;
+
+
+  /**
+   * Condition variable to singal when streaming_status changes
+   * interlocked with s_stream_mutex
+   */
+  pthread_cond_t s_tss_cond;
+  /**
+   *
+   */                     
+  int s_streaming_status;
+
+  // Progress
+#define TSS_INPUT_HARDWARE   0x1
+#define TSS_INPUT_SERVICE    0x2
+#define TSS_MUX_PACKETS      0x4
+#define TSS_PACKETS          0x8
+
+#define TSS_GRACEPERIOD      0x8000
+
+  // Errors
+#define TSS_NO_DESCRAMBLER   0x10000
+#define TSS_NO_ACCESS        0x20000
+
+#define TSS_ERRORS           0xffff0000
+
+
+  /**
+   * For simple streaming sources (such as video4linux) keeping
+   * track of the video and audio stream is convenient.
+   */
+  th_stream_t *s_video;
+  th_stream_t *s_audio;
+  /**
+   * Average continuity errors
+   */
+  avgstat_t s_cc_errors;
+
+  /**
+   * Average bitrate
+   */
+  avgstat_t s_rate;
+
+  /**
+   * Descrambling support
+   */
+
+  struct th_descrambler_list s_descramblers;
+  int s_scrambled;
+  int s_scrambled_seen;
+  int s_caid;
+
+  /**
+   * PCR drift compensation. This should really be per-packet.
+   */
+  int64_t  s_pcr_drift;
+
+  /**
+   * List of all components.
+   */
+  struct th_stream_queue s_components;
+
+
+  /**
+   * Delivery pad, this is were we finally deliver all streaming output
+   */
+  streaming_pad_t s_streaming_pad;
+
+
+  loglimiter_t s_loglimit_tei;
+
+
+  int64_t s_current_pts;
+
+} service_t;
+
+
+
+
+
+void service_init(void);
+
+unsigned int service_compute_weight(struct service_list *head);
+
+int service_start(service_t *t, unsigned int weight, int force_start);
+
+service_t *service_create(const char *identifier, int type,
+                                int source_type);
+
+void service_unref(service_t *t);
+
+void service_ref(service_t *t);
+
+service_t *service_find_by_identifier(const char *identifier);
+
+void service_map_channel(service_t *t, struct channel *ch, int save);
+
+service_t *service_find(struct channel *ch, unsigned int weight,
+                       const char *loginfo, int *errorp,
+                       service_t *skip);
+
+th_stream_t *service_stream_find(service_t *t, int pid);
+
+th_stream_t *service_stream_create(service_t *t, int pid,
+                                    streaming_component_type_t type);
+
+void service_set_priority(service_t *t, int prio);
+
+void service_settings_write(service_t *t);
+
+const char *service_servicetype_txt(service_t *t);
+
+int service_is_tv(service_t *t);
+
+void service_destroy(service_t *t);
+
+void service_remove_subscriber(service_t *t, struct th_subscription *s,
+                              int reason);
+
+void service_set_streaming_status_flags(service_t *t, int flag);
+
+struct streaming_start;
+struct streaming_start *service_build_stream_start(service_t *t);
+
+void service_set_enable(service_t *t, int enabled);
+
+void service_restart(service_t *t, int had_components);
+
+void service_stream_destroy(service_t *t, th_stream_t *st);
+
+void service_request_save(service_t *t, int restart);
+
+void service_source_info_free(source_info_t *si);
+
+void service_source_info_copy(source_info_t *dst, const source_info_t *src);
+
+void service_make_nicename(service_t *t);
+
+const char *service_nicename(service_t *t);
+
+const char *service_component_nicename(th_stream_t *st);
+
+const char *service_tss2text(int flags);
+
+static inline int service_tss_is_error(int flags)
+{
+  return flags & TSS_ERRORS ? 1 : 0;
+}
+
+void service_refresh_channel(service_t *t);
+
+int tss2errcode(int tss);
+
+uint16_t service_get_encryption(service_t *t);
+
+int service_get_signal_status(service_t *t, signal_status_t *status);
+
+
+#endif // SERVICE_H__