Annotation of multiplexer/splicets.c, revision 1.9
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.9 ! oskar 55: boolean splice_specific_init (void)
1.1 oskar 56: {
57: progs = 0;
58: nextpid = 0;
59: memset (outs,0,sizeof(outs));
60: changed_pat = TRUE;
61: pat_section = 0;
62: nextpat_version = 0;
63: pat_conticnt = 0;
64: psi_size = psi_done = 0;
65: unit_start = TS_UNIT_START;
66: transportstreamid = 0x4227;
67: return (TRUE);
68: }
69:
70: void splice_settransportstreamid (int tsid)
71: {
72: transportstreamid = tsid;
73: }
74:
75: void splice_setpsifrequency (int freq)
76: {
77: psi_frequency_msec = freq;
78: psi_frequency_changed = TRUE;
79: }
80:
81: static int findapid (stream_descr *s)
82: {
83: boolean ok = TRUE;
84: do {
1.2 oskar 85: if ((nextpid < TS_PID_SPLICELO) || (nextpid >= TS_PID_SPLICEHI)) {
1.1 oskar 86: if (!ok) {
87: warn (LERR,"No PID found",ETSC,2,1,0);
88: return (0);
89: }
90: ok = FALSE;
1.2 oskar 91: nextpid = TS_PID_SPLICELO;
1.1 oskar 92: } else {
93: nextpid += 1;
94: }
95: } while (outs[nextpid] != NULL);
96: outs[nextpid] = s;
97: warn (LDEB,"Next PID",ETSC,2,2,nextpid);
98: return (nextpid);
99: }
100:
1.9 ! oskar 101: void splice_all_configuration (void)
! 102: {
! 103: int i;
! 104: if (configuration_on && configuration_changed) {
! 105: i = progs;
! 106: fprintf (stderr, configuration_total, i);
! 107: while (--i >= 0) {
! 108: splice_one_configuration (prog[i]);
! 109: }
! 110: configuration_changed = FALSE;
! 111: }
! 112: }
! 113:
1.3 oskar 114: prog_descr *splice_getprog (int programnb)
115: {
116: int i;
117: i = progs;
118: while (--i >= 0) {
119: if (prog[i]->program_number == programnb) {
120: return (prog[i]);
121: }
122: }
123: return (NULL);
124: }
125:
1.1 oskar 126: prog_descr *splice_openprog (int programnb)
127: {
128: prog_descr *p;
129: int pid;
130: warn (LIMP,"Open prog",ETSC,1,0,programnb);
1.3 oskar 131: p = splice_getprog (programnb);
1.1 oskar 132: if (p == NULL) {
133: if (progs < MAX_OUTPROG) {
134: if ((pid = findapid (PMT_STREAM)) > 0) {
135: if ((p = malloc(sizeof(prog_descr))) != NULL) {
136: p->program_number = programnb;
137: p->pcr_pid = -1;
138: p->pmt_pid = pid;
139: p->pmt_conticnt = 0;
140: p->pmt_version = 0;
141: p->changed = TRUE;
142: p->pat_section = 0; /* more ? */
143: p->streams = 0;
144: prog[progs++] = p;
145: changed_pat = TRUE;
1.9 ! oskar 146: configuration_changed = TRUE;
1.1 oskar 147: } else {
148: outs[pid] = NULL;
149: warn (LERR,"Open prog",ETSC,1,1,0);
150: }
151: }
152: } else {
153: warn (LERR,"Max prog open",ETSC,1,2,0);
154: }
155: }
156: return (p);
157: }
158:
159: void splice_closeprog (prog_descr *p)
160: {
161: int i, n;
162: warn (LIMP,"Close prog",ETSC,3,0,p->program_number);
1.9 ! oskar 163: configuration_changed = TRUE;
1.1 oskar 164: while (p->streams > 0) {
1.3 oskar 165: unlink_streamprog (p->stream[0],p);
1.1 oskar 166: }
167: n = -1;
168: if (p->pmt_pid >= 0) {
169: i = progs;
170: while (--i >= 0) {
171: if (prog[i]->pmt_pid == p->pmt_pid) {
172: n += 1;
173: }
174: }
175: }
176: i = progs;
177: while (--i >= 0) {
178: if (prog[i] == p) {
179: prog[i] = prog[--progs];
180: if (n == 0) {
181: outs[p->pmt_pid] = NULL;
182: }
183: free (p);
184: changed_pat = TRUE;
185: return;
186: }
187: }
188: warn (LERR,"Close lost prog",ETSC,3,1,progs);
189: }
190:
191: int splice_addstream (prog_descr *p,
192: stream_descr *s,
193: boolean force_sid)
194: {
195: int pid = 0;
196: warn (LIMP,"Add stream",ETSC,4,force_sid,s->stream_id);
197: if (p->streams < MAX_STRPERPRG) {
198: if ((pid = findapid (s)) > 0) {
199: if (!force_sid) {
1.3 oskar 200: s->stream_id = splice_findfreestreamid (p,s->stream_id);
1.1 oskar 201: }
202: p->stream[p->streams++] = s;
203: p->changed = TRUE;
204: s->u.d.pid = pid;
1.9 ! oskar 205: configuration_changed = TRUE;
1.1 oskar 206: }
207: }
208: return (pid);
209: }
210:
211: boolean splice_delstream (prog_descr *p,
212: stream_descr *s)
213: {
214: int i;
215: warn (LIMP,"Del stream",ETSC,5,0,s->u.d.pid);
1.9 ! oskar 216: configuration_changed = TRUE;
1.1 oskar 217: i = p->streams;
218: while (--i >= 0) {
219: if (p->stream[i] == s) {
220: outs[s->u.d.pid] = NULL;
221: p->stream[i] = p->stream[--(p->streams)];
222: p->changed = TRUE;
223: if (p->pcr_pid == s->u.d.pid) {
224: p->pcr_pid = -1;
225: }
226: s->u.d.pid = 0;
227: return (TRUE);
228: }
229: }
230: warn (LERR,"Del lost stream",ETSC,5,1,p->streams);
231: return (FALSE);
232: }
233:
1.7 oskar 234: void process_finish (void)
235: {
236: warn (LIMP,"Finish",ETSC,6,0,0);
237: }
238:
1.1 oskar 239: static int make_patsection (int section,
240: byte *dest)
241: {
242: int i;
243: byte *d;
244: d = dest;
245: *d++ = TS_TABLEID_PAT;
246: d += 2;
247: *d++ = transportstreamid >> 8;
248: *d++ = (byte)transportstreamid;
249: *d++ = 0xC0 | 0x01 | (nextpat_version << 1);
250: *d++ = section;
251: *d++ = last_patsection;
252: i = progs;
253: while (--i >= 0) {
254: if (prog[i]->pat_section == section) {
255: int x;
256: x = prog[i]->program_number;
257: *d++ = (x >> 8);
258: *d++ = x;
259: x = prog[i]->pmt_pid;
260: *d++ = 0xE0 | (x >> 8);
261: *d++ = x;
262: }
263: }
264: i = d + CRC_SIZE - dest - TS_TRANSPORTID;
265: dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
266: dest[TS_SECTIONLEN+1] = i;
267: crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
268: return (i + TS_TRANSPORTID);
269: }
270:
271: static int make_pmtsection (stream_descr *s,
272: prog_descr *p,
273: byte *dest)
274: {
275: int i;
276: byte *d;
277: p->changed = FALSE;
278: d = dest;
279: *d++ = TS_TABLEID_PMT;
280: d += 2;
281: i = p->program_number;
282: *d++ = (i >> 8);
283: *d++ = i;
284: *d++ = 0xC0 | 0x01 | (p->pmt_version << 1);
285: p->pmt_version = (p->pmt_version+1) & 0x1F;
286: *d++ = 0;
287: *d++ = 0;
288: if (p->pcr_pid < 0) {
289: stream_descr *pcrs;
1.3 oskar 290: pcrs = splice_findpcrstream (p);
1.1 oskar 291: if (pcrs == NULL) {
292: pcrs = s;
293: }
294: pcrs->u.d.has_clockref = TRUE;
295: pcrs->u.d.next_clockref = msec_now () - MAX_MSEC_PCRDIST;
296: p->pcr_pid = pcrs->u.d.pid;
1.9 ! oskar 297: configuration_changed = TRUE;
1.1 oskar 298: }
299: i = p->pcr_pid;
300: *d++ = 0xE0 | (i >> 8);
301: *d++ = i;
302: d += 2;
303: i = NUMBER_ELEMD;
304: while (--i > 0) {
305: if (s->fdescr->content == ct_program) {
306: byte *y;
307: y = s->fdescr->u.ps.stream[0]->elemdvld[i]; /* this one ? why ? */
308: if (y != NULL) {
309: memcpy (d,y,y[1]+2);
310: d += y[1]+2;
311: }
312: }
313: }
314: i = d - dest - (TS_PMT_PILEN+2);
315: dest[TS_PMT_PILEN] = 0xF0 | (i >> 8);
316: dest[TS_PMT_PILEN+1] = i;
317: i = p->streams;
318: while (--i >= 0) {
319: if (p->stream[i]->u.d.mention) {
320: int x;
321: byte *e;
322: *d++ = p->stream[i]->stream_type;
323: x = p->stream[i]->u.d.pid;
324: *d++ = 0xE0 | (x >> 8);
325: *d++ = x;
326: d += 2;
327: e = d;
328: x = NUMBER_ELEMD;
329: while (--x > 0) {
330: byte *y;
331: y = p->stream[i]->elemdvld[x];
332: if (y != NULL) {
333: memcpy (d,y,y[1]+2);
334: d += y[1]+2;
335: }
336: }
337: x = d - e;
338: *--e = x;
339: *--e = 0xF0 | (x >> 8);
340: }
341: }
342: i = d + CRC_SIZE - dest - TS_TRANSPORTID;
343: dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
344: dest[TS_SECTIONLEN+1] = i;
345: crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
346: return (i + TS_TRANSPORTID);
347: }
348:
1.7 oskar 349: /* Check for generated psi data to-be-sent, select data source.
350: * If PAT or PMT needs to be rebuild, do so. If PAT or PMT is (partially)
351: * pending to be transmitted, select that to be packaged next. Otherwise
352: * select data payload. Set pid, scramble mode and PES paket size.
353: * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data.
354: * Input: stream s, current ctrl fifo out c.
355: * Output: *pid, *scramble, *size (PES paket ~) for the stream to generate.
356: */
357: static void procdata_check_psi (int *pid,
358: byte *scramble,
359: int *size,
360: stream_descr *s,
361: ctrl_buffer *c)
1.1 oskar 362: {
1.3 oskar 363: t_msec now;
1.1 oskar 364: if (psi_size > 0) {
1.7 oskar 365: *pid = psi_pid;
366: *scramble = 0;
367: *size = psi_size;
1.1 oskar 368: } else {
369: if (unit_start != 0) {
370: now = msec_now ();
371: if ((psi_frequency_changed)
372: || ((psi_frequency_msec > 0)
373: && ((next_psi_periodic - now) <= 0))) {
1.7 oskar 374: int l;
1.1 oskar 375: changed_pat = TRUE;
376: l = progs;
377: while (--l >= 0) {
378: prog[l]->changed = TRUE;
379: }
380: psi_frequency_changed = FALSE;
381: next_psi_periodic = now + psi_frequency_msec;
382: }
383: if (changed_pat) {
384: psi_pid = TS_PID_PAT;
385: conticnt = &pat_conticnt;
386: psi_data[0] = 0;
387: psi_size = make_patsection (pat_section,&psi_data[1]) + 1;
388: if (pat_section >= last_patsection) {
389: changed_pat = FALSE;
390: nextpat_version = (nextpat_version+1) & 0x1F;
391: pat_section = 0;
392: } else {
393: pat_section += 1;
394: }
395: psi_done = 0;
1.7 oskar 396: *pid = psi_pid;
397: *scramble = 0;
398: *size = psi_size;
1.1 oskar 399: } else {
1.7 oskar 400: int l;
1.1 oskar 401: l = s->u.d.progs;
402: while (--l >= 0) {
403: if (s->u.d.pdescr[l]->changed) {
1.7 oskar 404: int i;
405: i = s->u.d.pdescr[l]->streams;
406: while ((--i >= 0)
407: && (!s->u.d.pdescr[l]->stream[i]->u.d.mention)) {
1.1 oskar 408: }
1.7 oskar 409: if (i >= 0) {
1.1 oskar 410: psi_pid = s->u.d.pdescr[l]->pmt_pid;
411: conticnt = &s->u.d.pdescr[l]->pmt_conticnt;
412: psi_data[0] = 0;
413: psi_size = make_pmtsection (s,s->u.d.pdescr[l],&psi_data[1]) + 1;
414: psi_done = 0;
1.7 oskar 415: *pid = psi_pid;
416: *scramble = 0;
417: *size = psi_size;
418: return;
1.1 oskar 419: }
420: }
421: }
1.7 oskar 422: s->data.ptr[c->index+PES_STREAM_ID] = s->stream_id;
423: conticnt = &s->conticnt;
424: *pid = s->u.d.pid;
425: *scramble = c->scramble;
426: *size = c->length;
1.1 oskar 427: }
428: } else {
1.7 oskar 429: *pid = s->u.d.pid;
430: *scramble = c->scramble;
431: *size = c->length;
1.1 oskar 432: }
433: }
1.7 oskar 434: }
435:
436: /* Check for adaption field items to be filled in.
437: * First assume no adaption field is set and the complete packet except the
438: * header is available for payload. Then check which adaption fields have
439: * to be set and decrease the free space accordingly.
440: * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data.
441: * Input: stream s, current ctrl fifo out c.
442: * Output: *adapt_flags1, *adapt_flags2, *adapt_ext_len.
443: * Return: number of bytes of free space available for payload.
444: */
445: static int procdata_adaptfield_flags (byte *adapt_flags1,
446: byte *adapt_flags2,
447: int *adapt_ext_len,
448: stream_descr *s,
449: ctrl_buffer *c)
450: {
451: int space;
452: *adapt_ext_len = 1;
453: *adapt_flags2 = 0;
454: *adapt_flags1 = 0;
455: space = TS_PACKET_SIZE - TS_PACKET_HEADSIZE;
1.1 oskar 456: if ((psi_size <= 0)
457: && (s->u.d.discontinuity)) { /* o, not for contents, but PCR-disco ? */
458: s->u.d.discontinuity = FALSE;
1.7 oskar 459: *adapt_flags1 |= TS_ADAPT_DISCONTI;
1.1 oskar 460: }
461: if (0) {
1.7 oskar 462: *adapt_flags1 |= TS_ADAPT_RANDOMAC;
1.1 oskar 463: }
464: if (0) {
1.7 oskar 465: *adapt_flags1 |= TS_ADAPT_PRIORITY;
1.1 oskar 466: }
467: if ((psi_size <= 0)
468: && (s->u.d.has_clockref)
469: && ((c->pcr.valid)
1.2 oskar 470: || (s->u.d.next_clockref - (c->msecpush + s->u.d.delta) <= 0))) {
1.7 oskar 471: *adapt_flags1 |= TS_ADAPT_PCRFLAG;
472: space -= 6;
1.1 oskar 473: }
474: if ((psi_size <= 0)
1.4 oskar 475: && ((c->opcr.valid)
476: || ((!s->u.d.has_opcr)
477: && (c->pcr.valid)))) {
1.7 oskar 478: *adapt_flags1 |= TS_ADAPT_OPCRFLAG;
479: space -= 6;
1.1 oskar 480: }
481: if (0) {
1.7 oskar 482: *adapt_flags1 |= TS_ADAPT_SPLICING;
483: space -= 1;
1.1 oskar 484: }
485: if (0) {
1.7 oskar 486: int privdata;
487: *adapt_flags1 |= TS_ADAPT_TPRIVATE;
1.1 oskar 488: privdata = 0;
1.7 oskar 489: space -= (privdata + 1);
1.1 oskar 490: }
491: if (0) {
1.7 oskar 492: *adapt_flags2 |= TS_ADAPT2_LTWFLAG;
493: *adapt_ext_len += 2;
1.1 oskar 494: }
495: if (0) {
1.7 oskar 496: *adapt_flags2 |= TS_ADAPT2_PIECEWRF;
497: *adapt_ext_len += 3;
1.1 oskar 498: }
499: if (0) {
1.7 oskar 500: *adapt_flags2 |= TS_ADAPT2_SEAMLESS;
501: *adapt_ext_len += 5;
1.1 oskar 502: }
1.7 oskar 503: if (*adapt_flags2 != 0) {
504: *adapt_flags1 |= TS_ADAPT_EXTENSIO;
505: space -= *adapt_ext_len;
1.1 oskar 506: }
1.7 oskar 507: if (*adapt_flags1 != 0) {
508: space -= 2;
1.1 oskar 509: }
1.7 oskar 510: return (space);
511: }
512:
513: /* Adjust size of adaption field against size of payload. Set flags.
514: * Input: *space (number of bytes of free space available for payload),
515: * *adapt_flags1, size (number of bytes left to be sent).
516: * Output: *space (corrected in case of padding is done via adaption field),
517: * *adapt_field_ctrl.
518: * Return: Number of bytes of payload to be inserted into THIS packet.
519: */
520: static int procdata_adaptfield_frame (int *space,
521: byte *adapt_field_ctrl,
522: byte adapt_flags1,
523: int size)
524: {
525: int payload;
526: if (size < *space) {
527: payload = size;
1.1 oskar 528: if (adapt_flags1 == 0) {
1.7 oskar 529: *space -= 1;
530: if (*space > payload) {
531: *space -= 1;
1.1 oskar 532: }
533: }
1.7 oskar 534: *adapt_field_ctrl = TS_AFC_BOTH;
1.1 oskar 535: } else {
1.7 oskar 536: payload = *space;
537: if (payload == 0) {
538: *adapt_field_ctrl = TS_AFC_ADAPT;
1.1 oskar 539: } else if (adapt_flags1 == 0) {
1.7 oskar 540: *adapt_field_ctrl = TS_AFC_PAYLD;
1.1 oskar 541: } else {
1.7 oskar 542: *adapt_field_ctrl = TS_AFC_BOTH;
1.1 oskar 543: }
544: }
1.7 oskar 545: return (payload);
546: }
547:
548: /* Generate packet header.
549: * Keep track of continuity counter (which is selected in procdata_check_psi).
550: * Precondition: d!=NULL (data destination).
551: * Input: pid, scramble, adaption_field_ctrl.
552: * Return: d (increased by header size).
553: */
554: static byte *procdata_syn_head (byte *d,
555: int pid,
556: byte scramble,
557: byte adapt_field_ctrl)
558: {
1.1 oskar 559: *d++ = TS_SYNC_BYTE;
1.7 oskar 560: warn (LSEC,"Splice unitstart",ETSC,7,1,unit_start);
561: warn (LSEC,"Splice PID",ETSC,7,2,pid);
1.1 oskar 562: *d++ = (0 << 7) /* transport_error_indicator */
563: | unit_start
564: | (0 << 5) /* transport_priority */
565: | (pid >> 8);
566: *d++ = pid;
567: *d++ = (scramble << 6)
568: | adapt_field_ctrl
569: | *conticnt;
1.7 oskar 570: warn (LSEC,"Splice continuity cnt",ETSC,7,3,*conticnt);
1.1 oskar 571: if (adapt_field_ctrl & TS_AFC_PAYLD) {
572: *conticnt = (*conticnt+1) & 0x0F;
573: }
1.7 oskar 574: return (d);
575: }
576:
577: /* Generate adpation field.
578: * This MUST match the calculations in procdata_adaptfield_flags.
579: * Precondition: s!=NULL.
580: * Input: s (stream), c (current ctrl fifo out), d (data destination),
581: * padding (number of padding bytes needed), payload (number of payload bytes
582: * to insert), adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len.
583: * Return: d (increased by adaption field size).
584: */
585: static byte *procdata_syn_adaptfield (stream_descr *s,
586: ctrl_buffer *c,
587: byte *d,
588: int padding,
589: int payload,
590: byte adapt_field_ctrl,
591: byte adapt_flags1,
592: byte adapt_flags2,
593: int adapt_ext_len)
594: {
1.1 oskar 595: if (adapt_field_ctrl & TS_AFC_ADAPT) {
1.7 oskar 596: if ((*d++ = (TS_PACKET_SIZE - TS_PACKET_FLAGS1) - payload) != 0) {
1.1 oskar 597: *d++ = adapt_flags1;
598: if (adapt_flags1 & TS_ADAPT_PCRFLAG) {
599: clockref pcr;
1.2 oskar 600: msec2cref (&s->u.d.conv,c->msecpush + s->u.d.delta,&pcr);
1.1 oskar 601: *d++ = (pcr.base >> 25) | (pcr.ba33 << 7);
602: *d++ = pcr.base >> 17;
603: *d++ = pcr.base >> 9;
604: *d++ = pcr.base >> 1;
605: *d++ = (pcr.base << 7) | (pcr.ext >> 8) | 0x7E;
606: *d++ = pcr.ext;
607: s->u.d.next_clockref =
1.2 oskar 608: (c->msecpush + s->u.d.delta) + MAX_MSEC_PCRDIST;
1.1 oskar 609: c->pcr.valid = FALSE;
610: }
611: if (adapt_flags1 & TS_ADAPT_OPCRFLAG) {
1.4 oskar 612: clockref *opcr;
613: if (c->opcr.valid) {
614: opcr = &c->opcr;
615: } else {
616: opcr = &c->pcr;
617: }
618: *d++ = (opcr->base >> 25) | (opcr->ba33 << 7);
619: *d++ = opcr->base >> 17;
620: *d++ = opcr->base >> 9;
621: *d++ = opcr->base >> 1;
622: *d++ = (opcr->base << 7) | (opcr->ext >> 8) | 0x7E;
623: *d++ = opcr->ext;
624: opcr->valid = FALSE;
1.1 oskar 625: }
626: if (adapt_flags1 & TS_ADAPT_SPLICING) {
627: }
628: if (adapt_flags1 & TS_ADAPT_TPRIVATE) {
629: }
630: if (adapt_flags1 & TS_ADAPT_EXTENSIO) {
631: *d++ = adapt_ext_len;
632: *d++ = adapt_flags2 | 0x1F;
1.5 oskar 633: if (adapt_flags2 & TS_ADAPT2_LTWFLAG) {
1.1 oskar 634: }
1.5 oskar 635: if (adapt_flags2 & TS_ADAPT2_PIECEWRF) {
1.1 oskar 636: }
1.5 oskar 637: if (adapt_flags2 & TS_ADAPT2_SEAMLESS) {
1.1 oskar 638: }
639: }
640: }
1.7 oskar 641: if (padding > 0) {
642: warn (LSEC,"Splice padding",ETSC,8,1,padding);
643: memset (d,-1,padding);
644: d += padding;
1.1 oskar 645: }
646: }
1.7 oskar 647: return (d);
648: }
649:
650: /* Generate payload portion.
651: * Insert the appropriate payload (either PSI or data), check whether payload
652: * from this PES packet or section is left.
653: * Precondition: s!=NULL.
654: * Input: s (stream), c (current ctrl fifo out), d (data destination),
655: * payload (number of payload bytes to insert).
656: * Return: processed stream s, if there is more data from the current PES
657: * packet to be processed, NULL otherwise.
658: */
659: static stream_descr *procdata_syn_payload (stream_descr *s,
660: ctrl_buffer *c,
661: byte *d,
662: int payload)
663: {
664: if (payload > 0) {
1.1 oskar 665: if (psi_size > 0) {
1.7 oskar 666: memcpy (d,&psi_data[psi_done],payload);
667: if (payload < psi_size) {
668: warn (LSEC,"Splice PSI Data",ETSC,9,s->stream_id,payload);
669: psi_done += payload;
670: psi_size -= payload;
1.1 oskar 671: unit_start = 0;
672: } else {
1.7 oskar 673: warn (LINF,"Splice PSI Done",ETSC,9,s->stream_id,payload);
1.1 oskar 674: psi_done = psi_size = 0;
675: unit_start = TS_UNIT_START;
676: }
677: } else {
1.7 oskar 678: memcpy (d,&s->data.ptr[c->index],payload);
679: if (payload < c->length) {
680: warn (LSEC,"Splice Data",ETSC,9,s->stream_id,payload);
681: c->length -= payload;
682: s->data.out = (c->index += payload);
1.1 oskar 683: unit_start = 0;
684: } else {
1.7 oskar 685: warn (LINF,"Splice Done",ETSC,9,s->stream_id,payload);
1.1 oskar 686: list_incr (s->ctrl.out,s->ctrl,1);
687: if (list_empty (s->ctrl)) {
688: s->data.out = s->data.in;
689: } else {
690: s->data.out = s->ctrl.ptr[s->ctrl.out].index;
691: }
692: unit_start = TS_UNIT_START;
1.7 oskar 693: return (NULL);
1.1 oskar 694: }
695: }
696: }
697: return (s);
1.7 oskar 698: }
699:
700: /* Process unparsed si data and generate output.
701: * Take one TS paket, copy it to output stream data buffer.
702: * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_unparsedsi,
703: * s->ctrl.ptr[s->ctrl.out].length==TS_PACKET_SIZE, d!=NULL.
704: */
705: static void proc_unparsedsi (stream_descr *s,
706: byte *d)
707: {
708: warn (LINF,"Splice Unparsed SI",ETSC,10,0,s->u.usi.delta);
709: memcpy (d,&s->data.ptr[s->ctrl.ptr[s->ctrl.out].index],TS_PACKET_SIZE);
710: /* check if == s->ctrl.ptr[s->ctrl.out].length); ? */
711: list_incr (s->ctrl.out,s->ctrl,1);
712: if (list_empty (s->ctrl)) {
713: s->data.out = s->data.in;
714: } else {
715: s->data.out = s->ctrl.ptr[s->ctrl.out].index;
716: }
717: }
718:
719: stream_descr *process_something (stream_descr *s)
720: {
721: byte *d;
722: int pid;
723: byte scramble;
724: int size;
725: ctrl_buffer *c;
726: int payload;
727: int space;
728: int adapt_ext_len;
729: byte adapt_field_ctrl;
730: byte adapt_flags1, adapt_flags2;
731: warn (LDEB,"Splice TS",ETSC,0,0,s->ctrl.out);
732: switch (s->streamdata) {
733: case sd_data:
734: c = &s->ctrl.ptr[s->ctrl.out];
735: procdata_check_psi (&pid, &scramble, &size, s, c);
736: d = output_pushdata (TS_PACKET_SIZE,c->msecpush + s->u.d.delta);
737: if (d == NULL) {
738: return (s);
739: }
740: space = procdata_adaptfield_flags (&adapt_flags1, &adapt_flags2,
741: &adapt_ext_len, s, c);
1.8 oskar 742: payload = procdata_adaptfield_frame (&space, &adapt_field_ctrl,
743: adapt_flags1, size);
1.7 oskar 744: d = procdata_syn_head (d, pid, scramble, adapt_field_ctrl);
1.8 oskar 745: d = procdata_syn_adaptfield (s, c, d, space-payload, payload,
746: adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len);
1.7 oskar 747: return (procdata_syn_payload (s, c, d, payload));
748: break;
749: case sd_map:
750: validate_mapref (s);
751: return (NULL);
752: break;
753: case sd_unparsedsi:
754: c = &s->ctrl.ptr[s->ctrl.out];
755: d = output_pushdata (TS_PACKET_SIZE,c->msecpush + s->u.usi.delta);
756: if (d == NULL) {
757: return (s);
758: }
759: proc_unparsedsi (s,d);
760: return (NULL);
761: break;
762: default:
763: return (NULL);
764: break;
765: }
1.1 oskar 766: }
767:
LinuxTV legacy CVS <linuxtv.org/cvs>