Annotation of multiplexer/splitpes.c, revision 1.6
1.1 oskar 1: /*
2: * ISO 13818 stream multiplexer
3: * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
1.5 oskar 4: * Author: Oskar Schirmer (oskar@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: {
77: unsigned int p;
78: int i, l, k;
79: boolean r = FALSE;
80: l = k = list_size (f->data);
81: i = f->data.out;
82: p = 2;
83: while ((l > 0)
84: && ((p != 0x000001) || (r = TRUE, FALSE))) {
85: p = ((p & 0x0000FFFF) << 8) | f->data.ptr[i];
86: list_incr (i,f->data,1);
87: l -= 1;
88: }
89: k = k - l - PES_SYNC_SIZE;
90: if (k > 0) {
91: warn (LWAR,"Skipped",EPES,1,1,k);
92: f->skipped += k; /* evaluate: skip > good and skip > CONST -> bad */
93: f->total += k;
94: list_incr (f->data.out,f->data,k);
95: }
96: return (r);
97: }
98:
1.4 oskar 99: /* Determine the stream id of a packet.
100: * Precondition: d!=NULL points to a package.
101: * Return: stream id.
102: */
1.1 oskar 103: int pes_stream_id (refr_data *d)
104: {
105: int i;
106: i = d->out;
107: list_incr (i,*d,PES_STREAM_ID);
108: warn (LINF,"Stream Id",EPES,2,1,d->ptr[i]);
109: return (d->ptr[i]);
110: }
111:
1.4 oskar 112: /* Determine the length of a packet.
113: * Precondition: d!=NULL points to a package.
114: * Return: packet length.
115: */
1.1 oskar 116: int pes_packet_length (refr_data *d)
117: { /* special case len = 0: to do 2.4.3.7 */
118: #define MAX_PACKETSIZE_PROCESSABLE \
1.2 oskar 119: (mmin((MAX_DATA_RAWB-HIGHWATER_RAW),(MAX_DATA_INB/2)) - PES_HEADER_SIZE)
1.3 oskar 120: int i;
121: __u16 l;
1.1 oskar 122: i = d->out;
123: list_incr (i,*d,PES_PACKET_LENGTH);
124: l = d->ptr[i] << 8;
125: list_incr (i,*d,1);
126: l = l | d->ptr[i];
127: if (l > MAX_PACKETSIZE_PROCESSABLE) {
128: warn (LWAR,"Packet too large",EPES,3,2,l);
129: l = MAX_PACKETSIZE_PROCESSABLE;
130: }
131: warn (LINF,"Packet Length",EPES,3,1,l);
132: return (l);
133: }
134:
1.4 oskar 135: /* Copy data from a raw data input buffer to a stream buffer.
136: * wrapping is done for the raw data input buffer.
137: * If the data does not fit at the end of the buffer, break to the start
138: * of the buffer and put it there.
139: * Precondition: src!=NULL providing at least size bytes
140: * dst!=NULL with free unbroken space of a least size bytes.
141: * Return: Pointer to copied data.
142: */
1.1 oskar 143: int pes_transfer (refr_data *src,
144: refr_data *dst,
145: int size)
146: {
147: int l, r;
148: if (size > list_freeinend (*dst)) {
149: dst->in = 0;
150: }
151: r = dst->in;
152: while (size > 0) {
153: l = MAX_DATA_RAWB - src->out;
154: if (l > size) {
155: l = size;
156: }
157: memcpy (&dst->ptr[dst->in],&src->ptr[src->out],l);
158: list_incr (dst->in,*dst,l);
159: list_incr (src->out,*src,l);
160: warn (LDEB,"Transfer",EPES,4,1,l);
161: size -= l;
162: }
163: return (r);
164: }
165:
1.4 oskar 166: /* Split data from a PES stream.
167: * Precondition: f!=NULL
168: * Return: TRUE, if something was processed, FALSE if no data/space available
169: */
1.1 oskar 170: boolean split_pes (file_descr *f)
171: {
172: int l, p, q;
173: stream_descr *s;
174: ctrl_buffer *c;
175: warn (LDEB,"Split PES",EPES,0,0,f);
176: if (pes_skip_to_prefix (f)) {
177: l = list_size (f->data);
178: if (l >= PES_HDCODE_SIZE) {
179: p = pes_stream_id (&f->data);
180: if (p >= PES_LOWEST_SID) {
181: if (f->u.pes.stream == NULL) {
182: if (f->automatic) {
183: f->u.pes.stream = connect_streamprog (f,f->auto_programnb,
184: p,-p,guess_streamtype(p),NULL,NULL,FALSE);
185: if (f->u.pes.stream == NULL) {
186: f->automatic = FALSE;
187: return (FALSE);
188: }
189: } else {
1.2 oskar 190: if (list_free (f->data) < HIGHWATER_RAW) {
1.3 oskar 191: if (!S_ISREG(f->st_mode)) {
1.1 oskar 192: f->skipped += PES_SYNC_SIZE;
193: f->total += PES_SYNC_SIZE;
194: list_incr (f->data.out,f->data,PES_SYNC_SIZE);
195: return (TRUE);
196: }
197: }
198: return (FALSE);
199: }
200: }
201: s = f->u.pes.stream;
202: if (l >= PES_HEADER_SIZE) {
203: q = pes_packet_length (&f->data);
204: q += PES_HEADER_SIZE;
205: if (l >= q) {
206: if (p == s->stream_id) {
207: if (list_free (s->data) >= 2*q-1) {
208: c = &s->ctrl.ptr[s->ctrl.in];
209: c->length = q;
210: f->payload += q;
211: f->total += q;
212: c->index = pes_transfer (&f->data,&s->data,q);
213: warn (LDEB,"Sequence",EPES,0,1,f->sequence);
214: c->sequence = f->sequence++;
215: c->scramble = 0;
1.2 oskar 216: c->msecread = msec_now ();
1.3 oskar 217: if (S_ISREG (f->st_mode)) {
1.2 oskar 218: c->msecpush = c->msecread; /* wrong, but how ? */
1.1 oskar 219: } else {
1.2 oskar 220: c->msecpush = c->msecread; /* enough ? */
1.1 oskar 221: }
222: c->pcr.valid = FALSE;
223: c->opcr.valid = FALSE;
224: list_incr (s->ctrl.in,s->ctrl,1);
225: return (TRUE);
226: }
227: } else {
228: warn (LDEB,"Dropped PES Packet",EPES,0,p,q);
229: f->skipped += q;
230: f->total += q;
231: list_incr (f->data.out,f->data,q);
232: return (TRUE);
233: }
234: }
235: }
236: } else {
237: warn (LWAR,"Unknown PES Packet",EPES,0,2,p);
238: f->skipped += PES_SYNC_SIZE;
239: f->total += PES_SYNC_SIZE;
240: list_incr (f->data.out,f->data,PES_SYNC_SIZE);
241: return (TRUE);
242: }
243: }
244: }
245: return (FALSE);
246: }
247:
LinuxTV legacy CVS <linuxtv.org/cvs>