Annotation of multiplexer/repeatts.c, revision 1.3

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) {
1.3     ! oskar     130:             if ((l1 >= l2) || (l1 == 0)) {
        !           131:               if (arg3 != NULL) {
        !           132:                 if (nextf >= 0) {
        !           133:                   close (nextf);
        !           134:                 }
        !           135:                 if ((nextf = open (arg3, O_RDONLY)) >= 0) {
        !           136:                   if (fstat (nextf, &stat) == 0) {
        !           137:   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));
        !           138:                     if (S_ISREG (stat.st_mode)) {
        !           139:                       if ((stat.st_size % TS_PACKET_SIZE) == 0) {
        !           140:                         if (stat.st_size > 0) {
        !           141:                           nextrdelay = l2 / (stat.st_size / TS_PACKET_SIZE);
        !           142:                         } else {
        !           143:                           nextrdelay = 0;
        !           144:                         }
        !           145:                         nextfdelay = l1;
        !           146:   D(fprintf(stderr,"next opened(%d,%d)\n",nextfdelay,nextrdelay));
        !           147:                         return (TRUE);
1.1       oskar     148:                       } else {
1.3     ! oskar     149:                         fprintf (stderr, "File size not multiple of 188\n");
1.1       oskar     150:                       }
                    151:                     } else {
1.3     ! oskar     152:                       fprintf (stderr, "File not regular\n");
1.1       oskar     153:                     }
                    154:                   } else {
1.3     ! oskar     155:                     fprintf (stderr, "Cannot stat file\n");
1.1       oskar     156:                   }
1.3     ! oskar     157:                   close (nextf);
        !           158:                   nextf = -1;
1.1       oskar     159:                 } else {
1.3     ! oskar     160:                   fprintf (stderr, "Cannot open file\n");
1.1       oskar     161:                 }
                    162:               } else {
1.3     ! oskar     163:                 fprintf (stderr, "File name missing\n");
1.1       oskar     164:               }
                    165:             } else {
1.3     ! oskar     166:               fprintf (stderr, "0<delay<time not allowed\n");
1.1       oskar     167:             }
                    168:           } else {
                    169:             fprintf (stderr, "Time must not be negative\n");
                    170:           }
                    171:         } else {
                    172:           fprintf (stderr, "Time must be numeric\n");
                    173:         }
                    174:       } else {
                    175:         fprintf (stderr, "Time missing\n");
                    176:       }
                    177:     } else {
                    178:       fprintf (stderr, "Delay must be numeric\n");
                    179:     }
                    180:   } else {
                    181:     return (TRUE);
                    182:   }
                    183:   return (FALSE);
                    184: }
                    185: 
                    186: static boolean command_init (int cargc,
                    187:     char **cargv)
                    188: {
                    189:   nextf = -1;
                    190:   quit = FALSE;
                    191:   combln = 0;
                    192:   dati = dato = 0;
                    193:   if (cargc > 1) {
                    194:     if (!strcmp (cargv[1],"--help")) {
                    195:       command_help (cargv[0]);
                    196:       return (FALSE);
                    197:     } else if (
                    198:       !command_do (cargv[1], cargc>2?cargv[2]:NULL, cargc>3?cargv[3]:NULL)) {
                    199:       command_help (cargv[0]);
                    200:       return (FALSE);
                    201:     }
                    202:   }
                    203:   cmdf = STDIN_FILENO;
                    204:   outf = STDOUT_FILENO;
                    205:   return ((cmdf >= 0) && (outf >= 0));
                    206: }
                    207: 
                    208: int main (int argc,
                    209:     char *argv[])
                    210: {
                    211:   int polli, pollo, polls;
                    212:   int toberead;
                    213:   int currentf;
                    214:   boolean dotime;
                    215:   t_msec rtime, ftime, rdelay, fdelay, now;
                    216:   struct pollfd ufds [3];
                    217:   if (command_init (argc,&argv[0])) {
                    218:     currentf = -1;
                    219:     rtime = ftime = msec_now ();
                    220:     while (!quit) {
                    221:       now = msec_now ();
                    222: D(fprintf(stderr,"now(%d)\n",now));
                    223:       if (currentf < 0) {
                    224:         toberead = 0;
                    225:         rdelay = nextrdelay;
                    226:         fdelay = nextfdelay;
                    227:         if ((ftime-now) < 0) {
                    228:           ftime = now;
                    229:         }
                    230:         rtime = ftime;
                    231:         currentf = nextf;
                    232:         nextf = -1;
                    233: D(fprintf(stderr,"next current(%d,%d,%d)\n",currentf,fdelay,rdelay));
                    234:       }
                    235:       if (currentf >= 0) {
                    236:         if ((rtime - now) <= 0) {
                    237:           if ((((dato-dati-1) & (MAX_ANOTATE-1)) - toberead) > TS_PACKET_SIZE) {
                    238:             toberead += TS_PACKET_SIZE;
                    239:             rtime += rdelay;
                    240:             dotime = TRUE;
                    241: D(fprintf(stderr,"timer a(%d,%d)\n",toberead,rtime));
                    242:           } else {
                    243:             rtime = now;
                    244:             dotime = FALSE;
                    245: D(fprintf(stderr,"timer b(%d,%d)\n",toberead,rtime));
                    246:           }
                    247:         } else {
                    248:           dotime = TRUE;
                    249: D(fprintf(stderr,"timer c(%d,%d)\n",toberead,rtime));
                    250:         }
                    251:       } else {
                    252:         dotime = FALSE;
                    253: D(fprintf(stderr,"timer c(%d,%d)\n",toberead,rtime));
                    254:       }
                    255:       ufds[0].fd = cmdf;
                    256:       ufds[0].events = POLLIN;
                    257:       if (dati != dato) {
                    258:         ufds[1].fd = outf;
                    259:         ufds[1].events = POLLOUT;
                    260:         pollo = 1;
                    261:       } else {
                    262:         pollo = 0;
                    263:       }
                    264:       polls = pollo+1;
                    265:       if (toberead > 0) {
                    266:         polli = polls++;
                    267:         ufds[polli].fd = currentf;
                    268:         ufds[polli].events = POLLIN;
                    269:       } else {
                    270:         polli = 0;
                    271:       }
                    272:       poll (&ufds[0], polls, dotime ? ((rtime-now) > 0) ? (rtime-now) : 0 : -1);
                    273:       if (ufds[0].revents & POLLIN) {
                    274:         char *s1, *s2, *s3;
                    275:         if (combln >= MAX_DATA_COMB-HIGHWATER_COM) {
                    276:           combln -= HIGHWATER_COM;
                    277:           memmove (&combuf[0], &combuf[HIGHWATER_COM], combln);
                    278:         }
                    279:         combln += read (cmdf, &combuf[combln], MAX_DATA_COMB-combln);
                    280:         while (line_complete (&s1, &s2, &s3)) {
                    281:           command_do (s1, s2, s3);
                    282:           combln -= comlln;
                    283:           memmove (&combuf[0], &combuf[comlln], combln);
                    284:         }
                    285:       }
                    286:       if ((polli != 0)
                    287:        && (ufds[polli].revents & (POLLIN | POLLHUP | POLLERR))) {
                    288:         int l;
                    289:         if (ufds[polli].revents & POLLIN) {
                    290:           l = toberead;
                    291:           if (l > (MAX_ANOTATE - dati)) {
                    292:             l = MAX_ANOTATE - dati;
                    293:           }
                    294:           l = read (currentf, &data[dati], l);
                    295:           dati = (dati+l) & (MAX_ANOTATE-1);
                    296:           toberead -= l;
                    297:         } else {
                    298:           l = 0;
                    299:         }
                    300:         if (l == 0) {
                    301:           if ((nextf >= 0)
                    302:            || (fdelay == 0)) {
                    303:             close (currentf);
                    304:             currentf = -1;
                    305:           } else {
                    306:             lseek (currentf,0,SEEK_SET);
                    307:             toberead = ((toberead-1) / TS_PACKET_SIZE) * TS_PACKET_SIZE;
                    308:           }
                    309:           ftime += fdelay;
                    310:           now = msec_now ();
                    311:           if ((ftime-now) < 0) {
                    312:             ftime = now;
                    313:           }
                    314:           rtime = ftime;
                    315:         }
                    316:       }
                    317:       if ((pollo != 0)
                    318:        && (ufds[1].revents & (POLLOUT | POLLHUP | POLLERR))) {
                    319:         if (ufds[1].revents & POLLOUT) {
                    320:           int l;
                    321:           if (dati < dato) {
                    322:             l = MAX_ANOTATE - dato;
                    323:           } else {
                    324:             l = dati - dato;
                    325:           }
                    326:           l = write (outf, &data[dato], l);
                    327:           dato = (dato+l) & (MAX_ANOTATE-1);
                    328:           if (l == 0) {
                    329:             quit = TRUE;
                    330:           }
                    331:         } else {
                    332:           quit = TRUE;
                    333:         }
                    334:       }
                    335:     }
                    336:     return (EXIT_SUCCESS);
                    337:   }
                    338:   return (EXIT_FAILURE);
                    339: }

LinuxTV legacy CVS <linuxtv.org/cvs>