Annotation of multiplexer/repeatts.c, revision 1.4

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.4     ! jacob      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: 
1.4     ! jacob      38: t_msec
        !            39: msec_now (void)
1.1       oskar      40: {
                     41: #define MSEC_EXPONENT 21
                     42:   static long last;
                     43:   static int local_delta;
                     44:   struct timeval tv;
1.4     ! jacob      45:   gettimeofday (&tv, NULL);
        !            46:   if ((tv.tv_sec & (~((1L << MSEC_EXPONENT) - 1))) != last)
        !            47:     {
        !            48:       last = tv.tv_sec & (~((1L << MSEC_EXPONENT) - 1));
        !            49:       local_delta += 1000 * (1L << MSEC_EXPONENT);
        !            50:     }
1.1       oskar      51:   return ((tv.tv_sec & ((1L << MSEC_EXPONENT) - 1)) * 1000
1.4     ! jacob      52:           + tv.tv_usec / 1000 + local_delta);
1.1       oskar      53: }
                     54: 
1.4     ! jacob      55: static void
        !            56: command_help (char *command)
1.1       oskar      57: {
1.4     ! jacob      58:   fprintf (stderr, 
        !            59:     "Usage:\t%s [<delay> <time> <file>]\n"
        !            60:     "\tSend <file> repeated every <delay> msec evenly distributed within\n"
        !            61:     "\t<time> msec, Feed a (delay,time,file) tuple to stdin to reset\n"
        !            62:     "\tbehaviour, quit program with negative delay, don't repeat with delay=0.\n",
        !            63:            command);
1.1       oskar      64: }
                     65: 
1.4     ! jacob      66: static boolean
        !            67: line_complete (char **s1, char **s2, char **s3)
1.1       oskar      68: {
                     69:   int i;
1.4     ! jacob      70:   boolean b = FALSE;
1.1       oskar      71:   *s3 = NULL;
                     72:   *s2 = NULL;
                     73:   *s1 = NULL;
                     74:   i = 0;
1.4     ! jacob      75:   while (i < combln)
        !            76:     {
        !            77:       if (combuf[i] == '\n')
        !            78:         {
        !            79:           comlln = i;
        !            80:           while (i >= 0)
        !            81:             {
        !            82:               if (combuf[i] <= ' ')
        !            83:                 {
        !            84:                   combuf[i] = 0;
        !            85:                   b = TRUE;
        !            86:                 }
        !            87:               else
        !            88:                 {
        !            89:                   if (b)
        !            90:                     {
        !            91:                       *s3 = *s2;
        !            92:                       *s2 = *s1;
        !            93:                       b = FALSE;
        !            94:                     }
        !            95:                   *s1 = &combuf[i];
        !            96:                 }
        !            97:               i -= 1;
        !            98:             }
        !            99:           return (TRUE);
1.1       oskar     100:         }
1.4     ! jacob     101:       i += 1;
1.1       oskar     102:     }
                    103:   return (FALSE);
                    104: }
                    105: 
1.4     ! jacob     106: static boolean
        !           107: is_long (char *s, long *r)
1.1       oskar     108: {
                    109:   long i;
                    110:   char *e;
1.4     ! jacob     111:   if (s == NULL)
        !           112:     {
        !           113:       return (FALSE);
        !           114:     }
1.1       oskar     115:   errno = 0;
1.4     ! jacob     116:   i = strtol (s, &e, 0);
        !           117:   if ((errno != 0) || (*e != 0))
        !           118:     {
        !           119:       return (FALSE);
        !           120:     }
1.1       oskar     121:   *r = i;
                    122:   return (TRUE);
                    123: }
                    124: 
1.4     ! jacob     125: static boolean
        !           126: command_do (char *arg1, char *arg2, char *arg3)
1.1       oskar     127: {
                    128:   long l1, l2;
                    129:   struct stat stat;
1.4     ! jacob     130: D (fprintf (stderr, "command_do(%s,%s,%s)\n", arg1, arg2, arg3));
        !           131:   if (arg1 != NULL)
        !           132:     {
        !           133:       if (is_long (arg1, &l1))
        !           134:         {
        !           135:           if (l1 < 0)
        !           136:             {
        !           137:               quit = TRUE;
        !           138:               return (TRUE);
        !           139:             }
        !           140:           if (arg2 != NULL)
        !           141:             {
        !           142:               if (is_long (arg2, &l2))
        !           143:                 {
        !           144:                   if (l2 >= 0)
        !           145:                     {
        !           146:                       if ((l1 >= l2) || (l1 == 0))
        !           147:                         {
        !           148:                           if (arg3 != NULL)
        !           149:                             {
        !           150:                               if (nextf >= 0)
        !           151:                                 {
        !           152:                                   close (nextf);
        !           153:                                 }
        !           154:                               if ((nextf = open (arg3, O_RDONLY)) >= 0)
        !           155:                                 {
        !           156:                                   if (fstat (nextf, &stat) == 0)
        !           157:                                     {
        !           158: D (fprintf (stderr, "file %d, mode %07o, name %s, ino %ld, size %ld\n",
        !           159:             nextf, stat.st_mode, arg3, stat.st_ino, stat.st_size));
        !           160:                                       if (S_ISREG (stat.st_mode))
        !           161:                                         {
        !           162:                                           if ((stat.st_size %
        !           163:                                                TS_PACKET_SIZE) == 0)
        !           164:                                             {
        !           165:                                               if (stat.st_size > 0)
        !           166:                                                 {
        !           167:                                                   nextrdelay =
        !           168:                                                     l2 / (stat.st_size /
        !           169:                                                           TS_PACKET_SIZE);
        !           170:                                                 }
        !           171:                                               else
        !           172:                                                 {
        !           173:                                                   nextrdelay = 0;
        !           174:                                                 }
        !           175:                                               nextfdelay = l1;
        !           176: D (fprintf (stderr, "next opened(%d,%d)\n", nextfdelay, nextrdelay));
        !           177:                                               return (TRUE);
        !           178:                                             }
        !           179:                                           else
        !           180:                                             {
        !           181:                                               fprintf (stderr,
        !           182:                                                 "File size not multiple of 188\n");
        !           183:                                             }
        !           184:                                         }
        !           185:                                       else
        !           186:                                         {
        !           187:                                           fprintf (stderr,
        !           188:                                                    "File not regular\n");
        !           189:                                         }
        !           190:                                     }
        !           191:                                   else
        !           192:                                     {
        !           193:                                       fprintf (stderr, "Cannot stat file\n");
        !           194:                                     }
        !           195:                                   close (nextf);
        !           196:                                   nextf = -1;
        !           197:                                 }
        !           198:                               else
        !           199:                                 {
        !           200:                                   fprintf (stderr, "Cannot open file\n");
        !           201:                                 }
        !           202:                             }
        !           203:                           else
        !           204:                             {
        !           205:                               fprintf (stderr, "File name missing\n");
        !           206:                             }
        !           207:                         }
        !           208:                       else
        !           209:                         {
        !           210:                           fprintf (stderr, "0<delay<time not allowed\n");
1.3       oskar     211:                         }
1.4     ! jacob     212:                     }
        !           213:                   else
        !           214:                     {
        !           215:                       fprintf (stderr, "Time must not be negative\n");
        !           216:                     }
        !           217:                 }
        !           218:               else
        !           219:                 {
        !           220:                   fprintf (stderr, "Time must be numeric\n");
        !           221:                 }
        !           222:             }
        !           223:           else
        !           224:             {
        !           225:               fprintf (stderr, "Time missing\n");
        !           226:             }
        !           227:         }
        !           228:       else
        !           229:         {
        !           230:           fprintf (stderr, "Delay must be numeric\n");
1.1       oskar     231:         }
                    232:     }
1.4     ! jacob     233:   else
        !           234:     {
        !           235:       return (TRUE);
        !           236:     }
1.1       oskar     237:   return (FALSE);
                    238: }
                    239: 
1.4     ! jacob     240: static boolean
        !           241: command_init (int cargc, char **cargv)
1.1       oskar     242: {
                    243:   nextf = -1;
                    244:   quit = FALSE;
                    245:   combln = 0;
                    246:   dati = dato = 0;
1.4     ! jacob     247:   if (cargc > 1)
        !           248:     {
        !           249:       if (!strcmp (cargv[1], "--help"))
        !           250:         {
        !           251:           command_help (cargv[0]);
        !           252:           return (FALSE);
        !           253:         }
        !           254:       else
        !           255:         if (!command_do
        !           256:             (cargv[1], cargc > 2 ? cargv[2] : NULL,
        !           257:              cargc > 3 ? cargv[3] : NULL))
        !           258:         {
        !           259:           command_help (cargv[0]);
        !           260:           return (FALSE);
        !           261:         }
1.1       oskar     262:     }
                    263:   cmdf = STDIN_FILENO;
                    264:   outf = STDOUT_FILENO;
                    265:   return ((cmdf >= 0) && (outf >= 0));
                    266: }
                    267: 
1.4     ! jacob     268: int
        !           269: main (int argc, char *argv[])
1.1       oskar     270: {
                    271:   int polli, pollo, polls;
1.4     ! jacob     272:   int toberead = 0;   /* to make gcc happy */
1.1       oskar     273:   int currentf;
                    274:   boolean dotime;
1.4     ! jacob     275:   t_msec rtime;
        !           276:   t_msec ftime;
        !           277:   t_msec rdelay = 0;  /* to make gcc happy */
        !           278:   t_msec fdelay = 0;  /* to make gcc happy */
        !           279:   t_msec now;
        !           280:   struct pollfd ufds[3];
        !           281:   if (command_init (argc, &argv[0]))
        !           282:     {
        !           283:       currentf = -1;
        !           284:       rtime = ftime = msec_now ();
        !           285:       while (!quit)
        !           286:         {
1.1       oskar     287:           now = msec_now ();
1.4     ! jacob     288:           D (fprintf (stderr, "now(%d)\n", now));
        !           289:           if (currentf < 0)
        !           290:             {
        !           291:               toberead = 0;
        !           292:               rdelay = nextrdelay;
        !           293:               fdelay = nextfdelay;
        !           294:               if ((ftime - now) < 0)
        !           295:                 {
        !           296:                   ftime = now;
        !           297:                 }
        !           298:               rtime = ftime;
        !           299:               currentf = nextf;
        !           300:               nextf = -1;
        !           301:               D (fprintf (stderr, "next current(%d,%d,%d)\n", currentf, fdelay, rdelay));
        !           302:             }
        !           303:           if (currentf >= 0)
        !           304:             {
        !           305:               if ((rtime - now) <= 0)
        !           306:                 {
        !           307:                   if ((((dato - dati - 1) & (MAX_ANOTATE - 1)) - toberead) >
        !           308:                       TS_PACKET_SIZE)
        !           309:                     {
        !           310:                       toberead += TS_PACKET_SIZE;
        !           311:                       rtime += rdelay;
        !           312:                       dotime = TRUE;
        !           313:                       D (fprintf (stderr, "timer a(%d,%d)\n", toberead, rtime));
        !           314:                     }
        !           315:                   else
        !           316:                     {
        !           317:                       rtime = now;
        !           318:                       dotime = FALSE;
        !           319:                       D (fprintf (stderr, "timer b(%d,%d)\n", toberead, rtime));
        !           320:                     }
        !           321:                 }
        !           322:               else
        !           323:                 {
        !           324:                   dotime = TRUE;
        !           325:                   D (fprintf (stderr, "timer c(%d,%d)\n", toberead, rtime));
        !           326:                 }
        !           327:             }
        !           328:           else
        !           329:             {
        !           330:               dotime = FALSE;
        !           331:               D (fprintf (stderr, "timer c(%d,%d)\n", toberead, rtime));
        !           332:             }
        !           333:           ufds[0].fd = cmdf;
        !           334:           ufds[0].events = POLLIN;
        !           335:           if (dati != dato)
        !           336:             {
        !           337:               ufds[1].fd = outf;
        !           338:               ufds[1].events = POLLOUT;
        !           339:               pollo = 1;
        !           340:             }
        !           341:           else
        !           342:             {
        !           343:               pollo = 0;
        !           344:             }
        !           345:           polls = pollo + 1;
        !           346:           if (toberead > 0)
        !           347:             {
        !           348:               polli = polls++;
        !           349:               ufds[polli].fd = currentf;
        !           350:               ufds[polli].events = POLLIN;
        !           351:             }
        !           352:           else
        !           353:             {
        !           354:               polli = 0;
        !           355:             }
        !           356:           poll (&ufds[0], polls,
        !           357:                 dotime ? ((rtime - now) > 0) ? (rtime - now) : 0 : -1);
        !           358:           if (ufds[0].revents & POLLIN)
        !           359:             {
        !           360:               char *s1, *s2, *s3;
        !           361:               if (combln >= MAX_DATA_COMB - HIGHWATER_COM)
        !           362:                 {
        !           363:                   combln -= HIGHWATER_COM;
        !           364:                   memmove (&combuf[0], &combuf[HIGHWATER_COM], combln);
        !           365:                 }
        !           366:               combln += read (cmdf, &combuf[combln], MAX_DATA_COMB - combln);
        !           367:               while (line_complete (&s1, &s2, &s3))
        !           368:                 {
        !           369:                   command_do (s1, s2, s3);
        !           370:                   combln -= comlln;
        !           371:                   memmove (&combuf[0], &combuf[comlln], combln);
        !           372:                 }
        !           373:             }
        !           374:           if ((polli != 0)
        !           375:               && (ufds[polli].revents & (POLLIN | POLLHUP | POLLERR)))
        !           376:             {
        !           377:               int l;
        !           378:               if (ufds[polli].revents & POLLIN)
        !           379:                 {
        !           380:                   l = toberead;
        !           381:                   if (l > (MAX_ANOTATE - dati))
        !           382:                     {
        !           383:                       l = MAX_ANOTATE - dati;
        !           384:                     }
        !           385:                   l = read (currentf, &data[dati], l);
        !           386:                   dati = (dati + l) & (MAX_ANOTATE - 1);
        !           387:                   toberead -= l;
        !           388:                 }
        !           389:               else
        !           390:                 {
        !           391:                   l = 0;
        !           392:                 }
        !           393:               if (l == 0)
        !           394:                 {
        !           395:                   if ((nextf >= 0) || (fdelay == 0))
        !           396:                     {
        !           397:                       close (currentf);
        !           398:                       currentf = -1;
        !           399:                     }
        !           400:                   else
        !           401:                     {
        !           402:                       lseek (currentf, 0, SEEK_SET);
        !           403:                       toberead =
        !           404:                         ((toberead - 1) / TS_PACKET_SIZE) * TS_PACKET_SIZE;
        !           405:                     }
        !           406:                   ftime += fdelay;
        !           407:                   now = msec_now ();
        !           408:                   if ((ftime - now) < 0)
        !           409:                     {
        !           410:                       ftime = now;
        !           411:                     }
        !           412:                   rtime = ftime;
        !           413:                 }
        !           414:             }
        !           415:           if ((pollo != 0)
        !           416:               && (ufds[1].revents & (POLLOUT | POLLHUP | POLLERR)))
        !           417:             {
        !           418:               if (ufds[1].revents & POLLOUT)
        !           419:                 {
        !           420:                   int l;
        !           421:                   if (dati < dato)
        !           422:                     {
        !           423:                       l = MAX_ANOTATE - dato;
        !           424:                     }
        !           425:                   else
        !           426:                     {
        !           427:                       l = dati - dato;
        !           428:                     }
        !           429:                   l = write (outf, &data[dato], l);
        !           430:                   dato = (dato + l) & (MAX_ANOTATE - 1);
        !           431:                   if (l == 0)
        !           432:                     {
        !           433:                       quit = TRUE;
        !           434:                     }
        !           435:                 }
        !           436:               else
        !           437:                 {
        !           438:                   quit = TRUE;
        !           439:                 }
        !           440:             }
1.1       oskar     441:         }
1.4     ! jacob     442:       return (EXIT_SUCCESS);
1.1       oskar     443:     }
                    444:   return (EXIT_FAILURE);
                    445: }

LinuxTV legacy CVS <linuxtv.org/cvs>