diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
commit | 1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch) | |
tree | 64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/other/fiasco/output | |
download | netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip |
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/other/fiasco/output')
-rw-r--r-- | converter/other/fiasco/output/Makefile | 26 | ||||
-rw-r--r-- | converter/other/fiasco/output/matrices.c | 547 | ||||
-rw-r--r-- | converter/other/fiasco/output/matrices.h | 28 | ||||
-rw-r--r-- | converter/other/fiasco/output/mc.c | 250 | ||||
-rw-r--r-- | converter/other/fiasco/output/mc.h | 28 | ||||
-rw-r--r-- | converter/other/fiasco/output/nd.c | 244 | ||||
-rw-r--r-- | converter/other/fiasco/output/nd.h | 27 | ||||
-rw-r--r-- | converter/other/fiasco/output/tree.c | 176 | ||||
-rw-r--r-- | converter/other/fiasco/output/tree.h | 27 | ||||
-rw-r--r-- | converter/other/fiasco/output/weights.c | 200 | ||||
-rw-r--r-- | converter/other/fiasco/output/weights.h | 27 | ||||
-rw-r--r-- | converter/other/fiasco/output/write.c | 250 | ||||
-rw-r--r-- | converter/other/fiasco/output/write.h | 28 |
13 files changed, 1858 insertions, 0 deletions
diff --git a/converter/other/fiasco/output/Makefile b/converter/other/fiasco/output/Makefile new file mode 100644 index 00000000..3bdc4635 --- /dev/null +++ b/converter/other/fiasco/output/Makefile @@ -0,0 +1,26 @@ +ifeq ($(SRCDIR)x,x) + SRCDIR = $(CURDIR)/../../../.. + BUILDDIR = $(SRCDIR) +endif +FIASCOSUBDIR = converter/other/fiasco +SUBDIR = $(FIASCOSUBDIR)/output +VPATH=.:$(SRCDIR)/$(SUBDIR) + +include $(BUILDDIR)/Makefile.config + +OBJECTS = matrices.o mc.o nd.o tree.o weights.o write.o + +MERGE_OBJECTS = $(OBJECTS) + +INCLUDES = -I$(SRCDIR)/$(FIASCOSUBDIR) \ + -I$(SRCDIR)/$(FIASCOSUBDIR)/lib \ + -I$(SRCDIR)/$(FIASCOSUBDIR)/codec + +all: libfiasco_output.a + +include $(SRCDIR)/Makefile.common + +libfiasco_output.a: $(OBJECTS) + $(AR) -rc $@ $(OBJECTS) + $(RANLIB) $@ + diff --git a/converter/other/fiasco/output/matrices.c b/converter/other/fiasco/output/matrices.c new file mode 100644 index 00000000..fd8d31e2 --- /dev/null +++ b/converter/other/fiasco/output/matrices.c @@ -0,0 +1,547 @@ +/* + * matrices.c: Output of transitions matrices + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* NETPBM: When you call delta_encoding() with last_domain < 4, it + crashes. And we have seen it happen. +*/ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#include "config.h" + +#if STDC_HEADERS +# include <stdlib.h> +#endif /* not STDC_HEADERS */ + +#include "types.h" +#include "macros.h" +#include "error.h" + +#include "wfa.h" +#include "bit-io.h" +#include "arith.h" +#include "misc.h" +#include "wfalib.h" + +#include "matrices.h" + +/***************************************************************************** + + prototypes + +*****************************************************************************/ + +static unsigned +delta_encoding (bool_t use_normal_domains, bool_t use_delta_domains, + const wfa_t *wfa, unsigned last_domain, bitfile_t *output); +static unsigned +column_0_encoding (const wfa_t *wfa, unsigned last_row, bitfile_t *output); +static unsigned +chroma_encoding (const wfa_t *wfa, bitfile_t *output); + +/***************************************************************************** + + public code + +*****************************************************************************/ + +unsigned +write_matrices (bool_t use_normal_domains, bool_t use_delta_domains, + const wfa_t *wfa, bitfile_t *output) +/* + * Write transition matrices of 'wfa' to stream 'output'. + * + * Return value: + * number of transitions encoded + */ +{ + unsigned root_state; /* root of luminance */ + unsigned total = 0; /* number of transitions */ + + root_state = wfa->wfainfo->color + ? wfa->tree [wfa->tree [wfa->root_state][0]][0] + : wfa->root_state; + + total = column_0_encoding (wfa, root_state, output); + + total += delta_encoding (use_normal_domains, use_delta_domains, + wfa, root_state, output); + + if (wfa->wfainfo->color) + total += chroma_encoding (wfa, output); + + return total; +} + +/***************************************************************************** + + private code + +*****************************************************************************/ + +static unsigned +delta_encoding (bool_t use_normal_domains, bool_t use_delta_domains, + const wfa_t *wfa, unsigned last_domain, bitfile_t *output) +/* + * Write transition matrices with delta coding to stream 'input'. + * 'last_domain' is the maximum state number used as domain image. + * + * Return value: + * number of non-zero matrix elements (WFA edges) + */ +{ + range_sort_t rs; /* ranges are sorted as in the coder */ + unsigned max_domain; /* dummy used for recursion */ + unsigned total = 0; + + /* + * Generate a list of range blocks. + * The order is the same as in the coder. + */ + rs.range_state = Calloc ((last_domain + 1) * MAXLABELS, + sizeof (u_word_t)); + rs.range_label = Calloc ((last_domain + 1) * MAXLABELS, + sizeof (byte_t)); + rs.range_max_domain = Calloc ((last_domain + 1) * MAXLABELS, + sizeof (u_word_t)); + rs.range_subdivided = Calloc ((last_domain + 1) * MAXLABELS, + sizeof (bool_t)); + rs.range_no = 0; + max_domain = wfa->basis_states - 1; + sort_ranges (last_domain, &max_domain, &rs, wfa); + + /* + * Compute and write distribution of #edges + */ + { + unsigned state, label; + unsigned edge; + unsigned count [MAXEDGES + 1]; + unsigned n; + unsigned edges = 0; + unsigned M = 0; + unsigned bits = bits_processed (output); + + for (n = 0; n < MAXEDGES + 1; n++) + count [n] = 0; + + for (state = wfa->basis_states; state <= last_domain; state++) + for (label = 0; label < MAXLABELS; label++) + if (isrange (wfa->tree [state][label])) + { + for (edge = 0; isedge (wfa->into [state][label][edge]); edge++) + ; + count [edge]++; + edges++; + M = max (edge, M); + } + write_rice_code (M, 3, output); + for (n = 0; n <= M; n++) +/* NETPBM: The following causes a crash when last_domain < 4, because + it requests writing of a negative number of bits. And we have seen + last_domain = 3. But we have no clue what last_domain means, or + even what a rice code is, so we don't know where the error lies. + -Bryan 2001.02.09 +*/ + write_rice_code (count [n], (int) log2 (last_domain) - 2, output); + + /* + * Arithmetic coding of values */ + { + unsigned range; + model_t *elements = alloc_model (M + 1, 0, 0, count); + arith_t *encoder = alloc_encoder (output); + + for (range = 0; range < rs.range_no; range++) + if (!rs.range_subdivided [range]) + { + state = rs.range_state [range]; + label = rs.range_label [range]; + for (edge = 0; isedge (wfa->into [state][label][edge]); edge++) + ; + + encode_symbol (edge, encoder, elements); + } + free_encoder (encoder); + free_model (elements); + } + debug_message ("delta-#edges: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, edges, + edges > 0 ? ((bits_processed (output) - bits) / + (double) edges) : 0); + } + + /* + * Write matrix elements + */ + { + unsigned bits = bits_processed (output); + u_word_t *mapping1 = Calloc (wfa->states, sizeof (u_word_t)); + u_word_t *mapping2 = Calloc (wfa->states, sizeof (u_word_t)); + unsigned range; + + put_bit (output, use_normal_domains); + put_bit (output, use_delta_domains); + + /* + * Generate array of states which are admitted domains. + * When coding intra frames 'mapping1' == 'mapping2' otherwise + * 'mapping1' is a list of 'normal' domains which are admitted for + * coding intra blocks + * 'mapping2' is a list of 'delta' domains which are admitted for + * coding the motion compensated prediction error + */ + { + unsigned n1, n2, state; + + for (n1 = n2 = state = 0; state < wfa->states; state++) + { + mapping1 [state] = n1; + if (usedomain (state, wfa) + && (state < wfa->basis_states || use_delta_domains + || !wfa->delta_state [state])) + n1++; + + mapping2 [state] = n2; + if (usedomain (state, wfa) + && (state < wfa->basis_states || use_normal_domains + || wfa->delta_state [state])) + n2++; + } + debug_message ("# normal states = %d, # delta states = %d," + " # WFA states = %d", n1, n2, wfa->states); + } + + for (range = 0; range < rs.range_no; range++) + if (!rs.range_subdivided [range]) + { + unsigned state = rs.range_state [range]; + unsigned label = rs.range_label [range]; + unsigned last = 1; + u_word_t *mapping; + unsigned max_value; + unsigned edge; + word_t domain; + + if (wfa->delta_state [state] || + wfa->mv_tree [state][label].type != NONE) + mapping = mapping2; + else + mapping = mapping1; + + max_value = mapping [rs.range_max_domain [range]]; + + for (edge = 0; isedge (domain = wfa->into [state][label][edge]); + edge++) + if (domain > 0) + { + total++; + if (max_value - last) + { + write_bin_code (mapping [domain] - last, + max_value - last, output); + last = mapping [domain] + 1; + } + } + } + + debug_message ("delta-index: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total, + total > 0 ? ((bits_processed (output) - bits) / + (double) total) : 0); + Free (mapping1); + Free (mapping2); + } + + Free (rs.range_state); + Free (rs.range_label); + Free (rs.range_max_domain); + Free (rs.range_subdivided); + + return total; +} + +static unsigned +column_0_encoding (const wfa_t *wfa, unsigned last_row, bitfile_t *output) +/* + * Write column 0 of the transition matrices of the 'wfa' to stream 'output' + * with quasi arithmetic coding. + * All rows from 'wfa->basis_states' up to 'last_row' are decoded. + * + * Return value: + * number of non-zero matrix elements (WFA edges) + */ +{ + u_word_t high; /* Start of the current code range */ + u_word_t low; /* End of the current code range */ + unsigned *prob; /* probability array */ + unsigned row; /* current matrix row */ + unsigned label; /* current matrix label */ + unsigned underflow; /* Underflow bits */ + unsigned index; /* probability index */ + unsigned total = 0; /* Number of '1' elements */ + unsigned bits = bits_processed (output); + + /* + * Compute the probability array: + * prob[] = { 1/2, 1/2, 1/4, 1/4, 1/4, 1/4, + * 1/8, ... , 1/16, ..., 1/(MAXPROB+1)} + */ + { + unsigned n; + unsigned exp; /* current exponent */ + + prob = Calloc (1 << (MAX_PROB + 1), sizeof (unsigned)); + + for (index = 0, n = MIN_PROB; n <= MAX_PROB; n++) + for (exp = 0; exp < 1U << n; exp++, index++) + prob [index] = n; + } + + high = HIGH; /* 1.0 */ + low = LOW; /* 0.0 */ + underflow = 0; /* no underflow bits */ + + index = 0; + + /* + * Encode column 0 with a quasi arithmetic coder (QAC). + * Advantage of this QAC with respect to a binary AC: + * Instead of using time consuming multiplications and divisions + * to compute the probability of the most probable symbol (MPS) and + * the range of the interval, a table look up procedure linked + * with a shift operation is used for both computations. + */ + for (row = wfa->basis_states; row <= last_row; row++) + for (label = 0; label < MAXLABELS; label++) + if (isrange (wfa->tree [row][label])) + { + if (wfa->into [row][label][0] != 0) + { + /* + * encode the MPS '0' + */ + high = high - ((high - low) >> prob [index]) - 1; + RESCALE_OUTPUT_INTERVAL; + + if (index < 1020) + index++; + } + else + { + /* + * encode the LPS '1' + */ + low = high - ((high - low) >> prob [index]); + + RESCALE_OUTPUT_INTERVAL; + + total++; + index >>= 1; + } + } + /* + * Flush the quasi-arithmetic encoder + */ + low = high; + + RESCALE_OUTPUT_INTERVAL; + + OUTPUT_BYTE_ALIGN (output); + + Free (prob); + + debug_message ("delta-state0: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total, + total > 0 ? ((bits_processed (output) - bits) / + (double) total) : 0); + + return total; +} + +static unsigned +chroma_encoding (const wfa_t *wfa, bitfile_t *output) +/* + * Write transition matrices of 'wfa' states which are part of the + * chroma channels Cb and Cr to stream 'output'. + * + * Return value: + * number of non-zero matrix elements (WFA edges) + */ +{ + + unsigned domain; /* current domain, counter */ + unsigned label; /* current label */ + unsigned total = 0; /* number of '1' elements */ + u_word_t high; /* Start of the current code range */ + u_word_t low; /* End of the current code range */ + unsigned underflow; /* underflow bits */ + unsigned *prob; /* probability array */ + unsigned index; /* probability index, counter */ + unsigned next_index; /* probability of last domain */ + unsigned row; /* current matrix row */ + word_t *y_domains; + unsigned count = 0; /* number of transitions for part 1 */ + unsigned bits = bits_processed (output); + + /* + * Compute the asymmetric probability array + * prob[] = { 1/2, 1/2, 1/4, 1/4, 1/4, 1/4, + * 1/8, ... , 1/16, ..., 1/(MAXPROB+1)} + */ + { + unsigned n; + unsigned exp; /* current exponent */ + + prob = Calloc (1 << (MAX_PROB + 1), sizeof (unsigned)); + + for (index = 0, n = MIN_PROB; n <= MAX_PROB; n++) + for (exp = 0; exp < 1U << n; exp++, index++) + prob [index] = n; + } + + high = HIGH; /* 1.0 */ + low = LOW; /* 0.0 */ + underflow = 0; /* no underflow bits */ + + next_index = index = 0; + + y_domains = compute_hits (wfa->basis_states, + wfa->tree [wfa->tree [wfa->root_state][0]][0], + wfa->wfainfo->chroma_max_states, wfa); + + /* + * First of all, read all matrix columns given in the list 'y_domains' + * which note all admitted domains. + * These matrix elements are stored with QAC (see column_0_encoding ()). + */ + for (domain = 0; y_domains [domain] != -1; domain++) + { + bool_t save_index = YES; /* YES: store current prob. index */ + + row = wfa->tree [wfa->tree [wfa->root_state][0]][0] + 1; + index = next_index; + + for (; row < wfa->states; row++) + { + for (label = 0; label < MAXLABELS; label++) + if (isrange (wfa->tree [row][label])) + { + unsigned edge; + int into; + bool_t match; /* approx with current domain found */ + + for (match = NO, edge = 0; + isedge (into = wfa->into [row][label][edge]) + && (unsigned) into < row; + edge++) + if (into == y_domains [domain] + && into != wfa->y_state [row][label]) + match = YES; + if (!match) + { + /* + * encode the MPS '0' + */ + high = high - ((high - low) >> prob [index]) - 1; + + RESCALE_OUTPUT_INTERVAL; + + if (index < 1020) + index++; + } + else + { + /* + * encode the LPS '1' + */ + low = high - ((high - low) >> prob [index]); + + RESCALE_OUTPUT_INTERVAL; + + total++; + index >>= 1; + } + } + if (save_index) + { + next_index = index; + save_index = NO; + } + } + } + + debug_message ("CbCr_matrix: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total, + total > 0 ? ((bits_processed (output) - bits) / + (double) total) : 0); + count = total; + bits = bits_processed (output); + + /* + * Encode the additional column which indicates whether there + * are transitions to a state with same spatial coordinates + * in the Y component. + * + * Again, quasi arithmetic coding is used for this task. + */ + + next_index = index = 0; + + for (row = wfa->tree [wfa->tree [wfa->root_state][0]][0] + 1; + row < wfa->states; row++) + for (label = 0; label < MAXLABELS; label++) + if (!wfa->y_column [row][label]) + { + /* + * encode the MPS '0' + */ + high = high - ((high - low) >> prob [index]) - 1; + + RESCALE_OUTPUT_INTERVAL; + + if (index < 1020) + index++; + } + else + { + /* + * encode the LPS '1' + */ + low = high - ((high - low) >> prob [index]); + + RESCALE_OUTPUT_INTERVAL; + + index >>= 1; + total++; + } + + /* + * Flush the quasi-arithmetic encoder + */ + low = high; + + RESCALE_OUTPUT_INTERVAL; + OUTPUT_BYTE_ALIGN (output); + + debug_message ("Yreferences: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total - count, + total - count > 0 ? ((bits_processed (output) - bits) / + (double) (total - count)) : 0); + + Free (prob); + Free (y_domains); + + return total; +} diff --git a/converter/other/fiasco/output/matrices.h b/converter/other/fiasco/output/matrices.h new file mode 100644 index 00000000..f880fef8 --- /dev/null +++ b/converter/other/fiasco/output/matrices.h @@ -0,0 +1,28 @@ +/* + * matrices.h + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#ifndef _MATRICES_H +#define _MATRICES_H + +#include "wfa.h" +#include "bit-io.h" + +unsigned +write_matrices (bool_t use_normal_domains, bool_t use_delta_domains, + const wfa_t *wfa, bitfile_t *output); + +#endif /* _MATRICES_H */ + diff --git a/converter/other/fiasco/output/mc.c b/converter/other/fiasco/output/mc.c new file mode 100644 index 00000000..afff586b --- /dev/null +++ b/converter/other/fiasco/output/mc.c @@ -0,0 +1,250 @@ +/* + * mc.c: Output of motion compensation + * + * Written by: Michael Unger + * Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#include "config.h" + +#include "types.h" +#include "macros.h" +#include "error.h" + +#include "wfa.h" +#include "bit-io.h" +#include "mvcode.h" + +#include "mc.h" + +/***************************************************************************** + + local variables + +*****************************************************************************/ + +static unsigned p_frame_codes [4][2] = +/* + * Code values and bits for P-frame prediction + * NONE, FORWARD + */ +{ + {1, 1}, {0, 1}, {0, 0}, {0, 0} +}; + +static unsigned b_frame_codes [4][2] = +/* + * Code values and bits for B-frame prediction + * NONE, FORWARD, BACKWARD, INTERPOLATED + */ +{ + {1, 1}, {000, 3}, {001, 3}, {01, 2} +}; + +enum vlc_e {CODE = 0, BITS = 1}; + +/***************************************************************************** + + prototypes + +*****************************************************************************/ + +static void +encode_mc_tree (unsigned max_state, frame_type_e frame_type, const wfa_t *wfa, + bitfile_t *output); +static void +encode_mc_coords (unsigned max_state, const wfa_t *wfa, bitfile_t *output); + +/***************************************************************************** + + public code + +*****************************************************************************/ + +void +write_mc (frame_type_e frame_type, const wfa_t *wfa, bitfile_t *output) +{ + unsigned max_state = wfa->wfainfo->color + ? wfa->tree[wfa->tree[wfa->root_state][0]][0] + : wfa->states; + + encode_mc_tree (max_state, frame_type, wfa, output); + encode_mc_coords (max_state, wfa, output); +} + +/***************************************************************************** + + private code + +*****************************************************************************/ + +static void +encode_mc_tree (unsigned max_state, frame_type_e frame_type, const wfa_t *wfa, + bitfile_t *output) +/* + * Write tree of motion compensation decisions to the 'output' stream. + * Depending on 'frame_type' different decoding methods are used. + * 'max_state' is the last state with motion compensation infos. + * + * No return value. + */ +{ + unsigned label; /* current label */ + unsigned state; /* current state */ + unsigned total = 0; /* number of motion tree decisions */ + unsigned queue [MAXSTATES]; /* state numbers in BFO */ + unsigned current; /* current node to process */ + unsigned last; /* last node (update every new node) */ + mc_type_e type; /* type of motion compensation */ + unsigned (*mc_tree_codes)[2]; /* pointer to VLC table */ + unsigned bits = bits_processed (output); /* number of bits used */ + + if (frame_type == P_FRAME) + mc_tree_codes = p_frame_codes; /* binary code */ + else + mc_tree_codes = b_frame_codes; /* variable length code */ + + /* + * Traverse tree in breadth first order (starting at + * level 'wfa->p_max_level'). Use a queue to store the childs + * of each node ('last' is the next free queue element). + */ + + for (last = 0, state = wfa->basis_states; state < max_state; state++) + if (wfa->level_of_state [state] - 1 == (int) wfa->wfainfo->p_max_level) + queue [last++] = state; /* init level = 'mc_max_level' */ + + for (current = 0; current < last; current++) + for (label = 0; label < MAXLABELS; label++) + { + state = queue [current]; + type = wfa->mv_tree [state][label].type; + if (wfa->x [state][label] + + width_of_level (wfa->level_of_state [state] - 1) + <= wfa->wfainfo->width + && + wfa->y [state][label] + + height_of_level (wfa->level_of_state [state] - 1) + <= wfa->wfainfo->height) + { + put_bits (output, mc_tree_codes [type][CODE], + mc_tree_codes [type][BITS]); + total++; + } + if (type == NONE && !isrange (wfa->tree [state][label]) && + wfa->level_of_state [state] - 1 >= + (int) wfa->wfainfo->p_min_level) + queue [last++] = wfa->tree [state][label]; /* append child */ + + } + + OUTPUT_BYTE_ALIGN (output); + debug_message ("mc-tree: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total, + total > 0 ? ((bits_processed (output) - bits) / + (double) total) : 0); +} + +static void +encode_mc_coords (unsigned max_state, const wfa_t *wfa, bitfile_t *output) +/* + * Write motion vector coordinates to the 'output' stream. They are stored + * with the static Huffman code of the MPEG and H.263 standards. + * 'max_state' is the last state with motion compensation infos. + * + * No return value. + */ +{ + unsigned state; /* current state */ + unsigned label; /* current label */ + unsigned level_count [MAXLEVEL]; /* number of mv per level */ + unsigned level; /* counter */ + unsigned ftotal = 0; /* #forward motion tree decisions */ + unsigned btotal = 0; /* #backward decisions */ + unsigned itotal = 0; /* #interpolated decisions */ + unsigned bits = bits_processed (output); /* number of bits used */ + unsigned sr = wfa->wfainfo->search_range; /* search range */ + + for (level = wfa->wfainfo->p_max_level; + level >= wfa->wfainfo->p_min_level; level--) + level_count [level] = 0; + + for (state = wfa->basis_states; state < max_state; state++) + for (label = 0; label < MAXLABELS; label++) + { + mv_t *mv = &wfa->mv_tree[state][label]; /* motion vector info */ + + if (mv->type != NONE) + { + level_count [wfa->level_of_state [state] - 1]++; + switch (mv->type) + { + case FORWARD: + put_bits (output, + mv_code_table[(mv->fx + sr)][CODE], + mv_code_table[(mv->fx + sr)][BITS]); + put_bits (output, + mv_code_table[(mv->fy + sr)][CODE], + mv_code_table[(mv->fy + sr)][BITS]); + ftotal++; + break; + case BACKWARD: + put_bits (output, + mv_code_table[(mv->bx + sr)][CODE], + mv_code_table[(mv->bx + sr)][BITS]); + put_bits (output, + mv_code_table[(mv->by + sr)][CODE], + mv_code_table[(mv->by + sr)][BITS]); + btotal++; + break; + case INTERPOLATED: + put_bits (output, + mv_code_table[(mv->fx + sr)][CODE], + mv_code_table[(mv->fx + sr)][BITS]); + put_bits (output, + mv_code_table[(mv->fy + sr)][CODE], + mv_code_table[(mv->fy + sr)][BITS]); + put_bits (output, + mv_code_table[(mv->bx + sr)][CODE], + mv_code_table[(mv->bx + sr)][BITS]); + put_bits (output, + mv_code_table[(mv->by + sr)][CODE], + mv_code_table[(mv->by + sr)][BITS]); + itotal++; + break; + default: + break; + } + } + } + + OUTPUT_BYTE_ALIGN (output); + + debug_message ("Motion compensation: %d forward, %d backward, " + "%d interpolated", ftotal, btotal, itotal); + + for (level = wfa->wfainfo->p_max_level; + level >= wfa->wfainfo->p_min_level; level--) + debug_message ("Level %d: %d motion vectors", level, level_count[level]); + + { + unsigned total = ftotal * 2 + btotal * 2 + itotal * 4; + + debug_message ("mv-coord: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total, + total > 0 ? ((bits_processed (output) - bits) / + (double) total) : 0); + } + + return; +} diff --git a/converter/other/fiasco/output/mc.h b/converter/other/fiasco/output/mc.h new file mode 100644 index 00000000..b7843fd8 --- /dev/null +++ b/converter/other/fiasco/output/mc.h @@ -0,0 +1,28 @@ +/* + * mc.h + * + * Written by: Michael Unger + * Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#ifndef _MC_H +#define _MC_H + +#include "wfa.h" +#include "bit-io.h" + +void +write_mc (frame_type_e frame_type, const wfa_t *wfa, bitfile_t *output); + +#endif /* not _MC_H */ + diff --git a/converter/other/fiasco/output/nd.c b/converter/other/fiasco/output/nd.c new file mode 100644 index 00000000..a09ff762 --- /dev/null +++ b/converter/other/fiasco/output/nd.c @@ -0,0 +1,244 @@ +/* + * nd.c: Output of prediction tree + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#include "config.h" + +#include "types.h" +#include "macros.h" +#include "error.h" + +#include "wfa.h" +#include "arith.h" +#include "misc.h" +#include "bit-io.h" +#include "rpf.h" +#include "list.h" + +#include "nd.h" + +/***************************************************************************** + + prototypes + +*****************************************************************************/ + +static unsigned +encode_nd_tree (const wfa_t *wfa, bitfile_t *output); +static void +encode_nd_coefficients (unsigned total, const wfa_t *wfa, bitfile_t *output); + +/***************************************************************************** + + public code + +*****************************************************************************/ + +void +write_nd (const wfa_t *wfa, bitfile_t *output) +/* + * Write prediction information of 'wfa' to given stream 'output'. + * Coefficients are quantized with model 'p_rpf'. + * + * No return value. + */ +{ + unsigned total = encode_nd_tree (wfa, output); + + if (total > 0) + encode_nd_coefficients (total, wfa, output); +} + +/***************************************************************************** + + private code + +*****************************************************************************/ + +static unsigned +encode_nd_tree (const wfa_t *wfa, bitfile_t *output) +/* + * Write prediction tree of 'wfa' to given stream 'output'. + * + * No return value. + */ +{ + lqueue_t *queue; /* queue of states */ + int state, next; /* state and its current child */ + unsigned used, not_used; /* counter ND used/not used */ + u_word_t low; /* Start of the current code range */ + u_word_t high; /* End of the current code range */ + u_word_t underflow; /* Number of underflow bits pending */ + u_word_t sum0, sum1; /* Probability model */ + unsigned bits = bits_processed (output); + + used = not_used = 0; + + /* + * Initialize arithmetic coder + */ + low = 0; + high = 0xffff; + underflow = 0; + sum0 = 1; + sum1 = 11; + + queue = alloc_queue (sizeof (int)); + state = wfa->root_state; + queue_append (queue, &state); + + /* + * Traverse the WFA tree in breadth first order (using a queue). + */ + while (queue_remove (queue, &next)) + { + unsigned label; + + if (wfa->level_of_state [next] > wfa->wfainfo->p_max_level + 1) + { + /* + * Nondetermismn is not allowed at levels larger than + * 'wfa->wfainfo->p_max_level'. + */ + for (label = 0; label < MAXLABELS; label++) + if (ischild (state = wfa->tree [next][label])) + queue_append (queue, &state); /* continue with childs */ + } + else if (wfa->level_of_state [next] > wfa->wfainfo->p_min_level) + { + for (label = 0; label < MAXLABELS; label++) + if (ischild (state = wfa->tree [next][label])) + { + unsigned range; /* Current interval range */ + + if (isedge (wfa->into [next][label][0])) /* prediction used */ + { + used++; + + /* + * Encode a '1' symbol + */ + range = (high - low) + 1; + low = low + (u_word_t) ((range * sum0) / sum1); + RESCALE_OUTPUT_INTERVAL; + } + else /* no predict., continue with childs */ + { + not_used++; + if (wfa->level_of_state [state] > wfa->wfainfo->p_min_level) + queue_append (queue, &state); + + /* + * Encode a '0' symbol + */ + range = (high - low) + 1; + high = low + (u_word_t) ((range * sum0) / sum1 - 1); + RESCALE_OUTPUT_INTERVAL; + sum0++; + } + /* + * Update the frequency counts + */ + sum1++; + if (sum1 > 50) /* Scale the symbol frequencies */ + { + sum0 >>= 1; + sum1 >>= 1; + if (!sum0) + sum0 = 1; + if (sum0 >= sum1) + sum1 = sum0 + 1; + } + } + + } + } + free_queue (queue); + + /* + * Flush the quasi-arithmetic encoder + */ + low = high; + RESCALE_OUTPUT_INTERVAL; + OUTPUT_BYTE_ALIGN (output); + + debug_message ("%d nd fields: %d used nd, %d used not nd", used + not_used, + used, not_used); + { + unsigned total = used + not_used; + + debug_message ("nd-tree: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total, + total > 0 ? ((bits_processed (output) - bits) / + (double) total) : 0); + } + + return used; +} + +static void +encode_nd_coefficients (unsigned total, const wfa_t *wfa, bitfile_t *output) +/* + * Write #'total' weights of nondeterministic part of 'wfa' to given 'output' + * stream. Coefficients are stored with arithmetic coding (the model is + * given by 'p_rpf'). + * + * No return value. + */ +{ + unsigned bits = bits_processed (output); + + { + unsigned *coefficients; /* array of factors to encode */ + unsigned *ptr; /* pointer to current factor */ + unsigned state, label, edge; + word_t domain; + + ptr = coefficients = Calloc (total, sizeof (unsigned)); + + for (state = wfa->basis_states; state < wfa->states; state++) + for (label = 0; label < MAXLABELS; label++) + if (ischild (wfa->tree [state][label]) + && isedge (wfa->into [state][label][0])) + for (edge = 0; isedge (domain = wfa->into [state][label][edge]); + edge++) + { + if (ptr - coefficients >= (int) total) + error ("Can't write more than %d coefficients.", total); + + *ptr++ = rtob (wfa->weight [state][label][edge], + wfa->wfainfo->dc_rpf); + } + + /* + * Encode array of coefficients with arithmetic coding + */ + { + const int scaling = 50; /* scaling factor of prob. model */ + unsigned c_symbols = 1 << (wfa->wfainfo->dc_rpf->mantissa_bits + 1); + + encode_array (output, coefficients, NULL, &c_symbols, 1, + total, scaling); + } + + debug_message ("nd-factors: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total, + total ? ((bits_processed (output) - bits) + / (double) total) : 0); + Free (coefficients); + } +} + + diff --git a/converter/other/fiasco/output/nd.h b/converter/other/fiasco/output/nd.h new file mode 100644 index 00000000..600b3d73 --- /dev/null +++ b/converter/other/fiasco/output/nd.h @@ -0,0 +1,27 @@ +/* + * nd.h + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#ifndef _ND_H +#define _ND_H + +#include "wfa.h" +#include "bit-io.h" + +void +write_nd (const wfa_t *wfa, bitfile_t *output); + +#endif /* not _ND_H */ + diff --git a/converter/other/fiasco/output/tree.c b/converter/other/fiasco/output/tree.c new file mode 100644 index 00000000..0056d7dd --- /dev/null +++ b/converter/other/fiasco/output/tree.c @@ -0,0 +1,176 @@ +/* + * tree.c: Output of bintree partitioning + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#include "config.h" + +#include "types.h" +#include "macros.h" +#include "error.h" + +#include "wfa.h" +#include "bit-io.h" +#include "arith.h" +#include "misc.h" + +#include "tree.h" + +/***************************************************************************** + + prototypes + +*****************************************************************************/ + +static void +encode_tree (bitfile_t *output, const byte_t *data, unsigned n_data, + unsigned scaling, u_word_t sum0, u_word_t sum1); + +/***************************************************************************** + + public code + +*****************************************************************************/ + +void +write_tree (const wfa_t *wfa, bitfile_t *output) +/* + * Write bintree to stream 'output'. + * Traverse tree in breadth first order and save a '1' for each child + * and a '0' for each range image. + * + * No return value. + */ +{ + unsigned queue [MAXSTATES]; /* state numbers in BFO */ + unsigned current; /* current node to process */ + unsigned last; /* last node (update every new node) */ + unsigned label; /* current label */ + int into; /* next child */ + byte_t *tree_string; /* bitstring to encode */ + unsigned total = 0; /* number of ranges */ + unsigned bits = bits_processed (output); /* number of bits */ + + /* + * Traverse tree in breadth first order. Use a queue to store + * the childs of each node ('last' is the next free queue element). + * The first element ('current') of this queue will get the new parent + * node. + */ + tree_string = Calloc (MAXSTATES * MAXLABELS, sizeof (byte_t)); + queue [0] = wfa->root_state; + for (last = 1, current = 0; current < last; current++) + for (label = 0; label < MAXLABELS; label++) + if (!isrange (into = wfa->tree [queue[current]][label])) /* child ? */ + { + queue [last++] = into; + tree_string [total++] = 1; + } + else /* or range ? */ + tree_string [total++] = 0; + + if (total != (wfa->states - wfa->basis_states) * MAXLABELS) + error ("total [%d] != (states - basis_states) * 2 [%d]", total, + (wfa->states - wfa->basis_states) * MAXLABELS); + + { + unsigned scale = total / 20 ; + + encode_tree (output, tree_string, total, scale, 1, 11); + } + + Free (tree_string); + + debug_message ("tree: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total, + total > 0 ? ((bits_processed (output) - bits) + / (double) total) : 0); +} + +/***************************************************************************** + + private code + +*****************************************************************************/ + +static void +encode_tree (bitfile_t *output, const byte_t *data, unsigned n_data, + unsigned scaling, u_word_t sum0, u_word_t sum1) +/* + * Encode bintree data with adaptive binary arithmetic coding. + * Write 'n_data' output symbols stored in 'data' to stream 'output'. + * Rescale probability model after every 'scaling' symbols. + * Initial counts are given by 'sum0' and 'sum1'. + * + * No return value. + */ +{ + u_word_t low; /* Start of the current code range */ + u_word_t high; /* End of the current code range */ + u_word_t underflow; /* Number of underflow bits pending */ + unsigned n; /* Data counter */ + + low = 0; + high = 0xffff; + underflow = 0; + + for (n = n_data; n; n--) + { + unsigned range; /* Current interval range */ + + if (!*data++) + { + /* + * encode a '0' + */ + range = (high - low) + 1; + high = low + (u_word_t) ((range * sum0) / sum1 - 1); + + RESCALE_OUTPUT_INTERVAL; + + sum0++; + } + else + { + /* + * encode a '1' + */ + range = (high - low) + 1; + low = low + (u_word_t) ((range * sum0) / sum1); + + RESCALE_OUTPUT_INTERVAL; + } + /* + * Update the frequency counts + */ + sum1++; + if (sum1 > scaling) /* Scale the symbol frequencies */ + { + sum0 >>= 1; + sum1 >>= 1; + if (!sum0) + sum0 = 1; + if (sum0 >= sum1) + sum1 = sum0 + 1; + } + } + /* + * Flush the quasi-arithmetic encoder + */ + low = high; + + RESCALE_OUTPUT_INTERVAL; + + OUTPUT_BYTE_ALIGN (output); +} diff --git a/converter/other/fiasco/output/tree.h b/converter/other/fiasco/output/tree.h new file mode 100644 index 00000000..6f8a3800 --- /dev/null +++ b/converter/other/fiasco/output/tree.h @@ -0,0 +1,27 @@ +/* + * tree.h + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#ifndef _TREE_H +#define _TREE_H + +#include "wfa.h" +#include "bit-io.h" + +void +write_tree (const wfa_t *wfa, bitfile_t *output); + +#endif /* not _TREE_H */ + diff --git a/converter/other/fiasco/output/weights.c b/converter/other/fiasco/output/weights.c new file mode 100644 index 00000000..085a1f00 --- /dev/null +++ b/converter/other/fiasco/output/weights.c @@ -0,0 +1,200 @@ +/* + * weights.c: Output of weights + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#include "config.h" + +#include "types.h" +#include "macros.h" +#include "error.h" + +#include "wfa.h" +#include "misc.h" +#include "bit-io.h" +#include "arith.h" +#include "wfalib.h" + +#include "weights.h" + +/***************************************************************************** + + public code + +*****************************************************************************/ + +void +write_weights (unsigned total, const wfa_t *wfa, bitfile_t *output) +/* + * Traverse the transition matrices of the 'wfa' and write #'total' + * weights != 0 to stream 'output'. + * + * No return value. + */ +{ + unsigned state, label; /* current label */ + unsigned offset1, offset2; /* model offsets. */ + unsigned offset3, offset4; /* model offsets. */ + unsigned *weights_array; /* array of weights to encode */ + unsigned *wptr; /* pointer to current weight */ + unsigned *level_array; /* array of corresponding levels */ + unsigned *lptr; /* pointer to current corr. level */ + int min_level, max_level; /* min and max range level */ + int d_min_level, d_max_level; /* min and max delta range level */ + bool_t dc, d_dc; /* true if dc or delta dc are used */ + bool_t delta_approx = NO; /* true if delta has been used */ + unsigned delta_count = 0; /* number of delta ranges */ + unsigned bits = bits_processed (output); + + /* + * Check whether delta approximation has been used + */ + for (state = wfa->basis_states; state < wfa->states; state++) + if (wfa->delta_state [state]) + { + delta_approx = YES; + break; + } + + /* + * Generate array of corresponding levels (context of probability model) + */ + min_level = d_min_level = MAXLEVEL; + max_level = d_max_level = 0; + dc = d_dc = NO; + + for (state = wfa->basis_states; state < wfa->states; state++) + for (label = 0; label < MAXLABELS; label++) + if (isrange (wfa->tree [state][label])) + { + if (delta_approx && wfa->delta_state [state]) /* delta approx. */ + { + d_min_level = min (d_min_level, + wfa->level_of_state [state] - 1); + d_max_level = max (d_max_level, + wfa->level_of_state [state] - 1); + if (wfa->into [state][label][0] == 0) + d_dc = YES; + } + else + { + min_level = min (min_level, wfa->level_of_state [state] - 1); + max_level = max (max_level, wfa->level_of_state [state] - 1); + if (wfa->into [state][label][0] == 0) + dc = YES; + } + } + if (min_level > max_level) /* no lc found */ + max_level = min_level - 1; + if (d_min_level > d_max_level) + d_max_level = d_min_level - 1; + + /* + * Context model: + * 0 DC weight + * 1 Delta DC weight + * 2-k normal weights per level + * k+1 - m Delta weights per level + */ + + offset1 = dc ? 1 : 0; + offset2 = offset1 + (d_dc ? 1 : 0); + offset3 = offset2 + (max_level - min_level + 1); + offset4 = offset3 + (d_max_level - d_min_level + 1); + + /* + * Weights are encoded as follows: + * all weights of state n + * sorted by label + * sorted by domain number + */ + + wptr = weights_array = Calloc (total, sizeof (unsigned)); + lptr = level_array = Calloc (total, sizeof (unsigned)); + + for (state = wfa->basis_states; state < wfa->states; state++) + for (label = 0; label < MAXLABELS; label++) + if (isrange (wfa->tree [state][label])) + { + int edge; /* current edge */ + int domain; /* current domain (context of model) */ + + for (edge = 0; isedge (domain = wfa->into [state][label][edge]); + edge++) + { + if (wptr - weights_array >= (int) total) + error ("Can't write more than %d weights.", total); + if (domain) /* not DC component */ + { + if (delta_approx && wfa->delta_state [state]) /* delta */ + { + *wptr++ = rtob (wfa->weight [state][label][edge], + wfa->wfainfo->d_rpf); + *lptr++ = offset3 + + wfa->level_of_state [state] - 1 - d_min_level; + delta_count++; + } + else + { + *wptr++ = rtob (wfa->weight [state][label][edge], + wfa->wfainfo->rpf); + *lptr++ = offset2 + + wfa->level_of_state [state] - 1 - min_level; + } + } + else /* DC component */ + { + if (delta_approx && wfa->delta_state [state]) /* delta */ + { + *wptr++ = rtob (wfa->weight [state][label][edge], + wfa->wfainfo->d_dc_rpf); + *lptr++ = offset1; + } + else + { + *wptr++ = rtob (wfa->weight [state][label][edge], + wfa->wfainfo->dc_rpf); + *lptr++ = 0; + } + } + } + } + + { + unsigned i; + unsigned *c_symbols = Calloc (offset4, sizeof (int)); + const int scale = 500; /* scaling of probability model */ + + c_symbols [0] = 1 << (wfa->wfainfo->dc_rpf->mantissa_bits + 1); + if (offset1 != offset2) + c_symbols [offset1] = 1 << (wfa->wfainfo->d_dc_rpf->mantissa_bits + + 1); + for (i = offset2; i < offset3; i++) + c_symbols [i] = 1 << (wfa->wfainfo->rpf->mantissa_bits + 1); + for (; i < offset4; i++) + c_symbols [i] = 1 << (wfa->wfainfo->d_rpf->mantissa_bits + 1); + + encode_array (output, weights_array, level_array, c_symbols, offset4, + total, scale); + Free (c_symbols); + } + + debug_message ("%d delta weights out of %d.", delta_count, total); + debug_message ("weights: %5d bits. (%5d symbols => %5.2f bps)", + bits_processed (output) - bits, total, + (bits_processed (output) - bits) / (double) total); + + Free (weights_array); + Free (level_array); +} diff --git a/converter/other/fiasco/output/weights.h b/converter/other/fiasco/output/weights.h new file mode 100644 index 00000000..271203ad --- /dev/null +++ b/converter/other/fiasco/output/weights.h @@ -0,0 +1,27 @@ +/* + * weights.h + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/06/14 20:50:31 $ + * $Author: hafner $ + * $Revision: 5.1 $ + * $State: Exp $ + */ + +#ifndef _WEIGHTS_H +#define _WEIGHTS_H + +#include "wfa.h" +#include "bit-io.h" + +void +write_weights (unsigned total, const wfa_t *wfa, bitfile_t *output); + +#endif /* not _WEIGHTS_H */ + diff --git a/converter/other/fiasco/output/write.c b/converter/other/fiasco/output/write.c new file mode 100644 index 00000000..e6185ad3 --- /dev/null +++ b/converter/other/fiasco/output/write.c @@ -0,0 +1,250 @@ +/* + * write.c: Output of WFA files + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/07/18 15:44:59 $ + * $Author: hafner $ + * $Revision: 5.3 $ + * $State: Exp $ + */ + +#include "config.h" + +#include "types.h" +#include "macros.h" +#include "error.h" + +#include "cwfa.h" +#include "image.h" +#include "misc.h" +#include "bit-io.h" +#include "rpf.h" + +#include "tree.h" +#include "matrices.h" +#include "weights.h" +#include "mc.h" +#include "nd.h" +#include "write.h" + +/***************************************************************************** + + prototypes + +*****************************************************************************/ + +static void +write_tiling (const tiling_t *tiling, bitfile_t *output); + +/***************************************************************************** + + public code + + +*****************************************************************************/ + + +void +write_next_wfa (const wfa_t *wfa, const coding_t *c, bitfile_t *output) +/* + * Write 'wfa' to stream 'output'. If the first frame should be written + * then also store the header information of the coding struct 'c'. + * + * No return value. + */ +{ + unsigned edges = 0; /* number of transitions */ + unsigned bits; + + debug_message ("--------------------------------------" + "--------------------------------------"); + + if (c->mt->number == 0) /* first WFA */ + write_header (wfa->wfainfo, output); + + bits = bits_processed (output); + + /* + * Frame header information + */ + { + const int rice_k = 8; /* parameter of Rice Code */ + + write_rice_code (wfa->states, rice_k, output); + write_rice_code (c->mt->frame_type, rice_k, output); + write_rice_code (c->mt->number, rice_k, output); + } + + OUTPUT_BYTE_ALIGN (output); + + debug_message ("frame-header: %5d bits.", bits_processed (output) - bits); + + if (c->tiling->exponent) /* write tiling permutation */ + { + put_bit (output, 1); + write_tiling (c->tiling, output); + } + else + put_bit (output, 0); + + OUTPUT_BYTE_ALIGN (output); + + write_tree (wfa, output); + + if (c->options.prediction) /* write nondeterministic approx. */ + { + put_bit (output, 1); + write_nd (wfa, output); + } + else + put_bit (output, 0); + + if (c->mt->frame_type != I_FRAME) /* write motion compensation info */ + write_mc (c->mt->frame_type, wfa, output); + + edges = write_matrices (c->options.normal_domains, + c->options.delta_domains, wfa, output); + + if (edges) /* found at least one approximation */ + write_weights (edges, wfa, output); + + debug_message ("--------------------------------------" + "--------------------------------------"); +} + +void +write_header (const wfa_info_t *wi, bitfile_t *output) +/* + * Write the header information describing the type of 'wfa' + * to stream 'output'. + * + * No return value. + */ +{ + const unsigned rice_k = 8; /* parameter of Rice Code */ + unsigned bits = bits_processed (output); + const char *text; /* next character to write */ + + /* + * Write magic number and name of initial basis + */ + for (text = FIASCO_MAGIC; *text; text++) + put_bits (output, *text, 8); + put_bits (output, '\n', 8); + for (text = wi->basis_name; *text; text++) + put_bits (output, *text, 8); + put_bits (output, *text, 8); + + write_rice_code (FIASCO_BINFILE_RELEASE, rice_k, output); + + write_rice_code (HEADER_TITLE, rice_k, output); + for (text = wi->title; + text && *text && text - wi->title < MAXSTRLEN - 2; + text++) + put_bits (output, *text, 8); + put_bits (output, 0, 8); + + write_rice_code (HEADER_COMMENT, rice_k, output); + for (text = wi->comment; + text && *text && text - wi->comment < MAXSTRLEN - 2; + text++) + put_bits (output, *text, 8); + put_bits (output, 0, 8); + + write_rice_code (HEADER_END, rice_k, output); + + write_rice_code (wi->max_states, rice_k, output); + put_bit (output, wi->color ? 1 : 0); + write_rice_code (wi->width, rice_k, output); + write_rice_code (wi->height, rice_k, output); + if (wi->color) + write_rice_code (wi->chroma_max_states, rice_k, output); + write_rice_code (wi->p_min_level, rice_k, output); + write_rice_code (wi->p_max_level, rice_k, output); + write_rice_code (wi->frames, rice_k, output); + write_rice_code (wi->smoothing, rice_k, output); + + put_bits (output, wi->rpf->mantissa_bits - 2, 3); + put_bits (output, wi->rpf->range_e, 2); + if (wi->rpf->mantissa_bits != wi->dc_rpf->mantissa_bits || + wi->rpf->range != wi->dc_rpf->range) + { + put_bit (output, YES); + put_bits (output, wi->dc_rpf->mantissa_bits - 2, 3); + put_bits (output, wi->dc_rpf->range_e, 2); + } + else + put_bit (output, NO); + if (wi->rpf->mantissa_bits != wi->d_rpf->mantissa_bits || + wi->rpf->range != wi->d_rpf->range) + { + put_bit (output, YES); + put_bits (output, wi->d_rpf->mantissa_bits - 2, 3); + put_bits (output, wi->d_rpf->range_e, 2); + } + else + put_bit (output, NO); + if (wi->dc_rpf->mantissa_bits != wi->d_dc_rpf->mantissa_bits || + wi->dc_rpf->range != wi->d_dc_rpf->range) + { + put_bit (output, YES); + put_bits (output, wi->d_dc_rpf->mantissa_bits - 2, 3); + put_bits (output, wi->d_dc_rpf->range_e, 2); + } + else + put_bit (output, NO); + + if (wi->frames > 1) /* motion compensation stuff */ + { + write_rice_code (wi->fps, rice_k, output); + write_rice_code (wi->search_range, rice_k, output); + put_bit (output, wi->half_pixel ? 1 : 0); + put_bit (output, wi->B_as_past_ref ? 1 : 0); + } + + OUTPUT_BYTE_ALIGN (output); + debug_message ("header: %d bits.", bits_processed (output) - bits); +} + +/***************************************************************************** + + private code + +*****************************************************************************/ + +static void +write_tiling (const tiling_t *tiling, bitfile_t *output) +/* + * Write image tiling information given by 'tiling' to stream 'output'. + * + * No return value. + */ +{ + const unsigned rice_k = 8; /* parameter of Rice Code */ + unsigned bits = bits_processed (output); + + write_rice_code (tiling->exponent, rice_k, output); + if (tiling->method == FIASCO_TILING_VARIANCE_ASC + || tiling->method == FIASCO_TILING_VARIANCE_DSC) + { + unsigned tile; /* current image tile */ + + put_bit (output, 1); + for (tile = 0; tile < 1U << tiling->exponent; tile++) + if (tiling->vorder [tile] != -1) /* image tile is visible */ + put_bits (output, tiling->vorder [tile], tiling->exponent); + } + else + { + put_bit (output, 0); + put_bit (output, tiling->method == FIASCO_TILING_SPIRAL_ASC); + } + + debug_message ("tiling: %4d bits.", bits_processed (output) - bits); +} diff --git a/converter/other/fiasco/output/write.h b/converter/other/fiasco/output/write.h new file mode 100644 index 00000000..a3ede1f4 --- /dev/null +++ b/converter/other/fiasco/output/write.h @@ -0,0 +1,28 @@ +/* + * write.h + * + * Written by: Ullrich Hafner + * + * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) + * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> + */ + +/* + * $Date: 2000/07/15 17:27:30 $ + * $Author: hafner $ + * $Revision: 5.2 $ + * $State: Exp $ + */ + +#ifndef _WRITE_H +#define _WRITE_H + +#include "cwfa.h" +#include "bit-io.h" + +void +write_next_wfa (const wfa_t *wfa, const coding_t *c, bitfile_t *output); +void +write_header (const wfa_info_t *wi, bitfile_t *output); + +#endif /* not _WRITE_H */ |