Annotation of multiplexer/splitpes.c, revision 1.2

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

LinuxTV legacy CVS <linuxtv.org/cvs>