📄 splicets.c
字号:
byte *y; y = p->manudescr.refx[i]; if ((y == NULL) && (s->u.d.mapstream != NULL)) { y = s->u.d.mapstream->autodescr->refx[i]; /* why this one? */ } if (y != NULL) { int yl = y[1]; if (yl != 0) { yl += 2; memcpy (d,y,yl); d += yl; } } } i = d - dest - (TS_PMT_PILEN+2); dest[TS_PMT_PILEN] = 0xF0 | (i >> 8); dest[TS_PMT_PILEN+1] = i; i = p->streams; while (--i >= 0) { t = p->stream[i]; if (t->u.d.mention) { int x; byte *e; *d++ = t->stream_type; x = t->u.d.pid; *d++ = 0xE0 | (x >> 8); *d++ = x; d += 2; e = d; x = NUMBER_DESCR; while (--x >= 0) { byte *y; y = t->manudescr->refx[x]; if (y == NULL) { y = t->autodescr->refx[x]; } if (y != NULL) { int yl = y[1]; if (yl != 0) { yl += 2; memcpy (d,y,yl); d += yl; } } } x = d - e; *--e = x; *--e = 0xF0 | (x >> 8); } } st = p->stump; while (st != NULL) { int x; byte *e; *d++ = st->stream_type; x = st->pid; *d++ = 0xE0 | (x >> 8); *d++ = x; d += 2; e = d; x = NUMBER_DESCR; while (--x >= 0) { byte *y; y = st->manudescr.refx[x]; if (y != NULL) { int yl = y[1]; if (yl != 0) { yl += 2; memcpy (d,y,yl); d += yl; } } } x = d - e; *--e = x; *--e = 0xF0 | (x >> 8); st = st->next; } i = d + CRC_SIZE - dest - TS_TRANSPORTID; dest[TS_SECTIONLEN] = 0xB0 | (i >> 8); dest[TS_SECTIONLEN+1] = i; crc32_calc (dest,i + TS_TRANSPORTID - CRC_SIZE,d); return (i + TS_TRANSPORTID);}/* Check for generated psi data to-be-sent, select data source. * If PAT or PMT needs to be rebuild, do so. If PAT or PMT is (partially) * pending to be transmitted, select that to be packaged next. Otherwise * select data payload. Set pid, scramble mode and PES paket size. * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data. * Input: stream s, current ctrl fifo out c. * Output: *pid, *scramble, *size (PES paket ~) for the stream to generate. */static void procdata_check_psi (int *pid, byte *scramble, int *size, stream_descr *s, ctrl_buffer *c){ t_msec now; int i, l; prog_descr *p; if (psi_size > 0) { *pid = psi_pid; *scramble = 0; *size = psi_size; } else { if (unit_start != 0) { now = msec_now (); if ((psi_frequency_changed) || ((psi_frequency_msec > 0) && ((next_psi_periodic - now) <= 0))) { unchanged_pat = TRUE; l = progs; while (--l >= 0) { prog[l]->unchanged = TRUE; } psi_frequency_changed = FALSE; next_psi_periodic = now + psi_frequency_msec; } if (unchanged_pat || changed_pat) { psi_pid = TS_PID_PAT; conticnt = &pat_conticnt; psi_data[0] = 0; if ((pat_section == 0) && (changed_pat)) { nextpat_version = (nextpat_version+1) & 0x1F; } psi_size = make_patsection (pat_section,&psi_data[1]) + 1; if (pat_section >= last_patsection) { changed_pat = FALSE; unchanged_pat = FALSE; pat_section = 0; } else { pat_section += 1; } psi_done = 0; *pid = psi_pid; *scramble = 0; *size = psi_size; } else { l = s->u.d.progs; while (--l >= 0) { p = s->u.d.pdescr[l]; if (p->unchanged || p->changed) { i = p->streams; while ((--i >= 0) && (!p->stream[i]->u.d.mention)) { } if (i >= 0) { psi_pid = p->pmt_pid; conticnt = &p->pmt_conticnt; psi_data[0] = 0; if (p->changed) { p->pmt_version = (p->pmt_version+1) & 0x1F; } psi_size = make_pmtsection (s,p,&psi_data[1]) + 1; p->changed = FALSE; p->unchanged = FALSE; psi_done = 0; *pid = psi_pid; *scramble = 0; *size = psi_size; return; } } } s->data.ptr[c->index+PES_STREAM_ID] = s->stream_id; conticnt = &s->conticnt; *pid = s->u.d.pid; *scramble = c->scramble; *size = c->length; } } else { *pid = s->u.d.pid; *scramble = c->scramble; *size = c->length; } }}/* Check for adaption field items to be filled in. * First assume no adaption field is set and the complete packet except the * header is available for payload. Then check which adaption fields have * to be set and decrease the free space accordingly. * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_data. * Input: stream s, current ctrl fifo out c. * Output: *adapt_flags1, *adapt_flags2, *adapt_ext_len. * Return: number of bytes of free space available for payload. */static int procdata_adaptfield_flags (byte *adapt_flags1, byte *adapt_flags2, int *adapt_ext_len, stream_descr *s, ctrl_buffer *c){ int space; *adapt_ext_len = 1; *adapt_flags2 = 0; *adapt_flags1 = 0; space = TS_PACKET_SIZE - TS_PACKET_HEADSIZE; if ((psi_size <= 0) && (s->u.d.discontinuity)) { /* o, not for contents, but PCR-disco ? */ s->u.d.discontinuity = FALSE; *adapt_flags1 |= TS_ADAPT_DISCONTI; } if (0) { *adapt_flags1 |= TS_ADAPT_RANDOMAC; } if (0) { *adapt_flags1 |= TS_ADAPT_PRIORITY; } if ((psi_size <= 0) && (s->u.d.has_clockref) && ((c->pcr.valid) || (s->u.d.next_clockref - (c->msecpush + s->u.d.delta) <= 0))) { *adapt_flags1 |= TS_ADAPT_PCRFLAG; space -= 6; } if ((psi_size <= 0) && ((c->opcr.valid) || ((!s->u.d.has_opcr) && (c->pcr.valid)))) { *adapt_flags1 |= TS_ADAPT_OPCRFLAG; space -= 6; } if (0) { *adapt_flags1 |= TS_ADAPT_SPLICING; space -= 1; } if (0) { int privdata; *adapt_flags1 |= TS_ADAPT_TPRIVATE; privdata = 0; space -= (privdata + 1); } if (0) { *adapt_flags2 |= TS_ADAPT2_LTWFLAG; *adapt_ext_len += 2; } if (0) { *adapt_flags2 |= TS_ADAPT2_PIECEWRF; *adapt_ext_len += 3; } if (0) { *adapt_flags2 |= TS_ADAPT2_SEAMLESS; *adapt_ext_len += 5; } if (*adapt_flags2 != 0) { *adapt_flags1 |= TS_ADAPT_EXTENSIO; space -= *adapt_ext_len; } if (*adapt_flags1 != 0) { space -= 2; } return (space);}/* Adjust size of adaption field against size of payload. Set flags. * Input: *space (number of bytes of free space available for payload), * *adapt_flags1, size (number of bytes left to be sent). * Output: *space (corrected in case of padding is done via adaption field), * *adapt_field_ctrl. * Return: Number of bytes of payload to be inserted into THIS packet. */static int procdata_adaptfield_frame (int *space, byte *adapt_field_ctrl, byte adapt_flags1, int size){ int payload; if (size < *space) { payload = size; if (adapt_flags1 == 0) { *space -= 1; if (*space > payload) { *space -= 1; } } *adapt_field_ctrl = TS_AFC_BOTH; } else { payload = *space; if (payload == 0) { *adapt_field_ctrl = TS_AFC_ADAPT; } else if (adapt_flags1 == 0) { *adapt_field_ctrl = TS_AFC_PAYLD; } else { *adapt_field_ctrl = TS_AFC_BOTH; } } return (payload);}/* Generate packet header. * Keep track of continuity counter (which is selected in procdata_check_psi). * Precondition: d!=NULL (data destination). * Input: pid, scramble, adaption_field_ctrl. * Return: d (increased by header size). */static byte *procdata_syn_head (byte *d, int pid, byte scramble, byte adapt_field_ctrl){ *d++ = TS_SYNC_BYTE; warn (LSEC,"Splice unitstart",ETSC,7,1,unit_start); warn (LSEC,"Splice PID",ETSC,7,2,pid); *d++ = (0 << 7) /* transport_error_indicator */ | unit_start | (0 << 5) /* transport_priority */ | (pid >> 8); *d++ = pid; *d++ = (scramble << 6) | adapt_field_ctrl | *conticnt; warn (LSEC,"Splice continuity cnt",ETSC,7,3,*conticnt); if (adapt_field_ctrl & TS_AFC_PAYLD) { *conticnt = (*conticnt+1) & 0x0F; } return (d);}/* Generate adpation field. * This MUST match the calculations in procdata_adaptfield_flags. * Precondition: s!=NULL. * Input: s (stream), c (current ctrl fifo out), d (data destination), * padding (number of padding bytes needed), payload (number of payload bytes * to insert), adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len. * Return: d (increased by adaption field size). */static byte *procdata_syn_adaptfield (stream_descr *s, ctrl_buffer *c, byte *d, int padding, int payload, byte adapt_field_ctrl, byte adapt_flags1, byte adapt_flags2, int adapt_ext_len){ if (adapt_field_ctrl & TS_AFC_ADAPT) { if ((*d++ = (TS_PACKET_SIZE - TS_PACKET_FLAGS1) - payload) != 0) { *d++ = adapt_flags1; if (adapt_flags1 & TS_ADAPT_PCRFLAG) { clockref pcr; msec2cref (&s->u.d.conv, c->msecpush + s->u.d.delta, &pcr); *d++ = (pcr.base >> 25) | (pcr.ba33 << 7); *d++ = pcr.base >> 17; *d++ = pcr.base >> 9; *d++ = pcr.base >> 1; *d++ = (pcr.base << 7) | (pcr.ext >> 8) | 0x7E; *d++ = pcr.ext; s->u.d.next_clockref = (c->msecpush + s->u.d.delta) + MAX_MSEC_PCRDIST; c->pcr.valid = FALSE; } if (adapt_flags1 & TS_ADAPT_OPCRFLAG) { clockref *opcr; if (c->opcr.valid) { opcr = &c->opcr; } else { opcr = &c->pcr; } *d++ = (opcr->base >> 25) | (opcr->ba33 << 7); *d++ = opcr->base >> 17; *d++ = opcr->base >> 9; *d++ = opcr->base >> 1; *d++ = (opcr->base << 7) | (opcr->ext >> 8) | 0x7E; *d++ = opcr->ext; opcr->valid = FALSE; } if (adapt_flags1 & TS_ADAPT_SPLICING) { } if (adapt_flags1 & TS_ADAPT_TPRIVATE) { } if (adapt_flags1 & TS_ADAPT_EXTENSIO) { *d++ = adapt_ext_len; *d++ = adapt_flags2 | 0x1F; if (adapt_flags2 & TS_ADAPT2_LTWFLAG) { } if (adapt_flags2 & TS_ADAPT2_PIECEWRF) { } if (adapt_flags2 & TS_ADAPT2_SEAMLESS) { } } } if (padding > 0) { warn (LSEC,"Splice padding",ETSC,8,1,padding); memset (d,-1,padding); d += padding; } } return (d);}/* Generate payload portion. * Insert the appropriate payload (either PSI or data), check whether payload * from this PES packet or section is left. * Precondition: s!=NULL. * Input: s (stream), c (current ctrl fifo out), d (data destination), * payload (number of payload bytes to insert). * Return: processed stream s, if there is more data from the current PES * packet to be processed, NULL otherwise. */static stream_descr *procdata_syn_payload (stream_descr *s, ctrl_buffer *c, byte *d, int payload){ if (payload > 0) { if (psi_size > 0) { memcpy (d,&psi_data[psi_done],payload); if (payload < psi_size) { warn (LSEC,"Splice PSI Data",ETSC,9,s->stream_id,payload); psi_done += payload; psi_size -= payload; unit_start = 0; } else { warn (LINF,"Splice PSI Done",ETSC,9,s->stream_id,payload); psi_done = psi_size = 0; unit_start = TS_UNIT_START; } } else { memcpy (d,&s->data.ptr[c->index],payload); if (payload < c->length) { warn (LSEC,"Splice Data",ETSC,9,s->stream_id,payload); c->length -= payload; s->data.out = (c->index += payload); unit_start = 0; } else { warn (LINF,"Splice Done",ETSC,9,s->stream_id,payload); list_incr (s->ctrl.out,s->ctrl,1); if (list_empty (s->ctrl)) { s->data.out = s->data.in; } else { s->data.out = s->ctrl.ptr[s->ctrl.out].index; } unit_start = TS_UNIT_START; return (NULL); } } } return (s);}/* Process unparsed si data and generate output. * Take one TS paket, copy it to output stream data buffer. * Precondition: s!=NULL, !list_empty(s->ctrl), s->streamdata==sd_unparsedsi, * s->ctrl.ptr[s->ctrl.out].length==TS_PACKET_SIZE, d!=NULL. */static void proc_unparsedsi (stream_descr *s, byte *d){ warn (LINF,"Splice Unparsed SI",ETSC,10,s->sourceid,s->streamdata); memcpy (d,&s->data.ptr[s->ctrl.ptr[s->ctrl.out].index],TS_PACKET_SIZE); /* check if == s->ctrl.ptr[s->ctrl.out].length); ? */ list_incr (s->ctrl.out,s->ctrl,1); if (list_empty (s->ctrl)) { s->data.out = s->data.in; input_closefileifunused (s->fdescr); } else { s->data.out = s->ctrl.ptr[s->ctrl.out].index; }}stream_descr *process_something (stream_descr *s){ byte *d; int pid; byte scramble; int size; ctrl_buffer *c; int payload; int space; int adapt_ext_len; byte adapt_field_ctrl; byte adapt_flags1, adapt_flags2; warn (LDEB,"Splice TS",ETSC,0,0,s->ctrl.out); switch (s->streamdata) { case sd_data: c = &s->ctrl.ptr[s->ctrl.out]; procdata_check_psi (&pid, &scramble, &size, s, c); d = output_pushdata (TS_PACKET_SIZE, TRUE, c->msecpush + s->u.d.delta); if (d == NULL) { return (s); } space = procdata_adaptfield_flags (&adapt_flags1, &adapt_flags2, &adapt_ext_len, s, c); payload = procdata_adaptfield_frame (&space, &adapt_field_ctrl, adapt_flags1, size); d = procdata_syn_head (d, pid, scramble, adapt_field_ctrl); d = procdata_syn_adaptfield (s, c, d, space-payload, payload, adapt_field_ctrl, adapt_flags1, adapt_flags2, adapt_ext_len); return (procdata_syn_payload (s, c, d, payload)); break; case sd_map: validate_mapref (s); return (NULL); break; case sd_unparsedsi: c = &s->ctrl.ptr[s->ctrl.out]; d = output_pushdata (TS_PACKET_SIZE, FALSE, 0); if (d == NULL) { return (s); } proc_unparsedsi (s,d); return (NULL); break; default: return (NULL); break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -