/* * ISO 13818 stream multiplexer * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin * Author: Oskar Schirmer (oskar@convergence.de) */ #include #include #include #include #include #include #include #include #include #include #include /* for a timing and poll profile: */ #if 0 #define DEBUG_TIMEPOLL #endif #define MAX_MSEC_OUTDELAY 500 #define MAX_MSEC_PUSHJTTR (2 * 250) #define MAX_MSEC_PCRDIST (100 * 80/100) #define MAX_POLLFD (MAX_INFILE+3) #define MAX_DATA_COMB 512 #define HIGHWATER_COM 8 #define MAX_CTRL_OUTB (1 << 11) #define MAX_DATA_OUTB (MAX_CTRL_OUTB << 7) #define HIGHWATER_OUT 512 #define MAX_WRITE_OUT (128 * 188) #define MAX_CTRL_INB (1 << 8) #define MAX_DATA_INBV (MAX_CTRL_INB << 10) #define MAX_DATA_INBA (MAX_CTRL_INB << 9) #define MAX_DATA_INB (MAX_CTRL_INB << 9) #define HIGHWATER_IN (16 * 1024) #define MAX_DATA_RAWB (1 << 18) #define HIGHWATER_RAW (16 * 1024) #define MAX_READ_IN (8 * 1024) #define MAX_INSTREAM 64 /* ? */ #define MAX_INFILE 8 /* ? */ #define MAX_STRPERPS (1<<8) #define MAX_STRPERTS (1<<13) #define MAX_STRPERPRG 42 /* ? */ #define MAX_PRGFORSTR 12 /* ? */ #define MAX_OUTPROG 16 /* ? */ #define MAX_PSI_SIZE 1025 #define MAX_PMTSTREAMS (MAX_PSI_SIZE / 4) #define ENDFILE_CLOSE 0 #define ENDFILE_RESET 1 #define ENDFILE_CHAIN 2 #define ENDSTR_KILL 0 #define ENDSTR_CLOSE 1 #define ENDSTR_WAIT 2 #define PES_LOWEST_SID (0xBC) #define NUMBER_ELEMD 19 #define TS_PACKET_SIZE 188 #define CRC_SIZE 4 #define boolean __u8 #define FALSE 0 #define TRUE 1 #define byte __u8 #define t_msec __s32 typedef struct { __u32 base; __u16 ext; byte ba33; boolean valid; } clockref; typedef struct { __u32 base; t_msec msec; } conversion_base; typedef struct { int index; int length; int sequence; t_msec msecread; t_msec msecpush; clockref pcr; clockref opcr; byte scramble; } ctrl_buffer; typedef struct { ctrl_buffer *ptr; int in; int out; int mask; } refr_ctrl; typedef struct { byte *ptr; int in; int out; int mask; } refr_data; #define list_empty(refr) ((refr).out == (refr).in) #define list_create(refr,size) \ ((((size) & ((size)-1)) || (size < 2)) ? \ warn (LERR,"List Create",EGLO,1,1,size), FALSE : \ ((refr).ptr = malloc((size) * sizeof(*(refr).ptr))) == NULL ? \ warn (LERR,"List Create",EGLO,1,2,size), FALSE : \ ((refr).mask = (size)-1, (refr).in = (refr).out = 0, TRUE)) #define list_release(refr) \ ((refr).mask = 0, free((refr).ptr), (refr).ptr = NULL) #define list_free(refr) \ (((refr).out - (refr).in - 1) & (refr).mask) #define list_freeinend(refr) \ ((refr).mask + 1 - (refr).in) #define list_size(refr) \ (((refr).in - (refr).out) & (refr).mask) #define list_full(refr) \ (list_free(refr) == 0) #define list_halffull(refr) \ (list_size(refr) > ((refr).mask >> 1)) #define list_incr(var,refr,incr) \ ((var) = (((var) + (incr)) & (refr).mask)) #define marker_check(data,val,mask) \ (((data & mask) != val) ? \ warn(LWAR,"Marker bit",EGLO,2,data,mask), TRUE : FALSE) #define marker_bit(data,bit) \ marker_check(data,1<u)+sizeof(((typ*)0)->u.fld))) typedef struct { int programnumber; short sourceid; byte version; byte *elemdnew[NUMBER_ELEMD]; } mapreference; typedef struct pmtdescr { struct pmtdescr *next; short pat_section; byte pmt_version; int programnumber; short pcr_pid; short pmt_pid; short streams; short stream[MAX_PMTSTREAMS]; byte streamtype[MAX_PMTSTREAMS]; short descrlen; byte elemdescr[MAX_PSI_SIZE]; } pmt_descr; typedef struct { int sprg, tprg, ssid, tsid; } tsauto_descr; typedef enum { ct_none, ct_packetized, ct_program, ct_transport, ct_unknown } content_type; typedef struct { refr_data data; char *name; int handle; int st_mode; struct pollfd *ufds; int skipped; /* undesired bytes skipped, total */ int payload; /* split payload used total */ int total; /* split total (skipped, used, wasted) */ int sequence; /* source counter for PES sequence */ short opendatastreams; short openmapstreams; byte endaction; boolean automatic; /* extract'o'use */ int repeatitions; int auto_programnb; content_type content; union { struct { struct streamdescr *stream; } pes; struct { struct { clockref scr; __u32 muxrate; } ph; struct { __u32 ratebound; byte audiobound; byte videobound; boolean csps_flag; boolean fixed_flag; boolean system_video_lock_flag; boolean system_audio_lock_flag; boolean packet_rate_restriction_flag; short buffer_bound[MAX_STRPERPS-PES_LOWEST_SID]; } sh; /* struct { } dir; */ struct streamdescr *stream[MAX_STRPERPS]; } ps; struct { __u16 transportstreamid; byte pat_version; byte newpat_version; pmt_descr *pat; pmt_descr *newpat; int tsautos; tsauto_descr *tsauto; struct streamdescr *stream[MAX_STRPERTS]; } ts; } u; } file_descr; typedef struct { int program_number; short pcr_pid; short pmt_pid; byte pmt_conticnt; byte pmt_version; boolean changed; short pat_section; short streams; struct streamdescr *stream[MAX_STRPERPRG]; } prog_descr; typedef struct streamdescr { refr_ctrl ctrl; refr_data data; file_descr *fdescr; short sourceid; /* index into fdescr->u.xx.stream[] */ byte stream_id; /* elementary stream id, table 2-35, etc */ byte stream_type; byte version; byte conticnt; byte endaction; byte *elemdvld[NUMBER_ELEMD]; /* as valid for out */ byte elemdescr[MAX_PSI_SIZE]; /*what if a stream is leftupper corner in one prog, but elsewhere in another?*/ boolean isamap; union { struct { struct streamdescr *mapstream; t_msec next_clockref; t_msec delta; conversion_base conv; t_msec lasttime; short pid; /* splicets: 0010..1FFE, spliceps: ...FF */ boolean discontinuity; boolean trigger; boolean mention; boolean has_clockref; /* in output */ short progs; prog_descr *pdescr[MAX_PRGFORSTR]; } d; struct { t_msec msectime; conversion_base conv; int psi_length; byte psi_data[MAX_PSI_SIZE+TS_PACKET_SIZE]; } m; } u; } stream_descr; extern boolean timed_io; extern boolean accept_weird_scr; extern t_msec global_delta; extern t_msec psi_frequency_msec; extern boolean psi_frequency_changed; t_msec msec_now (void); void cref2msec (conversion_base *b, clockref c, t_msec *m); void msec2cref (conversion_base *b, t_msec m, clockref *c); void global_init (void); #ifdef DEBUG_TIMEPOLL #define max_timepoll (1024*1024) typedef struct { struct timeval tv; t_msec msec_now; int usec; int tmo; int sr, si, so; unsigned char cnt_msecnow; unsigned char nfdso, nfdsi; unsigned char nfdsrevent; unsigned char flags; } timepoll; #define LTP_FLAG_DELTASHIFT 0x80 #define LTP_FLAG_OUTPUT 0x40 #define LTP_FLAG_INPUT 0x20 #define LTP_FLAG_SPLIT 0x10 #define LTP_FLAG_PROCESS 0x08 extern timepoll logtp [max_timepoll]; extern long logtpc; extern timepoll *ltp; #endif