/dvbstream.c
C | 1645 lines | 1244 code | 165 blank | 236 comment | 392 complexity | e436117d7f0f5a2bfb0c2fcaafdbb92b MD5 | raw file
Possible License(s): GPL-2.0
- /*
- dvbstream - RTP-ize a DVB transport stream.
- (C) Dave Chapman <dave@dchapman.com> 2001, 2002.
- The latest version can be found at http://www.linuxstb.org/dvbstream
- Copyright notice:
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
- // Linux includes:
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <sys/ioctl.h>
- #include <sys/time.h>
- #include <sys/poll.h>
- #include <sys/stat.h>
- #include <resolv.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <signal.h>
- #include <values.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- // DVB includes:
- #include <linux/dvb/dmx.h>
- #include <linux/dvb/frontend.h>
- #include "rtp.h"
- #include "mpegtools/transform.h"
- #include "mpegtools/remux.h"
- #include "tune.h"
- // The default telnet port.
- #define DEFAULT_PORT 12345
- #define USAGE "\nUSAGE: dvbstream tpid1 tpid2 tpid3 .. tpid8\n\n"
- #define PACKET_SIZE 188
- // How often (in seconds) to update the "now" variable
- #define ALARM_TIME 5
- /* Thanks to Giancarlo Baracchino for this fix */
- #define MTU 1500
- #define IP_HEADER_SIZE 20
- #define UDP_HEADER_SIZE 8
- #define RTP_HEADER_SIZE 12
- #define MAX_RTP_SIZE (MTU-IP_HEADER_SIZE-UDP_HEADER_SIZE-RTP_HEADER_SIZE)
- #define writes(f,x) write((f),(x),strlen(x))
- /* Signal handling code shamelessly copied from VDR by Klaus Schmidinger
- - see http://www.cadsoft.de/people/kls/vdr/index.htm */
- unsigned int SLOF=(11700*1000UL);
- unsigned int LOF1=(5150*1000UL);
- unsigned int LOF2=(10750*1000UL);
- char* frontenddev[4]={"/dev/dvb/adapter0/frontend0","/dev/dvb/adapter1/frontend0","/dev/dvb/adapter2/frontend0","/dev/dvb/adapter3/frontend0"};
- char* dvrdev[4]={"/dev/dvb/adapter0/dvr0","/dev/dvb/adapter1/dvr0","/dev/dvb/adapter2/dvr0","/dev/dvb/adapter3/dvr0"};
- char* demuxdev[4]={"/dev/dvb/adapter0/demux0","/dev/dvb/adapter1/demux0","/dev/dvb/adapter2/demux0","/dev/dvb/adapter3/demux0"};
- int card=0;
- long now;
- long real_start_time;
- int Interrupted=0;
- fe_spectral_inversion_t specInv=INVERSION_AUTO;
- int tone=-1;
- fe_modulation_t modulation=CONSTELLATION_DEFAULT;
- fe_transmit_mode_t TransmissionMode=TRANSMISSION_MODE_DEFAULT;
- fe_bandwidth_t bandWidth=BANDWIDTH_DEFAULT;
- fe_guard_interval_t guardInterval=GUARD_INTERVAL_DEFAULT;
- fe_code_rate_t HP_CodeRate=HP_CODERATE_DEFAULT, LP_CodeRate=LP_CODERATE_DEFAULT;
- fe_hierarchy_t hier=HIERARCHY_DEFAULT;
- unsigned char diseqc=0;
- char pol=0;
- int streamtype = RTP;
- static int use_stdin=0;
- #define PID_MODE 0
- #define PROG_MODE 1
- static int selection_mode = PID_MODE;
- int open_fe(int* fd_frontend) {
- if((*fd_frontend = open(frontenddev[card],O_RDWR | O_NONBLOCK)) < 0){
- perror("FRONTEND DEVICE: ");
- return -1;
- }
- return 1;
- }
- static void SignalHandler(int signum) {
- struct timeval tv;
- if (signum == SIGALRM) {
- gettimeofday(&tv,(struct timezone*) NULL);
- now=tv.tv_sec-real_start_time;
- alarm(ALARM_TIME);
- } else if (signum != SIGPIPE) {
- Interrupted=signum;
- }
- signal(signum,SignalHandler);
- }
- long getmsec() {
- struct timeval tv;
- gettimeofday(&tv,(struct timezone*) NULL);
- return(tv.tv_sec%1000000)*1000 + tv.tv_usec/1000;
- }
- // There seems to be a limit of 16 simultaneous filters in the driver
- #define MAX_CHANNELS 16
- void set_ts_filt(int fd,uint16_t pid, dmx_pes_type_t pestype)
- {
- struct dmx_pes_filter_params pesFilterParams;
- //fprintf(stderr,"Setting filter for PID %d\n",pid);
- pesFilterParams.pid = pid;
- pesFilterParams.input = DMX_IN_FRONTEND;
- pesFilterParams.output = DMX_OUT_TS_TAP;
- pesFilterParams.pes_type = pestype;
- pesFilterParams.flags = DMX_IMMEDIATE_START;
- if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
- fprintf(stderr,"Failed setting filter for pid %i: ",pid);
- perror("DMX SET PES FILTER");
- }
- }
- void make_nonblock(int f) {
- int oldflags;
- if ((oldflags=fcntl(f,F_GETFL,0)) < 0) {
- perror("F_GETFL");
- }
- oldflags|=O_NONBLOCK;
- if (fcntl(f,F_SETFL,oldflags) < 0) {
- perror("F_SETFL");
- }
- }
- typedef enum {STREAM_ON,STREAM_OFF} state_t;
- int socketIn, ns;
- int pids[MAX_CHANNELS];
- int pestypes[MAX_CHANNELS];
- unsigned char hi_mappids[8192];
- unsigned char lo_mappids[8192];
- int fd_frontend;
- int pid,pid2;
- int connectionOpen;
- int fromlen;
- char hostname[64];
- char in_ch;
- struct hostent *hp;
- struct sockaddr_in name, fsin;
- int ReUseAddr=1;
- int oldflags;
- int npids = 0;
- int fd[MAX_CHANNELS];
- int to_stdout = 0; /* to stdout instead of rtp stream */
- /* rtp */
- struct rtpheader hdr;
- struct sockaddr_in sOut;
- int socketOut;
- ipack pa, pv;
- #define IPACKS 2048
- #define TS_SIZE 188
- #define IN_SIZE TS_SIZE
- /*
- int process_telnet() {
- char cmd[1024];
- int cmd_i=0;
- int i;
- char* ch;
- dmx_pes_type_t pestype;
- unsigned long freq=0;
- unsigned long srate=0;
- // Open a new telnet session if a client is trying to connect
- if (ns==-1) {
- if ((ns = accept(socketIn, (struct sockaddr *)&fsin, &fromlen)) > 0) {
- make_nonblock(ns);
- cmd_i=0;
- cmd[0]=0;
- printf("Opened connection\n");
- writes(ns,"220-DVBSTREAM - ");
- writes(ns,hostname);
- writes(ns,"\r\nDONE\r\n");
- connectionOpen=1;
- }
- }
- // If a telnet session is open, receive and process any input
- if (connectionOpen) {
- // Read in at most a line of text - any ctrl character ends the line
- while (read(ns,&in_ch,1)>0) {
- if (in_ch < 32) break;
- // Prevent buffer overflows
- if (cmd_i < 1024-1) {
- cmd[cmd_i++]=in_ch;
- cmd[cmd_i]=0;
- }
- }
- if (in_ch > 0) {
- if (cmd_i > 0) {
- printf("CMD: \"%s\"\n",cmd);
- if (strcasecmp(cmd,"QUIT")==0) {
- writes(ns,"DONE\r\n");
- close(ns);
- ns=-1;
- connectionOpen=0;
- printf("Closed connection\n");
- } else if (strcasecmp(cmd,"STOP")==0) {
- writes(ns,"STOP\n");
- for (i=0;i<npids;i++) {
- if (ioctl(fd[i], DMX_STOP) < 0) {
- perror("DMX_STOP");
- }
- }
- for (i=0;i<8192;i++) {
- hi_mappids[i]=(i >> 8);
- lo_mappids[i]=(i&0xff);
- }
- writes(ns,"DONE\r\n");
- } else if (strncasecmp(cmd,"ADD",3)==0) {
- i=4;
- if ((cmd[3]=='V') || (cmd[3]=='v')) pestype=DMX_PES_VIDEO;
- else if ((cmd[3]=='A') || (cmd[3]=='a')) pestype=DMX_PES_AUDIO;
- else if ((cmd[3]=='T') || (cmd[3]=='t')) pestype=DMX_PES_TELETEXT;
- else { pestype=DMX_PES_OTHER; i=3; }
- while (cmd[i]==' ') i++;
- if ((ch=(char*)strstr(&cmd[i],":"))!=NULL) {
- pid2=atoi(&ch[1]);
- ch[0]=0;
- } else {
- pid2=-1;
- }
- pid=atoi(&cmd[i]);
- if (pid) {
- if (npids == MAX_CHANNELS) {
- fprintf(stderr,"\nsorry, you can only set up to 8 filters.\n\n");
- return(-1);
- } else {
- pestypes[npids]=pestype;
- pestype=DMX_PES_OTHER;
- pids[npids]=pid;
- if (pid2!=-1) {
- hi_mappids[pid]=pid2>>8;
- lo_mappids[pid]=pid2&0xff;
- fprintf(stderr,"Mapping %d to %d\n",pid,pid2);
- }
-
- if((fd[npids] = open(demuxdev[card],O_RDWR|O_NONBLOCK)) < 0){
- fprintf(stderr,"FD %i: ",i);
- perror("DEMUX DEVICE: ");
- } else {
- set_ts_filt(fd[npids],pids[npids],pestypes[npids]);
- npids++;
- }
- }
- }
- writes(ns,"DONE\r\n");
- } else if (strcasecmp(cmd,"START")==0) {
- writes(ns,"START\n");
- for (i=0;i<npids;i++) {
- set_ts_filt(fd[i],pids[i],pestypes[i]);
- }
- writes(ns,"DONE\r\n");
- } else if (strncasecmp(cmd,"TUNE",4)==0) {
- for (i=0;i<8192;i++) {
- hi_mappids[i]=(i >> 8);
- lo_mappids[i]=(i&0xff);
- }
- for (i=0;i<npids;i++) {
- if (ioctl(fd[i], DMX_STOP) < 0) {
- perror("DMX_STOP");
- close(fd[i]);
- }
- }
- npids=0;
- i=4;
- while (cmd[i]==' ') i++;
- freq=atoi(&cmd[i]);
- while ((cmd[i]!=' ') && (cmd[i]!=0)) i++;
- if (cmd[i]!=0) {
- while (cmd[i]==' ') i++;
- pol=cmd[i];
- while ((cmd[i]!=' ') && (cmd[i]!=0)) i++;
- if (cmd[i]!=0) {
- while (cmd[i]==' ') i++;
- srate=atoi(&cmd[i])*1000UL;
- fprintf(stderr,"Tuning to %ld,%ld,%c\n",freq,srate,pol);
- if(!use_stdin)
- tune_it(fd_frontend,freq,srate,pol,tone,specInv,diseqc,modulation,HP_CodeRate,TransmissionMode,guardInterval,bandWidth, LP_CodeRate, hier);
- }
- }
- }
- cmd_i=0;
- cmd[0]=0;
- writes(ns,"DONE\r\n");
- }
- }
- }
- return(0);
- }
- */
- /* The output routine for sending a PS */
- void my_write_out(uint8_t *buf, int count,void *p)
- {
- /* to fix: change this buffer size and check for overflow */
- static uint8_t out_buffer[1000000];
- static int out_buffer_n=0;
- int i;
- if (to_stdout) {
- /* This one is easy. */
- write(STDOUT_FILENO, buf, count);
- } else { /* We are streaming it. */
- /* Copy data to write to the end of out_buffer */
- memcpy(&out_buffer[out_buffer_n],buf,count);
- out_buffer_n+=count;
- /* Send as many full packets as possible */
- i=0;
- while ((i + MAX_RTP_SIZE) < out_buffer_n) {
- hdr.timestamp = getmsec()*90;
- sendrtp2(socketOut,&sOut,&hdr,&out_buffer[i],MAX_RTP_SIZE);
- i+=MAX_RTP_SIZE;
- }
- /* Move whatever data is left to the start of the buffer */
- memmove(&out_buffer[0],&out_buffer[i],out_buffer_n-i);
- out_buffer_n-=i;
- }
- }
- void my_ts_to_ps( uint8_t* buf, uint16_t pida, uint16_t pidv)
- {
- uint16_t pid;
- ipack *p;
- uint8_t off = 0;
- pid = get_pid(buf+1);
- if (!(buf[3]&0x10)) // no payload?
- return;
- if (pid == pidv){
- p = &pv;
- } else {
- if (pid == pida){
- p = &pa;
- } else return;
- }
- if ( buf[1]&0x40) {
- if (p->plength == MMAX_PLENGTH-6){
- p->plength = p->found-6;
- p->found = 0;
- send_ipack(p);
- reset_ipack(p);
- }
- }
- if ( buf[3] & 0x20) { // adaptation field?
- off = buf[4] + 1;
- }
-
- instant_repack(buf+4+off, TS_SIZE-4-off, p);
- }
- typedef uint8_t PID_BIT_MAP[1024];
- static PID_BIT_MAP SI_PIDS;
- static PID_BIT_MAP USER_PIDS;
- typedef struct {
- char *filename;
- int fd;
- int pids[MAX_CHANNELS];
- int num;
- int pid_cnt;
- int progs[MAX_CHANNELS];
- int progs_cnt;
- uint8_t **prognames;
- int prognames_cnt;
- PID_BIT_MAP pidmap;
- long start_time; // in seconds
- long end_time; // in seconds
- int socket;
- struct rtpheader hdr;
- struct sockaddr_in sOut;
- unsigned char buf[MTU];
- unsigned char net[20];
- int pos;
- int port;
- } pids_map_t;
- pids_map_t *pids_map;
- int map_cnt;
- //1024 section payload +1 pointer +256 pointer value
- #define SECTION_LEN 1281
- typedef struct {
- uint8_t buf[SECTION_LEN];
- unsigned int pos;
- } section_t;
- typedef struct {
- int program;
- int pmt_pid;
- } pat_entry;
- static struct {
- int len; //section length
- int version;
- section_t section;
- pat_entry *entries;
- int entries_cnt;
- } PAT;
- #define MAX_PIDS 202
- typedef struct {
- section_t section;
- int version;
- int pids[MAX_PIDS];
- int pids_cnt;
- uint8_t name[256];
- } pmt_t;
- struct {
- pmt_t *entries;
- int cnt;
- } PMT;
- static struct {
- int len; //section length
- int version;
- section_t section;
- } SDT;
- static int SI_fd[MAX_CHANNELS];
- static int SI_fd_cnt = 0;
- #define SDT_PID 0x11
- #define getbit(buf, pid) (buf[(pid)/8] & (1 << ((pid) % 8)))
- #define mysetbit(buf, pid) buf[(pid)/8] |= (1 << ((pid) % 8))
- #define clearbits(buf) memset(buf, 0, sizeof(PID_BIT_MAP))
- #define setallbits(buf) memset(buf, 0xFF, sizeof(PID_BIT_MAP))
- #define min(x, y) ((x) <= (y) ? (x) : (y))
- void update_bitmaps()
- {
- int i, j, k, n;
- for(i = 0; i < map_cnt; i++)
- {
- clearbits(pids_map[i].pidmap);
- mysetbit(pids_map[i].pidmap, 0);
- for(j = 0; j < MAX_CHANNELS; j++)
- {
- if(pids_map[i].pids[j] == -1) break;
- if(pids_map[i].pids[j] == 8192)
- {
- setallbits(pids_map[i].pidmap);
- break;
- }
- mysetbit(pids_map[i].pidmap, pids_map[i].pids[j]);
- for(k = 0; k < PMT.cnt; k++)
- {
- for(n = 0; n < PMT.entries[k].pids_cnt; n++)
- {
- if(PMT.entries[k].pids[n] == pids_map[i].pids[j])
- {
- //add the pmt_pid to the map
- //fprintf(stderr, "ADDING TO map %d PMT n. %d with PID: %d, j: %d\n", i, k, PAT.entries[k].pmt_pid, j);
- mysetbit(pids_map[i].pidmap, PAT.entries[k].pmt_pid);
- }
- }
- }
- }
- }
- for(j = 0; j < map_cnt; j++)
- {
- for(k = 0; k < pids_map[j].progs_cnt; k++)
- {
- for(i = 0; i < PAT.entries_cnt; i++)
- {
- if(pids_map[j].progs[k] == PAT.entries[i].program)
- {
- mysetbit(pids_map[j].pidmap, PAT.entries[i].pmt_pid);
- mysetbit(pids_map[j].pidmap, SDT_PID);
- for(n = 0; n < PMT.entries[i].pids_cnt; n++)
- {
- int pid = PMT.entries[i].pids[n];
- mysetbit(pids_map[j].pidmap, pid);
- //fprintf(stderr, "\nADDED to map %d PROG pid %d, prog: %d", j, pid, PAT.entries[i].program);
- }
- }
- }
- }
- }
- for(i = 0; i < map_cnt; i++)
- {
- for(j = 0; j < pids_map[i].prognames_cnt; j++)
- {
- for(k = 0; k < PMT.cnt; k++)
- {
- if(!strcmp(pids_map[i].prognames[j], PMT.entries[k].name))
- {
- mysetbit(pids_map[i].pidmap, PAT.entries[k].pmt_pid);
- mysetbit(pids_map[i].pidmap, SDT_PID);
- for(n = 0; n < PMT.entries[k].pids_cnt; n++)
- {
- int pid = PMT.entries[k].pids[n];
- mysetbit(pids_map[i].pidmap, pid);
- //fprintf(stderr, "\nADDED to map %d PROG pid %d, prog: %d", j, pid, PAT.entries[k].program);
- }
- }
- }
- }
- }
- }
- static int collect_section(section_t *section, int pusi, uint8_t *buf, unsigned int len)
- {
- int skip, slen;
- uint8_t *ptr;
- if(pusi)
- section->pos = 0;
- if(section->pos + len > SECTION_LEN)
- return 0;
- memcpy(&(section->buf[section->pos]), buf, len);
- section->pos += len;
- skip = section->buf[0];
- if(skip + 4 > section->pos)
- return 0;
- ptr = &(section->buf[skip + 1]);
- slen = ((ptr[1] & 0x0f) << 8) | ptr[2];
- if(section->pos < (skip+1+3+slen))
- return 0;
- return skip+1;
- }
- static int parse_pat(int pusi, uint8_t *b, int l)
- {
- unsigned int i, j, vers, seclen, num, skip;
- uint8_t *buf;
- skip = collect_section(&PAT.section, pusi, b, l);
- if(!skip)
- return 0;
- //now we know the section is complete
- PAT.section.pos = 0;
- buf = &(PAT.section.buf[skip]);
- if(buf[0] != 0) //pat id
- return 0;
- if(!(buf[5] & 1)) //not yet valid
- return 0;
- vers = (buf[5] >> 1) & 0x1F;
- if(PAT.version == vers) //PAT didn't change
- return 1;
- clearbits(SI_PIDS);
- mysetbit(SI_PIDS, 0);
- mysetbit(SI_PIDS, SDT_PID);
- seclen = ((buf[1] & 0x0F) << 8) | buf[2];
- num = (seclen - 9) / 4;
- if(PAT.entries_cnt != num)
- {
- PAT.entries = realloc(PAT.entries, sizeof(pat_entry)*num);
- PAT.entries_cnt = num;
- PMT.entries = realloc(PMT.entries, sizeof(pmt_t)*num);
- if(!PMT.entries) return 0;
- PMT.cnt = num;
- }
- i = 8;
- j = 0;
- for(j=0; j<num; j++)
- {
- PAT.entries[j].program = (buf[i] << 8) | buf[i+1];
- PAT.entries[j].pmt_pid = ((buf[i+2] & 0x1F) << 8) | buf[i+3];
- mysetbit(SI_PIDS, PAT.entries[j].pmt_pid);
- i += 4;
- //fprintf(stderr, "PROGRAM: %d, pmt_pid: %d\n", PAT.entries[j].program, PAT.entries[j].pmt_pid);
- PMT.entries[j].section.pos = SECTION_LEN+1;
- PMT.entries[j].version = -1;
- PMT.entries[j].name[0] = 0;
- }
- SDT.version=-1;
- SDT.section.pos = SECTION_LEN+1;
- PAT.version = vers;
- return 2;
- }
- static void add_pmt_pids()
- {
- int i;
- PID_BIT_MAP simap;
- for(i = 0; i < SI_fd_cnt; i++)
- close(SI_fd[i]);
- clearbits(simap);
- mysetbit(simap, 0);
- for(i=0; i<min(PAT.entries_cnt, MAX_CHANNELS); i++)
- {
- if(getbit(USER_PIDS, PAT.entries[i].pmt_pid)) continue;
- if(getbit(simap, PAT.entries[i].pmt_pid)) continue;
- if((SI_fd[i] = open(demuxdev[card], O_RDWR|O_NONBLOCK)) < 0)
- {
- fprintf(stderr,"COULDN'T OPEN DEMUX %i: for pid: %d", i, PAT.entries[i].pmt_pid);
- return;
- }
- //fprintf(stderr, "\nADDED PMT PID: %d\n", PAT.entries[i].pmt_pid);
- set_ts_filt(SI_fd[i], PAT.entries[i].pmt_pid, DMX_PES_OTHER);
- mysetbit(simap, PAT.entries[i].pmt_pid);
- SI_fd_cnt++;
- }
- }
- static int parse_pmt(int pusi, pmt_t *pmt, uint8_t *b, int l)
- {
- unsigned int i, version, seclen, skip, prog, pcr_pid, pid;
- uint8_t *buf;
- skip = collect_section(&(pmt->section), pusi, b, l);
- if(!skip)
- return 0;
- //now we know the section is complete
- pmt->section.pos = 0;
- pmt->pids_cnt = 0;
- buf = &(pmt->section.buf[skip]);
- if(buf[0] != 2) //pmt id
- return 0;
- if(!(buf[5] & 1)) //not yet valid
- return 0;
- prog = (buf[3] << 8) | buf[4];
- version = (buf[5] >> 1) & 0x1F;
- if(pmt->version == version) //PMT didn't change
- return 1;
- seclen = ((buf[1] & 0x0F) << 8) | buf[2];
- pcr_pid = ((buf[8] & 0x1F) << 8) | buf[9];
- pmt->pids[pmt->pids_cnt++] = pcr_pid;
- //fprintf(stderr, "\nPROGRAM: %d, pcr_pid: %d, version: %d vs %d\n", prog, pcr_pid, pmt->version, version);
- skip = ((buf[10] & 0x0F) << 8) | buf[11];
- if(skip+12 > seclen)
- return 0;
- i = skip+12;
- while(i+5<seclen)
- {
- pid = ((buf[i+1] & 0x1F) << 8) | buf[i+2];
- pmt->pids[pmt->pids_cnt++] = pid;
- skip = ((buf[i+3] & 0x0F) << 8) | buf[i+4];
- i += skip+5;
- //fprintf(stderr, "prog %d, PID: %d, count: %d, type: 0x%x\n", prog, pid, pmt->pids_cnt, buf[i]);
- }
- pmt->version = version;
- return 2;
- }
- static int parse_sdt(int pusi, uint8_t *b, int l)
- {
- unsigned int i, version, seclen, skip, prog, k, descr_len, found, len;
- uint8_t *buf;
- skip = collect_section(&(SDT.section), pusi, b, l);
- if(!skip)
- return 0;
- buf = &(SDT.section.buf[skip]);
- if(buf[0] != 0x42) //pmt id
- return 0;
- if(!(buf[5] & 1)) //not yet valid
- return 0;
- version = (buf[5] >> 1) & 0x1F;
- if(SDT.version == version) //SDT didn't change
- return 1;
- seclen = ((buf[1] & 0x0F) << 8) | buf[2];
- if(seclen < 12)
- return 0;
- i = 11;
- while(i < seclen - 4)
- {
- descr_len = ((buf[i+3] & 0x0F) << 8) | buf[i+4];
- if(i+5+descr_len >= seclen)
- break;
- prog = (buf[i] << 8) | buf[i+1];
- found = -1;
- k = 0;
- for(k = 0; k < PAT.entries_cnt, k < PMT.cnt; k++)
- if(PAT.entries[k].program == prog)
- {
- found = k;
-
- if(k != -1)
- {
- int j, len, dlen;
- j = i + 5;
- len = dlen = 0;
- while(len < descr_len)
- {
- int provider_len, name_len, n;
- pmt_t *pmt;
- n = j;
- dlen = buf[n+1];
- if(len + dlen > descr_len) break;
- if(buf[n] == 0x48)
- {
- provider_len = buf[n+3];
- if(provider_len + 2 > dlen)
- break;
- n += 4 + provider_len;
- name_len = buf[n];
- if(provider_len + 3 + name_len > dlen)
- break;
- pmt = &PMT.entries[k];
- memcpy(pmt->name, &buf[n+1], name_len);
- pmt->name[name_len] = 0;
- fprintf(stderr, "Program n. %d, name: '%s'\n", prog, pmt->name);
- }
- len += dlen+2;
- j += dlen+2;
- }
- }
- }
- i += 5 + descr_len;
- }
- SDT.version = version;
- return 2;
- }
- static int parse_ts_packet(uint8_t *buf)
- {
- int pid, l, af, pusi;
- if(buf[0] != 0x47)
- return 0;
- pusi = buf[1] & 0x40;
- pid = ((buf[1] & 0x1F) << 8) | buf[2];
- af = (buf[3] >> 4) & 0x03;
- l = 4;
- if(af == 2) //only adaption
- return 0;
- else if(af == 3)
- l += buf[4] + 1;
- if(l >= TS_SIZE - 4)
- return 0;
- if(pid == 0)
- {
- if(parse_pat(pusi, &buf[l], TS_SIZE - l) == 2)
- add_pmt_pids();
- }
- else if(pid == SDT_PID)
- {
- if(parse_sdt(pusi, &buf[l], TS_SIZE - l) == 2)
- {
- int i;
- for(i = 0; i < PMT.cnt; i++)
- {
- PMT.entries[i].section.pos = SECTION_LEN+1;
- PMT.entries[i].version = -1;
- }
- update_bitmaps();
- }
- }
- else
- {
- int i;
- for(i=0; i<PAT.entries_cnt; i++)
- {
- if(pid==PAT.entries[i].pmt_pid)
- {
- if(parse_pmt(pusi, &PMT.entries[i], &buf[l], TS_SIZE - l) == 2)
- update_bitmaps();
- }
- }
- }
- }
- static int is_string(char *s)
- {
- int i, n, len;
- n = 0;
- len = strlen(s);
- for(i = 0; i < len; i++)
- if(isdigit(s[i]))
- n++;
- return (n != len);
- }
- int main(int argc, char **argv)
- {
- // state_t state=STREAM_OFF;
- #ifdef ENABLE_TELNET
- unsigned short int port=DEFAULT_PORT;
- #endif
- int fd_dvr;
- int i,j;
- uint8_t buf[MTU];
- struct pollfd pfds[2]; // DVR device and Telnet connection
- unsigned int secs = -1;
- unsigned long freq=0;
- unsigned long srate=1000000;
- int count;
- char* ch;
- dmx_pes_type_t pestype;
- int bytes_read;
- int do_analyse=0;
- unsigned char* free_bytes;
- int output_type=RTP_TS;
- int64_t counts[8192];
- double f;
- long start_time=-1;
- long end_time=-1;
- struct timeval tv;
- int found;
- unsigned int delsys = SYS_DVBS;
- int stream_whole_TS=0;
- /* Output: {uni,multi,broad}cast socket */
- char ipOut[20];
- int portOut;
- int ttl = 2;
-
- pids_map = NULL;
- map_cnt = 0;
- fprintf(stderr,"dvbstream v0.7 - (C) Dave Chapman 2001-2004\n");
- fprintf(stderr,"Released under the GPL.\n");
- fprintf(stderr,"*WARNING* Diseqc switch numbering has changed. See help.\n");
- /* Initialise PID map */
- for (i=0;i<8192;i++) {
- hi_mappids[i]=(i >> 8);
- lo_mappids[i]=(i&0xff);
- counts[i]=0;
- }
- memset(&PAT, 0, sizeof(PAT));
- PAT.version = -1;
- PAT.section.pos = SECTION_LEN+1;
- memset(&PMT, 0, sizeof(PMT));
- clearbits(SI_PIDS);
- mysetbit(SI_PIDS, 0);
- memset(&SDT, 0, sizeof(SDT));
- SDT.section.pos = SECTION_LEN+1;
- SDT.version = -1;
- mysetbit(SI_PIDS, SDT_PID);
- clearbits(USER_PIDS);
- mysetbit(USER_PIDS, 0);
- /* Set default IP and port */
- strcpy(ipOut,"127.0.0.1");
- portOut = 1234;
- if (argc==1) {
- fprintf(stderr,"Usage: dvbstream [OPTIONS] pid1 pid2 ... pid8\n\n");
- fprintf(stderr,"-i IP multicast address\n");
- fprintf(stderr,"-r IP multicast port\n");
- fprintf(stderr,"-net ip:prt IP address:port combination to be followed by pids list. Can be repeated to generate multiple RTP streams\n");
- fprintf(stderr,"-o Stream to stdout instead of network\n");
- fprintf(stderr,"-o:file.ts Stream to named file instead of network\n");
- fprintf(stderr,"-n secs Stop after secs seconds\n");
- fprintf(stderr,"-from n Start saving the file previously specified with -o: syntax in n minutes time\n");
- fprintf(stderr,"-to n Stop saving the file previously specified with -o: syntax in n minutes time\n");
- fprintf(stderr,"-ps Convert stream to Program Stream format (needs exactly 2 pids)\n");
- fprintf(stderr,"-v vpid Decode video PID (full cards only)\n");
- fprintf(stderr,"-a apid Decode audio PID (full cards only)\n");
- fprintf(stderr,"-t ttpid Decode teletext PID (full cards only)\n");
- fprintf(stderr,"\nStandard tuning options:\n\n");
- fprintf(stderr,"-f freq absolute Frequency (DVB-S in Hz or DVB-T in Hz)\n");
- fprintf(stderr," or L-band Frequency (DVB-S in Hz or DVB-T in Hz)\n");
- fprintf(stderr," or C Band 4 digits Mhz Ku Band 5 digits Mhz\n");
- fprintf(stderr,"-SL slof S-LOF(DVB-S only)\n");
- fprintf(stderr,"-L1 LOF1 LOF1(DVB-S only C Band default 5150)\n");
- fprintf(stderr,"-L2 LOF2 LOF2(DVB-S only Ku Band default 10750)\n");
- fprintf(stderr,"-p [H,V] Polarity (DVB-S only)\n");
- fprintf(stderr,"-s N Symbol rate (DVB-S or DVB-C default 1000000)\n");
- fprintf(stderr,"-S system System 1=DVBS 2=DVBS2 3=ATSC 4=DVBT (Default DVBS)\n");
- fprintf(stderr,"\nAdvanced tuning options:\n\n");
- fprintf(stderr,"-c [0-3] Use DVB card #[0-3]\n");
- fprintf(stderr,"-D [0-4AB] DiSEqC command (Burst A or B, Commited 0-3, 4=None )\n\n");
- fprintf(stderr,"-I [0|1|2] 0=Spectrum Inversion off, 1=Spectrum Inversion on, 2=auto\n");
- fprintf(stderr,"-qam X DVB-T/C and ATSC modulation - 16%s, 32%s, 64%s, 128%s or 256%s\n",(CONSTELLATION_DEFAULT==QAM_16 ? " (default)" : ""),(CONSTELLATION_DEFAULT==QAM_32 ? " (default)" : ""),(CONSTELLATION_DEFAULT==QAM_64 ? " (default)" : ""),(CONSTELLATION_DEFAULT==QAM_128 ? " (default)" : ""),(CONSTELLATION_DEFAULT==QAM_256 ? " (default)" : ""));
- #ifdef DVB_ATSC
- fprintf(stderr,"-vsb X ATSC modulation - 8, 16\n");
- #endif
- fprintf(stderr,"-gi N DVB-T guard interval 1_N (N=32%s, 16%s, 8%s or 4%s)\n",(GUARD_INTERVAL_DEFAULT==GUARD_INTERVAL_1_32 ? " (default)" : ""),(GUARD_INTERVAL_DEFAULT==GUARD_INTERVAL_1_16 ? " (default)" : ""),(GUARD_INTERVAL_DEFAULT==GUARD_INTERVAL_1_8 ? " (default)" : ""),(GUARD_INTERVAL_DEFAULT==GUARD_INTERVAL_1_4 ? " (default)" : ""));
- fprintf(stderr,"-cr N DVB-T/C code rate. N=AUTO%s, 1_2%s, 2_3%s, 3_4%s, 5_6%s, 7_8%s\n",(HP_CODERATE_DEFAULT==FEC_AUTO ? " (default)" : ""),(HP_CODERATE_DEFAULT==FEC_1_2 ? " (default)" : ""),(HP_CODERATE_DEFAULT==FEC_2_3 ? " (default)" : ""),(HP_CODERATE_DEFAULT==FEC_3_4 ? " (default)" : ""),(HP_CODERATE_DEFAULT==FEC_5_6 ? " (default)" : ""),(HP_CODERATE_DEFAULT==FEC_7_8 ? " (default)" : ""));
- fprintf(stderr,"-crlp N DVB-T code rate LP. N=AUTO%s, 1_2%s, 2_3%s, 3_4%s, 5_6%s, 7_8%s\n",(LP_CODERATE_DEFAULT==FEC_AUTO ? " (default)" : ""),(LP_CODERATE_DEFAULT==FEC_1_2 ? " (default)" : ""),(LP_CODERATE_DEFAULT==FEC_2_3 ? " (default)" : ""),(LP_CODERATE_DEFAULT==FEC_3_4 ? " (default)" : ""),(LP_CODERATE_DEFAULT==FEC_5_6 ? " (default)" : ""),(LP_CODERATE_DEFAULT==FEC_7_8 ? " (default)" : ""));
- fprintf(stderr,"-bw N DVB-T bandwidth (Mhz) - N=6%s, 7%s or 8%s\n",(BANDWIDTH_DEFAULT==BANDWIDTH_6_MHZ ? " (default)" : ""),(BANDWIDTH_DEFAULT==BANDWIDTH_7_MHZ ? " (default)" : ""),(BANDWIDTH_DEFAULT==BANDWIDTH_8_MHZ ? " (default)" : ""));
- fprintf(stderr,"-tm N DVB-T transmission mode - N=2%s or 8%s\n",(TRANSMISSION_MODE_DEFAULT==TRANSMISSION_MODE_2K ? " (default)" : ""),(TRANSMISSION_MODE_DEFAULT==TRANSMISSION_MODE_8K ? " (default)" : ""));
- fprintf(stderr,"-hy N DVB-T hierarchy - N=1%s, 2%s, 4%s, NONE%s or AUTO%s\n",(HIERARCHY_DEFAULT==HIERARCHY_1 ? " (default)" : ""),(HIERARCHY_DEFAULT==HIERARCHY_2 ? " (default)" : ""),(HIERARCHY_DEFAULT==HIERARCHY_4 ? " (default)" : ""),(HIERARCHY_DEFAULT==HIERARCHY_NONE ? " (default)" : ""),(HIERARCHY_DEFAULT==HIERARCHY_AUTO ? " (default)" : ""));
- fprintf(stderr,"-ttl N Sets TTL to N (default: 2) when streaming in RTP\n");
- fprintf(stderr,"-rtp Sets output type to RTP (default when using network out)\n");
- fprintf(stderr,"-udp Sets output type to UDP \n");
- fprintf(stderr,"-prog Selects PROGRAM mode (opens a demux on the whole TS)\n");
- fprintf(stderr,"-pid Selects PID mode (default)\n");
- fprintf(stderr,"-stdin Use STDIN as source rather than a DVB card\n");
- fprintf(stderr,"\n-analyse Perform a simple analysis of the bitrates of the PIDs in the transport stream\n");
- fprintf(stderr,"\n");
- fprintf(stderr,"NOTE: Use pid1=8192 to broadcast whole TS stream from a budget card\n");
- return(-1);
- } else {
- pids[0]=0;
- npids=1;
- pestype=DMX_PES_OTHER; // Default PES type
- for (i=1;i<argc;i++) {
- if (strcmp(argv[i],"-ps")==0) {
- output_type=RTP_PS;
- } else if(!strcmp(argv[i],"-rtp")) {
- streamtype = RTP;
- } else if(!strcmp(argv[i],"-udp")) {
- streamtype = UDP;
- } else if (strcmp(argv[i],"-analyse")==0) {
- do_analyse=1;
- output_type=RTP_NONE;
- if (secs==-1) { secs=10; }
- } else if(strcmp(argv[i],"-stdin")==0) {
- use_stdin = 1;
- } else if (strcmp(argv[i],"-i")==0) {
- if(pids_map != NULL) {
- fprintf(stderr, "ERROR! -i and -r can't be used with -o and -net. Use -net instead\n");
- exit(1);
- }
- i++;
- strcpy(ipOut,argv[i]);
- } else if(strcmp(argv[i],"-auto")==0) {
- modulation = QAM_AUTO;
- TransmissionMode = TRANSMISSION_MODE_AUTO;
- guardInterval = GUARD_INTERVAL_AUTO;
- HP_CodeRate = FEC_AUTO;
- LP_CodeRate = FEC_AUTO;
- hier = HIERARCHY_AUTO;
- specInv = INVERSION_AUTO;
- }
- else if (strcmp(argv[i],"-r")==0) {
- if(pids_map != NULL) {
- fprintf(stderr, "ERROR! -i and -r can't be used with -o and -net. Use -net instead\n");
- exit(1);
- }
- i++;
- portOut=atoi(argv[i]);
- } else if (strcmp(argv[i],"-net")==0) {
- char *tmp;
- i++;
- tmp = strchr(argv[i], ':');
- if((tmp == NULL) || (tmp - argv[i] > 19)) {
- fprintf(stderr, "No valid IP:port found after -net switch, discarding\n");
- } else {
- int len = (int) (tmp - argv[i]);
- char addr[20];
- int port;
- strncpy(ipOut, argv[i], len);
- ipOut[len] = 0;
- strncpy(addr, argv[i], len);
- addr[len] = 0;
- port = portOut = atoi(tmp+1);
-
-
- pids_map = (pids_map_t*) realloc(pids_map, sizeof(pids_map_t) * (map_cnt+1));
- if(pids_map != NULL) {
- map_cnt++;
- pids_map[map_cnt-1].pid_cnt = 0;
- pids_map[map_cnt-1].progs_cnt = 0;
- pids_map[map_cnt-1].start_time=start_time;
- pids_map[map_cnt-1].end_time=end_time;
- for(j=0; j < MAX_CHANNELS; j++) pids_map[map_cnt-1].pids[j] = -1;
- pids_map[map_cnt-1].filename = NULL;
- strncpy(pids_map[map_cnt-1].net, addr, len);
- pids_map[map_cnt-1].net[len] = 0;
- pids_map[map_cnt-1].port = port;
- pids_map[map_cnt-1].pos = 0;
-
- pids_map[map_cnt-1].socket = makesocket(addr,port,ttl,&(pids_map[map_cnt-1].sOut));
- initrtp(&(pids_map[map_cnt-1].hdr),(output_type==RTP_TS ? 33 : 34), streamtype);
- output_type = MAP_TS;
- } else
- fprintf(stderr, "Couldn't alloc enough entry for this %s:%d address\n", addr, port);
- }
- } else if (strcmp(argv[i],"-f")==0) {
- i++;
- freq=atoi(argv[i]);
- } else if (strcmp(argv[i],"-p")==0) {
- i++;
- if (argv[i][1]==0) {
- if (tolower(argv[i][0])=='v') {
- pol='V';
- } else if (tolower(argv[i][0])=='h') {
- pol='H';
- }
- }
- } else if (strcmp(argv[i],"-SL")==0) {
- i++;
- SLOF=atoi(argv[i]);
- SLOF*=1000UL;
- } else if (strcmp(argv[i],"-L1")==0) {
- i++;
- LOF1=atoi(argv[i]);
- LOF1*=1000UL;
- } else if (strcmp(argv[i],"-L2")==0) {
- i++;
- LOF2=atoi(argv[i]);
- LOF2*=1000UL;
- }
- else if (strcmp(argv[i],"-s")==0) {
- i++;
- srate=atoi(argv[i])*1000UL;
- }
- else if (strcmp(argv[i],"-D")==0)
- {
- i++;
- diseqc = argv[i][0];
- if(toupper(diseqc) == 'A')
- diseqc = 'A';
- else if(toupper(diseqc) == 'B')
- diseqc = 'B';
- else if(diseqc >= '0' && diseqc <= '4') {
- diseqc=diseqc - '0';
- }
- else {
- fprintf(stderr,"DiSEqC must be between 0 and 4 or A | B\n");
- exit(-1);
- }
- } else if (strcmp(argv[i],"-I")==0) {
- i++;
- if (atoi(argv[i])==0)
- specInv = INVERSION_OFF;
- else if (atoi(argv[i])==1)
- specInv = INVERSION_ON;
- else
- specInv = INVERSION_AUTO;
- }
- else if (strcmp(argv[i],"-S")==0) {
- i++;
- switch(atoi(argv[i])) {
- case 1: delsys=SYS_DVBS; fprintf(stderr,"Tuning DVB-S...\n"); break;
- case 2: delsys=SYS_DVBS2; fprintf(stderr,"Tuning DVB-S2...\n"); break;
- case 3: delsys=SYS_ATSC; fprintf(stderr,"Tuning ATSC...\n");break;
- case 4: delsys=SYS_DVBT; fprintf(stderr,"Tuning DVB-T...\n");break;
- default:
- fprintf(stderr,"Invalid Delivery System %s\n",argv[i]);
- exit(0);
- }
- }
- else if(strcmp(argv[i],"-prog")==0) {
- selection_mode = PROG_MODE;
- }
- else if(strcmp(argv[i],"-pid")==0) {
- selection_mode = PID_MODE;
- }
- else if (strcmp(argv[i],"-o")==0) {
- to_stdout = 1;
- } else if (strcmp(argv[i],"-n")==0) {
- i++;
- secs=atoi(argv[i]);
- } else if (strcmp(argv[i],"-c")==0) {
- i++;
- card=atoi(argv[i]);
- if ((card < 0) || (card > 3)) {
- fprintf(stderr,"ERROR: card parameter must be between 0 and 4\n");
- }
- } else if (strcmp(argv[i],"-v")==0) {
- pestype=DMX_PES_VIDEO;
- } else if (strcmp(argv[i],"-a")==0) {
- pestype=DMX_PES_AUDIO;
- } else if (strcmp(argv[i],"-t")==0) {
- pestype=DMX_PES_TELETEXT;
- } else if (strcmp(argv[i],"-qam")==0) {
- i++;
- switch(atoi(argv[i])) {
- case 16: modulation=QAM_16; break;
- case 32: modulation=QAM_32; break;
- case 64: modulation=QAM_64; break;
- case 128: modulation=QAM_128; break;
- case 256: modulation=QAM_256; break;
- default:
- fprintf(stderr,"Invalid QAM rate: %s\n",argv[i]);
- exit(0);
- }
- }
- #ifdef DVB_ATSC
- else if(strcmp(argv[i],"-vsb")==0) {
- i++;
- switch(atoi(argv[i])) {
- case 8: modulation=VSB_8; break;
- case 16: modulation=VSB_16; break;
- default:
- fprintf(stderr,"Invalid ATSC VSB modulation: %s\n",argv[i]);
- exit(0);
- }
- }
- #endif
- else if (strcmp(argv[i],"-gi")==0) {
- i++;
- switch(atoi(argv[i])) {
- case 32: guardInterval=GUARD_INTERVAL_1_32; break;
- case 16: guardInterval=GUARD_INTERVAL_1_16; break;
- case 8: guardInterval=GUARD_INTERVAL_1_8; break;
- case 4: guardInterval=GUARD_INTERVAL_1_4; break;
- default:
- fprintf(stderr,"Invalid Guard Interval: %s\n",argv[i]);
- exit(0);
- }
- } else if (strcmp(argv[i],"-tm")==0) {
- i++;
- switch(atoi(argv[i])) {
- case 8: TransmissionMode=TRANSMISSION_MODE_8K; break;
- case 2: TransmissionMode=TRANSMISSION_MODE_2K; break;
- default:
- fprintf(stderr,"Invalid Transmission Mode: %s\n",argv[i]);
- exit(0);
- }
- } else if (strcmp(argv[i],"-bw")==0) {
- i++;
- switch(atoi(argv[i])) {
- case 8: bandWidth=BANDWIDTH_8_MHZ; break;
- case 7: bandWidth=BANDWIDTH_7_MHZ; break;
- case 6: bandWidth=BANDWIDTH_6_MHZ; break;
- default:
- fprintf(stderr,"Invalid DVB-T bandwidth: %s\n",argv[i]);
- exit(0);
- }
- } else if (strcmp(argv[i],"-cr")==0) {
- i++;
- if (!strcmp(argv[i],"AUTO")) {
- HP_CodeRate=FEC_AUTO;
- } else if (!strcmp(argv[i],"1_2")) {
- HP_CodeRate=FEC_1_2;
- } else if (!strcmp(argv[i],"2_3")) {
- HP_CodeRate=FEC_2_3;
- } else if (!strcmp(argv[i],"3_4")) {
- HP_CodeRate=FEC_3_4;
- } else if (!strcmp(argv[i],"5_6")) {
- HP_CodeRate=FEC_5_6;
- } else if (!strcmp(argv[i],"7_8")) {
- HP_CodeRate=FEC_7_8;
- } else {
- fprintf(stderr,"Invalid Code Rate: %s\n",argv[i]);
- exit(0);
- }
- } else if (strcmp(argv[i],"-crlp")==0) {
- i++;
- if (!strcmp(argv[i],"AUTO")) {
- LP_CodeRate=FEC_AUTO;
- } else if (!strcmp(argv[i],"1_2")) {
- LP_CodeRate=FEC_1_2;
- } else if (!strcmp(argv[i],"2_3")) {
- LP_CodeRate=FEC_2_3;
- } else if (!strcmp(argv[i],"3_4")) {
- LP_CodeRate=FEC_3_4;
- } else if (!strcmp(argv[i],"5_6")) {
- LP_CodeRate=FEC_5_6;
- } else if (!strcmp(argv[i],"7_8")) {
- LP_CodeRate=FEC_7_8;
- } else {
- fprintf(stderr,"Invalid Code Rate LP: %s\n",argv[i]);
- exit(0);
- }
- } else if (strcmp(argv[i],"-hier")==0) {
- i++;
- if (!strcmp(argv[i],"AUTO")) {
- hier=HIERARCHY_AUTO;
- } else if (!strcmp(argv[i],"1")) {
- hier=HIERARCHY_2;
- } else if (!strcmp(argv[i],"4")) {
- hier=HIERARCHY_4;
- } else if (!strcmp(argv[i],"NONE")) {
- hier=HIERARCHY_NONE;
- } else {
- fprintf(stderr,"Invalid HIERARCHY: %s\n",argv[i]);
- exit(0);
- }
- } else if (strcmp(argv[i],"-ttl")==0) {
- i++;
- ttl = atoi(argv[i]);
- } else if (strcmp(argv[i],"-from")==0) {
- i++;
- if (map_cnt) {
- pids_map[map_cnt-1].start_time=atoi(argv[i])*60;
- } else {
- start_time=atoi(argv[i])*60;
- }
- } else if (strcmp(argv[i],"-to")==0) {
- i++;
- if (map_cnt) {
- pids_map[map_cnt-1].end_time=atoi(argv[i])*60;
- } else {
- end_time=atoi(argv[i])*60;
- secs=end_time;
- }
- } else if (strstr(argv[i], "-o:")==argv[i]) {
- if (strlen(argv[i]) > 3) {
- char * fname;
- fname = (char *) malloc(strlen(argv[i]) - 2);
- if(fname == NULL) {
- fprintf(stderr, "Couldn't alloc enough memory for this -o: entry, discarding\n");
- } else {
- strcpy(fname, &argv[i][3]);
- pids_map = (pids_map_t*) realloc(pids_map, sizeof(pids_map_t) * (map_cnt+1));
- if(pids_map != NULL) {
- map_cnt++;
- pids_map[map_cnt-1].pid_cnt = 0;
- pids_map[map_cnt-1].start_time=start_time;
- pids_map[map_cnt-1].end_time=end_time;
- for(j=0; j < MAX_CHANNELS; j++) pids_map[map_cnt-1].pids[j] = -1;
- pids_map[map_cnt-1].filename = fname;
- output_type = MAP_TS;
- } else
- fprintf(stderr, "Couldn't alloc enough memory for file %s: entry, discarding\n", fname);
- }
- }
- } else {
- if ((ch=(char*)strstr(argv[i],":"))!=NULL) {
- pid2=atoi(&ch[1]);
- ch[0]=0;
- } else {
- pid2=-1;
- }
- pid=atoi(argv[i]);
- // If we are currently processing a "-o:" option:
- if (map_cnt) {
- if(selection_mode == PID_MODE) {
- // block for the map
- found = 0;
- for (j=0;j<MAX_CHANNELS;j++) {
- if(pids_map[map_cnt-1].pids[j] == pid) found = 1;
- }
- if (found == 0) {
- if(pids_map[map_cnt-1].pid_cnt==0) {
- pids_map[map_cnt-1].pids[0]=0;
- pids_map[map_cnt-1].pid_cnt++;
- }
- if(pid==8192) {
- fprintf(stderr, "Adding whole transport stream to map n. %d\n", map_cnt-1);
- setallbits(USER_PIDS);
- }
- pids_map[map_cnt-1].pids[pids_map[map_cnt-1].pid_cnt] = pid;
- pids_map[map_cnt-1].pid_cnt++;
- }
- }
- else {
- // block for the map
- int is_progname = is_string(argv[i]);
- pids_map_t *map = &(pids_map[map_cnt-1]);
- stream_whole_TS=1;
- setallbits(USER_PIDS);
- found = 0;
- if(is_progname) {
- for(j=0;j<map->prognames_cnt;j++) {
- if(!strcmp(map->prognames[j], argv[i]))
- found = 1;
- }
- if(found == 0) {
- map->prognames = realloc(map->prognames, (map->prognames_cnt+1)*sizeof(map->prognames));
- map->prognames_cnt++;
- map->prognames[map->prognames_cnt-1] = malloc(strlen(argv[i])+1);
- strcpy(map->prognames[map->prognames_cnt-1], argv[i]);
- }
- }
- else {
- for (j=0;j<MAX_CHANNELS;j++) {
- if(pids_map[map_cnt-1].progs[j] == pid) found = 1;
- }
- if(found == 0)
- pids_map[map_cnt-1].progs[pids_map[map_cnt-1].progs_cnt++] = pid;
- }
- }
- }
- if(selection_mode == PID_MODE) {
- // block for the list of pids to demux
- found = 0;
- for (j=0;j<npids;j++) {
- if(pids[j] == pid) found = 1;
- }
- if (found==0) {
- if (npids == MAX_CHANNELS) {
- fprintf(stderr,"\nSorry, you can only set up to %d filters.\n\n",MAX_CHANNELS);
- return(-1);
- } else {
- pestypes[npids]=pestype;
- pestype=DMX_PES_OTHER;
- pids[npids++]=pid;
- if (pid2!=-1) {
- hi_mappids[pid]=pid2>>8;
- lo_mappids[pid]=pid2&0xff;
- fprintf(stderr,"Mapping %d to %d\n",pid,pid2);
- }
- }
- }
- }
- }
- }
- }
- if ((output_type==RTP_PS) && (npids!=3)) {
- fprintf(stderr,"ERROR: PS requires exactly two PIDS - video and audio.\n");
- exit(1);
- }
- for (i=0;i<map_cnt;i++) {
- if(pids_map[i].filename) {
- FILE *f;
- f = fopen(pids_map[i].filename, "w+b");
- if (f != NULL) {
- pids_map[i].fd = fileno(f);
- make_nonblock(pids_map[i].fd);
- fprintf(stderr, "Open file %s\n", pids_map[i].filename);
- } else {
- pids_map[i].fd = -1;
- fprintf(stderr, "Couldn't open file %s, errno:%d\n", pids_map[map_cnt-1].filename, errno);
- }
- }
- }
- update_bitmaps();
- if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
- if (signal(SIGINT, SignalHandler) == SIG_IGN) signal(SIGINT, SIG_IGN);
- if (signal(SIGTERM, SignalHandler) == SIG_IGN) signal(SIGTERM, SIG_IGN);
- if (signal(SIGALRM, SignalHandler) == SIG_IGN) signal(SIGALRM, SIG_IGN);
- alarm(ALARM_TIME);
- if (freq!=0 && !use_stdin) {
- if (open_fe(&fd_frontend)) {
- fprintf(stderr,"Tuning to %ld Hz\n",freq);
- i=tune_it(fd_frontend,freq,srate,pol,tone,specInv,diseqc,modulation,HP_CodeRate,TransmissionMode,guardInterval,bandWidth, LP_CodeRate, hier, delsys);
- }
- }
- // if (i<0) { exit(i); }
- if(map_cnt > 0)
- fprintf(stderr, "\n");
- for (i=0;i<map_cnt;i++) {
- if ((secs==-1) || (secs < pids_map[i].end_time)) { secs=pids_map[i].end_time; }
- if(pids_map[i].filename != NULL)
- fprintf(stderr,"MAP %d, file %s: From %ld secs, To %ld secs, %d PIDs - ",i,pids_map[i].filename,pids_map[i].start_time,pids_map[i].end_time,pids_map[i].pid_cnt);
- else
- fprintf(stderr,"MAP %d, addr %s:%d From %ld secs, To %ld secs, %d PIDs - ",i,pids_map[i].net,pids_map[i].port,pids_map[i].start_time,pids_map[i].end_time,pids_map[i].pid_cnt);
- for (j=0;j<MAX_CHANNELS;j++) { if (pids_map[i].pids[j]!=-1) fprintf(stderr," %d",pids_map[i].pids[j]); }
- fprintf(stderr,"\n");
- }
-
- fprintf(stderr,"dvbstream will stop after %d seconds (%d minutes)\n",secs,secs/60);
- if(stream_whole_TS) {
- npids=1;
- pids[0] = 8192;
- }
- else
- for(i=0; i<npids; i++) {
- if(pids[i] == 8192) {
- npids = 1;
- pids[0] = 8192;
- }
- }
- if(use_stdin) {
- fd_dvr = fileno(stdin);
- } else {
- for (i=0;i<npids;i++) {
- if((fd[i] = open(demuxdev[card],O_RDWR|O_NONBLOCK)) < 0){
- fprintf(stderr,"FD %i: ",i);
- perror("DEMUX DEVICE: ");
- return -1;
- }
- }
- if((fd_dvr = open(dvrdev[card],O_RDONLY|O_NONBLOCK)) < 0){
- perror("DVR DEVICE: ");
- return -1;
- }
- /* Now we set the filters */
- for (i=0;i<npids;i++) {
- set_ts_filt(fd[i],pids[i],pestypes[i]);
- mysetbit(USER_PIDS, pids[i]);
- }
- }
- gettimeofday(&tv,(struct timezone*) NULL);
- real_start_time=tv.tv_sec;
- now=0;
- if (do_analyse) {
- fprintf(stderr,"Analysing PIDS\n");
- } else {
- if (to_stdout) {
- fprintf(stderr,"Output to stdout\n");
- }
- else if(! map_cnt) {
- ttl = 2;
- fprintf(stderr,"Using %s:%d:%d\n",ipOut,portOut,ttl);
- /* Init RTP */
- socketOut = makesocket(ipOut,portOut,ttl,&sOut);
- // #warning WHAT SHOULD THE PAYLOAD TYPE BE FOR "MPEG-2 PS" ?
- initrtp(&hdr,(output_type==RTP_TS ? 33 : 34), streamtype);
- fprintf(stderr,"version=%X\n",hdr.b.v);
- }
- fprintf(stderr,"Streaming %d stream%s\n",npids,(npids==1 ? "" : "s"));
- }
- if (output_type==RTP_PS) {
- init_ipack(&pa, IPACKS,my_write_out, 1);
- init_ipack(&pv, IPACKS,my_write_out, 1);
- }
- /* Read packets */
- free_bytes = buf;
- /*
- #ifdef ENABLE_TELNET
- // Setup socket to accept input from a client //
- gethostname(hostname, sizeof(hostname));
- if ((hp = gethostbyname(hostname)) == NULL) {
- fprintf(stderr, "%s: host unknown.\n", hostname);
- exit(1);
- }
- if ((socketIn = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
- perror("server: socket");
- exit(1);
- }
- setsockopt(socketIn,SOL_SOCKET,SO_REUSEADDR,&ReUseAddr,sizeof(ReUseAddr));
- name.sin_family = AF_INET;
- name.sin_port = htons(port);
- name.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(socketIn,(struct sockaddr* )&name,sizeof(name)) < 0) {
- perror("server: bind");
- exit(1);
- }
- make_nonblock(socketIn);
- if (listen(socketIn, 1) < 0) {
- perror("server: listen");
- exit(1);
- }
- #endif
- */
- connectionOpen=0;
- ns=-1;
- pfds[0].fd=fd_dvr;
- pfds[0].events=POLLIN|POLLPRI;
- pfds[1].events=POLLIN|POLLPRI;
- while ( !Interrupted) {
- /* Poll the open file descriptors */
- if (ns==-1) {
- poll(pfds,1,500);
- } else {
- pfds[1].fd=ns; // This can change
- poll(pfds,2,500);
- }
- // process_telnet(); // See if there is an incoming telnet connection
- if (output_type==RTP_TS) {
- /* Attempt to read 188 bytes from /dev/ost/dvr */
- if ((bytes_read = read(fd_dvr,free_bytes,PACKET_SIZE)) > 0) {
- if (bytes_read!=PACKET_SIZE) {
- fprintf(stderr,"No bytes left to read - aborting\n");
- break;
- }
- pid=((free_bytes[1]&0x1f) << 8) | (free_bytes[2]);
- free_bytes[1]=(free_bytes[1]&0xe0)|hi_mappids[pid];
- free_bytes[2]=lo_mappids[pid];
- free_bytes+=bytes_read;
- // If there isn't enough room for 1 more packet, then send it.
- if ((free_bytes+PACKET_SIZE-buf)>MAX_RTP_SIZE) {
- hdr.timestamp = getmsec()*90;
- if (to_stdout) {
- write(1, buf, free_bytes-buf);
- } else {
- sendrtp2(socketOut,&sOut,&hdr,buf,free_bytes-buf);
- }
- free_bytes = buf;
- }
- count++;
- }
- } else if (output_type==RTP_PS) {
- if (read(fd_dvr,buf,TS_SIZE) > 0) {
- my_ts_to_ps((uint8_t*)buf, pids[1], pids[2]);
- } else if(use_stdin) break;
- } else if(output_type==MAP_TS) {
- int bytes_read;
- bytes_read = read(fd_dvr, buf, TS_SIZE);
- if(bytes_read > 0) {
- if(buf[0] == 0x47) {
- int pid, i;
- pid = ((buf[1] & 0x1f) << 8) | buf[2];
- if(getbit(SI_PIDS, pid)) parse_ts_packet(buf);
- if (pids_map != NULL) {
- for (i = 0; i < map_cnt; i++) {
- if ( ((pids_map[i].start_time==-1) || (pids_map[i].start_time <= now))
- && ((pids_map[i].end_time==-1) || (pids_map[i].end_time >= now))) {
- if(getbit(pids_map[i].pidmap, pid)) {
- errno = 0;
- if(pids_map[i].filename)
- write(pids_map[i].fd, buf, TS_SIZE);
- else {
- if((pids_map[i].pos + PACKET_SIZE) > MAX_RTP_SIZE) {
- hdr.timestamp = getmsec()*90;
- sendrtp2(pids_map[i].socket, &(pids_map[i].sOut), &(pids_map[i].hdr), pids_map[i].buf, pids_map[i].pos);
- pids_map[i].pos = 0;
- }
-
- memcpy(&(pids_map[i].buf[pids_map[i].pos]), buf, bytes_read);
- pids_map[i].pos += bytes_read;
- }
- }
- }
- }
- }
- } else {
- fprintf(stderr, "NON 0X47\n");
- }
- }
- else if(use_stdin) break;
- } else {
- if (do_analyse) {
- if (read(fd_dvr,buf,TS_SIZE) > 0) {
- pid=((buf[1]&0x1f) << 8) | (buf[2]);
- counts[pid]++;
- }
- }
- }
- if ((secs!=-1) && (secs <=now)) { Interrupted=1; }
- }
- if (Interrupted) {
- fprintf(stderr,"Caught signal %d - closing cleanly.\n",Interrupted);
- }
- if (ns!=-1) close(ns);
- close(socketIn);
- if (!to_stdout && !map_cnt) close(socketOut);
- if(!use_stdin) {
- for (i=0;i<npids;i++) close(fd[i]);
- close(fd_dvr);
- close(fd_frontend);
- }
- if (do_analyse) {
- for (i=0;i<8192;i++) {
- if (counts[i]) {
- f=(counts[i]*184.0*8.0)/(secs*1024.0*1024.0);
- if (f >= 1.0) {
- fprintf(stdout,"%d,%.3f Mbit/s\n",i,f);
- } else {
- fprintf(stdout,"%d,%.0f kbit/s\n",i,f*1024);
- }
- }
- }
- }
- return(0);
- }