Annotation of multiplexer/splitpes.c, revision 1.7

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;
1.7     ! oskar     121:   u_int16_t 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>