yading@10
|
1 /*
|
yading@10
|
2 * Copyright (C) 2007 Vitor Sessak <vitor1001@gmail.com>
|
yading@10
|
3 *
|
yading@10
|
4 * This file is part of FFmpeg.
|
yading@10
|
5 *
|
yading@10
|
6 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
7 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
8 * License as published by the Free Software Foundation; either
|
yading@10
|
9 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
10 *
|
yading@10
|
11 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
14 * Lesser General Public License for more details.
|
yading@10
|
15 *
|
yading@10
|
16 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
17 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
19 */
|
yading@10
|
20
|
yading@10
|
21 /**
|
yading@10
|
22 * @file
|
yading@10
|
23 * Codebook Generator using the ELBG algorithm
|
yading@10
|
24 */
|
yading@10
|
25
|
yading@10
|
26 #include <string.h>
|
yading@10
|
27
|
yading@10
|
28 #include "libavutil/avassert.h"
|
yading@10
|
29 #include "libavutil/common.h"
|
yading@10
|
30 #include "libavutil/lfg.h"
|
yading@10
|
31 #include "elbg.h"
|
yading@10
|
32 #include "avcodec.h"
|
yading@10
|
33
|
yading@10
|
34 #define DELTA_ERR_MAX 0.1 ///< Precision of the ELBG algorithm (as percentual error)
|
yading@10
|
35
|
yading@10
|
36 /**
|
yading@10
|
37 * In the ELBG jargon, a cell is the set of points that are closest to a
|
yading@10
|
38 * codebook entry. Not to be confused with a RoQ Video cell. */
|
yading@10
|
39 typedef struct cell_s {
|
yading@10
|
40 int index;
|
yading@10
|
41 struct cell_s *next;
|
yading@10
|
42 } cell;
|
yading@10
|
43
|
yading@10
|
44 /**
|
yading@10
|
45 * ELBG internal data
|
yading@10
|
46 */
|
yading@10
|
47 typedef struct{
|
yading@10
|
48 int error;
|
yading@10
|
49 int dim;
|
yading@10
|
50 int numCB;
|
yading@10
|
51 int *codebook;
|
yading@10
|
52 cell **cells;
|
yading@10
|
53 int *utility;
|
yading@10
|
54 int *utility_inc;
|
yading@10
|
55 int *nearest_cb;
|
yading@10
|
56 int *points;
|
yading@10
|
57 AVLFG *rand_state;
|
yading@10
|
58 int *scratchbuf;
|
yading@10
|
59 } elbg_data;
|
yading@10
|
60
|
yading@10
|
61 static inline int distance_limited(int *a, int *b, int dim, int limit)
|
yading@10
|
62 {
|
yading@10
|
63 int i, dist=0;
|
yading@10
|
64 for (i=0; i<dim; i++) {
|
yading@10
|
65 dist += (a[i] - b[i])*(a[i] - b[i]);
|
yading@10
|
66 if (dist > limit)
|
yading@10
|
67 return INT_MAX;
|
yading@10
|
68 }
|
yading@10
|
69
|
yading@10
|
70 return dist;
|
yading@10
|
71 }
|
yading@10
|
72
|
yading@10
|
73 static inline void vect_division(int *res, int *vect, int div, int dim)
|
yading@10
|
74 {
|
yading@10
|
75 int i;
|
yading@10
|
76 if (div > 1)
|
yading@10
|
77 for (i=0; i<dim; i++)
|
yading@10
|
78 res[i] = ROUNDED_DIV(vect[i],div);
|
yading@10
|
79 else if (res != vect)
|
yading@10
|
80 memcpy(res, vect, dim*sizeof(int));
|
yading@10
|
81
|
yading@10
|
82 }
|
yading@10
|
83
|
yading@10
|
84 static int eval_error_cell(elbg_data *elbg, int *centroid, cell *cells)
|
yading@10
|
85 {
|
yading@10
|
86 int error=0;
|
yading@10
|
87 for (; cells; cells=cells->next)
|
yading@10
|
88 error += distance_limited(centroid, elbg->points + cells->index*elbg->dim, elbg->dim, INT_MAX);
|
yading@10
|
89
|
yading@10
|
90 return error;
|
yading@10
|
91 }
|
yading@10
|
92
|
yading@10
|
93 static int get_closest_codebook(elbg_data *elbg, int index)
|
yading@10
|
94 {
|
yading@10
|
95 int i, pick=0, diff, diff_min = INT_MAX;
|
yading@10
|
96 for (i=0; i<elbg->numCB; i++)
|
yading@10
|
97 if (i != index) {
|
yading@10
|
98 diff = distance_limited(elbg->codebook + i*elbg->dim, elbg->codebook + index*elbg->dim, elbg->dim, diff_min);
|
yading@10
|
99 if (diff < diff_min) {
|
yading@10
|
100 pick = i;
|
yading@10
|
101 diff_min = diff;
|
yading@10
|
102 }
|
yading@10
|
103 }
|
yading@10
|
104 return pick;
|
yading@10
|
105 }
|
yading@10
|
106
|
yading@10
|
107 static int get_high_utility_cell(elbg_data *elbg)
|
yading@10
|
108 {
|
yading@10
|
109 int i=0;
|
yading@10
|
110 /* Using linear search, do binary if it ever turns to be speed critical */
|
yading@10
|
111 int r = av_lfg_get(elbg->rand_state)%elbg->utility_inc[elbg->numCB-1] + 1;
|
yading@10
|
112 while (elbg->utility_inc[i] < r)
|
yading@10
|
113 i++;
|
yading@10
|
114
|
yading@10
|
115 av_assert2(elbg->cells[i]);
|
yading@10
|
116
|
yading@10
|
117 return i;
|
yading@10
|
118 }
|
yading@10
|
119
|
yading@10
|
120 /**
|
yading@10
|
121 * Implementation of the simple LBG algorithm for just two codebooks
|
yading@10
|
122 */
|
yading@10
|
123 static int simple_lbg(elbg_data *elbg,
|
yading@10
|
124 int dim,
|
yading@10
|
125 int *centroid[3],
|
yading@10
|
126 int newutility[3],
|
yading@10
|
127 int *points,
|
yading@10
|
128 cell *cells)
|
yading@10
|
129 {
|
yading@10
|
130 int i, idx;
|
yading@10
|
131 int numpoints[2] = {0,0};
|
yading@10
|
132 int *newcentroid[2] = {
|
yading@10
|
133 elbg->scratchbuf + 3*dim,
|
yading@10
|
134 elbg->scratchbuf + 4*dim
|
yading@10
|
135 };
|
yading@10
|
136 cell *tempcell;
|
yading@10
|
137
|
yading@10
|
138 memset(newcentroid[0], 0, 2 * dim * sizeof(*newcentroid[0]));
|
yading@10
|
139
|
yading@10
|
140 newutility[0] =
|
yading@10
|
141 newutility[1] = 0;
|
yading@10
|
142
|
yading@10
|
143 for (tempcell = cells; tempcell; tempcell=tempcell->next) {
|
yading@10
|
144 idx = distance_limited(centroid[0], points + tempcell->index*dim, dim, INT_MAX)>=
|
yading@10
|
145 distance_limited(centroid[1], points + tempcell->index*dim, dim, INT_MAX);
|
yading@10
|
146 numpoints[idx]++;
|
yading@10
|
147 for (i=0; i<dim; i++)
|
yading@10
|
148 newcentroid[idx][i] += points[tempcell->index*dim + i];
|
yading@10
|
149 }
|
yading@10
|
150
|
yading@10
|
151 vect_division(centroid[0], newcentroid[0], numpoints[0], dim);
|
yading@10
|
152 vect_division(centroid[1], newcentroid[1], numpoints[1], dim);
|
yading@10
|
153
|
yading@10
|
154 for (tempcell = cells; tempcell; tempcell=tempcell->next) {
|
yading@10
|
155 int dist[2] = {distance_limited(centroid[0], points + tempcell->index*dim, dim, INT_MAX),
|
yading@10
|
156 distance_limited(centroid[1], points + tempcell->index*dim, dim, INT_MAX)};
|
yading@10
|
157 int idx = dist[0] > dist[1];
|
yading@10
|
158 newutility[idx] += dist[idx];
|
yading@10
|
159 }
|
yading@10
|
160
|
yading@10
|
161 return newutility[0] + newutility[1];
|
yading@10
|
162 }
|
yading@10
|
163
|
yading@10
|
164 static void get_new_centroids(elbg_data *elbg, int huc, int *newcentroid_i,
|
yading@10
|
165 int *newcentroid_p)
|
yading@10
|
166 {
|
yading@10
|
167 cell *tempcell;
|
yading@10
|
168 int *min = newcentroid_i;
|
yading@10
|
169 int *max = newcentroid_p;
|
yading@10
|
170 int i;
|
yading@10
|
171
|
yading@10
|
172 for (i=0; i< elbg->dim; i++) {
|
yading@10
|
173 min[i]=INT_MAX;
|
yading@10
|
174 max[i]=0;
|
yading@10
|
175 }
|
yading@10
|
176
|
yading@10
|
177 for (tempcell = elbg->cells[huc]; tempcell; tempcell = tempcell->next)
|
yading@10
|
178 for(i=0; i<elbg->dim; i++) {
|
yading@10
|
179 min[i]=FFMIN(min[i], elbg->points[tempcell->index*elbg->dim + i]);
|
yading@10
|
180 max[i]=FFMAX(max[i], elbg->points[tempcell->index*elbg->dim + i]);
|
yading@10
|
181 }
|
yading@10
|
182
|
yading@10
|
183 for (i=0; i<elbg->dim; i++) {
|
yading@10
|
184 int ni = min[i] + (max[i] - min[i])/3;
|
yading@10
|
185 int np = min[i] + (2*(max[i] - min[i]))/3;
|
yading@10
|
186 newcentroid_i[i] = ni;
|
yading@10
|
187 newcentroid_p[i] = np;
|
yading@10
|
188 }
|
yading@10
|
189 }
|
yading@10
|
190
|
yading@10
|
191 /**
|
yading@10
|
192 * Add the points in the low utility cell to its closest cell. Split the high
|
yading@10
|
193 * utility cell, putting the separate points in the (now empty) low utility
|
yading@10
|
194 * cell.
|
yading@10
|
195 *
|
yading@10
|
196 * @param elbg Internal elbg data
|
yading@10
|
197 * @param indexes {luc, huc, cluc}
|
yading@10
|
198 * @param newcentroid A vector with the position of the new centroids
|
yading@10
|
199 */
|
yading@10
|
200 static void shift_codebook(elbg_data *elbg, int *indexes,
|
yading@10
|
201 int *newcentroid[3])
|
yading@10
|
202 {
|
yading@10
|
203 cell *tempdata;
|
yading@10
|
204 cell **pp = &elbg->cells[indexes[2]];
|
yading@10
|
205
|
yading@10
|
206 while(*pp)
|
yading@10
|
207 pp= &(*pp)->next;
|
yading@10
|
208
|
yading@10
|
209 *pp = elbg->cells[indexes[0]];
|
yading@10
|
210
|
yading@10
|
211 elbg->cells[indexes[0]] = NULL;
|
yading@10
|
212 tempdata = elbg->cells[indexes[1]];
|
yading@10
|
213 elbg->cells[indexes[1]] = NULL;
|
yading@10
|
214
|
yading@10
|
215 while(tempdata) {
|
yading@10
|
216 cell *tempcell2 = tempdata->next;
|
yading@10
|
217 int idx = distance_limited(elbg->points + tempdata->index*elbg->dim,
|
yading@10
|
218 newcentroid[0], elbg->dim, INT_MAX) >
|
yading@10
|
219 distance_limited(elbg->points + tempdata->index*elbg->dim,
|
yading@10
|
220 newcentroid[1], elbg->dim, INT_MAX);
|
yading@10
|
221
|
yading@10
|
222 tempdata->next = elbg->cells[indexes[idx]];
|
yading@10
|
223 elbg->cells[indexes[idx]] = tempdata;
|
yading@10
|
224 tempdata = tempcell2;
|
yading@10
|
225 }
|
yading@10
|
226 }
|
yading@10
|
227
|
yading@10
|
228 static void evaluate_utility_inc(elbg_data *elbg)
|
yading@10
|
229 {
|
yading@10
|
230 int i, inc=0;
|
yading@10
|
231
|
yading@10
|
232 for (i=0; i < elbg->numCB; i++) {
|
yading@10
|
233 if (elbg->numCB*elbg->utility[i] > elbg->error)
|
yading@10
|
234 inc += elbg->utility[i];
|
yading@10
|
235 elbg->utility_inc[i] = inc;
|
yading@10
|
236 }
|
yading@10
|
237 }
|
yading@10
|
238
|
yading@10
|
239
|
yading@10
|
240 static void update_utility_and_n_cb(elbg_data *elbg, int idx, int newutility)
|
yading@10
|
241 {
|
yading@10
|
242 cell *tempcell;
|
yading@10
|
243
|
yading@10
|
244 elbg->utility[idx] = newutility;
|
yading@10
|
245 for (tempcell=elbg->cells[idx]; tempcell; tempcell=tempcell->next)
|
yading@10
|
246 elbg->nearest_cb[tempcell->index] = idx;
|
yading@10
|
247 }
|
yading@10
|
248
|
yading@10
|
249 /**
|
yading@10
|
250 * Evaluate if a shift lower the error. If it does, call shift_codebooks
|
yading@10
|
251 * and update elbg->error, elbg->utility and elbg->nearest_cb.
|
yading@10
|
252 *
|
yading@10
|
253 * @param elbg Internal elbg data
|
yading@10
|
254 * @param idx {luc (low utility cell, huc (high utility cell), cluc (closest cell to low utility cell)}
|
yading@10
|
255 */
|
yading@10
|
256 static void try_shift_candidate(elbg_data *elbg, int idx[3])
|
yading@10
|
257 {
|
yading@10
|
258 int j, k, olderror=0, newerror, cont=0;
|
yading@10
|
259 int newutility[3];
|
yading@10
|
260 int *newcentroid[3] = {
|
yading@10
|
261 elbg->scratchbuf,
|
yading@10
|
262 elbg->scratchbuf + elbg->dim,
|
yading@10
|
263 elbg->scratchbuf + 2*elbg->dim
|
yading@10
|
264 };
|
yading@10
|
265 cell *tempcell;
|
yading@10
|
266
|
yading@10
|
267 for (j=0; j<3; j++)
|
yading@10
|
268 olderror += elbg->utility[idx[j]];
|
yading@10
|
269
|
yading@10
|
270 memset(newcentroid[2], 0, elbg->dim*sizeof(int));
|
yading@10
|
271
|
yading@10
|
272 for (k=0; k<2; k++)
|
yading@10
|
273 for (tempcell=elbg->cells[idx[2*k]]; tempcell; tempcell=tempcell->next) {
|
yading@10
|
274 cont++;
|
yading@10
|
275 for (j=0; j<elbg->dim; j++)
|
yading@10
|
276 newcentroid[2][j] += elbg->points[tempcell->index*elbg->dim + j];
|
yading@10
|
277 }
|
yading@10
|
278
|
yading@10
|
279 vect_division(newcentroid[2], newcentroid[2], cont, elbg->dim);
|
yading@10
|
280
|
yading@10
|
281 get_new_centroids(elbg, idx[1], newcentroid[0], newcentroid[1]);
|
yading@10
|
282
|
yading@10
|
283 newutility[2] = eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[0]]);
|
yading@10
|
284 newutility[2] += eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[2]]);
|
yading@10
|
285
|
yading@10
|
286 newerror = newutility[2];
|
yading@10
|
287
|
yading@10
|
288 newerror += simple_lbg(elbg, elbg->dim, newcentroid, newutility, elbg->points,
|
yading@10
|
289 elbg->cells[idx[1]]);
|
yading@10
|
290
|
yading@10
|
291 if (olderror > newerror) {
|
yading@10
|
292 shift_codebook(elbg, idx, newcentroid);
|
yading@10
|
293
|
yading@10
|
294 elbg->error += newerror - olderror;
|
yading@10
|
295
|
yading@10
|
296 for (j=0; j<3; j++)
|
yading@10
|
297 update_utility_and_n_cb(elbg, idx[j], newutility[j]);
|
yading@10
|
298
|
yading@10
|
299 evaluate_utility_inc(elbg);
|
yading@10
|
300 }
|
yading@10
|
301 }
|
yading@10
|
302
|
yading@10
|
303 /**
|
yading@10
|
304 * Implementation of the ELBG block
|
yading@10
|
305 */
|
yading@10
|
306 static void do_shiftings(elbg_data *elbg)
|
yading@10
|
307 {
|
yading@10
|
308 int idx[3];
|
yading@10
|
309
|
yading@10
|
310 evaluate_utility_inc(elbg);
|
yading@10
|
311
|
yading@10
|
312 for (idx[0]=0; idx[0] < elbg->numCB; idx[0]++)
|
yading@10
|
313 if (elbg->numCB*elbg->utility[idx[0]] < elbg->error) {
|
yading@10
|
314 if (elbg->utility_inc[elbg->numCB-1] == 0)
|
yading@10
|
315 return;
|
yading@10
|
316
|
yading@10
|
317 idx[1] = get_high_utility_cell(elbg);
|
yading@10
|
318 idx[2] = get_closest_codebook(elbg, idx[0]);
|
yading@10
|
319
|
yading@10
|
320 if (idx[1] != idx[0] && idx[1] != idx[2])
|
yading@10
|
321 try_shift_candidate(elbg, idx);
|
yading@10
|
322 }
|
yading@10
|
323 }
|
yading@10
|
324
|
yading@10
|
325 #define BIG_PRIME 433494437LL
|
yading@10
|
326
|
yading@10
|
327 void ff_init_elbg(int *points, int dim, int numpoints, int *codebook,
|
yading@10
|
328 int numCB, int max_steps, int *closest_cb,
|
yading@10
|
329 AVLFG *rand_state)
|
yading@10
|
330 {
|
yading@10
|
331 int i, k;
|
yading@10
|
332
|
yading@10
|
333 if (numpoints > 24*numCB) {
|
yading@10
|
334 /* ELBG is very costly for a big number of points. So if we have a lot
|
yading@10
|
335 of them, get a good initial codebook to save on iterations */
|
yading@10
|
336 int *temp_points = av_malloc(dim*(numpoints/8)*sizeof(int));
|
yading@10
|
337 for (i=0; i<numpoints/8; i++) {
|
yading@10
|
338 k = (i*BIG_PRIME) % numpoints;
|
yading@10
|
339 memcpy(temp_points + i*dim, points + k*dim, dim*sizeof(int));
|
yading@10
|
340 }
|
yading@10
|
341
|
yading@10
|
342 ff_init_elbg(temp_points, dim, numpoints/8, codebook, numCB, 2*max_steps, closest_cb, rand_state);
|
yading@10
|
343 ff_do_elbg(temp_points, dim, numpoints/8, codebook, numCB, 2*max_steps, closest_cb, rand_state);
|
yading@10
|
344
|
yading@10
|
345 av_free(temp_points);
|
yading@10
|
346
|
yading@10
|
347 } else // If not, initialize the codebook with random positions
|
yading@10
|
348 for (i=0; i < numCB; i++)
|
yading@10
|
349 memcpy(codebook + i*dim, points + ((i*BIG_PRIME)%numpoints)*dim,
|
yading@10
|
350 dim*sizeof(int));
|
yading@10
|
351
|
yading@10
|
352 }
|
yading@10
|
353
|
yading@10
|
354 void ff_do_elbg(int *points, int dim, int numpoints, int *codebook,
|
yading@10
|
355 int numCB, int max_steps, int *closest_cb,
|
yading@10
|
356 AVLFG *rand_state)
|
yading@10
|
357 {
|
yading@10
|
358 int dist;
|
yading@10
|
359 elbg_data elbg_d;
|
yading@10
|
360 elbg_data *elbg = &elbg_d;
|
yading@10
|
361 int i, j, k, last_error, steps=0;
|
yading@10
|
362 int *dist_cb = av_malloc(numpoints*sizeof(int));
|
yading@10
|
363 int *size_part = av_malloc(numCB*sizeof(int));
|
yading@10
|
364 cell *list_buffer = av_malloc(numpoints*sizeof(cell));
|
yading@10
|
365 cell *free_cells;
|
yading@10
|
366 int best_dist, best_idx = 0;
|
yading@10
|
367
|
yading@10
|
368 elbg->error = INT_MAX;
|
yading@10
|
369 elbg->dim = dim;
|
yading@10
|
370 elbg->numCB = numCB;
|
yading@10
|
371 elbg->codebook = codebook;
|
yading@10
|
372 elbg->cells = av_malloc(numCB*sizeof(cell *));
|
yading@10
|
373 elbg->utility = av_malloc(numCB*sizeof(int));
|
yading@10
|
374 elbg->nearest_cb = closest_cb;
|
yading@10
|
375 elbg->points = points;
|
yading@10
|
376 elbg->utility_inc = av_malloc(numCB*sizeof(int));
|
yading@10
|
377 elbg->scratchbuf = av_malloc(5*dim*sizeof(int));
|
yading@10
|
378
|
yading@10
|
379 elbg->rand_state = rand_state;
|
yading@10
|
380
|
yading@10
|
381 do {
|
yading@10
|
382 free_cells = list_buffer;
|
yading@10
|
383 last_error = elbg->error;
|
yading@10
|
384 steps++;
|
yading@10
|
385 memset(elbg->utility, 0, numCB*sizeof(int));
|
yading@10
|
386 memset(elbg->cells, 0, numCB*sizeof(cell *));
|
yading@10
|
387
|
yading@10
|
388 elbg->error = 0;
|
yading@10
|
389
|
yading@10
|
390 /* This loop evaluate the actual Voronoi partition. It is the most
|
yading@10
|
391 costly part of the algorithm. */
|
yading@10
|
392 for (i=0; i < numpoints; i++) {
|
yading@10
|
393 best_dist = distance_limited(elbg->points + i*elbg->dim, elbg->codebook + best_idx*elbg->dim, dim, INT_MAX);
|
yading@10
|
394 for (k=0; k < elbg->numCB; k++) {
|
yading@10
|
395 dist = distance_limited(elbg->points + i*elbg->dim, elbg->codebook + k*elbg->dim, dim, best_dist);
|
yading@10
|
396 if (dist < best_dist) {
|
yading@10
|
397 best_dist = dist;
|
yading@10
|
398 best_idx = k;
|
yading@10
|
399 }
|
yading@10
|
400 }
|
yading@10
|
401 elbg->nearest_cb[i] = best_idx;
|
yading@10
|
402 dist_cb[i] = best_dist;
|
yading@10
|
403 elbg->error += dist_cb[i];
|
yading@10
|
404 elbg->utility[elbg->nearest_cb[i]] += dist_cb[i];
|
yading@10
|
405 free_cells->index = i;
|
yading@10
|
406 free_cells->next = elbg->cells[elbg->nearest_cb[i]];
|
yading@10
|
407 elbg->cells[elbg->nearest_cb[i]] = free_cells;
|
yading@10
|
408 free_cells++;
|
yading@10
|
409 }
|
yading@10
|
410
|
yading@10
|
411 do_shiftings(elbg);
|
yading@10
|
412
|
yading@10
|
413 memset(size_part, 0, numCB*sizeof(int));
|
yading@10
|
414
|
yading@10
|
415 memset(elbg->codebook, 0, elbg->numCB*dim*sizeof(int));
|
yading@10
|
416
|
yading@10
|
417 for (i=0; i < numpoints; i++) {
|
yading@10
|
418 size_part[elbg->nearest_cb[i]]++;
|
yading@10
|
419 for (j=0; j < elbg->dim; j++)
|
yading@10
|
420 elbg->codebook[elbg->nearest_cb[i]*elbg->dim + j] +=
|
yading@10
|
421 elbg->points[i*elbg->dim + j];
|
yading@10
|
422 }
|
yading@10
|
423
|
yading@10
|
424 for (i=0; i < elbg->numCB; i++)
|
yading@10
|
425 vect_division(elbg->codebook + i*elbg->dim,
|
yading@10
|
426 elbg->codebook + i*elbg->dim, size_part[i], elbg->dim);
|
yading@10
|
427
|
yading@10
|
428 } while(((last_error - elbg->error) > DELTA_ERR_MAX*elbg->error) &&
|
yading@10
|
429 (steps < max_steps));
|
yading@10
|
430
|
yading@10
|
431 av_free(dist_cb);
|
yading@10
|
432 av_free(size_part);
|
yading@10
|
433 av_free(elbg->utility);
|
yading@10
|
434 av_free(list_buffer);
|
yading@10
|
435 av_free(elbg->cells);
|
yading@10
|
436 av_free(elbg->utility_inc);
|
yading@10
|
437 av_free(elbg->scratchbuf);
|
yading@10
|
438 }
|