diff options
Diffstat (limited to 'converter/other/fiasco/output/mc.c')
-rw-r--r-- | converter/other/fiasco/output/mc.c | 250 |
1 files changed, 250 insertions, 0 deletions
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; +} |