/* dvbstream - RTP-ize a DVB transport stream. (C) Dave Chapman 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // DVB includes: #include #include #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 */ 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; 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> 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> 8); lo_mappids[i]=(i&0xff); } for (i=0;iplength == 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 struct { char *filename; int fd; int pids[MAX_CHANNELS]; int num; int pid_cnt; 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; 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; unsigned char buf[MTU]; struct pollfd pfds[2]; // DVR device and Telnet connection unsigned int secs = -1; unsigned long freq=0; unsigned long srate=0; 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; /* Output: {uni,multi,broad}cast socket */ char ipOut[20]; int portOut; int ttl = 2; pids_map = NULL; map_cnt = 0; fprintf(stderr,"dvbstream v0.6 - (C) Dave Chapman 2001-2004\n"); fprintf(stderr,"Released under the GPL.\n"); fprintf(stderr,"Latest version available from http://www.linuxstb.org/\n"); /* Initialise PID map */ for (i=0;i<8192;i++) { hi_mappids[i]=(i >> 8); lo_mappids[i]=(i&0xff); counts[i]=0; } /* Set default IP and port */ strcpy(ipOut,"224.0.1.2"); portOut = 5004; if (argc==1) { fprintf(stderr,"Usage: dvbtune [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,"-p [H,V] Polarity (DVB-S only)\n"); fprintf(stderr,"-s N Symbol rate (DVB-S or DVB-C)\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 (0=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,"\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 { npids=0; pestype=DMX_PES_OTHER; // Default PES type for (i=1;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].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],"-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],"-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) { // block for the map found = 0; for (j=0;j>8; lo_mappids[pid]=pid2&0xff; fprintf(stderr,"Mapping %d to %d\n",pid,pid2); } } } } } } if ((output_type==RTP_PS) && (npids!=2)) { fprintf(stderr,"ERROR: PS requires exactly two PIDS - video and audio.\n"); exit(1); } for (i=0;i 0) fprintf(stderr, "\n"); for (i=0;i 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[0], pids[1]); } } 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, j; pid = ((buf[1] & 0x1f) << 8) | buf[2]; 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))) { for (j = 0; j < MAX_CHANNELS; j++) { if (pids_map[i].pids[j] == 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 (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); for (i=0;i= 1.0) { fprintf(stdout,"%d,%.3f Mbit/s\n",i,f); } else { fprintf(stdout,"%d,%.0f kbit/s\n",i,f*1024); } } } } return(0); }