/* Copyright (c) 2010 Martin Lucina This file is part of zeromq-examples. zeromq-examples is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. zeromq-examples is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ // Standalone application for testing video capture // (without use of 0MQ) #include #include #include #include #include #include #define FOURCC(a,b,c,d) (unsigned int)((((unsigned int)d)<<24)+(((unsigned int)c)<<16)+(((unsigned int)b)<<8)+a) int main (void) { unicap_handle_t handle; unicap_device_t device; unicap_format_t src_format; unicap_format_t dest_format; unicap_data_buffer_t src_buffer; unicap_data_buffer_t dest_buffer; unicap_data_buffer_t *returned_buffer; SDL_Surface *screen; SDL_Surface *rgb_surface; int quit = 0; int conversion_found = 0; int index = 0; // Open first available video capture device if (!SUCCESS (unicap_enumerate_devices (NULL, &device, 0))) { fprintf (stderr, "Could not enumerate devices\n"); exit (1); } if (!SUCCESS (unicap_open (&handle, &device))) { fprintf (stderr, "Failed to open device: %s\n", device.identifier); exit (1); } printf( "Opened video capture device: %s\n", device.identifier ); // Find a suitable video format that we can convert to RGB24 while (SUCCESS (unicap_enumerate_formats (handle, NULL, &src_format, index))) { printf ("Trying video format: %s\n", src_format.identifier); if (ucil_conversion_supported (FOURCC ('R', 'G', 'B', '3'), src_format.fourcc)) { conversion_found = 1; break; } index++; } if (!conversion_found) { fprintf (stderr, "Could not find a suitable video format\n"); exit (1); } src_format.buffer_type = UNICAP_BUFFER_TYPE_USER; if (!SUCCESS (unicap_set_format (handle, &src_format))) { fprintf (stderr, "Failed to set video format\n"); exit (1); } printf ("Using video format: %s [%dx%d]\n", src_format.identifier, src_format.size.width, src_format.size.height); // Clone destination format with equal dimensions, but RGB24 colorspace unicap_copy_format (&dest_format, &src_format); strcpy (dest_format.identifier, "RGB 24bpp"); dest_format.fourcc = FOURCC ('R', 'G', 'B', '3'); dest_format.bpp = 24; dest_format.buffer_size = dest_format.size.width * dest_format.size.height * 3; // Initialise image buffers memset (&src_buffer, 0, sizeof (unicap_data_buffer_t)); src_buffer.data = malloc (src_format.buffer_size); src_buffer.buffer_size = src_format.buffer_size; memset (&dest_buffer, 0, sizeof (unicap_data_buffer_t)); dest_buffer.data = malloc (dest_format.buffer_size); dest_buffer.buffer_size = dest_format.buffer_size; dest_buffer.format = dest_format; // Initialise SDL if (SDL_Init (SDL_INIT_VIDEO) < 0) { fprintf (stderr, "Failed to initialize SDL: %s\n", SDL_GetError()); exit (1); } screen = SDL_SetVideoMode (dest_format.size.width, dest_format.size.height, 32, SDL_HWSURFACE); if (screen == NULL) { fprintf (stderr, "Unable to set video mode: %s\n", SDL_GetError ()); SDL_Quit (); exit (1); } // Start video capture if (!SUCCESS (unicap_start_capture (handle))) { fprintf (stderr, "Failed to start capture on device: %s\n", device.identifier); SDL_Quit (); exit (1); } // Display video until user closes window while (!quit) { SDL_Event event; // Queue buffer for video capture if (!SUCCESS (unicap_queue_buffer (handle, &src_buffer))) { fprintf (stderr, "Failed to queue a buffer on device: %s\n", device.identifier); SDL_Quit (); exit (1); } // Wait until buffer is ready if (!SUCCESS (unicap_wait_buffer (handle, &returned_buffer))) { fprintf (stderr, "Failed to wait for buffer on device: %s\n", device.identifier); SDL_Quit (); exit (1); } // Convert colorspace if (!SUCCESS (ucil_convert_buffer (&dest_buffer, &src_buffer))) { // XXX This fails sometimes for unknown reasons, just skip the frame for now fprintf (stderr, "Failed to convert video buffer\n"); } // Create RGB surface rgb_surface = SDL_CreateRGBSurfaceFrom ( dest_buffer.data, // Pixel data dest_format.size.width, // Width dest_format.size.height, // Height dest_format.bpp, // Depth dest_format.size.width * 3, // Scanline pitch 0, 0, 0, 0); // TODO RGBA mask // Blit surface to screen SDL_BlitSurface (rgb_surface, NULL, screen, NULL); SDL_UpdateRect (screen, 0, 0, 0, 0); SDL_FreeSurface (rgb_surface); // Check if user asked to quit while (SDL_PollEvent (&event)) { if (event.type == SDL_QUIT) quit = 1; } } // Cleanup and quit if (!SUCCESS (unicap_stop_capture (handle))) { fprintf (stderr, "Failed to stop capture on device: %s\n", device.identifier); } if (!SUCCESS (unicap_close (handle))) { fprintf (stderr, "Failed to close the device: %s\n", device.identifier); } SDL_Quit(); return 0; }