dvbv5-zap: add traffic monitor support
authorMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 19 Mar 2013 21:28:43 +0000 (18:28 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 19 Mar 2013 22:50:33 +0000 (19:50 -0300)
Add some code to do traffic monitor. The code there came from
dvb-apps dvbtraffic.c file, released under public domain.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
lib/libdvbv5/dvb-demux.c
utils/dvb/dvbv5-zap.c

index 6ed2dcd..2029204 100644 (file)
@@ -64,12 +64,6 @@ int dvb_set_pesfilter(int dmxfd, int pid, dmx_pes_type_t type, dmx_output_t outp
 {
        struct dmx_pes_filter_params pesfilter;
 
-       /* ignore this pid to allow radio services */
-       if (pid < 0 ||
-               pid >= 0x1fff ||
-               (pid == 0 && type != DMX_PES_OTHER))
-               return 0;
-
        if (buffersize) {
                if (ioctl(dmxfd, DMX_SET_BUFFER_SIZE, buffersize) == -1)
                        perror("DMX_SET_BUFFER_SIZE failed");
index d8e1872..b7cac00 100644 (file)
@@ -32,6 +32,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <argp.h>
+#include <sys/time.h>
 
 #include <config.h>
 
@@ -56,6 +57,8 @@ struct arguments {
        unsigned record;
        unsigned n_apid, n_vpid;
        enum file_formats input_format, output_format;
+       unsigned traffic_monitor;
+       char *search;
 
        /* Used by status print */
        unsigned n_status_lines;
@@ -81,7 +84,9 @@ static const struct argp_option options[] = {
        {"timeout",     't', "seconds",                 0, "timeout for zapping and for recording", 0},
        {"output",      'o', "file",                    0, "output filename (use -o - for stdout)", 0},
        {"input-format", 'I',   "format",               0, "Input format: ZAP, CHANNEL, DVBV5 (default: DVBV5)", 0},
-       {"dvbv3",       '3',    0,                      0, "Use DVBv3 only", 0},
+       {"dvbv3",       '3', NULL,                      0, "Use DVBv3 only", 0},
+       {"monitor",     'm', NULL,                      0, "monitors de DVB traffic", 0},
+       {"search",      'L', NULL,                      0, "search/look for a string inside the traffic", 0},
        { 0, 0, 0, 0, 0, 0 }
 };
 
@@ -462,12 +467,131 @@ static error_t parse_opt(int k, char *optarg, struct argp_state *state)
        case '3':
                args->force_dvbv3 = 1;
                break;
+       case 'm':
+               args->traffic_monitor = 1;
+               break;
+       case 'L':
+               args->search = strdup(optarg);
+               break;
        default:
                return ARGP_ERR_UNKNOWN;
        };
        return 0;
 }
 
+#define BSIZE 188
+
+int do_traffic_monitor(struct arguments *args,
+                   struct dvb_v5_fe_parms *parms)
+{
+       int fd, dvr_fd;
+       long long unsigned pidt[0x2001], wait;
+       int packets = 0;
+       struct timeval startt;
+
+       memset(pidt, 0, sizeof(pidt));
+
+       args->exit_after_tuning = 1;
+       check_frontend(args, parms);
+
+       if ((dvr_fd = open(args->dvr_dev, O_RDONLY)) < 0) {
+               PERROR("failed opening '%s'", args->dvr_dev);
+               return -1;
+       }
+
+       if (ioctl(dvr_fd, DMX_SET_BUFFER_SIZE, 1024 * 1024) == -1)
+               perror("DMX_SET_BUFFER_SIZE failed");
+
+       if ((fd = open(args->demux_dev, O_RDWR)) < 0) {
+               PERROR("failed opening '%s'", args->demux_dev);
+               return -1;
+       }
+
+       if (args->silent < 2)
+               fprintf(stderr, "  dvb_set_pesfilter to 0x2000\n");
+       if (dvb_set_pesfilter(fd, 0x2000, DMX_PES_OTHER,
+                             DMX_OUT_TS_TAP, 0) < 0) {
+               PERROR("couldn't set filter");
+               return -1;
+       }
+
+       gettimeofday(&startt, 0);
+       wait = 1000;
+
+       while (1) {
+               unsigned char buffer[BSIZE];
+               int pid, ok;
+               ssize_t r;
+               if ((r = read(dvr_fd, buffer, BSIZE)) <= 0) {
+                       perror("read");
+                       break;
+               }
+               if (r != BSIZE) {
+                       fprintf(stderr, "dvbtraffic: only read %zd bytes\n", r);
+                       break;
+               }
+               if (buffer[0] != 0x47) {
+                       continue;
+                       printf("desync (%x)\n", buffer[0]);
+                       while (buffer[0] != 0x47)
+                               read(fd, buffer, 1);
+                       continue;
+               }
+               ok = 1;
+               pid = ((((unsigned) buffer[1]) << 8) |
+                      ((unsigned) buffer[2])) & 0x1FFF;
+
+               if (args->search) {
+                       int i, sl = strlen(args->search);
+                       ok = 0;
+                       if (pid != 0x1fff) {
+                               for (i = 0; i < (188 - sl); ++i) {
+                                       if (!memcmp(buffer + i, args->search, sl))
+                                               ok = 1;
+                               }
+                       }
+               }
+
+               if (ok) {
+                       pidt[pid]++;
+                       pidt[0x2000]++;
+               }
+
+               packets++;
+
+               if (!(packets & 0xFF)) {
+                       struct timeval now;
+                       int diff;
+                       gettimeofday(&now, 0);
+                       diff =
+                           (now.tv_sec - startt.tv_sec) * 1000 +
+                           (now.tv_usec - startt.tv_usec) / 1000;
+                       if (diff > wait) {
+                               if (isatty(STDERR_FILENO))
+                                       printf("\x1b[1H\x1b[2J");
+
+                               args->n_status_lines = 0;
+                               printf(" PID         FREQ    BANDWIDTH      KBYTES\n");
+                               int _pid = 0;
+                               for (_pid = 0; _pid < 0x2001; _pid++) {
+                                       if (pidt[_pid]) {
+                                               printf("%04x %8.2f p/s %7.1f kb/s %8d Kb\n",
+                                                    _pid,
+                                                    pidt[_pid] * 1000. / diff,
+                                                    pidt[_pid] * 1000. / diff * 188 / 1024,
+                                                    pidt[_pid] * 8 * 188 / 1024);
+                                       }
+                               }
+                               printf("\n\n");
+                               print_frontend_stats(args, parms);
+                               wait += 1000;
+                       }
+               }
+       }
+       close (fd);
+       return 0;
+}
+
 int main(int argc, char **argv)
 {
        struct arguments args;
@@ -560,6 +684,9 @@ int main(int argc, char **argv)
                return 0;
        }
 
+       if (args.traffic_monitor)
+               return do_traffic_monitor(&args, parms);
+
        if (args.rec_psi) {
                if (sid < 0) {
                        fprintf(stderr, "Service id 0x%04x was not specified at the file\n",