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