summaryrefslogtreecommitdiff
path: root/zmq-camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'zmq-camera.c')
-rw-r--r--zmq-camera.c131
1 files changed, 68 insertions, 63 deletions
diff --git a/zmq-camera.c b/zmq-camera.c
index 007df9b..9ef2565 100644
--- a/zmq-camera.c
+++ b/zmq-camera.c
@@ -67,26 +67,24 @@ void *sender_thread (void *arg)
unicap_data_buffer_t src_buffer;
unicap_data_buffer_t dest_buffer;
unicap_data_buffer_t *returned_buffer;
+ int conversion_found = 0;
+ int index = 0;
sender_args = (struct sender_args_t *)arg;
/* 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. */
+ an inproc endpoint for the local loopback view and bind to the remote
+ endpoint specified by the user. */
s = zmq_socket (sender_args->ctx, ZMQ_PUB);
assert (s);
+ rc = zmq_connect (s, local_camera);
+ assert (rc == 0);
rc = zmq_bind (s, sender_args->endpoint);
if (rc != 0) {
fprintf (stderr, "zmq_bind (\"%s\"): %s\n", sender_args->endpoint,
zmq_strerror (errno));
exit (1);
}
- rc = zmq_connect (s, local_camera);
- if (rc != 0) {
- fprintf (stderr, "zmq_connect (\"%s\"): %s\n", local_camera,
- zmq_strerror (errno));
- exit (1);
- }
/* Open first available video capture device. */
if (!SUCCESS (unicap_enumerate_devices (NULL, &device, 0))) {
@@ -100,8 +98,6 @@ void *sender_thread (void *arg)
printf( "Opened video capture device: %s\n", device.identifier );
/* Find a suitable video format that we can convert to RGB24. */
- int conversion_found = 0;
- int index = 0;
while (SUCCESS (unicap_enumerate_formats (handle, NULL, &src_format,
index))) {
printf ("Trying video format: %s\n", src_format.identifier);
@@ -238,18 +234,16 @@ void *signal_thread (void *arg)
s = zmq_socket (signal_args->ctx, ZMQ_PUB);
assert (s);
rc = zmq_connect (s, local_signal);
- if (rc != 0) {
- fprintf (stderr, "zmq_connect (\"%s\"): %s\n", local_signal,
- zmq_strerror (errno));
- exit (1);
- }
+ assert (rc == 0);
+ /* Handle various termination signals and SIGALRM for alarm timer */
sigemptyset (&wait_set);
sigaddset (&wait_set, SIGTERM);
sigaddset (&wait_set, SIGINT);
sigaddset (&wait_set, SIGQUIT);
sigaddset (&wait_set, SIGALRM);
+ /* Loop and send a message to the main thread for each signal received */
while (1) {
rc = sigwait (&wait_set, &signo);
assert (rc == 0);
@@ -296,23 +290,34 @@ void err_usage(char *error)
/* Main program. */
int main (int argc, char *argv [])
{
- void *ctx,
- *s_sub,
- *s_signal;
+ void *ctx;
+ void *s_video; /* Video socket */
+ void *s_signal; /* Signalling socket */
int rc;
- int opt, opt_sender, opt_receiver, opt_frame_rate, frame_rate;
+ int opt;
+ int opt_sender; /* Sender mode? */
+ int opt_receiver;
+ int opt_frame_rate, frame_rate;
char *endpoint = NULL;
SDL_Surface *screen = NULL;
SDL_Surface *rgb_surface = NULL;
+ SDL_Event event; /* Event from UI */
uint32_t image_width, image_height;
int sdl_initialised = 0;
int quit = 0;
sigset_t block_set;
struct itimerval alarm_timer;
- uint64_t received_fps = 0;
- uint64_t received_bps = 0;
- double received_mbps;
+ uint64_t received_fps = 0; /* Frames received in the last second */
+ uint64_t received_bps = 0; /* Bytes received in the last second */
+ double received_mbps; /* Video bandwidth in megabits per second */
char window_title[80];
+ zmq_msg_t msg;
+ size_t msg_size;
+ unsigned char *data;
+ pthread_t signal_pthread, sender_pthread;
+ struct signal_args_t signal_args;
+ struct sender_args_t sender_args;
+ int received_signo; /* signo received from signal thread */
/* Parse command line. */
opt_sender = opt_receiver = opt_frame_rate = frame_rate = 0;
@@ -359,34 +364,31 @@ int main (int argc, char *argv [])
rc = zmq_bind (s_signal, local_signal);
assert (rc == 0);
- pthread_t signal;
- struct signal_args_t signal_args = {ctx};
- rc = pthread_create (&signal, NULL, signal_thread, (void *) &signal_args);
+ signal_args.ctx = ctx;
+ rc = pthread_create (&signal_pthread, NULL, signal_thread,
+ (void *)&signal_args);
assert (rc == 0);
/* Create a ZMQ_SUB socket to receive video data. If we're sending video,
bind to an inproc: endpoint that the sender thread will connect to,
- otherwise connect to the endpoint the user specified. */
- s_sub = zmq_socket (ctx, ZMQ_SUB);
- assert (s_sub);
+ otherwise connect to the remote endpoint the user specified. */
+ s_video = zmq_socket (ctx, ZMQ_SUB);
+ assert (s_video);
if (opt_sender) {
- rc = zmq_bind (s_sub, local_camera);
- if (rc != 0) {
- fprintf (stderr, "zmq_bind (\"%s\"): %s\n", local_camera,
- zmq_strerror (errno));
- exit (1);
- }
+ rc = zmq_bind (s_video, local_camera);
+ assert (rc == 0);
/* 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, frame_rate};
- pthread_t sender;
- rc = pthread_create (&sender, NULL, sender_thread,
- (void*) &sender_args);
+ sender_args.endpoint = endpoint;
+ sender_args.ctx = ctx;
+ sender_args.frame_rate = frame_rate;
+ rc = pthread_create (&sender_pthread, NULL, sender_thread,
+ (void *)&sender_args);
assert (rc == 0);
}
else {
- rc = zmq_connect (s_sub, endpoint);
+ rc = zmq_connect (s_video, endpoint);
if (rc != 0) {
fprintf (stderr, "zmq_connect (\"%s\"): %s\n", endpoint,
zmq_strerror (errno));
@@ -395,7 +397,7 @@ int main (int argc, char *argv [])
}
/* Subscribe to all messages on video and signal sockets. */
- rc = zmq_setsockopt (s_sub, ZMQ_SUBSCRIBE, "", 0);
+ rc = zmq_setsockopt (s_video, ZMQ_SUBSCRIBE, "", 0);
assert (rc == 0);
rc = zmq_setsockopt (s_signal, ZMQ_SUBSCRIBE, "", 0);
assert (rc == 0);
@@ -414,41 +416,41 @@ int main (int argc, char *argv [])
/* Set up pollset */
zmq_pollitem_t items[2];
- items[0].socket = s_sub;
+ items[0].socket = s_video;
items[0].events = ZMQ_POLLIN;
items[1].socket = s_signal;
items[1].events = ZMQ_POLLIN;
- /* Display video until user asks to quit. */
+ /*
+ * Main event loop
+ */
while (!quit) {
- zmq_msg_t msg;
- size_t msg_size;
- unsigned char *data;
- SDL_Event event;
-
- /* Poll for incoming messages on either socket */
+ /* Poll for incoming messages on either the video or
+ signalling socket */
rc = zmq_poll (items, 2, 100000);
assert (rc >= 0);
- /* Signal received */
+ /*
+ * Signal received
+ */
if (items[1].revents == ZMQ_POLLIN) {
rc = zmq_msg_init (&msg);
assert (rc == 0);
rc = zmq_recv (s_signal, &msg, 0);
assert (rc == 0);
assert (zmq_msg_size (&msg) == sizeof (int));
- int signo;
- memcpy (&signo, zmq_msg_data (&msg), sizeof (int));
+ memcpy (&received_signo, zmq_msg_data (&msg), sizeof (int));
- switch (signo) {
+ switch (received_signo) {
+ /* Termination request */
case SIGTERM:
case SIGINT:
case SIGQUIT:
fprintf (stderr, "Exiting.\n");
exit (1);
+ /* Alarm timer fired, update bandwidth statistics */
case SIGALRM:
- /* If the timer fired, recalculate bandwidth and update window title */
received_mbps = (double)received_bps * 8 / (1<<20);
snprintf (window_title, 80, "%s (%llu fps, %.2lf Mbps)",
opt_sender ? local_camera : endpoint,
@@ -457,18 +459,21 @@ int main (int argc, char *argv [])
SDL_WM_SetCaption (window_title, window_title);
received_fps = received_bps = 0;
break;
+ /* Ignore anything else */
default:
- ; /* Ignore anything else */
+ ;
}
zmq_msg_close (&msg);
}
- /* Video frame received */
+ /*
+ * Video frame received
+ */
if (items[0].revents == ZMQ_POLLIN) {
rc = zmq_msg_init (&msg);
assert (rc == 0);
- rc = zmq_recv (s_sub, &msg, 0);
+ rc = zmq_recv (s_video, &msg, 0);
assert (rc == 0);
/* Parse message data. */
@@ -540,13 +545,13 @@ int main (int argc, char *argv [])
received_bps += msg_size;
}
- /* Check if user asked to quit. */
- if (sdl_initialised) {
- while (SDL_PollEvent (&event))
- {
- if (event.type == SDL_QUIT)
- quit = 1;
- }
+ /*
+ * Poll for UI events
+ */
+ while (sdl_initialised && SDL_PollEvent (&event))
+ {
+ if (event.type == SDL_QUIT)
+ quit = 1;
}
}