Annotation of multiplexer/splice.c, revision 1.9

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

LinuxTV legacy CVS <linuxtv.org/cvs>