attempt at prefetch for play:generally unnoticable
[sparrow.git] / play.c
blob9f7472d91dfdfcdbb2b9d1ddf60f69e44a114085
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 #define DEBUG_PLAY 0
26 #define INITIAL_BLACK 32
27 #define MIN_BLACK 0
28 #define MAX_BLACK 160
31 typedef struct sparrow_play_s{
32 guint8 lut[256];
33 guint8 *image_row;
34 guint8 black_level;
35 guint jpeg_index;
36 } sparrow_play_t;
39 static inline guint8
40 negate(sparrow_play_t *player, guint8 in){
41 return player->lut[in];
44 static void set_up_jpeg(GstSparrow *sparrow, sparrow_play_t *player){
45 /*XXX pick a jpeg, somehow*/
46 sparrow_frame_t *frame = &sparrow->shared->index[player->jpeg_index];
47 GST_DEBUG("set up jpeg shared->index is %p, offset %d, frame %p\n",
48 sparrow->shared->index, player->jpeg_index, frame);
49 guint8 *src = sparrow->shared->jpeg_blob + frame->offset;
51 guint size = frame->jpeg_size;
52 GST_DEBUG("blob is %p, offset %d, src %p, size %d\n",
53 sparrow->shared->jpeg_blob, frame->offset, src, size);
55 begin_reading_jpeg(sparrow, src, size);
56 player->jpeg_index++;
57 if (player->jpeg_index == sparrow->shared->image_count){
58 player->jpeg_index = 0;
63 static inline guint8 one_subpixel(sparrow_play_t *player, guint8 inpix, guint8 jpegpix){
64 /* simplest possible */
65 guint sum = player->lut[inpix] + jpegpix;
66 //int diff = jpegpix - inpix;
69 return sum >> 1;
70 //return jpegpix;
73 static inline void
74 do_one_pixel(GstSparrow *sparrow, guint8 *outpix, guint8 *inpix, guint8 *jpegpix){
75 /* rather than cancel the whole other one, we need to calculate the
76 difference from the desired image, and only compensate by that
77 amount. If a lot of negative compensation (i.e, trying to blacken)
78 is needed, then it is time to raise the black level for the next
79 round (otherwise, lower the black level). Use sum of
80 compensations?, or count? or thresholded? or squared (via LUT)?
82 How are relative calculations calculated via LUT?
84 1. pre scale
85 2. combine
86 3. re scale
89 sparrow_play_t *player = sparrow->helper_struct;
90 //guint8 black = player->black_level;
92 int r = ib[sparrow->in.rbyte];
93 int g = ib[sparrow->in.gbyte];
94 int b = ib[sparrow->in.bbyte];
96 //outpix[0] = player->lut[inpix[0]];
97 //outpix[1] = player->lut[inpix[1]];
98 //outpix[2] = player->lut[inpix[2]];
99 //outpix[3] = player->lut[inpix[3]];
100 outpix[0] = one_subpixel(player, inpix[0], jpegpix[0]);
101 outpix[1] = one_subpixel(player, inpix[1], jpegpix[1]);
102 outpix[2] = one_subpixel(player, inpix[2], jpegpix[2]);
103 outpix[3] = one_subpixel(player, inpix[3], jpegpix[3]);
107 static void
108 play_from_full_lut(GstSparrow *sparrow, guint8 *in, guint8 *out){
109 GST_DEBUG("play_from_full_lut\n");
110 #if 0
111 memset(out, 0, sparrow->out.size); /*is this necessary? (only for outside
112 screen map, maybe in-loop might be
113 quicker) */
114 #endif
115 sparrow_play_t *player = sparrow->helper_struct;
116 guint i;
117 int ox, oy;
118 guint32 *out32 = (guint32 *)out;
119 guint32 *in32 = (guint32 *)in;
120 set_up_jpeg(sparrow, player);
121 GST_DEBUG("in %p out %p", in, out);
123 guint8 *jpeg_row = player->image_row;
124 int *prefetch = sparrow->in_prefetch;
125 i = 0;
127 for (oy = 0; oy < sparrow->out.height; oy++){
128 /*prefetch the points y increases or deceeases */
129 for (int j = 0; j < CACHE_PREFETCH_PER_ROW; j++){
130 if (! prefetch[j])
131 break;
132 __builtin_prefetch(in + prefetch[j], 0, 3);
134 prefetch += CACHE_PREFETCH_PER_ROW;
136 read_one_line(sparrow, jpeg_row);
137 for (ox = 0; ox < sparrow->out.width; ox++, i++){
138 int x = sparrow->map_lut[i].x;
139 int y = sparrow->map_lut[i].y;
140 if (x || y){
141 guint8 *inpix = (guint8*)&in32[y * sparrow->in.width + x];
142 do_one_pixel(sparrow,
143 &out[i * PIXSIZE],
144 inpix,
145 &jpeg_row[ox * PIXSIZE]);
147 else {
148 out32[i] = 0;
152 finish_reading_jpeg(sparrow);
154 if (DEBUG_PLAY && sparrow->debug){
155 debug_frame(sparrow, out, sparrow->out.width, sparrow->out.height, PIXSIZE);
160 INVISIBLE sparrow_state
161 mode_play(GstSparrow *sparrow, guint8 *in, guint8 *out){
162 play_from_full_lut(sparrow, in, out);
163 return SPARROW_STATUS_QUO;
166 static const double GAMMA = 1.5;
167 static const double INV_GAMMA = 1.0 / 1.5;
168 static const double FALSE_CEILING = 275;
170 static void
171 init_gamma_lut(sparrow_play_t *player){
172 for (int i = 0; i < 256; i++){
173 /* for each colour:
174 1. perform inverse gamma calculation (-> linear colour space)
175 2. negate
176 3 undo gamma.
178 double x;
179 x = i / 255.01;
180 x = 1 - pow(x, INV_GAMMA);
181 x = pow(x, GAMMA) * FALSE_CEILING;
182 if (x > 255){
183 x = 255;
185 player->lut[i] = (guint8)x;
189 INVISIBLE void init_play(GstSparrow *sparrow){
190 GST_DEBUG("starting play mode\n");
191 init_jpeg_src(sparrow);
192 sparrow_play_t *player = zalloc_aligned_or_die(sizeof(sparrow_play_t));
193 player->image_row = zalloc_aligned_or_die(sparrow->out.width * PIXSIZE);
194 player->black_level = INITIAL_BLACK;
195 sparrow->helper_struct = player;
196 init_gamma_lut(player);
197 GST_DEBUG("finished init_play\n");
200 INVISIBLE void finalise_play(GstSparrow *sparrow){
201 GST_DEBUG("leaving play mode\n");