Annotation of multiplexer/input.c, revision 1.28

1.1       oskar       1: /*
                      2:  * ISO 13818 stream multiplexer
                      3:  * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
1.27      oskar       4:  * Copyright (C) 2004 Oskar Schirmer (schirmer@scara.com)
1.24      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:  Input
                     23:  * Purpose: Data Acquisition from the various open files,
                     24:  *          promotion to the single split-functions.
                     25:  *
                     26:  * This module holds two main data structures, an unsorted list of
                     27:  * open input files, and an unsorted list of open input streams
                     28:  * (extracted from these files).
                     29:  * Further provided are functions to open and close files and streams,
                     30:  * to detect states of the input buffers, and to read data into the
                     31:  * (raw) file input buffers.
                     32:  */
                     33: 
                     34: #include "global.h"
                     35: #include "error.h"
                     36: #include "pes.h"
                     37: #include "splitpes.h"
                     38: #include "splitps.h"
                     39: #include "splitts.h"
                     40: #include "splice.h"
                     41: #include "input.h"
1.18      oskar      42: #include "descref.h"
1.9       oskar      43: #include "ts.h"
1.1       oskar      44: 
1.6       oskar      45: /* index of files in use, containing i.a. the raw input data buffers:
                     46:  */
1.1       oskar      47: static file_descr *inf [MAX_INFILE];
                     48: static int in_files;
1.13      oskar      49: static int in_openfiles[number_ct];
1.1       oskar      50: 
1.6       oskar      51: /* index of streams in use, containing i.a. the input pes buffers:
                     52:  */
1.1       oskar      53: static stream_descr *ins [MAX_INSTREAM];
                     54: static int in_streams;
1.13      oskar      55: static int in_openstreams[number_sd];
1.1       oskar      56: 
1.15      oskar      57: static t_msec trigger_msec_input;
                     58: 
1.1       oskar      59: boolean input_init (void)
                     60: {
                     61:   in_files = 0;
1.13      oskar      62:   memset (in_openfiles, 0, sizeof (in_openfiles));
1.1       oskar      63:   in_streams = 0;
1.13      oskar      64:   memset (in_openstreams, 0, sizeof (in_openstreams));
1.15      oskar      65:   trigger_msec_input = TRIGGER_MSEC_INPUT;
1.1       oskar      66:   return (TRUE);
                     67: }
                     68: 
                     69: #ifdef DEBUG_TIMEPOLL
                     70: int deb_inraw_free (int f)
                     71: {
                     72:   register int r;
                     73:   r = (f < in_files) ? list_free (inf[f]->data) : 0;
                     74:   return (r);
                     75: }
                     76: 
                     77: int deb_instr_free (int s)
                     78: {
                     79:   register int r;
                     80:   r = (s < in_streams) ? list_free (ins[s]->data) : 0;
                     81:   return (r);
                     82: }
                     83: #endif
                     84: 
1.6       oskar      85: /* Determine whether data is expected as input.
1.13      oskar      86:  * Return: TRUE, if any valuable file is open, FALSE otherwise
1.6       oskar      87:  */
1.1       oskar      88: boolean input_expected (void)
                     89: {
1.13      oskar      90:   return ((in_files > 0)
                     91:        && ((in_openfiles[ct_transport] != in_files)
                     92:         || (in_openstreams[sd_unparsedsi] != in_streams)));
1.1       oskar      93: }
                     94: 
1.15      oskar      95: /* Set trigger timing value.
                     96:  */
                     97: void input_settriggertiming (t_msec time)
                     98: {
                     99:   trigger_msec_input = time;
                    100: }
                    101: 
1.6       oskar     102: /* Determine whether input data is acceptable, i.e. there is space in buffers.
                    103:  * If so, set the poll struct accordingly for each file in question.
                    104:  * Check the streams for time stamps and set the timeout^ accordingly,
                    105:  * if the streams might be responsible alone for blocking pipes.
                    106:  * Return: TRUE, if at least one buffer has enough space to accept new data.
                    107:  *         FALSE otherwise.
                    108:  */
1.1       oskar     109: boolean input_acceptable (unsigned int *nfds,
                    110:     struct pollfd *ufds,
1.4       oskar     111:     t_msec *timeout,
1.1       oskar     112:     boolean outnotfull)
                    113: {
                    114:   boolean accept = FALSE;
1.4       oskar     115:   int i;
1.21      oskar     116:   t_msec t, now;
                    117:   file_descr *f;
                    118:   stream_descr *s;
1.1       oskar     119:   i = in_files;
                    120:   while (--i >= 0) {
1.21      oskar     121:     f = inf[i];
1.1       oskar     122:     warn (LDEB,"Acceptable",EINP,2,1,i);
1.21      oskar     123:     warn (LDEB,"Free Raw",EINP,2,2,list_free (f->data));
                    124:     if ((list_free (f->data) >= HIGHWATER_RAW)
                    125:      && (f->handle >= 0)) {
                    126:       ufds->fd = f->handle;
1.1       oskar     127:       ufds->events = POLLIN;
                    128:       *nfds += 1;
                    129:       accept = TRUE;
1.21      oskar     130:       f->ufds = ufds++;
1.1       oskar     131:     } else {
1.21      oskar     132:       f->ufds = NULL;
1.1       oskar     133:     }
                    134:   }
                    135:   if (outnotfull) {
1.21      oskar     136:     now = msec_now ();
1.1       oskar     137:     i = in_streams;
                    138:     while (--i >= 0) {
1.21      oskar     139:       s = ins[i];
                    140:       if (s->streamdata == sd_data) {
                    141:         if (!list_empty (s->ctrl)) {
                    142:           if (s->u.d.trigger) {
                    143:             t = s->ctrl.ptr[s->ctrl.out].msecpush - now + s->u.d.delta;
1.15      oskar     144:           } else {
1.21      oskar     145:             t = s->ctrl.ptr[s->ctrl.out].msecread - now + trigger_msec_input;
1.15      oskar     146:           }
                    147:           if ((t > 0)
                    148:            && ((*timeout < 0)
                    149:             || (*timeout > t))) {
                    150:             *timeout = t;
1.1       oskar     151:           }
                    152:         }
                    153:       }
                    154:     }
                    155:   }
                    156:   return (accept);
                    157: }
                    158: 
1.6       oskar     159: /* Set the trigger on a stream, enabling the data to be spliced now.
                    160:  * Set the trigger for all streams that correspond thru the target program, too
                    161:  * Precondition: s!=NULL
                    162:  */
1.1       oskar     163: static void set_trigger (stream_descr *s,
1.4       oskar     164:     t_msec now)
1.1       oskar     165: {
1.21      oskar     166:   int q, i;
                    167:   prog_descr *p;
1.1       oskar     168:   if (!list_empty (s->data)) {
                    169:     s->u.d.lasttime = now;
                    170:     s->u.d.delta =
1.3       oskar     171:       now - s->ctrl.ptr[s->ctrl.out].msecpush;
1.1       oskar     172:     warn (LDEB,"Set Trigger",EINP,8,s->u.d.pid,s->u.d.delta);
                    173:     s->u.d.trigger = TRUE;
                    174:     s->u.d.mention = TRUE;
1.21      oskar     175:     q = s->u.d.progs;
                    176:     while (--q >= 0) {
                    177:       p = s->u.d.pdescr[q];
1.22      oskar     178:       p->unchanged = TRUE;
1.21      oskar     179:       i = p->streams;
1.1       oskar     180:       while (--i >= 0) {
1.21      oskar     181:         if (!p->stream[i]->u.d.trigger) {
                    182:           set_trigger (p->stream[i],now);
1.1       oskar     183:         }
                    184:       }
                    185:     }
                    186:   }
                    187: }
                    188: 
1.6       oskar     189: /* Clear the trigger on a stream, clear it for all corresponding streams, too
                    190:  * Precondition: s!=NULL
                    191:  */
1.1       oskar     192: static void clear_trigger (stream_descr *s)
                    193: {
1.21      oskar     194:   int q, i;
                    195:   prog_descr *p;
1.11      oskar     196:   warn (LDEB,"Clear Trigger",EINP,13,s->u.d.pid,s->u.d.delta);
1.1       oskar     197:   s->u.d.discontinuity = TRUE;
                    198:   s->u.d.trigger = FALSE;
1.21      oskar     199:   q = s->u.d.progs;
                    200:   while (--q >= 0) {
                    201:     p = s->u.d.pdescr[q];
                    202:     i = p->streams;
1.1       oskar     203:     while (--i >= 0) {
1.21      oskar     204:       if (p->stream[i]->u.d.trigger) {
                    205:         clear_trigger (p->stream[i]);
1.1       oskar     206:       }
                    207:     }
                    208:   }
                    209: }
                    210: 
1.9       oskar     211: /* Check if mapstream provides prominent data.
                    212:  * Precondition: d!=NULL, !list_empty(d->ctrl)
                    213:  * Return: TRUE, if mapstream has prominent data, FALSE otherwise
                    214:  */
                    215: static boolean preceding_sequence (stream_descr *d,
                    216:     stream_descr *m)
                    217: {
                    218:   if (m != NULL) {
                    219:     if (!list_empty (m->ctrl)) {
                    220:       if (m->ctrl.ptr[m->ctrl.out].sequence
                    221:         - d->ctrl.ptr[d->ctrl.out].sequence <= 0) {
                    222:         return (TRUE);
                    223:       }
                    224:     }
                    225:   }
                    226:   return (FALSE);
                    227: }
                    228: 
1.6       oskar     229: /* Check for every stream whether data is available to be spliced.
1.9       oskar     230:  * Unparsed SI from an otherwise unused TS has priority.
1.6       oskar     231:  * If the stream with the lowest time stamp has a corresponding map stream,
                    232:  * that provides data to be spliced first, the map stream is returned.
                    233:  * Prior, check if a stream is empty and end it, if necessary; check if a
                    234:  * stream is ready but not yet triggered, so trigger it.
                    235:  * Return: stream to be spliced next.
                    236:  */
1.1       oskar     237: stream_descr *input_available (void)
                    238: {
1.4       oskar     239:   int i, s, q;
                    240:   t_msec t, u, now;
1.20      oskar     241:   stream_descr *d, *e;
                    242:   ctrl_buffer *c;
1.21      oskar     243:   file_descr *f;
1.1       oskar     244:   now = msec_now ();
1.9       oskar     245:   i = in_files;
                    246:   while (--i >= 0) {
1.21      oskar     247:     f = inf[i];
                    248:     if (f->content == ct_transport) {
                    249:       d = ts_file_stream (f,TS_UNPARSED_SI);
1.18      oskar     250:       if (d != NULL) {
1.21      oskar     251:         if (((f->openstreams[sd_data] == 0)
1.18      oskar     252:           && (!list_empty (d->ctrl)))
                    253:          || (list_full (d->ctrl))) {
                    254:           return (d);
                    255:         }
1.9       oskar     256:       }
                    257:     }
                    258:   }
1.1       oskar     259:   i = in_streams;
                    260:   while (--i >= 0) {
1.15      oskar     261:     d = ins[i];
                    262:     if (d->streamdata == sd_data) {
                    263:       if (list_empty (d->ctrl)) {
                    264:         switch (d->endaction) {
1.1       oskar     265:           case ENDSTR_CLOSE:
1.15      oskar     266:             input_endstream (d);
1.1       oskar     267:             if (i > in_streams) {
                    268:               i = in_streams;
                    269:             }
                    270:             break;
                    271:           case ENDSTR_KILL:
1.15      oskar     272:             input_endstreamkill (d);
1.1       oskar     273:             if (i > in_streams) {
                    274:               i = in_streams;
                    275:             }
                    276:             break;
                    277:           case ENDSTR_WAIT:
                    278:             break;
                    279:           default:
1.15      oskar     280:             warn (LERR,"End Action",EINP,3,1,d->endaction);
1.1       oskar     281:             break;
                    282:         }
                    283:         /* trigger:=false if empty? no ! */
                    284:       } else {
1.15      oskar     285:         if (!d->u.d.trigger) {
                    286:           if (list_full (d->ctrl)
                    287:            || list_partialfull (d->data)
                    288:         /* || (list_free (d->fdescr->data) < HIGHWATER_IN) */
                    289:            || (d->endaction == ENDSTR_CLOSE)
                    290:            || (d->endaction == ENDSTR_KILL)
1.21      oskar     291:            || ((now - d->ctrl.ptr[d->ctrl.out].msecread)
                    292:                  >= trigger_msec_input)) {
1.15      oskar     293:             set_trigger (d,now);
1.1       oskar     294:           }
                    295:         }
                    296:       }
                    297:     }
                    298:   }
                    299:   d = NULL;
                    300:   i = in_streams;
                    301:   while (--i >= 0) {
1.20      oskar     302:     e = ins[i];
                    303:     if ((e->streamdata == sd_data)
                    304:      && (e->u.d.trigger)) {
                    305:       if (!list_empty (e->ctrl)) {
1.1       oskar     306:         warn (LDEB,"Available",EINP,3,2,i);
1.20      oskar     307:         c = &(e->ctrl.ptr[e->ctrl.out]);
                    308:         t = c->msecpush + e->u.d.delta;
                    309:         if (t - e->u.d.lasttime < 0) {
                    310:           warn (LWAR,"Time Decrease",EINP,3,3,t - e->u.d.lasttime);
                    311:           clear_trigger (e);
1.1       oskar     312:         } else {
1.20      oskar     313:           e->u.d.lasttime = t; 
1.1       oskar     314:           t -= now;
                    315:           if ((t > MAX_MSEC_PUSHJTTR)
                    316:            || (t < -MAX_MSEC_PUSHJTTR)) {
                    317:             warn (LWAR,"Time Jumpness",EINP,3,4,t);
1.20      oskar     318:             clear_trigger (e);
1.1       oskar     319:           } else {
1.20      oskar     320:             q = c->sequence;
1.1       oskar     321:             if ((t <= 0)
                    322:              && ((d == NULL)
                    323:               || (t < u)
1.20      oskar     324:               || ((t == u) && (q - s < 0)))) {
1.1       oskar     325:               u = t;
                    326:               s = q;
1.21      oskar     327:               d = e;
1.1       oskar     328:             }
                    329:           }
                    330:         }
                    331:       }
                    332:     }
                    333:   }
                    334:   if (d != NULL) {
                    335:     switch (d->fdescr->content) {
1.9       oskar     336:       case ct_transport:
1.20      oskar     337:         e = d;
1.21      oskar     338:         if (preceding_sequence (d, ts_file_stream (d->fdescr,0))) {
1.9       oskar     339:           d = ts_file_stream (d->fdescr,0);
1.17      oskar     340:         } else {
1.21      oskar     341:           if (preceding_sequence (d, d->u.d.mapstream)) {
1.17      oskar     342:             d = d->u.d.mapstream;
                    343:           } else {
1.21      oskar     344:             if (preceding_sequence (d,
                    345:                   ts_file_stream (d->fdescr,TS_UNPARSED_SI))) {
1.17      oskar     346:               d = ts_file_stream (d->fdescr,TS_UNPARSED_SI);
                    347:             }
                    348:           }
1.9       oskar     349:         }
1.17      oskar     350:         break;
1.1       oskar     351:       case ct_program:
1.9       oskar     352:         if (preceding_sequence (d,d->u.d.mapstream)) {
                    353:           d = d->u.d.mapstream;
                    354:         }
1.1       oskar     355:         break;
                    356:       default:
                    357:         break;
                    358:     }
                    359:   }
                    360:   return (d);
                    361: }
                    362: 
1.6       oskar     363: /* Check all files for a given filerefnum.
                    364:  * Precondition: filerefnum>=0
                    365:  * Return: filename, if filerefnum matches, NULL otherwise
                    366:  */
1.5       oskar     367: char *input_filerefername (int filerefnum)
                    368: {
                    369:   int i;
1.21      oskar     370:   file_descr *f;
1.5       oskar     371:   i = in_files;
                    372:   while (--i >= 0) {
1.21      oskar     373:     f = inf[i];
                    374:     if (f->filerefnum == filerefnum) {
                    375:       return (f->name);
                    376:     }
                    377:     if ((f->append_name != NULL)
                    378:      && (f->append_filerefnum == filerefnum)) {
                    379:       return (f->append_name);
1.6       oskar     380:     }
1.5       oskar     381:   }
                    382:   return (NULL);
                    383: }
                    384: 
1.6       oskar     385: /* Open a file. Allocate and initialize it.
                    386:  * Precondition: name!=NULL
                    387:  * Return: file, if successful, NULL otherwise
                    388:  */
1.1       oskar     389: file_descr* input_openfile (char *name,
1.5       oskar     390:     int filerefnum,
1.1       oskar     391:     content_type content,
                    392:     boolean automatic,
                    393:     int programnb)
                    394: {
                    395:   file_descr *f;
1.4       oskar     396:   struct stat stat;
1.1       oskar     397:   warn (LIMP,"Create file",EINP,4,automatic,content);
                    398:   warn (LIMP,name,EINP,4,4,programnb);
                    399:   if (in_files < MAX_INFILE) {
                    400:     switch (content) {
                    401:       case ct_packetized:
                    402:         f = unionalloc (file_descr,pes);
                    403:         break;
                    404:       case ct_program:
                    405:         f = unionalloc (file_descr,ps);
                    406:         break;
                    407:       case ct_transport:
                    408:         f = unionalloc (file_descr,ts);
                    409:         break;
                    410:       default:
                    411:         warn (LERR,"Unknown contents",EINP,4,7,0);
                    412:         f = NULL;
                    413:         break;
                    414:     }
                    415:     if (f != NULL) {
                    416:       if ((f->name = malloc (strlen(name) + 1)) != NULL) {
                    417:         if (list_create (f->data,MAX_DATA_RAWB)) {
1.26      oskar     418:           if ((f->handle = open (name,O_RDONLY|O_NONBLOCK)) >= 0) {
1.4       oskar     419:             if (fstat (f->handle,&stat) == 0) {
                    420:               f->st_mode = stat.st_mode;
                    421:               if (!S_ISREG (f->st_mode)) {
1.1       oskar     422:                 timed_io = TRUE;
                    423:               }
                    424:               strcpy (f->name,name);
1.5       oskar     425:               f->filerefnum = filerefnum;
1.1       oskar     426:               f->skipped = 0;
                    427:               f->payload = 0;
                    428:               f->total = 0;
                    429:               f->sequence = 0;
1.13      oskar     430:               memset (f->openstreams,0,sizeof(f->openstreams));
1.5       oskar     431:               f->append_name = NULL;
1.2       oskar     432:               f->repeatitions = 0;
1.1       oskar     433:               f->auto_programnb = programnb;
1.5       oskar     434:               f->automatic = automatic;
                    435:               f->stopfile = FALSE;
1.1       oskar     436:               f->content = content;
                    437:               switch (content) {
                    438:                 case ct_packetized:
                    439:                   f->u.pes.stream = NULL;
1.13      oskar     440:                   in_openfiles[content] += 1;
1.1       oskar     441:                   inf[in_files++] = f;
                    442:                   return (f);
                    443:                   break;
                    444:                 case ct_program:
                    445:                   memset (f->u.ps.stream,0,sizeof(f->u.ps.stream));
1.10      oskar     446:                   f->u.ps.stream[0] = input_openstream (f,0,0,0,sd_map,NULL);
1.1       oskar     447:                   if (f->u.ps.stream[0] != NULL) {
1.13      oskar     448:                     in_openfiles[content] += 1;
1.1       oskar     449:                     inf[in_files++] = f;
                    450:                     return (f);
                    451:                   }
                    452:                   break;
                    453:                 case ct_transport:
                    454:                   f->u.ts.pat_version = 0xFF;
                    455:                   f->u.ts.newpat_version = 0xFF;
                    456:                   f->u.ts.pat = NULL;
                    457:                   f->u.ts.newpat = NULL;
                    458:                   f->u.ts.tsauto = NULL;
1.9       oskar     459:                   f->u.ts.tssi = NULL;
1.1       oskar     460:                   memset (f->u.ts.stream,0,sizeof(f->u.ts.stream));
1.10      oskar     461:                   ts_file_stream (f,0) = input_openstream (f,0,0,0,sd_map,NULL);
1.6       oskar     462:                   if (ts_file_stream (f,0) != NULL) {
1.13      oskar     463:                     in_openfiles[content] += 1;
1.1       oskar     464:                     inf[in_files++] = f;
                    465:                     return (f);
                    466:                   }
                    467:                   break;
                    468:                 default:
                    469:                   break;
                    470:               }
                    471:             } else {
                    472:               warn (LERR,"FStat fail",EINP,4,6,0);
                    473:             }
                    474:             close (f->handle);
                    475:           } else {
                    476:             warn (LERR,"Open fail",EINP,4,5,f->handle);
                    477:           }
                    478:           list_release (f->data);
                    479:         }
                    480:         free (f->name);
                    481:       } else {
                    482:         warn (LERR,"Alloc fail",EINP,4,8,in_files);
                    483:       }
                    484:       free (f);
                    485:     } else {
                    486:       warn (LERR,"Alloc fail",EINP,4,2,in_files);
                    487:     }
                    488:   } else {
                    489:     warn (LERR,"Max file open",EINP,4,3,in_files);
                    490:   }
                    491:   return (NULL);
                    492: }
                    493: 
1.6       oskar     494: /* Check if a file with a given name is yet open.
                    495:  * The file name comparision is purely textual.
                    496:  * Precondition: name!=NULL
                    497:  * Return: file if found, NULL otherwise.
                    498:  */
1.1       oskar     499: file_descr* input_existfile (char *name)
                    500: {
                    501:   int i;
                    502:   i = in_files;
                    503:   while (--i >= 0) {
                    504:     if (!strcmp (name,inf[i]->name)) {
                    505:       return (inf[i]);
                    506:     }
                    507:   }
                    508:   return (NULL);
                    509: }
                    510: 
1.6       oskar     511: /* Mark all streams in a file to end soon, close the file itself
                    512:  * Precondition: f!=NULL
                    513:  */
1.14      oskar     514: static void input_endfile (file_descr *f)
1.1       oskar     515: {
                    516:   int i;
1.21      oskar     517:   stream_descr *s;
1.1       oskar     518:   i = in_streams;
                    519:   while (--i >= 0) {
1.21      oskar     520:     s = ins[i];
                    521:     if (s->fdescr == f) {
                    522:       s->endaction = ENDSTR_CLOSE;
1.1       oskar     523:     }
                    524:   }
1.5       oskar     525:   if (f->handle >= 0) {
                    526:     close (f->handle);
                    527:     f->handle = -1;
                    528:   }
1.1       oskar     529:   input_closefileifunused (f);
                    530: }
                    531: 
1.6       oskar     532: /* Close a file and release all corresponding data structures
                    533:  * Precondition: f!=NULL, f->u.*.stream[*]==NULL
                    534:  */
1.1       oskar     535: static void input_closefile (file_descr *f)
                    536: {
                    537:   int i;
                    538:   if (f->handle >= 0) {
                    539:     close (f->handle);
                    540:   }
                    541:   list_release (f->data);
                    542:   free (f->name);
                    543:   switch (f->content) {
                    544:     case ct_transport:
1.9       oskar     545:       releasechain (pmt_descr,f->u.ts.pat);
                    546:       releasechain (pmt_descr,f->u.ts.newpat);
                    547:       releasechain (tsauto_descr,f->u.ts.tsauto);
                    548:       releasechain (tssi_descr,f->u.ts.tssi);
1.1       oskar     549:       break;
                    550:     default:
                    551:       break;
                    552:   }
                    553:   i = in_files;
                    554:   while (--i >= 0) {
                    555:     if (inf[i] == f) {
                    556:       inf[i] = inf[--in_files];
1.13      oskar     557:       in_openfiles[f->content] -= 1;
1.1       oskar     558:       warn (LDEB,"Close file",EINP,11,1,in_files);
1.13      oskar     559:       free (f);
1.1       oskar     560:       return;
                    561:     }
                    562:   }
                    563:   warn (LERR,"Close lost file",EINP,11,2,in_files);
1.13      oskar     564:   free (f);
1.1       oskar     565: }
                    566: 
1.6       oskar     567: /* Close a file if there are no more data streams open.
                    568:  * If so, close any map streams.
                    569:  * Precondition: f!=NULL
                    570:  */
1.1       oskar     571: void input_closefileifunused (file_descr *f)
                    572: {
                    573:   int i;
1.13      oskar     574:   stream_descr *s;
                    575:   if (f->openstreams[sd_data] <= 0) {
                    576:     if (f->openstreams[sd_unparsedsi] > 0) {
                    577:       switch (f->content) {
                    578:         case ct_transport:
                    579:           i = MAX_STRPERTS;
                    580:           while ((f->openstreams[sd_unparsedsi] > 0)
                    581:               && (--i >= 0)) {
                    582:             s = ts_file_stream (f,i);
                    583:             if ((s != NULL)
                    584:              && (s->streamdata == sd_unparsedsi)
1.14      oskar     585:              && (s->endaction == ENDSTR_CLOSE)
1.13      oskar     586:              && (list_empty (s->ctrl))) {
                    587:               input_closestream (ts_file_stream (f,i));
                    588:             }
                    589:           }
                    590:           break;
                    591:         default:
                    592:           break;
                    593:       }
                    594:     }
1.16      oskar     595:     if (f->openstreams[sd_unparsedsi] <= 0) {
                    596:       if (f->openstreams[sd_map] > 0) {
                    597:         switch (f->content) {
                    598:           case ct_program:
                    599:             i = MAX_STRPERPS;
                    600:             while (--i >= 0) {
                    601:               if (f->u.ps.stream[i] != NULL) {
                    602:                 input_closestream (f->u.ps.stream[i]);
                    603:               }
1.1       oskar     604:             }
1.16      oskar     605:             break;
                    606:           case ct_transport:
                    607:             i = MAX_STRPERTS;
                    608:             while (--i >= 0) {
                    609:               s = ts_file_stream (f,i);
                    610:               if ((s != NULL)
                    611:                && (s->streamdata == sd_map)) {
                    612:                 input_closestream (ts_file_stream (f,i));
                    613:               }
1.1       oskar     614:             }
1.16      oskar     615:             break;
                    616:           default:
                    617:             warn (LERR,"unexpected map",EINP,12,1,f->content);
                    618:             break;
                    619:         }
1.1       oskar     620:       }
1.13      oskar     621:       input_closefile (f);
                    622:     }
1.1       oskar     623:   }
                    624: }
                    625: 
1.6       oskar     626: /* Add a target program to a stream's list of programs that contain it.
                    627:  * Precondition: s!=NULL, p!=NULL, p not in s->u.d.pdescr[*]
                    628:  * Postcondition: p in s->u.d.pdescr[*] not more than once.
                    629:  * Return: TRUE if successful, FALSE otherwise.
                    630:  */
1.1       oskar     631: boolean input_addprog (stream_descr *s,
                    632:     prog_descr *p)
                    633: {
                    634:   if (s->u.d.progs < MAX_PRGFORSTR) {
                    635:     s->u.d.pdescr[s->u.d.progs++] = p;
                    636:     warn (LDEB,"Add prog",EINP,10,2,s->u.d.progs);
                    637:     return (TRUE);
                    638:   }
                    639:   warn (LERR,"Max add prog",EINP,10,1,s->u.d.progs);
                    640:   return (FALSE);
                    641: }
                    642: 
1.6       oskar     643: /* Delete a target program from a stream's list of programs that contain it.
                    644:  * Precondition: s!=NULL, p!=NULL, p in s->u.d.pdescr[*] not more than once.
                    645:  * Postcondition: p not in s->u.d.pdescr[*]
                    646:  * Return: TRUE if successful, FALSE otherwise.
                    647:  */
1.1       oskar     648: boolean input_delprog (stream_descr *s,
                    649:     prog_descr *p)
                    650: {
                    651:   int i;
                    652:   i = s->u.d.progs;
                    653:   while (--i >= 0) {
                    654:     if (s->u.d.pdescr[i] == p) {
                    655:       s->u.d.pdescr[i] = s->u.d.pdescr[--(s->u.d.progs)];
                    656:       warn (LDEB,"Del prog",EINP,9,2,i);
                    657:       return (TRUE);
                    658:     }
                    659:   }
                    660:   warn (LERR,"Del lost prog",EINP,9,1,s->u.d.progs);
                    661:   return (FALSE);
                    662: }
                    663: 
1.6       oskar     664: /* Open a stream in a file. Allocate and initialize it.
                    665:  * sourceid is the stream's ID in the source file.
                    666:  * streamid is the PES packet stream id.
                    667:  * streamtype is the stream type according to ISO 13818-1 table 2-29.
                    668:  * isamap is TRUE for a map stream, FALSE for data stream.
                    669:  * mapstream is the superior correlated map stream.
                    670:  * Precondition: f!=NULL
                    671:  * Return: stream if successful, NULL otherwise
                    672:  */
1.1       oskar     673: stream_descr *input_openstream (file_descr *f,
                    674:     int sourceid,
                    675:     int streamid,
                    676:     int streamtype,
1.10      oskar     677:     streamdata_type streamdata,
1.1       oskar     678:     stream_descr *mapstream)
                    679: {
                    680:   stream_descr *s;
                    681:   warn (LIMP,"Open stream",EINP,5,sourceid,streamid);
                    682:   if (in_streams < MAX_INSTREAM) {
1.10      oskar     683:     switch (streamdata) {
                    684:       case sd_data:
                    685:         s = unionalloc (stream_descr,d);
                    686:         break;
                    687:       case sd_map:
                    688:         s = unionalloc (stream_descr,m);
                    689:         break;
                    690:       case sd_unparsedsi:
                    691:         s = unionalloc (stream_descr,usi);
                    692:         break;
                    693:       default:
                    694:         s = NULL;
                    695:         break;
1.1       oskar     696:     }
1.18      oskar     697:     if ((s != NULL)
                    698:      && ((s->autodescr = malloc (sizeof (descr_descr))) != NULL)
                    699:      && ((s->manudescr = malloc (sizeof (descr_descr))) != NULL)) {
1.1       oskar     700:       if (list_create (s->ctrl,MAX_CTRL_INB)) {
1.20      oskar     701:         if ((streamdata == sd_map) ?
                    702:             list_create (s->data,MAX_DATA_INBPSI) :
                    703:             streamtype_isvideo (streamtype) ?
1.4       oskar     704:             list_create (s->data,MAX_DATA_INBV) :
                    705:             streamtype_isaudio (streamtype) ?
                    706:             list_create (s->data,MAX_DATA_INBA) :
                    707:             list_create (s->data,MAX_DATA_INB)) {
1.10      oskar     708:           s->streamdata = streamdata;
                    709:           switch (streamdata) {
                    710:             case sd_data:
                    711:               s->u.d.mapstream = mapstream;
                    712:               s->u.d.discontinuity = FALSE;
                    713:               s->u.d.trigger = FALSE;
                    714:               s->u.d.mention = FALSE;
                    715:               s->u.d.has_clockref = FALSE;
                    716:               s->u.d.has_opcr = FALSE;
                    717:               s->u.d.conv.base = 0;
                    718:               s->u.d.conv.msec = 0;
                    719:               s->u.d.progs = 0;
1.13      oskar     720:               f->openstreams[streamdata] += 1;
                    721:               in_openstreams[streamdata] += 1;
1.10      oskar     722:               break;
                    723:             case sd_map:
                    724:               s->u.m.msectime = 0;
                    725:               s->u.m.conv.base = 0;
                    726:               s->u.m.conv.msec = 0;
                    727:               s->u.m.psi_length = 0;
1.13      oskar     728:               f->openstreams[streamdata] += 1;
                    729:               in_openstreams[streamdata] += 1;
1.10      oskar     730:               break;
                    731:             case sd_unparsedsi:
1.13      oskar     732:               f->openstreams[streamdata] += 1;
                    733:               in_openstreams[streamdata] += 1;
1.10      oskar     734:               break;
                    735:             default:
                    736:               break;
1.1       oskar     737:           }
                    738:           s->ctrl.ptr[0].length = 0;
                    739:           s->ctrl.ptr[0].pcr.valid = FALSE;
                    740:           s->ctrl.ptr[0].opcr.valid = FALSE;
1.4       oskar     741:           s->fdescr = f;
1.1       oskar     742:           s->sourceid = sourceid;
                    743:           s->stream_id = streamid;
                    744:           s->stream_type = streamtype;
1.28    ! oskar     745:           warn (LINF,"Open Streamtype",EINP,5,3,streamtype);
1.1       oskar     746:           s->version = 0xFF;
                    747:           s->conticnt = 0;
                    748:           s->endaction = ENDSTR_WAIT;
1.18      oskar     749:           clear_descrdescr (s->autodescr);
                    750:           clear_descrdescr (s->manudescr);
1.1       oskar     751:           ins[in_streams++] = s;
                    752:           return (s);
                    753:         }
                    754:         list_release (s->ctrl);
                    755:       }
                    756:       free (s);
                    757:     } else {
                    758:       warn (LERR,"Alloc fail",EINP,5,1,in_streams);
                    759:     }
                    760:   } else {
                    761:     warn (LERR,"Max stream open",EINP,5,2,in_streams);
                    762:   }
                    763:   return (NULL);
                    764: }
                    765: 
1.6       oskar     766: /* End a stream, if opportune.
                    767:  * Check all target programs this stream is in, close those that
                    768:  * do not contain another stream from the same file that is still running.
                    769:  * Note, that the stream stays open if there is at least one other stream
                    770:  * from the same file, that is still running together with it in a program.
                    771:  * Precondition: s!=NULL
                    772:  */
1.1       oskar     773: void input_endstream (stream_descr *s)
                    774: {
1.21      oskar     775:   int q, i;
                    776:   prog_descr *p;
                    777:   stream_descr *t;
                    778:   q = s->u.d.progs;
                    779:   while (--q >= 0) {
                    780:     p = s->u.d.pdescr[q];
                    781:     i = p->streams;
1.1       oskar     782:     while (--i >= 0) {
1.21      oskar     783:       t = p->stream[i];
                    784:       if ((!list_empty (t->ctrl))
                    785:        && (t->u.d.trigger)
                    786:        && (t->fdescr == s->fdescr)) {
1.1       oskar     787:         break;
                    788:       }
                    789:     }
                    790:     if (i < 0) {
1.21      oskar     791:       splice_closeprog (p);
1.1       oskar     792:     }
                    793:   }
                    794: }
                    795: 
1.6       oskar     796: /* End a stream.
                    797:  * Unlink it from all target programs, no matter what is left therein.
                    798:  * Precondition: s!=NULL
                    799:  */
1.1       oskar     800: void input_endstreamkill (stream_descr *s)
                    801: {
1.4       oskar     802:   int i;
                    803:   i = s->u.d.progs;
1.1       oskar     804:   while (--i >= 0) {
                    805:     prog_descr *p;
                    806:     p = s->u.d.pdescr[i];
                    807:     if (p->streams > 1) {
1.4       oskar     808:       unlink_streamprog (s,p);
1.1       oskar     809:     } else {
1.21      oskar     810:       splice_closeprog (p);
1.1       oskar     811:     }
                    812:   }
                    813: }
                    814: 
1.6       oskar     815: /* Close a stream.
                    816:  * Release all structures. If this is the only data stream related to the
                    817:  * corresponding map stream, close the map stream, too.
                    818:  * Precondition: s!=NULL
                    819:  */
1.1       oskar     820: void input_closestream (stream_descr *s)
                    821: {
                    822:   int i;
1.14      oskar     823:   warn (LIMP,"Close stream",EINP,6,0,s->sourceid);
1.1       oskar     824:   switch (s->fdescr->content) {
                    825:     case ct_packetized:
                    826:       s->fdescr->u.pes.stream = NULL;
                    827:       break;
                    828:     case ct_program:
                    829:       s->fdescr->u.ps.stream[s->sourceid] = NULL;
                    830:       break;
                    831:     case ct_transport:
1.6       oskar     832:       ts_file_stream (s->fdescr,s->sourceid) = NULL;
1.1       oskar     833:       break;
                    834:     default:
                    835:       warn (LERR,"Unknown contents",EINP,6,2,s->fdescr->content);
                    836:       break;
                    837:   }
1.13      oskar     838:   s->fdescr->openstreams[s->streamdata] -= 1;
                    839:   if (s->streamdata == sd_data) {
1.1       oskar     840:     switch (s->fdescr->content) {
                    841:       case ct_transport:
1.19      oskar     842:         if (s->u.d.mapstream != ts_file_stream (s->fdescr,0)) {
                    843:           i = MAX_STRPERTS;
                    844:           while ((--i >= 0)
                    845:             && ((ts_file_stream (s->fdescr,i) == NULL)
                    846:              || (ts_file_stream (s->fdescr,i)->streamdata != sd_data)
                    847:              || (ts_file_stream (s->fdescr,i)->u.d.mapstream
                    848:                 != s->u.d.mapstream))) {
                    849:           }
                    850:           if (i < 0) {
                    851:             if (s->u.d.mapstream->endaction == ENDSTR_CLOSE) {
                    852:               input_closestream (s->u.d.mapstream);
                    853:             }
1.1       oskar     854:           }
                    855:         }
                    856:         break;
                    857:       default:
                    858:         break;
                    859:     }
                    860:   }
                    861:   i = in_streams;
                    862:   while (--i >= 0) {
                    863:     if (ins[i] == s) {
                    864:       ins[i] = ins[--in_streams];
1.13      oskar     865:       in_openstreams[s->streamdata] -= 1;
1.1       oskar     866:       break;
                    867:     }
                    868:   }
                    869:   if (i < 0) {
                    870:     warn (LERR,"Close lost stream",EINP,6,1,in_streams);
                    871:   }
                    872:   list_release (s->data);
                    873:   list_release (s->ctrl);
1.18      oskar     874:   free (s->manudescr);
                    875:   free (s->autodescr);
1.1       oskar     876:   free (s);
                    877: }
                    878: 
1.6       oskar     879: /* Split data from raw input buffers to PES data stream buffers.
                    880:  * Return: TRUE, if something was processed, FALSE if no data/space available
                    881:  */
1.1       oskar     882: boolean split_something (void)
                    883: {
                    884:   int i;
                    885:   boolean r = FALSE;
                    886:   warn (LDEB,"Split some",EINP,7,0,in_files);
                    887:   i = in_files;
                    888:   while (--i >= 0) {
                    889:     switch (inf[i]->content) {
                    890:       case ct_packetized:
                    891:         if (split_pes (inf[i])) {
                    892:           r = TRUE;
                    893:         }
                    894:         break;
                    895:       case ct_program:
                    896:         if (split_ps (inf[i])) {
                    897:           r = TRUE;
                    898:         }
                    899:         break;
                    900:       case ct_transport:
                    901:         if (split_ts (inf[i])) {
                    902:           r = TRUE;
                    903:         }
                    904:         break;
                    905:       default:
                    906:         warn (LERR,"Unknown contents",EINP,7,3,inf[i]->content);
                    907:         /* error ? */
                    908:         break;
                    909:     }
                    910:   }
                    911:   return (r);
1.18      oskar     912: }
                    913: 
                    914: /* Check all files of type ct_transport for --si ranges.
                    915:  * Return: higher bound of range, if match is found, -1 otherwise
                    916:  */
                    917: int input_tssiinafilerange (int pid)
                    918: {
                    919:   int i;
                    920:   i = in_files;
                    921:   while (--i >= 0) {
                    922:     warn (LDEB,"TSSI in file",EINP,14,-1,inf[i]->content);
                    923:     if (inf[i]->content == ct_transport) {
                    924:       int h;
                    925:       h = split_unparsedsi (inf[i],pid);
                    926:       if (h >= 0) {
                    927:         warn (LDEB,"TSSI in file",EINP,14,pid,h);
                    928:         return (h);
                    929:       }
                    930:     }
                    931:   }
                    932:   warn (LDEB,"TSSI in file",EINP,14,pid,-1);
                    933:   return (-1);
1.1       oskar     934: }
                    935: 
1.6       oskar     936: /* Determine the appropriate file for a given handle
                    937:  * Return: file, if found, NULL otherwise
                    938:  */
1.1       oskar     939: file_descr *input_filehandle (int handle)
                    940: {
                    941:   int i;
                    942:   i = in_files;
                    943:   while (--i >= 0) {
                    944:     if (inf[i]->handle == handle) {
                    945:       return (inf[i]);
                    946:     }
                    947:   }
                    948:   return (NULL);
                    949: }
                    950: 
1.6       oskar     951: /* Check whether there is a pair of filerefnum and filename among the open
                    952:  * files, that fits the criteria.
                    953:  * Precondition: filename!=NULL or filerefnum>=0
                    954:  * Return: file, if found, NULL otherwise
                    955:  */
1.5       oskar     956: file_descr *input_filereferenced (int filerefnum,
                    957:     char *filename)
                    958: {
                    959:   int i;
1.21      oskar     960:   file_descr *f;
1.5       oskar     961:   i = in_files;
                    962:   while (--i >= 0) {
1.21      oskar     963:     f = inf[i];
1.5       oskar     964:     if ((filename == NULL)
1.21      oskar     965:         ? (filerefnum == f->filerefnum)
                    966:         : ((!strcmp (filename, f->name))
1.5       oskar     967:         && ((filerefnum < 0)
1.21      oskar     968:          || (filerefnum == f->filerefnum)))) {
                    969:       return (f);
1.5       oskar     970:     }
                    971:   }
                    972:   return (NULL);
                    973: }
                    974: 
1.6       oskar     975: /* Mark a file to be stopped.
                    976:  * If stopped, the file will be handled as if eof was encountered, the
                    977:  * next time there is data to be read from it.
                    978:  * Precondition: f!=NULL
                    979:  */
1.5       oskar     980: void input_stopfile (file_descr *f)
                    981: {
                    982:   f->stopfile = TRUE;
                    983: }
                    984: 
1.6       oskar     985: /* Read some data from the file into the raw buffer.
                    986:  * On eof or f->stopfile, end the file, or handle repeatitions or append,
                    987:  * if applicable.
                    988:  * Precondition: poll has stated data or error for the file
                    989:  */
1.1       oskar     990: void input_something (file_descr *f,
                    991:   boolean readable)
                    992: {
                    993:   int l, m;
                    994:   if (f != NULL) {
                    995:     if (f->handle >= 0) {
                    996:       warn (LDEB,"Something",EINP,0,1,f);
1.5       oskar     997:       if (readable && !f->stopfile) {
1.1       oskar     998:         l = list_freeinend (f->data);
                    999:         if (l > MAX_READ_IN) {
                   1000:           l = MAX_READ_IN;
                   1001:         }
                   1002:         m = list_free (f->data);
                   1003:         if (l > m) {
                   1004:           l = m;
                   1005:         }
                   1006:         l = read (f->handle,&f->data.ptr[f->data.in],l);
                   1007:       } else {
                   1008:         l = 0;
                   1009:       }
                   1010:       warn (LDEB,"Some Read",EINP,0,2,l);
                   1011:       if (l > 0) {
                   1012:         list_incr (f->data.in,f->data,l);
                   1013:       } else if (l == 0) {
1.5       oskar    1014:         f->stopfile = FALSE;
                   1015:         if (f->repeatitions != 0) {
                   1016:           if (f->repeatitions > 0) {
                   1017:             f->repeatitions -= 1;
                   1018:           }
                   1019:           if (lseek (f->handle,0,SEEK_CUR) > 255) {
                   1020:             lseek (f->handle,0,SEEK_SET);
                   1021:             warn (LIMP,"End Repeat",EINP,0,4,f);
                   1022:           } else {
                   1023:             warn (LWAR,"Repeat fail",EINP,0,5,f);
                   1024:           }
                   1025:         } else if (f->append_name != NULL) {
                   1026:           free (f->name);
                   1027:           f->name = f->append_name;
                   1028:           f->append_name = NULL;
                   1029:           if (f->append_filerefnum >= 0) {
                   1030:             f->filerefnum = f->append_filerefnum;
                   1031:           }
                   1032:           close (f->handle);
1.26      oskar    1033:           if ((f->handle = open (f->name,O_RDONLY|O_NONBLOCK)) >= 0) {
1.5       oskar    1034:             struct stat stat;
                   1035:             if (fstat (f->handle,&stat) == 0) {
                   1036:               f->st_mode = stat.st_mode;
                   1037:               if (!S_ISREG (f->st_mode)) {
                   1038:                 timed_io = TRUE;
1.7       oskar    1039:                 if (f->append_repeatitions != 0) {
                   1040:                   warn (LWAR,"Cannot repeat nonregular file",
                   1041:                         EINP,0,9,f->append_repeatitions);
                   1042:                 }
1.5       oskar    1043:                 f->repeatitions = 0;
                   1044:               } else {
                   1045:                 f->repeatitions = f->append_repeatitions;
1.2       oskar    1046:               }
1.12      oskar    1047:               configuration_changed = TRUE;
1.5       oskar    1048:               warn (LIMP,"End Append",EINP,0,f->repeatitions,f);
1.2       oskar    1049:             } else {
1.6       oskar    1050:               warn (LWAR,"Append fail",EINP,0,7,f);
1.5       oskar    1051:               input_endfile (f);
1.2       oskar    1052:             }
1.5       oskar    1053:           } else {
1.6       oskar    1054:             warn (LWAR,"Append fail",EINP,0,8,f);
1.1       oskar    1055:             input_endfile (f);
1.5       oskar    1056:           }
                   1057:         } else {
                   1058:           input_endfile (f);
1.1       oskar    1059:         }
                   1060:       } else {
                   1061:         /* read error */
                   1062:       }
                   1063:     }
                   1064:   }
                   1065: }
                   1066: 

LinuxTV legacy CVS <linuxtv.org/cvs>