From 3314f2e66721cbf0856591e7e8142f61f79c7771 Mon Sep 17 00:00:00 2001 From: Martin Lucina Date: Sat, 30 Jan 2010 15:56:01 +0100 Subject: Implement bandwidth estimation Raw video streams require large amounts of bandwidth. For example a 640x480 RGB24 stream at 15 frames per second will consume around 100 Mbps. This code adds a bandwidth and fps display in the window title on the receiving side so that you can see the bandwidth requirements for the stream being sent. --- zmq-camera.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/zmq-camera.c b/zmq-camera.c index 3c0a5a7..c3e59c7 100644 --- a/zmq-camera.c +++ b/zmq-camera.c @@ -20,8 +20,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -60,8 +62,16 @@ void *sender_thread (void *arg) unicap_data_buffer_t src_buffer; unicap_data_buffer_t dest_buffer; unicap_data_buffer_t *returned_buffer; + sigset_t block_set; sender_args = (struct sender_args_t *)arg; + + /* Block SIGALRM in the sender thread since it's used for timers in the + main thread */ + sigemptyset (&block_set); + sigaddset (&block_set, SIGALRM); + pthread_sigmask (SIG_BLOCK, &block_set, NULL); + /* Create a ZMQ_PUB socket for sending video data and connect it to both an inproc endpoint for the local loopback view and bind to the endpoint @@ -230,6 +240,13 @@ void err_usage(void) * Main thread */ +volatile int alarm_expired = 0; + +void alarm_handler (int signo) +{ + alarm_expired = 1; +} + int main (int argc, char *argv []) { void *ctx, *s; @@ -241,6 +258,11 @@ int main (int argc, char *argv []) uint32_t image_width, image_height; int sdl_initialised = 0; int quit = 0; + struct sigaction alarm_action; + struct itimerval alarm_timer; + uint64_t received_fps = 0; + uint64_t received_bps = 0; + char window_title[80]; /* Parse command line. */ if (argc != 3) @@ -270,7 +292,7 @@ int main (int argc, char *argv []) zmq_strerror (errno)); exit (1); } - + /* Start the sender thread after binding to the inproc: endpoint since this must exist for it to connect. */ struct sender_args_t sender_args = {endpoint, ctx}; @@ -291,11 +313,28 @@ int main (int argc, char *argv []) /* Subscribe to all messages on socket. */ rc = zmq_setsockopt (s, ZMQ_SUBSCRIBE, "", 0); assert (rc == 0); + + /* Set up an interval timer to fire SIGALRM once a second so that + we can update bandwidth and fps statistics */ + alarm_action.sa_flags = 0; + alarm_action.sa_handler = alarm_handler; + rc = sigaction (SIGALRM, &alarm_action, NULL); + assert (rc == 0); + alarm_timer.it_interval.tv_sec = 1; + alarm_timer.it_interval.tv_usec = 0; + alarm_timer.it_value.tv_sec = 1; + alarm_timer.it_value.tv_usec = 0; + rc = setitimer (ITIMER_REAL, &alarm_timer, NULL); + assert (rc == 0); + + /* Intial window title is the endpoint we are receiving from */ + snprintf (window_title, 80, "%s", is_sender ? local_camera : endpoint); /* Display video until user asks to quit. */ while (!quit) { zmq_msg_t msg; + size_t msg_size; unsigned char *data; SDL_Event event; @@ -309,7 +348,8 @@ int main (int argc, char *argv []) data = (unsigned char*) zmq_msg_data (&msg); /* Sanity check that we have at least the width, height in the message data */ - assert (zmq_msg_size (&msg) >= sizeof (uint32_t) + sizeof (uint32_t)); + msg_size = zmq_msg_size (&msg); + assert (msg_size >= sizeof (uint32_t) + sizeof (uint32_t)); /* Get image width in pixels. */ memcpy (&image_width, data, sizeof (uint32_t)); @@ -321,6 +361,9 @@ int main (int argc, char *argv []) image_height = ntohl (image_height); data += sizeof (uint32_t); + /* Sanity check message size again */ + assert (msg_size >= image_width * image_height * 3); + /* data now points to RGB24 pixel data. */ if (!sdl_initialised) { @@ -342,11 +385,6 @@ int main (int argc, char *argv []) SDL_Quit (); exit (1); } - /* Set window title to endpoint we are receiving from */ - if (is_sender) - SDL_WM_SetCaption (local_camera, local_camera); - else - SDL_WM_SetCaption (endpoint, endpoint); sdl_initialised = 1; } @@ -367,6 +405,20 @@ int main (int argc, char *argv []) /* Free zmq_msg we received */ zmq_msg_close (&msg); + + /* Update statistics */ + received_fps += 1; + received_bps += msg_size; + /* If the timer fired, recalculate bandwidth and update window title */ + if (alarm_expired) { + double received_mbps = (double)received_bps * 8 / (1<<20); + snprintf (window_title, 80, "%s (%lu fps, %.2lf Mbps)", + is_sender ? local_camera : endpoint, + received_fps, received_mbps); + SDL_WM_SetCaption (window_title, window_title); + received_fps = received_bps = 0; + alarm_expired = 0; + } /* Check if user asked to quit. */ while (SDL_PollEvent (&event)) -- cgit v1.2.3