Annotation of multiplexer/splice.c, revision 1.7

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:  Splice
                      9:  * Purpose: Service functions for specific Splice* modules
                     10:  *
                     11:  * This module provides functions needed for splicing
                     12:  * which are independent from the splice type.
                     13:  */
                     14: 
                     15: #include "global.h"
                     16: #include "error.h"
                     17: #include "splice.h"
                     18: #include "input.h"
                     19: #include "pes.h"
1.6       oskar      20: #include "descref.h"
1.1       oskar      21: 
1.5       oskar      22: t_msec next_psi_periodic;
                     23: t_msec psi_frequency_msec;
                     24: boolean psi_frequency_changed;
                     25: 
1.7     ! oskar      26: int configuration_on;
1.5       oskar      27: boolean configuration_changed;
1.7     ! oskar      28: boolean configuration_descr_changed;
1.5       oskar      29: const char *configuration_total = "Conf: progs: %d\n";
                     30: 
1.7     ! oskar      31: static modifydescr_descr *globalmodifydescr;
        !            32: 
1.5       oskar      33: boolean splice_init (void)
                     34: {
                     35:   psi_frequency_msec = 0;
                     36:   psi_frequency_changed = FALSE;
1.7     ! oskar      37:   configuration_on = 0;
        !            38:   globalmodifydescr = NULL;
1.5       oskar      39:   return (splice_specific_init ());
                     40: }
                     41: 
1.2       oskar      42: /* Connect a stream with a target program.
                     43:  * programnb denotes the program to connect,
                     44:  * stream is the stream to connect,
                     45:  * all further parameters are as with input_openstream.
                     46:  * If stream is NULL, open a stream first.
                     47:  * Add the stream to the programs list of streams and vice versa.
                     48:  * Precondition: f!=NULL
                     49:  * Return: the changed stream on success, the unchanged "stream" otherwise
                     50:  */
1.1       oskar      51: stream_descr *connect_streamprog (file_descr *f,
                     52:     int programnb,
                     53:     int sourceid,
                     54:     int streamid,
                     55:     int streamtype,
                     56:     stream_descr *stream,
                     57:     stream_descr *mapstream,
                     58:     boolean mention)
                     59: {
                     60:   stream_descr *s;
                     61:   prog_descr *p;
                     62:   if (stream == NULL) {
                     63:     s = input_openstream (f,sourceid,streamid<0?-streamid:streamid,
1.3       oskar      64:             streamtype,sd_data,mapstream);
1.1       oskar      65:   } else {
                     66:     if (streamid < 0) {
                     67:       streamid = -streamid;
1.4       oskar      68:       warn (LWAR,"Cannot refind sid",ESPC,1,1,streamid);
1.1       oskar      69:     }
                     70:     s = stream;
                     71:   }
                     72:   if (s != NULL) {
                     73:     p = splice_openprog (programnb);
                     74:     if (p != NULL) {
                     75:       if (input_addprog (s,p)) {
                     76:         if (splice_addstream (p,s,streamid>=0) > 0) {
                     77: /*
                     78:           if (p->pcr_pid < 0) {
                     79:             if (xxx) {
                     80:               p->pcr_pid = s->u.d.pid;
                     81:               s->u.d.has_clockref = TRUE;
                     82:               s->u.d.next_clockref = msec_now () - MAX_MSEC_PCRDIST;
                     83:             }
                     84:           }
                     85: */
                     86:           s->endaction = ENDSTR_WAIT;
                     87:           s->u.d.mention = mention;
                     88:           return (s);
                     89:         }
                     90:         input_delprog (s,p);
                     91:       }
                     92:       if (p->streams <= 0) {
                     93:         splice_closeprog (p);
                     94:       }
                     95:     }
                     96:     if (stream == NULL) {
                     97:       input_closestream (s);
                     98:     }
                     99:   }
                    100:   return (stream);
                    101: }
1.2       oskar     102: 
                    103: /* Unlink a stream from a target program.
                    104:  * If the stream comes out to be in no program then, close it.
                    105:  *   This function may be used only, if the program in question will either
                    106:  *   be non-empty after the call, or will be closed by the calling function.
                    107:  * Precondition: s!=NULL, p!=NULL
                    108:  */
1.1       oskar     109: void unlink_streamprog (stream_descr *s,
                    110:     prog_descr *p)
                    111: {
                    112:   splice_delstream (p,s);
                    113:   input_delprog (s,p);
                    114:   if (s->u.d.progs <= 0) {
                    115:     file_descr *f;
                    116:     f = s->fdescr;
                    117:     input_closestream (s);
                    118:     input_closefileifunused (f);
                    119:   }
                    120: }
1.2       oskar     121: 
                    122: /* Remove a stream from a target program.
                    123:  * Close stream and/or program, if not contained in another program or stream.
1.5       oskar     124:  * The input file is no longer automatic, because we do manual changes here.
1.2       oskar     125:  * Precondition: s!=NULL, p!=NULL, s is stream in target program p
                    126:  */
1.1       oskar     127: void remove_streamprog (stream_descr *s,
                    128:     prog_descr *p)
                    129: {
1.5       oskar     130:   s->fdescr->automatic = FALSE;
1.2       oskar     131:   if (p->streams > 1) {
                    132:     unlink_streamprog (s,p);
                    133:   } else {
                    134:     splice_closeprog (p);
1.1       oskar     135:   }
                    136: }
                    137: 
1.2       oskar     138: /* Find the right stream in a program
                    139:  * Precondition: p!=NULL
                    140:  * Return: stream, if found, NULL otherwise
                    141:  */
1.1       oskar     142: stream_descr *get_streamprog (prog_descr *p,
                    143:     int streamid)
                    144: {
                    145:   int i;
                    146:   i = p->streams;
                    147:   while (--i >= 0) {
                    148:     stream_descr *s;
                    149:     s = p->stream[i];
                    150:     if (s->stream_id == streamid) {
                    151:       return (s);
                    152:     }
                    153:   }
                    154:   return (NULL);
                    155: }
                    156: 
1.2       oskar     157: /* Find a free stream ID in a program that is equivalent to the given stream id
                    158:  * Precondition: p!=NULL
                    159:  * Return: Free ID, if found; given sid otherwise.
                    160:  */
1.1       oskar     161: int splice_findfreestreamid (prog_descr *p,
                    162:     int sid)
                    163: {
1.2       oskar     164:   int s0, s, n;
                    165:   s0 = sid;
1.1       oskar     166:   if ((sid >= PES_CODE_AUDIO)
                    167:    && (sid < (PES_CODE_AUDIO+PES_NUMB_AUDIO))) {
                    168:     s = PES_CODE_AUDIO;
1.2       oskar     169:     n = PES_NUMB_AUDIO;
1.1       oskar     170:   } else if ((sid >= PES_CODE_VIDEO)
                    171:    && (sid < (PES_CODE_VIDEO+PES_NUMB_VIDEO))) {
                    172:     s = PES_CODE_VIDEO;
1.2       oskar     173:     n = PES_NUMB_VIDEO;
1.1       oskar     174:   } else {
                    175:     s = sid;
1.2       oskar     176:     n = 1;
1.1       oskar     177:   }
                    178:   while (--n >= 0) {
                    179:     int i;
                    180:     i = p->streams;
                    181:     while ((--i >= 0)
1.2       oskar     182:         && (p->stream[i]->stream_id != s0)) {
1.1       oskar     183:     }
                    184:     if (i < 0) {
1.4       oskar     185:       warn (LIMP,"Found SID free",ESPC,2,sid,s0);
1.2       oskar     186:       return (s0);
1.1       oskar     187:     }
1.2       oskar     188:     s0 = s;
1.1       oskar     189:     s += 1;
                    190:   }
1.4       oskar     191:   warn (LIMP,"Found SID",ESPC,2,sid,sid);
1.2       oskar     192:   return (sid);
1.1       oskar     193: }
                    194: 
1.2       oskar     195: /* Check if there is a source pcr stream in a target program
                    196:  * Precondition: p!=NULL
                    197:  * Return: pcr-stream, if found; NULL otherwise.
                    198:  */
1.1       oskar     199: stream_descr *splice_findpcrstream (prog_descr *p)
                    200: {
                    201:   int i;
                    202:   pmt_descr *pmt;
1.4       oskar     203:   warn (LIMP,"Find PCR Stream",ESPC,3,0,p->program_number);
1.1       oskar     204:   i = p->streams;
                    205:   while (--i >= 0) {
                    206:     if (p->stream[i]->fdescr->content == ct_transport) {
                    207:       pmt = p->stream[i]->fdescr->u.ts.pat;
                    208:       while (pmt != NULL) {
                    209:         if (pmt->pcr_pid == p->stream[i]->sourceid) {
1.4       oskar     210:           warn (LIMP,"Found PCR Stream",ESPC,3,1,p->stream[i]->sourceid);
1.1       oskar     211:           return (p->stream[i]);
                    212:         }
                    213:         pmt = pmt->next;
                    214:       }
                    215:     }
                    216:   }
                    217:   return (NULL);
1.5       oskar     218: }
                    219: 
1.7     ! oskar     220: /* Print configuration of descriptors
        !           221:  * Precondition: manud!=NULL
        !           222:  */
        !           223: static void splice_descr_configuration (descr_descr *manud,
        !           224:     descr_descr *autod)
        !           225: {
        !           226:   int i, l;
        !           227:   byte *y;
        !           228:   i = NUMBER_DESCR;
        !           229:   while (--i >= 0) {
        !           230:     y = manud->refx[i];
        !           231:     if (y == NULL) {
        !           232:       if (autod != NULL) {
        !           233:         y = autod->refx[i];
        !           234:       }
        !           235:     } else if (y[1] == 0) {
        !           236:       y = NULL;
        !           237:     }
        !           238:     if (y != NULL) {
        !           239:       l = y[1];
        !           240:       fprintf (stderr, "Conf: descr:%02X len:%d data:", *y++, l);
        !           241:       while (--l >= 0) {
        !           242:         fprintf (stderr, "%02X", *++y);
        !           243:       }
        !           244:       fprintf (stderr, "\n");
        !           245:     }
        !           246:   }
        !           247: }
        !           248: 
1.5       oskar     249: /* Print configuration for one program
                    250:  * Precondition: p!=NULL
                    251:  */
                    252: void splice_one_configuration (prog_descr *p)
                    253: {
1.6       oskar     254:   int i, s;
                    255:   stump_descr *st;
1.5       oskar     256:   i = p->streams;
1.6       oskar     257:   s = 0;
                    258:   st = p->stump;
                    259:   while (st != NULL) {
                    260:     s += 1;
                    261:     st = st->next;
                    262:   }
                    263:   fprintf (stderr, "Conf: prog:%04X pmt:%04hX pcr:%04hX streams:%2d",
                    264:       p->program_number, p->pmt_pid, p->pcr_pid, i+s);
                    265:   if (s > 0) {
                    266:     fprintf (stderr, " (%d)", s);
                    267:   }
                    268:   fprintf (stderr, "\n");
1.7     ! oskar     269:   if (configuration_on > 1) {
        !           270:     splice_descr_configuration (&p->manudescr, NULL); /* Missing auto descr! */
        !           271:   }
1.5       oskar     272:   while (--i >= 0) {
                    273:     stream_descr *s;
                    274:     s = p->stream[i];
1.6       oskar     275:     fprintf (stderr, "Conf: stream:%04hX type:%02X sid:%02X "
1.5       oskar     276:       "file:%d source:%04hX num:%2d name:%s\n",
1.6       oskar     277:       s->u.d.pid, s->stream_type, s->stream_id,
1.5       oskar     278:       s->fdescr->content, s->sourceid, s->fdescr->filerefnum, s->fdescr->name);
1.7     ! oskar     279:     if (configuration_on > 1) {
        !           280:       splice_descr_configuration (s->manudescr, s->autodescr);
        !           281:     }
1.6       oskar     282:   }
                    283:   st = p->stump;
                    284:   while (st != NULL) {
                    285:     fprintf (stderr, "Conf: stream:%04hX type:%02X\n",
                    286:       st->pid, st->stream_type);
1.7     ! oskar     287:     if (configuration_on > 1) {
        !           288:       splice_descr_configuration (&st->manudescr, NULL);
        !           289:     }
1.6       oskar     290:     st = st->next;
1.5       oskar     291:   }
                    292: }
                    293: 
1.7     ! oskar     294: void splice_set_configuration (int on)
1.5       oskar     295: {
                    296:   configuration_on = on;
                    297:   configuration_changed = TRUE;
1.7     ! oskar     298: }
        !           299: 
        !           300: static void splice_modifydescriptor (descr_descr *md,
        !           301:     int dtag,
        !           302:     int dlength,
        !           303:     byte *data,
        !           304:     stream_descr *s)
        !           305: {
        !           306:   int i, j;
        !           307:   byte *t, *u;
        !           308:   if (dtag < 0) {
        !           309:     clear_descrdescr (md);
        !           310:   } else {
        !           311:     t = md->refx[dtag];
        !           312:     if ((dlength < 0)
        !           313:      || ((t != NULL)
        !           314:       && (t != &md->null[0]))) {
        !           315:       j = t[1]+2;
        !           316:       i = NUMBER_DESCR;
        !           317:       while (--i >= 0) {
        !           318:         if ((md->refx[i]-t) > 0) {
        !           319:           md->refx[i] -= j;
        !           320:         }
        !           321:       }
        !           322:       memmove (t,&t[j],sizeof(md->data)-(j+(t-&md->data[0])));
        !           323:     }
        !           324:     if (dlength == 0) {
        !           325:       t = &md->null[0];
        !           326:     } else if (dlength < 0) {
        !           327:       t = NULL;
        !           328:     } else {
        !           329:       i = NUMBER_DESCR;
        !           330:       t = &md->data[0];
        !           331:       while (--i >= 0) {
        !           332:         u = md->refx[i];
        !           333:         if (u != NULL) {
        !           334:           u = &u[u[1]+2];
        !           335:           if ((u-t) > 0) {
        !           336:             t = u;
        !           337:           }
        !           338:         }
        !           339:       }
        !           340:       if (t-&md->data[0] < 0) {
        !           341:         warn (LERR,"No space left",ESPC,5,2,t-&md->data[0]);
        !           342:         return;
        !           343:       }
        !           344:       if ((t-&md->data[0]+dlength+2-MAX_PSI_SIZE) > 0) {
        !           345:         warn (LWAR,"No space left",ESPC,5,1,t-&md->data[0]);
        !           346:         return;
        !           347:       }
        !           348:       t[0] = dtag;
        !           349:       t[1] = dlength;
        !           350:       memcpy (&t[2],data,dlength);
        !           351:     }
        !           352:     md->refx[dtag] = t;
        !           353:   }
        !           354:   if (s != NULL) {
        !           355:     i = s->u.d.progs;
        !           356:     while (--i >= 0) {
        !           357:       s->u.d.pdescr[i]->changed = TRUE;
        !           358:     }
        !           359:   }
        !           360: }
        !           361: 
        !           362: static void splice_modifydescrlater (int programnb,
        !           363:     short sid,
        !           364:     short pid,
        !           365:     int dtag,
        !           366:     int dlength,
        !           367:     byte *data)
        !           368: {
        !           369:   modifydescr_descr *l;
        !           370:   modifydescr_descr **pl;
        !           371:   pl = &globalmodifydescr;
        !           372:   l = *pl;
        !           373:   while (l != NULL) {
        !           374:     if ((programnb < 0) /* delete older matching entries */
        !           375:      || ((programnb == l->programnb)
        !           376:       && ((pid == 0)
        !           377:        || ((pid == l->pid)
        !           378:         && (sid == l->sid)
        !           379:         && ((dtag < 0)
        !           380:          || (dtag == l->dtag)))))) {
        !           381:       *pl = l->next;
        !           382:       free (l);
        !           383:     } else {
        !           384:       pl = &l->next;
        !           385:     }
        !           386:     l = *pl;
        !           387:   }
        !           388:   if ((dtag >= 0)
        !           389:    && (dlength >= 0)) { /* don't save modifiers, that delete */
        !           390:     if ((l = malloc (sizeof(modifydescr_descr))) != NULL) {
        !           391:       l->next = NULL;
        !           392:       l->programnb = programnb;
        !           393:       l->sid = sid;
        !           394:       l->pid = pid;
        !           395:       l->dtag = dtag;
        !           396:       l->dlength = dlength;
        !           397:       if (dlength > 0) {
        !           398:         memcpy (&l->data[0],data,dlength);
        !           399:       }
        !           400:       *pl = l; /* append at end of list */
        !           401:     } else {
        !           402:       warn (LERR,"Malloc fail",ETSC,12,1,programnb);
        !           403:     }
        !           404:   }
        !           405: }
        !           406: 
        !           407: /* For a new program and maybe stream or stump,
        !           408:  * check presence of applicable descriptors, that have been stored.
        !           409:  * All non-NULL parameters must be completely linked into p upon call!
        !           410:  * Precondition: p != NULL
        !           411:  */
        !           412: void splice_modifycheckmatch (int programnb,
        !           413:     prog_descr *p,
        !           414:     stream_descr *s,
        !           415:     stump_descr *st)
        !           416: {
        !           417:   modifydescr_descr *l;
        !           418:   modifydescr_descr **pl;
        !           419:   pl = &globalmodifydescr;
        !           420:   l = *pl;
        !           421:   while (l != NULL) {
        !           422:     if ((programnb == l->programnb)
        !           423:      && (((l->sid < 0)
        !           424:        && (l->pid < 0))
        !           425:       || ((l->pid > 0)
        !           426:        && (((s != NULL)
        !           427:          && (l->pid == s->u.d.pid))
        !           428:         || ((st != NULL)
        !           429:          && (l->pid = st->pid))))
        !           430:       || ((l->sid >= 0)
        !           431:        && (s != NULL)
        !           432:        && (l->sid == s->stream_id)))) {
        !           433:       splice_modifytargetdescrprog (p,programnb,
        !           434:           l->sid,l->pid,l->dtag,l->dlength,&l->data[0],st);
        !           435:       *pl = l->next;
        !           436:       free (l);
        !           437:     } else {
        !           438:       pl = &l->next;
        !           439:     }
        !           440:     l = *pl;
        !           441:   }
        !           442: }
        !           443: 
        !           444: /* Modify an entry in a manudescr struct.
        !           445:  */
        !           446: void splice_modifytargetdescrprog (prog_descr *p,
        !           447:     int programnb,
        !           448:     short sid,
        !           449:     short pid,
        !           450:     int dtag,
        !           451:     int dlength,
        !           452:     byte *data,
        !           453:     stump_descr *globstump)
        !           454: {
        !           455:   int i;
        !           456:   stream_descr *s;
        !           457:   stump_descr *st;
        !           458:   if (sid >= 0) {
        !           459:     if (p != NULL) {
        !           460:       i = p->streams;
        !           461:       while (--i >= 0) {
        !           462:         s = p->stream[i];
        !           463:         if (s->stream_id == sid) {
        !           464:           splice_modifydescriptor (s->manudescr,dtag,dlength,data,s);
        !           465:           configuration_descr_changed = TRUE;
        !           466:           return;
        !           467:         }
        !           468:       }
        !           469:     }
        !           470:     splice_modifydescrlater (programnb,sid,pid,dtag,dlength,data);
        !           471:   } else {
        !           472:     if (pid > 0) {
        !           473:       if (p != NULL) {
        !           474:         i = p->streams;
        !           475:         while (--i >= 0) {
        !           476:           s = p->stream[i];
        !           477:           if (s->u.d.pid == pid) {
        !           478:             splice_modifydescriptor (s->manudescr,dtag,dlength,data,s);
        !           479:             configuration_descr_changed = TRUE;
        !           480:             return;
        !           481:           }
        !           482:         }
        !           483:         st = p->stump;
        !           484:       } else {
        !           485:         st = globstump;
        !           486:       }
        !           487:       while (st != NULL) {
        !           488:         if ((st->pid == pid)
        !           489:          && (st->program_number == programnb)) {
        !           490:           splice_modifydescriptor (&st->manudescr,dtag,dlength,data,NULL);
        !           491:           if (p != NULL) {
        !           492:             p->changed = TRUE;
        !           493:           }
        !           494:           configuration_descr_changed = TRUE;
        !           495:           return;
        !           496:         }
        !           497:         st = st->next;
        !           498:       }
        !           499:       splice_modifydescrlater (programnb,sid,pid,dtag,dlength,data);
        !           500:     } else if (pid < 0) {
        !           501:       if (p != NULL) {
        !           502:         splice_modifydescriptor (&p->manudescr,dtag,dlength,data,NULL);
        !           503:         p->changed = TRUE;
        !           504:         configuration_descr_changed = TRUE;
        !           505:       } else {
        !           506:         splice_modifydescrlater (programnb,sid,pid,dtag,dlength,data);
        !           507:       }
        !           508:     } else {
        !           509:       if (p != NULL) {
        !           510:         i = p->streams;
        !           511:         while (--i >= 0) {
        !           512:           s = p->stream[i];
        !           513:           splice_modifydescriptor (s->manudescr,dtag,dlength,data,s);
        !           514:         }
        !           515:         splice_modifydescriptor (&p->manudescr,dtag,dlength,data,NULL);
        !           516:         configuration_descr_changed = TRUE;
        !           517:         st = p->stump;
        !           518:       } else {
        !           519:         st = globstump;
        !           520:       }
        !           521:       while (st != NULL) {
        !           522:         if (st->program_number == programnb) {
        !           523:           splice_modifydescriptor (&st->manudescr,dtag,dlength,data,NULL);
        !           524:         }
        !           525:         st = st->next;
        !           526:       }
        !           527:       splice_modifydescrlater (programnb,sid,pid,dtag,dlength,data);
        !           528:     }
        !           529:   }
1.1       oskar     530: }
                    531: 

LinuxTV legacy CVS <linuxtv.org/cvs>