📄 splitts.c
字号:
/* * ISO 13818 stream multiplexer * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin * Author: Oskar Schirmer (schirmer@scara.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* * Module: Split TS * Purpose: Split a transport stream. * * This module examines a transport stream and collects the packets to * the input stream buffers. PSI data is extracted (and stored in the * files pat structures), descriptors are copied to the corresponding * mapstreams. */#include "global.h"#include "error.h"#include "input.h"#include "splice.h"#include "ts.h"#include "pes.h"#include "descref.h"#include "splitpes.h"#include "splitts.h"#include "crc.h"static byte pusi, afcc, afflg1;static int paylen;/* Skip in input raw data buffer for TS-syncbyte. * Precondition: f!=NULL * Postcondition: if found: f->data.out indicates the syncbyte. * Return: TRUE if found, FALSE otherwise */static boolean ts_skip_to_syncbyte (file_descr *f){ int i, l, k; boolean r = FALSE; l = k = list_size (f->data); i = f->data.out; while ((l > 0) && ((f->data.ptr[i] != TS_SYNC_BYTE) || (r = TRUE, FALSE))) { list_incr (i,f->data,1); l -= 1; } k -= l; if (k > 0) { warn (LWAR,"Skipped",ETST,1,1,k); f->skipped += k; f->total += k; list_incr (f->data.out,f->data,k); } return (r);}/* Determine the PID of a TS packet and other details. * Procondition: d!=NULL points to a packet. * Postcondition: Set global "Payload Unit Start Indicator", "Adaption Field * Control & Continuity Counter", "Adataption Field Flags 1". * Return: 13 bit PID. */static int ts_packet_headinfo (refr_data *d){ int i, l; i = d->out; list_incr (i,*d,TS_PACKET_PID); l = (pusi = d->ptr[i]) & 0x1F; list_incr (i,*d,1); l = (l << 8) | d->ptr[i]; list_incr (i,*d,1); if (!((afcc = d->ptr[i]) & TS_AFC_BOTH)) { l = TS_PID_NULL; } else { if (afcc & TS_AFC_ADAPT) { byte aflen; list_incr (i,*d,1); if ((aflen = d->ptr[i]) == 0) { afflg1 = 0x00; } else { list_incr (i,*d,1); afflg1 = d->ptr[i]; } paylen = TS_PACKET_SIZE - TS_PACKET_FLAGS1 - aflen; } else { paylen = TS_PACKET_SIZE - TS_PACKET_HEADSIZE; } } warn (LSEC,"Packet PID",ETST,2,1,l); warn (LDEB,"Packet PID",ETST,afcc,afflg1,paylen); return (l);}/* Extract adaption field from a TS packet. * Distribute the information as needed (to s, s->ctrl, etc). * Precondition: f!=NULL, adf indicates a packet in f->data, s!=NULL is the * destined data stream, m!=NULL the map stream, afcc and afflg1 set. */static void ts_adaption_field (file_descr *f, int adf, stream_descr *s, stream_descr *m){ warn (LDEB,"AdaptF",ETST,11,adf,afcc); if (afcc & TS_AFC_ADAPT) { list_incr (adf,f->data,TS_PACKET_FLAGS1+1); if (afflg1 & TS_ADAPT_DISCONTI) { } if (afflg1 & TS_ADAPT_RANDOMAC) { } if (afflg1 & TS_ADAPT_PRIORITY) { } if (afflg1 & TS_ADAPT_PCRFLAG) { clockref *pcr; long b; byte a; pcr = &s->ctrl.ptr[s->ctrl.in].pcr; a = f->data.ptr[adf]; list_incr (adf,f->data,1); pcr->ba33 = (a >> 7) & 1; b = (a << 8) | f->data.ptr[adf]; list_incr (adf,f->data,1); b = (b << 8) | f->data.ptr[adf]; list_incr (adf,f->data,1); b = (b << 8) | f->data.ptr[adf]; list_incr (adf,f->data,1); a = f->data.ptr[adf]; pcr->base = (b << 1) | ((a >> 7) & 1); marker_check (a,0x7E,0x7E); list_incr (adf,f->data,1); pcr->ext = ((a & 1) << 8) | f->data.ptr[adf]; warn (LINF,"PCR",ETST,10,pcr->ba33,pcr->base); pcr->valid = TRUE; list_incr (adf,f->data,1);/* attention ! what if it is not PCR_PID ? xxx */ if (S_ISREG (f->st_mode)) { cref2msec (&m->u.m.conv, *pcr, &m->u.m.msectime); } else { cref2msec (&m->u.m.conv, *pcr, &m->u.m.msectime); } } if (afflg1 & TS_ADAPT_OPCRFLAG) { clockref *opcr; long b; byte a; opcr = &s->ctrl.ptr[s->ctrl.in].opcr; a = f->data.ptr[adf]; list_incr (adf,f->data,1); opcr->ba33 = (a >> 7) & 1; b = (a << 8) | f->data.ptr[adf]; list_incr (adf,f->data,1); b = (b << 8) | f->data.ptr[adf]; list_incr (adf,f->data,1); b = (b << 8) | f->data.ptr[adf]; list_incr (adf,f->data,1); a = f->data.ptr[adf]; opcr->base = (b << 1) | ((a >> 7) & 1); marker_check (a,0x7E,0x7E); list_incr (adf,f->data,1); opcr->ext = ((a & 1) << 8) | f->data.ptr[adf]; warn (LINF,"OPCR",ETST,10,opcr->ba33,opcr->base); opcr->valid = TRUE; s->u.d.has_opcr = TRUE; list_incr (adf,f->data,1); } if (afflg1 & TS_ADAPT_SPLICING) { list_incr (adf,f->data,1); } if (afflg1 & TS_ADAPT_TPRIVATE) { byte tpdl; tpdl = f->data.ptr[adf]; list_incr (adf,f->data,tpdl+1); } if (afflg1 & TS_ADAPT_EXTENSIO) { byte afflg2, afel; afel = f->data.ptr[adf]; list_incr (adf,f->data,1); afflg2 = f->data.ptr[adf]; list_incr (adf,f->data,1); if (afflg2 & TS_ADAPT2_LTWFLAG) { list_incr (adf,f->data,2); } if (afflg2 & TS_ADAPT2_PIECEWRF) { list_incr (adf,f->data,3); } if (afflg2 & TS_ADAPT2_SEAMLESS) { list_incr (adf,f->data,5); } } }}/* Parse one TS packet with given PID. * Depending on the actual state (c->length) and the contents of the packet, * provide the data into the stream and possibly complete a PES package. * c->length keeps the progress of data acquisition, as follows: * =0: initial, waiting for payload unit start indicator * <-2, increasing: not yet enough data to evaluate the PES header * =-2: evaluate the PES packet length field * =-1: acquiring packet with unspecified length * >0, decreasing: amount of data still missing * =0: final, close PES packet, start new one * Precondition: f!=NULL. * Return: TRUE if something was processed, FALSE if no data/space available */static boolean ts_data_stream (file_descr *f, int pid){ stream_descr *s; ctrl_buffer *c; int i, fdo, sdi, adf; warn (LDEB,"Data Packet",ETST,3,0,pid); s = ts_file_stream (f,pid); if (s != NULL) { if (!list_full (s->ctrl)) { c = &s->ctrl.ptr[s->ctrl.in]; if (c->length == -1) { if (pusi & TS_UNIT_START) { c->length = s->data.in - c->index; warn (LINF,"Closed unbound packet",ETST,3,5,c->length); f->payload += c->length; c->sequence = f->sequence++; c->scramble = 0; c->msecread = msec_now (); c->msecpush = s->u.d.mapstream->u.m.msectime; list_incr (s->ctrl.in,s->ctrl,1); c = &s->ctrl.ptr[s->ctrl.in]; c->length = 0; c->pcr.valid = FALSE; c->opcr.valid = FALSE; } } if (c->length == 0) { if (pusi & TS_UNIT_START) { if (list_free (s->data) >= (2*(PES_HEADER_SIZE-1+TS_PACKET_SIZE-TS_PACKET_HEADSIZE)-1)) { if ((PES_HEADER_SIZE-1+TS_PACKET_SIZE-TS_PACKET_HEADSIZE) > list_freeinend (s->data)) { s->data.in = 0; } c->index = s->data.in; c->length = -2 - PES_HEADER_SIZE; } else { return (FALSE); } } else { f->skipped += TS_PACKET_SIZE; list_incr (f->data.out,f->data,TS_PACKET_SIZE); f->total += TS_PACKET_SIZE; return (TRUE); } } sdi = s->data.in; fdo = adf = f->data.out; list_incr (fdo,f->data,TS_PACKET_SIZE - paylen); if (c->length == -1) { if (list_freecachedin (s->data,sdi) >= paylen) { i = list_freeinendcachedin (s->data,sdi); if (i <= paylen) { if (list_freecachedin (s->data,sdi) >= (i + (sdi - c->index) + paylen)) { sdi -= c->index; memmove (&s->data.ptr[0],&s->data.ptr[c->index],sdi); c->index = 0; } else { return (FALSE); } } while (paylen > 0) { i = MAX_DATA_RAWB - fdo; if (i > paylen) { i = paylen; } memcpy (&s->data.ptr[sdi],&f->data.ptr[fdo],i); list_incr (sdi,s->data,i); list_incr (fdo,f->data,i); paylen -= i; } } else { return (FALSE); } } if (c->length < -2) { c->length += paylen; while (paylen > 0) { i = MAX_DATA_RAWB - fdo; if (i > paylen) { i = paylen; } memcpy (&s->data.ptr[sdi],&f->data.ptr[fdo],i); list_incr (sdi,s->data,i); list_incr (fdo,f->data,i); paylen -= i; } if (c->length > -2) { c->length = -2; } } if (c->length == -2) { if ((s->data.ptr[c->index] != 0x00) || (s->data.ptr[c->index+1] != 0x00) || (s->data.ptr[c->index+2] != 0x01)) { warn (LWAR,"Payload not good PES",ETST,3,3,0); c->length = 0; return (TRUE); } i = (s->data.ptr[c->index+PES_PACKET_LENGTH] << 8) | s->data.ptr[c->index+PES_PACKET_LENGTH+1]; if (i == 0) { warn (LSEC,"Payload length 0",ETST,3,4,0); c->length = -1; } else { if (i > list_freeinendcachedin (s->data,c->index) - PES_HEADER_SIZE) { if (list_freecachedin (s->data,sdi) < (2 * (i + PES_HEADER_SIZE) - (sdi - c->index) - 1)) { return (FALSE); } else { sdi -= c->index; memmove (&s->data.ptr[0],&s->data.ptr[c->index],sdi); c->index = 0; } } else { if (list_freecachedin (s->data,sdi) < (i + PES_HEADER_SIZE - (sdi - c->index))) { return (FALSE); } } c->length = i + PES_HEADER_SIZE - (sdi - c->index); if (c->length < 0) { warn (LWAR,"Too much payload",ETST,3,1,c->length); c->length = 0; } } } if ((c->length > 0) && (paylen > 0)) { if (paylen > c->length) { warn (LWAR,"Too much payload",ETST,3,2,c->length); paylen = c->length; } c->length -= paylen; while (paylen > 0) { i = MAX_DATA_RAWB - fdo; if (i > paylen) { i = paylen; } memcpy (&s->data.ptr[sdi],&f->data.ptr[fdo],i); list_incr (sdi,s->data,i); list_incr (fdo,f->data,i); paylen -= i; } } s->data.in = sdi; f->data.out = fdo; ts_adaption_field (f,adf,s,s->u.d.mapstream); if (c->length == 0) { c->length = s->data.in - c->index; f->payload += c->length; c->sequence = f->sequence++; c->scramble = 0; c->msecread = msec_now (); c->msecpush = s->u.d.mapstream->u.m.msectime; list_incr (s->ctrl.in,s->ctrl,1); c = &s->ctrl.ptr[s->ctrl.in]; c->length = 0; c->pcr.valid = FALSE; c->opcr.valid = FALSE; } } else { return (FALSE); } } else { list_incr (f->data.out,f->data,TS_PACKET_SIZE); } f->total += TS_PACKET_SIZE; return (TRUE);}/* Process changes that arise from a new PMT. * Match the new PMT with the existing PAT/PMT and adjust this to * reflect the changes in the TS. Try to keep PIDs etc stable. * Precondition: f!=NULL, new!=NULL the partial new PMT */static void remap_new_program (file_descr *f, pmt_descr *new){ pmt_descr* p; int i, j, k;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -