Annotation of multiplexer/splitpes.c, revision 1.2
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: Split PES
9: * Purpose: Split a packetized elementary stream.
10: *
11: * This module examines a packetized elementary stream and copies the
12: * packets to the input stream buffer. Some of the service functions
13: * provided are also used by module Split PS due to similarity of the
14: * format.
15: */
16:
17: #include "global.h"
18: #include "error.h"
19: #include "pes.h"
20: #include "splitpes.h"
21: #include "input.h"
22:
23: int guess_streamtype (int streamid)
24: {
25: if ((streamid >= PES_CODE_AUDIO)
26: && (streamid < PES_CODE_AUDIO + PES_NUMB_AUDIO)) {
27: return (PES_STRTYP_AUDIO13818);
28: }
29: if ((streamid >= PES_CODE_VIDEO)
30: && (streamid < PES_CODE_VIDEO + PES_NUMB_VIDEO)) {
31: return (PES_STRTYP_VIDEO13818);
32: }
33: switch (streamid) {
34: case PES_CODE_PRIVATE1:
35: case PES_CODE_PRIVATE2:
36: return (PES_STRTYP_PRIVATDATA);
37: case PES_CODE_DSMCC:
38: return (PES_STRTYP_DSMCC);
39: case PES_CODE_ITU222A:
40: case PES_CODE_ITU222B:
41: case PES_CODE_ITU222C:
42: case PES_CODE_ITU222D:
43: case PES_CODE_ITU222E:
44: return (PES_STRTYP_ITUH222);
45: case PES_CODE_ISO13522:
46: return (PES_STRTYP_MHEG13522);
47: default:
48: return (0);
49: }
50: }
51:
52: boolean pes_skip_to_prefix (file_descr *f)
53: {
54: unsigned int p;
55: int i, l, k;
56: boolean r = FALSE;
57: l = k = list_size (f->data);
58: i = f->data.out;
59: p = 2;
60: while ((l > 0)
61: && ((p != 0x000001) || (r = TRUE, FALSE))) {
62: p = ((p & 0x0000FFFF) << 8) | f->data.ptr[i];
63: list_incr (i,f->data,1);
64: l -= 1;
65: }
66: k = k - l - PES_SYNC_SIZE;
67: if (k > 0) {
68: warn (LWAR,"Skipped",EPES,1,1,k);
69: f->skipped += k; /* evaluate: skip > good and skip > CONST -> bad */
70: f->total += k;
71: list_incr (f->data.out,f->data,k);
72: }
73: return (r);
74: }
75:
76: int pes_stream_id (refr_data *d)
77: {
78: int i;
79: i = d->out;
80: list_incr (i,*d,PES_STREAM_ID);
81: warn (LINF,"Stream Id",EPES,2,1,d->ptr[i]);
82: return (d->ptr[i]);
83: }
84:
85: int pes_packet_length (refr_data *d)
86: { /* special case len = 0: to do 2.4.3.7 */
87: #define MAX_PACKETSIZE_PROCESSABLE \
1.2 ! oskar 88: (mmin((MAX_DATA_RAWB-HIGHWATER_RAW),(MAX_DATA_INB/2)) - PES_HEADER_SIZE)
1.1 oskar 89: int i, l;
90: i = d->out;
91: list_incr (i,*d,PES_PACKET_LENGTH);
92: l = d->ptr[i] << 8;
93: list_incr (i,*d,1);
94: l = l | d->ptr[i];
95: if (l > MAX_PACKETSIZE_PROCESSABLE) {
96: warn (LWAR,"Packet too large",EPES,3,2,l);
97: l = MAX_PACKETSIZE_PROCESSABLE;
98: }
99: warn (LINF,"Packet Length",EPES,3,1,l);
100: return (l);
101: }
102:
103: int pes_transfer (refr_data *src,
104: refr_data *dst,
105: int size)
106: {
107: int l, r;
108: if (size > list_freeinend (*dst)) {
109: dst->in = 0;
110: }
111: r = dst->in;
112: while (size > 0) {
113: l = MAX_DATA_RAWB - src->out;
114: if (l > size) {
115: l = size;
116: }
117: memcpy (&dst->ptr[dst->in],&src->ptr[src->out],l);
118: list_incr (dst->in,*dst,l);
119: list_incr (src->out,*src,l);
120: warn (LDEB,"Transfer",EPES,4,1,l);
121: size -= l;
122: }
123: return (r);
124: }
125:
126: boolean split_pes (file_descr *f)
127: {
128: int l, p, q;
129: stream_descr *s;
130: ctrl_buffer *c;
131: warn (LDEB,"Split PES",EPES,0,0,f);
132: if (pes_skip_to_prefix (f)) {
133: l = list_size (f->data);
134: if (l >= PES_HDCODE_SIZE) {
135: p = pes_stream_id (&f->data);
136: if (p >= PES_LOWEST_SID) {
137: if (f->u.pes.stream == NULL) {
138: if (f->automatic) {
139: f->u.pes.stream = connect_streamprog (f,f->auto_programnb,
140: p,-p,guess_streamtype(p),NULL,NULL,FALSE);
141: if (f->u.pes.stream == NULL) {
142: f->automatic = FALSE;
143: return (FALSE);
144: }
145: } else {
1.2 ! oskar 146: if (list_free (f->data) < HIGHWATER_RAW) {
1.1 oskar 147: if (!S_ISREG(f->stat.st_mode)) {
148: f->skipped += PES_SYNC_SIZE;
149: f->total += PES_SYNC_SIZE;
150: list_incr (f->data.out,f->data,PES_SYNC_SIZE);
151: return (TRUE);
152: }
153: }
154: return (FALSE);
155: }
156: }
157: s = f->u.pes.stream;
158: if (l >= PES_HEADER_SIZE) {
159: q = pes_packet_length (&f->data);
160: q += PES_HEADER_SIZE;
161: if (l >= q) {
162: if (p == s->stream_id) {
163: if (list_free (s->data) >= 2*q-1) {
164: c = &s->ctrl.ptr[s->ctrl.in];
165: c->length = q;
166: f->payload += q;
167: f->total += q;
168: c->index = pes_transfer (&f->data,&s->data,q);
169: warn (LDEB,"Sequence",EPES,0,1,f->sequence);
170: c->sequence = f->sequence++;
171: c->scramble = 0;
1.2 ! oskar 172: c->msecread = msec_now ();
1.1 oskar 173: if (S_ISREG (f->stat.st_mode)) {
1.2 ! oskar 174: c->msecpush = c->msecread; /* wrong, but how ? */
1.1 oskar 175: } else {
1.2 ! oskar 176: c->msecpush = c->msecread; /* enough ? */
1.1 oskar 177: }
178: c->pcr.valid = FALSE;
179: c->opcr.valid = FALSE;
180: list_incr (s->ctrl.in,s->ctrl,1);
181: return (TRUE);
182: }
183: } else {
184: warn (LDEB,"Dropped PES Packet",EPES,0,p,q);
185: f->skipped += q;
186: f->total += q;
187: list_incr (f->data.out,f->data,q);
188: return (TRUE);
189: }
190: }
191: }
192: } else {
193: warn (LWAR,"Unknown PES Packet",EPES,0,2,p);
194: f->skipped += PES_SYNC_SIZE;
195: f->total += PES_SYNC_SIZE;
196: list_incr (f->data.out,f->data,PES_SYNC_SIZE);
197: return (TRUE);
198: }
199: }
200: }
201: return (FALSE);
202: }
203:
LinuxTV legacy CVS <linuxtv.org/cvs>