Annotation of multiplexer/global.h, revision 1.19
1.1 oskar 1: /*
2: * ISO 13818 stream multiplexer
3: * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
4: * Author: Oskar Schirmer (oskar@convergence.de)
5: */
6:
7: #include <asm/types.h>
8: #include <sys/types.h>
9: #include <sys/poll.h>
10: #include <sys/time.h>
11: #include <sys/unistd.h>
12: #include <sys/stat.h>
13: #include <unistd.h>
14: #include <fcntl.h>
15: #include <stdlib.h>
16: #include <string.h>
17: #include <errno.h>
18:
19: /* for a timing and poll profile: */
20: #if 0
21: #define DEBUG_TIMEPOLL
22: #endif
23:
1.12 oskar 24: #define PES_LOWEST_SID (0xBC)
1.15 oskar 25: #define NUMBER_DESCR 256
1.12 oskar 26: #define TS_PACKET_SIZE 188
27:
28: #define CRC_SIZE 4
29:
1.1 oskar 30: #define MAX_MSEC_OUTDELAY 500
31: #define MAX_MSEC_PUSHJTTR (2 * 250)
1.3 oskar 32: #define MAX_MSEC_PCRDIST (100 * 80/100)
1.1 oskar 33:
1.12 oskar 34: #define TRIGGER_MSEC_INPUT 250
35: #define TRIGGER_MSEC_OUTPUT 250
1.1 oskar 36:
37: #define MAX_DATA_COMB 512
38: #define HIGHWATER_COM 8
39:
1.12 oskar 40: #define MAX_CTRL_OUTB (1 << 16)
1.4 oskar 41: #define MAX_DATA_OUTB (MAX_CTRL_OUTB << 7)
1.1 oskar 42: #define HIGHWATER_OUT 512
1.12 oskar 43: #define MAX_WRITE_OUT (44 * TS_PACKET_SIZE)
1.1 oskar 44:
1.12 oskar 45: #define MAX_CTRL_INB (1 << 10)
1.4 oskar 46: #define MAX_DATA_INBV (MAX_CTRL_INB << 10)
47: #define MAX_DATA_INBA (MAX_CTRL_INB << 9)
48: #define MAX_DATA_INB (MAX_CTRL_INB << 9)
1.18 oskar 49: #define MAX_DATA_INBPSI (MAX_CTRL_INB << 6)
1.4 oskar 50: #define HIGHWATER_IN (16 * 1024)
51:
52: #define MAX_DATA_RAWB (1 << 18)
53: #define HIGHWATER_RAW (16 * 1024)
54: #define MAX_READ_IN (8 * 1024)
1.1 oskar 55:
56: #define MAX_INSTREAM 64 /* ? */
57: #define MAX_INFILE 8 /* ? */
58:
59: #define MAX_STRPERPS (1<<8)
60: #define MAX_STRPERTS (1<<13)
61:
1.16 oskar 62: #define MAX_DESCR_LEN 0xFF
1.13 oskar 63: #define MAX_PSI_SIZE (4096+1)
64: #define CAN_PSI_SIZE (1024+1)
65: #define MAX_PMTSTREAMS (CAN_PSI_SIZE / 4)
66:
1.1 oskar 67: #define MAX_STRPERPRG 42 /* ? */
1.13 oskar 68: #define MAX_OUTPROG 32 /* ? */
69: #define MAX_PRGFORSTR MAX_OUTPROG
1.1 oskar 70:
1.12 oskar 71: #define MAX_POLLFD (MAX_INFILE+3)
72:
1.1 oskar 73: #define ENDSTR_KILL 0
74: #define ENDSTR_CLOSE 1
75: #define ENDSTR_WAIT 2
76:
77: #define boolean __u8
78: #define FALSE 0
79: #define TRUE 1
80:
81: #define byte __u8
1.4 oskar 82: #define t_msec __s32
1.1 oskar 83:
1.7 oskar 84: /* ISO 13818 clock reference 90kHz (33 bit) with 27MHz extension (9 bit).
85: * ba33 holds the high bit of base.
86: */
1.1 oskar 87: typedef struct {
1.4 oskar 88: __u32 base;
89: __u16 ext;
1.3 oskar 90: byte ba33;
1.1 oskar 91: boolean valid;
92: } clockref;
93:
1.7 oskar 94: /* For conversion purposes, this pair of values holds a partial clock
95: * reference and an internal value in milliseconds. This is to eliminate
96: * wrapping faults without producing conversion inaccuracies.
97: */
1.1 oskar 98: typedef struct {
1.4 oskar 99: __u32 base;
100: t_msec msec;
1.3 oskar 101: } conversion_base;
1.1 oskar 102:
1.7 oskar 103: /* On reference to a controlled data buffer, this one holds the control
104: * information, mainly: index into the data buffer, length of the referenced
105: * data block. In a controlled data buffer, a data block is never split to
106: * wrap at the end of the buffer. The other fields are usage dependend.
107: */
1.1 oskar 108: typedef struct {
109: int index;
110: int length;
111: int sequence;
1.4 oskar 112: t_msec msecread;
113: t_msec msecpush;
1.3 oskar 114: clockref pcr;
1.1 oskar 115: clockref opcr;
1.4 oskar 116: byte scramble;
1.1 oskar 117: } ctrl_buffer;
118:
1.7 oskar 119: /* Control buffer */
1.1 oskar 120: typedef struct {
121: ctrl_buffer *ptr;
122: int in;
123: int out;
124: int mask;
125: } refr_ctrl;
126:
1.7 oskar 127: /* Data buffer */
1.1 oskar 128: typedef struct {
129: byte *ptr;
130: int in;
131: int out;
132: int mask;
133: } refr_data;
134:
135:
1.7 oskar 136: /* Create a new buffer, return TRUE on success, FALSE otherwise */
1.1 oskar 137: #define list_create(refr,size) \
138: ((((size) & ((size)-1)) || (size < 2)) ? \
139: warn (LERR,"List Create",EGLO,1,1,size), FALSE : \
140: ((refr).ptr = malloc((size) * sizeof(*(refr).ptr))) == NULL ? \
141: warn (LERR,"List Create",EGLO,1,2,size), FALSE : \
142: ((refr).mask = (size)-1, (refr).in = (refr).out = 0, TRUE))
143:
1.7 oskar 144: /* Release a buffer no longer used */
1.1 oskar 145: #define list_release(refr) \
146: ((refr).mask = 0, free((refr).ptr), (refr).ptr = NULL)
147:
1.12 oskar 148: /* Test on buffer emptiness */
149: #define list_empty(refr) ((refr).out == (refr).in)
150:
1.7 oskar 151: /* Compute number of free elements in buffer */
1.1 oskar 152: #define list_free(refr) \
153: (((refr).out - (refr).in - 1) & (refr).mask)
154:
1.17 oskar 155: /* Version of list_free with cached (refr).in */
156: #define list_freecachedin(refr,refrin) \
157: (((refr).out - refrin - 1) & (refr).mask)
158:
1.7 oskar 159: /* Compute number of free elements up to the wrapping point, if the
160: latter is included in the free part of the buffer */
1.1 oskar 161: #define list_freeinend(refr) \
162: ((refr).mask + 1 - (refr).in)
1.17 oskar 163:
164: /* Version of list_freeinend with cached (refr).in */
165: #define list_freeinendcachedin(refr,refrin) \
166: ((refr).mask + 1 - refrin)
1.1 oskar 167:
1.7 oskar 168: /* Compute number of used elements in buffer (i.e. its current size) */
1.1 oskar 169: #define list_size(refr) \
170: (((refr).in - (refr).out) & (refr).mask)
171:
1.7 oskar 172: /* Test on buffer fullness */
1.1 oskar 173: #define list_full(refr) \
174: (list_free(refr) == 0)
175:
1.12 oskar 176: /* Test on buffer partial fullness (as trigger criterium) */
177: #define list_partialfull(refr) \
178: (list_size(refr) > ((refr).mask * 3/4))
1.4 oskar 179:
1.7 oskar 180: /* Increment an index variable that points in to a buffer by a given value */
1.1 oskar 181: #define list_incr(var,refr,incr) \
182: ((var) = (((var) + (incr)) & (refr).mask))
1.12 oskar 183:
1.1 oskar 184:
1.7 oskar 185: /* Check a data byte against a mask */
1.1 oskar 186: #define marker_check(data,val,mask) \
187: (((data & mask) != val) ? \
188: warn(LWAR,"Marker bit",EGLO,2,data,mask), TRUE : FALSE)
189:
1.7 oskar 190: /* Check whether a given bit is set in a data byte */
1.1 oskar 191: #define marker_bit(data,bit) \
192: marker_check(data,1<<bit,1<<bit)
193:
194: #define mmin(a,b) ((a)<(b)?(a):(b))
195: #define mmax(a,b) ((a)<(b)?(b):(a))
196:
1.7 oskar 197: /* Allocate memory for a struct with known union usage */
1.1 oskar 198: #define unionalloc(typ,fld) \
199: (malloc (sizeof(typ)-sizeof(((typ*)0)->u)+sizeof(((typ*)0)->u.fld)))
200:
1.8 oskar 201: /* Release a chained list completely */
202: #define releasechain(typ,root) \
1.14 oskar 203: { register typ *relchn_n, *relchn_p = root; \
204: while (relchn_p != NULL) { \
205: relchn_n = relchn_p->next; free (relchn_p); relchn_p = relchn_n; \
1.8 oskar 206: } }
207:
1.10 oskar 208: /* Supported input file types */
209: typedef enum {
210: ct_packetized, /* packetized elementary stream */
211: ct_program, /* program stream */
212: ct_transport, /* transport stream */
1.11 oskar 213: number_ct
1.10 oskar 214: } content_type;
215:
216: /* stream data types, dependend on buffer contents */
217: typedef enum {
218: sd_data, /* PES packet */
219: sd_map, /* mapreference containing descriptors */
220: sd_unparsedsi, /* TS packet containing raw partial SI sections */
1.11 oskar 221: number_sd
1.10 oskar 222: } streamdata_type;
223:
1.7 oskar 224: /* Reference descriptors as these are parsed from PSI */
1.1 oskar 225: typedef struct {
226: int programnumber;
1.4 oskar 227: short sourceid;
1.1 oskar 228: byte version;
1.15 oskar 229: byte *elemdnew[NUMBER_DESCR];
1.1 oskar 230: } mapreference;
231:
1.7 oskar 232: /* Source TS PMT list */
1.1 oskar 233: typedef struct pmtdescr {
234: struct pmtdescr *next;
235: short pat_section;
236: byte pmt_version;
237: int programnumber;
1.4 oskar 238: short pcr_pid;
239: short pmt_pid;
240: short streams;
1.1 oskar 241: short stream[MAX_PMTSTREAMS];
242: byte streamtype[MAX_PMTSTREAMS];
1.4 oskar 243: short descrlen;
1.1 oskar 244: byte elemdescr[MAX_PSI_SIZE];
245: } pmt_descr;
246:
1.7 oskar 247: /* Automatic stream usage requests as stated via command */
1.8 oskar 248: typedef struct tsautodescr {
249: struct tsautodescr *next;
250: int sprg;
251: int tprg;
252: int ssid; /* ssid<0 when referencing a complete program */
253: int tsid;
1.1 oskar 254: } tsauto_descr;
255:
1.9 oskar 256: /* Declaration of pid ranges as being not-to-be-parsed SI */
257: typedef struct tssidescr {
258: struct tssidescr *next;
259: short pid_low;
260: short pid_high;
261: } tssi_descr;
262:
1.7 oskar 263: /* Source file */
1.1 oskar 264: typedef struct {
265: refr_data data;
1.5 oskar 266: int handle;
1.1 oskar 267: char *name;
1.5 oskar 268: int filerefnum;
1.4 oskar 269: int st_mode;
1.1 oskar 270: struct pollfd *ufds;
271: int skipped; /* undesired bytes skipped, total */
272: int payload; /* split payload used total */
273: int total; /* split total (skipped, used, wasted) */
274: int sequence; /* source counter for PES sequence */
1.11 oskar 275: short openstreams[number_sd];
1.5 oskar 276: char *append_name;
277: int append_filerefnum;
278: int append_repeatitions;
1.2 oskar 279: int repeatitions;
1.1 oskar 280: int auto_programnb;
1.5 oskar 281: boolean automatic; /* extract'o'use */
282: boolean stopfile;
1.1 oskar 283: content_type content;
284: union {
285: struct {
286: struct streamdescr *stream;
287: } pes;
288: struct {
289: struct {
290: clockref scr;
1.4 oskar 291: __u32 muxrate;
1.1 oskar 292: } ph;
293: struct {
1.4 oskar 294: __u32 ratebound;
295: byte audiobound;
296: byte videobound;
1.1 oskar 297: boolean csps_flag;
298: boolean fixed_flag;
299: boolean system_video_lock_flag;
300: boolean system_audio_lock_flag;
301: boolean packet_rate_restriction_flag;
302: short buffer_bound[MAX_STRPERPS-PES_LOWEST_SID];
303: } sh;
304: /*
305: struct {
306: } dir;
307: */
308: struct streamdescr *stream[MAX_STRPERPS];
309: } ps;
310: struct {
1.4 oskar 311: __u16 transportstreamid;
1.1 oskar 312: byte pat_version;
313: byte newpat_version;
314: pmt_descr *pat;
315: pmt_descr *newpat;
316: tsauto_descr *tsauto;
1.9 oskar 317: tssi_descr *tssi;
1.1 oskar 318: struct streamdescr *stream[MAX_STRPERTS];
319: } ts;
320: } u;
321: } file_descr;
322:
1.14 oskar 323: /* Descriptors, data and reference index list */
324: typedef struct {
1.15 oskar 325: byte *refx[NUMBER_DESCR];
1.16 oskar 326: byte null[2];
1.14 oskar 327: byte data[MAX_PSI_SIZE];
328: } descr_descr;
329:
330: /* Stream entry in target PMT, without corresponding input stream.
331: * This is used to manually denote si streams, that are brought in
332: * via --si and have to be mentioned in PMT in some way.
333: */
334: typedef struct stumpdescr {
335: struct stumpdescr *next;
336: int program_number;
337: short pid;
338: byte stream_type;
339: descr_descr manudescr;
340: } stump_descr;
341:
1.7 oskar 342: /* Target program */
1.1 oskar 343: typedef struct {
344: int program_number;
1.4 oskar 345: short pcr_pid;
346: short pmt_pid;
1.1 oskar 347: byte pmt_conticnt;
348: byte pmt_version;
1.18 oskar 349: boolean changed; /* must generate new psi due to change */
350: boolean unchanged; /* must generate new psi due to timing */
1.4 oskar 351: short pat_section;
352: short streams;
1.1 oskar 353: struct streamdescr *stream[MAX_STRPERPRG];
1.14 oskar 354: stump_descr *stump; /* just entries in PMT, not really data streams */
1.16 oskar 355: descr_descr manudescr;
1.1 oskar 356: } prog_descr;
357:
1.7 oskar 358: /* Single data or map stream */
1.1 oskar 359: typedef struct streamdescr {
360: refr_ctrl ctrl;
361: refr_data data;
1.4 oskar 362: file_descr *fdescr;
363: short sourceid; /* index into fdescr->u.xx.stream[] */
1.1 oskar 364: byte stream_id; /* elementary stream id, table 2-35, etc */
1.14 oskar 365: byte stream_type; /* table 2-29 */
1.1 oskar 366: byte version;
1.4 oskar 367: byte conticnt;
368: byte endaction;
1.14 oskar 369: descr_descr *autodescr; /* Descriptors copied from input stream */
370: descr_descr *manudescr; /* Descriptors manually added */
1.1 oskar 371: /*what if a stream is leftupper corner in one prog, but elsewhere in another?*/
1.10 oskar 372: streamdata_type streamdata;
1.1 oskar 373: union {
374: struct {
1.4 oskar 375: short pid; /* splicets: 0010..1FFE, spliceps: ...FF */
1.1 oskar 376: boolean discontinuity;
377: boolean trigger;
378: boolean mention;
379: boolean has_clockref; /* in output */
1.6 oskar 380: boolean has_opcr; /* in input */
1.14 oskar 381: struct streamdescr *mapstream;
382: t_msec next_clockref;
383: t_msec delta;
384: conversion_base conv;
385: t_msec lasttime;
1.4 oskar 386: short progs;
1.1 oskar 387: prog_descr *pdescr[MAX_PRGFORSTR];
388: } d;
389: struct {
1.4 oskar 390: t_msec msectime;
1.3 oskar 391: conversion_base conv;
1.1 oskar 392: int psi_length;
393: byte psi_data[MAX_PSI_SIZE+TS_PACKET_SIZE];
394: } m;
1.10 oskar 395: struct {
396: } usi;
1.1 oskar 397: } u;
398: } stream_descr;
399:
400:
401: extern boolean timed_io;
402: extern boolean accept_weird_scr;
1.4 oskar 403: extern t_msec global_delta;
404: extern t_msec psi_frequency_msec;
1.1 oskar 405: extern boolean psi_frequency_changed;
406:
1.4 oskar 407: t_msec msec_now (void);
1.3 oskar 408:
409: void cref2msec (conversion_base *b,
410: clockref c,
1.4 oskar 411: t_msec *m);
1.3 oskar 412:
413: void msec2cref (conversion_base *b,
1.4 oskar 414: t_msec m,
1.3 oskar 415: clockref *c);
1.1 oskar 416:
417: void global_init (void);
418:
419:
420: #ifdef DEBUG_TIMEPOLL
421:
422: #define max_timepoll (1024*1024)
423:
424: typedef struct {
425: struct timeval tv;
1.4 oskar 426: t_msec msec_now;
1.1 oskar 427: int usec;
428: int tmo;
429: int sr, si, so;
430: unsigned char cnt_msecnow;
431: unsigned char nfdso, nfdsi;
432: unsigned char nfdsrevent;
433: unsigned char flags;
434: } timepoll;
435: #define LTP_FLAG_DELTASHIFT 0x80
436: #define LTP_FLAG_OUTPUT 0x40
437: #define LTP_FLAG_INPUT 0x20
438: #define LTP_FLAG_SPLIT 0x10
439: #define LTP_FLAG_PROCESS 0x08
440:
441: extern timepoll logtp [max_timepoll];
442: extern long logtpc;
443: extern timepoll *ltp;
444:
445: #endif
446:
LinuxTV legacy CVS <linuxtv.org/cvs>