Annotation of multiplexer/splitpes.c, revision 1.9
1.1 oskar 1: /*
2: * ISO 13818 stream multiplexer
3: * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
1.9 ! oskar 4: * Copyright (C) 2004..2006 Oskar Schirmer (schirmer@scara.com)
1.6 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: Split PES
23: * Purpose: Split a packetized elementary stream.
24: *
25: * This module examines a packetized elementary stream and copies the
26: * packets to the input stream buffer. Some of the service functions
27: * provided are also used by module Split PS due to similarity of the
28: * format.
29: */
30:
31: #include "global.h"
32: #include "error.h"
33: #include "pes.h"
34: #include "splitpes.h"
35: #include "input.h"
1.3 oskar 36: #include "splice.h"
1.1 oskar 37:
1.4 oskar 38: /* Guess a stream type.
39: * Return: a stream type according to ISO 13818-1 table 2-29, 0 if none such
40: */
1.1 oskar 41: int guess_streamtype (int streamid)
42: {
43: if ((streamid >= PES_CODE_AUDIO)
44: && (streamid < PES_CODE_AUDIO + PES_NUMB_AUDIO)) {
45: return (PES_STRTYP_AUDIO13818);
46: }
47: if ((streamid >= PES_CODE_VIDEO)
48: && (streamid < PES_CODE_VIDEO + PES_NUMB_VIDEO)) {
49: return (PES_STRTYP_VIDEO13818);
50: }
51: switch (streamid) {
52: case PES_CODE_PRIVATE1:
53: case PES_CODE_PRIVATE2:
54: return (PES_STRTYP_PRIVATDATA);
55: case PES_CODE_DSMCC:
56: return (PES_STRTYP_DSMCC);
57: case PES_CODE_ITU222A:
58: case PES_CODE_ITU222B:
59: case PES_CODE_ITU222C:
60: case PES_CODE_ITU222D:
61: case PES_CODE_ITU222E:
62: return (PES_STRTYP_ITUH222);
63: case PES_CODE_ISO13522:
64: return (PES_STRTYP_MHEG13522);
65: default:
66: return (0);
67: }
68: }
69:
1.4 oskar 70: /* Skip to find a PES/PS stream prefix
71: * Precondition: f!=NULL
72: * Postcondition: if found: f->data.out indicates the prefix.
73: * Return: TRUE, if found, FALSE otherwise.
74: */
1.1 oskar 75: boolean pes_skip_to_prefix (file_descr *f)
76: {
1.9 ! oskar 77: int i, l, k, n;
! 78: byte d;
1.1 oskar 79: l = k = list_size (f->data);
80: i = f->data.out;
1.9 ! oskar 81: n = 1;
! 82: d = f->data.ptr[i];
! 83: while ((--l > 0)
! 84: && ((n >= 0)
! 85: || (d != 0x01))) {
1.1 oskar 86: list_incr (i,f->data,1);
1.9 ! oskar 87: if (d) n = 1; else n -= 1;
! 88: d = f->data.ptr[i];
1.1 oskar 89: }
90: k = k - l - PES_SYNC_SIZE;
91: if (k > 0) {
92: warn (LWAR,"Skipped",EPES,1,1,k);
93: f->skipped += k; /* evaluate: skip > good and skip > CONST -> bad */
94: f->total += k;
95: list_incr (f->data.out,f->data,k);
96: }
1.9 ! oskar 97: return ((n < 0) && (d == 0x01));
1.1 oskar 98: }
99:
1.4 oskar 100: /* Determine the stream id of a packet.
101: * Precondition: d!=NULL points to a package.
102: * Return: stream id.
103: */
1.1 oskar 104: int pes_stream_id (refr_data *d)
105: {
106: int i;
107: i = d->out;
108: list_incr (i,*d,PES_STREAM_ID);
109: warn (LINF,"Stream Id",EPES,2,1,d->ptr[i]);
110: return (d->ptr[i]);
111: }
112:
1.4 oskar 113: /* Determine the length of a packet.
114: * Precondition: d!=NULL points to a package.
115: * Return: packet length.
116: */
1.1 oskar 117: int pes_packet_length (refr_data *d)
118: { /* special case len = 0: to do 2.4.3.7 */
119: #define MAX_PACKETSIZE_PROCESSABLE \
1.2 oskar 120: (mmin((MAX_DATA_RAWB-HIGHWATER_RAW),(MAX_DATA_INB/2)) - PES_HEADER_SIZE)
1.3 oskar 121: int i;
1.7 oskar 122: u_int16_t l;
1.1 oskar 123: i = d->out;
124: list_incr (i,*d,PES_PACKET_LENGTH);
125: l = d->ptr[i] << 8;
126: list_incr (i,*d,1);
127: l = l | d->ptr[i];
128: if (l > MAX_PACKETSIZE_PROCESSABLE) {
129: warn (LWAR,"Packet too large",EPES,3,2,l);
130: l = MAX_PACKETSIZE_PROCESSABLE;
131: }
132: warn (LINF,"Packet Length",EPES,3,1,l);
133: return (l);
134: }
135:
1.4 oskar 136: /* Copy data from a raw data input buffer to a stream buffer.
137: * wrapping is done for the raw data input buffer.
138: * If the data does not fit at the end of the buffer, break to the start
139: * of the buffer and put it there.
140: * Precondition: src!=NULL providing at least size bytes
141: * dst!=NULL with free unbroken space of a least size bytes.
142: * Return: Pointer to copied data.
143: */
1.1 oskar 144: int pes_transfer (refr_data *src,
145: refr_data *dst,
146: int size)
147: {
148: int l, r;
149: if (size > list_freeinend (*dst)) {
150: dst->in = 0;
151: }
152: r = dst->in;
153: while (size > 0) {
154: l = MAX_DATA_RAWB - src->out;
155: if (l > size) {
156: l = size;
157: }
158: memcpy (&dst->ptr[dst->in],&src->ptr[src->out],l);
159: list_incr (dst->in,*dst,l);
160: list_incr (src->out,*src,l);
161: warn (LDEB,"Transfer",EPES,4,1,l);
162: size -= l;
163: }
164: return (r);
165: }
166:
1.4 oskar 167: /* Split data from a PES stream.
168: * Precondition: f!=NULL
169: * Return: TRUE, if something was processed, FALSE if no data/space available
170: */
1.1 oskar 171: boolean split_pes (file_descr *f)
172: {
173: int l, p, q;
174: stream_descr *s;
175: ctrl_buffer *c;
176: warn (LDEB,"Split PES",EPES,0,0,f);
177: if (pes_skip_to_prefix (f)) {
178: l = list_size (f->data);
179: if (l >= PES_HDCODE_SIZE) {
180: p = pes_stream_id (&f->data);
181: if (p >= PES_LOWEST_SID) {
182: if (f->u.pes.stream == NULL) {
183: if (f->automatic) {
184: f->u.pes.stream = connect_streamprog (f,f->auto_programnb,
185: p,-p,guess_streamtype(p),NULL,NULL,FALSE);
186: if (f->u.pes.stream == NULL) {
187: f->automatic = FALSE;
188: return (FALSE);
189: }
190: } else {
1.2 oskar 191: if (list_free (f->data) < HIGHWATER_RAW) {
1.3 oskar 192: if (!S_ISREG(f->st_mode)) {
1.1 oskar 193: f->skipped += PES_SYNC_SIZE;
194: f->total += PES_SYNC_SIZE;
195: list_incr (f->data.out,f->data,PES_SYNC_SIZE);
196: return (TRUE);
197: }
198: }
199: return (FALSE);
200: }
201: }
202: s = f->u.pes.stream;
203: if (l >= PES_HEADER_SIZE) {
204: q = pes_packet_length (&f->data);
205: q += PES_HEADER_SIZE;
206: if (l >= q) {
207: if (p == s->stream_id) {
208: if (list_free (s->data) >= 2*q-1) {
209: c = &s->ctrl.ptr[s->ctrl.in];
210: c->length = q;
211: f->payload += q;
212: f->total += q;
213: c->index = pes_transfer (&f->data,&s->data,q);
214: warn (LDEB,"Sequence",EPES,0,1,f->sequence);
215: c->sequence = f->sequence++;
216: c->scramble = 0;
1.2 oskar 217: c->msecread = msec_now ();
1.3 oskar 218: if (S_ISREG (f->st_mode)) {
1.2 oskar 219: c->msecpush = c->msecread; /* wrong, but how ? */
1.1 oskar 220: } else {
1.2 oskar 221: c->msecpush = c->msecread; /* enough ? */
1.1 oskar 222: }
223: c->pcr.valid = FALSE;
224: c->opcr.valid = FALSE;
225: list_incr (s->ctrl.in,s->ctrl,1);
226: return (TRUE);
227: }
228: } else {
229: warn (LDEB,"Dropped PES Packet",EPES,0,p,q);
230: f->skipped += q;
231: f->total += q;
232: list_incr (f->data.out,f->data,q);
233: return (TRUE);
234: }
235: }
236: }
237: } else {
238: warn (LWAR,"Unknown PES Packet",EPES,0,2,p);
239: f->skipped += PES_SYNC_SIZE;
240: f->total += PES_SYNC_SIZE;
241: list_incr (f->data.out,f->data,PES_SYNC_SIZE);
242: return (TRUE);
243: }
244: }
245: }
246: return (FALSE);
247: }
248:
LinuxTV legacy CVS <linuxtv.org/cvs>