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>