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