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>