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