about summary refs log tree commit diff
path: root/converter/other/fiasco/input/matrices.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/other/fiasco/input/matrices.c')
-rw-r--r--converter/other/fiasco/input/matrices.c644
1 files changed, 644 insertions, 0 deletions
diff --git a/converter/other/fiasco/input/matrices.c b/converter/other/fiasco/input/matrices.c
new file mode 100644
index 00000000..47cde1aa
--- /dev/null
+++ b/converter/other/fiasco/input/matrices.c
@@ -0,0 +1,644 @@
+/*
+ *  matrices.c:		Input of transition 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>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:13 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "bit-io.h"
+#include "arith.h"
+#include "misc.h"
+#include "wfalib.h"
+
+#include "matrices.h"
+
+#if STDC_HEADERS
+#	include <stdlib.h>
+#endif /* not STDC_HEADERS */
+
+/*****************************************************************************
+
+				prototypes
+  
+*****************************************************************************/
+
+static unsigned
+delta_decoding (wfa_t *wfa, unsigned last_domain, bitfile_t *input);
+static unsigned
+column_0_decoding (wfa_t *wfa, unsigned last_row, bitfile_t *input);
+static unsigned
+chroma_decoding (wfa_t *wfa, bitfile_t *input);
+static void
+compute_y_state (int state, int y_state, wfa_t *wfa);
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+unsigned
+read_matrices (wfa_t *wfa, bitfile_t *input)
+/* 
+ *  Read transitions of WFA given from the stream 'input'.
+ *
+ *  Return value:
+ *	number of edges
+ *
+ *  Side effects:
+ *	'wfa->into' is filled with decoded values 
+ */
+{
+   unsigned total;			/* total number of edges in the WFA */
+   unsigned root_state = wfa->wfainfo->color
+			 ? wfa->tree [wfa->tree [wfa->root_state][0]][0]
+			 : wfa->root_state;
+
+   total  = column_0_decoding (wfa, root_state, input);
+   total += delta_decoding (wfa, root_state, input);
+   if (wfa->wfainfo->color)
+      total += chroma_decoding (wfa, input);
+       
+   return total;
+}
+
+/*****************************************************************************
+
+				private code
+  
+*****************************************************************************/
+
+static unsigned
+delta_decoding (wfa_t *wfa, unsigned last_domain, bitfile_t *input)
+/*
+ *  Read transition matrices which are encoded with delta coding
+ *  from stream 'input'.
+ *  'last_domain' is the maximum state number used as domain image.
+ *
+ *  Return value:
+ *	number of non-zero matrix elements (WFA edges)
+ *
+ *  Side effects:
+ *	'wfa->into' is filled with decoded values 
+ */
+{
+   range_sort_t	 rs;			/* ranges are sorted as in the coder */
+   unsigned	 max_domain;		/* dummy used for recursion */
+   unsigned	 range;
+   unsigned	 count [MAXEDGES + 1];
+   unsigned 	 state, label;
+   unsigned	*n_edges;		/* number of elements per row */
+   unsigned	 total = 0;		/* total number of decoded edges */
+
+   /*
+    *  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);
+
+   /*
+    *  Get row statistics
+    */
+   {
+      arith_t  *decoder;
+      model_t  *elements;
+      unsigned 	max_edges = read_rice_code (3, input);
+      
+      /*
+       *  Get the probability array of the number of edges distribution
+       *  and allocate the corresponding model.
+       */
+      {
+	 unsigned edge;
+	 
+	 for (edge = 0; edge <= max_edges; edge++)
+	    count [edge] = read_rice_code ((int) log2 (last_domain) - 2,
+					   input);
+	 elements = alloc_model (max_edges + 1, 0, 0, count);
+      }
+      
+      /*
+       *  Get number of elements per matrix row
+       */
+      {
+	 unsigned row;
+      
+	 n_edges = Calloc (wfa->states, sizeof (unsigned));
+	 decoder = alloc_decoder (input);
+	 for (row = range = 0; range < rs.range_no; range++)
+	    if (!rs.range_subdivided [range])
+	    {
+	       state = rs.range_state [range];
+	       label = rs.range_label [range];
+	       
+	       n_edges [row++]
+		  = decode_symbol (decoder, elements)
+		  - (isedge (wfa->into [state][label][0]) ? 1 : 0);
+	    }
+	 
+	 free_decoder (decoder);
+	 free_model (elements);
+      }
+   }
+   
+   /*
+    *  Get matrix elements
+    */
+   {
+      unsigned row;
+      u_word_t *mapping1           = Calloc (wfa->states, sizeof (word_t));
+      u_word_t *mapping_coder1     = Calloc (wfa->states, sizeof (word_t));
+      u_word_t *mapping2           = Calloc (wfa->states, sizeof (word_t));
+      u_word_t *mapping_coder2     = Calloc (wfa->states, sizeof (word_t));
+      bool_t	use_normal_domains = get_bit (input);
+      bool_t	use_delta_domains  = get_bit (input);
+	  
+      /*
+       *  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 [n1] = state;
+	    mapping_coder1 [state] = n1;
+	    if (usedomain (state, wfa)
+		&& (state < wfa->basis_states
+		    || use_delta_domains || !wfa->delta_state [state]))
+	       n1++;
+	    
+	    mapping2 [n2] = state;
+	    mapping_coder2 [state] = n2;
+	    if (usedomain (state, wfa)
+		&& (state < wfa->basis_states || use_normal_domains
+		    || wfa->delta_state [state]))
+	       n2++;
+	 }
+      }
+	 
+      for (row = 0, range = 0; range < rs.range_no; range++)
+	 if (!rs.range_subdivided [range])
+	 {
+	    u_word_t *mapping;
+	    u_word_t *mapping_coder;
+	    unsigned  max_value;
+	    unsigned  edge;
+	    unsigned  state = rs.range_state [range];
+	    unsigned  label = rs.range_label [range];
+	    unsigned  last  = 1;
+
+	    if (wfa->delta_state [state] ||
+		wfa->mv_tree [state][label].type != NONE)
+	    {
+	       mapping 	     = mapping2;
+	       mapping_coder = mapping_coder2;
+	    }
+	    else
+	    {
+	       mapping 	     = mapping1;
+	       mapping_coder = mapping_coder1;
+	    }
+	    max_value = mapping_coder [rs.range_max_domain [range]];
+	    for (edge = n_edges [row]; edge; edge--)
+	    {
+	       unsigned domain;
+
+	       if (max_value - last)
+		  domain = read_bin_code (max_value - last, input) + last;
+	       else
+		  domain = max_value;
+	       append_edge (state, mapping [domain], -1, label, wfa);
+	       last = domain + 1;
+	       total++;
+	    }
+	    row++;
+	 }
+      Free (mapping1);
+      Free (mapping_coder1);
+      Free (mapping2);
+      Free (mapping_coder2);
+   }
+      
+   Free (n_edges);
+   Free (rs.range_state);
+   Free (rs.range_label);
+   Free (rs.range_max_domain);
+   Free (rs.range_subdivided);
+
+   return total;
+}
+
+static unsigned
+column_0_decoding (wfa_t *wfa, unsigned last_row, bitfile_t *input)
+/*
+ *  Read column 0 of the transition matrices of the 'wfa' which are coded
+ *  with quasi arithmetic coding from stream 'input'.
+ *  All rows from 'wfa->basis_states' up to 'last_row' are decoded.
+ * 
+ *  Return value:
+ *	number of non-zero matrix elements (WFA edges)
+ *
+ *  Side effects:
+ *	'wfa->into' is filled with decoded values 
+ */
+{
+   unsigned  row;			/* current matrix row */
+   unsigned  total = 0;			/* total number of edges in col 0 */
+   unsigned *prob_ptr;			/* pointer to current probability */
+   unsigned *last;			/* pointer to minimum probability */
+   unsigned *first;			/* pointer to maximum probability */
+   unsigned *new_prob_ptr;		/* ptr to probability of last domain */
+   unsigned *prob;			/* probability array */
+   u_word_t  high;			/* Start of the current code range */
+   u_word_t  low;			/* End of the current code range */
+   u_word_t  code;			/* The present input code value */
+   word_t   *is_leaf;			/* pointer to the tree structure */
+
+   /*
+    *  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 index;			/* probability index */
+      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;
+   }
+
+   first = prob_ptr = new_prob_ptr = prob;
+   last  = first + 1020;
+   
+   is_leaf = wfa->tree [wfa->basis_states]; /* use pointer arithmetics ... */
+
+   high = HIGH;				/* 1.0 */
+   low  = LOW;				/* 0.0 */
+   code = get_bits (input, 16);		
+
+   /*
+    *  Decode 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.
+    *
+    *  Loops and array accesses have been removed
+    *  to make real time decoding possible.
+    */
+   for (row = wfa->basis_states; row <= last_row; row++)
+   {
+      unsigned count;			/* value in the current interval */
+      
+      /*
+       *  Read label 0 element
+       */
+      if (isrange (*is_leaf++))		/* valid matrix index */
+      {
+	 count = high - ((high - low) >> *prob_ptr);
+	 if (code < count)
+	 {
+	    if (prob_ptr < last)	/* model update */
+	       prob_ptr++;
+	    /*
+	     *  Decode the MPS '0'
+	     */
+	    high = count - 1;
+
+	    RESCALE_INPUT_INTERVAL;
+	 }
+	 else
+	 {
+	    prob_ptr = ((prob_ptr - first) >> 1) + first; /* model update */
+	    /*
+	     *  Decode the LPS '1'
+	     */
+	    low = count;
+
+	    RESCALE_INPUT_INTERVAL;
+	    /*
+	     *  Restore the transition (weight = -1)
+	     */
+	    append_edge (row, 0, -1, 0, wfa);
+	    total++;
+	 }
+      }
+      /*
+       *  Read label 1 element
+       */
+      if (isrange (*is_leaf++)) /* valid matrix index */
+      {
+	 count = high - ((high - low) >> *prob_ptr);
+	 if (code < count)
+	 {
+	    if (prob_ptr < last)
+	       prob_ptr++;		/* model update */
+	    /*
+	     *  Decode the MPS '0'
+	     */
+	    high = count - 1;
+
+	    RESCALE_INPUT_INTERVAL;
+	 }
+	 else
+	 {
+	    prob_ptr = ((prob_ptr - first) >> 1) + first; /* model update */
+	    /*
+	     *  Decode the LPS '1'
+	     */
+	    low = count;
+
+	    RESCALE_INPUT_INTERVAL;
+	    /*
+	     *  Restore the transition (weight = -1)
+	     */
+	    append_edge (row, 0, -1, 1, wfa);
+	    total++;
+	 }
+      }
+   }
+
+   INPUT_BYTE_ALIGN (input);
+
+   Free (prob);
+   
+   return total;
+}
+
+static unsigned
+chroma_decoding (wfa_t *wfa, bitfile_t *input)
+/*
+ *  Read transition matrices of 'wfa' states which are part of the
+ *  chroma channels Cb and Cr from stream 'input'.
+ *
+ *  Return value:
+ *	number of non-zero matrix elements (WFA edges)
+ *
+ *  Side effects:
+ *	'wfa->into' is filled with decoded values 
+ */
+{
+   unsigned  domain;			/* current domain, counter */
+   unsigned  total = 0;			/* total number of chroma edges */
+   unsigned *prob_ptr;			/* pointer to current probability */
+   unsigned *last;			/* pointer to minimum probability */
+   unsigned *first;			/* pointer to maximum probability */
+   unsigned *new_prob_ptr;		/* ptr to probability of last domain */
+   unsigned *prob;			/* probability array */
+   u_word_t  high;			/* Start of the current code range */
+   u_word_t  low;			/* End of the current code range */
+   u_word_t  code;			/* The present input code value */
+   word_t   *y_domains;			/* domain images corresponding to Y */
+   int	     save_index;		/* YES: store current probabilty */
+
+   /*
+    *  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 index;			/* probability index */
+      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 */
+   code = get_bits (input, 16);
+
+   /*
+    *  Compute list of admitted domains
+    */
+   y_domains = compute_hits (wfa->basis_states,
+			     wfa->tree [wfa->tree [wfa->root_state][0]][0],
+			     wfa->wfainfo->chroma_max_states, wfa);
+   
+   first = prob_ptr = new_prob_ptr = prob;
+   last  = first + 1020;
+
+   /*
+    *  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_decoding ()).
+    */
+   for (domain = 0; y_domains [domain] != -1; domain++)
+   {
+      unsigned 	row	= wfa->tree [wfa->tree [wfa->root_state][0]][0] + 1;
+      word_t   *is_leaf = wfa->tree [row];
+
+      prob_ptr   = new_prob_ptr;
+      save_index = YES;
+
+      for (; row < wfa->states; row++)
+      {
+	 unsigned count;		/* value in the current interval */
+	 /*
+	  *  Read label 0 element
+	  */
+	 if (isrange (*is_leaf++)) 	/* valid matrix index */
+	 {
+	    count = high - ((high - low) >> *prob_ptr);
+	    if (code < count)
+	    {
+	       if (prob_ptr < last)
+		  prob_ptr++;
+	       /*
+		*  Decode the MPS '0'
+		*/
+	       high = count - 1;
+
+	       RESCALE_INPUT_INTERVAL;
+	    }
+	    else
+	    {
+	       prob_ptr = ((prob_ptr - first) >> 1) + first;
+	       /*
+		*  Decode the LPS '1'
+		*/
+	       low = count;
+
+	       RESCALE_INPUT_INTERVAL;
+	       /*
+		*  Restore the transition (weight = -1)
+		*/
+	       append_edge (row, y_domains [domain], -1, 0, wfa);
+	       total++;
+	    }
+	 }
+	 /*
+	  *  Read label 1 element
+	  */
+	 if (isrange (*is_leaf++)) /* valid matrix index */
+	 {
+	    count = high - ((high - low) >> *prob_ptr);
+	    if (code < count)
+	    {
+	       if (prob_ptr < last)
+		  prob_ptr++;
+	       /*
+		*  Decode the MPS '0'
+		*/
+	       high = count - 1;
+
+	       RESCALE_INPUT_INTERVAL;
+	    }
+	    else
+	    {
+	       prob_ptr = ((prob_ptr - first) >> 1) + first;
+	       /*
+		*  Decode the LPS '1'
+		*/
+	       low = count;
+
+	       RESCALE_INPUT_INTERVAL;
+	       /*
+		*  Restore the transition (weight = -1)
+		*/
+	       append_edge (row, y_domains [domain], -1, 1, wfa);
+	       total++;
+	    }
+	 }
+	 if (save_index)
+	 {
+	    save_index 	 = NO;
+	    new_prob_ptr = prob_ptr;
+	 }
+      }
+   }
+
+   Free (y_domains);
+
+   compute_y_state (wfa->tree [wfa->tree [wfa->root_state][0]][1],
+		    wfa->tree [wfa->tree [wfa->root_state][0]][0], wfa);
+   compute_y_state (wfa->tree [wfa->tree [wfa->root_state][1]][0],
+		    wfa->tree [wfa->tree [wfa->root_state][0]][0], wfa);
+   
+   first = prob_ptr = new_prob_ptr = prob;
+
+   /*
+    *  Decode the additional column which indicates whether there
+    *  are transitions to a state with same spatial coordinates
+    *  in the Y component.
+    *
+    *  Again, quasi arithmetic decoding is used for this task.
+    */
+   {
+      unsigned 	row;
+      
+      for (row = wfa->tree [wfa->tree [wfa->root_state][0]][0] + 1;
+	   row < wfa->states; row++)
+      {
+	 int label;			/* current label */
+
+	 for (label = 0; label < MAXLABELS; label++)
+	 {
+	    u_word_t count = high - ((high - low) >> *prob_ptr);
+
+	    if (code < count)
+	    {
+	       if (prob_ptr < last)
+		  prob_ptr++;
+	       /*
+		*  Decode the MPS '0'
+		*/
+	       high = count - 1;
+
+	       RESCALE_INPUT_INTERVAL;
+	    }
+	    else
+	    {
+	       prob_ptr = ((prob_ptr - first) >> 1) + first;
+	       /*
+		*  Decode the LPS '1'
+		*/
+	       low = count;
+
+	       RESCALE_INPUT_INTERVAL;
+	       /*
+		*  Restore the transition (weight = -1)
+		*/
+	       append_edge (row, wfa->y_state [row][label], -1, label, wfa);
+	       total++;
+	    }
+	 }
+      }
+   }
+
+   INPUT_BYTE_ALIGN (input);
+
+   Free (prob);
+
+   return total;
+}
+
+static void
+compute_y_state (int state, int y_state, wfa_t *wfa)
+/*
+ *  Compute the 'wfa->y_state' array which denotes those states of
+ *  the Y band that have the same spatial coordinates as the corresponding
+ *  states of the Cb and Cr bands.
+ *  The current root of the Y tree is given by 'y_state'.
+ *  The current root of the tree of the chroma channel is given by 'state'.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	'wfa->y_state' is filled with the generated tree structure.
+ */
+{
+   unsigned label;
+   
+   for (label = 0; label < MAXLABELS; label++)
+      if (isrange (y_state))
+	 wfa->y_state [state][label] = RANGE;
+      else
+      {
+	 wfa->y_state [state][label] = wfa->tree [y_state][label];
+	 if (!isrange (wfa->tree [state][label]))
+	    compute_y_state (wfa->tree [state][label],
+			     wfa->y_state [state][label], wfa);
+      }
+      
+}