Annotation of multiplexer/repeatts.c, revision 1.2

1.1       oskar       1: /*
                      2:  * ISO 13818 stream multiplexer / additional repeater tool
                      3:  * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
                      4:  * Author: Oskar Schirmer (oskar@convergence.de)
                      5:  */
                      6: 
                      7: /*
                      8:  * Module:  Repeater
                      9:  * Purpose: Additional tool to repeat and pipe an input stream.
                     10:  *
                     11:  * This tool accepts a (time1,time2,filename) tuple via stdin,
                     12:  * opens the filename, assuming it contains a ISO 13818 Transport Stream,
                     13:  * and sends it packet-wise to stdout timed in such a way, that
                     14:  * all pakets are sent equally distributed within time2 msec.
                     15:  * As long as no further tuple is provided, after time1 msec the same
                     16:  * file is sent over and over again.
                     17:  */
                     18: 
                     19: 
                     20: #include <stdio.h>
                     21: #include "global.h"
                     22: 
1.2     ! oskar      23: #define D(x) /* x */
1.1       oskar      24: 
                     25: #define MAX_ANOTATE (16 * 256)
                     26: 
                     27: static boolean quit;
                     28: static int cmdf, outf, nextf;
                     29: 
                     30: static int combln, comlln;
                     31: static byte combuf[MAX_DATA_COMB];
                     32: 
                     33: static int dati, dato;
                     34: static byte data[MAX_ANOTATE];
                     35: 
                     36: static t_msec nextrdelay, nextfdelay;
                     37: 
                     38: t_msec msec_now (void)
                     39: {
                     40: #define MSEC_EXPONENT 21
                     41:   static long last;
                     42:   static int local_delta;
                     43:   struct timeval tv;
                     44:   gettimeofday (&tv,NULL);
                     45:   if ((tv.tv_sec & (~((1L << MSEC_EXPONENT) - 1))) != last) {
                     46:     last = tv.tv_sec & (~((1L << MSEC_EXPONENT) - 1));
                     47:     local_delta += 1000 * (1L << MSEC_EXPONENT);
                     48:   }
                     49:   return ((tv.tv_sec & ((1L << MSEC_EXPONENT) - 1)) * 1000
                     50:          + tv.tv_usec / 1000 + local_delta);
                     51: }
                     52: 
                     53: static void command_help (char *command)
                     54: {
                     55:   fprintf (stderr, "Usage:\t%s [<delay> <time> <file>]\n"
                     56:   "\tSend <file> repeated every <delay> msec evenly distributed within\n"
                     57:   "\t<time> msec, Feed a (delay,time,file) tuple to stdin to reset\n"
                     58:   "\tbehaviour, quit program with negative delay, don't repeat with delay=0.\n",
                     59:      command);
                     60: }
                     61: 
                     62: static boolean line_complete (char **s1,
                     63:     char **s2,
                     64:     char **s3)
                     65: {
                     66:   int i;
                     67:   boolean b;
                     68:   *s3 = NULL;
                     69:   *s2 = NULL;
                     70:   *s1 = NULL;
                     71:   i = 0;
                     72:   while (i < combln) {
                     73:     if (combuf[i] == '\n') {
                     74:       comlln = i;
                     75:       while (i >= 0) {
                     76:         if (combuf[i] <= ' ') {
                     77:           combuf[i] = 0;
                     78:           b = TRUE;
                     79:         } else {
                     80:           if (b) {
                     81:             *s3 = *s2;
                     82:             *s2 = *s1;
                     83:             b = FALSE;
                     84:           }
                     85:           *s1 = &combuf[i];
                     86:         }
                     87:         i -= 1;
                     88:       }
                     89:       return (TRUE);
                     90:     }
                     91:     i += 1;
                     92:   }
                     93:   return (FALSE);
                     94: }
                     95: 
                     96: static boolean is_long (char *s,
                     97:     long *r)
                     98: {
                     99:   long i;
                    100:   char *e;
                    101:   if (s == NULL) {
                    102:     return (FALSE);
                    103:   }
                    104:   errno = 0;
                    105:   i = strtol (s,&e,0);
                    106:   if ((errno != 0)
                    107:    || (*e != 0)) {
                    108:     return (FALSE);
                    109:   }
                    110:   *r = i;
                    111:   return (TRUE);
                    112: }
                    113: 
                    114: static boolean command_do (char *arg1,
                    115:     char *arg2,
                    116:     char *arg3)
                    117: {
                    118:   long l1, l2;
                    119:   struct stat stat;
                    120: D(fprintf(stderr,"command_do(%s,%s,%s)\n",arg1,arg2,arg3));
                    121:   if (arg1 != NULL) {
                    122:     if (is_long (arg1, &l1)) {
                    123:       if (l1 < 0) {
                    124:         quit = TRUE;
                    125:         return (TRUE);
                    126:       }
                    127:       if (arg2 != NULL) {
                    128:         if (is_long (arg2, &l2)) {
                    129:           if (l2 >= 0) {
                    130:             if (arg3 != NULL) {
                    131:               if (nextf >= 0) {
                    132:                 close (nextf);
                    133:               }
                    134:               if ((nextf = open (arg3, O_RDONLY)) >= 0) {
                    135:                 if (fstat (nextf, &stat) == 0) {
                    136: D(fprintf(stderr,"file %d, mode %07o, name %s, ino %ld, size %ld\n",nextf,stat.st_mode,arg3,stat.st_ino,stat.st_size));
                    137:                   if (S_ISREG (stat.st_mode)) {
                    138:                     if ((stat.st_size % TS_PACKET_SIZE) == 0) {
                    139:                       if (stat.st_size > 0) {
                    140:                         nextrdelay = l2 / (stat.st_size / TS_PACKET_SIZE);
                    141:                       } else {
                    142:                         nextrdelay = 0;
                    143:                       }
                    144:                       nextfdelay = l1;
                    145: D(fprintf(stderr,"next opened(%d,%d)\n",nextfdelay,nextrdelay));
                    146:                       return (TRUE);
                    147:                     } else {
                    148:                       fprintf (stderr, "File size not multiple of 188\n");
                    149:                     }
                    150:                   } else {
                    151:                     fprintf (stderr, "File not regular\n");
                    152:                   }
                    153:                 } else {
                    154:                   fprintf (stderr, "Cannot stat file\n");
                    155:                 }
                    156:                 close (nextf);
                    157:                 nextf = -1;
                    158:               } else {
                    159:                 fprintf (stderr, "Cannot open file\n");
                    160:               }
                    161:             } else {
                    162:               fprintf (stderr, "File name missing\n");
                    163:             }
                    164:           } else {
                    165:             fprintf (stderr, "Time must not be negative\n");
                    166:           }
                    167:         } else {
                    168:           fprintf (stderr, "Time must be numeric\n");
                    169:         }
                    170:       } else {
                    171:         fprintf (stderr, "Time missing\n");
                    172:       }
                    173:     } else {
                    174:       fprintf (stderr, "Delay must be numeric\n");
                    175:     }
                    176:   } else {
                    177:     return (TRUE);
                    178:   }
                    179:   return (FALSE);
                    180: }
                    181: 
                    182: static boolean command_init (int cargc,
                    183:     char **cargv)
                    184: {
                    185:   nextf = -1;
                    186:   quit = FALSE;
                    187:   combln = 0;
                    188:   dati = dato = 0;
                    189:   if (cargc > 1) {
                    190:     if (!strcmp (cargv[1],"--help")) {
                    191:       command_help (cargv[0]);
                    192:       return (FALSE);
                    193:     } else if (
                    194:       !command_do (cargv[1], cargc>2?cargv[2]:NULL, cargc>3?cargv[3]:NULL)) {
                    195:       command_help (cargv[0]);
                    196:       return (FALSE);
                    197:     }
                    198:   }
                    199:   cmdf = STDIN_FILENO;
                    200:   outf = STDOUT_FILENO;
                    201:   return ((cmdf >= 0) && (outf >= 0));
                    202: }
                    203: 
                    204: int main (int argc,
                    205:     char *argv[])
                    206: {
                    207:   int polli, pollo, polls;
                    208:   int toberead;
                    209:   int currentf;
                    210:   boolean dotime;
                    211:   t_msec rtime, ftime, rdelay, fdelay, now;
                    212:   struct pollfd ufds [3];
                    213:   if (command_init (argc,&argv[0])) {
                    214:     currentf = -1;
                    215:     rtime = ftime = msec_now ();
                    216:     while (!quit) {
                    217:       now = msec_now ();
                    218: D(fprintf(stderr,"now(%d)\n",now));
                    219:       if (currentf < 0) {
                    220:         toberead = 0;
                    221:         rdelay = nextrdelay;
                    222:         fdelay = nextfdelay;
                    223:         if ((ftime-now) < 0) {
                    224:           ftime = now;
                    225:         }
                    226:         rtime = ftime;
                    227:         currentf = nextf;
                    228:         nextf = -1;
                    229: D(fprintf(stderr,"next current(%d,%d,%d)\n",currentf,fdelay,rdelay));
                    230:       }
                    231:       if (currentf >= 0) {
                    232:         if ((rtime - now) <= 0) {
                    233:           if ((((dato-dati-1) & (MAX_ANOTATE-1)) - toberead) > TS_PACKET_SIZE) {
                    234:             toberead += TS_PACKET_SIZE;
                    235:             rtime += rdelay;
                    236:             dotime = TRUE;
                    237: D(fprintf(stderr,"timer a(%d,%d)\n",toberead,rtime));
                    238:           } else {
                    239:             rtime = now;
                    240:             dotime = FALSE;
                    241: D(fprintf(stderr,"timer b(%d,%d)\n",toberead,rtime));
                    242:           }
                    243:         } else {
                    244:           dotime = TRUE;
                    245: D(fprintf(stderr,"timer c(%d,%d)\n",toberead,rtime));
                    246:         }
                    247:       } else {
                    248:         dotime = FALSE;
                    249: D(fprintf(stderr,"timer c(%d,%d)\n",toberead,rtime));
                    250:       }
                    251:       ufds[0].fd = cmdf;
                    252:       ufds[0].events = POLLIN;
                    253:       if (dati != dato) {
                    254:         ufds[1].fd = outf;
                    255:         ufds[1].events = POLLOUT;
                    256:         pollo = 1;
                    257:       } else {
                    258:         pollo = 0;
                    259:       }
                    260:       polls = pollo+1;
                    261:       if (toberead > 0) {
                    262:         polli = polls++;
                    263:         ufds[polli].fd = currentf;
                    264:         ufds[polli].events = POLLIN;
                    265:       } else {
                    266:         polli = 0;
                    267:       }
                    268:       poll (&ufds[0], polls, dotime ? ((rtime-now) > 0) ? (rtime-now) : 0 : -1);
                    269:       if (ufds[0].revents & POLLIN) {
                    270:         char *s1, *s2, *s3;
                    271:         if (combln >= MAX_DATA_COMB-HIGHWATER_COM) {
                    272:           combln -= HIGHWATER_COM;
                    273:           memmove (&combuf[0], &combuf[HIGHWATER_COM], combln);
                    274:         }
                    275:         combln += read (cmdf, &combuf[combln], MAX_DATA_COMB-combln);
                    276:         while (line_complete (&s1, &s2, &s3)) {
                    277:           command_do (s1, s2, s3);
                    278:           combln -= comlln;
                    279:           memmove (&combuf[0], &combuf[comlln], combln);
                    280:         }
                    281:       }
                    282:       if ((polli != 0)
                    283:        && (ufds[polli].revents & (POLLIN | POLLHUP | POLLERR))) {
                    284:         int l;
                    285:         if (ufds[polli].revents & POLLIN) {
                    286:           l = toberead;
                    287:           if (l > (MAX_ANOTATE - dati)) {
                    288:             l = MAX_ANOTATE - dati;
                    289:           }
                    290:           l = read (currentf, &data[dati], l);
                    291:           dati = (dati+l) & (MAX_ANOTATE-1);
                    292:           toberead -= l;
                    293:         } else {
                    294:           l = 0;
                    295:         }
                    296:         if (l == 0) {
                    297:           if ((nextf >= 0)
                    298:            || (fdelay == 0)) {
                    299:             close (currentf);
                    300:             currentf = -1;
                    301:           } else {
                    302:             lseek (currentf,0,SEEK_SET);
                    303:             toberead = ((toberead-1) / TS_PACKET_SIZE) * TS_PACKET_SIZE;
                    304:           }
                    305:           ftime += fdelay;
                    306:           now = msec_now ();
                    307:           if ((ftime-now) < 0) {
                    308:             ftime = now;
                    309:           }
                    310:           rtime = ftime;
                    311:         }
                    312:       }
                    313:       if ((pollo != 0)
                    314:        && (ufds[1].revents & (POLLOUT | POLLHUP | POLLERR))) {
                    315:         if (ufds[1].revents & POLLOUT) {
                    316:           int l;
                    317:           if (dati < dato) {
                    318:             l = MAX_ANOTATE - dato;
                    319:           } else {
                    320:             l = dati - dato;
                    321:           }
                    322:           l = write (outf, &data[dato], l);
                    323:           dato = (dato+l) & (MAX_ANOTATE-1);
                    324:           if (l == 0) {
                    325:             quit = TRUE;
                    326:           }
                    327:         } else {
                    328:           quit = TRUE;
                    329:         }
                    330:       }
                    331:     }
                    332:     return (EXIT_SUCCESS);
                    333:   }
                    334:   return (EXIT_FAILURE);
                    335: }

LinuxTV legacy CVS <linuxtv.org/cvs>