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