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