sdl_image_saving.c
Upload User: shyika
Upload Date: 2017-11-25
Package Size: 1227k
Code Size: 8k
Category:

Video Capture

Development Platform:

Unix_Linux

  1. /*
  2.     unicap
  3.     Copyright (C) 2004  Arne Caspari
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.     This program is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.     GNU General Public License for more details.
  12.     You should have received a copy of the GNU General Public License
  13.     along with this program; if not, write to the Free Software
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15. */
  16. /**
  17.    sdl_display.c
  18.    This example demonstrates how to display a live video stream using libSDL
  19.  **/
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <unicap.h>
  23. #include <unicap_status.h>
  24. #include "colorspace.h"
  25. #include <SDL.h>
  26. #include <time.h>
  27. #include <jpeglib.h>
  28. #define UYVY 0x59565955 /* UYVY (packed, 16 bits) */
  29. #define FOURCC(a,b,c,d) (unsigned int)((((unsigned int)d)<<24)+(((unsigned int)c)<<16)+(((unsigned int)b)<<8)+a)
  30. #define MIN(x,y) (x < y ? x : y )
  31. int main( int argc, char **argv )
  32. {
  33. unicap_handle_t handle;
  34. unicap_device_t device;
  35. unicap_format_t format_spec;
  36. unicap_format_t format;
  37. unicap_data_buffer_t buffer;
  38. unicap_data_buffer_t *returned_buffer;
  39. int width, height;
  40. int i;
  41. SDL_Surface *screen;
  42. SDL_Overlay *overlay;
  43. int quit=0;
  44. int imgcnt = 0;
  45. printf( "select video devicen" );
  46. for( i = 0; SUCCESS( unicap_enumerate_devices( NULL, &device, i ) ); i++ )
  47. {
  48. printf( "%i: %sn", i, device.identifier );
  49. }
  50. if( --i > 0 )
  51. {
  52. printf( "Select video capture device: " );
  53. scanf( "%d", &i );
  54. }
  55. if( !SUCCESS( unicap_enumerate_devices( NULL, &device, i ) ) )
  56. {
  57. fprintf( stderr, "Failed to get info for device '%s'n", device.identifier );
  58. exit( 1 );
  59. }
  60. /*
  61.   Acquire a handle to this device
  62.  */
  63. if( !SUCCESS( unicap_open( &handle, &device ) ) )
  64. {
  65. fprintf( stderr, "Failed to open device: %sn", device.identifier );
  66. exit( 1 );
  67. }
  68. printf( "Opened video capture device: %sn", device.identifier );
  69. /*
  70.   Create a format specification to limit the list of formats returned by 
  71.   unicap_enumerate_formats to the ones with the color format 'UYVY'
  72.  */
  73. unicap_void_format( &format_spec );
  74. format_spec.fourcc = FOURCC('U','Y','V','Y');
  75. /*
  76.   Get the list of video formats of the colorformat UYVY
  77.  */
  78. for( i = 0; SUCCESS( unicap_enumerate_formats( handle, &format_spec, &format, i ) ); i++ )
  79. {
  80. printf( "%d: %s [%dx%d]n", 
  81. i,
  82. format.identifier, 
  83. format.size.width, 
  84. format.size.height );
  85. }
  86. if( --i > 0 )
  87. {
  88. printf( "Select video format: " );
  89. scanf( "%d", &i );
  90. }
  91. if( !SUCCESS( unicap_enumerate_formats( handle, &format_spec, &format, i ) ) )
  92. {
  93. fprintf( stderr, "Failed to get video formatn" );
  94. exit( 1 );
  95. }
  96.    /*
  97.      If a video format has more than one size, ask for which size to use
  98.    */
  99.    if( format.size_count )
  100.    {
  101.       for( i = 0; i < format.size_count; i++ )
  102.       {
  103.  printf( "%d: %dx%dn", i, format.sizes[i].width, format.sizes[i].height );
  104.       }
  105.       do
  106.       {
  107.  printf( "Select video format size: " );
  108.  scanf( "%d", &i );
  109.       }while( ( i < 0 ) && ( i > format.size_count ) );
  110.       format.size.width = format.sizes[i].width;
  111.       format.size.height = format.sizes[i].height;
  112.    }
  113. /*
  114.   Set this video format
  115.  */
  116. if( !SUCCESS( unicap_set_format( handle, &format ) ) )
  117. {
  118. fprintf( stderr, "Failed to set video formatn" );
  119. exit( 1 );
  120. }
  121. /*
  122.   Initialize the image buffer
  123.  */
  124. memset( &buffer, 0x0, sizeof( unicap_data_buffer_t ) );
  125. /**
  126.    Init SDL & SDL_Overlay
  127.  **/
  128. if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
  129. {
  130.    fprintf(stderr, "Failed to initialize SDL:  %sn", SDL_GetError());
  131.    exit(1);
  132. }
  133. atexit(SDL_Quit);
  134. /*
  135.   Make sure the video window does not get too big. 
  136.  */
  137. width = MIN( format.size.width, 800 );
  138. height = MIN( format.size.height, 600 );
  139. screen = SDL_SetVideoMode( width, height, 32, SDL_HWSURFACE);
  140. if ( screen == NULL ) {
  141.    fprintf(stderr, "Unable to set video mode: %sn", SDL_GetError());
  142.    exit(1);
  143. }
  144. overlay = SDL_CreateYUVOverlay( format.size.width, 
  145. format.size.height, SDL_UYVY_OVERLAY, screen );
  146. if( overlay == NULL )
  147. {
  148.    fprintf( stderr, "Unable to create overlay: %sn", SDL_GetError() );
  149.    exit( 1 );
  150. }
  151. /*
  152.   Pass the pointer to the overlay to the unicap data buffer. 
  153.  */
  154. buffer.data = overlay->pixels[0];
  155.    buffer.buffer_size = format.size.width * format.size.height * format.bpp / 8;
  156. /*
  157.   Start the capture process on the device
  158.  */
  159. if( !SUCCESS( unicap_start_capture( handle ) ) )
  160. {
  161. fprintf( stderr, "Failed to start capture on device: %sn", device.identifier );
  162. exit( 1 );
  163. }
  164. while( !quit )
  165. {
  166. SDL_Rect rect;
  167. SDL_Event event;
  168. rect.x = 0;
  169. rect.y = 0;
  170. rect.w = width;
  171. rect.h = height;
  172. /*
  173.   Queue the buffer
  174.   
  175.   The buffer now gets filled with image data by the capture device
  176. */
  177. if( !SUCCESS( unicap_queue_buffer( handle, &buffer ) ) )
  178. {
  179. fprintf( stderr, "Failed to queue a buffer on device: %sn", device.identifier );
  180. exit( 1 );
  181. }
  182. /*
  183.   Wait until the image buffer is ready
  184. */
  185. if( !SUCCESS( unicap_wait_buffer( handle, &returned_buffer ) ) )
  186. {
  187. fprintf( stderr, "Failed to wait for buffer on device: %sn", device.identifier );
  188. }
  189. /*
  190.   Display the video data
  191.  */
  192. SDL_UnlockYUVOverlay( overlay );
  193. SDL_DisplayYUVOverlay( overlay, &rect );
  194. while( SDL_PollEvent( &event ) )
  195. {
  196. switch( event.type )
  197. {
  198. case SDL_QUIT:
  199. quit = 1;
  200. break;
  201. case SDL_MOUSEBUTTONDOWN:
  202. {
  203. unsigned char *pixels;
  204. struct jpeg_compress_struct cinfo;
  205. struct jpeg_error_mgr jerr;
  206. FILE *outfile;
  207. JSAMPROW row_pointer[1];
  208. int row_stride;
  209. char filename[128];
  210. struct timeval t1, t2;
  211. unsigned long long usecs;
  212. sprintf( filename, "%04d.jpg", imgcnt++ );
  213. cinfo.err = jpeg_std_error(&jerr);
  214. /* Now we can initialize the JPEG compression object. */
  215. jpeg_create_compress(&cinfo);
  216. if ((outfile = fopen( filename, "wb" ) ) == NULL ) 
  217. {
  218. fprintf(stderr, "can't open %sn", "file");
  219. exit(1);
  220. }
  221. jpeg_stdio_dest(&cinfo, outfile);
  222. cinfo.image_width = format.size.width;  /* image width and height, in pixels */
  223. cinfo.image_height = format.size.height;
  224. cinfo.input_components = 3; /* # of color components per pixel */
  225. cinfo.in_color_space = JCS_RGB;  /* colorspace of input image */
  226. jpeg_set_defaults(&cinfo);
  227. pixels = malloc( format.size.width * format.size.height * 3 );
  228. uyvy2rgb24( pixels, returned_buffer->data,
  229.     format.size.width * format.size.height * 3,
  230.     format.size.width * format.size.height * 2 );
  231. gettimeofday( &t1, NULL );
  232. jpeg_start_compress(&cinfo, TRUE);
  233. while( cinfo.next_scanline < cinfo.image_height )
  234. {
  235. row_pointer[0] = &pixels[cinfo.next_scanline * format.size.width * 3 ];
  236. (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
  237. }
  238. jpeg_finish_compress(&cinfo);
  239. gettimeofday( &t2, NULL );
  240. usecs = t2.tv_sec * 1000000LL + t2.tv_usec;
  241. usecs -= ( t1.tv_sec * 1000000LL + t1.tv_usec );
  242. printf( "Compression took: %lld usecn", usecs );
  243. /* After finish_compress, we can close the output file. */
  244. fclose(outfile);
  245. jpeg_destroy_compress(&cinfo);
  246. free( pixels );
  247. }
  248. break;
  249. default: 
  250. break;
  251. }
  252. }
  253. SDL_LockYUVOverlay(overlay);
  254. }
  255. /*
  256.   Stop the device
  257.  */
  258. if( !SUCCESS( unicap_stop_capture( handle ) ) )
  259. {
  260. fprintf( stderr, "Failed to stop capture on device: %sn", device.identifier );
  261. }
  262. /*
  263.   Close the device 
  264.   This invalidates the handle
  265.  */
  266. if( !SUCCESS( unicap_close( handle ) ) )
  267. {
  268. fprintf( stderr, "Failed to close the device: %sn", device.identifier );
  269. }
  270. SDL_Quit();
  271. return 0;
  272. }