Annotation of multiplexer/repeatts.c, revision 1.6

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

LinuxTV legacy CVS <linuxtv.org/cvs>