smoothen video processing line a little
[sparrow.git] / play.c
blob980b9167865419eaf4e5a74214cb28cc77b27e72
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_clamp
28 static inline void
29 do_one_pixel(sparrow_play_t *player, guint8 *outpix, guint8 *inpix, guint8 *jpegpix,
30 guint8 *oldframe){
31 outpix[0] = one_subpixel(player, inpix[0], jpegpix[0], oldframe[0]);
32 outpix[1] = one_subpixel(player, inpix[1], jpegpix[1], oldframe[1]);
33 outpix[2] = one_subpixel(player, inpix[2], jpegpix[2], oldframe[2]);
34 outpix[3] = one_subpixel(player, inpix[3], jpegpix[3], oldframe[3]);
38 static void
39 set_up_jpeg(GstSparrow *sparrow, sparrow_play_t *player){
40 /*XXX pick a jpeg, somehow*/
41 /*first, chance of random jump anywhere. */
42 if (rng_uniform(sparrow) < 1.0 / 500){
43 player->jpeg_index = RANDINT(sparrow, 0, sparrow->shared->image_count);
44 GST_DEBUG("CHANGE_SHOT: random jump: %d to %d", player->jpeg_index, player->jpeg_index);
46 else {
47 sparrow_frame_t *old_frame = &sparrow->shared->index[player->jpeg_index];
48 int next = old_frame->successors[0];
49 if (!next){
50 int i = RANDINT(sparrow, 1, 8);
51 next = old_frame->successors[i];
52 GST_DEBUG("CHANGE_SHOT: %d to %d (option %d)", player->jpeg_index, next, i);
54 player->jpeg_index = next;
57 sparrow_frame_t *frame = &sparrow->shared->index[player->jpeg_index];
58 guint8 *src = sparrow->shared->jpeg_blob + frame->offset;
59 guint size = frame->jpeg_size;
60 GST_DEBUG("blob is %p, offset %d, src %p, size %d\n",
61 sparrow->shared->jpeg_blob, frame->offset, src, size);
63 begin_reading_jpeg(sparrow, src, size);
67 static void
68 play_from_full_lut(GstSparrow *sparrow, guint8 *in, guint8 *out){
69 sparrow_play_t *player = sparrow->helper_struct;
70 guint i;
71 int ox, oy;
72 guint32 *out32 = (guint32 *)out;
73 guint32 *in32 = (guint32 *)in;
74 GstBuffer *oldbuf = player->old_frames[player->old_frames_tail];
75 guint8 *old_frame = (oldbuf) ? (guint8 *)GST_BUFFER_DATA(oldbuf) : out;
77 set_up_jpeg(sparrow, player);
79 guint8 *jpeg_row = player->image_row;
80 i = 0;
81 for (oy = 0; oy < sparrow->out.height; oy++){
82 read_one_line(sparrow, jpeg_row);
83 for (ox = 0; ox < sparrow->out.width; ox++, i++){
84 guint inpos = sparrow->map_lut[i];
85 if (inpos){
86 do_one_pixel(player,
87 &out[i * PIXSIZE],
88 (guint8 *)&in32[inpos],
89 &jpeg_row[ox * PIXSIZE],
90 &old_frame[i * PIXSIZE]
93 else {
94 out32[i] = 0;
98 finish_reading_jpeg(sparrow);
100 if (DEBUG_PLAY && sparrow->debug){
101 debug_frame(sparrow, out, sparrow->out.width, sparrow->out.height, PIXSIZE);
105 static void
106 store_old_frame(GstSparrow *sparrow, GstBuffer *outbuf){
107 sparrow_play_t *player = sparrow->helper_struct;
108 player->old_frames[player->old_frames_head] = outbuf;
109 gst_buffer_ref(outbuf);
110 player->old_frames_head++;
111 player->old_frames_head %= OLD_FRAMES;
114 static void
115 drop_old_frame(GstSparrow *sparrow, GstBuffer *outbuf){
116 sparrow_play_t *player = sparrow->helper_struct;
117 GstBuffer *tail = player->old_frames[player->old_frames_tail];
118 if (tail){
119 gst_buffer_unref(tail);
121 player->old_frames_tail++;
122 player->old_frames_tail %= OLD_FRAMES;
126 INVISIBLE sparrow_state
127 mode_play(GstSparrow *sparrow, GstBuffer *inbuf, GstBuffer *outbuf){
128 guint8 *in = GST_BUFFER_DATA(inbuf);
129 guint8 *out = GST_BUFFER_DATA(outbuf);
130 store_old_frame(sparrow, outbuf);
131 play_from_full_lut(sparrow, in, out);
132 drop_old_frame(sparrow, outbuf);
133 return SPARROW_STATUS_QUO;
136 static const double GAMMA = 2.0;
137 static const double INV_GAMMA = 1.0 / 2.0;
138 static const double FALSE_CEILING = 275;
140 static void
141 init_gamma_lut(sparrow_play_t *player){
142 for (int i = 0; i < 256; i++){
143 /* for each colour:
144 1. perform inverse gamma calculation (-> linear colour space)
145 2. negate
146 3 undo gamma.
148 double x, y;
149 x = i / 255.01;
150 y = pow(x, INV_GAMMA) *255;
151 x = pow(x, GAMMA) * 255;
152 if (x > 255){
153 x = 255;
155 if (y > 255){
156 y = 255;
158 player->lut_hi[i] = (guint8)x;
159 player->lut_lo[i] = (guint8)y;
163 INVISIBLE void init_play(GstSparrow *sparrow){
164 GST_DEBUG("starting play mode\n");
165 init_jpeg_src(sparrow);
166 sparrow_play_t *player = zalloc_aligned_or_die(sizeof(sparrow_play_t));
167 player->image_row = zalloc_aligned_or_die(sparrow->out.width * PIXSIZE);
168 player->old_frames_head = MIN(sparrow->lag, OLD_FRAMES - 1) || 1;
169 GST_INFO("using old frame lag of %d\n", player->old_frames_head);
170 sparrow->helper_struct = player;
171 init_gamma_lut(player);
172 GST_DEBUG("finished init_play\n");
175 INVISIBLE void finalise_play(GstSparrow *sparrow){
176 GST_DEBUG("leaving play mode\n");