int doReadTS (OPTION *opt) { int fd_dmx = 0, fd_dvr = 0; u_char buf[READ_BUF_SIZE]; /* data buffer */ u_char *b; /* ptr for packet start */ long count; long filtered_count; char *f; int openMode; int fileMode; long dmx_buffer_size = TS_BUF_SIZE; if (opt->inpPidFile) { f = opt->inpPidFile; openMode = O_RDONLY | O_LARGEFILE | O_BINARY; fileMode = 1; } else { f = opt->devDvr; openMode = O_RDONLY; fileMode = 0; } if((fd_dvr = open(f,openMode)) < 0){ IO_error(f); return -1; } /* -- init demux */ if (!fileMode) { struct dmx_pes_filter_params flt; if((fd_dmx = open(opt->devDemux,O_RDWR)) < 0){ IO_error(opt->devDemux); close (fd_dvr); return -1; } // -- alloc dmx buffer for TS if (opt->rd_buffer_size > 0) { dmx_buffer_size = opt->rd_buffer_size; } // -- full Transport Stream Read?? (special DVB-API-PID...) if (opt->ts_raw_mode) { opt->pid = PID_FULL_TS; } if (ioctl(fd_dmx,DMX_SET_BUFFER_SIZE, dmx_buffer_size) < 0) { IO_error ("DMX_SET_BUFFER_SIZE failed: "); close (fd_dmx); close (fd_dvr); return -1; } memset (&flt, 0, sizeof (struct dmx_pes_filter_params)); flt.pid = opt->pid; flt.input = DMX_IN_FRONTEND; flt.output = DMX_OUT_TS_TAP; flt.pes_type = DMX_PES_OTHER; flt.flags = DMX_IMMEDIATE_START; if (ioctl(fd_dmx,DMX_SET_PES_FILTER,&flt) < 0) { IO_error ("DMX_SET_PES_FILTER failed: "); close (fd_dmx); close (fd_dvr); return -1; } } // -- acquire TS subdecoding buffer if (opt->ts_subdecode) { ts2SecPesInit (); } // -- init TS CC check ts_cc_init (); /* -- read TS packets for pid */ count = 0; filtered_count = 0; while ( ! isSigAbort() ) { long n; long skipped_bytes = 0; int pid_filter_match = 1; int packet_pid = -1; // -- Sync TS read! n = ts_SyncRead (fd_dvr,buf,sizeof(buf), &skipped_bytes); b = buf+(skipped_bytes % TS_PACKET_LEN); // -- error or eof? if (n < 0) { int err; err = IO_error("read"); // if (err == ETIMEDOUT) break; // Timout, abort continue; } if (n == 0) { if (!fileMode) continue; // DVRmode = no eof! else { // filemode eof ts2SecPes_LastPacketReadSubdecode_Output (); break; } } count ++; // -- skipped Data to get sync byte? if (skipped_bytes) { if (! opt->binary_out) { out_nl (3,"!!! %ld bytes skipped to get TS sync!!!"); } } // -- SyncByte for TS packet and correct len? if (b[0] != TS_SYNC_BYTE || n != TS_PACKET_LEN) { if (! opt->binary_out) { out_nl (3,"!!! Wrong SyncByte or packet length mismatch (= no TS)!!!"); } continue; } // -- PID soft filter mode // -- We alway do this check (even if we are reading directly // -- from dvb device and PID has already been filtered by demux) packet_pid = getBits (b, 0,11, 13); if ((opt->pid >= 0) && (opt->pid <= MAX_PID) && (opt->pid != packet_pid)) { pid_filter_match = 0; } // -- packet output ? (binary or decoded) // -- This happens, when filter are matching (hard or soft filter) if (pid_filter_match) { filtered_count++; if (opt->binary_out) { // direct write to FD 1 ( == stdout) write (1, b, n); } else { processTS_packet (packet_pid, filtered_count, b, n); } } // pid_filter_match: packet out // count packets ? if (opt->rd_packet_count > 0) { if (count >= opt->rd_packet_count) break; } if (opt->dec_packet_count > 0) { if (filtered_count >= opt->dec_packet_count) break; } } // while // -- release TS subdecoding buffer if (opt->ts_subdecode) ts2SecPesFree (); // -- release TS CC checka buffer, etc. ts_cc_init (); // -- Stop Demux if (!fileMode) { ioctl (fd_dmx, DMX_STOP, 0); close(fd_dmx); } close(fd_dvr); return 0; }
// int doReadPS (OPTION *opt) int doReadPES (OPTION *opt) { int fd; u_char buf[READ_BUF_SIZE]; /* data buffer */ u_char *b; /* ptr to packet start */ long count; char *f; int openMode; int dmxMode; long dmx_buffer_size = PES_BUF_SIZE; if (opt->inpPidFile) { f = opt->inpPidFile; openMode = O_RDONLY | O_LARGEFILE | O_BINARY; dmxMode = 0; } else { f = opt->devDemux; openMode = O_RDWR; dmxMode = 1; } if((fd = open(f,openMode)) < 0){ IO_error(f); return -1; } /* -- init demux */ if (dmxMode) { struct dmx_pes_filter_params flt; // -- alloc dmx buffer for PES if (opt->rd_buffer_size > 0) { dmx_buffer_size = opt->rd_buffer_size; } if (ioctl(fd,DMX_SET_BUFFER_SIZE, dmx_buffer_size) < 0) { IO_error ("DMX_SET_BUFFER_SIZE failed: "); close (fd); return -1; } memset (&flt, 0, sizeof (struct dmx_pes_filter_params)); flt.pid = opt->pid; flt.input = DMX_IN_FRONTEND; flt.output = DMX_OUT_TAP; flt.pes_type = DMX_PES_OTHER; flt.flags = DMX_IMMEDIATE_START; if (ioctl(fd,DMX_SET_PES_FILTER,&flt) < 0) { IO_error ("DMX_SET_PES_FILTER failed: "); close (fd); return -1; } } /* -- read PES packet for pid */ count = 0; while (! isSigAbort() ) { long n; u_long skipped_bytes = 0; // -- Read PES packet (sync Read) n = pes_SyncBufferRead (fd,buf,sizeof(buf), &skipped_bytes); b = buf; // -- error or eof? if (n < 0) { int err; err = IO_error("read"); // if (err == ETIMEDOUT) break; // Timout, abort continue; } if (n == 0) { if (dmxMode) continue; // dmxmode = no eof! else break; // filemode eof } count ++; if (opt->binary_out) { // direct write to FD 1 ( == stdout) write (1, b, n); } else { // -- skipped Data to get sync byte? if (skipped_bytes) { out_nl (3,"!!! %ld bytes skipped to get PS/PES sync!!!",skipped_bytes); out_SkipBuffer (8, skipped_bytes); } processPS_PES_packet (opt->pid, count, b, n); } // bin_out // Clean Buffer // if (n > 0 && n < sizeof(buf)) memset (buf,0,n+1); // count packets ? if (opt->rd_packet_count > 0) { if (count >= opt->rd_packet_count) break; } if (opt->dec_packet_count > 0) { if (count >= opt->dec_packet_count) break; } } // while /* -- Stop Demux */ if (dmxMode) { ioctl (fd, DMX_STOP, 0); } close(fd); return 0; }
int ts_pidbandwidth (OPTION *opt) { u_char buf[TS_BUF_SIZE]; struct pollfd pfd; struct dmx_pes_filter_params flt; int dmxfd; struct timeval tv,last_tv, first_tv; int pid; unsigned long long b_total; long b; long packets_bad; long packets_total; struct { // simple struct for storing last average bandwidth unsigned long kb_sec; unsigned long b_sec; } last_avg; if (opt->ts_raw_mode) { pid = PID_FULL_TS; } else { pid = opt->pid; } indent (0); out_nl (2,""); out_nl (2,"---------------------------------------------------------"); out_nl (2,"PID bandwidth statistics..."); if (opt->ts_raw_mode) { out (2,"Full Transponder"); } else { out (2,"PID: %u (0x%04x)", pid, pid); } if (opt->rd_packet_count != 0) { out (2," - max packet count: %ld ", opt->rd_packet_count); } out_nl (2,""); out_nl (2,"---------------------------------------------------------"); // -- open DVR device for reading pfd.events = POLLIN | POLLPRI; if((pfd.fd = open(opt->devDvr,O_RDONLY|O_NONBLOCK)) < 0){ IO_error(opt->devDvr); return -1; } if ((dmxfd=open(opt->devDemux,O_RDWR)) < 0) { IO_error(opt->devDemux); close(pfd.fd); return -1; } ioctl (dmxfd,DMX_SET_BUFFER_SIZE, sizeof(buf)); flt.pid = pid; flt.input = DMX_IN_FRONTEND; flt.output = DMX_OUT_TS_TAP; flt.pes_type = DMX_PES_OTHER; flt.flags = DMX_IMMEDIATE_START; if (ioctl(dmxfd, DMX_SET_PES_FILTER, &flt) < 0) { IO_error("DMX_SET_PES_FILTER"); close(pfd.fd); close(dmxfd); return -1; } gettimeofday (&first_tv, NULL); last_tv.tv_sec = first_tv.tv_sec; last_tv.tv_usec = first_tv.tv_usec; b_total = 0; packets_total = 0; packets_bad = 0; while ( !isSigAbort() ) { int b_len, b_start; // -- we will poll the PID in 2 secs intervall int timeout = 2000; b_len = 0; b_start = 0; if (poll(&pfd, 1, timeout) > 0) { if (pfd.revents & POLLIN) { b_len = read(pfd.fd, buf, sizeof(buf)); gettimeofday (&tv, NULL); if (b_len >= TS_LEN) { b_start = sync_ts (buf, b_len); } else { b_len = 0; } b = b_len - b_start; if (b == 0) continue; if (b < 0) { IO_error("read"); continue; } b_total += b; // -- calc bandwidth { unsigned long long bit_s; long d_tim_ms; int packets; packets = b/TS_LEN; packets_total += packets; // output on different verbosity levels // -- current bandwidth d_tim_ms = delta_time_ms (&tv, &last_tv); if (d_tim_ms <= 0) d_tim_ms = 1; // ignore usecs out (3, "packets read: %3d/(%ld) d_time: %2ld.%03ld s = ", packets, packets_total, d_tim_ms / 1000UL, d_tim_ms % 1000UL); // -- current bandwidth in kbit/sec // --- cast to unsigned long long so it doesn't overflow as // --- early, add time / 2 before division for correct rounding bit_s = (((unsigned long long)b * 8000ULL) + ((unsigned long long)d_tim_ms / 2ULL)) / (unsigned long long)d_tim_ms; out (1, "%5llu.%03llu kbit/s", bit_s / 1000ULL, bit_s % 1000ULL); // -- average bandwidth d_tim_ms = delta_time_ms (&tv,&first_tv); if (d_tim_ms <= 0) d_tim_ms = 1; // ignore usecs bit_s = ((b_total * 8000ULL) + ((unsigned long long)d_tim_ms / 2ULL)) / (unsigned long long)d_tim_ms; last_avg.kb_sec = (unsigned long) (bit_s / 1000ULL); last_avg.b_sec = (unsigned long) (bit_s % 1000ULL); out (2, " (Avrg: %5lu.%03lu kbit/s)", last_avg.kb_sec, last_avg.b_sec); // -- bad packet(s) check in buffer { int bp; bp = ts_error_count (buf+b_start, b); packets_bad += bp; out (4, " [bad: %d]", bp); } out_NL (1); } last_tv.tv_sec = tv.tv_sec; last_tv.tv_usec = tv.tv_usec; // count packets ? if (opt->rd_packet_count > 0) { opt->rd_packet_count -= b/TS_LEN; if (opt->rd_packet_count <= 0) break; } } } } // -- packets stats out (4, "## "); if (opt->ts_raw_mode) { out (2,"PID: <ALL>"); } else { out (2,"PID: %u (0x%04x)", pid, pid); } out (4, " bad/total packets: %ld/%ld (= %1.1Lf%%)", packets_bad, packets_total, (((long double) packets_bad)*100)/packets_total ); out (4, " Avrg: %5lu.%03lu kbit/s", last_avg.kb_sec, last_avg.b_sec); out_NL(4); if (ioctl(dmxfd, DMX_STOP) < 0) { IO_error("DMX_STOP"); } close(dmxfd); close(pfd.fd); return 0; }
int do_SignalStrength (OPTION *opt) { int fd_fe = 0; struct timeval tv,last_tv, first_tv; u_long count; FE_SIGNAL s; FE_SIG_CAP has; if (opt->inpPidFile) { fprintf (stderr,"Error: FileMode not supported...\n"); return -1; } if((fd_fe = open(opt->devFE,O_RDONLY)) < 0){ IO_error(opt->devFE); return -1; } // -- check capabilities has.ber = capability_Check (fd_fe, FE_READ_BER); has.snr = capability_Check (fd_fe, FE_READ_SNR); has.strength = capability_Check (fd_fe, FE_READ_SIGNAL_STRENGTH); has.status = capability_Check (fd_fe, FE_READ_STATUS); has.ublocks = capability_Check (fd_fe, FE_READ_UNCORRECTED_BLOCKS); indent (0); out_NL (2); out_nl (2,"---------------------------------------------------------"); out_nl (2,"Transponder/Frequency signal strength statistics..."); if (opt->rd_packet_count > 0) { out_nl (2,"max cycle count: %ld ", opt->rd_packet_count); } out_nl (9,"Capabilities: BER: %d SNR: %d SIG: %d STAT: %d UBLK: %d", has.ber, has.snr, has.strength, has.status, has.ublocks); out_nl (2,"---------------------------------------------------------"); gettimeofday (&first_tv, NULL); last_tv.tv_sec = first_tv.tv_sec; last_tv.tv_usec = first_tv.tv_usec; count = 0; while ( !isSigAbort() ) { int err; int d_tim_ms; count++; out (6, "cycle: %lu ",count); gettimeofday (&tv, NULL); d_tim_ms = delta_time_ms (&tv, &last_tv); if (d_tim_ms <= 0) d_tim_ms = 1; // ignore usecs last_tv.tv_sec = tv.tv_sec; last_tv.tv_usec = tv.tv_usec; out (6, "d_time: %ld.%03ld s ", d_tim_ms / 1000UL, d_tim_ms % 1000UL); err = read_Signal (fd_fe, &s, &has); if (err == -1) return -1; // if (err == -2) { // out_nl (1," No signal..."); // continue; // } // & 0xFFFF necessary, due to interface transformations?? if (has.strength) out (1,"Sig: %u ", s.strength & 0xFFFFL); if (has.snr) out (2,"SNR: %u ", s.snr & 0xFFFFL); if (has.ber) out (3,"BER: %lu ",s.ber); if (has.ublocks) out (4,"UBLK: %ld ",s.ublocks); if (has.status) { out (4,"Stat: 0x%02x ",s.status); out_status_detail (5,s.status); } out_NL(1); if (opt->timeout_ms) usleep (opt->timeout_ms * 1000); if (d_tim_ms == 0) usleep (1000); // don't kill the system // count cycles? ? if (opt->rd_packet_count && (opt->rd_packet_count <= count)) break; } // while close(fd_fe); return 0; }
int main(int argc, char **argv) { OPTION opt; int err = 0; /* -- init options and cmdline parsing */ init_PidMemory (); if (! cmdline_options (argc,argv, &opt) ) return (-1); setVerboseLevel (opt.printdecode); setHexPrintMode (opt.printhex); indent (0); if (! opt.binary_out) { if (! opt.hide_copyright) { out_nl (1, "%s -- %s ", DVBSNOOP_PROG_VERSION, DVBSNOOP_URL); } if (! opt.inpPidFile) { if (opt.pid != DUMMY_PID) { out_nl (9, " PID : %d (0x%04x)",opt.pid,opt.pid); } if ((opt.packet_mode == SECT) && (opt.filterLen > 0)) { // filter are only for sections int i; out (9, " Filter: 0x"); for (i=0; i < opt.filterLen; i++) { out (9,"%02x ",opt.filter[i]); } out_NL (9); out (9, " Mask : 0x"); for (i=0; i < opt.filterLen; i++) { out (9,"%02x ",opt.mask[i]); } out_NL (9); out_nl (9, " Max. Filtersize: %d",DMX_FILTER_SIZE); } out_nl (9, " DEMUX : %s",opt.devDemux); out_nl (9, " DVR : %s",opt.devDvr); out_nl (9, " FRONTEND: %s",opt.devFE); } } initOSSigHandler (); init_receive_time (); switch (opt.packet_mode) { case SECT: err = doReadSECT (&opt); break; case PS: case PES: err = doReadPES (&opt); break; case TS: err = doReadTS (&opt); break; case PIDSCAN: err = ts_pidscan (&opt); break; case PIDBANDWIDTH: err = ts_pidbandwidth (&opt); break; case SCAN_FE_SIGNAL: err = do_SignalStrength (&opt); break; case SCAN_FE_INFO: err = do_FE_Info (&opt); break; default: fprintf (stderr,"unknown snoop type (this should never happen).\n"); break; } if ( isSigAbort() ) { out_nl (1,"... aborted (Signal: %d)",isSigAbort()); } restoreOSSigHandler(); return err; }