1/* 2 * getjpeg.c, sample tool for grabbing images from video devices 3 * 4 * Copyright (c) 2003 Joerg Heckenbach <joerg@heckenbach-aw.de> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 * 20 */ 21 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <fcntl.h> 28#include <unistd.h> 29#include <linux/types.h> 30#include <linux/videodev.h> 31#include <sys/ioctl.h> 32#include <sys/mman.h> 33#include <libgen.h> 34 35#define GETJPEG_MMAP 36#define DEF_WIDTH 640 37#define DEF_HEIGHT 480 38 39void 40usage (char *pname) 41{ 42 fprintf (stderr, 43 "Usage: %s <options>\n" 44 " -d <device> video device (default: /dev/video)\n" 45 " -o <file> write output to file instead of stdout\n" 46 " -s NxN define size of the output image (default:" 47 " %dx%d)\n" 48 " -n <num> number of frames to grab\n" 49 "Example: %s -d /dev/video0 -o imagefile -s 640x480 -n 10\n", 50 (char*)basename(pname), DEF_WIDTH, DEF_HEIGHT, (char*)basename(pname)); 51 exit (1); 52} 53 54int main(int argc, char **argv) 55{ 56 FILE *ofid; 57 int ifid; 58 ssize_t count; 59 int num_frames=1, frame=0; 60#ifndef GETJPEG_MMAP 61 unsigned char buffer[524288]; 62#endif 63 char default_dev[] = "/dev/video"; 64 char *device = default_dev; 65 char default_file_templ[] = "image"; 66 char *file_templ = default_file_templ; 67 char filename[255]; 68 69 char *vmbuffer = NULL; 70 unsigned short *vmpointer = NULL; 71 struct video_mbuf vmbuf; 72 struct video_mmap vmmap; 73 int c; 74 int width = DEF_WIDTH, height = DEF_HEIGHT; 75 76 while ((c = getopt (argc, argv, "d:o:s:n:")) != EOF) { 77 switch (c) { 78 case 'd': /* change default device */ 79 device = optarg; 80 break; 81 case 'o': 82 file_templ = optarg; 83 break; 84 case 'n': 85 sscanf (optarg, "%d", &num_frames); 86 break; 87 case 's': 88 sscanf (optarg, "%dx%d", &width, &height); 89 break; 90 default: 91 usage (argv[0]); 92 break; 93 } 94 } 95 96// if ((ifid = open(device, O_RDWR)) < 0) { 97// printf("Could not open device %s\n", device); 98// return -1; 99// } 100// sleep(1); 101// count = read(ifid, buffer, sizeof(buffer)); 102// close(ifid); 103//sleep(1); 104 105 if ((ifid = open(device, O_RDWR)) < 0) { 106 printf("Could not open device %s\n", device); 107 return -1; 108 } 109 110#ifdef GETJPEG_MMAP 111 /* setup everything */ 112 ioctl(ifid, VIDIOCGMBUF, &vmbuf); 113 //printf("VMBUF: size=%d, frames=%d, offset[0]=%d, offset[1]=%d\n", 114 // vmbuf.size, vmbuf.frames, vmbuf.offsets[0], vmbuf.offsets[1]); 115 116 vmbuffer = mmap(0, vmbuf.size, PROT_READ, MAP_SHARED, ifid, 0); 117 if (!(vmbuffer)) 118 perror("mmap failed"); 119 120 vmmap.format = VIDEO_PALETTE_RGB24; 121 vmmap.frame = 0; 122 vmmap.width = width; 123 vmmap.height = height; 124 125 if (ioctl (ifid, VIDIOCMCAPTURE, &vmmap) == -1) { 126 perror ("VIDIOCMCAPTURE(0)"); 127 } 128 vmmap.frame = 1; 129 130 for (frame = 0; frame < num_frames; frame++) { 131 132 if (ioctl (ifid, VIDIOCMCAPTURE, &vmmap) == -1) { 133 perror ("VIDIOCMCAPTURE()"); 134 } 135 vmmap.frame = (vmmap.frame + 1) % vmbuf.frames; 136 if (ioctl (ifid, VIDIOCSYNC, &vmmap.frame) == -1) { 137 perror ("VIDIOCSYNC()"); 138 } 139 140 /* process frame while the hardware captures next frame */ 141 sprintf(filename, "%s-%02d.jpg", file_templ, frame); 142 143 if ((ofid = fopen(filename, "wb")) == NULL) { 144 printf("Could not open file %s for writing\n", filename); 145 return -1; 146 } 147 // The length / 8 of the JPEG is stored in the first 2 bytes of vmbuffer 148 vmpointer = (unsigned short *)(vmbuffer+vmbuf.offsets[vmmap.frame]); 149 count = (ssize_t)((unsigned int)(vmpointer[0])<<3); 150 151 if (fwrite(vmbuffer+vmbuf.offsets[vmmap.frame] + 2, sizeof(unsigned char), (size_t)count, ofid) == count) { 152 printf("Frame %d, %d bytes... success\n", frame, (int)count); 153 } 154 fclose(ofid); 155 156 } 157 158 munmap (vmbuffer, vmbuf.size); 159 160#else // v4l_read 161 162 for (frame = 0; frame < num_frames; frame++) { 163 count = read(ifid, buffer, sizeof(buffer)) - 2; // Delete the 2 bytes of length information 164 165 sprintf(filename, "%s-%02d.jpg", file_templ, frame); 166 167 if ((ofid = fopen(filename, "wb")) == NULL) { 168 printf("Could not open file %s for writing\n", filename); 169 return -1; 170 } 171 if (fwrite(buffer + 2, sizeof(unsigned char), (size_t)count, ofid) == count) { 172 printf("Frame %d, %d bytes... success\n", frame, (int)count); 173 } 174 fclose(ofid); 175 } 176 177#endif 178 close(ifid); 179 180 return 0; 181} 182