Annotation of multiplexer/splicets.c, revision 1.24
1.1 oskar 1: /*
2: * ISO 13818 stream multiplexer
3: * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
1.24 ! oskar 4: * Copyright (C) 2004..2005 Oskar Schirmer (schirmer@scara.com)
1.19 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 TS
23: * Purpose: Generate transport stream.
24: *
25: * This module generates from the available input stream data (as
26: * seperated by the split functions) the complete output stream.
27: * It provides functions to handle programs for the resulting stream,
28: * as these are output format dependent. Further, it accepts PSI data
29: * just in time, validating it not earlier than with the arrival of
30: * the corresponding payload at this stage.
31: */
32:
33: #include "global.h"
1.23 oskar 34: #include "crc32.h"
1.1 oskar 35: #include "error.h"
36: #include "input.h"
37: #include "output.h"
38: #include "descref.h"
1.6 oskar 39: #include "splitts.h"
1.1 oskar 40: #include "pes.h"
41: #include "ts.h"
42: #include "splice.h"
43: #include "splicets.h"
44:
45: const boolean splice_multipleprograms = TRUE;
46:
47: static boolean changed_pat;
1.16 oskar 48: static boolean unchanged_pat;
1.1 oskar 49: static int pat_section;
50: static const int last_patsection = 0;
51: static byte nextpat_version;
52: static byte pat_conticnt;
53:
54: static int transportstreamid;
55:
56: static int psi_size;
57: static int psi_done;
58: static byte psi_data [MAX_PSI_SIZE];
59:
60: static byte unit_start;
61: static byte *conticnt;
62: static int psi_pid;
1.24 ! oskar 63: static short network_pid = 0;
1.1 oskar 64:
65: static int progs;
66: static prog_descr *prog [MAX_OUTPROG];
67:
68: static int nextpid;
69: static stream_descr *outs [MAX_STRPERTS];
70:
1.13 oskar 71: static stump_descr *globalstumps;
72:
1.9 oskar 73: boolean splice_specific_init (void)
1.1 oskar 74: {
75: progs = 0;
76: nextpid = 0;
77: memset (outs,0,sizeof(outs));
78: changed_pat = TRUE;
79: pat_section = 0;
80: nextpat_version = 0;
81: pat_conticnt = 0;
82: psi_size = psi_done = 0;
83: unit_start = TS_UNIT_START;
84: transportstreamid = 0x4227;
1.13 oskar 85: globalstumps = NULL;
1.1 oskar 86: return (TRUE);
87: }
88:
89: void splice_settransportstreamid (int tsid)
90: {
91: transportstreamid = tsid;
92: }
93:
1.11 oskar 94: void splice_setpsifrequency (t_msec freq)
1.1 oskar 95: {
96: psi_frequency_msec = freq;
97: psi_frequency_changed = TRUE;
98: }
99:
1.24 ! oskar 100: void splice_setnetworkpid (short pid)
! 101: {
! 102: if ((pid < 0) || (pid > TS_PID_HIGHEST)) {
! 103: network_pid = 0;
! 104: } else {
! 105: network_pid = pid;
! 106: }
! 107: }
! 108:
1.21 oskar 109: static int findapid (stream_descr *s, int desire)
1.1 oskar 110: {
1.13 oskar 111: byte okness = 2;
112: int h;
1.21 oskar 113: if (conservative_pid_assignment
114: && (desire >= 0)
115: && (outs[desire] == NULL)
116: && (input_tssiinafilerange (desire) < 0)) {
117: return (desire);
118: }
1.1 oskar 119: do {
1.2 oskar 120: if ((nextpid < TS_PID_SPLICELO) || (nextpid >= TS_PID_SPLICEHI)) {
1.13 oskar 121: warn (LDEB,"Next PID",ETSC,1,okness,nextpid);
122: if (okness == 0) {
1.1 oskar 123: warn (LERR,"No PID found",ETSC,2,1,0);
124: return (0);
125: }
1.13 oskar 126: okness -= 1;
1.2 oskar 127: nextpid = TS_PID_SPLICELO;
1.1 oskar 128: } else {
1.13 oskar 129: warn (LDEB,"Next PID",ETSC,2,okness,nextpid);
1.1 oskar 130: nextpid += 1;
131: }
1.13 oskar 132: if (okness != 0) {
133: h = input_tssiinafilerange (nextpid);
134: warn (LDEB,"Next PID",ETSC,3,h,nextpid);
135: if (h >= 0) {
136: nextpid = h;
137: }
138: } else {
139: h = -1;
140: }
141: } while ((h >= 0)
142: || (outs[nextpid] != NULL));
1.1 oskar 143: outs[nextpid] = s;
144: warn (LDEB,"Next PID",ETSC,2,2,nextpid);
145: return (nextpid);
146: }
147:
1.9 oskar 148: void splice_all_configuration (void)
149: {
150: int i;
1.15 oskar 151: if (configuration_must_print) {
1.9 oskar 152: i = progs;
153: fprintf (stderr, configuration_total, i);
154: while (--i >= 0) {
155: splice_one_configuration (prog[i]);
156: }
1.15 oskar 157: configuration_was_printed;
1.9 oskar 158: }
159: }
160:
1.13 oskar 161: void splice_addsirange (file_descr *f,
162: int lower,
163: int upper)
164: {
165: int i, r;
166: tssi_descr *tssi;
167: prog_descr *p;
168: tssi = malloc (sizeof (tssi_descr));
169: if (tssi != NULL) {
170: if (ts_file_stream (f,TS_UNPARSED_SI) == NULL) {
171: ts_file_stream (f,TS_UNPARSED_SI) = input_openstream (f,
172: TS_UNPARSED_SI,0,0,sd_unparsedsi,NULL);
173: }
174: if (ts_file_stream (f,TS_UNPARSED_SI) != NULL) {
175: tssi->next = f->u.ts.tssi;
176: tssi->pid_low = lower;
177: tssi->pid_high = upper;
178: f->u.ts.tssi = tssi;
179: r = upper; /* check for collision against existing PIDs, first sd_data */
180: while (r >= lower) {
181: stream_descr *s;
182: s = outs[r];
183: if ((s != NULL)
184: && (s != PMT_STREAM)) {
185: if (s->streamdata == sd_data) {
1.21 oskar 186: i = findapid (s, -1);
1.13 oskar 187: if (input_tssiinafilerange (i) >= 0) { /* none free! */
188: outs[i] = NULL;
189: } else {
190: int j;
191: s->u.d.pid = i;
192: j = s->u.d.progs;
193: while (--j >= 0) {
194: p = s->u.d.pdescr[j];
195: p->changed = TRUE;
196: if (p->pcr_pid == r) {
197: p->pcr_pid = i;
198: }
199: }
200: configuration_changed = TRUE;
201: outs[r] = NULL;
202: }
203: } else {
204: warn (LERR,"Bad PID",ETSC,11,s->streamdata,r);
205: }
206: }
207: r -= 1;
208: }
209: i = progs; /* ...then sd_map */
210: while (--i >= 0) {
211: p = prog[i];
212: r = p->pmt_pid;
213: if ((r >= lower)
214: && (r <= upper)) {
215: int q;
1.21 oskar 216: q = findapid (PMT_STREAM, -1);
1.13 oskar 217: if (input_tssiinafilerange (q) >= 0) { /* none free! */
218: outs[q] = NULL;
219: } else {
220: int j;
221: outs[r] = NULL;
222: j = i;
223: while (--j >= 0) {
224: if (prog[j]->pmt_pid == r) {
225: prog[j]->pmt_pid = q;
226: }
227: }
228: p->pmt_pid = q;
229: changed_pat = TRUE;
230: configuration_changed = TRUE;
231: }
232: }
233: }
234: } else {
235: free (tssi);
236: }
237: }
238: }
239:
240: void splice_createstump (int programnb,
241: short pid,
242: byte styp)
243: {
244: prog_descr *p;
245: stump_descr **pst;
246: stump_descr *st;
247: p = splice_getprog (programnb);
248: if (p != NULL) {
249: configuration_changed = TRUE;
250: p->changed = TRUE;
251: pst = &(p->stump);
252: } else {
253: pst = &globalstumps;
254: }
255: st = *pst;
256: while ((st != NULL)
257: && ((st->pid != pid)
258: || (st->program_number != programnb))) {
259: st = st->next;
260: }
261: if (st == NULL) {
262: st = malloc (sizeof(stump_descr));
263: st->next = *pst;
264: st->program_number = programnb;
265: st->pid = pid;
266: *pst = st;
267: }
268: st->stream_type = styp;
269: clear_descrdescr (&(st->manudescr));
1.15 oskar 270: splice_modifycheckmatch (programnb,p,NULL,st);
1.13 oskar 271: }
272:
273: stump_descr *splice_getstumps (int programnb,
274: short pid)
275: {
276: prog_descr *p;
277: stump_descr **pst;
278: stump_descr *rl;
279: rl = NULL;
280: p = splice_getprog (programnb);
281: if (p != NULL) {
282: pst = &(p->stump);
283: } else {
284: pst = &globalstumps;
285: }
286: while (*pst != NULL) {
287: stump_descr *st;
288: st = *pst;
289: if ((st->program_number == programnb)
290: && ((pid < 0)
291: || (pid == st->pid))) {
292: st = *pst;
293: *pst = st->next;
294: st->next = rl;
295: rl = st;
296: if (p != NULL) {
297: configuration_changed = TRUE;
298: p->changed = TRUE;
299: }
300: } else {
301: pst = &((*pst)->next);
302: }
303: }
304: return (rl);
305: }
306:
1.15 oskar 307: void splice_modifytargetdescriptor (int programnb,
308: short sid,
309: short pid,
310: int dtag,
311: int dlength,
312: byte *data)
313: {
314: int i;
315: if (programnb < 0) {
316: i = progs;
317: while (--i >= 0) {
318: splice_modifytargetdescrprog (prog[i],
319: prog[i]->program_number,-1,0,-1,-1,NULL,globalstumps);
320: }
321: splice_modifytargetdescrprog (NULL,-1,-1,0,-1,-1,NULL,globalstumps);
322: } else {
323: splice_modifytargetdescrprog (splice_getprog (programnb),
324: programnb,sid,pid,dtag,dlength,data,globalstumps);
325: }
326: }
327:
1.3 oskar 328: prog_descr *splice_getprog (int programnb)
329: {
330: int i;
331: i = progs;
332: while (--i >= 0) {
333: if (prog[i]->program_number == programnb) {
334: return (prog[i]);
335: }
336: }
337: return (NULL);
338: }
339:
1.1 oskar 340: prog_descr *splice_openprog (int programnb)
341: {
342: prog_descr *p;
343: int pid;
344: warn (LIMP,"Open prog",ETSC,1,0,programnb);
1.3 oskar 345: p = splice_getprog (programnb);
1.1 oskar 346: if (p == NULL) {
347: if (progs < MAX_OUTPROG) {
1.21 oskar 348: if ((pid = findapid (PMT_STREAM, -1)) > 0) {
1.1 oskar 349: if ((p = malloc(sizeof(prog_descr))) != NULL) {
350: p->program_number = programnb;
351: p->pcr_pid = -1;
352: p->pmt_pid = pid;
353: p->pmt_conticnt = 0;
354: p->pmt_version = 0;
355: p->changed = TRUE;
356: p->pat_section = 0; /* more ? */
357: p->streams = 0;
1.13 oskar 358: p->stump = splice_getstumps (programnb,-1);
1.15 oskar 359: clear_descrdescr (&p->manudescr);
1.1 oskar 360: prog[progs++] = p;
361: changed_pat = TRUE;
1.9 oskar 362: configuration_changed = TRUE;
1.15 oskar 363: splice_modifycheckmatch (programnb,p,NULL,NULL);
1.1 oskar 364: } else {
365: outs[pid] = NULL;
366: warn (LERR,"Open prog",ETSC,1,1,0);
367: }
368: }
369: } else {
370: warn (LERR,"Max prog open",ETSC,1,2,0);
371: }
372: }
373: return (p);
374: }
375:
376: void splice_closeprog (prog_descr *p)
377: {
378: int i, n;
379: warn (LIMP,"Close prog",ETSC,3,0,p->program_number);
1.9 oskar 380: configuration_changed = TRUE;
1.1 oskar 381: while (p->streams > 0) {
1.3 oskar 382: unlink_streamprog (p->stream[0],p);
1.1 oskar 383: }
1.13 oskar 384: releasechain (stump_descr,p->stump);
1.1 oskar 385: n = -1;
386: if (p->pmt_pid >= 0) {
387: i = progs;
388: while (--i >= 0) {
389: if (prog[i]->pmt_pid == p->pmt_pid) {
390: n += 1;
391: }
392: }
393: }
394: i = progs;
395: while (--i >= 0) {
396: if (prog[i] == p) {
397: prog[i] = prog[--progs];
398: if (n == 0) {
399: outs[p->pmt_pid] = NULL;
400: }
401: free (p);
402: changed_pat = TRUE;
403: return;
404: }
405: }
406: warn (LERR,"Close lost prog",ETSC,3,1,progs);
407: }
408:
409: int splice_addstream (prog_descr *p,
410: stream_descr *s,
411: boolean force_sid)
412: {
413: int pid = 0;
414: warn (LIMP,"Add stream",ETSC,4,force_sid,s->stream_id);
415: if (p->streams < MAX_STRPERPRG) {
1.21 oskar 416: pid = findapid (s,(s->fdescr->content == ct_transport) ? s->sourceid : -1);
1.20 jens 417: if (pid > 0) {
1.1 oskar 418: if (!force_sid) {
1.3 oskar 419: s->stream_id = splice_findfreestreamid (p,s->stream_id);
1.1 oskar 420: }
421: p->stream[p->streams++] = s;
422: p->changed = TRUE;
423: s->u.d.pid = pid;
1.9 oskar 424: configuration_changed = TRUE;
1.15 oskar 425: splice_modifycheckmatch (p->program_number,p,s,NULL);
1.1 oskar 426: }
427: }
428: return (pid);
429: }
430:
431: boolean splice_delstream (prog_descr *p,
432: stream_descr *s)
433: {
434: int i;
435: warn (LIMP,"Del stream",ETSC,5,0,s->u.d.pid);
1.9 oskar 436: configuration_changed = TRUE;
1.1 oskar 437: i = p->streams;
438: while (--i >= 0) {
439: if (p->stream[i] == s) {
440: outs[s->u.d.pid] = NULL;
441: p->stream[i] = p->stream[--(p->streams)];
442: p->changed = TRUE;
443: if (p->pcr_pid == s->u.d.pid) {
444: p->pcr_pid = -1;
445: }
446: s->u.d.pid = 0;
447: return (TRUE);
448: }
449: }
450: warn (LERR,"Del lost stream",ETSC,5,1,p->streams);
451: return (FALSE);
452: }
453:
1.7 oskar 454: void process_finish (void)
455: {
456: warn (LIMP,"Finish",ETSC,6,0,0);
457: }
458:
1.1 oskar 459: static int make_patsection (int section,
460: byte *dest)
461: {
462: int i;
463: byte *d;
1.17 oskar 464: prog_descr *p;
1.1 oskar 465: d = dest;
466: *d++ = TS_TABLEID_PAT;
467: d += 2;
468: *d++ = transportstreamid >> 8;
469: *d++ = (byte)transportstreamid;
470: *d++ = 0xC0 | 0x01 | (nextpat_version << 1);
471: *d++ = section;
472: *d++ = last_patsection;
473: i = progs;
474: while (--i >= 0) {
1.17 oskar 475: p = prog[i];
476: if (p->pat_section == section) {
1.1 oskar 477: int x;
1.17 oskar 478: x = p->program_number;
1.1 oskar 479: *d++ = (x >> 8);
480: *d++ = x;
1.17 oskar 481: x = p->pmt_pid;
1.1 oskar 482: *d++ = 0xE0 | (x >> 8);
483: *d++ = x;
484: }
485: }
1.24 ! oskar 486: if (network_pid > 0) {
! 487: *d++ = 0;
! 488: *d++ = 0;
! 489: *d++ = 0xE0 | (network_pid >> 8);
! 490: *d++ = network_pid;
! 491: }
1.1 oskar 492: i = d + CRC_SIZE - dest - TS_TRANSPORTID;
493: dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
494: dest[TS_SECTIONLEN+1] = i;
495: crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
496: return (i + TS_TRANSPORTID);
497: }
498:
499: static int make_pmtsection (stream_descr *s,
500: prog_descr *p,
501: byte *dest)
502: {
503: int i;
504: byte *d;
1.13 oskar 505: stump_descr *st;
1.17 oskar 506: stream_descr *t;
1.1 oskar 507: d = dest;
508: *d++ = TS_TABLEID_PMT;
509: d += 2;
510: i = p->program_number;
511: *d++ = (i >> 8);
512: *d++ = i;
513: *d++ = 0xC0 | 0x01 | (p->pmt_version << 1);
514: *d++ = 0;
515: *d++ = 0;
516: if (p->pcr_pid < 0) {
517: stream_descr *pcrs;
1.3 oskar 518: pcrs = splice_findpcrstream (p);
1.1 oskar 519: if (pcrs == NULL) {
520: pcrs = s;
521: }
522: pcrs->u.d.has_clockref = TRUE;
523: pcrs->u.d.next_clockref = msec_now () - MAX_MSEC_PCRDIST;
524: p->pcr_pid = pcrs->u.d.pid;
1.9 oskar 525: configuration_changed = TRUE;
1.1 oskar 526: }
527: i = p->pcr_pid;
528: *d++ = 0xE0 | (i >> 8);
529: *d++ = i;
530: d += 2;
1.15 oskar 531: i = NUMBER_DESCR;
1.17 oskar 532: while (--i >= 0) {
1.15 oskar 533: byte *y;
534: y = p->manudescr.refx[i];
535: if ((y == NULL)
536: && (s->u.d.mapstream != NULL)) {
537: y = s->u.d.mapstream->autodescr->refx[i]; /* why this one? */
538: }
539: if (y != NULL) {
540: int yl = y[1];
541: if (yl != 0) {
542: yl += 2;
543: memcpy (d,y,yl);
544: d += yl;
1.1 oskar 545: }
546: }
547: }
548: i = d - dest - (TS_PMT_PILEN+2);
549: dest[TS_PMT_PILEN] = 0xF0 | (i >> 8);
550: dest[TS_PMT_PILEN+1] = i;
551: i = p->streams;
552: while (--i >= 0) {
1.17 oskar 553: t = p->stream[i];
554: if (t->u.d.mention) {
1.1 oskar 555: int x;
556: byte *e;
1.17 oskar 557: *d++ = t->stream_type;
558: x = t->u.d.pid;
1.1 oskar 559: *d++ = 0xE0 | (x >> 8);
560: *d++ = x;
561: d += 2;
562: e = d;
1.14 oskar 563: x = NUMBER_DESCR;
1.17 oskar 564: while (--x >= 0) {
1.1 oskar 565: byte *y;
1.17 oskar 566: y = t->manudescr->refx[x];
1.13 oskar 567: if (y == NULL) {
1.17 oskar 568: y = t->autodescr->refx[x];
1.13 oskar 569: }
1.1 oskar 570: if (y != NULL) {
1.15 oskar 571: int yl = y[1];
572: if (yl != 0) {
573: yl += 2;
574: memcpy (d,y,yl);
575: d += yl;
576: }
1.1 oskar 577: }
578: }
579: x = d - e;
580: *--e = x;
581: *--e = 0xF0 | (x >> 8);
582: }
1.13 oskar 583: }
584: st = p->stump;
585: while (st != NULL) {
586: int x;
587: byte *e;
588: *d++ = st->stream_type;
589: x = st->pid;
590: *d++ = 0xE0 | (x >> 8);
591: *d++ = x;
592: d += 2;
593: e = d;
1.14 oskar 594: x = NUMBER_DESCR;
1.17 oskar 595: while (--x >= 0) {
1.13 oskar 596: byte *y;
597: y = st->manudescr.refx[x];
598: if (y != NULL) {
1.15 oskar 599: int yl = y[1];
600: if (yl != 0) {
601: yl += 2;
602: memcpy (d,y,yl);
603: d += yl;
604: }
1.13 oskar 605: }
606: }
607: x = d - e;
608: *--e = x;
609: *--e = 0xF0 | (x >> 8);
610: st = st->next;
1.1 oskar 611: }
612: i = d + CRC_SIZE - dest - TS_TRANSPORTID;
613: dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
614: dest[TS_SECTIONLEN+1] = i;
615: crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
616: return (i + TS_TRANSPORTID);
617: }
618:
1.7 oskar 619: /* Check for generated psi data to-be-sent, select data source.
620: * If PAT or PMT needs to be rebuild, do so. If PAT or PMT is (partially)
621: * pending to be transmitted, select that to be packaged next. Otherwise
622: * select data payload. Set pid, scramble mode and PES paket size.
623: * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data.
624: * Input: stream s, current ctrl fifo out c.
625: * Output: *pid, *scramble, *size (PES paket ~) for the stream to generate.
626: */
627: static void procdata_check_psi (int *pid,
628: byte *scramble,
629: int *size,
630: stream_descr *s,
631: ctrl_buffer *c)
1.1 oskar 632: {
1.3 oskar 633: t_msec now;
1.16 oskar 634: int i, l;
635: prog_descr *p;
1.1 oskar 636: if (psi_size > 0) {
1.7 oskar 637: *pid = psi_pid;
638: *scramble = 0;
639: *size = psi_size;
1.1 oskar 640: } else {
641: if (unit_start != 0) {
642: now = msec_now ();
643: if ((psi_frequency_changed)
644: || ((psi_frequency_msec > 0)
645: && ((next_psi_periodic - now) <= 0))) {
1.16 oskar 646: unchanged_pat = TRUE;
1.1 oskar 647: l = progs;
648: while (--l >= 0) {
1.16 oskar 649: prog[l]->unchanged = TRUE;
1.1 oskar 650: }
651: psi_frequency_changed = FALSE;
652: next_psi_periodic = now + psi_frequency_msec;
653: }
1.16 oskar 654: if (unchanged_pat || changed_pat) {
1.1 oskar 655: psi_pid = TS_PID_PAT;
656: conticnt = &pat_conticnt;
657: psi_data[0] = 0;
1.16 oskar 658: if ((pat_section == 0)
659: && (changed_pat)) {
660: nextpat_version = (nextpat_version+1) & 0x1F;
661: }
1.1 oskar 662: psi_size = make_patsection (pat_section,&psi_data[1]) + 1;
663: if (pat_section >= last_patsection) {
664: changed_pat = FALSE;
1.16 oskar 665: unchanged_pat = FALSE;
1.1 oskar 666: pat_section = 0;
667: } else {
668: pat_section += 1;
669: }
670: psi_done = 0;
1.7 oskar 671: *pid = psi_pid;
672: *scramble = 0;
673: *size = psi_size;
1.1 oskar 674: } else {
675: l = s->u.d.progs;
676: while (--l >= 0) {
1.16 oskar 677: p = s->u.d.pdescr[l];
678: if (p->unchanged || p->changed) {
679: i = p->streams;
1.7 oskar 680: while ((--i >= 0)
1.16 oskar 681: && (!p->stream[i]->u.d.mention)) {
1.1 oskar 682: }
1.7 oskar 683: if (i >= 0) {
1.16 oskar 684: psi_pid = p->pmt_pid;
685: conticnt = &p->pmt_conticnt;
1.1 oskar 686: psi_data[0] = 0;
1.16 oskar 687: if (p->changed) {
688: p->pmt_version = (p->pmt_version+1) & 0x1F;
689: }
690: psi_size = make_pmtsection (s,p,&psi_data[1]) + 1;
691: p->changed = FALSE;
692: p->unchanged = FALSE;
1.1 oskar 693: psi_done = 0;
1.7 oskar 694: *pid = psi_pid;
695: *scramble = 0;
696: *size = psi_size;
697: return;
1.1 oskar 698: }
699: }
700: }
1.7 oskar 701: s->data.ptr[c->index+PES_STREAM_ID] = s->stream_id;
702: conticnt = &s->conticnt;
703: *pid = s->u.d.pid;
704: *scramble = c->scramble;
705: *size = c->length;
1.1 oskar 706: }
707: } else {
1.7 oskar 708: *pid = s->u.d.pid;
709: *scramble = c->scramble;
710: *size = c->length;
1.1 oskar 711: }
712: }
1.7 oskar 713: }
714:
715: /* Check for adaption field items to be filled in.
716: * First assume no adaption field is set and the complete packet except the
717: * header is available for payload. Then check which adaption fields have
718: * to be set and decrease the free space accordingly.
719: * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data.
720: * Input: stream s, current ctrl fifo out c.
721: * Output: *adapt_flags1, *adapt_flags2, *adapt_ext_len.
722: * Return: number of bytes of free space available for payload.
723: */
724: static int procdata_adaptfield_flags (byte *adapt_flags1,
725: byte *adapt_flags2,
726: int *adapt_ext_len,
727: stream_descr *s,
728: ctrl_buffer *c)
729: {
730: int space;
731: *adapt_ext_len = 1;
732: *adapt_flags2 = 0;
733: *adapt_flags1 = 0;
734: space = TS_PACKET_SIZE - TS_PACKET_HEADSIZE;
1.1 oskar 735: if ((psi_size <= 0)
736: && (s->u.d.discontinuity)) { /* o, not for contents, but PCR-disco ? */
737: s->u.d.discontinuity = FALSE;
1.7 oskar 738: *adapt_flags1 |= TS_ADAPT_DISCONTI;
1.1 oskar 739: }
740: if (0) {
1.7 oskar 741: *adapt_flags1 |= TS_ADAPT_RANDOMAC;
1.1 oskar 742: }
743: if (0) {
1.7 oskar 744: *adapt_flags1 |= TS_ADAPT_PRIORITY;
1.1 oskar 745: }
746: if ((psi_size <= 0)
747: && (s->u.d.has_clockref)
748: && ((c->pcr.valid)
1.2 oskar 749: || (s->u.d.next_clockref - (c->msecpush + s->u.d.delta) <= 0))) {
1.7 oskar 750: *adapt_flags1 |= TS_ADAPT_PCRFLAG;
751: space -= 6;
1.1 oskar 752: }
753: if ((psi_size <= 0)
1.4 oskar 754: && ((c->opcr.valid)
755: || ((!s->u.d.has_opcr)
756: && (c->pcr.valid)))) {
1.7 oskar 757: *adapt_flags1 |= TS_ADAPT_OPCRFLAG;
758: space -= 6;
1.1 oskar 759: }
760: if (0) {
1.7 oskar 761: *adapt_flags1 |= TS_ADAPT_SPLICING;
762: space -= 1;
1.1 oskar 763: }
764: if (0) {
1.7 oskar 765: int privdata;
766: *adapt_flags1 |= TS_ADAPT_TPRIVATE;
1.1 oskar 767: privdata = 0;
1.7 oskar 768: space -= (privdata + 1);
1.1 oskar 769: }
770: if (0) {
1.7 oskar 771: *adapt_flags2 |= TS_ADAPT2_LTWFLAG;
772: *adapt_ext_len += 2;
1.1 oskar 773: }
774: if (0) {
1.7 oskar 775: *adapt_flags2 |= TS_ADAPT2_PIECEWRF;
776: *adapt_ext_len += 3;
1.1 oskar 777: }
778: if (0) {
1.7 oskar 779: *adapt_flags2 |= TS_ADAPT2_SEAMLESS;
780: *adapt_ext_len += 5;
1.1 oskar 781: }
1.7 oskar 782: if (*adapt_flags2 != 0) {
783: *adapt_flags1 |= TS_ADAPT_EXTENSIO;
784: space -= *adapt_ext_len;
1.1 oskar 785: }
1.7 oskar 786: if (*adapt_flags1 != 0) {
787: space -= 2;
1.1 oskar 788: }
1.7 oskar 789: return (space);
790: }
791:
792: /* Adjust size of adaption field against size of payload. Set flags.
793: * Input: *space (number of bytes of free space available for payload),
794: * *adapt_flags1, size (number of bytes left to be sent).
795: * Output: *space (corrected in case of padding is done via adaption field),
796: * *adapt_field_ctrl.
797: * Return: Number of bytes of payload to be inserted into THIS packet.
798: */
799: static int procdata_adaptfield_frame (int *space,
800: byte *adapt_field_ctrl,
801: byte adapt_flags1,
802: int size)
803: {
804: int payload;
805: if (size < *space) {
806: payload = size;
1.1 oskar 807: if (adapt_flags1 == 0) {
1.7 oskar 808: *space -= 1;
809: if (*space > payload) {
810: *space -= 1;
1.1 oskar 811: }
812: }
1.7 oskar 813: *adapt_field_ctrl = TS_AFC_BOTH;
1.1 oskar 814: } else {
1.7 oskar 815: payload = *space;
816: if (payload == 0) {
817: *adapt_field_ctrl = TS_AFC_ADAPT;
1.1 oskar 818: } else if (adapt_flags1 == 0) {
1.7 oskar 819: *adapt_field_ctrl = TS_AFC_PAYLD;
1.1 oskar 820: } else {
1.7 oskar 821: *adapt_field_ctrl = TS_AFC_BOTH;
1.1 oskar 822: }
823: }
1.7 oskar 824: return (payload);
825: }
826:
827: /* Generate packet header.
828: * Keep track of continuity counter (which is selected in procdata_check_psi).
829: * Precondition: d!=NULL (data destination).
830: * Input: pid, scramble, adaption_field_ctrl.
831: * Return: d (increased by header size).
832: */
833: static byte *procdata_syn_head (byte *d,
834: int pid,
835: byte scramble,
836: byte adapt_field_ctrl)
837: {
1.1 oskar 838: *d++ = TS_SYNC_BYTE;
1.7 oskar 839: warn (LSEC,"Splice unitstart",ETSC,7,1,unit_start);
840: warn (LSEC,"Splice PID",ETSC,7,2,pid);
1.1 oskar 841: *d++ = (0 << 7) /* transport_error_indicator */
842: | unit_start
843: | (0 << 5) /* transport_priority */
844: | (pid >> 8);
845: *d++ = pid;
846: *d++ = (scramble << 6)
847: | adapt_field_ctrl
848: | *conticnt;
1.7 oskar 849: warn (LSEC,"Splice continuity cnt",ETSC,7,3,*conticnt);
1.1 oskar 850: if (adapt_field_ctrl & TS_AFC_PAYLD) {
851: *conticnt = (*conticnt+1) & 0x0F;
852: }
1.7 oskar 853: return (d);
854: }
855:
856: /* Generate adpation field.
857: * This MUST match the calculations in procdata_adaptfield_flags.
858: * Precondition: s!=NULL.
859: * Input: s (stream), c (current ctrl fifo out), d (data destination),
860: * padding (number of padding bytes needed), payload (number of payload bytes
861: * to insert), adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len.
862: * Return: d (increased by adaption field size).
863: */
864: static byte *procdata_syn_adaptfield (stream_descr *s,
865: ctrl_buffer *c,
866: byte *d,
867: int padding,
868: int payload,
869: byte adapt_field_ctrl,
870: byte adapt_flags1,
871: byte adapt_flags2,
872: int adapt_ext_len)
873: {
1.1 oskar 874: if (adapt_field_ctrl & TS_AFC_ADAPT) {
1.7 oskar 875: if ((*d++ = (TS_PACKET_SIZE - TS_PACKET_FLAGS1) - payload) != 0) {
1.1 oskar 876: *d++ = adapt_flags1;
877: if (adapt_flags1 & TS_ADAPT_PCRFLAG) {
878: clockref pcr;
1.17 oskar 879: msec2cref (&s->u.d.conv, c->msecpush + s->u.d.delta, &pcr);
1.1 oskar 880: *d++ = (pcr.base >> 25) | (pcr.ba33 << 7);
881: *d++ = pcr.base >> 17;
882: *d++ = pcr.base >> 9;
883: *d++ = pcr.base >> 1;
884: *d++ = (pcr.base << 7) | (pcr.ext >> 8) | 0x7E;
885: *d++ = pcr.ext;
886: s->u.d.next_clockref =
1.2 oskar 887: (c->msecpush + s->u.d.delta) + MAX_MSEC_PCRDIST;
1.1 oskar 888: c->pcr.valid = FALSE;
889: }
890: if (adapt_flags1 & TS_ADAPT_OPCRFLAG) {
1.4 oskar 891: clockref *opcr;
892: if (c->opcr.valid) {
893: opcr = &c->opcr;
894: } else {
895: opcr = &c->pcr;
896: }
897: *d++ = (opcr->base >> 25) | (opcr->ba33 << 7);
898: *d++ = opcr->base >> 17;
899: *d++ = opcr->base >> 9;
900: *d++ = opcr->base >> 1;
901: *d++ = (opcr->base << 7) | (opcr->ext >> 8) | 0x7E;
902: *d++ = opcr->ext;
903: opcr->valid = FALSE;
1.1 oskar 904: }
905: if (adapt_flags1 & TS_ADAPT_SPLICING) {
906: }
907: if (adapt_flags1 & TS_ADAPT_TPRIVATE) {
908: }
909: if (adapt_flags1 & TS_ADAPT_EXTENSIO) {
910: *d++ = adapt_ext_len;
911: *d++ = adapt_flags2 | 0x1F;
1.5 oskar 912: if (adapt_flags2 & TS_ADAPT2_LTWFLAG) {
1.1 oskar 913: }
1.5 oskar 914: if (adapt_flags2 & TS_ADAPT2_PIECEWRF) {
1.1 oskar 915: }
1.5 oskar 916: if (adapt_flags2 & TS_ADAPT2_SEAMLESS) {
1.1 oskar 917: }
918: }
919: }
1.7 oskar 920: if (padding > 0) {
921: warn (LSEC,"Splice padding",ETSC,8,1,padding);
922: memset (d,-1,padding);
923: d += padding;
1.1 oskar 924: }
925: }
1.7 oskar 926: return (d);
927: }
928:
929: /* Generate payload portion.
930: * Insert the appropriate payload (either PSI or data), check whether payload
931: * from this PES packet or section is left.
932: * Precondition: s!=NULL.
933: * Input: s (stream), c (current ctrl fifo out), d (data destination),
934: * payload (number of payload bytes to insert).
935: * Return: processed stream s, if there is more data from the current PES
936: * packet to be processed, NULL otherwise.
937: */
938: static stream_descr *procdata_syn_payload (stream_descr *s,
939: ctrl_buffer *c,
940: byte *d,
941: int payload)
942: {
943: if (payload > 0) {
1.1 oskar 944: if (psi_size > 0) {
1.7 oskar 945: memcpy (d,&psi_data[psi_done],payload);
946: if (payload < psi_size) {
947: warn (LSEC,"Splice PSI Data",ETSC,9,s->stream_id,payload);
948: psi_done += payload;
949: psi_size -= payload;
1.1 oskar 950: unit_start = 0;
951: } else {
1.7 oskar 952: warn (LINF,"Splice PSI Done",ETSC,9,s->stream_id,payload);
1.1 oskar 953: psi_done = psi_size = 0;
954: unit_start = TS_UNIT_START;
955: }
956: } else {
1.7 oskar 957: memcpy (d,&s->data.ptr[c->index],payload);
958: if (payload < c->length) {
959: warn (LSEC,"Splice Data",ETSC,9,s->stream_id,payload);
960: c->length -= payload;
961: s->data.out = (c->index += payload);
1.1 oskar 962: unit_start = 0;
963: } else {
1.7 oskar 964: warn (LINF,"Splice Done",ETSC,9,s->stream_id,payload);
1.1 oskar 965: list_incr (s->ctrl.out,s->ctrl,1);
966: if (list_empty (s->ctrl)) {
967: s->data.out = s->data.in;
968: } else {
969: s->data.out = s->ctrl.ptr[s->ctrl.out].index;
970: }
971: unit_start = TS_UNIT_START;
1.7 oskar 972: return (NULL);
1.1 oskar 973: }
974: }
975: }
976: return (s);
1.7 oskar 977: }
978:
979: /* Process unparsed si data and generate output.
980: * Take one TS paket, copy it to output stream data buffer.
981: * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_unparsedsi,
982: * s->ctrl.ptr[s->ctrl.out].length==TS_PACKET_SIZE, d!=NULL.
983: */
984: static void proc_unparsedsi (stream_descr *s,
985: byte *d)
986: {
1.17 oskar 987: warn (LINF,"Splice Unparsed SI",ETSC,10,s->sourceid,s->streamdata);
1.7 oskar 988: memcpy (d,&s->data.ptr[s->ctrl.ptr[s->ctrl.out].index],TS_PACKET_SIZE);
989: /* check if == s->ctrl.ptr[s->ctrl.out].length); ? */
990: list_incr (s->ctrl.out,s->ctrl,1);
991: if (list_empty (s->ctrl)) {
1.12 oskar 992: s->data.out = s->data.in;
1.10 oskar 993: input_closefileifunused (s->fdescr);
1.7 oskar 994: } else {
995: s->data.out = s->ctrl.ptr[s->ctrl.out].index;
996: }
997: }
998:
999: stream_descr *process_something (stream_descr *s)
1000: {
1001: byte *d;
1002: int pid;
1003: byte scramble;
1004: int size;
1005: ctrl_buffer *c;
1006: int payload;
1007: int space;
1008: int adapt_ext_len;
1009: byte adapt_field_ctrl;
1010: byte adapt_flags1, adapt_flags2;
1011: warn (LDEB,"Splice TS",ETSC,0,0,s->ctrl.out);
1012: switch (s->streamdata) {
1013: case sd_data:
1014: c = &s->ctrl.ptr[s->ctrl.out];
1015: procdata_check_psi (&pid, &scramble, &size, s, c);
1.17 oskar 1016: d = output_pushdata (TS_PACKET_SIZE, TRUE, c->msecpush + s->u.d.delta);
1.7 oskar 1017: if (d == NULL) {
1018: return (s);
1019: }
1020: space = procdata_adaptfield_flags (&adapt_flags1, &adapt_flags2,
1021: &adapt_ext_len, s, c);
1.8 oskar 1022: payload = procdata_adaptfield_frame (&space, &adapt_field_ctrl,
1023: adapt_flags1, size);
1.7 oskar 1024: d = procdata_syn_head (d, pid, scramble, adapt_field_ctrl);
1.8 oskar 1025: d = procdata_syn_adaptfield (s, c, d, space-payload, payload,
1026: adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len);
1.7 oskar 1027: return (procdata_syn_payload (s, c, d, payload));
1028: break;
1029: case sd_map:
1030: validate_mapref (s);
1031: return (NULL);
1032: break;
1033: case sd_unparsedsi:
1034: c = &s->ctrl.ptr[s->ctrl.out];
1.17 oskar 1035: d = output_pushdata (TS_PACKET_SIZE, FALSE, 0);
1.7 oskar 1036: if (d == NULL) {
1037: return (s);
1038: }
1039: proc_unparsedsi (s,d);
1040: return (NULL);
1041: break;
1042: default:
1043: return (NULL);
1044: break;
1045: }
1.1 oskar 1046: }
1047:
LinuxTV legacy CVS <linuxtv.org/cvs>