1 /*
2 * dfiasco.c: Decoder public interface
3 *
4 * Written by: Ullrich Hafner
5 *
6 * This file is part of FIASCO (Fractal Image And Sequence COdec)
7 * Copyright (C) 1994-2000 Ullrich Hafner
8 */
9
10 /*
11 * $Date: 2000/10/28 17:39:30 $
12 * $Author: hafner $
13 * $Revision: 5.7 $
14 * $State: Exp $
15 */
16
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include "pm_c_util.h"
21 #include "nstring.h"
22
23 #include "config.h"
24
25 #include "types.h"
26 #include "macros.h"
27 #include "error.h"
28
29 #include "dfiasco.h"
30 #include "wfa.h"
31 #include "read.h"
32 #include "misc.h"
33 #include "bit-io.h"
34 #include "decoder.h"
35 #include "options.h"
36 #include "wfalib.h"
37
38 /*****************************************************************************
39
40 prototypes
41
42 *****************************************************************************/
43
44 static dfiasco_t *
45 cast_dfiasco (fiasco_decoder_t *dfiasco);
46 static void
47 free_dfiasco (dfiasco_t *dfiasco);
48 static dfiasco_t *
49 alloc_dfiasco (wfa_t *wfa, video_t *video, bitfile_t *input,
50 int enlarge_factor, int smoothing, format_e image_format);
51
52 /*****************************************************************************
53
54 public code
55
56 *****************************************************************************/
57
58 fiasco_decoder_t *
fiasco_decoder_new(const char * filename,const fiasco_d_options_t * options)59 fiasco_decoder_new (const char *filename, const fiasco_d_options_t *options)
60 {
61 try
62 {
63 bitfile_t *input; /* pointer to WFA FIASCO stream */
64 wfa_t *wfa; /* wfa structure */
65 video_t *video; /* information about decoder state */
66 const d_options_t *dop; /* decoder additional options */
67 dfiasco_t *dfiasco; /* decoder internal state */
68 fiasco_decoder_t *decoder; /* public interface to decoder */
69 fiasco_d_options_t *default_options = NULL;
70
71 if (options)
72 {
73 dop = cast_d_options ((fiasco_d_options_t *) options);
74 if (!dop)
75 return NULL;
76 }
77 else
78 {
79 default_options = fiasco_d_options_new ();
80 dop = cast_d_options (default_options);
81 }
82
83 wfa = alloc_wfa (NO);
84 video = alloc_video (NO);
85 input = open_wfa (filename, wfa->wfainfo);
86 read_basis (wfa->wfainfo->basis_name, wfa);
87
88 decoder = Calloc (1, sizeof (fiasco_decoder_t));
89 decoder->delete = fiasco_decoder_delete;
90 decoder->write_frame = fiasco_decoder_write_frame;
91 decoder->get_frame = fiasco_decoder_get_frame;
92 decoder->get_length = fiasco_decoder_get_length;
93 decoder->get_rate = fiasco_decoder_get_rate;
94 decoder->get_width = fiasco_decoder_get_width;
95 decoder->get_height = fiasco_decoder_get_height;
96 decoder->get_title = fiasco_decoder_get_title;
97 decoder->get_comment = fiasco_decoder_get_comment;
98 decoder->is_color = fiasco_decoder_is_color;
99
100 decoder->private = dfiasco
101 = alloc_dfiasco (wfa, video, input,
102 dop->magnification,
103 dop->smoothing,
104 dop->image_format);
105
106 if (default_options)
107 fiasco_d_options_delete (default_options);
108 if (dfiasco->enlarge_factor >= 0)
109 {
110 int n;
111 unsigned long pixels = wfa->wfainfo->width * wfa->wfainfo->height;
112
113 for (n = 1; n <= (int) dfiasco->enlarge_factor; n++)
114 {
115 if (pixels << (n << 1) > 2048 * 2048)
116 {
117 set_error (_("Magnifaction factor `%d' is too large. "
118 "Maximum value is %d."),
119 dfiasco->enlarge_factor, MAX(0, n - 1));
120 fiasco_decoder_delete (decoder);
121 return NULL;
122 }
123 }
124 }
125 else
126 {
127 int n;
128
129 for (n = 0; n <= (int) - dfiasco->enlarge_factor; n++)
130 {
131 if (wfa->wfainfo->width >> n < 32
132 || wfa->wfainfo->height >> n < 32)
133 {
134 set_error (_("Magnifaction factor `%d' is too small. "
135 "Minimum value is %d."),
136 dfiasco->enlarge_factor, - MAX(0, n - 1));
137 fiasco_decoder_delete (decoder);
138 return NULL;
139 }
140 }
141 }
142 return (fiasco_decoder_t *) decoder;
143 }
144 catch
145 {
146 return NULL;
147 }
148 }
149
150 int
fiasco_decoder_write_frame(fiasco_decoder_t * decoder,const char * filename)151 fiasco_decoder_write_frame (fiasco_decoder_t *decoder,
152 const char *filename)
153 {
154 dfiasco_t *dfiasco = cast_dfiasco (decoder);
155
156 if (!dfiasco)
157 return 0;
158 else
159 {
160 try
161 {
162 image_t *frame = get_next_frame (NO, dfiasco->enlarge_factor,
163 dfiasco->smoothing, NULL,
164 FORMAT_4_4_4, dfiasco->video, NULL,
165 dfiasco->wfa, dfiasco->input);
166 write_image (filename, frame);
167 }
168 catch
169 {
170 return 0;
171 }
172 return 1;
173 }
174 }
175
176 fiasco_image_t *
fiasco_decoder_get_frame(fiasco_decoder_t * decoder)177 fiasco_decoder_get_frame (fiasco_decoder_t *decoder)
178 {
179 dfiasco_t *dfiasco = cast_dfiasco (decoder);
180
181 if (!dfiasco)
182 return NULL;
183 else
184 {
185 try
186 {
187 fiasco_image_t *image = Calloc (1, sizeof (fiasco_image_t));
188 image_t *frame = get_next_frame (NO, dfiasco->enlarge_factor,
189 dfiasco->smoothing, NULL,
190 dfiasco->image_format,
191 dfiasco->video, NULL,
192 dfiasco->wfa, dfiasco->input);
193
194 frame->reference_count++; /* for motion compensation */
195 image->private = frame;
196 image->delete = fiasco_image_delete;
197 image->get_width = fiasco_image_get_width;
198 image->get_height = fiasco_image_get_height;
199 image->is_color = fiasco_image_is_color;
200
201 return image;
202 }
203 catch
204 {
205 return NULL;
206 }
207 }
208 }
209
210 unsigned
fiasco_decoder_get_length(fiasco_decoder_t * decoder)211 fiasco_decoder_get_length (fiasco_decoder_t *decoder)
212 {
213 dfiasco_t *dfiasco = cast_dfiasco (decoder);
214
215 if (!dfiasco)
216 return 0;
217 else
218 return dfiasco->wfa->wfainfo->frames;
219 }
220
221 unsigned
fiasco_decoder_get_rate(fiasco_decoder_t * decoder)222 fiasco_decoder_get_rate (fiasco_decoder_t *decoder)
223 {
224 dfiasco_t *dfiasco = cast_dfiasco (decoder);
225
226 if (!dfiasco)
227 return 0;
228 else
229 return dfiasco->wfa->wfainfo->fps;
230 }
231
232 unsigned
fiasco_decoder_get_width(fiasco_decoder_t * decoder)233 fiasco_decoder_get_width (fiasco_decoder_t *decoder)
234 {
235 dfiasco_t *dfiasco = cast_dfiasco (decoder);
236
237 if (!dfiasco)
238 return 0;
239 else
240 {
241 unsigned width;
242
243 if (dfiasco->enlarge_factor >= 0)
244 width = dfiasco->wfa->wfainfo->width << dfiasco->enlarge_factor;
245 else
246 width = dfiasco->wfa->wfainfo->width >> - dfiasco->enlarge_factor;
247
248 return width & 1 ? width + 1 : width;
249 }
250 }
251
252 unsigned
fiasco_decoder_get_height(fiasco_decoder_t * decoder)253 fiasco_decoder_get_height (fiasco_decoder_t *decoder)
254 {
255 dfiasco_t *dfiasco = cast_dfiasco (decoder);
256
257 if (!dfiasco)
258 return 0;
259 else
260 {
261 unsigned height;
262
263 if (dfiasco->enlarge_factor >= 0)
264 height = dfiasco->wfa->wfainfo->height << dfiasco->enlarge_factor;
265 else
266 height = dfiasco->wfa->wfainfo->height >> - dfiasco->enlarge_factor;
267
268 return height & 1 ? height + 1 : height;
269 }
270 }
271
272 const char *
fiasco_decoder_get_title(fiasco_decoder_t * decoder)273 fiasco_decoder_get_title (fiasco_decoder_t *decoder)
274 {
275 dfiasco_t *dfiasco = cast_dfiasco (decoder);
276
277 if (!dfiasco)
278 return NULL;
279 else
280 return dfiasco->wfa->wfainfo->title;
281 }
282
283 const char *
fiasco_decoder_get_comment(fiasco_decoder_t * decoder)284 fiasco_decoder_get_comment (fiasco_decoder_t *decoder)
285 {
286 dfiasco_t *dfiasco = cast_dfiasco (decoder);
287
288 if (!dfiasco)
289 return NULL;
290 else
291 return dfiasco->wfa->wfainfo->comment;
292 }
293
294 int
fiasco_decoder_is_color(fiasco_decoder_t * decoder)295 fiasco_decoder_is_color (fiasco_decoder_t *decoder)
296 {
297 dfiasco_t *dfiasco = cast_dfiasco (decoder);
298
299 if (!dfiasco)
300 return 0;
301 else
302 return dfiasco->wfa->wfainfo->color;
303 }
304
305 int
fiasco_decoder_delete(fiasco_decoder_t * decoder)306 fiasco_decoder_delete (fiasco_decoder_t *decoder)
307 {
308 dfiasco_t *dfiasco = cast_dfiasco (decoder);
309
310 if (!dfiasco)
311 return 1;
312
313 try
314 {
315 free_wfa (dfiasco->wfa);
316 free_video (dfiasco->video);
317 close_bitfile (dfiasco->input);
318 strcpy (dfiasco->id, " ");
319 free_dfiasco(dfiasco);
320 Free (decoder);
321 }
322 catch
323 {
324 return 0;
325 }
326
327 return 1;
328 }
329
330 /*****************************************************************************
331
332 private code
333
334 *****************************************************************************/
335
336 static dfiasco_t *
alloc_dfiasco(wfa_t * wfa,video_t * video,bitfile_t * input,int enlarge_factor,int smoothing,format_e image_format)337 alloc_dfiasco (wfa_t *wfa, video_t *video, bitfile_t *input,
338 int enlarge_factor, int smoothing, format_e image_format)
339 /*
340 * FIASCO decoder constructor:
341 * Initialize decoder structure.
342 *
343 * Return value:
344 * pointer to the new decoder structure
345 */
346 {
347 dfiasco_t *dfiasco = Calloc (1, sizeof (dfiasco_t));
348
349 strcpy (dfiasco->id, "DFIASCO");
350
351 dfiasco->wfa = wfa;
352 dfiasco->video = video;
353 dfiasco->input = input;
354 dfiasco->enlarge_factor = enlarge_factor;
355 dfiasco->smoothing = smoothing;
356 dfiasco->image_format = image_format;
357
358 return dfiasco;
359 }
360
361 static void
free_dfiasco(dfiasco_t * dfiasco)362 free_dfiasco (dfiasco_t *dfiasco)
363 /*
364 * FIASCO decoder destructor:
365 * Free memory of given 'decoder' struct.
366 *
367 * No return value.
368 *
369 * Side effects:
370 * 'video' struct is discarded.
371 */
372 {
373 Free (dfiasco);
374 }
375
376 static dfiasco_t *
cast_dfiasco(fiasco_decoder_t * dfiasco)377 cast_dfiasco (fiasco_decoder_t *dfiasco)
378 /*
379 * Cast pointer `dfiasco' to type dfiasco_t.
380 * Check whether `dfiasco' is a valid object of type dfiasco_t.
381 *
382 * Return value:
383 * pointer to dfiasco_t struct on success
384 * NULL otherwise
385 */
386 {
387 dfiasco_t *this = (dfiasco_t *) dfiasco->private;
388 if (this)
389 {
390 if (!streq (this->id, "DFIASCO"))
391 {
392 set_error (_("Parameter `dfiasco' doesn't match required type."));
393 return NULL;
394 }
395 }
396 else
397 {
398 set_error (_("Parameter `%s' not defined (NULL)."), "dfiasco");
399 }
400
401 return this;
402 }
403