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