Annotation of multiplexer/splicets.c, revision 1.24

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

LinuxTV legacy CVS <linuxtv.org/cvs>