debug map_lut image
[sparrow.git] / sparrow.c
blob3c0662fe0b4073ac14b42f842eb65dd405a617eb
1 /* Copyright (C) <2010> Douglas Bagnall <douglas@halo.gen.nz>
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Library General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
8 * This library 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 GNU
11 * Library General Public License for more details.
13 * You should have received a copy of the GNU Library General Public
14 * License along with this library; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 02111-1307, USA.
19 #include "sparrow.h"
20 #include "gstsparrow.h"
22 #include <string.h>
23 #include <math.h>
25 /* static functions (via `make cproto`) */
26 static void change_state(GstSparrow *sparrow, sparrow_state state);
29 /* set up whatever debugging methods are enabled */
30 static void
31 init_debug(GstSparrow *sparrow){
32 if (!sparrow->debug_frame){
33 sparrow->debug_frame = malloc_aligned_or_die(MAX(sparrow->in.size, sparrow->out.size));
37 /*RNG code */
38 /*seed with -1 for automatic seed choice */
39 static void rng_init(GstSparrow *sparrow, guint32 seed){
40 GST_DEBUG("in RNG init\n");
41 if (seed == (guint32)-1){
42 /* XXX should really use /dev/urandom */
43 seed = rand() ^ (size_t)&(sparrow);
44 GST_DEBUG("Real seed %u\n", seed);
46 if (seed == 0)
47 seed = 12345;
49 dsfmt_init_gen_rand(sparrow->dsfmt, seed);
50 dsfmt_gen_rand_all(sparrow->dsfmt);
51 GST_DEBUG("RNG seeded with %u\n", seed);
54 /** debugging: write frames out somewhere. **/
56 /*spit out the frame as a ppm image */
57 void INVISIBLE
58 ppm_dump(sparrow_format *rgb, guint8 *data, guint32 width, guint32 height, const char *name)
60 guint i;
61 FILE *fh = fopen(name, "w");
62 guint32 size = width * height;
63 fprintf(fh, "P6\n%u %u\n255\n", width, height);
64 /* 4 cases: xBGR xRGB BGRx RGBx
65 need to convert to 24bit R G B
66 XX maybe could optimise some cases?
68 guint32 *p = (guint32 *)data;
69 for (i = 0; i < size; i++){
70 putc((*p >> rgb->rshift) & 255, fh);
71 putc((*p >> rgb->gshift) & 255, fh);
72 putc((*p >> rgb->bshift) & 255, fh);
73 p++;
75 fflush(fh);
76 fclose(fh);
79 /*pgm for greyscale */
80 void INVISIBLE
81 pgm_dump(guint8 *data, guint32 width, guint32 height, const char *name)
83 FILE *fh = fopen(name, "w");
84 size_t size = width * height;
85 fprintf(fh, "P5\n%u %u\n255\n", width, height);
86 size_t wrote = fwrite(data, 1, size, fh);
87 if (wrote != size){
88 GST_DEBUG("wanted to write %u bytes; fwrite said %u\n", size, wrote);
90 fflush(fh);
91 fclose(fh);
95 #define PPM_FILENAME_TEMPLATE "/tmp/sparrow_%05d.%s"
96 #define PPM_FILENAME_LENGTH (sizeof(PPM_FILENAME_TEMPLATE) + 15)
98 void INVISIBLE
99 debug_frame(GstSparrow *sparrow, guint8 *data, guint32 width, guint32 height, int pixsize){
100 char name[PPM_FILENAME_LENGTH];
101 int res;
102 if (pixsize == 4){ /*rgb*/
103 res = snprintf(name, PPM_FILENAME_LENGTH, PPM_FILENAME_TEMPLATE, sparrow->frame_count, "ppm");
104 if (res > 0){
105 ppm_dump(&(sparrow->in), data, width, height, name);
108 else {/*greyscale*/
109 res = snprintf(name, PPM_FILENAME_LENGTH, PPM_FILENAME_TEMPLATE, sparrow->frame_count, "pgm");
110 if (res > 0){
111 pgm_dump(data, width, height, name);
116 /** interpret gst attributes **/
118 /* Extract a colour (R,G,B) bitmask from gobject */
119 static guint32 get_mask(GstStructure *s, char *mask_name){
120 gint32 mask;
121 int res = gst_structure_get_int(s, mask_name, &mask);
122 if (!res){
123 GST_WARNING("No mask for '%s' !\n", mask_name);
125 return (guint32)mask;
128 static void
129 extract_caps(sparrow_format *im, GstCaps *caps)
131 GstStructure *s = gst_caps_get_structure (caps, 0);
132 gst_structure_get_int(s, "width", &(im->width));
133 gst_structure_get_int(s, "height", &(im->height));
134 im->rshift = mask_to_shift(get_mask(s, "red_mask"));
135 im->gshift = mask_to_shift(get_mask(s, "green_mask"));
136 im->bshift = mask_to_shift(get_mask(s, "blue_mask"));
137 /* recalculate shifts as little-endian */
138 im->rmask = 0xff << im->rshift;
139 im->gmask = 0xff << im->gshift;
140 im->bmask = 0xff << im->bshift;
141 im->rbyte = im->rshift / 8;
142 im->gbyte = im->gshift / 8;
143 im->bbyte = im->bshift / 8;
145 im->pixcount = im->width * im->height;
146 im->size = im->pixcount * PIXSIZE;
147 im->colours[SPARROW_WHITE] = im->rmask | im->gmask | im->bmask;
148 im->colours[SPARROW_GREEN] = im->gmask;
149 im->colours[SPARROW_MAGENTA] = im->rmask | im->bmask;
151 GST_DEBUG("\ncaps:\n%" GST_PTR_FORMAT, caps);
152 GST_DEBUG("shifts: r %u g %u b %u\n", im->rshift, im->gshift, im->bshift);
153 GST_DEBUG("dimensions: w %u h %u pix %u size %u\n", im->width, im->height,
154 im->pixcount, im->size);
159 /*Most functions below here are called from gstsparrow.c and are NOT static */
161 /* called by gst_sparrow_init(). The source/sink capabilities (and commandline
162 arguments[?]) are unknown at this stage, so there isn't much useful to do
163 here.*/
164 void INVISIBLE
165 sparrow_pre_init(GstSparrow *sparrow){
168 /* called by gst_sparrow_set_caps(). This sets up everything after gstreamer
169 has worked out what the pipeline will look like.
171 gboolean INVISIBLE
172 sparrow_init(GstSparrow *sparrow, GstCaps *incaps, GstCaps *outcaps){
173 change_state(sparrow, SPARROW_INIT);
174 extract_caps(&(sparrow->in), incaps);
175 extract_caps(&(sparrow->out), outcaps);
176 sparrow_format *in = &(sparrow->in);
178 sparrow->shared = sparrow_get_shared();
179 maybe_load_images(sparrow);
180 maybe_load_index(sparrow);
182 sparrow->dsfmt = zalloc_aligned_or_die(sizeof(dsfmt_t));
183 sparrow->screenmask = malloc_aligned_or_die(in->pixcount);
185 #if ! USE_FULL_LUT
186 size_t point_memsize = (sizeof(sparrow_map_path_t) * sparrow->out.pixcount / LINE_PERIOD) + 1;
187 size_t row_memsize = sizeof(sparrow_map_row_t) * sparrow->out.height + 1;
188 sparrow->map.point_mem = malloc_aligned_or_die(point_memsize);
189 sparrow->map.rows = zalloc_aligned_or_die(row_memsize);
190 #else
191 size_t lutsize = sizeof(sparrow_map_lut_t) * sparrow->out.pixcount;
192 sparrow->map_lut = zalloc_aligned_or_die(lutsize);
193 #endif
195 sparrow->timer_start.tv_sec = 0;
196 sparrow->timer_stop.tv_sec = 0;
198 rng_init(sparrow, sparrow->rng_seed);
200 if (sparrow->debug){
201 init_debug(sparrow);
204 if (sparrow->rng_seed & 1){/*XXX need better test */
205 sparrow->colour = SPARROW_GREEN;
207 else {
208 sparrow->colour = SPARROW_MAGENTA;
211 sparrow->timer_log = (sparrow->use_timer) ? fopen(TIMER_LOG_FILE, "w") : NULL;
213 if(sparrow->reload){
214 change_state(sparrow, SPARROW_FIND_EDGES);
216 else {
217 change_state(sparrow, SPARROW_NEXT_STATE);
219 return TRUE;
222 void INVISIBLE
223 sparrow_finalise(GstSparrow *sparrow)
225 free(sparrow->dsfmt);
226 free(sparrow->screenmask);
227 #if ! USE_FULL_LUT
228 free(sparrow->map.point_mem);
229 free(sparrow->map.rows);
230 #else
231 free(sparrow->map_lut);
232 #endif
235 if (sparrow->timer_log){
236 fclose(sparrow->timer_log);
238 //free everything
239 //cvReleaseImageHeader(IplImage** image)
243 /* initialisation functions and sparrow_transform() use this to set up a new
244 state. */
245 static void
246 change_state(GstSparrow *sparrow, sparrow_state state)
248 GST_DEBUG("state is %d, sparrow->state is %d\n", state, sparrow->state);
249 switch(sparrow->state){
250 case SPARROW_FIND_SELF:
251 finalise_find_self(sparrow);
252 break;
253 case SPARROW_FIND_SCREEN:
254 finalise_find_screen(sparrow);
255 break;
256 case SPARROW_FIND_EDGES:
257 finalise_find_edges(sparrow);
258 break;
259 case SPARROW_PLAY:
260 finalise_play(sparrow);
261 break;
262 case SPARROW_INIT:
263 break;
264 default:
265 GST_DEBUG("change_state got unknown state: %d\n", state);
267 if (state == SPARROW_NEXT_STATE){
268 state = sparrow->state + 1;
270 switch(state){
271 case SPARROW_FIND_SELF:
272 init_find_self(sparrow);
273 break;
274 case SPARROW_FIND_SCREEN:
275 init_find_screen(sparrow);
276 break;
277 case SPARROW_FIND_EDGES:
278 init_find_edges(sparrow);
279 break;
280 case SPARROW_PLAY:
281 init_play(sparrow);
282 break;
283 case SPARROW_INIT:
284 //init_init(sparrow);
285 break;
286 default:
287 GST_DEBUG("change_state got unknown state: %d\n", state);
289 sparrow->state = state;
293 /*called by gst_sparrow_transform_ip every frame.
295 decide what to do based on sparrow->state. All the processing is done in a
296 "mode_*" function, which returns a state or SPARROW_STATUS_QUO. If a state
297 is returned, then change_state() is called to initialise the state, even if
298 it is the current state (so states can use this to reset).
300 void INVISIBLE
301 sparrow_transform(GstSparrow *sparrow, guint8 *in, guint8 *out)
303 sparrow_state new_state;
304 #if TIME_TRANSFORM
305 TIMER_START(sparrow);
306 #endif
307 //GST_DEBUG("in %p, out %p\n", in, out);
308 switch(sparrow->state){
309 case SPARROW_FIND_SELF:
310 new_state = mode_find_self(sparrow, in, out);
311 break;
312 case SPARROW_FIND_SCREEN:
313 new_state = mode_find_screen(sparrow, in, out);
314 break;
315 case SPARROW_FIND_EDGES:
316 new_state = mode_find_edges(sparrow, in, out);
317 break;
318 case SPARROW_PLAY:
319 new_state = mode_play(sparrow, in, out);
320 break;
321 default:
322 GST_DEBUG("unknown state:%d\n", sparrow->state);
323 new_state = SPARROW_STATUS_QUO;
325 sparrow->frame_count++;
326 if (new_state != SPARROW_STATUS_QUO){
327 change_state(sparrow, new_state);
329 #if TIME_TRANSFORM
330 TIMER_STOP(sparrow);
331 #endif