/* * dfiasco.c: Decoder public interface * * Written by: Ullrich Hafner * * This file is part of FIASCO (Fractal Image And Sequence COdec) * Copyright (C) 1994-2000 Ullrich Hafner */ /* * $Date: 2000/10/28 17:39:30 $ * $Author: hafner $ * $Revision: 5.7 $ * $State: Exp $ */ #include #include #include "pm_c_util.h" #include "nstring.h" #include "config.h" #include "types.h" #include "macros.h" #include "error.h" #include "dfiasco.h" #include "wfa.h" #include "read.h" #include "misc.h" #include "bit-io.h" #include "decoder.h" #include "options.h" #include "wfalib.h" /***************************************************************************** prototypes *****************************************************************************/ static dfiasco_t * cast_dfiasco (fiasco_decoder_t *dfiasco); static void free_dfiasco (dfiasco_t *dfiasco); static dfiasco_t * alloc_dfiasco (wfa_t *wfa, video_t *video, bitfile_t *input, int enlarge_factor, int smoothing, format_e image_format); /***************************************************************************** public code *****************************************************************************/ fiasco_decoder_t * fiasco_decoder_new (const char *filename, const fiasco_d_options_t *options) { try { bitfile_t *input; /* pointer to WFA FIASCO stream */ wfa_t *wfa; /* wfa structure */ video_t *video; /* information about decoder state */ const d_options_t *dop; /* decoder additional options */ dfiasco_t *dfiasco; /* decoder internal state */ fiasco_decoder_t *decoder; /* public interface to decoder */ fiasco_d_options_t *default_options = NULL; if (options) { dop = cast_d_options ((fiasco_d_options_t *) options); if (!dop) return NULL; } else { default_options = fiasco_d_options_new (); dop = cast_d_options (default_options); } wfa = alloc_wfa (NO); video = alloc_video (NO); input = open_wfa (filename, wfa->wfainfo); read_basis (wfa->wfainfo->basis_name, wfa); decoder = Calloc (1, sizeof (fiasco_decoder_t)); decoder->delete = fiasco_decoder_delete; decoder->write_frame = fiasco_decoder_write_frame; decoder->get_frame = fiasco_decoder_get_frame; decoder->get_length = fiasco_decoder_get_length; decoder->get_rate = fiasco_decoder_get_rate; decoder->get_width = fiasco_decoder_get_width; decoder->get_height = fiasco_decoder_get_height; decoder->get_title = fiasco_decoder_get_title; decoder->get_comment = fiasco_decoder_get_comment; decoder->is_color = fiasco_decoder_is_color; decoder->private = dfiasco = alloc_dfiasco (wfa, video, input, dop->magnification, dop->smoothing, dop->image_format); if (default_options) fiasco_d_options_delete (default_options); if (dfiasco->enlarge_factor >= 0) { int n; unsigned long pixels = wfa->wfainfo->width * wfa->wfainfo->height; for (n = 1; n <= (int) dfiasco->enlarge_factor; n++) { if (pixels << (n << 1) > 2048 * 2048) { set_error (_("Magnifaction factor `%d' is too large. " "Maximum value is %d."), dfiasco->enlarge_factor, MAX(0, n - 1)); fiasco_decoder_delete (decoder); return NULL; } } } else { int n; for (n = 0; n <= (int) - dfiasco->enlarge_factor; n++) { if (wfa->wfainfo->width >> n < 32 || wfa->wfainfo->height >> n < 32) { set_error (_("Magnifaction factor `%d' is too small. " "Minimum value is %d."), dfiasco->enlarge_factor, - MAX(0, n - 1)); fiasco_decoder_delete (decoder); return NULL; } } } return (fiasco_decoder_t *) decoder; } catch { return NULL; } } int fiasco_decoder_write_frame (fiasco_decoder_t *decoder, const char *filename) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return 0; else { try { image_t *frame = get_next_frame (NO, dfiasco->enlarge_factor, dfiasco->smoothing, NULL, FORMAT_4_4_4, dfiasco->video, NULL, dfiasco->wfa, dfiasco->input); write_image (filename, frame); } catch { return 0; } return 1; } } fiasco_image_t * fiasco_decoder_get_frame (fiasco_decoder_t *decoder) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return NULL; else { try { fiasco_image_t *image = Calloc (1, sizeof (fiasco_image_t)); image_t *frame = get_next_frame (NO, dfiasco->enlarge_factor, dfiasco->smoothing, NULL, dfiasco->image_format, dfiasco->video, NULL, dfiasco->wfa, dfiasco->input); frame->reference_count++; /* for motion compensation */ image->private = frame; image->delete = fiasco_image_delete; image->get_width = fiasco_image_get_width; image->get_height = fiasco_image_get_height; image->is_color = fiasco_image_is_color; return image; } catch { return NULL; } } } unsigned fiasco_decoder_get_length (fiasco_decoder_t *decoder) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return 0; else return dfiasco->wfa->wfainfo->frames; } unsigned fiasco_decoder_get_rate (fiasco_decoder_t *decoder) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return 0; else return dfiasco->wfa->wfainfo->fps; } unsigned fiasco_decoder_get_width (fiasco_decoder_t *decoder) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return 0; else { unsigned width; if (dfiasco->enlarge_factor >= 0) width = dfiasco->wfa->wfainfo->width << dfiasco->enlarge_factor; else width = dfiasco->wfa->wfainfo->width >> - dfiasco->enlarge_factor; return width & 1 ? width + 1 : width; } } unsigned fiasco_decoder_get_height (fiasco_decoder_t *decoder) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return 0; else { unsigned height; if (dfiasco->enlarge_factor >= 0) height = dfiasco->wfa->wfainfo->height << dfiasco->enlarge_factor; else height = dfiasco->wfa->wfainfo->height >> - dfiasco->enlarge_factor; return height & 1 ? height + 1 : height; } } const char * fiasco_decoder_get_title (fiasco_decoder_t *decoder) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return NULL; else return dfiasco->wfa->wfainfo->title; } const char * fiasco_decoder_get_comment (fiasco_decoder_t *decoder) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return NULL; else return dfiasco->wfa->wfainfo->comment; } int fiasco_decoder_is_color (fiasco_decoder_t *decoder) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return 0; else return dfiasco->wfa->wfainfo->color; } int fiasco_decoder_delete (fiasco_decoder_t *decoder) { dfiasco_t *dfiasco = cast_dfiasco (decoder); if (!dfiasco) return 1; try { free_wfa (dfiasco->wfa); free_video (dfiasco->video); close_bitfile (dfiasco->input); strcpy (dfiasco->id, " "); free_dfiasco(dfiasco); Free (decoder); } catch { return 0; } return 1; } /***************************************************************************** private code *****************************************************************************/ static dfiasco_t * alloc_dfiasco (wfa_t *wfa, video_t *video, bitfile_t *input, int enlarge_factor, int smoothing, format_e image_format) /* * FIASCO decoder constructor: * Initialize decoder structure. * * Return value: * pointer to the new decoder structure */ { dfiasco_t *dfiasco = Calloc (1, sizeof (dfiasco_t)); strcpy (dfiasco->id, "DFIASCO"); dfiasco->wfa = wfa; dfiasco->video = video; dfiasco->input = input; dfiasco->enlarge_factor = enlarge_factor; dfiasco->smoothing = smoothing; dfiasco->image_format = image_format; return dfiasco; } static void free_dfiasco (dfiasco_t *dfiasco) /* * FIASCO decoder destructor: * Free memory of given 'decoder' struct. * * No return value. * * Side effects: * 'video' struct is discarded. */ { Free (dfiasco); } static dfiasco_t * cast_dfiasco (fiasco_decoder_t *dfiasco) /* * Cast pointer `dfiasco' to type dfiasco_t. * Check whether `dfiasco' is a valid object of type dfiasco_t. * * Return value: * pointer to dfiasco_t struct on success * NULL otherwise */ { dfiasco_t *this = (dfiasco_t *) dfiasco->private; if (this) { if (!streq (this->id, "DFIASCO")) { set_error (_("Parameter `dfiasco' doesn't match required type.")); return NULL; } } else { set_error (_("Parameter `%s' not defined (NULL)."), "dfiasco"); } return this; }