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