rearranging things for clarity
[sparrow.git] / sparrow.c
blobea7d5a401dbb62b6a49a7e29ee4db3184b1eb3ee
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`) */
28 /* set up whatever debugging methods are enabled */
29 static void
30 init_debug(GstSparrow *sparrow){
31 if (!sparrow->debug_frame){
32 sparrow->debug_frame = malloc_aligned_or_die(MAX(sparrow->in.size, sparrow->out.size));
36 /*RNG code */
37 /*seed with -1 for automatic seed choice */
38 static void rng_init(GstSparrow *sparrow, guint32 seed){
39 GST_DEBUG("in RNG init\n");
40 if (seed == (guint32)-1){
41 /* XXX should really use /dev/urandom */
42 seed = rand();
43 GST_DEBUG("Real seed %u\n", seed);
45 if (seed == 0)
46 seed = 12345;
48 dsfmt_init_gen_rand(sparrow->dsfmt, seed);
49 dsfmt_gen_rand_all(sparrow->dsfmt);
50 GST_DEBUG("RNG seeded with %u\n", seed);
53 /** debugging: write frames out somewhere. **/
55 /*spit out the frame as a ppm image */
56 static void
57 ppm_dump(sparrow_format *rgb, guint8 *data, guint32 width, guint32 height, char *name)
59 guint i;
60 FILE *fh = fopen(name, "w");
61 guint32 size = width * height;
62 fprintf(fh, "P6\n%u %u\n255\n", width, height);
63 /* 4 cases: xBGR xRGB BGRx RGBx
64 need to convert to 24bit R G B
65 XX maybe could optimise some cases?
67 guint32 *p = (guint32 *)data;
68 for (i = 0; i < size; i++){
69 putc((*p >> rgb->rshift) & 255, fh);
70 putc((*p >> rgb->gshift) & 255, fh);
71 putc((*p >> rgb->bshift) & 255, fh);
72 p++;
74 fflush(fh);
75 fclose(fh);
79 #define PPM_FILENAME_TEMPLATE "/tmp/sparrow_%05d.ppm"
80 #define PPM_FILENAME_LENGTH (sizeof(PPM_FILENAME_TEMPLATE) + 10)
82 void INVISIBLE
83 debug_frame(GstSparrow *sparrow, guint8 *data, guint32 width, guint32 height){
84 #if SPARROW_PPM_DEBUG
85 char name[PPM_FILENAME_LENGTH];
86 int res = snprintf(name, PPM_FILENAME_LENGTH, PPM_FILENAME_TEMPLATE, sparrow->frame_count);
87 if (res > 0){
88 ppm_dump(&(sparrow->in), data, width, height, name);
90 #endif
93 /** interpret gst attributes **/
95 /* Extract a colour (R,G,B) bitmask from gobject */
96 static guint32 get_mask(GstStructure *s, char *mask_name){
97 gint32 mask;
98 int res = gst_structure_get_int(s, mask_name, &mask);
99 if (!res){
100 GST_WARNING("No mask for '%s' !\n", mask_name);
102 return (guint32)mask;
105 static void
106 extract_caps(sparrow_format *im, GstCaps *caps)
108 GstStructure *s = gst_caps_get_structure (caps, 0);
109 gst_structure_get_int(s, "width", &(im->width));
110 gst_structure_get_int(s, "height", &(im->height));
111 im->rmask = get_mask(s, "red_mask");
112 im->rshift = mask_to_shift(im->rmask);
113 im->gmask = get_mask(s, "green_mask");
114 im->gshift = mask_to_shift(im->gmask);
115 im->bmask = get_mask(s, "blue_mask");
116 im->bshift = mask_to_shift(im->bmask);
118 im->pixcount = im->width * im->height;
119 im->size = im->pixcount * PIXSIZE;
121 GST_DEBUG("\ncaps:\n%" GST_PTR_FORMAT, caps);
122 GST_DEBUG("shifts: r %u g %u b %u\n", im->rshift, im->gshift, im->bshift);
123 GST_DEBUG("dimensions: w %u h %u pix %u size %u\n", im->width, im->height,
124 im->pixcount, im->size);
129 /*Functions below here are called from gstsparrow.c and are NOT static */
131 void INVISIBLE
132 sparrow_rotate_history(GstSparrow *sparrow, GstBuffer *inbuf){
133 if (sparrow->in_buffer){
134 gst_buffer_unref(sparrow->prev_buffer);
135 sparrow->prev_buffer = sparrow->in_buffer;
136 sparrow->prev_frame = sparrow->in_frame;
138 gst_buffer_ref(inbuf);
139 sparrow->in_buffer = inbuf;
141 sparrow->in_frame = GST_BUFFER_DATA(inbuf);
144 /* called by gst_sparrow_init() */
145 void INVISIBLE
146 sparrow_pre_init(GstSparrow *sparrow){
149 /* called by gst_sparrow_set_caps() */
150 gboolean INVISIBLE
151 sparrow_init(GstSparrow *sparrow, GstCaps *incaps, GstCaps *outcaps){
152 extract_caps(&(sparrow->in), incaps);
153 extract_caps(&(sparrow->out), outcaps);
154 sparrow_format *in = &(sparrow->in);
156 GST_DEBUG("allocating %u * %u for lag_table\n", in->pixcount, sizeof(lag_times_t));
157 sparrow->lag_table = zalloc_aligned_or_die(in->pixcount * sizeof(lag_times_t));
158 sparrow->work_frame = zalloc_aligned_or_die(in->size);
159 sparrow->dsfmt = zalloc_aligned_or_die(sizeof(dsfmt_t));
161 sparrow->prev_buffer = gst_buffer_new_and_alloc(in->size);
162 sparrow->prev_frame = GST_BUFFER_DATA(sparrow->prev_buffer);
163 memset(sparrow->prev_frame, 0, in->size);
165 /*initialise IPL structs for openCV */
166 for (int i = 0; i < 3; i++){
167 sparrow->in_ipl[i] = init_ipl_image(&(sparrow->in));
170 rng_init(sparrow, sparrow->rng_seed);
172 if (sparrow->debug){
173 init_debug(sparrow);
176 change_state(sparrow, SPARROW_FIND_SELF);
177 return TRUE;
180 void
181 INVISIBLE
182 sparrow_finalise(GstSparrow *sparrow)
184 //free everything
186 //cvReleaseImageHeader(IplImage** image)
190 /*when a state is done, it calls back here and names its preferred
191 successor */
192 void INVISIBLE
193 change_state(GstSparrow *sparrow, sparrow_state state)
195 switch(state){
196 case SPARROW_FIND_SELF:
197 reset_find_self(sparrow, 1);
198 break;
199 case SPARROW_FIND_EDGES:
200 init_find_edges(sparrow);
201 break;
202 case SPARROW_WAIT_FOR_GRID:
203 break;
204 case SPARROW_FIND_GRID:
205 calibrate_init_grid(sparrow);
206 break;
207 case SPARROW_INIT:
208 case SPARROW_PLAY:
209 break;
211 sparrow->state = state;
216 /*called by gst_sparrow_transform_ip */
217 void INVISIBLE
218 sparrow_transform(GstSparrow *sparrow, guint8 *in, guint8 *out)
220 switch(sparrow->state){
221 case SPARROW_FIND_SELF:
222 find_self(sparrow, in, out);
223 break;
224 case SPARROW_WAIT_FOR_GRID:
225 if (wait_for_blank(sparrow, in, out)){
226 change_state(sparrow, SPARROW_FIND_EDGES);
228 break;
229 case SPARROW_FIND_EDGES:
230 find_edges(sparrow, in, out);
231 break;
232 default:
233 gamma_negation(sparrow, in, out);
235 sparrow->frame_count++;