Annotation of multiplexer/spliceps.c, revision 1.16

1.1       oskar       1: /*
                      2:  * ISO 13818 stream multiplexer
                      3:  * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin
1.16    ! oskar       4:  * Copyright (C) 2005 Oskar Schirmer (schirmer@scara.com)
1.13      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 PS
                     23:  * Purpose: Generate a program 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 (though multiple programs are
                     29:  * obsolete for a program stream). Further, it accepts PSI data
                     30:  * just in time, validating it not earlier than with the arrival of
                     31:  * the corresponding payload at this stage.
                     32:  */
                     33: 
                     34: #include "global.h"
1.15      oskar      35: #include "crc32.h"
1.1       oskar      36: #include "error.h"
                     37: #include "input.h"
                     38: #include "output.h"
                     39: #include "descref.h"
                     40: #include "pes.h"
                     41: #include "ps.h"
                     42: #include "splice.h"
                     43: #include "spliceps.h"
                     44: 
                     45: const boolean splice_multipleprograms = FALSE;
                     46: 
                     47: static int psi_size;
                     48: static byte psi_data [MAX_PSI_SIZE + PS_SYSTHD_SIZE + PS_STRMAP_SIZE +
                     49:     MAX_STRPERPRG * (PS_SYSTHD_STRLEN + PS_STRMAP_STRLEN)];
                     50: 
                     51: static prog_descr prog;
                     52: 
1.5       oskar      53: boolean splice_specific_init (void)
1.1       oskar      54: {
1.9       oskar      55:   prog.program_number = 0;
1.1       oskar      56:   prog.pmt_conticnt = 0;
                     57:   prog.pmt_version = 0;
                     58:   prog.changed = TRUE;
                     59:   prog.streams = 0;
1.7       oskar      60:   prog.stump = NULL;
1.9       oskar      61:   clear_descrdescr (&prog.manudescr);
1.1       oskar      62:   psi_size = 0;
                     63:   return (TRUE);
                     64: }
                     65: 
                     66: void splice_settransportstreamid (int tsid)
                     67: {
                     68: }
                     69: 
1.6       oskar      70: void splice_setpsifrequency (t_msec freq)
1.1       oskar      71: {
                     72:   psi_frequency_msec = freq;
                     73:   psi_frequency_changed = TRUE;
                     74: }
                     75: 
1.16    ! oskar      76: void splice_setnetworkpid (short pid)
        !            77: {
        !            78: }
        !            79: 
1.5       oskar      80: void splice_all_configuration (void)
                     81: {
1.9       oskar      82:   if (configuration_must_print) {
1.5       oskar      83:     fprintf (stderr, configuration_total, 1);
                     84:     splice_one_configuration (&prog);
1.9       oskar      85:     configuration_was_printed;
1.5       oskar      86:   }
                     87: }
                     88: 
1.7       oskar      89: void splice_addsirange (file_descr *f,
                     90:     int lower,
                     91:     int upper)
                     92: {
                     93: }
                     94: 
                     95: void splice_createstump (int programnb,
                     96:     short pid,
                     97:     byte styp)
                     98: {
                     99: }
                    100:  
                    101: stump_descr *splice_getstumps (int programnb,
                    102:     short pid)
                    103: {
                    104:   return (NULL);
                    105: }
                    106: 
1.9       oskar     107: void splice_modifytargetdescriptor (int programnb,
                    108:     short sid,
                    109:     short pid,
                    110:     int dtag,
                    111:     int dlength,
                    112:     byte *data)
                    113: {
                    114:   splice_modifytargetdescrprog (&prog,0,sid,pid,dtag,dlength,data,NULL);
                    115: }
                    116: 
1.3       oskar     117: prog_descr *splice_getprog (int programnb)
                    118: {
                    119:   return (&prog);
                    120: }
                    121: 
1.1       oskar     122: prog_descr *splice_openprog (int programnb)
                    123: {
1.9       oskar     124: /*  prog.program_number = programnb;  must stay zero */
                    125: /*  configuration_changed = TRUE; */
1.1       oskar     126:   warn (LIMP,"Open prog",EPSC,1,0,programnb);
                    127:   return (&prog);
                    128: }
                    129: 
                    130: void splice_closeprog (prog_descr *p)
                    131: {
                    132:   stream_descr *s;
                    133:   file_descr *f;
                    134:   warn (LIMP,"Close prog",EPSC,2,0,prog.streams);
                    135:   while (prog.streams > 0) {
                    136:     s = prog.stream[0];
                    137:     input_delprog (s,&prog);
                    138:     splice_delstream (&prog,s);
                    139:     if (s->u.d.progs == 0) {
                    140:       f = s->fdescr;
                    141:       input_closestream (s);
                    142:       input_closefileifunused (f);
                    143:     } else {
                    144:       warn (LERR,"Close prog",EPSC,2,s->u.d.progs,s->stream_id);
                    145:     }
                    146:   }
1.5       oskar     147:   configuration_changed = TRUE;
1.1       oskar     148: }
                    149: 
                    150: int splice_addstream (prog_descr *p,
                    151:     stream_descr *s,
                    152:     boolean force_sid)
                    153: {
                    154:   /* add stream to main program */
                    155:   int sid = 0;
                    156:   warn (LIMP,"Add stream",EPSC,3,force_sid,s->stream_id);
                    157:   if (prog.streams < MAX_STRPERPRG) {
                    158:     if (!force_sid) {
1.3       oskar     159:       s->stream_id = splice_findfreestreamid (&prog,s->stream_id);
1.1       oskar     160:     }
                    161:     prog.stream[prog.streams++] = s;
                    162:     prog.changed = TRUE;
                    163:     s->u.d.pid = sid = s->stream_id;
1.5       oskar     164:     configuration_changed = TRUE;
1.9       oskar     165:     splice_modifycheckmatch (0,&prog,s,NULL);
1.1       oskar     166:   }
                    167:   return (sid);
                    168: }
                    169: 
                    170: boolean splice_delstream (prog_descr *p,
                    171:     stream_descr *s)
                    172: {
                    173:   int i;
                    174:   warn (LIMP,"Del stream",EPSC,4,0,s->u.d.pid);
                    175:   i = p->streams;
                    176:   while (--i >= 0) {
                    177:     if (p->stream[i] == s) {
                    178:       prog.stream[i] = prog.stream[--(prog.streams)];
                    179:       prog.changed = TRUE;
                    180:       s->u.d.pid = 0;
1.5       oskar     181:       configuration_changed = TRUE;
1.1       oskar     182:       return (TRUE);
                    183:     }
                    184:   }
                    185:   warn (LERR,"Del lost stream",EPSC,4,1,p->streams);
                    186:   return (FALSE);
                    187: }
                    188: 
1.5       oskar     189: void process_finish (void)
                    190: {
                    191:   byte *d;
                    192:   warn (LIMP,"Finish",EPSC,5,0,0);
1.11      oskar     193:   d = output_pushdata (PES_HDCODE_SIZE, FALSE, 0);
1.5       oskar     194:   if (d != NULL) {
                    195:     *d++ = 0x00;
                    196:     *d++ = 0x00;
                    197:     *d++ = 0x01;
                    198:     *d++ = PS_CODE_END;
                    199:     warn (LIMP,"Finish Done",EPSC,5,1,0);
                    200:   }
                    201: }
                    202: 
1.1       oskar     203: static int make_systemheader (stream_descr *s,
                    204:     byte *dest)
                    205: {
1.11      oskar     206:   int i, pid;
1.3       oskar     207:   byte v, a;
1.1       oskar     208:   byte *d;
                    209:   d = dest;
                    210:   *d++ = 0x00;
                    211:   *d++ = 0x00;
                    212:   *d++ = 0x01;
                    213:   *d++ = PS_CODE_SYST_HDR;
                    214:   d += 2;
                    215:   if (s->fdescr->content == ct_program) {
                    216:     i = s->fdescr->u.ps.sh.ratebound;
                    217:   } else {
                    218:     i = 4500000 / 400; /* wrong for sure */
                    219:   }
                    220:   *d++ = 0x80
                    221:        | (i >> 15);
                    222:   *d++ = (i >> 7);
                    223:   *d++ = (i << 1)
                    224:        | 0x01;
                    225:   d += 2;
                    226:   *d++ = 0 /* packet_rate_restriction_flag */
                    227:        | 0x7F;
                    228:   a = v = 0;
                    229:   i = prog.streams;
                    230:   while (--i >= 0) {
1.11      oskar     231:     pid = prog.stream[i]->u.d.pid;
                    232:     if ((pid >= PES_CODE_VIDEO)
                    233:      && (pid < (PES_CODE_VIDEO + PES_NUMB_VIDEO))) {
1.1       oskar     234:       if (v == 0) {
                    235:         *d++ = PES_JOKER_AUDIO;
                    236:         *d++ = 0xC0
                    237:              | (0 << 5) /* buffer bound scale */
                    238:              | ((4096/128) >> 8);
                    239:         *d++ = (4096/128) & 0xFF; /* fixme! propagate from input, or derive */
                    240:       }
                    241:       v += 1;
                    242:     } else {
1.11      oskar     243:       if ((pid >= PES_CODE_AUDIO)
                    244:        && (pid < (PES_CODE_AUDIO + PES_NUMB_AUDIO))) {
1.1       oskar     245:         if (a == 0) {
                    246:           *d++ = PES_JOKER_VIDEO;
                    247:           *d++ = 0xC0
                    248:                | (0 << 5) /* buffer bound scale */
                    249:                | ((237568/128) >> 8);
                    250:           *d++ = (237568/128) & 0xFF;
                    251:         }
                    252:         a += 1;
                    253:       } else {
1.11      oskar     254:         *d++ = pid;
1.1       oskar     255:         *d++ = 0xC0
                    256:              | (0 << 5) /* buffer bound scale */
                    257:              | ((2048/128) >> 8);
                    258:         *d++ = (2048/128) & 0xFF;
                    259:       }
                    260:     }
                    261:   }
                    262:   dest[PS_SYSTHD_AUDBND] = (a << 2)
                    263:        | 0 /* fixed_flag */
                    264:        | 0; /* CSPS_flag */
                    265:   dest[PS_SYSTHD_VIDBND] = 0 /* system_audio_lock_flag */
                    266:        | 0 /* system_video_lock_flag */
                    267:        | 0x20
                    268:        | v;
                    269:   i = d - dest - PES_HEADER_SIZE;
                    270:   dest[PES_PACKET_LENGTH] = (i >> 8);
                    271:   dest[PES_PACKET_LENGTH+1] = i;
                    272:   return (i + PES_HEADER_SIZE);
                    273: }
                    274: 
                    275: static int make_streammap (stream_descr *s,
                    276:     byte *dest)
                    277: {
                    278:   int i, l;
                    279:   byte *d;
1.11      oskar     280:   stream_descr *t;
1.1       oskar     281:   d = dest;
                    282:   *d++ = 0x00;
                    283:   *d++ = 0x00;
                    284:   *d++ = 0x01;
                    285:   *d++ = PES_CODE_STR_MAP;
                    286:   d += 2;
                    287:   *d++ = (1 << 7) /* current applicable */
                    288:        | 0x60
                    289:        | prog.pmt_version;
                    290:   *d++ = 0xFE
                    291:        | 0x01;
                    292:   d += 2;
1.8       oskar     293:   i = NUMBER_DESCR;
1.11      oskar     294:   while (--i >= 0) {
1.9       oskar     295:     byte *y;
                    296:     y = prog.manudescr.refx[i];
                    297:     if ((y == NULL)
                    298:      && (s->u.d.mapstream != NULL)) {
                    299:       y = s->u.d.mapstream->autodescr->refx[i];
                    300:     }
                    301:     if (y != NULL) {
                    302:       int yl = y[1];
                    303:       if (yl != 0) {
                    304:         yl += 2;
                    305:         memcpy (d,y,yl);
                    306:         d += yl;
1.1       oskar     307:       }
                    308:     }
                    309:   }
                    310:   l = d - dest - PS_STRMAP_PSID;
                    311:   dest[PS_STRMAP_PSIL] = (l >> 8);
                    312:   dest[PS_STRMAP_PSIL+1] = l;
                    313:   d += 2;
                    314:   i = prog.streams;
                    315:   while (--i >= 0) {
1.11      oskar     316:     t = prog.stream[i];
                    317:     if (t->u.d.mention) {
1.1       oskar     318:       int x;
                    319:       byte *e;
1.11      oskar     320:       *d++ = t->stream_type;
                    321:       *d++ = t->u.d.pid;
1.1       oskar     322:       d += 2;
                    323:       e = d;
1.8       oskar     324:       x = NUMBER_DESCR;
1.11      oskar     325:       while (--x >= 0) {
1.1       oskar     326:         byte *y;
1.11      oskar     327:         y = t->manudescr->refx[x];
1.7       oskar     328:         if (y == NULL) {
1.11      oskar     329:           y = t->autodescr->refx[x];
1.7       oskar     330:         }
1.1       oskar     331:         if (y != NULL) {
1.9       oskar     332:           int yl = y[1];
                    333:           if (yl != 0) {
                    334:             yl += 2;
                    335:             memcpy (d,y,yl);
                    336:             d += yl;
                    337:           }
1.1       oskar     338:         }
                    339:       }
                    340:       x = d - e;
                    341:       *--e = x;
                    342:       *--e = (x >> 8);
                    343:     }
                    344:   }
                    345:   i = d - dest - l - (PS_STRMAP_SIZE - CRC_SIZE);
                    346:   dest[PS_STRMAP_PSID + l] = (i >> 8);
                    347:   dest[PS_STRMAP_PSID+l+1] = i;
                    348:   i = d + CRC_SIZE - dest - PES_HEADER_SIZE;
                    349:   dest[PES_PACKET_LENGTH] = (i >> 8);
                    350:   dest[PES_PACKET_LENGTH+1] = i;
                    351:   crc32_calc (dest,i + PES_HEADER_SIZE - CRC_SIZE,d);
                    352:   return (i + PES_HEADER_SIZE);
                    353: }
                    354: 
                    355: stream_descr *process_something (stream_descr *s)
                    356: {
                    357:   byte *d;
                    358:   ctrl_buffer *c;
                    359:   clockref pcr;
                    360:   int i;
1.3       oskar     361:   t_msec now;
1.1       oskar     362:   warn (LDEB,"Splice PS",EPSC,0,0,s->ctrl.out);
1.4       oskar     363:   if (s->streamdata == sd_map) {
1.1       oskar     364:     validate_mapref (s);
                    365:     return (NULL);
                    366:   }
                    367:   c = &s->ctrl.ptr[s->ctrl.out];
                    368:   now = msec_now ();
                    369:   if ((psi_frequency_changed)
                    370:    || ((psi_frequency_msec > 0)
                    371:     && ((next_psi_periodic - now) <= 0))) {
1.10      oskar     372:     prog.unchanged = TRUE;
1.1       oskar     373:     psi_frequency_changed = FALSE;
                    374:     next_psi_periodic = now + psi_frequency_msec;
                    375:   }
1.10      oskar     376:   if (prog.unchanged || prog.changed) {
                    377:     if (prog.changed) {
                    378:       prog.pmt_version = (prog.pmt_version+1) & 0x1F;
                    379:     }
1.1       oskar     380:     psi_size = make_systemheader (s,&psi_data[0]);
                    381:     psi_size += make_streammap (s,&psi_data[psi_size]);
                    382:     prog.changed = FALSE;
1.10      oskar     383:     prog.unchanged = FALSE;
1.1       oskar     384:   }
1.11      oskar     385:   i = c->msecpush + s->u.d.delta;
                    386:   d = output_pushdata (PS_PACKHD_SIZE + psi_size + c->length, TRUE, i);
1.1       oskar     387:   if (d == NULL) {
                    388:     return (s);
                    389:   }
                    390:   *d++ = 0x00;
                    391:   *d++ = 0x00;
                    392:   *d++ = 0x01;
                    393:   *d++ = PS_CODE_PACK_HDR;
1.11      oskar     394:   msec2cref (&s->u.d.conv, i, &pcr);
1.1       oskar     395:   *d++ = 0x40
                    396:        | (((pcr.ba33 << 5) | (pcr.base >> 27)) & 0x38)
                    397:        | 0x04
                    398:        | ((pcr.base >> 28) & 0x03);
                    399:   *d++ = (pcr.base >> 20);
                    400:   *d++ = ((pcr.base >> 12) & 0xF8)
                    401:        | 0x04
                    402:        | ((pcr.base >> 13) & 0x03);
                    403:   *d++ = (pcr.base >> 5);
                    404:   *d++ = ((pcr.base << 3) & 0xF8)
                    405:        | 0x04
                    406:        | ((pcr.ext >> 7) & 0x03);
                    407:   *d++ = (pcr.ext << 1)
                    408:        | 0x01;
                    409:   if (s->fdescr->content == ct_program) {
                    410:     i = s->fdescr->u.ps.ph.muxrate; /* wrong, because maybe old */
                    411:   } else {
1.2       oskar     412:     i = 4500000 / 400; /* xxx wrong for sure */
1.1       oskar     413:   }
                    414:   *d++ = (i >> 14);
                    415:   *d++ = (i >> 6);
                    416:   *d++ = (i << 2)
                    417:        | 0x03;
                    418:   *d++ = 0xF8
                    419:        | 0; /* stuffing length */
                    420:   if (psi_size > 0) {
                    421:     memcpy (d,&psi_data[0],psi_size);
                    422:     d += psi_size;
                    423:     psi_size = 0;
                    424:   }
                    425:   memcpy (d,&s->data.ptr[c->index],c->length);
                    426:   d[PES_STREAM_ID] = s->stream_id;
                    427:   warn (LINF,"Splice Done",EPSC,0,s->stream_id,c->length);
                    428:   list_incr (s->ctrl.out,s->ctrl,1);
                    429:   if (list_empty (s->ctrl)) {
                    430:     s->data.out = s->data.in;
                    431:   } else {
                    432:     s->data.out = s->ctrl.ptr[s->ctrl.out].index;
                    433:   }
                    434:   return (NULL);
                    435: }
                    436: 

LinuxTV legacy CVS <linuxtv.org/cvs>