summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Lucina <mato@kotelna.sk>2010-01-30 15:56:01 +0100
committerMartin Lucina <mato@kotelna.sk>2010-01-30 15:56:01 +0100
commit3314f2e66721cbf0856591e7e8142f61f79c7771 (patch)
tree7b02d6a6fa8087bef7e9b65894997588d5a23e28
parent795d551b0863dfb9f33cfb37ebc1ffaede146c5a (diff)
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.
-rw-r--r--zmq-camera.c66
1 files 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 <arpa/inet.h>
#include <assert.h>
#include <pthread.h>
+#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <unicap.h>
@@ -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))