File:  [DVB] / multiplexer / global.h
Revision 1.1: download - view: text, annotated - select for diffs
Mon Mar 19 20:52:34 2001 UTC (23 years, 2 months ago) by oskar
Branches: MAIN
CVS tags: HEAD
Multiplexer, first archived version.
New feature: --badtiming (see --help)

/*
 * ISO 13818 stream multiplexer
 * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
 * Author: Oskar Schirmer (oskar@convergence.de)
 */

#include <asm/types.h>
#include <sys/types.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

/* 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
#define PCR_INTERPOLSIZE   8

#define MAX_POLLFD    (MAX_INFILE+3)

#define MAX_DATA_COMB 512
#define HIGHWATER_COM 8

#define BUFSIZ_FACTOR 32 * 2

#define MAX_CTRL_OUTB 32 * BUFSIZ_FACTOR
#define MAX_DATA_OUTB 4096 * BUFSIZ_FACTOR
#define HIGHWATER_OUT 512
#define MAX_WRITE_OUT (128 * 188)
#define OUT_TRIGCOND  (MAX_DATA_OUTB / 2)

#define MAX_CTRL_INB  32 * BUFSIZ_FACTOR
#define MAX_DATA_INB  4096 * BUFSIZ_FACTOR
#define MAX_DATA_RAWB 4096 * BUFSIZ_FACTOR
#define HIGHWATER_IN  (512 * 4 * 8)
#define MAX_READ_IN   (1024 * 8)
#define IN_TRIGCOND   (MAX_DATA_INB / 2)

#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_CTRL_MAPSTR  4
#define MAX_DATA_MAPSTR  4096
*/

#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

typedef struct {
  unsigned long base;
  unsigned short ext;
  unsigned char ba33;
  boolean valid;
} clockref;

/*
#define MIXTIME_MSEC 0x01
#define MIXTIME_TVAL 0x02
#define MIXTIME_CREF 0x04
#define mixflag cr.flags
typedef struct {
  int msec;
  struct timeval tv;
  clockref cr;
  clockref *localrelativeclockref;
} mixtime;
*/

typedef struct {
  int read;
  int push;
} time_stamp;

typedef struct {
  int index;
  int length;
  int sequence;
  int scramble;
  time_stamp time;
  clockref pcr; /* FIXME: this goes parallel to time.push */
  clockref opcr;
} 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_incr(var,refr,incr) \
  ((var) = (((var) + (incr)) & (refr).mask))

#define clockref2msec(cref) \
  ((cref).base / 90)

#define msec2clockref(msec,cref) \
  (((cref).base = (msec) * 90), ((cref).ext = 0), ((cref).ba33 = 0))

#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<<bit,1<<bit)

#define mmin(a,b) ((a)<(b)?(a):(b))
#define mmax(a,b) ((a)<(b)?(b):(a))

#define unionalloc(typ,fld) \
  (malloc (sizeof(typ)-sizeof(((typ*)0)->u)+sizeof(((typ*)0)->u.fld)))

typedef struct {
  int sourceid;
  int programnumber;
  byte version;
  byte *elemdnew[NUMBER_ELEMD];
} mapreference;

typedef struct pmtdescr {
  struct pmtdescr *next;
  short pat_section;
  byte pmt_version;
  int programnumber;
  int pcr_pid;
  int pmt_pid;
  int streams;
  short stream[MAX_PMTSTREAMS];
  byte streamtype[MAX_PMTSTREAMS];
  int descrlen;
  byte elemdescr[MAX_PSI_SIZE];
} pmt_descr;

typedef struct {
  int sprg, tprg, ssid, tsid;
} tsauto_descr;

typedef enum {
  ct_none,
/*  ct_elementary, */
  ct_packetized,
  ct_program,
  ct_transport,
  ct_unknown
} content_type;

typedef struct {
  refr_data data;
  char *name;
  int handle;
  struct stat stat;
  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 */
  int opendatastreams;
  int openmapstreams;
  byte endaction;
  boolean automatic; /* extract'o'use */
  int auto_programnb;
  content_type content;
  union {
    struct {
      struct streamdescr *stream;
    } pes;
    struct {
      time_stamp time;
      struct {
        clockref scr;
        long muxrate;
      } ph;
      struct {
        long ratebound;
        int audiobound;
        int 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 {
      int 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;
  int pcr_pid;
  int pmt_pid;
  int map_sequence; /* don't need ? */
  byte pmt_conticnt;
  byte pmt_version;
  boolean changed;
  int pat_section;
  int streams;
  struct streamdescr *stream[MAX_STRPERPRG];
} prog_descr;

typedef struct streamdescr {
  refr_ctrl ctrl;
  refr_data data;
  int sourceid; /* index into fdescr->u.xx.stream[] */
  byte stream_id; /* elementary stream id, table 2-35, etc */
  byte stream_type;
  byte version;
  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?*/
  file_descr *fdescr;
  byte conticnt;
  byte endaction;
  boolean isamap;
  union {
    struct {
      int pid; /* splicets: 0010..1FFE, spliceps: ...FF */
      struct streamdescr *mapstream;
      boolean discontinuity;
      boolean trigger;
      boolean mention;
      boolean has_clockref; /* in output */
      int next_clockref;
      int delta;
      int lasttime;
      int progs;
      prog_descr *pdescr[MAX_PRGFORSTR];
    } d;
    struct {
      int readtime;
      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 int global_delta;
extern int psi_frequency_msec;
extern boolean psi_frequency_changed;

int msec_now (void);

void global_init (void);


#ifdef DEBUG_TIMEPOLL

#define max_timepoll (1024*1024)

typedef struct {
  struct timeval tv;
  int 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


LinuxTV legacy CVS <linuxtv.org/cvs>