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