Annotation of multiplexer/splice.c, revision 1.8

1.1       oskar       1: /*
                      2:  * ISO 13818 stream multiplexer
                      3:  * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
1.8     ! oskar       4:  * Author: Oskar Schirmer (oskar@scara.com)
1.1       oskar       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>