Annotation of multiplexer/splicets.c, revision 1.15

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 TS
                      9:  * Purpose: Generate transport stream.
                     10:  *
                     11:  * This module generates from the available input stream data (as
                     12:  * seperated by the split functions) the complete output stream.
                     13:  * It provides functions to handle programs for the resulting stream,
                     14:  * as these are output format dependent. Further, it accepts PSI data
                     15:  * just in time, validating it not earlier than with the arrival of
                     16:  * the corresponding payload at this stage.
                     17:  */
                     18: 
                     19: #include "global.h"
                     20: #include "crc.h"
                     21: #include "error.h"
                     22: #include "input.h"
                     23: #include "output.h"
                     24: #include "descref.h"
1.6       oskar      25: #include "splitts.h"
1.1       oskar      26: #include "pes.h"
                     27: #include "ts.h"
                     28: #include "splice.h"
                     29: #include "splicets.h"
                     30: 
                     31: const boolean splice_multipleprograms = TRUE;
                     32: 
                     33: static boolean changed_pat;
                     34: static int pat_section;
                     35: static const int last_patsection = 0;
                     36: static byte nextpat_version;
                     37: static byte pat_conticnt;
                     38: 
                     39: static int transportstreamid;
                     40: 
                     41: static int psi_size;
                     42: static int psi_done;
                     43: static byte psi_data [MAX_PSI_SIZE];
                     44: 
                     45: static byte unit_start;
                     46: static byte *conticnt;
                     47: static int psi_pid;
                     48: 
                     49: static int progs;
                     50: static prog_descr *prog [MAX_OUTPROG];
                     51: 
                     52: static int nextpid;
                     53: static stream_descr *outs [MAX_STRPERTS];
                     54: 
1.13      oskar      55: static stump_descr *globalstumps;
                     56: 
1.9       oskar      57: boolean splice_specific_init (void)
1.1       oskar      58: {
                     59:   progs = 0;
                     60:   nextpid = 0;
                     61:   memset (outs,0,sizeof(outs));
                     62:   changed_pat = TRUE;
                     63:   pat_section = 0;
                     64:   nextpat_version = 0;
                     65:   pat_conticnt = 0;
                     66:   psi_size = psi_done = 0;
                     67:   unit_start = TS_UNIT_START;
                     68:   transportstreamid = 0x4227;
1.13      oskar      69:   globalstumps = NULL;
1.1       oskar      70:   return (TRUE);
                     71: }
                     72: 
                     73: void splice_settransportstreamid (int tsid)
                     74: {
                     75:   transportstreamid = tsid;
                     76: }
                     77: 
1.11      oskar      78: void splice_setpsifrequency (t_msec freq)
1.1       oskar      79: {
                     80:   psi_frequency_msec = freq;
                     81:   psi_frequency_changed = TRUE;
                     82: }
                     83: 
                     84: static int findapid (stream_descr *s)
                     85: {
1.13      oskar      86:   byte okness = 2;
                     87:   int h;
1.1       oskar      88:   do {
1.2       oskar      89:     if ((nextpid < TS_PID_SPLICELO) || (nextpid >= TS_PID_SPLICEHI)) {
1.13      oskar      90:       warn (LDEB,"Next PID",ETSC,1,okness,nextpid);
                     91:       if (okness == 0) {
1.1       oskar      92:         warn (LERR,"No PID found",ETSC,2,1,0);
                     93:         return (0);
                     94:       }
1.13      oskar      95:       okness -= 1;
1.2       oskar      96:       nextpid = TS_PID_SPLICELO;
1.1       oskar      97:     } else {
1.13      oskar      98:       warn (LDEB,"Next PID",ETSC,2,okness,nextpid);
1.1       oskar      99:       nextpid += 1;
                    100:     }
1.13      oskar     101:     if (okness != 0) {
                    102:       h = input_tssiinafilerange (nextpid);
                    103:       warn (LDEB,"Next PID",ETSC,3,h,nextpid);
                    104:       if (h >= 0) {
                    105:         nextpid = h;
                    106:       }
                    107:     } else {
                    108:       h = -1;
                    109:     }
                    110:   } while ((h >= 0)
                    111:         || (outs[nextpid] != NULL));
1.1       oskar     112:   outs[nextpid] = s;
                    113:   warn (LDEB,"Next PID",ETSC,2,2,nextpid);
                    114:   return (nextpid);
                    115: }
                    116: 
1.9       oskar     117: void splice_all_configuration (void)
                    118: {
                    119:   int i;
1.15    ! oskar     120:   if (configuration_must_print) {
1.9       oskar     121:     i = progs;
                    122:     fprintf (stderr, configuration_total, i);
                    123:     while (--i >= 0) {
                    124:       splice_one_configuration (prog[i]);
                    125:     }
1.15    ! oskar     126:     configuration_was_printed;
1.9       oskar     127:   }
                    128: }
                    129: 
1.13      oskar     130: void splice_addsirange (file_descr *f,
                    131:     int lower,
                    132:     int upper)
                    133: {
                    134:   int i, r;
                    135:   tssi_descr *tssi;
                    136:   prog_descr *p;
                    137:   tssi = malloc (sizeof (tssi_descr));
                    138:   if (tssi != NULL) {
                    139:     if (ts_file_stream (f,TS_UNPARSED_SI) == NULL) {
                    140:       ts_file_stream (f,TS_UNPARSED_SI) = input_openstream (f,
                    141:               TS_UNPARSED_SI,0,0,sd_unparsedsi,NULL);
                    142:     }
                    143:     if (ts_file_stream (f,TS_UNPARSED_SI) != NULL) {
                    144:       tssi->next = f->u.ts.tssi;
                    145:       tssi->pid_low = lower;
                    146:       tssi->pid_high = upper;
                    147:       f->u.ts.tssi = tssi;
                    148:       r = upper; /* check for collision against existing PIDs, first sd_data */
                    149:       while (r >= lower) {
                    150:         stream_descr *s;
                    151:         s = outs[r];
                    152:         if ((s != NULL)
                    153:          && (s != PMT_STREAM)) {
                    154:           if (s->streamdata == sd_data) {
                    155:             i = findapid (s);
                    156:             if (input_tssiinafilerange (i) >= 0) { /* none free! */
                    157:               outs[i] = NULL;
                    158:             } else {
                    159:               int j;
                    160:               s->u.d.pid = i;
                    161:               j = s->u.d.progs;
                    162:               while (--j >= 0) {
                    163:                 p = s->u.d.pdescr[j];
                    164:                 p->changed = TRUE;
                    165:                 if (p->pcr_pid == r) {
                    166:                   p->pcr_pid = i;
                    167:                 }
                    168:               }
                    169:               configuration_changed = TRUE;
                    170:               outs[r] = NULL;
                    171:             }
                    172:           } else {
                    173:             warn (LERR,"Bad PID",ETSC,11,s->streamdata,r);
                    174:           }
                    175:         }
                    176:         r -= 1;
                    177:       }
                    178:       i = progs; /* ...then sd_map */
                    179:       while (--i >= 0) {
                    180:         p = prog[i];
                    181:         r = p->pmt_pid;
                    182:         if ((r >= lower)
                    183:          && (r <= upper)) {
                    184:           int q;
                    185:           q = findapid (PMT_STREAM);
                    186:           if (input_tssiinafilerange (q) >= 0) { /* none free! */
                    187:             outs[q] = NULL;
                    188:           } else {
                    189:             int j;
                    190:             outs[r] = NULL;
                    191:             j = i;
                    192:             while (--j >= 0) {
                    193:               if (prog[j]->pmt_pid == r) {
                    194:                 prog[j]->pmt_pid = q;
                    195:               }
                    196:             }
                    197:             p->pmt_pid = q;
                    198:             changed_pat = TRUE;
                    199:             configuration_changed = TRUE;
                    200:           }
                    201:         }
                    202:       }
                    203:     } else {
                    204:       free (tssi);
                    205:     }
                    206:   }
                    207: }
                    208: 
                    209: void splice_createstump (int programnb,
                    210:     short pid,
                    211:     byte styp)
                    212: {
                    213:   prog_descr *p;
                    214:   stump_descr **pst;
                    215:   stump_descr *st;
                    216:   p = splice_getprog (programnb);
                    217:   if (p != NULL) {
                    218:     configuration_changed = TRUE;
                    219:     p->changed = TRUE;
                    220:     pst = &(p->stump);
                    221:   } else {
                    222:     pst = &globalstumps;
                    223:   }
                    224:   st = *pst;
                    225:   while ((st != NULL)
                    226:       && ((st->pid != pid)
                    227:        || (st->program_number != programnb))) {
                    228:     st = st->next;
                    229:   }
                    230:   if (st == NULL) {
                    231:     st = malloc (sizeof(stump_descr));
                    232:     st->next = *pst;
                    233:     st->program_number = programnb;
                    234:     st->pid = pid;
                    235:     *pst = st;
                    236:   }
                    237:   st->stream_type = styp;
                    238:   clear_descrdescr (&(st->manudescr));
1.15    ! oskar     239:   splice_modifycheckmatch (programnb,p,NULL,st);
1.13      oskar     240: }
                    241: 
                    242: stump_descr *splice_getstumps (int programnb,
                    243:     short pid)
                    244: {
                    245:   prog_descr *p;
                    246:   stump_descr **pst;
                    247:   stump_descr *rl;
                    248:   rl = NULL;
                    249:   p = splice_getprog (programnb);
                    250:   if (p != NULL) {
                    251:     pst = &(p->stump);
                    252:   } else {
                    253:     pst = &globalstumps;
                    254:   }
                    255:   while (*pst != NULL) {
                    256:     stump_descr *st;
                    257:     st = *pst;
                    258:     if ((st->program_number == programnb)
                    259:      && ((pid < 0)
                    260:       || (pid == st->pid))) {
                    261:       st = *pst;
                    262:       *pst = st->next;
                    263:       st->next = rl;
                    264:       rl = st;
                    265:       if (p != NULL) {
                    266:         configuration_changed = TRUE;
                    267:         p->changed = TRUE;
                    268:       }
                    269:     } else {
                    270:       pst = &((*pst)->next);
                    271:     }
                    272:   }
                    273:   return (rl);
                    274: }
                    275: 
1.15    ! oskar     276: void splice_modifytargetdescriptor (int programnb,
        !           277:     short sid,
        !           278:     short pid,
        !           279:     int dtag,
        !           280:     int dlength,
        !           281:     byte *data)
        !           282: {
        !           283:   int i;
        !           284:   if (programnb < 0) {
        !           285:     i = progs;
        !           286:     while (--i >= 0) {
        !           287:       splice_modifytargetdescrprog (prog[i],
        !           288:           prog[i]->program_number,-1,0,-1,-1,NULL,globalstumps);
        !           289:     }
        !           290:     splice_modifytargetdescrprog (NULL,-1,-1,0,-1,-1,NULL,globalstumps);
        !           291:   } else {
        !           292:     splice_modifytargetdescrprog (splice_getprog (programnb),
        !           293:         programnb,sid,pid,dtag,dlength,data,globalstumps);
        !           294:   }
        !           295: }
        !           296: 
1.3       oskar     297: prog_descr *splice_getprog (int programnb)
                    298: {
                    299:   int i;
                    300:   i = progs;
                    301:   while (--i >= 0) {
                    302:     if (prog[i]->program_number == programnb) {
                    303:       return (prog[i]);
                    304:     }
                    305:   }
                    306:   return (NULL);
                    307: }
                    308: 
1.1       oskar     309: prog_descr *splice_openprog (int programnb)
                    310: {
                    311:   prog_descr *p;
                    312:   int pid;
                    313:   warn (LIMP,"Open prog",ETSC,1,0,programnb);
1.3       oskar     314:   p = splice_getprog (programnb);
1.1       oskar     315:   if (p == NULL) {
                    316:     if (progs < MAX_OUTPROG) {
                    317:       if ((pid = findapid (PMT_STREAM)) > 0) {
                    318:         if ((p = malloc(sizeof(prog_descr))) != NULL) {
                    319:           p->program_number = programnb;
                    320:           p->pcr_pid = -1;
                    321:           p->pmt_pid = pid;
                    322:           p->pmt_conticnt = 0;
                    323:           p->pmt_version = 0;
                    324:           p->changed = TRUE;
                    325:           p->pat_section = 0; /* more ? */
                    326:           p->streams = 0;
1.13      oskar     327:           p->stump = splice_getstumps (programnb,-1);
1.15    ! oskar     328:           clear_descrdescr (&p->manudescr);
1.1       oskar     329:           prog[progs++] = p;
                    330:           changed_pat = TRUE;
1.9       oskar     331:           configuration_changed = TRUE;
1.15    ! oskar     332:           splice_modifycheckmatch (programnb,p,NULL,NULL);
1.1       oskar     333:         } else {
                    334:           outs[pid] = NULL;
                    335:           warn (LERR,"Open prog",ETSC,1,1,0);
                    336:         }
                    337:       }
                    338:     } else {
                    339:       warn (LERR,"Max prog open",ETSC,1,2,0);
                    340:     }
                    341:   }
                    342:   return (p);
                    343: }
                    344: 
                    345: void splice_closeprog (prog_descr *p)
                    346: {
                    347:   int i, n;
                    348:   warn (LIMP,"Close prog",ETSC,3,0,p->program_number);
1.9       oskar     349:   configuration_changed = TRUE;
1.1       oskar     350:   while (p->streams > 0) {
1.3       oskar     351:     unlink_streamprog (p->stream[0],p);
1.1       oskar     352:   }
1.13      oskar     353:   releasechain (stump_descr,p->stump);
1.1       oskar     354:   n = -1;
                    355:   if (p->pmt_pid >= 0) {
                    356:     i = progs;
                    357:     while (--i >= 0) {
                    358:       if (prog[i]->pmt_pid == p->pmt_pid) {
                    359:         n += 1;
                    360:       }
                    361:     }
                    362:   }
                    363:   i = progs;
                    364:   while (--i >= 0) {
                    365:     if (prog[i] == p) {
                    366:       prog[i] = prog[--progs];
                    367:       if (n == 0) {
                    368:         outs[p->pmt_pid] = NULL;
                    369:       }
                    370:       free (p);
                    371:       changed_pat = TRUE;
                    372:       return;
                    373:     }
                    374:   }
                    375:   warn (LERR,"Close lost prog",ETSC,3,1,progs);
                    376: }
                    377: 
                    378: int splice_addstream (prog_descr *p,
                    379:     stream_descr *s,
                    380:     boolean force_sid)
                    381: {
                    382:   int pid = 0;
                    383:   warn (LIMP,"Add stream",ETSC,4,force_sid,s->stream_id);
                    384:   if (p->streams < MAX_STRPERPRG) {
                    385:     if ((pid = findapid (s)) > 0) {
                    386:       if (!force_sid) {
1.3       oskar     387:         s->stream_id = splice_findfreestreamid (p,s->stream_id);
1.1       oskar     388:       }
                    389:       p->stream[p->streams++] = s;
                    390:       p->changed = TRUE;
                    391:       s->u.d.pid = pid;
1.9       oskar     392:       configuration_changed = TRUE;
1.15    ! oskar     393:       splice_modifycheckmatch (p->program_number,p,s,NULL);
1.1       oskar     394:     }
                    395:   }
                    396:   return (pid);
                    397: }
                    398: 
                    399: boolean splice_delstream (prog_descr *p,
                    400:     stream_descr *s)
                    401: {
                    402:   int i;
                    403:   warn (LIMP,"Del stream",ETSC,5,0,s->u.d.pid);
1.9       oskar     404:   configuration_changed = TRUE;
1.1       oskar     405:   i = p->streams;
                    406:   while (--i >= 0) {
                    407:     if (p->stream[i] == s) {
                    408:       outs[s->u.d.pid] = NULL;
                    409:       p->stream[i] = p->stream[--(p->streams)];
                    410:       p->changed = TRUE;
                    411:       if (p->pcr_pid == s->u.d.pid) {
                    412:         p->pcr_pid = -1;
                    413:       }
                    414:       s->u.d.pid = 0;
                    415:       return (TRUE);
                    416:     }
                    417:   }
                    418:   warn (LERR,"Del lost stream",ETSC,5,1,p->streams);
                    419:   return (FALSE);
                    420: }
                    421: 
1.7       oskar     422: void process_finish (void)
                    423: {
                    424:   warn (LIMP,"Finish",ETSC,6,0,0);
                    425: }
                    426: 
1.1       oskar     427: static int make_patsection (int section,
                    428:     byte *dest)
                    429: {
                    430:   int i;
                    431:   byte *d;
                    432:   d = dest;
                    433:   *d++ = TS_TABLEID_PAT;
                    434:   d += 2;
                    435:   *d++ = transportstreamid >> 8;
                    436:   *d++ = (byte)transportstreamid;
                    437:   *d++ = 0xC0 | 0x01 | (nextpat_version << 1);
                    438:   *d++ = section;
                    439:   *d++ = last_patsection;
                    440:   i = progs;
                    441:   while (--i >= 0) {
                    442:     if (prog[i]->pat_section == section) {
                    443:       int x;
                    444:       x = prog[i]->program_number;
                    445:       *d++ = (x >> 8);
                    446:       *d++ = x;
                    447:       x = prog[i]->pmt_pid;
                    448:       *d++ = 0xE0 | (x >> 8);
                    449:       *d++ = x;
                    450:     }
                    451:   }
                    452:   i = d + CRC_SIZE - dest - TS_TRANSPORTID;
                    453:   dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
                    454:   dest[TS_SECTIONLEN+1] = i;
                    455:   crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
                    456:   return (i + TS_TRANSPORTID);
                    457: }
                    458: 
                    459: static int make_pmtsection (stream_descr *s,
                    460:     prog_descr *p,
                    461:     byte *dest)
                    462: {
                    463:   int i;
                    464:   byte *d;
1.13      oskar     465:   stump_descr *st;
1.1       oskar     466:   p->changed = FALSE;
                    467:   d = dest;
                    468:   *d++ = TS_TABLEID_PMT;
                    469:   d += 2;
                    470:   i = p->program_number;
                    471:   *d++ = (i >> 8);
                    472:   *d++ = i;
                    473:   *d++ = 0xC0 | 0x01 | (p->pmt_version << 1);
                    474:   p->pmt_version = (p->pmt_version+1) & 0x1F;
                    475:   *d++ = 0;
                    476:   *d++ = 0;
                    477:   if (p->pcr_pid < 0) {
                    478:     stream_descr *pcrs;
1.3       oskar     479:     pcrs = splice_findpcrstream (p);
1.1       oskar     480:     if (pcrs == NULL) {
                    481:       pcrs = s;
                    482:     }
                    483:     pcrs->u.d.has_clockref = TRUE;
                    484:     pcrs->u.d.next_clockref = msec_now () - MAX_MSEC_PCRDIST;
                    485:     p->pcr_pid = pcrs->u.d.pid;
1.9       oskar     486:     configuration_changed = TRUE;
1.1       oskar     487:   }
                    488:   i = p->pcr_pid;
                    489:   *d++ = 0xE0 | (i >> 8);
                    490:   *d++ = i;
                    491:   d += 2;
1.15    ! oskar     492:   i = NUMBER_DESCR;
        !           493:   while (--i > 0) {
        !           494:     byte *y;
        !           495:     y = p->manudescr.refx[i];
        !           496:     if ((y == NULL)
        !           497:      && (s->u.d.mapstream != NULL)) {
        !           498:       y = s->u.d.mapstream->autodescr->refx[i]; /* why this one? */
        !           499:     }
        !           500:     if (y != NULL) {
        !           501:       int yl = y[1];
        !           502:       if (yl != 0) {
        !           503:         yl += 2;
        !           504:         memcpy (d,y,yl);
        !           505:         d += yl;
1.1       oskar     506:       }
                    507:     }
                    508:   }
                    509:   i = d - dest - (TS_PMT_PILEN+2);
                    510:   dest[TS_PMT_PILEN] = 0xF0 | (i >> 8);
                    511:   dest[TS_PMT_PILEN+1] = i;
                    512:   i = p->streams;
                    513:   while (--i >= 0) {
                    514:     if (p->stream[i]->u.d.mention) {
                    515:       int x;
                    516:       byte *e;
                    517:       *d++ = p->stream[i]->stream_type;
                    518:       x = p->stream[i]->u.d.pid;
                    519:       *d++ = 0xE0 | (x >> 8);
                    520:       *d++ = x;
                    521:       d += 2;
                    522:       e = d;
1.14      oskar     523:       x = NUMBER_DESCR;
1.1       oskar     524:       while (--x > 0) {
                    525:         byte *y;
1.13      oskar     526:         y = p->stream[i]->manudescr->refx[x];
                    527:         if (y == NULL) {
                    528:           y = p->stream[i]->autodescr->refx[x];
                    529:         }
1.1       oskar     530:         if (y != NULL) {
1.15    ! oskar     531:           int yl = y[1];
        !           532:           if (yl != 0) {
        !           533:             yl += 2;
        !           534:             memcpy (d,y,yl);
        !           535:             d += yl;
        !           536:           }
1.1       oskar     537:         }
                    538:       }
                    539:       x = d - e;
                    540:       *--e = x;
                    541:       *--e = 0xF0 | (x >> 8);
                    542:     }
1.13      oskar     543:   }
                    544:   st = p->stump;
                    545:   while (st != NULL) {
                    546:     int x;
                    547:     byte *e;
                    548:     *d++ = st->stream_type;
                    549:     x = st->pid;
                    550:     *d++ = 0xE0 | (x >> 8);
                    551:     *d++ = x;
                    552:     d += 2;
                    553:     e = d;
1.14      oskar     554:     x = NUMBER_DESCR;
1.13      oskar     555:     while (--x > 0) {
                    556:       byte *y;
                    557:       y = st->manudescr.refx[x];
                    558:       if (y != NULL) {
1.15    ! oskar     559:         int yl = y[1];
        !           560:         if (yl != 0) {
        !           561:           yl += 2;
        !           562:           memcpy (d,y,yl);
        !           563:           d += yl;
        !           564:         }
1.13      oskar     565:       }
                    566:     }
                    567:     x = d - e;
                    568:     *--e = x;
                    569:     *--e = 0xF0 | (x >> 8);
                    570:     st = st->next;
1.1       oskar     571:   }
                    572:   i = d + CRC_SIZE - dest - TS_TRANSPORTID;
                    573:   dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
                    574:   dest[TS_SECTIONLEN+1] = i;
                    575:   crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
                    576:   return (i + TS_TRANSPORTID);
                    577: }
                    578: 
1.7       oskar     579: /* Check for generated psi data to-be-sent, select data source.
                    580:  * If PAT or PMT needs to be rebuild, do so. If PAT or PMT is (partially)
                    581:  * pending to be transmitted, select that to be packaged next. Otherwise
                    582:  * select data payload. Set pid, scramble mode and PES paket size.
                    583:  * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data.
                    584:  * Input: stream s, current ctrl fifo out c. 
                    585:  * Output: *pid, *scramble, *size (PES paket ~) for the stream to generate.
                    586:  */
                    587: static void procdata_check_psi (int *pid,
                    588:     byte *scramble,
                    589:     int *size,
                    590:     stream_descr *s,
                    591:     ctrl_buffer *c)
1.1       oskar     592: {
1.3       oskar     593:   t_msec now;
1.1       oskar     594:   if (psi_size > 0) {
1.7       oskar     595:     *pid = psi_pid;
                    596:     *scramble = 0;
                    597:     *size = psi_size;
1.1       oskar     598:   } else {
                    599:     if (unit_start != 0) {
                    600:       now = msec_now ();
                    601:       if ((psi_frequency_changed)
                    602:        || ((psi_frequency_msec > 0)
                    603:         && ((next_psi_periodic - now) <= 0))) {
1.7       oskar     604:         int l;
1.1       oskar     605:         changed_pat = TRUE;
                    606:         l = progs;
                    607:         while (--l >= 0) {
                    608:           prog[l]->changed = TRUE;
                    609:         }
                    610:         psi_frequency_changed = FALSE;
                    611:         next_psi_periodic = now + psi_frequency_msec;
                    612:       }
                    613:       if (changed_pat) {
                    614:         psi_pid = TS_PID_PAT;
                    615:         conticnt = &pat_conticnt;
                    616:         psi_data[0] = 0;
                    617:         psi_size = make_patsection (pat_section,&psi_data[1]) + 1;
                    618:         if (pat_section >= last_patsection) {
                    619:           changed_pat = FALSE;
                    620:           nextpat_version = (nextpat_version+1) & 0x1F;
                    621:           pat_section = 0;
                    622:         } else {
                    623:           pat_section += 1;
                    624:         }
                    625:         psi_done = 0;
1.7       oskar     626:         *pid = psi_pid;
                    627:         *scramble = 0;
                    628:         *size = psi_size;
1.1       oskar     629:       } else {
1.7       oskar     630:         int l;
1.1       oskar     631:         l = s->u.d.progs;
                    632:         while (--l >= 0) {
                    633:           if (s->u.d.pdescr[l]->changed) {
1.7       oskar     634:             int i;
                    635:             i = s->u.d.pdescr[l]->streams;
                    636:             while ((--i >= 0)
                    637:                 && (!s->u.d.pdescr[l]->stream[i]->u.d.mention)) {
1.1       oskar     638:             }
1.7       oskar     639:             if (i >= 0) {
1.1       oskar     640:               psi_pid = s->u.d.pdescr[l]->pmt_pid;
                    641:               conticnt = &s->u.d.pdescr[l]->pmt_conticnt;
                    642:               psi_data[0] = 0;
                    643:               psi_size = make_pmtsection (s,s->u.d.pdescr[l],&psi_data[1]) + 1;
                    644:               psi_done = 0;
1.7       oskar     645:               *pid = psi_pid;
                    646:               *scramble = 0;
                    647:               *size = psi_size;
                    648:               return;
1.1       oskar     649:             }
                    650:           }
                    651:         }
1.7       oskar     652:         s->data.ptr[c->index+PES_STREAM_ID] = s->stream_id;
                    653:         conticnt = &s->conticnt;
                    654:         *pid = s->u.d.pid;
                    655:         *scramble = c->scramble;
                    656:         *size = c->length;
1.1       oskar     657:       }
                    658:     } else {
1.7       oskar     659:       *pid = s->u.d.pid;
                    660:       *scramble = c->scramble;
                    661:       *size = c->length;
1.1       oskar     662:     }
                    663:   }
1.7       oskar     664: }
                    665: 
                    666: /* Check for adaption field items to be filled in.
                    667:  * First assume no adaption field is set and the complete packet except the
                    668:  * header is available for payload. Then check which adaption fields have
                    669:  * to be set and decrease the free space accordingly.
                    670:  * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data.
                    671:  * Input: stream s, current ctrl fifo out c.
                    672:  * Output: *adapt_flags1, *adapt_flags2, *adapt_ext_len.
                    673:  * Return: number of bytes of free space available for payload.
                    674:  */
                    675: static int procdata_adaptfield_flags (byte *adapt_flags1,
                    676:     byte *adapt_flags2,
                    677:     int *adapt_ext_len,
                    678:     stream_descr *s,
                    679:     ctrl_buffer *c)
                    680: {
                    681:   int space;
                    682:   *adapt_ext_len = 1;
                    683:   *adapt_flags2 = 0;
                    684:   *adapt_flags1 = 0;
                    685:   space = TS_PACKET_SIZE - TS_PACKET_HEADSIZE;
1.1       oskar     686:   if ((psi_size <= 0)
                    687:    && (s->u.d.discontinuity)) { /* o, not for contents, but PCR-disco ? */
                    688:     s->u.d.discontinuity = FALSE;
1.7       oskar     689:     *adapt_flags1 |= TS_ADAPT_DISCONTI;
1.1       oskar     690:   }
                    691:   if (0) {
1.7       oskar     692:     *adapt_flags1 |= TS_ADAPT_RANDOMAC;
1.1       oskar     693:   }
                    694:   if (0) {
1.7       oskar     695:     *adapt_flags1 |= TS_ADAPT_PRIORITY;
1.1       oskar     696:   }
                    697:   if ((psi_size <= 0)
                    698:    && (s->u.d.has_clockref)
                    699:    && ((c->pcr.valid)
1.2       oskar     700:     || (s->u.d.next_clockref - (c->msecpush + s->u.d.delta) <= 0))) {
1.7       oskar     701:     *adapt_flags1 |= TS_ADAPT_PCRFLAG;
                    702:     space -= 6;
1.1       oskar     703:   }
                    704:   if ((psi_size <= 0)
1.4       oskar     705:    && ((c->opcr.valid)
                    706:     || ((!s->u.d.has_opcr)
                    707:      && (c->pcr.valid)))) {
1.7       oskar     708:     *adapt_flags1 |= TS_ADAPT_OPCRFLAG;
                    709:     space -= 6;
1.1       oskar     710:   }
                    711:   if (0) {
1.7       oskar     712:     *adapt_flags1 |= TS_ADAPT_SPLICING;
                    713:     space -= 1;
1.1       oskar     714:   }
                    715:   if (0) {
1.7       oskar     716:     int privdata;
                    717:     *adapt_flags1 |= TS_ADAPT_TPRIVATE;
1.1       oskar     718:     privdata = 0;
1.7       oskar     719:     space -= (privdata + 1);
1.1       oskar     720:   }
                    721:   if (0) {
1.7       oskar     722:     *adapt_flags2 |= TS_ADAPT2_LTWFLAG;
                    723:     *adapt_ext_len += 2;
1.1       oskar     724:   }
                    725:   if (0) {
1.7       oskar     726:     *adapt_flags2 |= TS_ADAPT2_PIECEWRF;
                    727:     *adapt_ext_len += 3;
1.1       oskar     728:   }
                    729:   if (0) {
1.7       oskar     730:     *adapt_flags2 |= TS_ADAPT2_SEAMLESS;
                    731:     *adapt_ext_len += 5;
1.1       oskar     732:   }
1.7       oskar     733:   if (*adapt_flags2 != 0) {
                    734:     *adapt_flags1 |= TS_ADAPT_EXTENSIO;
                    735:     space -= *adapt_ext_len;
1.1       oskar     736:   }
1.7       oskar     737:   if (*adapt_flags1 != 0) {
                    738:     space -= 2;
1.1       oskar     739:   }
1.7       oskar     740:   return (space);
                    741: }
                    742: 
                    743: /* Adjust size of adaption field against size of payload. Set flags.
                    744:  * Input: *space (number of bytes of free space available for payload),
                    745:  *   *adapt_flags1, size (number of bytes left to be sent).
                    746:  * Output: *space (corrected in case of padding is done via adaption field),
                    747:  *   *adapt_field_ctrl.
                    748:  * Return: Number of bytes of payload to be inserted into THIS packet.
                    749:  */
                    750: static int procdata_adaptfield_frame (int *space,
                    751:     byte *adapt_field_ctrl,
                    752:     byte adapt_flags1,
                    753:     int size)
                    754: {
                    755:   int payload;
                    756:   if (size < *space) {
                    757:     payload = size;
1.1       oskar     758:     if (adapt_flags1 == 0) {
1.7       oskar     759:       *space -= 1;
                    760:       if (*space > payload) {
                    761:         *space -= 1;
1.1       oskar     762:       }
                    763:     }
1.7       oskar     764:     *adapt_field_ctrl = TS_AFC_BOTH;
1.1       oskar     765:   } else {
1.7       oskar     766:     payload = *space;
                    767:     if (payload == 0) {
                    768:       *adapt_field_ctrl = TS_AFC_ADAPT;
1.1       oskar     769:     } else if (adapt_flags1 == 0) {
1.7       oskar     770:       *adapt_field_ctrl = TS_AFC_PAYLD;
1.1       oskar     771:     } else {
1.7       oskar     772:       *adapt_field_ctrl = TS_AFC_BOTH;
1.1       oskar     773:     }
                    774:   }
1.7       oskar     775:   return (payload);
                    776: }
                    777: 
                    778: /* Generate packet header.
                    779:  * Keep track of continuity counter (which is selected in procdata_check_psi).
                    780:  * Precondition: d!=NULL (data destination).
                    781:  * Input: pid, scramble, adaption_field_ctrl.
                    782:  * Return: d (increased by header size).
                    783:  */
                    784: static byte *procdata_syn_head (byte *d,
                    785:     int pid,
                    786:     byte scramble,
                    787:     byte adapt_field_ctrl)
                    788: {
1.1       oskar     789:   *d++ = TS_SYNC_BYTE;
1.7       oskar     790:   warn (LSEC,"Splice unitstart",ETSC,7,1,unit_start);
                    791:   warn (LSEC,"Splice PID",ETSC,7,2,pid);
1.1       oskar     792:   *d++ = (0 << 7) /* transport_error_indicator */
                    793:        | unit_start
                    794:        | (0 << 5) /* transport_priority */
                    795:        | (pid >> 8);
                    796:   *d++ = pid;
                    797:   *d++ = (scramble << 6)
                    798:        | adapt_field_ctrl
                    799:        | *conticnt;
1.7       oskar     800:   warn (LSEC,"Splice continuity cnt",ETSC,7,3,*conticnt);
1.1       oskar     801:   if (adapt_field_ctrl & TS_AFC_PAYLD) {
                    802:     *conticnt = (*conticnt+1) & 0x0F;
                    803:   }
1.7       oskar     804:   return (d);
                    805: }
                    806: 
                    807: /* Generate adpation field.
                    808:  * This MUST match the calculations in procdata_adaptfield_flags.
                    809:  * Precondition: s!=NULL.
                    810:  * Input: s (stream), c (current ctrl fifo out), d (data destination),
                    811:  *   padding (number of padding bytes needed), payload (number of payload bytes
                    812:  *   to insert), adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len.
                    813:  * Return: d (increased by adaption field size).
                    814:  */
                    815: static byte *procdata_syn_adaptfield (stream_descr *s,
                    816:     ctrl_buffer *c,
                    817:     byte *d,
                    818:     int padding,
                    819:     int payload,
                    820:     byte adapt_field_ctrl,
                    821:     byte adapt_flags1,
                    822:     byte adapt_flags2,
                    823:     int adapt_ext_len)
                    824: {
1.1       oskar     825:   if (adapt_field_ctrl & TS_AFC_ADAPT) {
1.7       oskar     826:     if ((*d++ = (TS_PACKET_SIZE - TS_PACKET_FLAGS1) - payload) != 0) {
1.1       oskar     827:       *d++ = adapt_flags1;
                    828:       if (adapt_flags1 & TS_ADAPT_PCRFLAG) {
                    829:         clockref pcr;
1.2       oskar     830:         msec2cref (&s->u.d.conv,c->msecpush + s->u.d.delta,&pcr);
1.1       oskar     831:         *d++ = (pcr.base >> 25) | (pcr.ba33 << 7);
                    832:         *d++ = pcr.base >> 17;
                    833:         *d++ = pcr.base >> 9;
                    834:         *d++ = pcr.base >> 1;
                    835:         *d++ = (pcr.base << 7) | (pcr.ext >> 8) | 0x7E;
                    836:         *d++ = pcr.ext;
                    837:         s->u.d.next_clockref =
1.2       oskar     838:           (c->msecpush + s->u.d.delta) + MAX_MSEC_PCRDIST;
1.1       oskar     839:         c->pcr.valid = FALSE;
                    840:       }
                    841:       if (adapt_flags1 & TS_ADAPT_OPCRFLAG) {
1.4       oskar     842:         clockref *opcr;
                    843:         if (c->opcr.valid) {
                    844:           opcr = &c->opcr;
                    845:         } else {
                    846:           opcr = &c->pcr;
                    847:         }
                    848:         *d++ = (opcr->base >> 25) | (opcr->ba33 << 7);
                    849:         *d++ = opcr->base >> 17;
                    850:         *d++ = opcr->base >> 9;
                    851:         *d++ = opcr->base >> 1;
                    852:         *d++ = (opcr->base << 7) | (opcr->ext >> 8) | 0x7E;
                    853:         *d++ = opcr->ext;
                    854:         opcr->valid = FALSE;
1.1       oskar     855:       }
                    856:       if (adapt_flags1 & TS_ADAPT_SPLICING) {
                    857:       }
                    858:       if (adapt_flags1 & TS_ADAPT_TPRIVATE) {
                    859:       }
                    860:       if (adapt_flags1 & TS_ADAPT_EXTENSIO) {
                    861:         *d++ = adapt_ext_len;
                    862:         *d++ = adapt_flags2 | 0x1F;
1.5       oskar     863:         if (adapt_flags2 & TS_ADAPT2_LTWFLAG) {
1.1       oskar     864:         }
1.5       oskar     865:         if (adapt_flags2 & TS_ADAPT2_PIECEWRF) {
1.1       oskar     866:         }
1.5       oskar     867:         if (adapt_flags2 & TS_ADAPT2_SEAMLESS) {
1.1       oskar     868:         }
                    869:       }
                    870:     }
1.7       oskar     871:     if (padding > 0) {
                    872:       warn (LSEC,"Splice padding",ETSC,8,1,padding);
                    873:       memset (d,-1,padding);
                    874:       d += padding;
1.1       oskar     875:     }
                    876:   }
1.7       oskar     877:   return (d);
                    878: }
                    879: 
                    880: /* Generate payload portion.
                    881:  * Insert the appropriate payload (either PSI or data), check whether payload
                    882:  * from this PES packet or section is left.
                    883:  * Precondition: s!=NULL.
                    884:  * Input: s (stream), c (current ctrl fifo out), d (data destination),
                    885:  *   payload (number of payload bytes to insert).
                    886:  * Return: processed stream s, if there is more data from the current PES
                    887:  *   packet to be processed, NULL otherwise.
                    888:  */
                    889: static stream_descr *procdata_syn_payload (stream_descr *s,
                    890:     ctrl_buffer *c,
                    891:     byte *d,
                    892:     int payload)
                    893: {
                    894:   if (payload > 0) {
1.1       oskar     895:     if (psi_size > 0) {
1.7       oskar     896:       memcpy (d,&psi_data[psi_done],payload);
                    897:       if (payload < psi_size) {
                    898:         warn (LSEC,"Splice PSI Data",ETSC,9,s->stream_id,payload);
                    899:         psi_done += payload;
                    900:         psi_size -= payload;
1.1       oskar     901:         unit_start = 0;
                    902:       } else {
1.7       oskar     903:         warn (LINF,"Splice PSI Done",ETSC,9,s->stream_id,payload);
1.1       oskar     904:         psi_done = psi_size = 0;
                    905:         unit_start = TS_UNIT_START;
                    906:       }
                    907:     } else {
1.7       oskar     908:       memcpy (d,&s->data.ptr[c->index],payload);
                    909:       if (payload < c->length) {
                    910:         warn (LSEC,"Splice Data",ETSC,9,s->stream_id,payload);
                    911:         c->length -= payload;
                    912:         s->data.out = (c->index += payload);
1.1       oskar     913:         unit_start = 0;
                    914:       } else {
1.7       oskar     915:         warn (LINF,"Splice Done",ETSC,9,s->stream_id,payload);
1.1       oskar     916:         list_incr (s->ctrl.out,s->ctrl,1);
                    917:         if (list_empty (s->ctrl)) {
                    918:           s->data.out = s->data.in;
                    919:         } else {
                    920:           s->data.out = s->ctrl.ptr[s->ctrl.out].index;
                    921:         }
                    922:         unit_start = TS_UNIT_START;
1.7       oskar     923:         return (NULL);
1.1       oskar     924:       }
                    925:     }
                    926:   }
                    927:   return (s);
1.7       oskar     928: }
                    929: 
                    930: /* Process unparsed si data and generate output.
                    931:  * Take one TS paket, copy it to output stream data buffer.
                    932:  * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_unparsedsi,
                    933:  *   s->ctrl.ptr[s->ctrl.out].length==TS_PACKET_SIZE, d!=NULL.
                    934:  */
                    935: static void proc_unparsedsi (stream_descr *s,
                    936:     byte *d)
                    937: {
1.12      oskar     938:   warn (LINF,"Splice Unparsed SI",ETSC,10,s->streamdata,s->u.usi.delta);
                    939:   warn (LDEB,"Splice Unparsed SI",ETSC,10,s->stream_id,s->sourceid);
1.7       oskar     940:   memcpy (d,&s->data.ptr[s->ctrl.ptr[s->ctrl.out].index],TS_PACKET_SIZE);
                    941:                 /* check if ==  s->ctrl.ptr[s->ctrl.out].length); ? */
                    942:   list_incr (s->ctrl.out,s->ctrl,1);
                    943:   if (list_empty (s->ctrl)) {
1.12      oskar     944:     s->data.out = s->data.in;
1.10      oskar     945:     input_closefileifunused (s->fdescr);
1.7       oskar     946:   } else {
                    947:     s->data.out = s->ctrl.ptr[s->ctrl.out].index;
                    948:   }
                    949: }
                    950: 
                    951: stream_descr *process_something (stream_descr *s)
                    952: {
                    953:   byte *d;
                    954:   int pid;
                    955:   byte scramble;
                    956:   int size;
                    957:   ctrl_buffer *c;
                    958:   int payload;
                    959:   int space;
                    960:   int adapt_ext_len;
                    961:   byte adapt_field_ctrl;
                    962:   byte adapt_flags1, adapt_flags2;
                    963:   warn (LDEB,"Splice TS",ETSC,0,0,s->ctrl.out);
                    964:   switch (s->streamdata) {
                    965:     case sd_data:
                    966:       c = &s->ctrl.ptr[s->ctrl.out];
                    967:       procdata_check_psi (&pid, &scramble, &size, s, c);
                    968:       d = output_pushdata (TS_PACKET_SIZE,c->msecpush + s->u.d.delta);
                    969:       if (d == NULL) {
                    970:         return (s);
                    971:       }
                    972:       space = procdata_adaptfield_flags (&adapt_flags1, &adapt_flags2,
                    973:           &adapt_ext_len, s, c);
1.8       oskar     974:       payload = procdata_adaptfield_frame (&space, &adapt_field_ctrl,
                    975:           adapt_flags1, size);
1.7       oskar     976:       d = procdata_syn_head (d, pid, scramble, adapt_field_ctrl);
1.8       oskar     977:       d = procdata_syn_adaptfield (s, c, d, space-payload, payload,
                    978:           adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len);
1.7       oskar     979:       return (procdata_syn_payload (s, c, d, payload));
                    980:       break;
                    981:     case sd_map:
                    982:       validate_mapref (s);
                    983:       return (NULL);
                    984:       break;
                    985:     case sd_unparsedsi:
                    986:       c = &s->ctrl.ptr[s->ctrl.out];
                    987:       d = output_pushdata (TS_PACKET_SIZE,c->msecpush + s->u.usi.delta);
                    988:       if (d == NULL) {
                    989:         return (s);
                    990:       }
                    991:       proc_unparsedsi (s,d);
                    992:       return (NULL);
                    993:       break;
                    994:     default:
                    995:       return (NULL);
                    996:       break;
                    997:   }
1.1       oskar     998: }
                    999: 

LinuxTV legacy CVS <linuxtv.org/cvs>