gitignore ignorable gtksparrow executable
[sparrow.git] / play.c
blob83ac79b93bdc74771d3173857fb778ee17f1b976
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>
24 #include "play_core.h"
26 #define one_subpixel one_subpixel_gamma_clamp_oldpix
27 //#define one_subpixel one_subpixel_clamp
29 static inline void
30 do_one_pixel(sparrow_play_t *player, guint8 *outpix, guint8 *inpix, guint8 *jpegpix,
31 guint8 *oldframe){
32 outpix[0] = one_subpixel(player, inpix[0], jpegpix[0], oldframe[0]);
33 outpix[1] = one_subpixel(player, inpix[1], jpegpix[1], oldframe[1]);
34 outpix[2] = one_subpixel(player, inpix[2], jpegpix[2], oldframe[2]);
35 outpix[3] = one_subpixel(player, inpix[3], jpegpix[3], oldframe[3]);
38 static inline int
39 select_jpeg_adaptive(GstSparrow *sparrow, sparrow_play_t *player){
41 GST_DEBUG("in select_jpeg_adaptive, starting at %d", player->jpeg_index);
42 GstBuffer *oldbuf = player->old_frames[player->old_frames_tail];
43 if (! oldbuf){
44 GST_DEBUG("old buffer is not there! using random jump: %d to %d",
45 player->jpeg_index, player->jpeg_index);
46 return RANDINT(sparrow, 0, sparrow->shared->image_count);
48 guint8 *old_frame = (guint8 *)GST_BUFFER_DATA(oldbuf);
50 cvResize( const CvArr* src, CvArr* dst, CV_INTER_LINEAR)
52 int x, y;
53 guint32 summary[6 * 8 * PIXSIZE] = {0};
54 int xdiv = sparrow->out.width / 8;
55 int ydiv = sparrow->out.height / 6;
56 int y2 = 0;
57 int x2 = 0;
58 for (y2 = 0; y2 < 6; y2++){
59 for (y = y2 * ydiv; y < (y2 + 1) * ydiv; y += 4){
60 for (x2 = 0; x2 < 8; x2++){
61 for (x = x2 * xdiv; x < (x2 + 1) * xdiv; x++){
62 int i2 = y2 * 8 + x2;
63 int i = y * sparrow->out.width + x;
65 summary[i2 + ] += old_frame[];
70 for (x = 0; x < sparrow->out.width; x++){
75 GST_DEBUG("in select_jpeg_adaptive");
77 return RANDINT(sparrow, 0, sparrow->shared->image_count);
81 static void
82 set_up_jpeg(GstSparrow *sparrow, sparrow_play_t *player){
83 /*XXX pick a jpeg, somehow*/
84 /*first, chance of random jump anywhere. */
85 if (rng_uniform(sparrow) < 1.0 / 500){
86 player->jpeg_index = RANDINT(sparrow, 0, sparrow->shared->image_count);
87 GST_DEBUG("CHANGE_SHOT: random jump: %d to %d", player->jpeg_index, player->jpeg_index);
89 else {
90 sparrow_frame_t *old_frame = &sparrow->shared->index[player->jpeg_index];
91 int next = old_frame->successors[0];
92 if (!next){
93 int i = RANDINT(sparrow, 1, 8);
94 if (i < 8){
95 next = old_frame->successors[i];
96 GST_DEBUG("CHANGE_SHOT: %d to %d (option %d)", player->jpeg_index, next, i);
98 else{
99 next = select_jpeg_adaptive(sparrow, player);
102 player->jpeg_index = next;
105 sparrow_frame_t *frame = &sparrow->shared->index[player->jpeg_index];
106 guint8 *src = sparrow->shared->jpeg_blob + frame->offset;
107 guint size = frame->jpeg_size;
108 GST_DEBUG("blob is %p, offset %d, src %p, size %d\n",
109 sparrow->shared->jpeg_blob, frame->offset, src, size);
111 begin_reading_jpeg(sparrow, src, size);
114 static void
115 play_from_full_lut(GstSparrow *sparrow, guint8 *in, guint8 *out){
116 sparrow_play_t *player = sparrow->helper_struct;
117 guint i;
118 int ox, oy;
119 guint32 *out32 = (guint32 *)out;
120 guint32 *in32 = (guint32 *)in;
121 GstBuffer *oldbuf = player->old_frames[player->old_frames_tail];
122 guint8 *old_frame = (oldbuf) ? (guint8 *)GST_BUFFER_DATA(oldbuf) : out;
124 set_up_jpeg(sparrow, player);
126 guint8 *jpeg_row = player->image_row;
127 i = 0;
128 for (oy = 0; oy < sparrow->out.height; oy++){
129 read_one_line(sparrow, jpeg_row);
130 for (ox = 0; ox < sparrow->out.width; ox++, i++){
131 guint inpos = sparrow->map_lut[i];
132 if (inpos){
133 do_one_pixel(player,
134 &out[i * PIXSIZE],
135 (guint8 *)&in32[inpos],
136 &jpeg_row[ox * PIXSIZE],
137 &old_frame[i * PIXSIZE]
140 else {
141 out32[i] = 0;
145 finish_reading_jpeg(sparrow);
147 if (DEBUG_PLAY && sparrow->debug){
148 debug_frame(sparrow, out, sparrow->out.width, sparrow->out.height, PIXSIZE);
152 static void
153 store_old_frame(GstSparrow *sparrow, GstBuffer *outbuf){
154 sparrow_play_t *player = sparrow->helper_struct;
155 player->old_frames[player->old_frames_head] = outbuf;
156 gst_buffer_ref(outbuf);
157 player->old_frames_head++;
158 player->old_frames_head %= OLD_FRAMES;
161 static void
162 drop_old_frame(GstSparrow *sparrow, GstBuffer *outbuf){
163 sparrow_play_t *player = sparrow->helper_struct;
164 GstBuffer *tail = player->old_frames[player->old_frames_tail];
165 if (tail){
166 gst_buffer_unref(tail);
168 player->old_frames_tail++;
169 player->old_frames_tail %= OLD_FRAMES;
173 INVISIBLE sparrow_state
174 mode_play(GstSparrow *sparrow, GstBuffer *inbuf, GstBuffer *outbuf){
175 guint8 *in = GST_BUFFER_DATA(inbuf);
176 guint8 *out = GST_BUFFER_DATA(outbuf);
177 store_old_frame(sparrow, outbuf);
178 play_from_full_lut(sparrow, in, out);
179 drop_old_frame(sparrow, outbuf);
180 return SPARROW_STATUS_QUO;
184 static void
185 init_gamma_lut(sparrow_play_t *player){
186 /* for each colour:
187 1. perform inverse gamma calculation (-> linear colour space)
188 2. negate
189 3 undo gamma.
191 for (int i = 0; i < 256; i++){
192 double x;
193 x = (double)i / 255;
194 x = pow(x, GAMMA) * (GAMMA_UNIT_LIMIT - 1);
195 if (x >= GAMMA_UNIT_LIMIT){
196 x = GAMMA_UNIT_LIMIT - 1;
198 player->lut_f[i] = (guint16)x;
200 for (int i = GAMMA_FLOOR; i < GAMMA_UNIT_LIMIT; i++){
201 double x;
202 x = (double)i / (GAMMA_UNIT_LIMIT - GAMMA_FLOOR - 1);
203 x = pow(x, INV_GAMMA) * 255 + 0.5;
204 if (x > 255){
205 x = 255;
207 player->lut_b[i] = (guint8)x;
209 /*add some extra on the table to catch overflow -- should perhaps ramp
210 toward 255, if the top is not that high
211 XXX current implemetation doesn't use this*/
212 for (int i = GAMMA_UNIT_LIMIT; i < GAMMA_TABLE_TOP; i++){
213 player->lut_b[i] = 255;
217 INVISIBLE void init_play(GstSparrow *sparrow){
218 GST_DEBUG("starting play mode\n");
219 init_jpeg_src(sparrow);
220 sparrow_play_t *player = zalloc_aligned_or_die(sizeof(sparrow_play_t));
221 player->image_row = zalloc_aligned_or_die(sparrow->out.width * PIXSIZE);
222 player->old_frames_head = MIN(sparrow->lag, OLD_FRAMES - 1) || 1;
223 GST_INFO("using old frame lag of %d\n", player->old_frames_head);
224 sparrow->helper_struct = player;
225 init_gamma_lut(player);
226 GST_DEBUG("finished init_play\n");
229 INVISIBLE void finalise_play(GstSparrow *sparrow){
230 GST_DEBUG("leaving play mode\n");