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