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