![]() ![]() | ![]() |
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: }