Annotation of multiplexer/splice.c, revision 1.8
1.1 oskar 1: /*
2: * ISO 13818 stream multiplexer
3: * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
1.8 ! oskar 4: * Author: Oskar Schirmer (oskar@scara.com)
1.1 oskar 5: */
6:
7: /*
8: * Module: Splice
9: * Purpose: Service functions for specific Splice* modules
10: *
11: * This module provides functions needed for splicing
12: * which are independent from the splice type.
13: */
14:
15: #include "global.h"
16: #include "error.h"
17: #include "splice.h"
18: #include "input.h"
19: #include "pes.h"
1.6 oskar 20: #include "descref.h"
1.1 oskar 21:
1.5 oskar 22: t_msec next_psi_periodic;
23: t_msec psi_frequency_msec;
24: boolean psi_frequency_changed;
25:
1.7 oskar 26: int configuration_on;
1.5 oskar 27: boolean configuration_changed;
1.7 oskar 28: boolean configuration_descr_changed;
1.5 oskar 29: const char *configuration_total = "Conf: progs: %d\n";
30:
1.7 oskar 31: static modifydescr_descr *globalmodifydescr;
32:
1.5 oskar 33: boolean splice_init (void)
34: {
35: psi_frequency_msec = 0;
36: psi_frequency_changed = FALSE;
1.7 oskar 37: configuration_on = 0;
38: globalmodifydescr = NULL;
1.5 oskar 39: return (splice_specific_init ());
40: }
41:
1.2 oskar 42: /* Connect a stream with a target program.
43: * programnb denotes the program to connect,
44: * stream is the stream to connect,
45: * all further parameters are as with input_openstream.
46: * If stream is NULL, open a stream first.
47: * Add the stream to the programs list of streams and vice versa.
48: * Precondition: f!=NULL
49: * Return: the changed stream on success, the unchanged "stream" otherwise
50: */
1.1 oskar 51: stream_descr *connect_streamprog (file_descr *f,
52: int programnb,
53: int sourceid,
54: int streamid,
55: int streamtype,
56: stream_descr *stream,
57: stream_descr *mapstream,
58: boolean mention)
59: {
60: stream_descr *s;
61: prog_descr *p;
62: if (stream == NULL) {
63: s = input_openstream (f,sourceid,streamid<0?-streamid:streamid,
1.3 oskar 64: streamtype,sd_data,mapstream);
1.1 oskar 65: } else {
66: if (streamid < 0) {
67: streamid = -streamid;
1.4 oskar 68: warn (LWAR,"Cannot refind sid",ESPC,1,1,streamid);
1.1 oskar 69: }
70: s = stream;
71: }
72: if (s != NULL) {
73: p = splice_openprog (programnb);
74: if (p != NULL) {
75: if (input_addprog (s,p)) {
76: if (splice_addstream (p,s,streamid>=0) > 0) {
77: /*
78: if (p->pcr_pid < 0) {
79: if (xxx) {
80: p->pcr_pid = s->u.d.pid;
81: s->u.d.has_clockref = TRUE;
82: s->u.d.next_clockref = msec_now () - MAX_MSEC_PCRDIST;
83: }
84: }
85: */
86: s->endaction = ENDSTR_WAIT;
87: s->u.d.mention = mention;
88: return (s);
89: }
90: input_delprog (s,p);
91: }
92: if (p->streams <= 0) {
93: splice_closeprog (p);
94: }
95: }
96: if (stream == NULL) {
97: input_closestream (s);
98: }
99: }
100: return (stream);
101: }
1.2 oskar 102:
103: /* Unlink a stream from a target program.
104: * If the stream comes out to be in no program then, close it.
105: * This function may be used only, if the program in question will either
106: * be non-empty after the call, or will be closed by the calling function.
107: * Precondition: s!=NULL, p!=NULL
108: */
1.1 oskar 109: void unlink_streamprog (stream_descr *s,
110: prog_descr *p)
111: {
112: splice_delstream (p,s);
113: input_delprog (s,p);
114: if (s->u.d.progs <= 0) {
115: file_descr *f;
116: f = s->fdescr;
117: input_closestream (s);
118: input_closefileifunused (f);
119: }
120: }
1.2 oskar 121:
122: /* Remove a stream from a target program.
123: * Close stream and/or program, if not contained in another program or stream.
1.5 oskar 124: * The input file is no longer automatic, because we do manual changes here.
1.2 oskar 125: * Precondition: s!=NULL, p!=NULL, s is stream in target program p
126: */
1.1 oskar 127: void remove_streamprog (stream_descr *s,
128: prog_descr *p)
129: {
1.5 oskar 130: s->fdescr->automatic = FALSE;
1.2 oskar 131: if (p->streams > 1) {
132: unlink_streamprog (s,p);
133: } else {
134: splice_closeprog (p);
1.1 oskar 135: }
136: }
137:
1.2 oskar 138: /* Find the right stream in a program
139: * Precondition: p!=NULL
140: * Return: stream, if found, NULL otherwise
141: */
1.1 oskar 142: stream_descr *get_streamprog (prog_descr *p,
143: int streamid)
144: {
145: int i;
146: i = p->streams;
147: while (--i >= 0) {
148: stream_descr *s;
149: s = p->stream[i];
150: if (s->stream_id == streamid) {
151: return (s);
152: }
153: }
154: return (NULL);
155: }
156:
1.2 oskar 157: /* Find a free stream ID in a program that is equivalent to the given stream id
158: * Precondition: p!=NULL
159: * Return: Free ID, if found; given sid otherwise.
160: */
1.1 oskar 161: int splice_findfreestreamid (prog_descr *p,
162: int sid)
163: {
1.2 oskar 164: int s0, s, n;
165: s0 = sid;
1.1 oskar 166: if ((sid >= PES_CODE_AUDIO)
167: && (sid < (PES_CODE_AUDIO+PES_NUMB_AUDIO))) {
168: s = PES_CODE_AUDIO;
1.2 oskar 169: n = PES_NUMB_AUDIO;
1.1 oskar 170: } else if ((sid >= PES_CODE_VIDEO)
171: && (sid < (PES_CODE_VIDEO+PES_NUMB_VIDEO))) {
172: s = PES_CODE_VIDEO;
1.2 oskar 173: n = PES_NUMB_VIDEO;
1.1 oskar 174: } else {
175: s = sid;
1.2 oskar 176: n = 1;
1.1 oskar 177: }
178: while (--n >= 0) {
179: int i;
180: i = p->streams;
181: while ((--i >= 0)
1.2 oskar 182: && (p->stream[i]->stream_id != s0)) {
1.1 oskar 183: }
184: if (i < 0) {
1.4 oskar 185: warn (LIMP,"Found SID free",ESPC,2,sid,s0);
1.2 oskar 186: return (s0);
1.1 oskar 187: }
1.2 oskar 188: s0 = s;
1.1 oskar 189: s += 1;
190: }
1.4 oskar 191: warn (LIMP,"Found SID",ESPC,2,sid,sid);
1.2 oskar 192: return (sid);
1.1 oskar 193: }
194:
1.2 oskar 195: /* Check if there is a source pcr stream in a target program
196: * Precondition: p!=NULL
197: * Return: pcr-stream, if found; NULL otherwise.
198: */
1.1 oskar 199: stream_descr *splice_findpcrstream (prog_descr *p)
200: {
201: int i;
202: pmt_descr *pmt;
1.4 oskar 203: warn (LIMP,"Find PCR Stream",ESPC,3,0,p->program_number);
1.1 oskar 204: i = p->streams;
205: while (--i >= 0) {
206: if (p->stream[i]->fdescr->content == ct_transport) {
207: pmt = p->stream[i]->fdescr->u.ts.pat;
208: while (pmt != NULL) {
209: if (pmt->pcr_pid == p->stream[i]->sourceid) {
1.4 oskar 210: warn (LIMP,"Found PCR Stream",ESPC,3,1,p->stream[i]->sourceid);
1.1 oskar 211: return (p->stream[i]);
212: }
213: pmt = pmt->next;
214: }
215: }
216: }
217: return (NULL);
1.5 oskar 218: }
219:
1.7 oskar 220: /* Print configuration of descriptors
221: * Precondition: manud!=NULL
222: */
223: static void splice_descr_configuration (descr_descr *manud,
224: descr_descr *autod)
225: {
226: int i, l;
227: byte *y;
228: i = NUMBER_DESCR;
229: while (--i >= 0) {
230: y = manud->refx[i];
231: if (y == NULL) {
232: if (autod != NULL) {
233: y = autod->refx[i];
234: }
235: } else if (y[1] == 0) {
236: y = NULL;
237: }
238: if (y != NULL) {
239: l = y[1];
240: fprintf (stderr, "Conf: descr:%02X len:%d data:", *y++, l);
241: while (--l >= 0) {
242: fprintf (stderr, "%02X", *++y);
243: }
244: fprintf (stderr, "\n");
245: }
246: }
247: }
248:
1.5 oskar 249: /* Print configuration for one program
250: * Precondition: p!=NULL
251: */
252: void splice_one_configuration (prog_descr *p)
253: {
1.6 oskar 254: int i, s;
255: stump_descr *st;
1.5 oskar 256: i = p->streams;
1.6 oskar 257: s = 0;
258: st = p->stump;
259: while (st != NULL) {
260: s += 1;
261: st = st->next;
262: }
263: fprintf (stderr, "Conf: prog:%04X pmt:%04hX pcr:%04hX streams:%2d",
264: p->program_number, p->pmt_pid, p->pcr_pid, i+s);
265: if (s > 0) {
266: fprintf (stderr, " (%d)", s);
267: }
268: fprintf (stderr, "\n");
1.7 oskar 269: if (configuration_on > 1) {
270: splice_descr_configuration (&p->manudescr, NULL); /* Missing auto descr! */
271: }
1.5 oskar 272: while (--i >= 0) {
273: stream_descr *s;
274: s = p->stream[i];
1.6 oskar 275: fprintf (stderr, "Conf: stream:%04hX type:%02X sid:%02X "
1.5 oskar 276: "file:%d source:%04hX num:%2d name:%s\n",
1.6 oskar 277: s->u.d.pid, s->stream_type, s->stream_id,
1.5 oskar 278: s->fdescr->content, s->sourceid, s->fdescr->filerefnum, s->fdescr->name);
1.7 oskar 279: if (configuration_on > 1) {
280: splice_descr_configuration (s->manudescr, s->autodescr);
281: }
1.6 oskar 282: }
283: st = p->stump;
284: while (st != NULL) {
285: fprintf (stderr, "Conf: stream:%04hX type:%02X\n",
286: st->pid, st->stream_type);
1.7 oskar 287: if (configuration_on > 1) {
288: splice_descr_configuration (&st->manudescr, NULL);
289: }
1.6 oskar 290: st = st->next;
1.5 oskar 291: }
292: }
293:
1.7 oskar 294: void splice_set_configuration (int on)
1.5 oskar 295: {
296: configuration_on = on;
297: configuration_changed = TRUE;
1.7 oskar 298: }
299:
300: static void splice_modifydescriptor (descr_descr *md,
301: int dtag,
302: int dlength,
303: byte *data,
304: stream_descr *s)
305: {
306: int i, j;
307: byte *t, *u;
308: if (dtag < 0) {
309: clear_descrdescr (md);
310: } else {
311: t = md->refx[dtag];
312: if ((dlength < 0)
313: || ((t != NULL)
314: && (t != &md->null[0]))) {
315: j = t[1]+2;
316: i = NUMBER_DESCR;
317: while (--i >= 0) {
318: if ((md->refx[i]-t) > 0) {
319: md->refx[i] -= j;
320: }
321: }
322: memmove (t,&t[j],sizeof(md->data)-(j+(t-&md->data[0])));
323: }
324: if (dlength == 0) {
325: t = &md->null[0];
326: } else if (dlength < 0) {
327: t = NULL;
328: } else {
329: i = NUMBER_DESCR;
330: t = &md->data[0];
331: while (--i >= 0) {
332: u = md->refx[i];
333: if (u != NULL) {
334: u = &u[u[1]+2];
335: if ((u-t) > 0) {
336: t = u;
337: }
338: }
339: }
340: if (t-&md->data[0] < 0) {
341: warn (LERR,"No space left",ESPC,5,2,t-&md->data[0]);
342: return;
343: }
344: if ((t-&md->data[0]+dlength+2-MAX_PSI_SIZE) > 0) {
345: warn (LWAR,"No space left",ESPC,5,1,t-&md->data[0]);
346: return;
347: }
348: t[0] = dtag;
349: t[1] = dlength;
350: memcpy (&t[2],data,dlength);
351: }
352: md->refx[dtag] = t;
353: }
354: if (s != NULL) {
355: i = s->u.d.progs;
356: while (--i >= 0) {
357: s->u.d.pdescr[i]->changed = TRUE;
358: }
359: }
360: }
361:
362: static void splice_modifydescrlater (int programnb,
363: short sid,
364: short pid,
365: int dtag,
366: int dlength,
367: byte *data)
368: {
369: modifydescr_descr *l;
370: modifydescr_descr **pl;
371: pl = &globalmodifydescr;
372: l = *pl;
373: while (l != NULL) {
374: if ((programnb < 0) /* delete older matching entries */
375: || ((programnb == l->programnb)
376: && ((pid == 0)
377: || ((pid == l->pid)
378: && (sid == l->sid)
379: && ((dtag < 0)
380: || (dtag == l->dtag)))))) {
381: *pl = l->next;
382: free (l);
383: } else {
384: pl = &l->next;
385: }
386: l = *pl;
387: }
388: if ((dtag >= 0)
389: && (dlength >= 0)) { /* don't save modifiers, that delete */
390: if ((l = malloc (sizeof(modifydescr_descr))) != NULL) {
391: l->next = NULL;
392: l->programnb = programnb;
393: l->sid = sid;
394: l->pid = pid;
395: l->dtag = dtag;
396: l->dlength = dlength;
397: if (dlength > 0) {
398: memcpy (&l->data[0],data,dlength);
399: }
400: *pl = l; /* append at end of list */
401: } else {
402: warn (LERR,"Malloc fail",ETSC,12,1,programnb);
403: }
404: }
405: }
406:
407: /* For a new program and maybe stream or stump,
408: * check presence of applicable descriptors, that have been stored.
409: * All non-NULL parameters must be completely linked into p upon call!
410: * Precondition: p != NULL
411: */
412: void splice_modifycheckmatch (int programnb,
413: prog_descr *p,
414: stream_descr *s,
415: stump_descr *st)
416: {
417: modifydescr_descr *l;
418: modifydescr_descr **pl;
419: pl = &globalmodifydescr;
420: l = *pl;
421: while (l != NULL) {
422: if ((programnb == l->programnb)
423: && (((l->sid < 0)
424: && (l->pid < 0))
425: || ((l->pid > 0)
426: && (((s != NULL)
427: && (l->pid == s->u.d.pid))
428: || ((st != NULL)
429: && (l->pid = st->pid))))
430: || ((l->sid >= 0)
431: && (s != NULL)
432: && (l->sid == s->stream_id)))) {
433: splice_modifytargetdescrprog (p,programnb,
434: l->sid,l->pid,l->dtag,l->dlength,&l->data[0],st);
435: *pl = l->next;
436: free (l);
437: } else {
438: pl = &l->next;
439: }
440: l = *pl;
441: }
442: }
443:
444: /* Modify an entry in a manudescr struct.
445: */
446: void splice_modifytargetdescrprog (prog_descr *p,
447: int programnb,
448: short sid,
449: short pid,
450: int dtag,
451: int dlength,
452: byte *data,
453: stump_descr *globstump)
454: {
455: int i;
456: stream_descr *s;
457: stump_descr *st;
458: if (sid >= 0) {
459: if (p != NULL) {
460: i = p->streams;
461: while (--i >= 0) {
462: s = p->stream[i];
463: if (s->stream_id == sid) {
464: splice_modifydescriptor (s->manudescr,dtag,dlength,data,s);
465: configuration_descr_changed = TRUE;
466: return;
467: }
468: }
469: }
470: splice_modifydescrlater (programnb,sid,pid,dtag,dlength,data);
471: } else {
472: if (pid > 0) {
473: if (p != NULL) {
474: i = p->streams;
475: while (--i >= 0) {
476: s = p->stream[i];
477: if (s->u.d.pid == pid) {
478: splice_modifydescriptor (s->manudescr,dtag,dlength,data,s);
479: configuration_descr_changed = TRUE;
480: return;
481: }
482: }
483: st = p->stump;
484: } else {
485: st = globstump;
486: }
487: while (st != NULL) {
488: if ((st->pid == pid)
489: && (st->program_number == programnb)) {
490: splice_modifydescriptor (&st->manudescr,dtag,dlength,data,NULL);
491: if (p != NULL) {
492: p->changed = TRUE;
493: }
494: configuration_descr_changed = TRUE;
495: return;
496: }
497: st = st->next;
498: }
499: splice_modifydescrlater (programnb,sid,pid,dtag,dlength,data);
500: } else if (pid < 0) {
501: if (p != NULL) {
502: splice_modifydescriptor (&p->manudescr,dtag,dlength,data,NULL);
503: p->changed = TRUE;
504: configuration_descr_changed = TRUE;
505: } else {
506: splice_modifydescrlater (programnb,sid,pid,dtag,dlength,data);
507: }
508: } else {
509: if (p != NULL) {
510: i = p->streams;
511: while (--i >= 0) {
512: s = p->stream[i];
513: splice_modifydescriptor (s->manudescr,dtag,dlength,data,s);
514: }
515: splice_modifydescriptor (&p->manudescr,dtag,dlength,data,NULL);
516: configuration_descr_changed = TRUE;
517: st = p->stump;
518: } else {
519: st = globstump;
520: }
521: while (st != NULL) {
522: if (st->program_number == programnb) {
523: splice_modifydescriptor (&st->manudescr,dtag,dlength,data,NULL);
524: }
525: st = st->next;
526: }
527: splice_modifydescrlater (programnb,sid,pid,dtag,dlength,data);
528: }
529: }
1.1 oskar 530: }
531:
LinuxTV legacy CVS <linuxtv.org/cvs>