1 /*
2  *  Tvheadend - TS file input system
3  *
4  *  Copyright (C) 2013 Adam Sutton
5  *
6  *  This program is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef __TVH_MPEGTS_H__
21 #define __TVH_MPEGTS_H__
22 
23 #ifndef __TVH_INPUT_H__
24 #error "Use header file input.h not input/mpegts.h"
25 #endif
26 
27 #include "atomic.h"
28 #include "input.h"
29 #include "service.h"
30 #include "mpegts/dvb.h"
31 #include "subscriptions.h"
32 
33 #define MPEGTS_ONID_NONE        0xFFFF
34 #define MPEGTS_TSID_NONE        0xFFFF
35 #define MPEGTS_FULLMUX_PID      0x2000
36 #define MPEGTS_TABLES_PID       0x2001
37 #define MPEGTS_PID_NONE         0xFFFF
38 
39 /* Types */
40 typedef struct mpegts_apid          mpegts_apid_t;
41 typedef struct mpegts_apids         mpegts_apids_t;
42 typedef struct mpegts_table         mpegts_table_t;
43 typedef struct mpegts_network       mpegts_network_t;
44 typedef struct mpegts_mux           mpegts_mux_t;
45 typedef struct mpegts_service       mpegts_service_t;
46 typedef struct mpegts_mux_instance  mpegts_mux_instance_t;
47 typedef struct mpegts_mux_sub       mpegts_mux_sub_t;
48 typedef struct mpegts_input         mpegts_input_t;
49 typedef struct mpegts_table_feed    mpegts_table_feed_t;
50 typedef struct mpegts_network_link  mpegts_network_link_t;
51 typedef struct mpegts_packet        mpegts_packet_t;
52 typedef struct mpegts_pcr           mpegts_pcr_t;
53 typedef struct mpegts_buffer        mpegts_buffer_t;
54 
55 /* Lists */
56 typedef LIST_HEAD (,mpegts_network)             mpegts_network_list_t;
57 typedef LIST_HEAD (,mpegts_input)               mpegts_input_list_t;
58 typedef TAILQ_HEAD(mpegts_mux_queue,mpegts_mux) mpegts_mux_queue_t;
59 typedef LIST_HEAD (,mpegts_mux)                 mpegts_mux_list_t;
60 typedef LIST_HEAD (,mpegts_network_link)        mpegts_network_link_list_t;
61 typedef TAILQ_HEAD(mpegts_table_feed_queue, mpegts_table_feed)
62   mpegts_table_feed_queue_t;
63 
64 /* Classes */
65 extern const idclass_t mpegts_network_class;
66 extern const idclass_t mpegts_mux_class;
67 extern const idclass_t mpegts_mux_instance_class;
68 extern const idclass_t mpegts_service_class;
69 extern const idclass_t mpegts_service_raw_class;
70 extern const idclass_t mpegts_input_class;
71 
72 /* **************************************************************************
73  * Setup / Tear down
74  * *************************************************************************/
75 
76 void mpegts_init ( int linuxdvb_mask, int nosatip, str_list_t *satip_client,
77                    str_list_t *tsfiles, int tstuners );
78 void mpegts_done ( void );
79 
80 /* **************************************************************************
81  * PIDs
82  * *************************************************************************/
83 
84 struct mpegts_apid {
85   uint16_t pid;
86   uint16_t weight;
87 };
88 
89 struct mpegts_apids {
90   mpegts_apid_t *pids;
91   int alloc;
92   int count;
93   int all;
94   int sorted;
95 };
96 
97 int mpegts_pid_init ( mpegts_apids_t *pids );
98 void mpegts_pid_done ( mpegts_apids_t *pids );
99 mpegts_apids_t *mpegts_pid_alloc ( void );
100 void mpegts_pid_destroy ( mpegts_apids_t **pids );
101 void mpegts_pid_reset ( mpegts_apids_t *pids );
102 int mpegts_pid_add ( mpegts_apids_t *pids, uint16_t pid, uint16_t weight );
103 int mpegts_pid_add_group ( mpegts_apids_t *pids, mpegts_apids_t *vals );
104 int mpegts_pid_del ( mpegts_apids_t *pids, uint16_t pid, uint16_t weight );
105 int mpegts_pid_del_group ( mpegts_apids_t *pids, mpegts_apids_t *vals );
106 int mpegts_pid_find_windex ( mpegts_apids_t *pids, uint16_t pid, uint16_t weight );
107 int mpegts_pid_find_rindex ( mpegts_apids_t *pids, uint16_t pid );
mpegts_pid_wexists(mpegts_apids_t * pids,uint16_t pid,uint16_t weight)108 static inline int mpegts_pid_wexists ( mpegts_apids_t *pids, uint16_t pid, uint16_t weight )
109   { return pids && (pids->all || mpegts_pid_find_windex(pids, pid, weight) >= 0); }
mpegts_pid_rexists(mpegts_apids_t * pids,uint16_t pid)110 static inline int mpegts_pid_rexists ( mpegts_apids_t *pids, uint16_t pid )
111   { return pids && (pids->all || mpegts_pid_find_rindex(pids, pid) >= 0); }
112 int mpegts_pid_copy ( mpegts_apids_t *dst, mpegts_apids_t *src );
113 int mpegts_pid_compare ( mpegts_apids_t *dst, mpegts_apids_t *src,
114                          mpegts_apids_t *add, mpegts_apids_t *del );
115 int mpegts_pid_weighted( mpegts_apids_t *dst, mpegts_apids_t *src, int limit );
116 int mpegts_pid_dump ( mpegts_apids_t *pids, char *buf, int len, int wflag, int raw );
117 
118 /* **************************************************************************
119  * Data / SI processing
120  * *************************************************************************/
121 
122 struct mpegts_packet
123 {
124   TAILQ_ENTRY(mpegts_packet)  mp_link;
125   size_t                      mp_len;
126   mpegts_mux_t               *mp_mux;
127   uint8_t                     mp_cc_restart;
128   uint8_t                     mp_data[0];
129 };
130 
131 struct mpegts_pcr {
132   int64_t  pcr_first;
133   int64_t  pcr_last;
134   uint16_t pcr_pid;
135 };
136 
137 #define MPEGTS_DATA_CC_RESTART		(1<<0)
138 #define MPEGTS_DATA_REMOVE_SCRAMBLED	(1<<1)
139 
140 typedef int (*mpegts_table_callback_t)
141   ( mpegts_table_t*, const uint8_t *buf, int len, int tableid );
142 
143 struct mpegts_table_mux_cb
144 {
145   int tag;
146   int (*cb) ( mpegts_table_t*, mpegts_mux_t *mm, uint16_t nbid,
147               const uint8_t dtag, const uint8_t *dptr, int dlen );
148 };
149 
150 typedef struct mpegts_pid_sub
151 {
152   RB_ENTRY(mpegts_pid_sub) mps_link;
153   LIST_ENTRY(mpegts_pid_sub) mps_raw_link;
154   LIST_ENTRY(mpegts_pid_sub) mps_svcraw_link;
155 #define MPS_NONE    0x00
156 #define MPS_ALL     0x01
157 #define MPS_RAW     0x02
158 #define MPS_STREAM  0x04
159 #define MPS_SERVICE 0x08
160 #define MPS_TABLE   0x10
161 #define MPS_FTABLE  0x20
162 #define MPS_TABLES  0x40
163   int   mps_type;
164 #define MPS_WEIGHT_PAT     1000
165 #define MPS_WEIGHT_CAT      999
166 #define MPS_WEIGHT_SDT      999
167 #define MPS_WEIGHT_NIT      999
168 #define MPS_WEIGHT_BAT      999
169 #define MPS_WEIGHT_VCT      999
170 #define MPS_WEIGHT_EIT      999
171 #define MPS_WEIGHT_ETT      999
172 #define MPS_WEIGHT_MGT      999
173 #define MPS_WEIGHT_PMT      998
174 #define MPS_WEIGHT_PCR      997
175 #define MPS_WEIGHT_CA       996
176 #define MPS_WEIGHT_VIDEO    900
177 #define MPS_WEIGHT_AUDIO    800
178 #define MPS_WEIGHT_SUBTITLE 700
179 #define MPS_WEIGHT_ESOTHER  500
180 #define MPS_WEIGHT_RAW      400
181 #define MPS_WEIGHT_NIT2     300
182 #define MPS_WEIGHT_SDT2     300
183 #define MPS_WEIGHT_TDT      101
184 #define MPS_WEIGHT_STT      101
185 #define MPS_WEIGHT_PMT_SCAN 100
186   int   mps_weight;
187   void *mps_owner;
188 } mpegts_pid_sub_t;
189 
190 typedef struct mpegts_pid
191 {
192   int                      mp_pid;
193   int                      mp_type; // mask for all subscribers
194   int8_t                   mp_cc;
195   RB_HEAD(,mpegts_pid_sub) mp_subs; // subscribers to pid
196   LIST_HEAD(,mpegts_pid_sub) mp_raw_subs;
197   LIST_HEAD(,mpegts_pid_sub) mp_svc_subs;
198   RB_ENTRY(mpegts_pid)     mp_link;
199 } mpegts_pid_t;
200 
201 struct mpegts_table
202 {
203   mpegts_psi_table_t;
204 
205   /**
206    * Flags, must never be changed after creation.
207    * We inspect it without holding global_lock
208    */
209   int mt_flags;
210 
211 #define MT_CRC        0x0001
212 #define MT_FULL       0x0002
213 #define MT_QUICKREQ   0x0004
214 #define MT_FASTSWITCH 0x0008
215 #define MT_ONESHOT    0x0010
216 #define MT_RECORD     0x0020
217 #define MT_SKIPSUBS   0x0040
218 #define MT_SCANSUBS   0x0080
219 #define MT_FAST       0x0100
220 #define MT_SLOW       0x0200
221 #define MT_DEFER      0x0400
222 
223   /**
224    * PID subscription weight
225    */
226   int mt_weight;
227 
228   /**
229    * Cycle queue
230    * Tables that did not get a fd or filter in hardware will end up here
231    * waiting for any other table to be received so it can reuse that fd.
232    * Only linked if fd == -1
233    */
234   TAILQ_ENTRY(mpegts_table) mt_pending_link;
235 
236   /**
237    * File descriptor for filter
238    */
239 
240   TAILQ_ENTRY(mpegts_table) mt_defer_link;
241   mpegts_mux_t *mt_mux;
242 
243   void *mt_bat;
244   mpegts_table_callback_t mt_callback;
245 
246   uint8_t mt_subscribed;
247   uint8_t mt_defer_cmd;
248 
249 #define MT_DEFER_OPEN_PID  1
250 #define MT_DEFER_CLOSE_PID 2
251 
252   int mt_working;
253 
254   int mt_count;
255 
256   int mt_id;
257 
258   int mt_destroyed; // Refcounting
259   int mt_arefcount;
260 
261   struct mpegts_table_mux_cb *mt_mux_cb;
262 
263   mpegts_service_t *mt_service;
264 
265   void (*mt_destroy) (mpegts_table_t *mt); // Allow customisable destroy hook
266                                            // useful for dynamic allocation of
267                                            // the opaque field
268 };
269 
270 /**
271  * When in raw mode we need to enqueue raw TS packet
272  * to a different thread because we need to hold
273  * global_lock when doing delivery of the tables
274  */
275 
276 struct mpegts_table_feed {
277   TAILQ_ENTRY(mpegts_table_feed) mtf_link;
278   int mtf_len;
279   mpegts_mux_t *mtf_mux;
280   uint8_t mtf_tsb[0];
281 };
282 
283 /* **************************************************************************
284  * Logical network
285  * *************************************************************************/
286 
287 typedef enum {
288   MN_DISCOVERY_DISABLE = 0,
289   MN_DISCOVERY_NEW     = 1,
290   MN_DISCOVERY_CHANGE  = 2
291 } mpegts_discovery_t;
292 
293 /* Network/Input linkage */
294 struct mpegts_network_link
295 {
296   int                             mnl_mark;
297   mpegts_input_t                  *mnl_input;
298   mpegts_network_t                *mnl_network;
299   LIST_ENTRY(mpegts_network_link) mnl_mn_link;
300   LIST_ENTRY(mpegts_network_link) mnl_mi_link;
301 };
302 
303 /* Network */
304 struct mpegts_network
305 {
306   idnode_t                   mn_id;
307   LIST_ENTRY(mpegts_network) mn_global_link;
308 
309   /*
310    * Identification
311    */
312   char                    *mn_network_name;
313   char                    *mn_provider_network_name;
314   int                      mn_wizard;
315   uint8_t                  mn_wizard_free;
316 
317   /*
318    * Inputs
319    */
320   mpegts_network_link_list_t   mn_inputs;
321 
322   /*
323    * Multiplexes
324    */
325   mpegts_mux_list_t       mn_muxes;
326 
327   /*
328    * Scanning
329    */
330   mpegts_mux_queue_t mn_scan_pend;    // Pending muxes
331   mpegts_mux_queue_t mn_scan_active;  // Active muxes
332   mtimer_t           mn_scan_timer;   // Timer for activity
333 
334   /*
335    * Functions
336    */
337   void              (*mn_delete)       (mpegts_network_t*, int delconf);
338   void              (*mn_display_name) (mpegts_network_t*, char *buf, size_t len);
339   htsmsg_t *        (*mn_config_save)  (mpegts_network_t*, char *filename, size_t fsize);
340   mpegts_mux_t*     (*mn_create_mux)
341     (mpegts_network_t*, void *origin, uint16_t onid, uint16_t tsid,
342      void *conf, int force);
343   mpegts_service_t* (*mn_create_service)
344     (mpegts_mux_t*, uint16_t sid, uint16_t pmt_pid);
345   const idclass_t*  (*mn_mux_class)   (mpegts_network_t*);
346   mpegts_mux_t *    (*mn_mux_create2) (mpegts_network_t *mn, htsmsg_t *conf);
347 
348   /*
349    * Configuration
350    */
351   uint16_t mn_nid;
352   uint16_t mn_satip_source;
353   int      mn_autodiscovery;
354   int      mn_skipinitscan;
355   char    *mn_charset;
356   int      mn_idlescan;
357   int      mn_ignore_chnum;
358   int      mn_sid_chnum;
359   int      mn_localtime;
360   int      mn_satpos;
361 };
362 
363 typedef enum mpegts_mux_scan_state
364 {
365   MM_SCAN_STATE_IDLE,     // Nothing
366   MM_SCAN_STATE_PEND,     // Queue'd pending scan
367   MM_SCAN_STATE_ACTIVE,   // Scan is active
368 } mpegts_mux_scan_state_t;
369 
370 typedef enum mpegts_mux_scan_result
371 {
372   MM_SCAN_NONE,
373   MM_SCAN_OK,
374   MM_SCAN_FAIL,
375   MM_SCAN_PARTIAL,
376   MM_SCAN_IGNORE,
377 } mpegts_mux_scan_result_t;
378 
379 #define MM_SCAN_CHECK_OK(mm) \
380   ((mm)->mm_scan_result == MM_SCAN_OK || (mm)->mm_scan_result == MM_SCAN_PARTIAL)
381 
382 enum mpegts_mux_enable
383 {
384   MM_IGNORE  = -1,
385   MM_DISABLE =  0,
386   MM_ENABLE  =  1,
387 };
388 
389 enum mpegts_mux_epg_flag
390 {
391   MM_EPG_DISABLE,
392   MM_EPG_ENABLE,
393   MM_EPG_FORCE,
394   MM_EPG_ONLY_EIT,
395   MM_EPG_ONLY_UK_FREESAT,
396   MM_EPG_ONLY_UK_FREEVIEW,
397   MM_EPG_ONLY_VIASAT_BALTIC,
398   MM_EPG_ONLY_OPENTV_SKY_UK,
399   MM_EPG_ONLY_OPENTV_SKY_ITALIA,
400   MM_EPG_ONLY_OPENTV_SKY_AUSAT,
401   MM_EPG_ONLY_BULSATCOM_39E,
402   MM_EPG_ONLY_PSIP,
403 };
404 #define MM_EPG_LAST MM_EPG_ONLY_PSIP
405 
406 enum mpegts_mux_ac3_flag
407 {
408   MM_AC3_STANDARD,
409   MM_AC3_PMT_06,
410   MM_AC3_PMT_N05,
411 };
412 
413 typedef struct tsdebug_packet {
414   TAILQ_ENTRY(tsdebug_packet) link;
415   uint8_t pkt[188];
416   off_t pos;
417 } tsdebug_packet_t;
418 
419 /* Multiplex */
420 struct mpegts_mux
421 {
422   idnode_t mm_id;
423   int      mm_refcount;
424 
425   /*
426    * Identification
427    */
428 
429   LIST_ENTRY(mpegts_mux)  mm_network_link;
430   mpegts_network_t       *mm_network;
431   char                   *mm_provider_network_name;
432   uint16_t                mm_onid;
433   uint16_t                mm_tsid;
434   int                     mm_tsid_checks;
435   int                     mm_tsid_accept_zero_value;
436   tvhlog_limit_t          mm_tsid_loglimit;
437   int64_t                 mm_start_monoclock;
438 
439   int                     mm_update_pids_flag;
440   mtimer_t                mm_update_pids_timer;
441 
442   /*
443    * Services
444    */
445 
446   LIST_HEAD(,mpegts_service) mm_services;
447 
448   /*
449    * Scanning
450    */
451 
452   mpegts_mux_scan_result_t mm_scan_result;  ///< Result of last scan
453   int                      mm_scan_weight;  ///< Scan priority
454   int                      mm_scan_flags;   ///< Subscription flags
455   int                      mm_scan_init;    ///< Flag to timeout handler
456   mtimer_t                 mm_scan_timeout; ///< Timer to handle timeout
457   TAILQ_ENTRY(mpegts_mux)  mm_scan_link;    ///< Link to Queue
458   mpegts_mux_scan_state_t  mm_scan_state;   ///< Scanning state
459 
460 #if 0
461   enum {
462     MM_ORIG_USER, ///< Manually added
463     MM_ORIG_FILE, ///< Added from scan file
464     MM_ORIG_AUTO  ///< From NIT
465   }                        mm_dmc_origin2;
466 #endif
467   void                    *mm_dmc_origin;
468   int64_t                  mm_dmc_origin_expire;
469 
470   char                    *mm_fastscan_muxes;
471 
472   /*
473    * Physical instances
474    */
475 
476   LIST_HEAD(, mpegts_mux_instance) mm_instances;
477   mpegts_mux_instance_t      *mm_active;
478   LIST_HEAD(,service)         mm_transports;
479 
480   /*
481    * Raw subscriptions
482    */
483 
484   LIST_HEAD(, th_subscription) mm_raw_subs;
485 
486   /*
487    * Data processing
488    */
489 
490   RB_HEAD(, mpegts_pid)       mm_pids;
491   LIST_HEAD(, mpegts_pid_sub) mm_all_subs;
492   int                         mm_last_pid;
493   mpegts_pid_t               *mm_last_mp;
494 
495   int                         mm_num_tables;
496   LIST_HEAD(, mpegts_table)   mm_tables;
497   TAILQ_HEAD(, mpegts_table)  mm_defer_tables;
498   pthread_mutex_t             mm_tables_lock;
499   TAILQ_HEAD(, mpegts_table)  mm_table_queue;
500 
501   LIST_HEAD(, caid)           mm_descrambler_caids;
502   TAILQ_HEAD(, descrambler_table) mm_descrambler_tables;
503   TAILQ_HEAD(, descrambler_emm) mm_descrambler_emms;
504   pthread_mutex_t             mm_descrambler_lock;
505   int                         mm_descrambler_flush;
506 
507   /*
508    * Functions
509    */
510 
511   void (*mm_delete)           (mpegts_mux_t *mm, int delconf);
512   void (*mm_free)             (mpegts_mux_t *mm);
513   htsmsg_t *(*mm_config_save) (mpegts_mux_t *mm, char *filename, size_t fsize);
514   void (*mm_display_name)     (mpegts_mux_t*, char *buf, size_t len);
515   int  (*mm_is_enabled)       (mpegts_mux_t *mm);
516   void (*mm_stop)             (mpegts_mux_t *mm, int force, int reason);
517   void (*mm_open_table)       (mpegts_mux_t*,mpegts_table_t*,int subscribe);
518   void (*mm_unsubscribe_table)(mpegts_mux_t*,mpegts_table_t*);
519   void (*mm_close_table)      (mpegts_mux_t*,mpegts_table_t*);
520   void (*mm_create_instances) (mpegts_mux_t*);
521   int  (*mm_is_epg)           (mpegts_mux_t*);
522 
523   /*
524    * Configuration
525    */
526   char *mm_crid_authority;
527   int   mm_enabled;
528   int   mm_epg;
529   char *mm_charset;
530   int   mm_pmt_ac3;
531   int   mm_eit_tsid_nocheck;
532   uint16_t mm_sid_filter;
533 
534   /*
535    * TSDEBUG
536    */
537 #if ENABLE_TSDEBUG
538   int   mm_tsdebug_fd;
539   int   mm_tsdebug_fd2;
540   off_t mm_tsdebug_pos;
541   TAILQ_HEAD(, tsdebug_packet) mm_tsdebug_packets;
542 #endif
543 };
544 
545 #define PREFCAPID_OFF      0
546 #define PREFCAPID_ON       1
547 #define PREFCAPID_FORCE    2
548 
549 /* Service */
550 struct mpegts_service
551 {
552   service_t; // Parent
553 
554   int (*s_update_pids)(mpegts_service_t *t, struct mpegts_apids *pids);
555   int (*s_link)(mpegts_service_t *master, mpegts_service_t *slave);
556   int (*s_unlink)(mpegts_service_t *master, mpegts_service_t *slave);
557 
558   int      s_dvb_subscription_flags;
559   int      s_dvb_subscription_weight;
560 
561   mpegts_apids_t             *s_pids;
562   idnode_set_t                s_masters;
563   LIST_HEAD(, mpegts_service) s_slaves;
564   LIST_ENTRY(mpegts_service)  s_slaves_link;
565   mpegts_apids_t             *s_slaves_pids;
566 
567   /*
568    * Fields defined by DVB standard EN 300 468
569    */
570 
571   uint32_t s_dvb_channel_num;
572   uint16_t s_dvb_channel_minor;
573   uint8_t  s_dvb_channel_dtag;
574   uint16_t s_dvb_service_id;
575   char    *s_dvb_svcname;
576   char    *s_dvb_provider;
577   char    *s_dvb_cridauth;
578   uint16_t s_dvb_servicetype;
579   int      s_dvb_ignore_eit;
580   char    *s_dvb_charset;
581   uint16_t s_dvb_prefcapid;
582   int      s_dvb_prefcapid_lock;
583   time_t   s_dvb_created;
584   time_t   s_dvb_last_seen;
585   time_t   s_dvb_check_seen;
586 
587   /*
588    * EIT/EPG control
589    */
590 
591   int      s_dvb_eit_enable;
592   uint64_t s_dvb_opentv_chnum;
593   uint16_t s_dvb_opentv_id;
594   uint16_t s_atsc_source_id;
595 
596   /*
597    * Link to carrying multiplex and active adapter
598    */
599 
600   LIST_ENTRY(mpegts_service) s_dvb_mux_link;
601   mpegts_mux_t               *s_dvb_mux;
602   mpegts_input_t             *s_dvb_active_input;
603 
604   /*
605    * Streaming elements
606    *
607    * see service.h for locking rules
608    */
609 
610   /**
611    * When a subscription request SMT_MPEGTS, chunk them togeather
612    * in order to recude load.
613    */
614   sbuf_t s_tsbuf;
615   int64_t s_tsbuf_last;
616 
617   /**
618    * PCR drift compensation. This should really be per-packet.
619    */
620   int64_t  s_pcr_drift;
621 
622   /**
623    * PMT/CAT monitoring
624    */
625 
626   mpegts_table_t *s_pmt_mon; ///< Table entry for monitoring PMT
627   mpegts_table_t *s_cat_mon; ///< Table entry for monitoring CAT
628 
629 };
630 
631 /* **************************************************************************
632  * Physical Network
633  * *************************************************************************/
634 
635 /* Physical mux instance */
636 struct mpegts_mux_instance
637 {
638   tvh_input_instance_t;
639 
640   LIST_ENTRY(mpegts_mux_instance) mmi_mux_link;
641   LIST_ENTRY(mpegts_mux_instance) mmi_active_link;
642 
643   streaming_pad_t mmi_streaming_pad;
644 
645   mpegts_mux_t   *mmi_mux;
646   mpegts_input_t *mmi_input;
647 
648   int             mmi_start_weight;
649   int             mmi_tune_failed;
650 };
651 
652 struct mpegts_mux_sub
653 {
654   RB_ENTRY(mpegts_mux_sub)  mms_link;
655   void                     *mms_src;
656   int                       mms_weight;
657 };
658 
659 enum mpegts_input_is_enabled {
660   MI_IS_ENABLED_RETRY = -1,
661   MI_IS_ENABLED_NEVER = 0,
662   MI_IS_ENABLED_OK = 1,
663 };
664 
665 /* Input source */
666 struct mpegts_input
667 {
668   tvh_input_t;
669 
670   int mi_enabled;
671 
672   int mi_instance;
673 
674   char *mi_name;
675 
676   int mi_priority;
677   int mi_streaming_priority;
678 
679   int mi_ota_epg;
680 
681   int mi_initscan;
682   int mi_idlescan;
683   uint32_t mi_free_weight;
684 
685   char *mi_linked;
686 
687   LIST_ENTRY(mpegts_input) mi_global_link;
688 
689   mpegts_network_link_list_t mi_networks;
690 
691   LIST_HEAD(,tvh_input_instance) mi_mux_instances;
692 
693 
694   /*
695    * Status
696    */
697   mtimer_t mi_status_timer;
698 
699   /*
700    * Input processing
701    */
702 
703   int mi_running;            /* threads running */
704   int64_t mi_last_dispatch;
705 
706   /* Data input */
707   // Note: this section is protected by mi_input_lock
708   pthread_t                       mi_input_tid;
709   mtimer_t                        mi_input_thread_start;
710   pthread_mutex_t                 mi_input_lock;
711   tvh_cond_t                      mi_input_cond;
712   TAILQ_HEAD(,mpegts_packet)      mi_input_queue;
713   uint64_t                        mi_input_queue_size;
714   tvhlog_limit_t                  mi_input_queue_loglimit;
715   int                             mi_remove_scrambled_bits;
716 
717   /* Data processing/output */
718   // Note: this lock (mi_output_lock) protects all the remaining
719   //       data fields (excluding the callback functions)
720   pthread_mutex_t                 mi_output_lock;
721 
722   /* Active sources */
723   LIST_HEAD(,mpegts_mux_instance) mi_mux_active;
724 
725   /* Table processing */
726   pthread_t                       mi_table_tid;
727   tvh_cond_t                      mi_table_cond;
728   mpegts_table_feed_queue_t       mi_table_queue;
729   uint64_t                        mi_table_queue_size;
730   tvhlog_limit_t                  mi_table_queue_loglimit;
731 
732   /* DBus */
733 #if ENABLE_DBUS_1
734   int64_t                         mi_dbus_subs;
735 #endif
736 
737   /*
738    * Functions
739    */
740   int  (*mi_is_enabled)     (mpegts_input_t*, mpegts_mux_t *mm, int flags, int weight);
741   void (*mi_enabled_updated)(mpegts_input_t*);
742   void (*mi_display_name)   (mpegts_input_t*, char *buf, size_t len);
743   int  (*mi_get_weight)     (mpegts_input_t*, mpegts_mux_t *mm, int flags, int weight);
744   int  (*mi_get_priority)   (mpegts_input_t*, mpegts_mux_t *mm, int flags);
745   int  (*mi_get_grace)      (mpegts_input_t*, mpegts_mux_t *mm);
746   int  (*mi_warm_mux)       (mpegts_input_t*,mpegts_mux_instance_t*);
747   int  (*mi_start_mux)      (mpegts_input_t*,mpegts_mux_instance_t*, int weight);
748   void (*mi_stop_mux)       (mpegts_input_t*,mpegts_mux_instance_t*);
749   void (*mi_open_service)   (mpegts_input_t*,mpegts_service_t*, int flags, int first, int weight);
750   void (*mi_close_service)  (mpegts_input_t*,mpegts_service_t*);
751   void (*mi_update_pids)    (mpegts_input_t*,mpegts_mux_t*);
752   void (*mi_create_mux_instance) (mpegts_input_t*,mpegts_mux_t*);
753   void (*mi_started_mux)    (mpegts_input_t*,mpegts_mux_instance_t*);
754   void (*mi_stopping_mux)   (mpegts_input_t*,mpegts_mux_instance_t*);
755   void (*mi_stopped_mux)    (mpegts_input_t*,mpegts_mux_instance_t*);
756   int  (*mi_has_subscription) (mpegts_input_t*, mpegts_mux_t *mm);
757   void (*mi_tuning_error)   (mpegts_input_t*, mpegts_mux_t *);
758   void (*mi_empty_status)   (mpegts_input_t*, tvh_input_stream_t *);
759   idnode_set_t *(*mi_network_list) (mpegts_input_t*);
760 };
761 
762 /* ****************************************************************************
763  * Lists
764  * ***************************************************************************/
765 
766 extern mpegts_network_list_t mpegts_network_all;
767 
768 typedef struct mpegts_network_builder {
769   LIST_ENTRY(mpegts_network_builder) link;
770   const idclass_t     *idc;
771   mpegts_network_t * (*build) ( const idclass_t *idc, htsmsg_t *conf );
772 } mpegts_network_builder_t;
773 
774 
775 typedef LIST_HEAD(,mpegts_network_builder) mpegts_network_builder_list_t;
776 
777 extern mpegts_network_builder_list_t mpegts_network_builders;
778 
779 extern mpegts_input_list_t mpegts_input_all;
780 
781 /* ****************************************************************************
782  * Functions
783  * ***************************************************************************/
784 
785 mpegts_input_t *mpegts_input_create0
786   ( mpegts_input_t *mi, const idclass_t *idc, const char *uuid, htsmsg_t *c );
787 
788 #define mpegts_input_create(t, u, c)\
789   (struct t*)mpegts_input_create0(calloc(1, sizeof(struct t)), &t##_class, u, c)
790 
791 #define mpegts_input_create1(u, c)\
792   mpegts_input_create0(calloc(1, sizeof(mpegts_input_t)),\
793                        &mpegts_input_class, u, c)
794 
795 void mpegts_input_stop_all ( mpegts_input_t *mi );
796 
797 void mpegts_input_delete ( mpegts_input_t *mi, int delconf );
798 
mpegts_input_find(const char * uuid)799 static inline mpegts_input_t *mpegts_input_find(const char *uuid)
800   { return idnode_find(uuid, &mpegts_input_class, NULL); }
801 
802 int mpegts_input_set_networks ( mpegts_input_t *mi, htsmsg_t *msg );
803 
804 int mpegts_input_add_network  ( mpegts_input_t *mi, mpegts_network_t *mn );
805 
806 void mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int flags, int init, int weight );
807 void mpegts_input_close_service ( mpegts_input_t *mi, mpegts_service_t *s );
808 
809 void mpegts_input_status_timer ( void *p );
810 
811 int mpegts_input_grace ( mpegts_input_t * mi, mpegts_mux_t * mm );
812 
813 int mpegts_input_is_enabled ( mpegts_input_t * mi, mpegts_mux_t *mm, int flags, int weight );
814 
815 void mpegts_input_set_enabled ( mpegts_input_t *mi, int enabled );
816 
817 void mpegts_input_empty_status ( mpegts_input_t *mi, tvh_input_stream_t *st );
818 
819 
820 /* TODO: exposing these class methods here is a bit of a hack */
821 const void *mpegts_input_class_network_get  ( void *o );
822 int         mpegts_input_class_network_set  ( void *o, const void *p );
823 htsmsg_t   *mpegts_input_class_network_enum ( void *o, const char *lang );
824 char       *mpegts_input_class_network_rend ( void *o, const char *lang );
825 const void *mpegts_input_class_active_get   ( void *o );
826 
827 int mpegts_mps_weight(elementary_stream_t *st);
828 
829 int mpegts_mps_cmp( mpegts_pid_sub_t *a, mpegts_pid_sub_t *b );
830 
831 void mpegts_network_register_builder
832   ( const idclass_t *idc,
833     mpegts_network_t *(*build)(const idclass_t *idc, htsmsg_t *conf) );
834 
835 void mpegts_network_unregister_builder
836   ( const idclass_t *idc );
837 
838 mpegts_network_builder_t *mpegts_network_builder_find ( const char *clazz );
839 
840 mpegts_network_t *mpegts_network_build
841   ( const char *clazz, htsmsg_t *conf );
842 
843 mpegts_network_t *mpegts_network_create0
844   ( mpegts_network_t *mn, const idclass_t *idc, const char *uuid,
845     const char *name, htsmsg_t *conf );
846 
847 #define mpegts_network_create(t, u, n, c)\
848   (struct t*)mpegts_network_create0(calloc(1, sizeof(struct t)), &t##_class, u, n, c)
849 
850 extern const idclass_t mpegts_network_class;
851 
mpegts_network_find(const char * uuid)852 static inline mpegts_network_t *mpegts_network_find(const char *uuid)
853   { return idnode_find(uuid, &mpegts_network_class, NULL); }
854 
855 mpegts_mux_t *mpegts_network_find_mux
856   (mpegts_network_t *mn, uint16_t onid, uint16_t tsid, int check);
857 
858 mpegts_service_t *mpegts_network_find_active_service
859   (mpegts_network_t *mn, uint16_t sid, mpegts_mux_t **rmm);
860 
861 void mpegts_network_class_delete ( const idclass_t *idc, int delconf );
862 
863 void mpegts_network_delete ( mpegts_network_t *mn, int delconf );
864 
865 int mpegts_network_set_nid          ( mpegts_network_t *mn, uint16_t nid );
866 int mpegts_network_set_network_name ( mpegts_network_t *mn, const char *name );
867 void mpegts_network_scan ( mpegts_network_t *mn );
868 void mpegts_network_get_type_str( mpegts_network_t *mn, char *buf, size_t buflen );
869 
870 htsmsg_t * mpegts_network_wizard_get ( mpegts_input_t *mi, const idclass_t *idc,
871                                        mpegts_network_t *mn, const char *lang );
872 void mpegts_network_wizard_create ( const char *clazz, htsmsg_t **nlist, const char *lang );
873 
874 mpegts_mux_t *mpegts_mux_create0
875   ( mpegts_mux_t *mm, const idclass_t *class, const char *uuid,
876     mpegts_network_t *mn, uint16_t onid, uint16_t tsid,
877     htsmsg_t *conf );
878 
879 #define mpegts_mux_create(type, uuid, mn, onid, tsid, conf)\
880   (struct type*)mpegts_mux_create0(calloc(1, sizeof(struct type)),\
881                                    &type##_class, uuid,\
882                                    mn, onid, tsid, conf)
883 #define mpegts_mux_create1(uuid, mn, onid, tsid, conf)\
884   mpegts_mux_create0(calloc(1, sizeof(mpegts_mux_t)), &mpegts_mux_class, uuid,\
885                      mn, onid, tsid, conf)
886 
mpegts_mux_find(const char * uuid)887 static inline mpegts_mux_t *mpegts_mux_find(const char *uuid)
888   { return idnode_find(uuid, &mpegts_mux_class, NULL); }
889 
890 #define mpegts_mux_delete_by_uuid(u, delconf)\
891   { mpegts_mux_t *mm = mpegts_mux_find(u); if (mm) mm->mm_delete(mm, delconf); }
892 
893 void mpegts_mux_delete ( mpegts_mux_t *mm, int delconf );
894 
895 void mpegts_mux_free ( mpegts_mux_t *mm );
896 
mpegts_mux_grab(mpegts_mux_t * mm)897 static inline void mpegts_mux_grab ( mpegts_mux_t *mm )
898 {
899   int v = atomic_add(&mm->mm_refcount, 1);
900   assert(v > 0);
901 }
902 
mpegts_mux_release(mpegts_mux_t * mm)903 static inline int mpegts_mux_release ( mpegts_mux_t *mm )
904 {
905   int v = atomic_dec(&mm->mm_refcount, 1);
906   assert(v > 0);
907   if (v == 1) {
908     mm->mm_free(mm);
909     return 1;
910   }
911   return 0;
912 }
913 
914 void mpegts_mux_save ( mpegts_mux_t *mm, htsmsg_t *c );
915 
916 void mpegts_mux_tuning_error( const char *mux_uuid, mpegts_mux_instance_t *mmi_match );
917 
918 mpegts_mux_instance_t *mpegts_mux_instance_create0
919   ( mpegts_mux_instance_t *mmi, const idclass_t *class, const char *uuid,
920     mpegts_input_t *mi, mpegts_mux_t *mm );
921 
922 mpegts_service_t *mpegts_mux_find_service(mpegts_mux_t *ms, uint16_t sid);
923 
924 #define mpegts_mux_instance_create(type, uuid, mi, mm)\
925   (struct type*)mpegts_mux_instance_create0(calloc(1, sizeof(struct type)),\
926                                             &type##_class, uuid,\
927                                             mi, mm);
928 
929 void mpegts_mux_instance_delete ( tvh_input_instance_t *tii );
930 
931 int mpegts_mux_instance_start
932   ( mpegts_mux_instance_t **mmiptr, service_t *t, int weight );
933 
934 int mpegts_mux_instance_weight ( mpegts_mux_instance_t *mmi );
935 
936 int mpegts_mux_set_network_name ( mpegts_mux_t *mm, const char *name );
937 int mpegts_mux_set_tsid ( mpegts_mux_t *mm, uint16_t tsid, int force );
938 int mpegts_mux_set_onid ( mpegts_mux_t *mm, uint16_t onid );
939 int mpegts_mux_set_crid_authority ( mpegts_mux_t *mm, const char *defauth );
940 
941 void mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe );
942 void mpegts_mux_unsubscribe_table ( mpegts_mux_t *mm, mpegts_table_t *mt );
943 void mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt );
944 
945 void mpegts_mux_remove_subscriber(mpegts_mux_t *mm, th_subscription_t *s, int reason);
946 int  mpegts_mux_subscribe(mpegts_mux_t *mm, mpegts_input_t *mi,
947                           const char *name, int weight, int flags);
948 void mpegts_mux_unsubscribe_by_name(mpegts_mux_t *mm, const char *name);
949 th_subscription_t *mpegts_mux_find_subscription_by_name(mpegts_mux_t *mm, const char *name);
950 
951 void mpegts_mux_unsubscribe_linked(mpegts_input_t *mi, service_t *t);
952 
953 void mpegts_mux_scan_done ( mpegts_mux_t *mm, const char *buf, int res );
954 
955 void mpegts_mux_bouquet_rescan ( const char *src, const char *extra );
956 
957 void mpegts_mux_nice_name( mpegts_mux_t *mm, char *buf, size_t len );
958 
959 int mpegts_mux_class_scan_state_set ( void *, const void * );
960 
mpegts_mux_scan_state_set(mpegts_mux_t * m,int state)961 static inline int mpegts_mux_scan_state_set ( mpegts_mux_t *m, int state )
962   { return mpegts_mux_class_scan_state_set ( m, &state ); }
963 
964 mpegts_pid_t *mpegts_mux_find_pid_(mpegts_mux_t *mm, int pid, int create);
965 
966 static inline mpegts_pid_t *
mpegts_mux_find_pid(mpegts_mux_t * mm,int pid,int create)967 mpegts_mux_find_pid(mpegts_mux_t *mm, int pid, int create)
968 {
969   if (mm->mm_last_pid != pid)
970     return mpegts_mux_find_pid_(mm, pid, create);
971   else
972     return mm->mm_last_mp;
973 }
974 
975 void mpegts_mux_update_pids ( mpegts_mux_t *mm );
976 
977 int mpegts_mux_compare ( mpegts_mux_t *a, mpegts_mux_t *b );
978 
979 void mpegts_input_recv_packets
980   (mpegts_input_t *mi, mpegts_mux_instance_t *mmi, sbuf_t *sb,
981    int flags, mpegts_pcr_t *pcr);
982 
983 int mpegts_input_get_weight ( mpegts_input_t *mi, mpegts_mux_t *mm, int flags, int weight );
984 int mpegts_input_get_priority ( mpegts_input_t *mi, mpegts_mux_t *mm, int flags );
985 int mpegts_input_get_grace ( mpegts_input_t *mi, mpegts_mux_t *mm );
986 int mpegts_input_warm_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi );
987 
988 void mpegts_input_save ( mpegts_input_t *mi, htsmsg_t *c );
989 
990 void mpegts_input_flush_mux ( mpegts_input_t *mi, mpegts_mux_t *mm );
991 
992 mpegts_pid_t * mpegts_input_open_pid
993   ( mpegts_input_t *mi, mpegts_mux_t *mm, int pid, int type, int weight, void *owner, int reopen );
994 
995 int mpegts_input_close_pid
996   ( mpegts_input_t *mi, mpegts_mux_t *mm, int pid, int type, int weight, void *owner );
997 
998 void mpegts_input_close_pids
999   ( mpegts_input_t *mi, mpegts_mux_t *mm, void *owner, int all );
1000 
1001 static inline void
tsdebug_write(mpegts_mux_t * mm,uint8_t * buf,size_t len)1002 tsdebug_write(mpegts_mux_t *mm, uint8_t *buf, size_t len)
1003 {
1004 #if ENABLE_TSDEBUG
1005   if (mm && mm->mm_tsdebug_fd2 >= 0)
1006     if (write(mm->mm_tsdebug_fd2, buf, len) != len)
1007       tvherror(LS_TSDEBUG, "unable to write input data (%i)", errno);
1008 #endif
1009 }
1010 
1011 static inline ssize_t
sbuf_tsdebug_read(mpegts_mux_t * mm,sbuf_t * sb,int fd)1012 sbuf_tsdebug_read(mpegts_mux_t *mm, sbuf_t *sb, int fd)
1013 {
1014 #if ENABLE_TSDEBUG
1015   ssize_t r = sbuf_read(sb, fd);
1016   tsdebug_write(mm, sb->sb_data + sb->sb_ptr - r, r);
1017   return r;
1018 #else
1019   return sbuf_read(sb, fd);
1020 #endif
1021 }
1022 
1023 void mpegts_table_dispatch
1024   (const uint8_t *sec, size_t r, void *mt);
mpegts_table_grab(mpegts_table_t * mt)1025 static inline void mpegts_table_grab
1026   (mpegts_table_t *mt)
1027 {
1028   int v = atomic_add(&mt->mt_arefcount, 1);
1029   assert(v > 0);
1030 }
1031 void mpegts_table_release_
1032   (mpegts_table_t *mt);
mpegts_table_release(mpegts_table_t * mt)1033 static inline int mpegts_table_release
1034   (mpegts_table_t *mt)
1035 {
1036   int v = atomic_dec(&mt->mt_arefcount, 1);
1037   assert(v > 0);
1038   if (v == 1) {
1039     assert(mt->mt_destroyed == 1);
1040     mpegts_table_release_(mt);
1041     return 1;
1042   }
1043   return 0;
1044 }
1045 int mpegts_table_type
1046   ( mpegts_table_t *mt );
1047 mpegts_table_t *mpegts_table_add
1048   (mpegts_mux_t *mm, int tableid, int mask,
1049    mpegts_table_callback_t callback, void *opaque,
1050    const char *name, int subsys, int flags, int pid, int weight);
1051 void mpegts_table_flush_all
1052   (mpegts_mux_t *mm);
1053 void mpegts_table_destroy ( mpegts_table_t *mt );
1054 
1055 void mpegts_table_consistency_check( mpegts_mux_t *mm );
1056 
1057 void dvb_bat_destroy
1058   (struct mpegts_table *mt);
1059 
1060 int dvb_pat_callback
1061   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1062 int dvb_cat_callback
1063   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1064 int dvb_pmt_callback
1065   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tabelid);
1066 int dvb_nit_callback
1067   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1068 int dvb_bat_callback
1069   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1070 int dvb_fs_sdt_callback
1071   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1072 int dvb_sdt_callback
1073   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1074 int dvb_tdt_callback
1075   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1076 int dvb_tot_callback
1077   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1078 int atsc_vct_callback
1079   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1080 int atsc_stt_callback
1081   (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid);
1082 
1083 void psi_tables_install
1084   (mpegts_input_t *mi, mpegts_mux_t *mm, dvb_fe_delivery_system_t delsys);
1085 
1086 mpegts_service_t *mpegts_service_create0
1087   ( mpegts_service_t *ms, const idclass_t *class, const char *uuid,
1088     mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, htsmsg_t *conf );
1089 
1090 #define mpegts_service_create(t, u, m, s, p, c)\
1091   (struct t*)mpegts_service_create0(calloc(1, sizeof(struct t)),\
1092                                     &t##_class, u, m, s, p, c)
1093 
1094 #define mpegts_service_create1(u, m, s, p, c)\
1095   mpegts_service_create0(calloc(1, sizeof(mpegts_service_t)),\
1096                          &mpegts_service_class, u, m, s, p, c)
1097 
1098 mpegts_service_t *mpegts_service_create_raw(mpegts_mux_t *mm);
1099 
1100 mpegts_service_t *mpegts_service_find
1101   ( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, int create, int *save );
1102 
1103 service_t *
1104 mpegts_service_find_e2
1105   ( uint32_t stype, uint32_t sid, uint32_t tsid, uint32_t onid, uint32_t hash);
1106 
1107 mpegts_service_t *
1108 mpegts_service_find_by_pid ( mpegts_mux_t *mm, int pid );
1109 
1110 void mpegts_service_update_slave_pids ( mpegts_service_t *t, int del );
1111 
mpegts_service_find_by_uuid(const char * uuid)1112 static inline mpegts_service_t *mpegts_service_find_by_uuid(const char *uuid)
1113   { return idnode_find(uuid, &mpegts_service_class, NULL); }
1114 
1115 void mpegts_service_unref ( service_t *s );
1116 
1117 void mpegts_service_delete ( service_t *s, int delconf );
1118 
1119 int64_t mpegts_service_channel_number ( service_t *s );
1120 
1121 /*
1122  * MPEG-TS event handler
1123  */
1124 
1125 typedef struct mpegts_listener
1126 {
1127   LIST_ENTRY(mpegts_listener) ml_link;
1128   void *ml_opaque;
1129   void (*ml_mux_start)  (mpegts_mux_t *mm, void *p);
1130   void (*ml_mux_stop)   (mpegts_mux_t *mm, void *p, int reason);
1131   void (*ml_mux_create) (mpegts_mux_t *mm, void *p);
1132   void (*ml_mux_delete) (mpegts_mux_t *mm, void *p);
1133 } mpegts_listener_t;
1134 
1135 extern LIST_HEAD(mpegts_listeners, mpegts_listener) mpegts_listeners;
1136 
1137 #define mpegts_add_listener(ml)\
1138   LIST_INSERT_HEAD(&mpegts_listeners, ml, ml_link)
1139 
1140 #define mpegts_rem_listener(ml)\
1141   LIST_REMOVE(ml, ml_link)
1142 
1143 #define mpegts_fire_event(t, op)\
1144 {\
1145   mpegts_listener_t *ml;\
1146   LIST_FOREACH(ml, &mpegts_listeners, ml_link)\
1147     if (ml->op) ml->op(t, ml->ml_opaque);\
1148 } (void)0
1149 
1150 #define mpegts_fire_event1(t, op, arg1)\
1151 {\
1152   mpegts_listener_t *ml;\
1153   LIST_FOREACH(ml, &mpegts_listeners, ml_link)\
1154     if (ml->op) ml->op(t, ml->ml_opaque, arg1);\
1155 } (void)0
1156 
1157 #endif /* __TVH_MPEGTS_H__ */
1158 
1159 /******************************************************************************
1160  * Editor Configuration
1161  *
1162  * vim:sts=2:ts=2:sw=2:et
1163  *****************************************************************************/
1164 
1165