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