summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Lucina <mato@kotelna.sk>2010-01-30 16:34:24 +0100
committerMartin Lucina <mato@kotelna.sk>2010-01-30 16:34:24 +0100
commitb8beebbef45b5f99b53256d6c0cc30c1785f8a90 (patch)
treeebc68a81fb557105675af9df5f1e714fcf4200d0
parentd44fe8406cf5e4bce66a0423c5292e9af1ed0067 (diff)
Add primitive frame rate limiting
Doesn't work quite as well as I would like it to, but until 0MQ has queue limits implemented it's useful if you want to test a large video stream on e.g. 802.11g wifi. Also added proper option handling using getopt().
-rw-r--r--zmq-camera.c69
1 files changed, 50 insertions, 19 deletions
diff --git a/zmq-camera.c b/zmq-camera.c
index 1dd7ce3..717eade 100644
--- a/zmq-camera.c
+++ b/zmq-camera.c
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <unistd.h>
#include <unicap.h>
#include <ucil.h>
@@ -44,6 +45,7 @@ struct sender_args_t
{
const char *endpoint;
void *ctx;
+ int frame_rate;
};
/*
@@ -65,14 +67,13 @@ void *sender_thread (void *arg)
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
specified by the user. */
@@ -207,6 +208,10 @@ void *sender_thread (void *arg)
rc = zmq_send (s, &msg, 0);
assert (rc == 0);
zmq_msg_close (&msg);
+
+ /* Limit to maximum frame rate if requested */
+ if (sender_args->frame_rate > 1)
+ usleep (1000000 / sender_args->frame_rate);
}
return NULL;
@@ -216,22 +221,28 @@ void *sender_thread (void *arg)
* Print usage and exit.
*/
-void err_usage(void)
+void err_usage(char *error)
{
const char usage[] = \
- "Usage: zmq-camera -r | -s ENDPOINT\n" \
+ "Usage: zmq-camera [OPTIONS] -r | -s ENDPOINT\n" \
"Sends or receives video using 0MQ.\n" \
"\n" \
+ "Mode:\n" \
" -r receive video from ENDPOINT\n" \
" -s send video to ENDPOINT\n" \
"\n" \
"ENDPOINT is any 0MQ endpoint valid for a ZMQ_PUB/ZMQ_SUB socket.\n"
"\n" \
+ "Options:\n" \
+ " -f RATE limit maximum frame rate to RATE\n" \
+ "\n" \
"Examples:\n" \
"\n" \
" zmq-camera -s tcp://eth0:5555\n" \
" zmq-camera -r tcp://eth0:5555\n";
-
+
+ if (error)
+ fprintf (stderr, "Error: %s\n", error);
fprintf (stderr, "%s", usage);
exit (1);
}
@@ -251,7 +262,7 @@ int main (int argc, char *argv [])
{
void *ctx, *s;
int rc;
- int is_sender = 0;
+ int opt, opt_sender, opt_receiver, opt_frame_rate, frame_rate;
char *endpoint = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *rgb_surface = NULL;
@@ -265,15 +276,33 @@ int main (int argc, char *argv [])
char window_title[80];
/* Parse command line. */
- if (argc != 3)
- err_usage();
- if (strcmp (argv [1], "-r") == 0)
- is_sender = 0;
- else if (strcmp (argv [1], "-s") == 0)
- is_sender = 1;
- else
- err_usage();
- endpoint = argv [2];
+ opt_sender = opt_receiver = opt_frame_rate = frame_rate = 0;
+ while ((opt = getopt (argc, argv, "rsf:")) != -1) {
+ switch (opt) {
+ case 'r':
+ opt_receiver = 1;
+ break;
+ case 's':
+ opt_sender = 1;
+ break;
+ case 'f':
+ opt_frame_rate = 1;
+ frame_rate = atoi (optarg);
+ if (frame_rate < 1)
+ err_usage ("RATE must be numeric and non-zero");
+ printf ("Limiting frame rate to %d fps\n", frame_rate);
+ break;
+ default:
+ err_usage (NULL);
+ }
+ }
+ if (optind >= argc)
+ err_usage ("Expected ENDPOINT argument after options");
+ if (opt_receiver && opt_sender)
+ err_usage ("Please specify either the -r or -s option");
+ if ((opt_receiver == 0) && (opt_sender == 0))
+ err_usage ("Please specify either the -r or -s option");
+ endpoint = argv [optind];
/* Initialise 0MQ infrastructure for 2 application threads and
a single I/O thread */
@@ -285,7 +314,7 @@ int main (int argc, char *argv [])
otherwise connect to the endpoint the user specified. */
s = zmq_socket (ctx, ZMQ_SUB);
assert (s);
- if (is_sender) {
+ if (opt_sender) {
rc = zmq_bind (s, local_camera);
if (rc != 0) {
fprintf (stderr, "zmq_bind (\"%s\"): %s\n", local_camera,
@@ -295,7 +324,7 @@ int main (int argc, char *argv [])
/* 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};
+ struct sender_args_t sender_args = {endpoint, ctx, frame_rate};
pthread_t sender;
rc = pthread_create (&sender, NULL, sender_thread,
(void*) &sender_args);
@@ -328,7 +357,7 @@ int main (int argc, char *argv [])
assert (rc == 0);
/* Intial window title is the endpoint we are receiving from */
- snprintf (window_title, 80, "%s", is_sender ? local_camera : endpoint);
+ snprintf (window_title, 80, "%s", opt_sender ? local_camera : endpoint);
/* Display video until user asks to quit. */
while (!quit) {
@@ -385,6 +414,8 @@ int main (int argc, char *argv [])
SDL_Quit ();
exit (1);
}
+ /* Set initial window title */
+ SDL_WM_SetCaption (window_title, window_title);
sdl_initialised = 1;
}
@@ -413,7 +444,7 @@ int main (int argc, char *argv [])
if (alarm_expired) {
double received_mbps = (double)received_bps * 8 / (1<<20);
snprintf (window_title, 80, "%s (%llu fps, %.2lf Mbps)",
- is_sender ? local_camera : endpoint,
+ opt_sender ? local_camera : endpoint,
(long long unsigned int) received_fps, received_mbps);
SDL_WM_SetCaption (window_title, window_title);
received_fps = received_bps = 0;