📄 splicets.c
字号:
/* * ISO 13818 stream multiplexer * Copyright (C) 2001 Convergence Integrated Media GmbH Berlin * Copyright (C) 2004 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: Splice TS * Purpose: Generate transport stream. * * This module generates from the available input stream data (as * seperated by the split functions) the complete output stream. * It provides functions to handle programs for the resulting stream, * as these are output format dependent. Further, it accepts PSI data * just in time, validating it not earlier than with the arrival of * the corresponding payload at this stage. */#include "global.h"#include "crc.h"#include "error.h"#include "input.h"#include "output.h"#include "descref.h"#include "splitts.h"#include "pes.h"#include "ts.h"#include "splice.h"#include "splicets.h"const boolean splice_multipleprograms = TRUE;static boolean changed_pat;static boolean unchanged_pat;static int pat_section;static const int last_patsection = 0;static byte nextpat_version;static byte pat_conticnt;static int transportstreamid;static int psi_size;static int psi_done;static byte psi_data [MAX_PSI_SIZE];static byte unit_start;static byte *conticnt;static int psi_pid;static int progs;static prog_descr *prog [MAX_OUTPROG];static int nextpid;static stream_descr *outs [MAX_STRPERTS];static stump_descr *globalstumps;boolean splice_specific_init (void){ progs = 0; nextpid = 0; memset (outs,0,sizeof(outs)); changed_pat = TRUE; pat_section = 0; nextpat_version = 0; pat_conticnt = 0; psi_size = psi_done = 0; unit_start = TS_UNIT_START; transportstreamid = 0x4227; globalstumps = NULL; return (TRUE);}void splice_settransportstreamid (int tsid){ transportstreamid = tsid;}void splice_setpsifrequency (t_msec freq){ psi_frequency_msec = freq; psi_frequency_changed = TRUE;}static int findapid (stream_descr *s, int desire){ byte okness = 2; int h; if (conservative_pid_assignment && (desire >= 0) && (outs[desire] == NULL) && (input_tssiinafilerange (desire) < 0)) { return (desire); } do { if ((nextpid < TS_PID_SPLICELO) || (nextpid >= TS_PID_SPLICEHI)) { warn (LDEB,"Next PID",ETSC,1,okness,nextpid); if (okness == 0) { warn (LERR,"No PID found",ETSC,2,1,0); return (0); } okness -= 1; nextpid = TS_PID_SPLICELO; } else { warn (LDEB,"Next PID",ETSC,2,okness,nextpid); nextpid += 1; } if (okness != 0) { h = input_tssiinafilerange (nextpid); warn (LDEB,"Next PID",ETSC,3,h,nextpid); if (h >= 0) { nextpid = h; } } else { h = -1; } } while ((h >= 0) || (outs[nextpid] != NULL)); outs[nextpid] = s; warn (LDEB,"Next PID",ETSC,2,2,nextpid); return (nextpid);}void splice_all_configuration (void){ int i; if (configuration_must_print) { i = progs; fprintf (stderr, configuration_total, i); while (--i >= 0) { splice_one_configuration (prog[i]); } configuration_was_printed; }}void splice_addsirange (file_descr *f, int lower, int upper){ int i, r; tssi_descr *tssi; prog_descr *p; tssi = malloc (sizeof (tssi_descr)); if (tssi != NULL) { if (ts_file_stream (f,TS_UNPARSED_SI) == NULL) { ts_file_stream (f,TS_UNPARSED_SI) = input_openstream (f, TS_UNPARSED_SI,0,0,sd_unparsedsi,NULL); } if (ts_file_stream (f,TS_UNPARSED_SI) != NULL) { tssi->next = f->u.ts.tssi; tssi->pid_low = lower; tssi->pid_high = upper; f->u.ts.tssi = tssi; r = upper; /* check for collision against existing PIDs, first sd_data */ while (r >= lower) { stream_descr *s; s = outs[r]; if ((s != NULL) && (s != PMT_STREAM)) { if (s->streamdata == sd_data) { i = findapid (s, -1); if (input_tssiinafilerange (i) >= 0) { /* none free! */ outs[i] = NULL; } else { int j; s->u.d.pid = i; j = s->u.d.progs; while (--j >= 0) { p = s->u.d.pdescr[j]; p->changed = TRUE; if (p->pcr_pid == r) { p->pcr_pid = i; } } configuration_changed = TRUE; outs[r] = NULL; } } else { warn (LERR,"Bad PID",ETSC,11,s->streamdata,r); } } r -= 1; } i = progs; /* ...then sd_map */ while (--i >= 0) { p = prog[i]; r = p->pmt_pid; if ((r >= lower) && (r <= upper)) { int q; q = findapid (PMT_STREAM, -1); if (input_tssiinafilerange (q) >= 0) { /* none free! */ outs[q] = NULL; } else { int j; outs[r] = NULL; j = i; while (--j >= 0) { if (prog[j]->pmt_pid == r) { prog[j]->pmt_pid = q; } } p->pmt_pid = q; changed_pat = TRUE; configuration_changed = TRUE; } } } } else { free (tssi); } }}void splice_createstump (int programnb, short pid, byte styp){ prog_descr *p; stump_descr **pst; stump_descr *st; p = splice_getprog (programnb); if (p != NULL) { configuration_changed = TRUE; p->changed = TRUE; pst = &(p->stump); } else { pst = &globalstumps; } st = *pst; while ((st != NULL) && ((st->pid != pid) || (st->program_number != programnb))) { st = st->next; } if (st == NULL) { st = malloc (sizeof(stump_descr)); st->next = *pst; st->program_number = programnb; st->pid = pid; *pst = st; } st->stream_type = styp; clear_descrdescr (&(st->manudescr)); splice_modifycheckmatch (programnb,p,NULL,st);}stump_descr *splice_getstumps (int programnb, short pid){ prog_descr *p; stump_descr **pst; stump_descr *rl; rl = NULL; p = splice_getprog (programnb); if (p != NULL) { pst = &(p->stump); } else { pst = &globalstumps; } while (*pst != NULL) { stump_descr *st; st = *pst; if ((st->program_number == programnb) && ((pid < 0) || (pid == st->pid))) { st = *pst; *pst = st->next; st->next = rl; rl = st; if (p != NULL) { configuration_changed = TRUE; p->changed = TRUE; } } else { pst = &((*pst)->next); } } return (rl);}void splice_modifytargetdescriptor (int programnb, short sid, short pid, int dtag, int dlength, byte *data){ int i; if (programnb < 0) { i = progs; while (--i >= 0) { splice_modifytargetdescrprog (prog[i], prog[i]->program_number,-1,0,-1,-1,NULL,globalstumps); } splice_modifytargetdescrprog (NULL,-1,-1,0,-1,-1,NULL,globalstumps); } else { splice_modifytargetdescrprog (splice_getprog (programnb), programnb,sid,pid,dtag,dlength,data,globalstumps); }}prog_descr *splice_getprog (int programnb){ int i; i = progs; while (--i >= 0) { if (prog[i]->program_number == programnb) { return (prog[i]); } } return (NULL);}prog_descr *splice_openprog (int programnb){ prog_descr *p; int pid; warn (LIMP,"Open prog",ETSC,1,0,programnb); p = splice_getprog (programnb); if (p == NULL) { if (progs < MAX_OUTPROG) { if ((pid = findapid (PMT_STREAM, -1)) > 0) { if ((p = malloc(sizeof(prog_descr))) != NULL) { p->program_number = programnb; p->pcr_pid = -1; p->pmt_pid = pid; p->pmt_conticnt = 0; p->pmt_version = 0; p->changed = TRUE; p->pat_section = 0; /* more ? */ p->streams = 0; p->stump = splice_getstumps (programnb,-1); clear_descrdescr (&p->manudescr); prog[progs++] = p; changed_pat = TRUE; configuration_changed = TRUE; splice_modifycheckmatch (programnb,p,NULL,NULL); } else { outs[pid] = NULL; warn (LERR,"Open prog",ETSC,1,1,0); } } } else { warn (LERR,"Max prog open",ETSC,1,2,0); } } return (p);}void splice_closeprog (prog_descr *p){ int i, n; warn (LIMP,"Close prog",ETSC,3,0,p->program_number); configuration_changed = TRUE; while (p->streams > 0) { unlink_streamprog (p->stream[0],p); } releasechain (stump_descr,p->stump); n = -1; if (p->pmt_pid >= 0) { i = progs; while (--i >= 0) { if (prog[i]->pmt_pid == p->pmt_pid) { n += 1; } } } i = progs; while (--i >= 0) { if (prog[i] == p) { prog[i] = prog[--progs]; if (n == 0) { outs[p->pmt_pid] = NULL; } free (p); changed_pat = TRUE; return; } } warn (LERR,"Close lost prog",ETSC,3,1,progs);}int splice_addstream (prog_descr *p, stream_descr *s, boolean force_sid){ int pid = 0; warn (LIMP,"Add stream",ETSC,4,force_sid,s->stream_id); if (p->streams < MAX_STRPERPRG) { pid = findapid (s,(s->fdescr->content == ct_transport) ? s->sourceid : -1); if (pid > 0) { if (!force_sid) { s->stream_id = splice_findfreestreamid (p,s->stream_id); } p->stream[p->streams++] = s; p->changed = TRUE; s->u.d.pid = pid; configuration_changed = TRUE; splice_modifycheckmatch (p->program_number,p,s,NULL); } } return (pid);}boolean splice_delstream (prog_descr *p, stream_descr *s){ int i; warn (LIMP,"Del stream",ETSC,5,0,s->u.d.pid); configuration_changed = TRUE; i = p->streams; while (--i >= 0) { if (p->stream[i] == s) { outs[s->u.d.pid] = NULL; p->stream[i] = p->stream[--(p->streams)]; p->changed = TRUE; if (p->pcr_pid == s->u.d.pid) { p->pcr_pid = -1; } s->u.d.pid = 0; return (TRUE); } } warn (LERR,"Del lost stream",ETSC,5,1,p->streams); return (FALSE);}void process_finish (void){ warn (LIMP,"Finish",ETSC,6,0,0);}static int make_patsection (int section, byte *dest){ int i; byte *d; prog_descr *p; d = dest; *d++ = TS_TABLEID_PAT; d += 2; *d++ = transportstreamid >> 8; *d++ = (byte)transportstreamid; *d++ = 0xC0 | 0x01 | (nextpat_version << 1); *d++ = section; *d++ = last_patsection; i = progs; while (--i >= 0) { p = prog[i]; if (p->pat_section == section) { int x; x = p->program_number; *d++ = (x >> 8); *d++ = x; x = p->pmt_pid; *d++ = 0xE0 | (x >> 8); *d++ = x; } } 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);}static int make_pmtsection (stream_descr *s, prog_descr *p, byte *dest){ int i; byte *d; stump_descr *st; stream_descr *t; d = dest; *d++ = TS_TABLEID_PMT; d += 2; i = p->program_number; *d++ = (i >> 8); *d++ = i; *d++ = 0xC0 | 0x01 | (p->pmt_version << 1); *d++ = 0; *d++ = 0; if (p->pcr_pid < 0) { stream_descr *pcrs; pcrs = splice_findpcrstream (p); if (pcrs == NULL) { pcrs = s; } pcrs->u.d.has_clockref = TRUE; pcrs->u.d.next_clockref = msec_now () - MAX_MSEC_PCRDIST; p->pcr_pid = pcrs->u.d.pid; configuration_changed = TRUE; } i = p->pcr_pid; *d++ = 0xE0 | (i >> 8); *d++ = i; d += 2; i = NUMBER_DESCR; while (--i >= 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -