Return to repeatts.c CVS log | Up to [DVB] / multiplexer |
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: }