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.
20 #include "gstsparrow.h"
26 #define INITIAL_BLACK 32
31 typedef struct sparrow_play_s
{
40 negate(sparrow_play_t
*player
, guint8 in
){
41 return player
->lut
[in
];
45 play_from_lut(GstSparrow
*sparrow
, guint8
*in
, guint8
*out
){
46 sparrow_map_t
*map
= &sparrow
->map
;
47 memset(out
, 0, sparrow
->out
.size
);
49 guint32
*line
= (guint32
*)out
;
50 for (y
= 0; y
< sparrow
->out
.height
; y
++){
51 sparrow_map_row_t
*row
= map
->rows
+ y
;
52 for(x
= row
->start
; x
< row
->end
; x
++){
56 GST_DEBUG("row %p %d: s %d e%d line %d\n",
57 row, y, row->start, row->end, line);
59 line
+= sparrow
->out
.width
;
63 static void set_up_jpeg(GstSparrow
*sparrow
, sparrow_play_t
*player
){
64 /*XXX pick a jpeg, somehow*/
65 sparrow_frame_t
*frame
= &sparrow
->shared
->index
[player
->jpeg_index
];
66 GST_DEBUG("set up jpeg shared->index is %p, offset %d, frame %p\n",
67 sparrow
->shared
->index
, player
->jpeg_index
, frame
);
68 guint8
*src
= sparrow
->shared
->jpeg_blob
+ frame
->offset
;
70 guint size
= frame
->jpeg_size
;
71 GST_DEBUG("blob is %p, offset %d, src %p, size %d\n",
72 sparrow
->shared
->jpeg_blob
, frame
->offset
, src
, size
);
74 begin_reading_jpeg(sparrow
, src
, size
);
76 if (player
->jpeg_index
== sparrow
->shared
->image_count
){
77 player
->jpeg_index
= 0;
82 static inline guint8
one_subpixel(sparrow_play_t
*player
, guint8 inpix
, guint8 jpegpix
){
83 /* simplest possible */
84 guint sum
= player
->lut
[inpix
] + jpegpix
;
85 //int diff = jpegpix - inpix;
93 do_one_pixel(GstSparrow
*sparrow
, guint8
*outpix
, guint8
*inpix
, guint8
*jpegpix
){
94 /* rather than cancel the whole other one, we need to calculate the
95 difference from the desired image, and only compensate by that
96 amount. If a lot of negative compensation (i.e, trying to blacken)
97 is needed, then it is time to raise the black level for the next
98 round (otherwise, lower the black level). Use sum of
99 compensations?, or count? or thresholded? or squared (via LUT)?
101 How are relative calculations calculated via LUT?
108 sparrow_play_t
*player
= sparrow
->helper_struct
;
109 //guint8 black = player->black_level;
111 int r = ib[sparrow->in.rbyte];
112 int g = ib[sparrow->in.gbyte];
113 int b = ib[sparrow->in.bbyte];
115 //outpix[0] = player->lut[inpix[0]];
116 //outpix[1] = player->lut[inpix[1]];
117 //outpix[2] = player->lut[inpix[2]];
118 //outpix[3] = player->lut[inpix[3]];
119 outpix
[0] = one_subpixel(player
, inpix
[0], jpegpix
[0]);
120 outpix
[1] = one_subpixel(player
, inpix
[1], jpegpix
[1]);
121 outpix
[2] = one_subpixel(player
, inpix
[2], jpegpix
[2]);
122 outpix
[3] = one_subpixel(player
, inpix
[3], jpegpix
[3]);
125 static inline guint8
* get_in_pixel(GstSparrow
*sparrow
, guint32
*in32
, int x
, int y
){
126 return (guint8
*)&in32
[y
* sparrow
->in
.width
+ x
];
130 play_from_full_lut(GstSparrow
*sparrow
, guint8
*in
, guint8
*out
){
131 GST_DEBUG("play_from_full_lut\n");
132 memset(out
, 0, sparrow
->out
.size
); /*is this necessary? (only for outside
133 screen map, maybe in-loop might be
135 sparrow_play_t
*player
= sparrow
->helper_struct
;
138 //guint32 *out32 = (guint32 *)out;
139 guint32
*in32
= (guint32
*)in
;
140 set_up_jpeg(sparrow
, player
);
141 GST_DEBUG("in %p out %p", in
, out
);
143 guint8
*jpeg_row
= player
->image_row
;
145 for (oy
= 0; oy
< sparrow
->out
.height
; oy
++){
146 //GST_DEBUG("about to read line to %p", player->image_row);
147 read_one_line(sparrow
, player
->image_row
);
148 for (ox
= 0; ox
< sparrow
->out
.width
; ox
++, i
++){
149 int x
= sparrow
->map_lut
[i
].x
;
150 int y
= sparrow
->map_lut
[i
].y
;
152 //GST_DEBUG("in %p x %d y %d", in, x, y);
153 guint8
*inpix
= get_in_pixel(sparrow
, in32
, x
, y
);
154 do_one_pixel(sparrow
,
157 &jpeg_row
[ox
* PIXSIZE
]);
161 finish_reading_jpeg(sparrow
);
163 if (DEBUG_PLAY
&& sparrow
->debug
){
164 debug_frame(sparrow
, out
, sparrow
->out
.width
, sparrow
->out
.height
, PIXSIZE
);
170 INVISIBLE sparrow_state
171 mode_play(GstSparrow
*sparrow
, guint8
*in
, guint8
*out
){
172 //do actual stuff here
173 //memcpy(out, in, sparrow->out.size);
174 //simple_negation(out, sparrow->out.size);
175 if (sparrow
->countdown
){
176 memset(out
, 0, sparrow
->out
.size
);
177 sparrow
->countdown
--;
181 play_from_full_lut(sparrow
, in
, out
);
183 play_from_lut(sparrow
, in
, out
);
186 return SPARROW_STATUS_QUO
;
189 static const double GAMMA
= 1.5;
190 static const double INV_GAMMA
= 1.0 / 1.5;
191 static const double FALSE_CEILING
= 275;
194 init_gamma_lut(sparrow_play_t
*player
){
195 for (int i
= 0; i
< 256; i
++){
197 1. perform inverse gamma calculation (-> linear colour space)
203 x
= 1 - pow(x
, INV_GAMMA
);
204 x
= pow(x
, GAMMA
) * FALSE_CEILING
;
208 player
->lut
[i
] = (guint8
)x
;
213 INVISIBLE
void init_play(GstSparrow
*sparrow
){
214 GST_DEBUG("starting play mode\n");
215 init_jpeg_src(sparrow
);
216 sparrow_play_t
*player
= zalloc_aligned_or_die(sizeof(sparrow_play_t
));
217 player
->image_row
= zalloc_aligned_or_die(sparrow
->out
.width
* PIXSIZE
);
218 player
->black_level
= INITIAL_BLACK
;
219 sparrow
->helper_struct
= player
;
220 init_gamma_lut(player
);
221 sparrow
->countdown
= 100;
222 GST_DEBUG("finished init_play\n");
225 INVISIBLE
void finalise_play(GstSparrow
*sparrow
){
226 GST_DEBUG("leaving play mode\n");