Annotation of multiplexer/splicets.c, revision 1.11

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.9       oskar      55: boolean splice_specific_init (void)
1.1       oskar      56: {
                     57:   progs = 0;
                     58:   nextpid = 0;
                     59:   memset (outs,0,sizeof(outs));
                     60:   changed_pat = TRUE;
                     61:   pat_section = 0;
                     62:   nextpat_version = 0;
                     63:   pat_conticnt = 0;
                     64:   psi_size = psi_done = 0;
                     65:   unit_start = TS_UNIT_START;
                     66:   transportstreamid = 0x4227;
                     67:   return (TRUE);
                     68: }
                     69: 
                     70: void splice_settransportstreamid (int tsid)
                     71: {
                     72:   transportstreamid = tsid;
                     73: }
                     74: 
1.11    ! oskar      75: void splice_setpsifrequency (t_msec freq)
1.1       oskar      76: {
                     77:   psi_frequency_msec = freq;
                     78:   psi_frequency_changed = TRUE;
                     79: }
                     80: 
                     81: static int findapid (stream_descr *s)
                     82: {
                     83:   boolean ok = TRUE;
                     84:   do {
1.2       oskar      85:     if ((nextpid < TS_PID_SPLICELO) || (nextpid >= TS_PID_SPLICEHI)) {
1.1       oskar      86:       if (!ok) {
                     87:         warn (LERR,"No PID found",ETSC,2,1,0);
                     88:         return (0);
                     89:       }
                     90:       ok = FALSE;
1.2       oskar      91:       nextpid = TS_PID_SPLICELO;
1.1       oskar      92:     } else {
                     93:       nextpid += 1;
                     94:     }
                     95:   } while (outs[nextpid] != NULL);
                     96:   outs[nextpid] = s;
                     97:   warn (LDEB,"Next PID",ETSC,2,2,nextpid);
                     98:   return (nextpid);
                     99: }
                    100: 
1.9       oskar     101: void splice_all_configuration (void)
                    102: {
                    103:   int i;
                    104:   if (configuration_on && configuration_changed) {
                    105:     i = progs;
                    106:     fprintf (stderr, configuration_total, i);
                    107:     while (--i >= 0) {
                    108:       splice_one_configuration (prog[i]);
                    109:     }
                    110:     configuration_changed = FALSE;
                    111:   }
                    112: }
                    113: 
1.3       oskar     114: prog_descr *splice_getprog (int programnb)
                    115: {
                    116:   int i;
                    117:   i = progs;
                    118:   while (--i >= 0) {
                    119:     if (prog[i]->program_number == programnb) {
                    120:       return (prog[i]);
                    121:     }
                    122:   }
                    123:   return (NULL);
                    124: }
                    125: 
1.1       oskar     126: prog_descr *splice_openprog (int programnb)
                    127: {
                    128:   prog_descr *p;
                    129:   int pid;
                    130:   warn (LIMP,"Open prog",ETSC,1,0,programnb);
1.3       oskar     131:   p = splice_getprog (programnb);
1.1       oskar     132:   if (p == NULL) {
                    133:     if (progs < MAX_OUTPROG) {
                    134:       if ((pid = findapid (PMT_STREAM)) > 0) {
                    135:         if ((p = malloc(sizeof(prog_descr))) != NULL) {
                    136:           p->program_number = programnb;
                    137:           p->pcr_pid = -1;
                    138:           p->pmt_pid = pid;
                    139:           p->pmt_conticnt = 0;
                    140:           p->pmt_version = 0;
                    141:           p->changed = TRUE;
                    142:           p->pat_section = 0; /* more ? */
                    143:           p->streams = 0;
                    144:           prog[progs++] = p;
                    145:           changed_pat = TRUE;
1.9       oskar     146:           configuration_changed = TRUE;
1.1       oskar     147:         } else {
                    148:           outs[pid] = NULL;
                    149:           warn (LERR,"Open prog",ETSC,1,1,0);
                    150:         }
                    151:       }
                    152:     } else {
                    153:       warn (LERR,"Max prog open",ETSC,1,2,0);
                    154:     }
                    155:   }
                    156:   return (p);
                    157: }
                    158: 
                    159: void splice_closeprog (prog_descr *p)
                    160: {
                    161:   int i, n;
                    162:   warn (LIMP,"Close prog",ETSC,3,0,p->program_number);
1.9       oskar     163:   configuration_changed = TRUE;
1.1       oskar     164:   while (p->streams > 0) {
1.3       oskar     165:     unlink_streamprog (p->stream[0],p);
1.1       oskar     166:   }
                    167:   n = -1;
                    168:   if (p->pmt_pid >= 0) {
                    169:     i = progs;
                    170:     while (--i >= 0) {
                    171:       if (prog[i]->pmt_pid == p->pmt_pid) {
                    172:         n += 1;
                    173:       }
                    174:     }
                    175:   }
                    176:   i = progs;
                    177:   while (--i >= 0) {
                    178:     if (prog[i] == p) {
                    179:       prog[i] = prog[--progs];
                    180:       if (n == 0) {
                    181:         outs[p->pmt_pid] = NULL;
                    182:       }
                    183:       free (p);
                    184:       changed_pat = TRUE;
                    185:       return;
                    186:     }
                    187:   }
                    188:   warn (LERR,"Close lost prog",ETSC,3,1,progs);
                    189: }
                    190: 
                    191: int splice_addstream (prog_descr *p,
                    192:     stream_descr *s,
                    193:     boolean force_sid)
                    194: {
                    195:   int pid = 0;
                    196:   warn (LIMP,"Add stream",ETSC,4,force_sid,s->stream_id);
                    197:   if (p->streams < MAX_STRPERPRG) {
                    198:     if ((pid = findapid (s)) > 0) {
                    199:       if (!force_sid) {
1.3       oskar     200:         s->stream_id = splice_findfreestreamid (p,s->stream_id);
1.1       oskar     201:       }
                    202:       p->stream[p->streams++] = s;
                    203:       p->changed = TRUE;
                    204:       s->u.d.pid = pid;
1.9       oskar     205:       configuration_changed = TRUE;
1.1       oskar     206:     }
                    207:   }
                    208:   return (pid);
                    209: }
                    210: 
                    211: boolean splice_delstream (prog_descr *p,
                    212:     stream_descr *s)
                    213: {
                    214:   int i;
                    215:   warn (LIMP,"Del stream",ETSC,5,0,s->u.d.pid);
1.9       oskar     216:   configuration_changed = TRUE;
1.1       oskar     217:   i = p->streams;
                    218:   while (--i >= 0) {
                    219:     if (p->stream[i] == s) {
                    220:       outs[s->u.d.pid] = NULL;
                    221:       p->stream[i] = p->stream[--(p->streams)];
                    222:       p->changed = TRUE;
                    223:       if (p->pcr_pid == s->u.d.pid) {
                    224:         p->pcr_pid = -1;
                    225:       }
                    226:       s->u.d.pid = 0;
                    227:       return (TRUE);
                    228:     }
                    229:   }
                    230:   warn (LERR,"Del lost stream",ETSC,5,1,p->streams);
                    231:   return (FALSE);
                    232: }
                    233: 
1.7       oskar     234: void process_finish (void)
                    235: {
                    236:   warn (LIMP,"Finish",ETSC,6,0,0);
                    237: }
                    238: 
1.1       oskar     239: static int make_patsection (int section,
                    240:     byte *dest)
                    241: {
                    242:   int i;
                    243:   byte *d;
                    244:   d = dest;
                    245:   *d++ = TS_TABLEID_PAT;
                    246:   d += 2;
                    247:   *d++ = transportstreamid >> 8;
                    248:   *d++ = (byte)transportstreamid;
                    249:   *d++ = 0xC0 | 0x01 | (nextpat_version << 1);
                    250:   *d++ = section;
                    251:   *d++ = last_patsection;
                    252:   i = progs;
                    253:   while (--i >= 0) {
                    254:     if (prog[i]->pat_section == section) {
                    255:       int x;
                    256:       x = prog[i]->program_number;
                    257:       *d++ = (x >> 8);
                    258:       *d++ = x;
                    259:       x = prog[i]->pmt_pid;
                    260:       *d++ = 0xE0 | (x >> 8);
                    261:       *d++ = x;
                    262:     }
                    263:   }
                    264:   i = d + CRC_SIZE - dest - TS_TRANSPORTID;
                    265:   dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
                    266:   dest[TS_SECTIONLEN+1] = i;
                    267:   crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
                    268:   return (i + TS_TRANSPORTID);
                    269: }
                    270: 
                    271: static int make_pmtsection (stream_descr *s,
                    272:     prog_descr *p,
                    273:     byte *dest)
                    274: {
                    275:   int i;
                    276:   byte *d;
                    277:   p->changed = FALSE;
                    278:   d = dest;
                    279:   *d++ = TS_TABLEID_PMT;
                    280:   d += 2;
                    281:   i = p->program_number;
                    282:   *d++ = (i >> 8);
                    283:   *d++ = i;
                    284:   *d++ = 0xC0 | 0x01 | (p->pmt_version << 1);
                    285:   p->pmt_version = (p->pmt_version+1) & 0x1F;
                    286:   *d++ = 0;
                    287:   *d++ = 0;
                    288:   if (p->pcr_pid < 0) {
                    289:     stream_descr *pcrs;
1.3       oskar     290:     pcrs = splice_findpcrstream (p);
1.1       oskar     291:     if (pcrs == NULL) {
                    292:       pcrs = s;
                    293:     }
                    294:     pcrs->u.d.has_clockref = TRUE;
                    295:     pcrs->u.d.next_clockref = msec_now () - MAX_MSEC_PCRDIST;
                    296:     p->pcr_pid = pcrs->u.d.pid;
1.9       oskar     297:     configuration_changed = TRUE;
1.1       oskar     298:   }
                    299:   i = p->pcr_pid;
                    300:   *d++ = 0xE0 | (i >> 8);
                    301:   *d++ = i;
                    302:   d += 2;
                    303:   i = NUMBER_ELEMD;
                    304:   while (--i > 0) {
                    305:     if (s->fdescr->content == ct_program) {
                    306:       byte *y;
                    307:       y = s->fdescr->u.ps.stream[0]->elemdvld[i]; /* this one ? why ? */
                    308:       if (y != NULL) {
                    309:         memcpy (d,y,y[1]+2);
                    310:         d += y[1]+2;
                    311:       }
                    312:     }
                    313:   }
                    314:   i = d - dest - (TS_PMT_PILEN+2);
                    315:   dest[TS_PMT_PILEN] = 0xF0 | (i >> 8);
                    316:   dest[TS_PMT_PILEN+1] = i;
                    317:   i = p->streams;
                    318:   while (--i >= 0) {
                    319:     if (p->stream[i]->u.d.mention) {
                    320:       int x;
                    321:       byte *e;
                    322:       *d++ = p->stream[i]->stream_type;
                    323:       x = p->stream[i]->u.d.pid;
                    324:       *d++ = 0xE0 | (x >> 8);
                    325:       *d++ = x;
                    326:       d += 2;
                    327:       e = d;
                    328:       x = NUMBER_ELEMD;
                    329:       while (--x > 0) {
                    330:         byte *y;
                    331:         y = p->stream[i]->elemdvld[x];
                    332:         if (y != NULL) {
                    333:           memcpy (d,y,y[1]+2);
                    334:           d += y[1]+2;
                    335:         }
                    336:       }
                    337:       x = d - e;
                    338:       *--e = x;
                    339:       *--e = 0xF0 | (x >> 8);
                    340:     }
                    341:   }
                    342:   i = d + CRC_SIZE - dest - TS_TRANSPORTID;
                    343:   dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
                    344:   dest[TS_SECTIONLEN+1] = i;
                    345:   crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
                    346:   return (i + TS_TRANSPORTID);
                    347: }
                    348: 
1.7       oskar     349: /* Check for generated psi data to-be-sent, select data source.
                    350:  * If PAT or PMT needs to be rebuild, do so. If PAT or PMT is (partially)
                    351:  * pending to be transmitted, select that to be packaged next. Otherwise
                    352:  * select data payload. Set pid, scramble mode and PES paket size.
                    353:  * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data.
                    354:  * Input: stream s, current ctrl fifo out c. 
                    355:  * Output: *pid, *scramble, *size (PES paket ~) for the stream to generate.
                    356:  */
                    357: static void procdata_check_psi (int *pid,
                    358:     byte *scramble,
                    359:     int *size,
                    360:     stream_descr *s,
                    361:     ctrl_buffer *c)
1.1       oskar     362: {
1.3       oskar     363:   t_msec now;
1.1       oskar     364:   if (psi_size > 0) {
1.7       oskar     365:     *pid = psi_pid;
                    366:     *scramble = 0;
                    367:     *size = psi_size;
1.1       oskar     368:   } else {
                    369:     if (unit_start != 0) {
                    370:       now = msec_now ();
                    371:       if ((psi_frequency_changed)
                    372:        || ((psi_frequency_msec > 0)
                    373:         && ((next_psi_periodic - now) <= 0))) {
1.7       oskar     374:         int l;
1.1       oskar     375:         changed_pat = TRUE;
                    376:         l = progs;
                    377:         while (--l >= 0) {
                    378:           prog[l]->changed = TRUE;
                    379:         }
                    380:         psi_frequency_changed = FALSE;
                    381:         next_psi_periodic = now + psi_frequency_msec;
                    382:       }
                    383:       if (changed_pat) {
                    384:         psi_pid = TS_PID_PAT;
                    385:         conticnt = &pat_conticnt;
                    386:         psi_data[0] = 0;
                    387:         psi_size = make_patsection (pat_section,&psi_data[1]) + 1;
                    388:         if (pat_section >= last_patsection) {
                    389:           changed_pat = FALSE;
                    390:           nextpat_version = (nextpat_version+1) & 0x1F;
                    391:           pat_section = 0;
                    392:         } else {
                    393:           pat_section += 1;
                    394:         }
                    395:         psi_done = 0;
1.7       oskar     396:         *pid = psi_pid;
                    397:         *scramble = 0;
                    398:         *size = psi_size;
1.1       oskar     399:       } else {
1.7       oskar     400:         int l;
1.1       oskar     401:         l = s->u.d.progs;
                    402:         while (--l >= 0) {
                    403:           if (s->u.d.pdescr[l]->changed) {
1.7       oskar     404:             int i;
                    405:             i = s->u.d.pdescr[l]->streams;
                    406:             while ((--i >= 0)
                    407:                 && (!s->u.d.pdescr[l]->stream[i]->u.d.mention)) {
1.1       oskar     408:             }
1.7       oskar     409:             if (i >= 0) {
1.1       oskar     410:               psi_pid = s->u.d.pdescr[l]->pmt_pid;
                    411:               conticnt = &s->u.d.pdescr[l]->pmt_conticnt;
                    412:               psi_data[0] = 0;
                    413:               psi_size = make_pmtsection (s,s->u.d.pdescr[l],&psi_data[1]) + 1;
                    414:               psi_done = 0;
1.7       oskar     415:               *pid = psi_pid;
                    416:               *scramble = 0;
                    417:               *size = psi_size;
                    418:               return;
1.1       oskar     419:             }
                    420:           }
                    421:         }
1.7       oskar     422:         s->data.ptr[c->index+PES_STREAM_ID] = s->stream_id;
                    423:         conticnt = &s->conticnt;
                    424:         *pid = s->u.d.pid;
                    425:         *scramble = c->scramble;
                    426:         *size = c->length;
1.1       oskar     427:       }
                    428:     } else {
1.7       oskar     429:       *pid = s->u.d.pid;
                    430:       *scramble = c->scramble;
                    431:       *size = c->length;
1.1       oskar     432:     }
                    433:   }
1.7       oskar     434: }
                    435: 
                    436: /* Check for adaption field items to be filled in.
                    437:  * First assume no adaption field is set and the complete packet except the
                    438:  * header is available for payload. Then check which adaption fields have
                    439:  * to be set and decrease the free space accordingly.
                    440:  * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data.
                    441:  * Input: stream s, current ctrl fifo out c.
                    442:  * Output: *adapt_flags1, *adapt_flags2, *adapt_ext_len.
                    443:  * Return: number of bytes of free space available for payload.
                    444:  */
                    445: static int procdata_adaptfield_flags (byte *adapt_flags1,
                    446:     byte *adapt_flags2,
                    447:     int *adapt_ext_len,
                    448:     stream_descr *s,
                    449:     ctrl_buffer *c)
                    450: {
                    451:   int space;
                    452:   *adapt_ext_len = 1;
                    453:   *adapt_flags2 = 0;
                    454:   *adapt_flags1 = 0;
                    455:   space = TS_PACKET_SIZE - TS_PACKET_HEADSIZE;
1.1       oskar     456:   if ((psi_size <= 0)
                    457:    && (s->u.d.discontinuity)) { /* o, not for contents, but PCR-disco ? */
                    458:     s->u.d.discontinuity = FALSE;
1.7       oskar     459:     *adapt_flags1 |= TS_ADAPT_DISCONTI;
1.1       oskar     460:   }
                    461:   if (0) {
1.7       oskar     462:     *adapt_flags1 |= TS_ADAPT_RANDOMAC;
1.1       oskar     463:   }
                    464:   if (0) {
1.7       oskar     465:     *adapt_flags1 |= TS_ADAPT_PRIORITY;
1.1       oskar     466:   }
                    467:   if ((psi_size <= 0)
                    468:    && (s->u.d.has_clockref)
                    469:    && ((c->pcr.valid)
1.2       oskar     470:     || (s->u.d.next_clockref - (c->msecpush + s->u.d.delta) <= 0))) {
1.7       oskar     471:     *adapt_flags1 |= TS_ADAPT_PCRFLAG;
                    472:     space -= 6;
1.1       oskar     473:   }
                    474:   if ((psi_size <= 0)
1.4       oskar     475:    && ((c->opcr.valid)
                    476:     || ((!s->u.d.has_opcr)
                    477:      && (c->pcr.valid)))) {
1.7       oskar     478:     *adapt_flags1 |= TS_ADAPT_OPCRFLAG;
                    479:     space -= 6;
1.1       oskar     480:   }
                    481:   if (0) {
1.7       oskar     482:     *adapt_flags1 |= TS_ADAPT_SPLICING;
                    483:     space -= 1;
1.1       oskar     484:   }
                    485:   if (0) {
1.7       oskar     486:     int privdata;
                    487:     *adapt_flags1 |= TS_ADAPT_TPRIVATE;
1.1       oskar     488:     privdata = 0;
1.7       oskar     489:     space -= (privdata + 1);
1.1       oskar     490:   }
                    491:   if (0) {
1.7       oskar     492:     *adapt_flags2 |= TS_ADAPT2_LTWFLAG;
                    493:     *adapt_ext_len += 2;
1.1       oskar     494:   }
                    495:   if (0) {
1.7       oskar     496:     *adapt_flags2 |= TS_ADAPT2_PIECEWRF;
                    497:     *adapt_ext_len += 3;
1.1       oskar     498:   }
                    499:   if (0) {
1.7       oskar     500:     *adapt_flags2 |= TS_ADAPT2_SEAMLESS;
                    501:     *adapt_ext_len += 5;
1.1       oskar     502:   }
1.7       oskar     503:   if (*adapt_flags2 != 0) {
                    504:     *adapt_flags1 |= TS_ADAPT_EXTENSIO;
                    505:     space -= *adapt_ext_len;
1.1       oskar     506:   }
1.7       oskar     507:   if (*adapt_flags1 != 0) {
                    508:     space -= 2;
1.1       oskar     509:   }
1.7       oskar     510:   return (space);
                    511: }
                    512: 
                    513: /* Adjust size of adaption field against size of payload. Set flags.
                    514:  * Input: *space (number of bytes of free space available for payload),
                    515:  *   *adapt_flags1, size (number of bytes left to be sent).
                    516:  * Output: *space (corrected in case of padding is done via adaption field),
                    517:  *   *adapt_field_ctrl.
                    518:  * Return: Number of bytes of payload to be inserted into THIS packet.
                    519:  */
                    520: static int procdata_adaptfield_frame (int *space,
                    521:     byte *adapt_field_ctrl,
                    522:     byte adapt_flags1,
                    523:     int size)
                    524: {
                    525:   int payload;
                    526:   if (size < *space) {
                    527:     payload = size;
1.1       oskar     528:     if (adapt_flags1 == 0) {
1.7       oskar     529:       *space -= 1;
                    530:       if (*space > payload) {
                    531:         *space -= 1;
1.1       oskar     532:       }
                    533:     }
1.7       oskar     534:     *adapt_field_ctrl = TS_AFC_BOTH;
1.1       oskar     535:   } else {
1.7       oskar     536:     payload = *space;
                    537:     if (payload == 0) {
                    538:       *adapt_field_ctrl = TS_AFC_ADAPT;
1.1       oskar     539:     } else if (adapt_flags1 == 0) {
1.7       oskar     540:       *adapt_field_ctrl = TS_AFC_PAYLD;
1.1       oskar     541:     } else {
1.7       oskar     542:       *adapt_field_ctrl = TS_AFC_BOTH;
1.1       oskar     543:     }
                    544:   }
1.7       oskar     545:   return (payload);
                    546: }
                    547: 
                    548: /* Generate packet header.
                    549:  * Keep track of continuity counter (which is selected in procdata_check_psi).
                    550:  * Precondition: d!=NULL (data destination).
                    551:  * Input: pid, scramble, adaption_field_ctrl.
                    552:  * Return: d (increased by header size).
                    553:  */
                    554: static byte *procdata_syn_head (byte *d,
                    555:     int pid,
                    556:     byte scramble,
                    557:     byte adapt_field_ctrl)
                    558: {
1.1       oskar     559:   *d++ = TS_SYNC_BYTE;
1.7       oskar     560:   warn (LSEC,"Splice unitstart",ETSC,7,1,unit_start);
                    561:   warn (LSEC,"Splice PID",ETSC,7,2,pid);
1.1       oskar     562:   *d++ = (0 << 7) /* transport_error_indicator */
                    563:        | unit_start
                    564:        | (0 << 5) /* transport_priority */
                    565:        | (pid >> 8);
                    566:   *d++ = pid;
                    567:   *d++ = (scramble << 6)
                    568:        | adapt_field_ctrl
                    569:        | *conticnt;
1.7       oskar     570:   warn (LSEC,"Splice continuity cnt",ETSC,7,3,*conticnt);
1.1       oskar     571:   if (adapt_field_ctrl & TS_AFC_PAYLD) {
                    572:     *conticnt = (*conticnt+1) & 0x0F;
                    573:   }
1.7       oskar     574:   return (d);
                    575: }
                    576: 
                    577: /* Generate adpation field.
                    578:  * This MUST match the calculations in procdata_adaptfield_flags.
                    579:  * Precondition: s!=NULL.
                    580:  * Input: s (stream), c (current ctrl fifo out), d (data destination),
                    581:  *   padding (number of padding bytes needed), payload (number of payload bytes
                    582:  *   to insert), adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len.
                    583:  * Return: d (increased by adaption field size).
                    584:  */
                    585: static byte *procdata_syn_adaptfield (stream_descr *s,
                    586:     ctrl_buffer *c,
                    587:     byte *d,
                    588:     int padding,
                    589:     int payload,
                    590:     byte adapt_field_ctrl,
                    591:     byte adapt_flags1,
                    592:     byte adapt_flags2,
                    593:     int adapt_ext_len)
                    594: {
1.1       oskar     595:   if (adapt_field_ctrl & TS_AFC_ADAPT) {
1.7       oskar     596:     if ((*d++ = (TS_PACKET_SIZE - TS_PACKET_FLAGS1) - payload) != 0) {
1.1       oskar     597:       *d++ = adapt_flags1;
                    598:       if (adapt_flags1 & TS_ADAPT_PCRFLAG) {
                    599:         clockref pcr;
1.2       oskar     600:         msec2cref (&s->u.d.conv,c->msecpush + s->u.d.delta,&pcr);
1.1       oskar     601:         *d++ = (pcr.base >> 25) | (pcr.ba33 << 7);
                    602:         *d++ = pcr.base >> 17;
                    603:         *d++ = pcr.base >> 9;
                    604:         *d++ = pcr.base >> 1;
                    605:         *d++ = (pcr.base << 7) | (pcr.ext >> 8) | 0x7E;
                    606:         *d++ = pcr.ext;
                    607:         s->u.d.next_clockref =
1.2       oskar     608:           (c->msecpush + s->u.d.delta) + MAX_MSEC_PCRDIST;
1.1       oskar     609:         c->pcr.valid = FALSE;
                    610:       }
                    611:       if (adapt_flags1 & TS_ADAPT_OPCRFLAG) {
1.4       oskar     612:         clockref *opcr;
                    613:         if (c->opcr.valid) {
                    614:           opcr = &c->opcr;
                    615:         } else {
                    616:           opcr = &c->pcr;
                    617:         }
                    618:         *d++ = (opcr->base >> 25) | (opcr->ba33 << 7);
                    619:         *d++ = opcr->base >> 17;
                    620:         *d++ = opcr->base >> 9;
                    621:         *d++ = opcr->base >> 1;
                    622:         *d++ = (opcr->base << 7) | (opcr->ext >> 8) | 0x7E;
                    623:         *d++ = opcr->ext;
                    624:         opcr->valid = FALSE;
1.1       oskar     625:       }
                    626:       if (adapt_flags1 & TS_ADAPT_SPLICING) {
                    627:       }
                    628:       if (adapt_flags1 & TS_ADAPT_TPRIVATE) {
                    629:       }
                    630:       if (adapt_flags1 & TS_ADAPT_EXTENSIO) {
                    631:         *d++ = adapt_ext_len;
                    632:         *d++ = adapt_flags2 | 0x1F;
1.5       oskar     633:         if (adapt_flags2 & TS_ADAPT2_LTWFLAG) {
1.1       oskar     634:         }
1.5       oskar     635:         if (adapt_flags2 & TS_ADAPT2_PIECEWRF) {
1.1       oskar     636:         }
1.5       oskar     637:         if (adapt_flags2 & TS_ADAPT2_SEAMLESS) {
1.1       oskar     638:         }
                    639:       }
                    640:     }
1.7       oskar     641:     if (padding > 0) {
                    642:       warn (LSEC,"Splice padding",ETSC,8,1,padding);
                    643:       memset (d,-1,padding);
                    644:       d += padding;
1.1       oskar     645:     }
                    646:   }
1.7       oskar     647:   return (d);
                    648: }
                    649: 
                    650: /* Generate payload portion.
                    651:  * Insert the appropriate payload (either PSI or data), check whether payload
                    652:  * from this PES packet or section is left.
                    653:  * Precondition: s!=NULL.
                    654:  * Input: s (stream), c (current ctrl fifo out), d (data destination),
                    655:  *   payload (number of payload bytes to insert).
                    656:  * Return: processed stream s, if there is more data from the current PES
                    657:  *   packet to be processed, NULL otherwise.
                    658:  */
                    659: static stream_descr *procdata_syn_payload (stream_descr *s,
                    660:     ctrl_buffer *c,
                    661:     byte *d,
                    662:     int payload)
                    663: {
                    664:   if (payload > 0) {
1.1       oskar     665:     if (psi_size > 0) {
1.7       oskar     666:       memcpy (d,&psi_data[psi_done],payload);
                    667:       if (payload < psi_size) {
                    668:         warn (LSEC,"Splice PSI Data",ETSC,9,s->stream_id,payload);
                    669:         psi_done += payload;
                    670:         psi_size -= payload;
1.1       oskar     671:         unit_start = 0;
                    672:       } else {
1.7       oskar     673:         warn (LINF,"Splice PSI Done",ETSC,9,s->stream_id,payload);
1.1       oskar     674:         psi_done = psi_size = 0;
                    675:         unit_start = TS_UNIT_START;
                    676:       }
                    677:     } else {
1.7       oskar     678:       memcpy (d,&s->data.ptr[c->index],payload);
                    679:       if (payload < c->length) {
                    680:         warn (LSEC,"Splice Data",ETSC,9,s->stream_id,payload);
                    681:         c->length -= payload;
                    682:         s->data.out = (c->index += payload);
1.1       oskar     683:         unit_start = 0;
                    684:       } else {
1.7       oskar     685:         warn (LINF,"Splice Done",ETSC,9,s->stream_id,payload);
1.1       oskar     686:         list_incr (s->ctrl.out,s->ctrl,1);
                    687:         if (list_empty (s->ctrl)) {
                    688:           s->data.out = s->data.in;
                    689:         } else {
                    690:           s->data.out = s->ctrl.ptr[s->ctrl.out].index;
                    691:         }
                    692:         unit_start = TS_UNIT_START;
1.7       oskar     693:         return (NULL);
1.1       oskar     694:       }
                    695:     }
                    696:   }
                    697:   return (s);
1.7       oskar     698: }
                    699: 
                    700: /* Process unparsed si data and generate output.
                    701:  * Take one TS paket, copy it to output stream data buffer.
                    702:  * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_unparsedsi,
                    703:  *   s->ctrl.ptr[s->ctrl.out].length==TS_PACKET_SIZE, d!=NULL.
                    704:  */
                    705: static void proc_unparsedsi (stream_descr *s,
                    706:     byte *d)
                    707: {
                    708:   warn (LINF,"Splice Unparsed SI",ETSC,10,0,s->u.usi.delta);
                    709:   memcpy (d,&s->data.ptr[s->ctrl.ptr[s->ctrl.out].index],TS_PACKET_SIZE);
                    710:                 /* check if ==  s->ctrl.ptr[s->ctrl.out].length); ? */
                    711:   list_incr (s->ctrl.out,s->ctrl,1);
                    712:   if (list_empty (s->ctrl)) {
1.10      oskar     713:     input_closefileifunused (s->fdescr);
1.7       oskar     714:     s->data.out = s->data.in;
                    715:   } else {
                    716:     s->data.out = s->ctrl.ptr[s->ctrl.out].index;
                    717:   }
                    718: }
                    719: 
                    720: stream_descr *process_something (stream_descr *s)
                    721: {
                    722:   byte *d;
                    723:   int pid;
                    724:   byte scramble;
                    725:   int size;
                    726:   ctrl_buffer *c;
                    727:   int payload;
                    728:   int space;
                    729:   int adapt_ext_len;
                    730:   byte adapt_field_ctrl;
                    731:   byte adapt_flags1, adapt_flags2;
                    732:   warn (LDEB,"Splice TS",ETSC,0,0,s->ctrl.out);
                    733:   switch (s->streamdata) {
                    734:     case sd_data:
                    735:       c = &s->ctrl.ptr[s->ctrl.out];
                    736:       procdata_check_psi (&pid, &scramble, &size, s, c);
                    737:       d = output_pushdata (TS_PACKET_SIZE,c->msecpush + s->u.d.delta);
                    738:       if (d == NULL) {
                    739:         return (s);
                    740:       }
                    741:       space = procdata_adaptfield_flags (&adapt_flags1, &adapt_flags2,
                    742:           &adapt_ext_len, s, c);
1.8       oskar     743:       payload = procdata_adaptfield_frame (&space, &adapt_field_ctrl,
                    744:           adapt_flags1, size);
1.7       oskar     745:       d = procdata_syn_head (d, pid, scramble, adapt_field_ctrl);
1.8       oskar     746:       d = procdata_syn_adaptfield (s, c, d, space-payload, payload,
                    747:           adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len);
1.7       oskar     748:       return (procdata_syn_payload (s, c, d, payload));
                    749:       break;
                    750:     case sd_map:
                    751:       validate_mapref (s);
                    752:       return (NULL);
                    753:       break;
                    754:     case sd_unparsedsi:
                    755:       c = &s->ctrl.ptr[s->ctrl.out];
                    756:       d = output_pushdata (TS_PACKET_SIZE,c->msecpush + s->u.usi.delta);
                    757:       if (d == NULL) {
                    758:         return (s);
                    759:       }
                    760:       proc_unparsedsi (s,d);
                    761:       return (NULL);
                    762:       break;
                    763:     default:
                    764:       return (NULL);
                    765:       break;
                    766:   }
1.1       oskar     767: }
                    768: 

LinuxTV legacy CVS <linuxtv.org/cvs>