1 /*
2  *  mc.c:		Output of motion compensation
3  *
4  *  Written by:		Michael Unger
5  *			Ullrich Hafner
6  *
7  *  This file is part of FIASCO (Fractal Image And Sequence COdec)
8  *  Copyright (C) 1994-2000 Ullrich Hafner
9  */
10 
11 /*
12  *  $Date: 2000/06/14 20:50:31 $
13  *  $Author: hafner $
14  *  $Revision: 5.1 $
15  *  $State: Exp $
16  */
17 
18 #include "config.h"
19 
20 #include "types.h"
21 #include "macros.h"
22 #include "error.h"
23 
24 #include "wfa.h"
25 #include "bit-io.h"
26 #include "mvcode.h"
27 
28 #include "mc.h"
29 
30 /*****************************************************************************
31 
32 			     local variables
33 
34 *****************************************************************************/
35 
36 static unsigned p_frame_codes [4][2] =
37 /*
38  *  Code values and bits for P-frame prediction
39  *  NONE,  FORWARD
40  */
41 {
42    {1, 1}, {0, 1}, {0, 0}, {0, 0}
43 };
44 
45 static unsigned b_frame_codes [4][2] =
46 /*
47  *  Code values and bits for B-frame prediction
48  *  NONE,  FORWARD,  BACKWARD, INTERPOLATED
49  */
50 {
51    {1, 1}, {000, 3}, {001, 3}, {01, 2}
52 };
53 
54 enum vlc_e {CODE = 0, BITS = 1};
55 
56 /*****************************************************************************
57 
58 				prototypes
59 
60 *****************************************************************************/
61 
62 static void
63 encode_mc_tree (unsigned max_state, frame_type_e frame_type, const wfa_t *wfa,
64 	       bitfile_t *output);
65 static void
66 encode_mc_coords (unsigned max_state, const wfa_t *wfa, bitfile_t *output);
67 
68 /*****************************************************************************
69 
70 				public code
71 
72 *****************************************************************************/
73 
74 void
write_mc(frame_type_e frame_type,const wfa_t * wfa,bitfile_t * output)75 write_mc (frame_type_e frame_type, const wfa_t *wfa, bitfile_t *output)
76 {
77    unsigned max_state = wfa->wfainfo->color
78 			? wfa->tree[wfa->tree[wfa->root_state][0]][0]
79 			: wfa->states;
80 
81    encode_mc_tree (max_state, frame_type, wfa, output);
82    encode_mc_coords (max_state, wfa, output);
83 }
84 
85 /*****************************************************************************
86 
87 				private code
88 
89 *****************************************************************************/
90 
91 static void
encode_mc_tree(unsigned max_state,frame_type_e frame_type,const wfa_t * wfa,bitfile_t * output)92 encode_mc_tree (unsigned max_state, frame_type_e frame_type, const wfa_t *wfa,
93 		bitfile_t *output)
94 /*
95  *  Write tree of motion compensation decisions to the 'output' stream.
96  *  Depending on 'frame_type' different decoding methods are used.
97  *  'max_state' is the last state with motion compensation infos.
98  *
99  *  No return value.
100  */
101 {
102    unsigned  label;			/* current label */
103    unsigned  state;			/* current state */
104    unsigned  total = 0;			/* number of motion tree decisions */
105    unsigned  queue [MAXSTATES];		/* state numbers in BFO */
106    unsigned  current;			/* current node to process */
107    unsigned  last;			/* last node (update every new node) */
108    mc_type_e type;			/* type of motion compensation */
109    unsigned	     (*mc_tree_codes)[2]; /* pointer to VLC table */
110    unsigned  bits  = bits_processed (output); /* number of bits used */
111 
112    if (frame_type == P_FRAME)
113       mc_tree_codes = p_frame_codes;	/* binary code */
114    else
115       mc_tree_codes = b_frame_codes;	/* variable length code */
116 
117    /*
118     *  Traverse tree in breadth first order (starting at
119     *  level 'wfa->p_max_level'). Use a queue to store the children
120     *  of each node ('last' is the next free queue element).
121     */
122 
123    for (last = 0, state = wfa->basis_states; state < max_state; state++)
124       if (wfa->level_of_state [state] - 1 == (int) wfa->wfainfo->p_max_level)
125 	 queue [last++] = state;	/* init level = 'mc_max_level' */
126 
127    for (current = 0; current < last; current++)
128       for (label = 0; label < MAXLABELS; label++)
129       {
130 	 state = queue [current];
131 	 type  = wfa->mv_tree [state][label].type;
132 	 if (wfa->x [state][label]
133 	     + width_of_level (wfa->level_of_state [state] - 1)
134 	     <= wfa->wfainfo->width
135 	     &&
136 	     wfa->y [state][label]
137 	     + height_of_level (wfa->level_of_state [state] - 1)
138 	     <= wfa->wfainfo->height)
139 	 {
140 	    put_bits (output, mc_tree_codes [type][CODE],
141 		      mc_tree_codes [type][BITS]);
142 	    total++;
143 	 }
144 	 if (type == NONE && !isrange (wfa->tree [state][label]) &&
145 	     wfa->level_of_state [state] - 1 >=
146 	     (int) wfa->wfainfo->p_min_level)
147 	    queue [last++] = wfa->tree [state][label]; /* append child */
148 
149       }
150 
151    OUTPUT_BYTE_ALIGN (output);
152    debug_message ("mc-tree:      %5d bits. (%5d symbols => %5.2f bps)",
153 		  bits_processed (output) - bits, total,
154 		  total > 0 ? ((bits_processed (output) - bits) /
155 			       (double) total) : 0);
156 }
157 
158 static void
encode_mc_coords(unsigned max_state,const wfa_t * wfa,bitfile_t * output)159 encode_mc_coords (unsigned max_state, const wfa_t *wfa, bitfile_t *output)
160 /*
161  *  Write motion vector coordinates to the 'output' stream. They are stored
162  *  with the static Huffman code of the MPEG and H.263 standards.
163  *  'max_state' is the last state with motion compensation infos.
164  *
165  *  No return value.
166  */
167 {
168    unsigned  state;			/* current state */
169    unsigned  label;			/* current label */
170    unsigned  level_count [MAXLEVEL];	/* number of mv per level */
171    unsigned  level;			/* counter */
172    unsigned  ftotal = 0;		/* #forward motion tree decisions */
173    unsigned  btotal = 0;		/* #backward decisions */
174    unsigned  itotal = 0;		/* #interpolated decisions */
175    unsigned  bits   = bits_processed (output); /* number of bits used */
176    unsigned  sr     = wfa->wfainfo->search_range; /* search range */
177 
178    for (level = wfa->wfainfo->p_max_level;
179 	level >= wfa->wfainfo->p_min_level; level--)
180       level_count [level] = 0;
181 
182    for (state = wfa->basis_states; state < max_state; state++)
183       for (label = 0; label < MAXLABELS; label++)
184       {
185 	 mv_t *mv = &wfa->mv_tree[state][label]; /* motion vector info */
186 
187 	 if (mv->type != NONE)
188 	 {
189 	    level_count [wfa->level_of_state [state] - 1]++;
190 	    switch (mv->type)
191 	    {
192 	       case FORWARD:
193 		  put_bits (output,
194 			    mv_code_table[(mv->fx + sr)][CODE],
195 			    mv_code_table[(mv->fx + sr)][BITS]);
196 		  put_bits (output,
197 			    mv_code_table[(mv->fy + sr)][CODE],
198 			    mv_code_table[(mv->fy + sr)][BITS]);
199 		  ftotal++;
200 		  break;
201 	       case BACKWARD:
202 		  put_bits (output,
203 			    mv_code_table[(mv->bx + sr)][CODE],
204 			    mv_code_table[(mv->bx + sr)][BITS]);
205 		  put_bits (output,
206 			    mv_code_table[(mv->by + sr)][CODE],
207 			    mv_code_table[(mv->by + sr)][BITS]);
208 		  btotal++;
209 		  break;
210 	       case INTERPOLATED:
211 		  put_bits (output,
212 			    mv_code_table[(mv->fx + sr)][CODE],
213 			    mv_code_table[(mv->fx + sr)][BITS]);
214 		  put_bits (output,
215 			    mv_code_table[(mv->fy + sr)][CODE],
216 			    mv_code_table[(mv->fy + sr)][BITS]);
217 		  put_bits (output,
218 			    mv_code_table[(mv->bx + sr)][CODE],
219 			    mv_code_table[(mv->bx + sr)][BITS]);
220 		  put_bits (output,
221 			    mv_code_table[(mv->by + sr)][CODE],
222 			    mv_code_table[(mv->by + sr)][BITS]);
223 		  itotal++;
224 		  break;
225 	       default:
226 		  break;
227 	    }
228 	 }
229       }
230 
231    OUTPUT_BYTE_ALIGN (output);
232 
233    debug_message ("Motion compensation: %d forward, %d backward, "
234 		  "%d interpolated", ftotal, btotal, itotal);
235 
236    for (level = wfa->wfainfo->p_max_level;
237 	level >= wfa->wfainfo->p_min_level; level--)
238       debug_message ("Level %d: %d motion vectors", level, level_count[level]);
239 
240    {
241       unsigned  total = ftotal * 2 + btotal * 2 + itotal * 4;
242 
243       debug_message ("mv-coord:     %5d bits. (%5d symbols => %5.2f bps)",
244 		     bits_processed (output) - bits, total,
245 		     total > 0 ? ((bits_processed (output) - bits) /
246 				  (double) total) : 0);
247    }
248 
249    return;
250 }
251