FPS option part 2
[fswebcam.git] / src_file.c
blob731cc8a220bdcfd3864d01c6fad567cb48879ec4
1 /* fswebcam - FireStorm.cx's webcam generator */
2 /*===========================================================*/
3 /* Copyright (C)2005-2006 Philip Heron <phil@firestorm.cx> */
4 /* */
5 /* This program is distributed under the terms of the GNU */
6 /* General Public License, version 2. You may use, modify, */
7 /* and redistribute it under the terms of this license. A */
8 /* copy should be included with this source. */
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18 #include <sys/stat.h>
19 #include "src.h"
20 #include "log.h"
22 typedef struct {
24 FILE *f;
26 uint8_t *start;
27 size_t length;
29 } src_file_t;
31 int src_file_open_jpeg(src_t *src)
33 src_file_t *s = (src_file_t *) src->state;
34 uint8_t *p;
36 src->palette = SRC_PAL_JPEG;
38 /* Scan the JPEG segments for the SOF, which contains
39 * the width and height of the image. */
41 p = s->start + 2;
43 while(p - s->start < src->length - 3)
45 uint8_t header;
46 uint16_t length;
48 /* Check for the segment marker. */
49 if(*(p++) != 0xFF)
51 ERROR("Segment marker not found,");
52 return(-1);
55 header = *(p++);
56 length = (p[0] << 8) + p[1];
58 /* Verify the full segment is present. */
59 if((p - s->start) + length >= s->length)
61 ERROR("Incomplete segment.");
62 return(-1);
65 if(header == 0xC0) /* SOF */
67 uint16_t width = (p[5] << 8) + p[6];
68 uint16_t height = (p[3] << 8) + p[4];
70 if(src->width != width ||
71 src->height != height)
73 MSG("Adjusting resolution to %ix%i.",
74 width, height);
76 src->width = width;
77 src->height = height;
80 return(0);
83 if(header == 0xD9 || /* EOI */
84 header == 0xDA) /* SOS */
86 WARN("%s: Unable to read resolution.", src->source);
87 return(-1);
90 p += length;
93 return(0);
96 int src_file_open_png(src_t *src)
98 src_file_t *s = (src_file_t *) src->state;
99 uint32_t width, height;
100 uint8_t *p;
102 src->palette = SRC_PAL_PNG;
104 if(s->length < 24)
106 ERROR("%s: Unexpected end of file.", src->source);
107 return(-1);
110 p = s->start + 12;
112 if(strncmp((char *) p, "IHDR", 4))
114 ERROR("%s: IHDR chunk must be first.", src->source);
115 return(-1);
118 p += 4;
120 width = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
121 height = (p[4] << 24) + (p[5] << 16) + (p[6] << 8) + p[7];
123 if(src->width != width ||
124 src->height != height)
126 MSG("Adjusting resolution to %ix%i.",
127 width, height);
129 src->width = width;
130 src->height = height;
133 return(0);
136 int src_file_open(src_t *src)
138 src_file_t *s;
139 struct stat st;
140 size_t size;
142 s = calloc(sizeof(src_file_t), 1);
143 if(!s)
145 ERROR("Out of memory.");
146 return(-2);
149 src->state = (void *) s;
151 /* Get the file's size in bytes. */
152 if(stat(src->source, &st) == -1)
154 ERROR("Error accessing file %s", src->source);
155 ERROR("stat: %s", strerror(errno));
156 free(s);
157 return(-2);
160 s->f = fopen(src->source, "rb");
161 if(!s->f)
163 ERROR("Error opening file %s", src->source);
164 ERROR("fopen: %s", strerror(errno));
165 free(s);
166 return(-2);
169 /* Allocate memory for the file. */
170 s->length = st.st_size;
171 s->start = (uint8_t *) malloc(s->length);
172 if(!s->start)
174 ERROR("Out of memory.");
175 fclose(s->f);
176 free(s);
177 return(-1);
180 /* Read the entire file into memory. */
181 size = 0;
182 while(!feof(s->f) && size < s->length)
183 size += fread(s->start, 1, s->length, s->f);
185 fclose(s->f);
186 s->f = NULL;
188 if(size != s->length)
190 ERROR("Error reading file. Read %i bytes of %i byte file.",
191 size, s->length);
192 free(s->start);
193 free(s);
194 return(-1);
197 src->length = s->length;
198 src->img = s->start;
200 /* Test for a JPEG file. */
201 if(s->start[0] == 0xFF && s->start[1] == 0xD8)
203 MSG("%s: Loading JPEG file.", src->source);
205 if(src_file_open_jpeg(src))
207 src_close(src);
208 return(-1);
211 return(0);
214 /* Test for a PNG file. */
215 if(s->start[0] == 0x89 && s->start[1] == 0x50 &&
216 s->start[2] == 0x4e && s->start[3] == 0x47)
218 MSG("%s: Loading PNG file.", src->source);
220 if(src_file_open_png(src))
222 src_close(src);
223 return(-1);
226 return(0);
229 ERROR("%s: Unknown file format.", src->source);
230 src_close(src);
232 return(-2);
235 int src_file_close(src_t *src)
237 src_file_t *s = (src_file_t *) src->state;
239 if(s->f) fclose(s->f);
240 free(s->start);
241 free(s);
243 return(0);
246 int src_file_grab(src_t *src)
248 return(0);
251 src_mod_t src_file = {
252 "file", SRC_TYPE_FILE,
253 src_file_open,
254 src_file_close,
255 src_file_grab