Annotation of multiplexer/splicets.c, revision 1.3

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"
                     25: #include "pes.h"
                     26: #include "ts.h"
                     27: #include "splice.h"
                     28: #include "splicets.h"
                     29: 
                     30: const boolean splice_multipleprograms = TRUE;
                     31: 
                     32: static boolean changed_pat;
                     33: static int pat_section;
                     34: static const int last_patsection = 0;
                     35: static byte nextpat_version;
                     36: static byte pat_conticnt;
                     37: 
                     38: static int transportstreamid;
                     39: 
                     40: static int psi_size;
                     41: static int psi_done;
                     42: static byte psi_data [MAX_PSI_SIZE];
                     43: 
                     44: static byte unit_start;
                     45: static byte *conticnt;
                     46: static int psi_pid;
                     47: 
                     48: static int progs;
                     49: static prog_descr *prog [MAX_OUTPROG];
                     50: 
                     51: static int nextpid;
                     52: static stream_descr *outs [MAX_STRPERTS];
                     53: 
1.3     ! oskar      54: static t_msec next_psi_periodic;
        !            55: static t_msec psi_frequency_msec;
1.1       oskar      56: static boolean psi_frequency_changed;
                     57: 
                     58: boolean splice_init (void)
                     59: {
                     60:   progs = 0;
                     61:   nextpid = 0;
                     62:   memset (outs,0,sizeof(outs));
                     63:   changed_pat = TRUE;
                     64:   pat_section = 0;
                     65:   nextpat_version = 0;
                     66:   pat_conticnt = 0;
                     67:   psi_size = psi_done = 0;
                     68:   unit_start = TS_UNIT_START;
                     69:   transportstreamid = 0x4227;
                     70:   psi_frequency_msec = 0;
                     71:   psi_frequency_changed = FALSE;
                     72:   return (TRUE);
                     73: }
                     74: 
                     75: void splice_settransportstreamid (int tsid)
                     76: {
                     77:   transportstreamid = tsid;
                     78: }
                     79: 
                     80: void splice_setpsifrequency (int freq)
                     81: {
                     82:   psi_frequency_msec = freq;
                     83:   psi_frequency_changed = TRUE;
                     84: }
                     85: 
                     86: static int findapid (stream_descr *s)
                     87: {
                     88:   boolean ok = TRUE;
                     89:   do {
1.2       oskar      90:     if ((nextpid < TS_PID_SPLICELO) || (nextpid >= TS_PID_SPLICEHI)) {
1.1       oskar      91:       if (!ok) {
                     92:         warn (LERR,"No PID found",ETSC,2,1,0);
                     93:         return (0);
                     94:       }
                     95:       ok = FALSE;
1.2       oskar      96:       nextpid = TS_PID_SPLICELO;
1.1       oskar      97:     } else {
                     98:       nextpid += 1;
                     99:     }
                    100:   } while (outs[nextpid] != NULL);
                    101:   outs[nextpid] = s;
                    102:   warn (LDEB,"Next PID",ETSC,2,2,nextpid);
                    103:   return (nextpid);
                    104: }
                    105: 
1.3     ! oskar     106: prog_descr *splice_getprog (int programnb)
        !           107: {
        !           108:   int i;
        !           109:   i = progs;
        !           110:   while (--i >= 0) {
        !           111:     if (prog[i]->program_number == programnb) {
        !           112:       return (prog[i]);
        !           113:     }
        !           114:   }
        !           115:   return (NULL);
        !           116: }
        !           117: 
1.1       oskar     118: prog_descr *splice_openprog (int programnb)
                    119: {
                    120:   prog_descr *p;
                    121:   int pid;
                    122:   warn (LIMP,"Open prog",ETSC,1,0,programnb);
1.3     ! oskar     123:   p = splice_getprog (programnb);
1.1       oskar     124:   if (p == NULL) {
                    125:     if (progs < MAX_OUTPROG) {
                    126:       if ((pid = findapid (PMT_STREAM)) > 0) {
                    127:         if ((p = malloc(sizeof(prog_descr))) != NULL) {
                    128:           p->program_number = programnb;
                    129:           p->pcr_pid = -1;
                    130:           p->pmt_pid = pid;
                    131:           p->pmt_conticnt = 0;
                    132:           p->pmt_version = 0;
                    133:           p->changed = TRUE;
                    134:           p->pat_section = 0; /* more ? */
                    135:           p->streams = 0;
                    136:           prog[progs++] = p;
                    137:           changed_pat = TRUE;
                    138:         } else {
                    139:           outs[pid] = NULL;
                    140:           warn (LERR,"Open prog",ETSC,1,1,0);
                    141:         }
                    142:       }
                    143:     } else {
                    144:       warn (LERR,"Max prog open",ETSC,1,2,0);
                    145:     }
                    146:   }
                    147:   return (p);
                    148: }
                    149: 
                    150: void splice_closeprog (prog_descr *p)
                    151: {
                    152:   int i, n;
                    153:   warn (LIMP,"Close prog",ETSC,3,0,p->program_number);
                    154:   while (p->streams > 0) {
1.3     ! oskar     155:     unlink_streamprog (p->stream[0],p);
1.1       oskar     156:   }
                    157:   n = -1;
                    158:   if (p->pmt_pid >= 0) {
                    159:     i = progs;
                    160:     while (--i >= 0) {
                    161:       if (prog[i]->pmt_pid == p->pmt_pid) {
                    162:         n += 1;
                    163:       }
                    164:     }
                    165:   }
                    166:   i = progs;
                    167:   while (--i >= 0) {
                    168:     if (prog[i] == p) {
                    169:       prog[i] = prog[--progs];
                    170:       if (n == 0) {
                    171:         outs[p->pmt_pid] = NULL;
                    172:       }
                    173:       free (p);
                    174:       changed_pat = TRUE;
                    175:       return;
                    176:     }
                    177:   }
                    178:   warn (LERR,"Close lost prog",ETSC,3,1,progs);
                    179: }
                    180: 
                    181: int splice_addstream (prog_descr *p,
                    182:     stream_descr *s,
                    183:     boolean force_sid)
                    184: {
                    185:   int pid = 0;
                    186:   warn (LIMP,"Add stream",ETSC,4,force_sid,s->stream_id);
                    187:   if (p->streams < MAX_STRPERPRG) {
                    188:     if ((pid = findapid (s)) > 0) {
                    189:       if (!force_sid) {
1.3     ! oskar     190:         s->stream_id = splice_findfreestreamid (p,s->stream_id);
1.1       oskar     191:       }
                    192:       p->stream[p->streams++] = s;
                    193:       p->changed = TRUE;
                    194:       s->u.d.pid = pid;
                    195:     }
                    196:   }
                    197:   return (pid);
                    198: }
                    199: 
                    200: boolean splice_delstream (prog_descr *p,
                    201:     stream_descr *s)
                    202: {
                    203:   int i;
                    204:   warn (LIMP,"Del stream",ETSC,5,0,s->u.d.pid);
                    205:   i = p->streams;
                    206:   while (--i >= 0) {
                    207:     if (p->stream[i] == s) {
                    208:       outs[s->u.d.pid] = NULL;
                    209:       p->stream[i] = p->stream[--(p->streams)];
                    210:       p->changed = TRUE;
                    211:       if (p->pcr_pid == s->u.d.pid) {
                    212:         p->pcr_pid = -1;
                    213:       }
                    214:       s->u.d.pid = 0;
                    215:       return (TRUE);
                    216:     }
                    217:   }
                    218:   warn (LERR,"Del lost stream",ETSC,5,1,p->streams);
                    219:   return (FALSE);
                    220: }
                    221: 
                    222: static int make_patsection (int section,
                    223:     byte *dest)
                    224: {
                    225:   int i;
                    226:   byte *d;
                    227:   d = dest;
                    228:   *d++ = TS_TABLEID_PAT;
                    229:   d += 2;
                    230:   *d++ = transportstreamid >> 8;
                    231:   *d++ = (byte)transportstreamid;
                    232:   *d++ = 0xC0 | 0x01 | (nextpat_version << 1);
                    233:   *d++ = section;
                    234:   *d++ = last_patsection;
                    235:   i = progs;
                    236:   while (--i >= 0) {
                    237:     if (prog[i]->pat_section == section) {
                    238:       int x;
                    239:       x = prog[i]->program_number;
                    240:       *d++ = (x >> 8);
                    241:       *d++ = x;
                    242:       x = prog[i]->pmt_pid;
                    243:       *d++ = 0xE0 | (x >> 8);
                    244:       *d++ = x;
                    245:     }
                    246:   }
                    247:   i = d + CRC_SIZE - dest - TS_TRANSPORTID;
                    248:   dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
                    249:   dest[TS_SECTIONLEN+1] = i;
                    250:   crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
                    251:   return (i + TS_TRANSPORTID);
                    252: }
                    253: 
                    254: static int make_pmtsection (stream_descr *s,
                    255:     prog_descr *p,
                    256:     byte *dest)
                    257: {
                    258:   int i;
                    259:   byte *d;
                    260:   p->changed = FALSE;
                    261:   d = dest;
                    262:   *d++ = TS_TABLEID_PMT;
                    263:   d += 2;
                    264:   i = p->program_number;
                    265:   *d++ = (i >> 8);
                    266:   *d++ = i;
                    267:   *d++ = 0xC0 | 0x01 | (p->pmt_version << 1);
                    268:   p->pmt_version = (p->pmt_version+1) & 0x1F;
                    269:   *d++ = 0;
                    270:   *d++ = 0;
                    271:   if (p->pcr_pid < 0) {
                    272:     stream_descr *pcrs;
1.3     ! oskar     273:     pcrs = splice_findpcrstream (p);
1.1       oskar     274:     if (pcrs == NULL) {
                    275:       pcrs = s;
                    276:     }
                    277:     pcrs->u.d.has_clockref = TRUE;
                    278:     pcrs->u.d.next_clockref = msec_now () - MAX_MSEC_PCRDIST;
                    279:     p->pcr_pid = pcrs->u.d.pid;
                    280:   }
                    281:   i = p->pcr_pid;
                    282:   *d++ = 0xE0 | (i >> 8);
                    283:   *d++ = i;
                    284:   d += 2;
                    285:   i = NUMBER_ELEMD;
                    286:   while (--i > 0) {
                    287:     if (s->fdescr->content == ct_program) {
                    288:       byte *y;
                    289:       y = s->fdescr->u.ps.stream[0]->elemdvld[i]; /* this one ? why ? */
                    290:       if (y != NULL) {
                    291:         memcpy (d,y,y[1]+2);
                    292:         d += y[1]+2;
                    293:       }
                    294:     }
                    295:   }
                    296:   i = d - dest - (TS_PMT_PILEN+2);
                    297:   dest[TS_PMT_PILEN] = 0xF0 | (i >> 8);
                    298:   dest[TS_PMT_PILEN+1] = i;
                    299:   i = p->streams;
                    300:   while (--i >= 0) {
                    301:     if (p->stream[i]->u.d.mention) {
                    302:       int x;
                    303:       byte *e;
                    304:       *d++ = p->stream[i]->stream_type;
                    305:       x = p->stream[i]->u.d.pid;
                    306:       *d++ = 0xE0 | (x >> 8);
                    307:       *d++ = x;
                    308:       d += 2;
                    309:       e = d;
                    310:       x = NUMBER_ELEMD;
                    311:       while (--x > 0) {
                    312:         byte *y;
                    313:         y = p->stream[i]->elemdvld[x];
                    314:         if (y != NULL) {
                    315:           memcpy (d,y,y[1]+2);
                    316:           d += y[1]+2;
                    317:         }
                    318:       }
                    319:       x = d - e;
                    320:       *--e = x;
                    321:       *--e = 0xF0 | (x >> 8);
                    322:     }
                    323:   }
                    324:   i = d + CRC_SIZE - dest - TS_TRANSPORTID;
                    325:   dest[TS_SECTIONLEN] = 0xB0 | (i >> 8);
                    326:   dest[TS_SECTIONLEN+1] = i;
                    327:   crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d);
                    328:   return (i + TS_TRANSPORTID);
                    329: }
                    330: 
                    331: void process_finish (void)
                    332: {
                    333:   warn (LIMP,"Finish",ETSC,6,0,0);
                    334: }
                    335: 
                    336: stream_descr *process_something (stream_descr *s)
                    337: {
                    338:   byte *d;
                    339:   int pid;
                    340:   byte scramble;
                    341:   ctrl_buffer *c;
                    342:   int l, f, k;
                    343:   int privdata;
                    344:   int adapt_ext_len;
1.3     ! oskar     345:   t_msec now;
1.1       oskar     346:   byte adapt_field_ctrl;
                    347:   byte adapt_flags1, adapt_flags2;
                    348:   warn (LDEB,"Splice TS",ETSC,0,0,s->ctrl.out);
                    349:   if (s->isamap) {
                    350:     validate_mapref (s);
                    351:     return (NULL);
                    352:   }
                    353:   c = &s->ctrl.ptr[s->ctrl.out];
                    354:   if (psi_size > 0) {
                    355:     pid = psi_pid;
                    356:     scramble = 0;
                    357:     k = psi_size;
                    358:   } else {
                    359:     if (unit_start != 0) {
                    360:       now = msec_now ();
                    361:       if ((psi_frequency_changed)
                    362:        || ((psi_frequency_msec > 0)
                    363:         && ((next_psi_periodic - now) <= 0))) {
                    364:         changed_pat = TRUE;
                    365:         l = progs;
                    366:         while (--l >= 0) {
                    367:           prog[l]->changed = TRUE;
                    368:         }
                    369:         psi_frequency_changed = FALSE;
                    370:         next_psi_periodic = now + psi_frequency_msec;
                    371:       }
                    372:       if (changed_pat) {
                    373:         psi_pid = TS_PID_PAT;
                    374:         conticnt = &pat_conticnt;
                    375:         psi_data[0] = 0;
                    376:         psi_size = make_patsection (pat_section,&psi_data[1]) + 1;
                    377:         if (pat_section >= last_patsection) {
                    378:           changed_pat = FALSE;
                    379:           nextpat_version = (nextpat_version+1) & 0x1F;
                    380:           pat_section = 0;
                    381:         } else {
                    382:           pat_section += 1;
                    383:         }
                    384:         psi_done = 0;
                    385:         pid = psi_pid;
                    386:         scramble = 0;
                    387:         k = psi_size;
                    388:       } else {
                    389:         l = s->u.d.progs;
                    390:         while (--l >= 0) {
                    391:           if (s->u.d.pdescr[l]->changed) {
                    392:             f = s->u.d.pdescr[l]->streams;
                    393:             while ((--f >= 0)
                    394:                 && (!s->u.d.pdescr[l]->stream[f]->u.d.mention)) {
                    395:             }
                    396:             if (f >= 0) {
                    397:               psi_pid = s->u.d.pdescr[l]->pmt_pid;
                    398:               conticnt = &s->u.d.pdescr[l]->pmt_conticnt;
                    399:               psi_data[0] = 0;
                    400:               psi_size = make_pmtsection (s,s->u.d.pdescr[l],&psi_data[1]) + 1;
                    401:               psi_done = 0;
                    402:               pid = psi_pid;
                    403:               scramble = 0;
                    404:               k = psi_size;
                    405:               break;
                    406:             }
                    407:           }
                    408:         }
                    409:         if (l < 0) {
                    410:           s->data.ptr[c->index+PES_STREAM_ID] = s->stream_id;
                    411:           conticnt = &s->conticnt;
                    412:           pid = s->u.d.pid;
                    413:           scramble = c->scramble;
                    414:           k = c->length;
                    415:         }
                    416:       }
                    417:     } else {
                    418:       pid = s->u.d.pid;
                    419:       scramble = c->scramble;
                    420:       k = c->length;
                    421:     }
                    422:   }
1.2       oskar     423:   d = output_pushdata (TS_PACKET_SIZE,c->msecpush + s->u.d.delta);
1.1       oskar     424:   if (d == NULL) {
                    425:     return (s);
                    426:   }
                    427:   adapt_ext_len = 1;
                    428:   adapt_flags2 = 0;
                    429:   adapt_flags1 = 0;
                    430:   f = TS_PACKET_SIZE - TS_PACKET_HEADSIZE;
                    431:   if ((psi_size <= 0)
                    432:    && (s->u.d.discontinuity)) { /* o, not for contents, but PCR-disco ? */
                    433:     s->u.d.discontinuity = FALSE;
                    434:     adapt_flags1 |= TS_ADAPT_DISCONTI;
                    435:   }
                    436:   if (0) {
                    437:     adapt_flags1 |= TS_ADAPT_RANDOMAC;
                    438:   }
                    439:   if (0) {
                    440:     adapt_flags1 |= TS_ADAPT_PRIORITY;
                    441:   }
                    442:   if ((psi_size <= 0)
                    443:    && (s->u.d.has_clockref)
                    444:    && ((c->pcr.valid)
1.2       oskar     445:     || (s->u.d.next_clockref - (c->msecpush + s->u.d.delta) <= 0))) {
1.1       oskar     446:     adapt_flags1 |= TS_ADAPT_PCRFLAG;
                    447:     f -= 6;
                    448:   }
                    449:   if ((psi_size <= 0)
                    450:    && (c->opcr.valid)) {
                    451:     adapt_flags1 |= TS_ADAPT_OPCRFLAG;
                    452:     f -= 6;
                    453:   }
                    454:   if (0) {
                    455:     adapt_flags1 |= TS_ADAPT_SPLICING;
                    456:     f -= 1;
                    457:   }
                    458:   if (0) {
                    459:     adapt_flags1 |= TS_ADAPT_TPRIVATE;
                    460:     privdata = 0;
                    461:     f -= (privdata + 1);
                    462:   }
                    463:   if (0) {
                    464:     adapt_flags2 |= TS_ADAPT_LTWFLAG;
                    465:     adapt_ext_len += 2;
                    466:   }
                    467:   if (0) {
                    468:     adapt_flags2 |= TS_ADAPT_PIECEWRF;
                    469:     adapt_ext_len += 3;
                    470:   }
                    471:   if (0) {
                    472:     adapt_flags2 |= TS_ADAPT_SEAMLESS;
                    473:     adapt_ext_len += 5;
                    474:   }
                    475:   if (adapt_flags2 != 0) {
                    476:     adapt_flags1 |= TS_ADAPT_EXTENSIO;
                    477:     f -= adapt_ext_len;
                    478:   }
                    479:   if (adapt_flags1 != 0) {
                    480:     f -= 2;
                    481:   }
                    482:   if (k < f) {
                    483:     l = k;
                    484:     if (adapt_flags1 == 0) {
                    485:       f -= 1;
                    486:       if (f > l) {
                    487:         f -= 1;
                    488:       }
                    489:     }
                    490:     adapt_field_ctrl = TS_AFC_BOTH;
                    491:   } else {
                    492:     l = f;
                    493:     if (f == 0) {
                    494:       adapt_field_ctrl = TS_AFC_ADAPT;
                    495:     } else if (adapt_flags1 == 0) {
                    496:       adapt_field_ctrl = TS_AFC_PAYLD;
                    497:     } else {
                    498:       adapt_field_ctrl = TS_AFC_BOTH;
                    499:     }
                    500:   }
                    501:   *d++ = TS_SYNC_BYTE;
                    502:   warn (LSEC,"Splice unitstart",ETSC,0,1,unit_start);
                    503:   warn (LSEC,"Splice PID",ETSC,0,2,pid);
                    504:   *d++ = (0 << 7) /* transport_error_indicator */
                    505:        | unit_start
                    506:        | (0 << 5) /* transport_priority */
                    507:        | (pid >> 8);
                    508:   *d++ = pid;
                    509:   *d++ = (scramble << 6)
                    510:        | adapt_field_ctrl
                    511:        | *conticnt;
                    512:   warn (LSEC,"Splice continuity cnt",ETSC,0,3,*conticnt);
                    513:   if (adapt_field_ctrl & TS_AFC_PAYLD) {
                    514:     *conticnt = (*conticnt+1) & 0x0F;
                    515:   }
                    516:   if (adapt_field_ctrl & TS_AFC_ADAPT) {
                    517:     if ((*d++ = (TS_PACKET_SIZE - TS_PACKET_FLAGS1) - l) != 0) {
                    518:       *d++ = adapt_flags1;
                    519:       if (adapt_flags1 & TS_ADAPT_PCRFLAG) {
                    520:         clockref pcr;
1.2       oskar     521:         msec2cref (&s->u.d.conv,c->msecpush + s->u.d.delta,&pcr);
1.1       oskar     522:         *d++ = (pcr.base >> 25) | (pcr.ba33 << 7);
                    523:         *d++ = pcr.base >> 17;
                    524:         *d++ = pcr.base >> 9;
                    525:         *d++ = pcr.base >> 1;
                    526:         *d++ = (pcr.base << 7) | (pcr.ext >> 8) | 0x7E;
                    527:         *d++ = pcr.ext;
                    528:         s->u.d.next_clockref =
1.2       oskar     529:           (c->msecpush + s->u.d.delta) + MAX_MSEC_PCRDIST;
1.1       oskar     530:         c->pcr.valid = FALSE;
                    531:       }
                    532:       if (adapt_flags1 & TS_ADAPT_OPCRFLAG) {
                    533:         *d++ = (c->opcr.base >> 25) | (c->opcr.ba33 << 7);
                    534:         *d++ = c->opcr.base >> 17;
                    535:         *d++ = c->opcr.base >> 9;
                    536:         *d++ = c->opcr.base >> 1;
                    537:         *d++ = (c->opcr.base << 7) | (c->opcr.ext >> 8) | 0x7E;
                    538:         *d++ = c->opcr.ext;
                    539:         c->opcr.valid = FALSE;
                    540:       }
                    541:       if (adapt_flags1 & TS_ADAPT_SPLICING) {
                    542:       }
                    543:       if (adapt_flags1 & TS_ADAPT_TPRIVATE) {
                    544:       }
                    545:       if (adapt_flags1 & TS_ADAPT_EXTENSIO) {
                    546:         *d++ = adapt_ext_len;
                    547:         *d++ = adapt_flags2 | 0x1F;
                    548:         if (adapt_flags2 & TS_ADAPT_LTWFLAG) {
                    549:         }
                    550:         if (adapt_flags2 & TS_ADAPT_PIECEWRF) {
                    551:         }
                    552:         if (adapt_flags2 & TS_ADAPT_SEAMLESS) {
                    553:         }
                    554:       }
                    555:     }
                    556:     if (f > l) {
                    557:       warn (LSEC,"Splice padding",ETSC,0,4,f-l);
                    558:       memset (d,-1,f-l);
                    559:       d += (f-l);
                    560:     }
                    561:   }
                    562:   if (l > 0) {
                    563:     if (psi_size > 0) {
                    564:       memcpy (d,&psi_data[psi_done],l);
                    565:       if (l < psi_size) {
                    566:         warn (LSEC,"Splice PSI Data",ETSC,0,s->stream_id,l);
                    567:         psi_done += l;
                    568:         psi_size -= l;
                    569:         unit_start = 0;
                    570:       } else {
                    571:         warn (LINF,"Splice PSI Done",ETSC,0,s->stream_id,l);
                    572:         psi_done = psi_size = 0;
                    573:         unit_start = TS_UNIT_START;
                    574:       }
                    575:     } else {
                    576:       memcpy (d,&s->data.ptr[c->index],l);
                    577:       if (l < c->length) {
                    578:         warn (LSEC,"Splice Data",ETSC,0,s->stream_id,l);
                    579:         c->length -= l;
                    580:         s->data.out = (c->index += l);
                    581:         unit_start = 0;
                    582:       } else {
                    583:         warn (LINF,"Splice Done",ETSC,0,s->stream_id,l);
                    584:         list_incr (s->ctrl.out,s->ctrl,1);
                    585:         if (list_empty (s->ctrl)) {
                    586:           s->data.out = s->data.in;
                    587:         } else {
                    588:           s->data.out = s->ctrl.ptr[s->ctrl.out].index;
                    589:         }
                    590:         s = NULL;
                    591:         unit_start = TS_UNIT_START;
                    592:       }
                    593:     }
                    594:   }
                    595:   return (s);
                    596: }
                    597: 

LinuxTV legacy CVS <linuxtv.org/cvs>