Annotation of multiplexer/splice.c, revision 1.7
1.1 oskar 1: /*
2: * ISO 13818 stream multiplexer
3: * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
4: * Author: Oskar Schirmer (oskar@convergence.de)
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>