/src/trunk/xvidcore/src/encoder.c
Line | Count | Source (jump to first uncovered line) |
1 | | /***************************************************************************** |
2 | | * |
3 | | * XVID MPEG-4 VIDEO CODEC |
4 | | * - Encoder main module - |
5 | | * |
6 | | * Copyright(C) 2002-2010 Michael Militzer <isibaar@xvid.org> |
7 | | * 2002-2003 Peter Ross <pross@xvid.org> |
8 | | * 2002 Daniel Smith <danielsmith@astroboymail.com> |
9 | | * |
10 | | * This program is free software ; you can redistribute it and/or modify |
11 | | * it under the terms of the GNU General Public License as published by |
12 | | * the Free Software Foundation ; either version 2 of the License, or |
13 | | * (at your option) any later version. |
14 | | * |
15 | | * This program is distributed in the hope that it will be useful, |
16 | | * but WITHOUT ANY WARRANTY ; without even the implied warranty of |
17 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | | * GNU General Public License for more details. |
19 | | * |
20 | | * You should have received a copy of the GNU General Public License |
21 | | * along with this program ; if not, write to the Free Software |
22 | | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 | | * |
24 | | * $Id: encoder.c 2098 2014-11-25 23:13:32Z Isibaar $ |
25 | | * |
26 | | ****************************************************************************/ |
27 | | |
28 | | #include <stdlib.h> |
29 | | #include <stdio.h> |
30 | | #include <math.h> |
31 | | #include <string.h> |
32 | | |
33 | | #include "encoder.h" |
34 | | #include "prediction/mbprediction.h" |
35 | | #include "global.h" |
36 | | #include "utils/timer.h" |
37 | | #include "image/image.h" |
38 | | #include "image/font.h" |
39 | | #include "motion/sad.h" |
40 | | #include "motion/motion.h" |
41 | | #include "motion/gmc.h" |
42 | | |
43 | | #include "bitstream/cbp.h" |
44 | | #include "utils/mbfunctions.h" |
45 | | #include "bitstream/bitstream.h" |
46 | | #include "bitstream/mbcoding.h" |
47 | | #include "utils/emms.h" |
48 | | #include "bitstream/mbcoding.h" |
49 | | #include "quant/quant_matrix.h" |
50 | | #include "utils/mem_align.h" |
51 | | |
52 | | # include "motion/motion_smp.h" |
53 | | |
54 | | |
55 | | /***************************************************************************** |
56 | | * Local function prototypes |
57 | | ****************************************************************************/ |
58 | | |
59 | | static int FrameCodeI(Encoder * pEnc, |
60 | | Bitstream * bs); |
61 | | |
62 | | static int FrameCodeP(Encoder * pEnc, |
63 | | Bitstream * bs); |
64 | | |
65 | | static void FrameCodeB(Encoder * pEnc, |
66 | | FRAMEINFO * frame, |
67 | | Bitstream * bs); |
68 | | |
69 | | |
70 | | /***************************************************************************** |
71 | | * Encoder creation |
72 | | * |
73 | | * This function creates an Encoder instance, it allocates all necessary |
74 | | * image buffers (reference, current and bframes) and initialize the internal |
75 | | * xvid encoder paremeters according to the XVID_ENC_PARAM input parameter. |
76 | | * |
77 | | * The code seems to be very long but is very basic, mainly memory allocation |
78 | | * and cleaning code. |
79 | | * |
80 | | * Returned values : |
81 | | * - 0 - no errors |
82 | | * - XVID_ERR_MEMORY - the libc could not allocate memory, the function |
83 | | * cleans the structure before exiting. |
84 | | * pParam->handle is also set to NULL. |
85 | | * |
86 | | ****************************************************************************/ |
87 | | |
88 | | /* |
89 | | * Simplify the "fincr/fbase" fraction |
90 | | */ |
91 | | static int |
92 | | gcd(int a, int b) |
93 | 0 | { |
94 | 0 | int r ; |
95 | |
|
96 | 0 | if (b > a) { |
97 | 0 | r = a; |
98 | 0 | a = b; |
99 | 0 | b = r; |
100 | 0 | } |
101 | |
|
102 | 0 | while ((r = a % b)) { |
103 | 0 | a = b; |
104 | 0 | b = r; |
105 | 0 | } |
106 | 0 | return b; |
107 | 0 | } |
108 | | |
109 | | static void |
110 | | simplify_time(int *inc, int *base) |
111 | 0 | { |
112 | | /* common factor */ |
113 | 0 | const int s = gcd(*inc, *base); |
114 | 0 | *inc /= s; |
115 | 0 | *base /= s; |
116 | |
|
117 | 0 | if (*base > 65535 || *inc > 65535) { |
118 | 0 | int *biggest; |
119 | 0 | int *other; |
120 | 0 | float div; |
121 | |
|
122 | 0 | if (*base > *inc) { |
123 | 0 | biggest = base; |
124 | 0 | other = inc; |
125 | 0 | } else { |
126 | 0 | biggest = inc; |
127 | 0 | other = base; |
128 | 0 | } |
129 | | |
130 | 0 | div = ((float)*biggest)/((float)65535); |
131 | 0 | *biggest = (unsigned int)(((float)*biggest)/div); |
132 | 0 | *other = (unsigned int)(((float)*other)/div); |
133 | 0 | } |
134 | 0 | } |
135 | | |
136 | | |
137 | | int |
138 | | enc_create(xvid_enc_create_t * create) |
139 | 0 | { |
140 | 0 | Encoder *pEnc; |
141 | 0 | int n; |
142 | |
|
143 | 0 | if (XVID_VERSION_MAJOR(create->version) != 1) /* v1.x.x */ |
144 | 0 | return XVID_ERR_VERSION; |
145 | | |
146 | 0 | if (create->width%2 || create->height%2) |
147 | 0 | return XVID_ERR_FAIL; |
148 | | |
149 | 0 | if (create->width<=0 || create->height<=0) |
150 | 0 | return XVID_ERR_FAIL; |
151 | | |
152 | | /* allocate encoder struct */ |
153 | | |
154 | 0 | pEnc = (Encoder *) xvid_malloc(sizeof(Encoder), CACHE_LINE); |
155 | 0 | if (pEnc == NULL) |
156 | 0 | return XVID_ERR_MEMORY; |
157 | 0 | memset(pEnc, 0, sizeof(Encoder)); |
158 | |
|
159 | 0 | pEnc->mbParam.profile = create->profile; |
160 | | |
161 | | /* global flags */ |
162 | 0 | pEnc->mbParam.global_flags = create->global; |
163 | 0 | if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED)) |
164 | 0 | pEnc->mbParam.global_flags |= XVID_GLOBAL_DIVX5_USERDATA; |
165 | | |
166 | | /* width, height */ |
167 | 0 | pEnc->mbParam.width = create->width; |
168 | 0 | pEnc->mbParam.height = create->height; |
169 | 0 | pEnc->mbParam.mb_width = (pEnc->mbParam.width + 15) / 16; |
170 | 0 | pEnc->mbParam.mb_height = (pEnc->mbParam.height + 15) / 16; |
171 | 0 | pEnc->mbParam.edged_width = 16 * pEnc->mbParam.mb_width + 2 * EDGE_SIZE; |
172 | 0 | pEnc->mbParam.edged_height = 16 * pEnc->mbParam.mb_height + 2 * EDGE_SIZE; |
173 | | |
174 | | /* framerate */ |
175 | 0 | pEnc->mbParam.fincr = MAX(create->fincr, 0); |
176 | 0 | pEnc->mbParam.fbase = create->fincr <= 0 ? 25 : create->fbase; |
177 | 0 | if (pEnc->mbParam.fincr>0) |
178 | 0 | simplify_time((int*)&pEnc->mbParam.fincr, (int*)&pEnc->mbParam.fbase); |
179 | | |
180 | | /* zones */ |
181 | 0 | if(create->num_zones > 0) { |
182 | 0 | pEnc->num_zones = create->num_zones; |
183 | 0 | pEnc->zones = xvid_malloc(sizeof(xvid_enc_zone_t) * pEnc->num_zones, CACHE_LINE); |
184 | 0 | if (pEnc->zones == NULL) |
185 | 0 | goto xvid_err_memory0; |
186 | 0 | memcpy(pEnc->zones, create->zones, sizeof(xvid_enc_zone_t) * pEnc->num_zones); |
187 | 0 | } else { |
188 | 0 | pEnc->num_zones = 0; |
189 | 0 | pEnc->zones = NULL; |
190 | 0 | } |
191 | | |
192 | | /* plugins */ |
193 | 0 | if(create->num_plugins > 0) { |
194 | 0 | pEnc->num_plugins = create->num_plugins; |
195 | 0 | pEnc->plugins = xvid_malloc(sizeof(xvid_enc_plugin_t) * pEnc->num_plugins, CACHE_LINE); |
196 | 0 | if (pEnc->plugins == NULL) |
197 | 0 | goto xvid_err_memory0; |
198 | 0 | } else { |
199 | 0 | pEnc->num_plugins = 0; |
200 | 0 | pEnc->plugins = NULL; |
201 | 0 | } |
202 | | |
203 | 0 | for (n=0; n<pEnc->num_plugins;n++) { |
204 | 0 | xvid_plg_create_t pcreate; |
205 | 0 | xvid_plg_info_t pinfo; |
206 | |
|
207 | 0 | memset(&pinfo, 0, sizeof(xvid_plg_info_t)); |
208 | 0 | pinfo.version = XVID_VERSION; |
209 | 0 | if (create->plugins[n].func(NULL, XVID_PLG_INFO, &pinfo, NULL) >= 0) { |
210 | 0 | pEnc->mbParam.plugin_flags |= pinfo.flags; |
211 | 0 | } |
212 | |
|
213 | 0 | memset(&pcreate, 0, sizeof(xvid_plg_create_t)); |
214 | 0 | pcreate.version = XVID_VERSION; |
215 | 0 | pcreate.num_zones = pEnc->num_zones; |
216 | 0 | pcreate.zones = pEnc->zones; |
217 | 0 | pcreate.width = pEnc->mbParam.width; |
218 | 0 | pcreate.height = pEnc->mbParam.height; |
219 | 0 | pcreate.mb_width = pEnc->mbParam.mb_width; |
220 | 0 | pcreate.mb_height = pEnc->mbParam.mb_height; |
221 | 0 | pcreate.fincr = pEnc->mbParam.fincr; |
222 | 0 | pcreate.fbase = pEnc->mbParam.fbase; |
223 | 0 | pcreate.param = create->plugins[n].param; |
224 | |
|
225 | 0 | pEnc->plugins[n].func = NULL; /* disable plugins that fail */ |
226 | 0 | if (create->plugins[n].func(NULL, XVID_PLG_CREATE, &pcreate, &pEnc->plugins[n].param) >= 0) { |
227 | 0 | pEnc->plugins[n].func = create->plugins[n].func; |
228 | 0 | } |
229 | 0 | } |
230 | |
|
231 | 0 | if ((pEnc->mbParam.global_flags & XVID_GLOBAL_EXTRASTATS_ENABLE) || |
232 | 0 | (pEnc->mbParam.plugin_flags & XVID_REQPSNR)) { |
233 | 0 | pEnc->mbParam.plugin_flags |= XVID_REQORIGINAL; /* psnr calculation requires the original */ |
234 | 0 | } |
235 | | |
236 | | /* temp dquants */ |
237 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { |
238 | 0 | pEnc->temp_dquants = (int *) xvid_malloc(pEnc->mbParam.mb_width * |
239 | 0 | pEnc->mbParam.mb_height * sizeof(int), CACHE_LINE); |
240 | 0 | if (pEnc->temp_dquants==NULL) |
241 | 0 | goto xvid_err_memory1a; |
242 | 0 | } |
243 | | |
244 | | /* temp lambdas */ |
245 | 0 | if (pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) { |
246 | 0 | pEnc->temp_lambda = (float *) xvid_malloc(pEnc->mbParam.mb_width * |
247 | 0 | pEnc->mbParam.mb_height * 6 * sizeof(float), CACHE_LINE); |
248 | 0 | if (pEnc->temp_lambda == NULL) |
249 | 0 | goto xvid_err_memory1a; |
250 | 0 | } |
251 | | |
252 | | /* bframes */ |
253 | 0 | pEnc->mbParam.max_bframes = MAX(create->max_bframes, 0); |
254 | 0 | pEnc->mbParam.bquant_ratio = MAX(create->bquant_ratio, 0); |
255 | 0 | pEnc->mbParam.bquant_offset = create->bquant_offset; |
256 | | |
257 | | /* min/max quant */ |
258 | 0 | for (n=0; n<3; n++) { |
259 | 0 | pEnc->mbParam.min_quant[n] = create->min_quant[n] > 0 ? create->min_quant[n] : 2; |
260 | 0 | pEnc->mbParam.max_quant[n] = create->max_quant[n] > 0 ? create->max_quant[n] : 31; |
261 | 0 | } |
262 | | |
263 | | /* frame drop ratio */ |
264 | 0 | pEnc->mbParam.frame_drop_ratio = MAX(create->frame_drop_ratio, 0); |
265 | | |
266 | | /* max keyframe interval */ |
267 | 0 | pEnc->mbParam.iMaxKeyInterval = create->max_key_interval <= 0 ? (10 * (int)pEnc->mbParam.fbase) / (int)pEnc->mbParam.fincr : create->max_key_interval; |
268 | | |
269 | | /* allocate working frame-image memory */ |
270 | |
|
271 | 0 | pEnc->current = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE); |
272 | 0 | pEnc->reference = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE); |
273 | |
|
274 | 0 | if (pEnc->current == NULL || pEnc->reference == NULL) |
275 | 0 | goto xvid_err_memory1; |
276 | | |
277 | | /* allocate macroblock memory */ |
278 | | |
279 | 0 | pEnc->current->mbs = |
280 | 0 | xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width * |
281 | 0 | pEnc->mbParam.mb_height, CACHE_LINE); |
282 | 0 | pEnc->reference->mbs = |
283 | 0 | xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width * |
284 | 0 | pEnc->mbParam.mb_height, CACHE_LINE); |
285 | |
|
286 | 0 | if (pEnc->current->mbs == NULL || pEnc->reference->mbs == NULL) |
287 | 0 | goto xvid_err_memory2; |
288 | | |
289 | | /* allocate quant matrix memory */ |
290 | | |
291 | 0 | pEnc->mbParam.mpeg_quant_matrices = |
292 | 0 | xvid_malloc(sizeof(uint16_t) * 64 * 8, CACHE_LINE); |
293 | |
|
294 | 0 | if (pEnc->mbParam.mpeg_quant_matrices == NULL) |
295 | 0 | goto xvid_err_memory2a; |
296 | | |
297 | | /* allocate interpolation image memory */ |
298 | | |
299 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { |
300 | 0 | image_null(&pEnc->sOriginal); |
301 | 0 | image_null(&pEnc->sOriginal2); |
302 | 0 | } |
303 | |
|
304 | 0 | image_null(&pEnc->f_refh); |
305 | 0 | image_null(&pEnc->f_refv); |
306 | 0 | image_null(&pEnc->f_refhv); |
307 | |
|
308 | 0 | image_null(&pEnc->current->image); |
309 | 0 | image_null(&pEnc->reference->image); |
310 | 0 | image_null(&pEnc->vInterH); |
311 | 0 | image_null(&pEnc->vInterV); |
312 | 0 | image_null(&pEnc->vInterHV); |
313 | |
|
314 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { |
315 | 0 | if (image_create |
316 | 0 | (&pEnc->sOriginal, pEnc->mbParam.edged_width, |
317 | 0 | pEnc->mbParam.edged_height) < 0) |
318 | 0 | goto xvid_err_memory3; |
319 | | |
320 | 0 | if (image_create |
321 | 0 | (&pEnc->sOriginal2, pEnc->mbParam.edged_width, |
322 | 0 | pEnc->mbParam.edged_height) < 0) |
323 | 0 | goto xvid_err_memory3; |
324 | 0 | } |
325 | | |
326 | 0 | if (image_create |
327 | 0 | (&pEnc->f_refh, pEnc->mbParam.edged_width, |
328 | 0 | pEnc->mbParam.edged_height) < 0) |
329 | 0 | goto xvid_err_memory3; |
330 | 0 | if (image_create |
331 | 0 | (&pEnc->f_refv, pEnc->mbParam.edged_width, |
332 | 0 | pEnc->mbParam.edged_height) < 0) |
333 | 0 | goto xvid_err_memory3; |
334 | 0 | if (image_create |
335 | 0 | (&pEnc->f_refhv, pEnc->mbParam.edged_width, |
336 | 0 | pEnc->mbParam.edged_height) < 0) |
337 | 0 | goto xvid_err_memory3; |
338 | | |
339 | 0 | if (image_create |
340 | 0 | (&pEnc->current->image, pEnc->mbParam.edged_width, |
341 | 0 | pEnc->mbParam.edged_height) < 0) |
342 | 0 | goto xvid_err_memory3; |
343 | 0 | if (image_create |
344 | 0 | (&pEnc->reference->image, pEnc->mbParam.edged_width, |
345 | 0 | pEnc->mbParam.edged_height) < 0) |
346 | 0 | goto xvid_err_memory3; |
347 | 0 | if (image_create |
348 | 0 | (&pEnc->vInterH, pEnc->mbParam.edged_width, |
349 | 0 | pEnc->mbParam.edged_height) < 0) |
350 | 0 | goto xvid_err_memory3; |
351 | 0 | if (image_create |
352 | 0 | (&pEnc->vInterV, pEnc->mbParam.edged_width, |
353 | 0 | pEnc->mbParam.edged_height) < 0) |
354 | 0 | goto xvid_err_memory3; |
355 | 0 | if (image_create |
356 | 0 | (&pEnc->vInterHV, pEnc->mbParam.edged_width, |
357 | 0 | pEnc->mbParam.edged_height) < 0) |
358 | 0 | goto xvid_err_memory3; |
359 | | |
360 | | /* Create full bitplane for GMC, this might be wasteful */ |
361 | 0 | if (image_create |
362 | 0 | (&pEnc->vGMC, pEnc->mbParam.edged_width, |
363 | 0 | pEnc->mbParam.edged_height) < 0) |
364 | 0 | goto xvid_err_memory3; |
365 | | |
366 | | /* init bframe image buffers */ |
367 | | |
368 | 0 | pEnc->bframenum_head = 0; |
369 | 0 | pEnc->bframenum_tail = 0; |
370 | 0 | pEnc->flush_bframes = 0; |
371 | 0 | pEnc->closed_bframenum = -1; |
372 | | |
373 | | /* B Frames specific init */ |
374 | 0 | pEnc->bframes = NULL; |
375 | |
|
376 | 0 | if (pEnc->mbParam.max_bframes > 0) { |
377 | |
|
378 | 0 | pEnc->bframes = |
379 | 0 | xvid_malloc(pEnc->mbParam.max_bframes * sizeof(FRAMEINFO *), |
380 | 0 | CACHE_LINE); |
381 | |
|
382 | 0 | if (pEnc->bframes == NULL) |
383 | 0 | goto xvid_err_memory3; |
384 | | |
385 | 0 | for (n = 0; n < pEnc->mbParam.max_bframes; n++) |
386 | 0 | pEnc->bframes[n] = NULL; |
387 | | |
388 | |
|
389 | 0 | for (n = 0; n < pEnc->mbParam.max_bframes; n++) { |
390 | 0 | pEnc->bframes[n] = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE); |
391 | |
|
392 | 0 | if (pEnc->bframes[n] == NULL) |
393 | 0 | goto xvid_err_memory4; |
394 | | |
395 | 0 | pEnc->bframes[n]->mbs = |
396 | 0 | xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width * |
397 | 0 | pEnc->mbParam.mb_height, CACHE_LINE); |
398 | |
|
399 | 0 | if (pEnc->bframes[n]->mbs == NULL) |
400 | 0 | goto xvid_err_memory4; |
401 | | |
402 | 0 | image_null(&pEnc->bframes[n]->image); |
403 | |
|
404 | 0 | if (image_create |
405 | 0 | (&pEnc->bframes[n]->image, pEnc->mbParam.edged_width, |
406 | 0 | pEnc->mbParam.edged_height) < 0) |
407 | 0 | goto xvid_err_memory4; |
408 | |
|
409 | 0 | } |
410 | 0 | } |
411 | | |
412 | | /* init incoming frame queue */ |
413 | 0 | pEnc->queue_head = 0; |
414 | 0 | pEnc->queue_tail = 0; |
415 | 0 | pEnc->queue_size = 0; |
416 | |
|
417 | 0 | pEnc->queue = |
418 | 0 | xvid_malloc((pEnc->mbParam.max_bframes+1) * sizeof(QUEUEINFO), |
419 | 0 | CACHE_LINE); |
420 | |
|
421 | 0 | if (pEnc->queue == NULL) |
422 | 0 | goto xvid_err_memory4; |
423 | | |
424 | 0 | for (n = 0; n < pEnc->mbParam.max_bframes+1; n++) |
425 | 0 | image_null(&pEnc->queue[n].image); |
426 | | |
427 | |
|
428 | 0 | for (n = 0; n < pEnc->mbParam.max_bframes+1; n++) { |
429 | 0 | if (image_create |
430 | 0 | (&pEnc->queue[n].image, pEnc->mbParam.edged_width, |
431 | 0 | pEnc->mbParam.edged_height) < 0) |
432 | 0 | goto xvid_err_memory5; |
433 | 0 | } |
434 | | |
435 | | /* timestamp stuff */ |
436 | | |
437 | 0 | pEnc->mbParam.m_stamp = 0; |
438 | 0 | pEnc->m_framenum = create->start_frame_num; |
439 | 0 | pEnc->current->stamp = 0; |
440 | 0 | pEnc->reference->stamp = 0; |
441 | | |
442 | | /* other stuff */ |
443 | |
|
444 | 0 | pEnc->iFrameNum = 0; |
445 | 0 | pEnc->fMvPrevSigma = -1; |
446 | | |
447 | | /* slices */ |
448 | 0 | pEnc->num_slices = MIN(MAX(1, create->num_slices), (int) pEnc->mbParam.mb_height); |
449 | | |
450 | | /* multithreaded stuff */ |
451 | 0 | if (create->num_threads > 0) { |
452 | | #ifndef HAVE_PTHREAD |
453 | | int t = MAX(1, create->num_threads); |
454 | | #else |
455 | 0 | int t = MAX(1, MIN(create->num_threads, (int) (pEnc->mbParam.mb_height>>1))); /* at least two rows per thread */ |
456 | 0 | #endif |
457 | 0 | int threads_per_slice = MAX(1, (t / pEnc->num_slices)); |
458 | 0 | int rows_per_thread = (pEnc->mbParam.mb_height + threads_per_slice - 1) / threads_per_slice; |
459 | |
|
460 | 0 | pEnc->num_threads = t; |
461 | 0 | pEnc->smpData = xvid_malloc(t*sizeof(SMPData), CACHE_LINE); |
462 | 0 | if (!pEnc->smpData) |
463 | 0 | goto xvid_err_nosmp; |
464 | | |
465 | | /* tmp bitstream buffer for slice coding */ |
466 | 0 | pEnc->smpData[0].tmp_buffer = xvid_malloc(16*pEnc->mbParam.edged_width*pEnc->mbParam.mb_height*sizeof(uint8_t), CACHE_LINE); |
467 | 0 | if (! pEnc->smpData[0].tmp_buffer) goto xvid_err_nosmp; |
468 | | |
469 | 0 | for (n = 0; n < t; n++) { |
470 | 0 | int s = MIN(pEnc->num_threads, pEnc->num_slices); |
471 | |
|
472 | 0 | pEnc->smpData[n].complete_count_self = |
473 | 0 | xvid_malloc(rows_per_thread * sizeof(int), CACHE_LINE); |
474 | |
|
475 | 0 | if (!pEnc->smpData[n].complete_count_self) |
476 | 0 | goto xvid_err_nosmp; |
477 | | |
478 | 0 | if (n > 0 && n < s) { |
479 | 0 | pEnc->smpData[n].bs = (Bitstream *) xvid_malloc(sizeof(Bitstream), CACHE_LINE); |
480 | 0 | if (!pEnc->smpData[n].bs) |
481 | 0 | goto xvid_err_nosmp; |
482 | | |
483 | 0 | pEnc->smpData[n].sStat = (Statistics *) xvid_malloc(sizeof(Statistics), CACHE_LINE); |
484 | 0 | if (!pEnc->smpData[n].sStat) |
485 | 0 | goto xvid_err_nosmp; |
486 | | |
487 | 0 | pEnc->smpData[n].tmp_buffer = pEnc->smpData[0].tmp_buffer + 16*(((n-1)*pEnc->mbParam.edged_width*pEnc->mbParam.mb_height)/s); |
488 | 0 | BitstreamInit(pEnc->smpData[n].bs, pEnc->smpData[n].tmp_buffer, 0); |
489 | 0 | } |
490 | | |
491 | 0 | if (n != 0) |
492 | 0 | pEnc->smpData[n].complete_count_above = |
493 | 0 | pEnc->smpData[n-1].complete_count_self; |
494 | 0 | } |
495 | 0 | pEnc->smpData[0].complete_count_above = |
496 | 0 | pEnc->smpData[t-1].complete_count_self - 1; |
497 | |
|
498 | 0 | } else { |
499 | 0 | xvid_err_nosmp: |
500 | | /* no SMP */ |
501 | 0 | if (pEnc->smpData) { |
502 | 0 | if (pEnc->smpData[0].tmp_buffer) |
503 | 0 | xvid_free(pEnc->smpData[0].tmp_buffer); |
504 | 0 | } |
505 | 0 | else { |
506 | 0 | pEnc->smpData = xvid_malloc(1*sizeof(SMPData), CACHE_LINE); |
507 | 0 | if (pEnc->smpData == NULL) |
508 | 0 | goto xvid_err_memory5; |
509 | 0 | } |
510 | | |
511 | 0 | create->num_threads = 0; |
512 | 0 | } |
513 | | |
514 | 0 | create->handle = (void *) pEnc; |
515 | |
|
516 | 0 | init_timer(); |
517 | 0 | init_mpeg_matrix(pEnc->mbParam.mpeg_quant_matrices); |
518 | |
|
519 | 0 | return 0; /* ok */ |
520 | | |
521 | | /* |
522 | | * We handle all XVID_ERR_MEMORY here, this makes the code lighter |
523 | | */ |
524 | | |
525 | 0 | xvid_err_memory5: |
526 | |
|
527 | 0 | for (n = 0; n < pEnc->mbParam.max_bframes+1; n++) { |
528 | 0 | image_destroy(&pEnc->queue[n].image, pEnc->mbParam.edged_width, |
529 | 0 | pEnc->mbParam.edged_height); |
530 | 0 | } |
531 | |
|
532 | 0 | xvid_free(pEnc->queue); |
533 | |
|
534 | 0 | xvid_err_memory4: |
535 | |
|
536 | 0 | if (pEnc->mbParam.max_bframes > 0) { |
537 | 0 | int i; |
538 | |
|
539 | 0 | for (i = 0; i < pEnc->mbParam.max_bframes; i++) { |
540 | |
|
541 | 0 | if (pEnc->bframes[i] == NULL) |
542 | 0 | continue; |
543 | | |
544 | 0 | image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width, |
545 | 0 | pEnc->mbParam.edged_height); |
546 | 0 | xvid_free(pEnc->bframes[i]->mbs); |
547 | 0 | xvid_free(pEnc->bframes[i]); |
548 | 0 | } |
549 | |
|
550 | 0 | xvid_free(pEnc->bframes); |
551 | 0 | } |
552 | |
|
553 | 0 | xvid_err_memory3: |
554 | |
|
555 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { |
556 | 0 | image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width, |
557 | 0 | pEnc->mbParam.edged_height); |
558 | 0 | image_destroy(&pEnc->sOriginal2, pEnc->mbParam.edged_width, |
559 | 0 | pEnc->mbParam.edged_height); |
560 | 0 | } |
561 | |
|
562 | 0 | image_destroy(&pEnc->f_refh, pEnc->mbParam.edged_width, |
563 | 0 | pEnc->mbParam.edged_height); |
564 | 0 | image_destroy(&pEnc->f_refv, pEnc->mbParam.edged_width, |
565 | 0 | pEnc->mbParam.edged_height); |
566 | 0 | image_destroy(&pEnc->f_refhv, pEnc->mbParam.edged_width, |
567 | 0 | pEnc->mbParam.edged_height); |
568 | |
|
569 | 0 | image_destroy(&pEnc->current->image, pEnc->mbParam.edged_width, |
570 | 0 | pEnc->mbParam.edged_height); |
571 | 0 | image_destroy(&pEnc->reference->image, pEnc->mbParam.edged_width, |
572 | 0 | pEnc->mbParam.edged_height); |
573 | 0 | image_destroy(&pEnc->vInterH, pEnc->mbParam.edged_width, |
574 | 0 | pEnc->mbParam.edged_height); |
575 | 0 | image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width, |
576 | 0 | pEnc->mbParam.edged_height); |
577 | 0 | image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width, |
578 | 0 | pEnc->mbParam.edged_height); |
579 | | |
580 | | /* destroy GMC image */ |
581 | 0 | image_destroy(&pEnc->vGMC, pEnc->mbParam.edged_width, |
582 | 0 | pEnc->mbParam.edged_height); |
583 | |
|
584 | 0 | xvid_err_memory2a: |
585 | 0 | xvid_free(pEnc->mbParam.mpeg_quant_matrices); |
586 | |
|
587 | 0 | xvid_err_memory2: |
588 | 0 | xvid_free(pEnc->current->mbs); |
589 | 0 | xvid_free(pEnc->reference->mbs); |
590 | |
|
591 | 0 | xvid_err_memory1: |
592 | 0 | xvid_free(pEnc->current); |
593 | 0 | xvid_free(pEnc->reference); |
594 | |
|
595 | 0 | xvid_err_memory1a: |
596 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { |
597 | 0 | xvid_free(pEnc->temp_dquants); |
598 | 0 | } |
599 | |
|
600 | 0 | if(pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) { |
601 | 0 | xvid_free(pEnc->temp_lambda); |
602 | 0 | } |
603 | |
|
604 | 0 | xvid_err_memory0: |
605 | 0 | for (n=0; n<pEnc->num_plugins;n++) { |
606 | 0 | if (pEnc->plugins[n].func) { |
607 | 0 | pEnc->plugins[n].func(pEnc->plugins[n].param, XVID_PLG_DESTROY, NULL, NULL); |
608 | 0 | } |
609 | 0 | } |
610 | 0 | xvid_free(pEnc->plugins); |
611 | |
|
612 | 0 | xvid_free(pEnc->zones); |
613 | |
|
614 | 0 | xvid_free(pEnc); |
615 | |
|
616 | 0 | create->handle = NULL; |
617 | |
|
618 | 0 | return XVID_ERR_MEMORY; |
619 | 0 | } |
620 | | |
621 | | /***************************************************************************** |
622 | | * Encoder destruction |
623 | | * |
624 | | * This function destroy the entire encoder structure created by a previous |
625 | | * successful enc_create call. |
626 | | * |
627 | | * Returned values (for now only one returned value) : |
628 | | * - 0 - no errors |
629 | | * |
630 | | ****************************************************************************/ |
631 | | |
632 | | int |
633 | | enc_destroy(Encoder * pEnc) |
634 | 0 | { |
635 | 0 | int i; |
636 | | |
637 | | /* B Frames specific */ |
638 | 0 | for (i = 0; i < pEnc->mbParam.max_bframes+1; i++) { |
639 | 0 | image_destroy(&pEnc->queue[i].image, pEnc->mbParam.edged_width, |
640 | 0 | pEnc->mbParam.edged_height); |
641 | 0 | } |
642 | |
|
643 | 0 | xvid_free(pEnc->queue); |
644 | |
|
645 | 0 | if (pEnc->mbParam.max_bframes > 0) { |
646 | |
|
647 | 0 | for (i = 0; i < pEnc->mbParam.max_bframes; i++) { |
648 | |
|
649 | 0 | if (pEnc->bframes[i] == NULL) |
650 | 0 | continue; |
651 | | |
652 | 0 | image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width, |
653 | 0 | pEnc->mbParam.edged_height); |
654 | 0 | xvid_free(pEnc->bframes[i]->mbs); |
655 | 0 | xvid_free(pEnc->bframes[i]); |
656 | 0 | } |
657 | |
|
658 | 0 | xvid_free(pEnc->bframes); |
659 | |
|
660 | 0 | } |
661 | | |
662 | | /* All images, reference, current etc ... */ |
663 | |
|
664 | 0 | image_destroy(&pEnc->current->image, pEnc->mbParam.edged_width, |
665 | 0 | pEnc->mbParam.edged_height); |
666 | 0 | image_destroy(&pEnc->reference->image, pEnc->mbParam.edged_width, |
667 | 0 | pEnc->mbParam.edged_height); |
668 | 0 | image_destroy(&pEnc->vInterH, pEnc->mbParam.edged_width, |
669 | 0 | pEnc->mbParam.edged_height); |
670 | 0 | image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width, |
671 | 0 | pEnc->mbParam.edged_height); |
672 | 0 | image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width, |
673 | 0 | pEnc->mbParam.edged_height); |
674 | 0 | image_destroy(&pEnc->f_refh, pEnc->mbParam.edged_width, |
675 | 0 | pEnc->mbParam.edged_height); |
676 | 0 | image_destroy(&pEnc->f_refv, pEnc->mbParam.edged_width, |
677 | 0 | pEnc->mbParam.edged_height); |
678 | 0 | image_destroy(&pEnc->f_refhv, pEnc->mbParam.edged_width, |
679 | 0 | pEnc->mbParam.edged_height); |
680 | 0 | image_destroy(&pEnc->vGMC, pEnc->mbParam.edged_width, |
681 | 0 | pEnc->mbParam.edged_height); |
682 | |
|
683 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { |
684 | 0 | image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width, |
685 | 0 | pEnc->mbParam.edged_height); |
686 | 0 | image_destroy(&pEnc->sOriginal2, pEnc->mbParam.edged_width, |
687 | 0 | pEnc->mbParam.edged_height); |
688 | 0 | } |
689 | | |
690 | | /* Encoder structure */ |
691 | |
|
692 | 0 | xvid_free(pEnc->current->mbs); |
693 | 0 | xvid_free(pEnc->current); |
694 | |
|
695 | 0 | xvid_free(pEnc->reference->mbs); |
696 | 0 | xvid_free(pEnc->reference); |
697 | |
|
698 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { |
699 | 0 | xvid_free(pEnc->temp_dquants); |
700 | 0 | } |
701 | |
|
702 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQLAMBDA)) { |
703 | 0 | xvid_free(pEnc->temp_lambda); |
704 | 0 | } |
705 | |
|
706 | 0 | if (pEnc->num_plugins>0) { |
707 | 0 | xvid_plg_destroy_t pdestroy; |
708 | 0 | memset(&pdestroy, 0, sizeof(xvid_plg_destroy_t)); |
709 | |
|
710 | 0 | pdestroy.version = XVID_VERSION; |
711 | 0 | pdestroy.num_frames = pEnc->m_framenum; |
712 | |
|
713 | 0 | for (i=0; i<pEnc->num_plugins;i++) { |
714 | 0 | if (pEnc->plugins[i].func) { |
715 | 0 | pEnc->plugins[i].func(pEnc->plugins[i].param, XVID_PLG_DESTROY, &pdestroy, NULL); |
716 | 0 | } |
717 | 0 | } |
718 | 0 | xvid_free(pEnc->plugins); |
719 | 0 | } |
720 | |
|
721 | 0 | xvid_free(pEnc->mbParam.mpeg_quant_matrices); |
722 | |
|
723 | 0 | if (pEnc->num_zones > 0) |
724 | 0 | xvid_free(pEnc->zones); |
725 | |
|
726 | 0 | if (pEnc->num_threads > 0) { |
727 | 0 | for (i = 1; i < MAX(1, MIN(pEnc->num_threads, pEnc->num_slices)); i++) { |
728 | 0 | xvid_free(pEnc->smpData[i].bs); |
729 | 0 | xvid_free(pEnc->smpData[i].sStat); |
730 | 0 | } |
731 | 0 | if (pEnc->smpData[0].tmp_buffer) xvid_free(pEnc->smpData[0].tmp_buffer); |
732 | |
|
733 | 0 | for (i = 0; i < pEnc->num_threads; i++) |
734 | 0 | xvid_free(pEnc->smpData[i].complete_count_self); |
735 | 0 | } |
736 | 0 | xvid_free(pEnc->smpData); |
737 | |
|
738 | 0 | xvid_free(pEnc); |
739 | |
|
740 | 0 | return 0; /* ok */ |
741 | 0 | } |
742 | | |
743 | | |
744 | | /* |
745 | | call the plugins |
746 | | */ |
747 | | |
748 | | static void call_plugins(Encoder * pEnc, FRAMEINFO * frame, IMAGE * original, |
749 | | int opt, int * type, int * quant, xvid_enc_stats_t * stats) |
750 | 0 | { |
751 | 0 | unsigned int i, j, k; |
752 | 0 | xvid_plg_data_t data; |
753 | | |
754 | | /* set data struct */ |
755 | |
|
756 | 0 | memset(&data, 0, sizeof(xvid_plg_data_t)); |
757 | 0 | data.version = XVID_VERSION; |
758 | | |
759 | | /* find zone */ |
760 | 0 | for(i=0; i<pEnc->num_zones && pEnc->zones[i].frame<=frame->frame_num; i++) ; |
761 | 0 | data.zone = i>0 ? &pEnc->zones[i-1] : NULL; |
762 | |
|
763 | 0 | data.width = pEnc->mbParam.width; |
764 | 0 | data.height = pEnc->mbParam.height; |
765 | 0 | data.mb_width = pEnc->mbParam.mb_width; |
766 | 0 | data.mb_height = pEnc->mbParam.mb_height; |
767 | 0 | data.fincr = frame->fincr; |
768 | 0 | data.fbase = pEnc->mbParam.fbase; |
769 | 0 | data.bquant_ratio = pEnc->mbParam.bquant_ratio; |
770 | 0 | data.bquant_offset = pEnc->mbParam.bquant_offset; |
771 | |
|
772 | 0 | for (i=0; i<3; i++) { |
773 | 0 | data.min_quant[i] = pEnc->mbParam.min_quant[i]; |
774 | 0 | data.max_quant[i] = pEnc->mbParam.max_quant[i]; |
775 | 0 | } |
776 | |
|
777 | 0 | data.reference.csp = XVID_CSP_PLANAR; |
778 | 0 | data.reference.plane[0] = pEnc->reference->image.y; |
779 | 0 | data.reference.plane[1] = pEnc->reference->image.u; |
780 | 0 | data.reference.plane[2] = pEnc->reference->image.v; |
781 | 0 | data.reference.stride[0] = pEnc->mbParam.edged_width; |
782 | 0 | data.reference.stride[1] = pEnc->mbParam.edged_width/2; |
783 | 0 | data.reference.stride[2] = pEnc->mbParam.edged_width/2; |
784 | |
|
785 | 0 | data.current.csp = XVID_CSP_PLANAR; |
786 | 0 | data.current.plane[0] = frame->image.y; |
787 | 0 | data.current.plane[1] = frame->image.u; |
788 | 0 | data.current.plane[2] = frame->image.v; |
789 | 0 | data.current.stride[0] = pEnc->mbParam.edged_width; |
790 | 0 | data.current.stride[1] = pEnc->mbParam.edged_width/2; |
791 | 0 | data.current.stride[2] = pEnc->mbParam.edged_width/2; |
792 | |
|
793 | 0 | data.frame_num = frame->frame_num; |
794 | |
|
795 | 0 | if (opt == XVID_PLG_BEFORE) { |
796 | 0 | data.type = *type; |
797 | 0 | data.quant = *quant; |
798 | |
|
799 | 0 | data.vol_flags = frame->vol_flags; |
800 | 0 | data.vop_flags = frame->vop_flags; |
801 | 0 | data.motion_flags = frame->motion_flags; |
802 | |
|
803 | 0 | } else if (opt == XVID_PLG_FRAME) { |
804 | 0 | data.type = coding2type(frame->coding_type); |
805 | 0 | data.quant = frame->quant; |
806 | |
|
807 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { |
808 | 0 | data.dquant = pEnc->temp_dquants; |
809 | 0 | data.dquant_stride = pEnc->mbParam.mb_width; |
810 | 0 | memset(data.dquant, 0, data.mb_width*data.mb_height*sizeof(int)); |
811 | 0 | } |
812 | |
|
813 | 0 | if(pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) { |
814 | 0 | int block = 0; |
815 | 0 | emms(); |
816 | 0 | data.lambda = pEnc->temp_lambda; |
817 | 0 | for(i = 0;i < pEnc->mbParam.mb_height; i++) |
818 | 0 | for(j = 0;j < pEnc->mbParam.mb_width; j++) |
819 | 0 | for (k = 0; k < 6; k++) |
820 | 0 | data.lambda[block++] = 1.0f; |
821 | 0 | } |
822 | |
|
823 | 0 | } else { /* XVID_PLG_AFTER */ |
824 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { |
825 | 0 | data.original.csp = XVID_CSP_PLANAR; |
826 | 0 | data.original.plane[0] = original->y; |
827 | 0 | data.original.plane[1] = original->u; |
828 | 0 | data.original.plane[2] = original->v; |
829 | 0 | data.original.stride[0] = pEnc->mbParam.edged_width; |
830 | 0 | data.original.stride[1] = pEnc->mbParam.edged_width/2; |
831 | 0 | data.original.stride[2] = pEnc->mbParam.edged_width/2; |
832 | 0 | } |
833 | |
|
834 | 0 | if ((frame->vol_flags & XVID_VOL_EXTRASTATS) || |
835 | 0 | (pEnc->mbParam.plugin_flags & XVID_REQPSNR)) { |
836 | |
|
837 | 0 | data.sse_y = |
838 | 0 | plane_sse( original->y, frame->image.y, |
839 | 0 | pEnc->mbParam.edged_width, pEnc->mbParam.width, |
840 | 0 | pEnc->mbParam.height); |
841 | |
|
842 | 0 | data.sse_u = |
843 | 0 | plane_sse( original->u, frame->image.u, |
844 | 0 | pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2, |
845 | 0 | pEnc->mbParam.height/2); |
846 | |
|
847 | 0 | data.sse_v = |
848 | 0 | plane_sse( original->v, frame->image.v, |
849 | 0 | pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2, |
850 | 0 | pEnc->mbParam.height/2); |
851 | 0 | } |
852 | |
|
853 | 0 | data.type = coding2type(frame->coding_type); |
854 | 0 | data.quant = frame->quant; |
855 | |
|
856 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { |
857 | 0 | data.dquant = pEnc->temp_dquants; |
858 | 0 | data.dquant_stride = pEnc->mbParam.mb_width; |
859 | |
|
860 | 0 | for (j=0; j<pEnc->mbParam.mb_height; j++) |
861 | 0 | for (i=0; i<pEnc->mbParam.mb_width; i++) { |
862 | 0 | data.dquant[j*data.dquant_stride + i] = frame->mbs[j*pEnc->mbParam.mb_width + i].dquant; |
863 | 0 | } |
864 | 0 | } |
865 | |
|
866 | 0 | data.vol_flags = frame->vol_flags; |
867 | 0 | data.vop_flags = frame->vop_flags; |
868 | 0 | data.motion_flags = frame->motion_flags; |
869 | |
|
870 | 0 | data.length = frame->length; |
871 | 0 | data.kblks = frame->sStat.kblks; |
872 | 0 | data.mblks = frame->sStat.mblks; |
873 | 0 | data.ublks = frame->sStat.ublks; |
874 | | |
875 | | /* New code */ |
876 | 0 | data.stats.type = coding2type(frame->coding_type); |
877 | 0 | data.stats.quant = frame->quant; |
878 | 0 | data.stats.vol_flags = frame->vol_flags; |
879 | 0 | data.stats.vop_flags = frame->vop_flags; |
880 | 0 | data.stats.length = frame->length; |
881 | 0 | data.stats.hlength = frame->length - (frame->sStat.iTextBits / 8); |
882 | 0 | data.stats.kblks = frame->sStat.kblks; |
883 | 0 | data.stats.mblks = frame->sStat.mblks; |
884 | 0 | data.stats.ublks = frame->sStat.ublks; |
885 | 0 | data.stats.sse_y = data.sse_y; |
886 | 0 | data.stats.sse_u = data.sse_u; |
887 | 0 | data.stats.sse_v = data.sse_v; |
888 | |
|
889 | 0 | if (stats) |
890 | 0 | *stats = data.stats; |
891 | 0 | } |
892 | | |
893 | | /* call plugins */ |
894 | 0 | for (i=0; i<(unsigned int)pEnc->num_plugins;i++) { |
895 | 0 | emms(); |
896 | 0 | if (pEnc->plugins[i].func) { |
897 | 0 | if (pEnc->plugins[i].func(pEnc->plugins[i].param, opt, &data, NULL) < 0) { |
898 | 0 | continue; |
899 | 0 | } |
900 | 0 | } |
901 | 0 | } |
902 | 0 | emms(); |
903 | | |
904 | | /* copy modified values back into frame*/ |
905 | 0 | if (opt == XVID_PLG_BEFORE) { |
906 | 0 | *type = data.type; |
907 | 0 | *quant = data.quant > 0 ? data.quant : 2; /* default */ |
908 | |
|
909 | 0 | frame->vol_flags = data.vol_flags; |
910 | 0 | frame->vop_flags = data.vop_flags; |
911 | 0 | frame->motion_flags = data.motion_flags; |
912 | | |
913 | 0 | } else if (opt == XVID_PLG_FRAME) { |
914 | |
|
915 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { |
916 | 0 | for (j=0; j<pEnc->mbParam.mb_height; j++) |
917 | 0 | for (i=0; i<pEnc->mbParam.mb_width; i++) { |
918 | 0 | frame->mbs[j*pEnc->mbParam.mb_width + i].dquant = data.dquant[j*data.mb_width + i]; |
919 | 0 | } |
920 | 0 | } else { |
921 | 0 | for (j=0; j<pEnc->mbParam.mb_height; j++) |
922 | 0 | for (i=0; i<pEnc->mbParam.mb_width; i++) { |
923 | 0 | frame->mbs[j*pEnc->mbParam.mb_width + i].dquant = 0; |
924 | 0 | } |
925 | 0 | } |
926 | |
|
927 | 0 | if (pEnc->mbParam.plugin_flags & XVID_REQLAMBDA) { |
928 | 0 | for (j = 0; j < pEnc->mbParam.mb_height; j++) |
929 | 0 | for (i = 0; i < pEnc->mbParam.mb_width; i++) |
930 | 0 | for (k = 0; k < 6; k++) { |
931 | 0 | frame->mbs[j*pEnc->mbParam.mb_width + i].lambda[k] = |
932 | 0 | (int) ((float)(1<<LAMBDA_EXP) * data.lambda[6 * (j * data.mb_width + i) + k]); |
933 | 0 | } |
934 | 0 | } else { |
935 | 0 | for (j = 0; j<pEnc->mbParam.mb_height; j++) |
936 | 0 | for (i = 0; i<pEnc->mbParam.mb_width; i++) |
937 | 0 | for (k = 0; k < 6; k++) { |
938 | 0 | frame->mbs[j*pEnc->mbParam.mb_width + i].lambda[k] = 1<<LAMBDA_EXP; |
939 | 0 | } |
940 | 0 | } |
941 | | |
942 | |
|
943 | 0 | frame->mbs[0].quant = data.quant; /* FRAME will not affect the quant in stats */ |
944 | 0 | } |
945 | | |
946 | |
|
947 | 0 | } |
948 | | |
949 | | |
950 | | static __inline void inc_frame_num(Encoder * pEnc) |
951 | 0 | { |
952 | 0 | pEnc->current->frame_num = pEnc->m_framenum; |
953 | 0 | pEnc->current->stamp = pEnc->mbParam.m_stamp; /* first frame is zero */ |
954 | |
|
955 | 0 | pEnc->mbParam.m_stamp += pEnc->current->fincr; |
956 | 0 | pEnc->m_framenum++; /* debug ticker */ |
957 | 0 | } |
958 | | |
959 | | static __inline void dec_frame_num(Encoder * pEnc) |
960 | 0 | { |
961 | 0 | pEnc->mbParam.m_stamp -= pEnc->mbParam.fincr; |
962 | 0 | pEnc->m_framenum--; /* debug ticker */ |
963 | 0 | } |
964 | | |
965 | | static __inline void |
966 | | MBSetDquant(MACROBLOCK * pMB, int x, int y, MBParam * mbParam) |
967 | 0 | { |
968 | 0 | if (pMB->cbp == 0) { |
969 | | /* we want to code dquant but the quantizer value will not be used yet |
970 | | let's find out if we can postpone dquant to next MB |
971 | | */ |
972 | 0 | if (x == mbParam->mb_width-1 && y == mbParam->mb_height-1) { |
973 | 0 | pMB->dquant = 0; /* it's the last MB of all, the easiest case */ |
974 | 0 | return; |
975 | 0 | } else { |
976 | 0 | MACROBLOCK * next = pMB + 1; |
977 | 0 | const MACROBLOCK * prev = pMB - 1; |
978 | 0 | if (next->mode != MODE_INTER4V && next->mode != MODE_NOT_CODED) |
979 | | /* mode allows dquant change in the future */ |
980 | 0 | if (abs(next->quant - prev->quant) <= 2) { |
981 | | /* quant change is not out of range */ |
982 | 0 | pMB->quant = prev->quant; |
983 | 0 | pMB->dquant = 0; |
984 | 0 | next->dquant = next->quant - prev->quant; |
985 | 0 | return; |
986 | 0 | } |
987 | 0 | } |
988 | 0 | } |
989 | | /* couldn't skip this dquant */ |
990 | 0 | pMB->mode = MODE_INTER_Q; |
991 | 0 | } |
992 | | |
993 | | |
994 | | |
995 | | static __inline void |
996 | | set_timecodes(FRAMEINFO* pCur,FRAMEINFO *pRef, int32_t time_base) |
997 | 0 | { |
998 | |
|
999 | 0 | pCur->ticks = (int32_t)pCur->stamp % time_base; |
1000 | 0 | pCur->seconds = ((int32_t)pCur->stamp / time_base) - ((int32_t)pRef->stamp / time_base) ; |
1001 | |
|
1002 | | #if 0 /* HEAVY DEBUG OUTPUT */ |
1003 | | fprintf(stderr,"WriteVop: %d - %d \n", |
1004 | | ((int32_t)pCur->stamp / time_base), ((int32_t)pRef->stamp / time_base)); |
1005 | | fprintf(stderr,"set_timecodes: VOP %1d stamp=%lld ref_stamp=%lld base=%d\n", |
1006 | | pCur->coding_type, pCur->stamp, pRef->stamp, time_base); |
1007 | | fprintf(stderr,"set_timecodes: VOP %1d seconds=%d ticks=%d (ref-sec=%d ref-tick=%d)\n", |
1008 | | pCur->coding_type, pCur->seconds, pCur->ticks, pRef->seconds, pRef->ticks); |
1009 | | #endif |
1010 | 0 | } |
1011 | | |
1012 | | static void |
1013 | | simplify_par(int *par_width, int *par_height) |
1014 | 0 | { |
1015 | |
|
1016 | 0 | int _par_width = (!*par_width) ? 1 : (*par_width<0) ? -*par_width: *par_width; |
1017 | 0 | int _par_height = (!*par_height) ? 1 : (*par_height<0) ? -*par_height: *par_height; |
1018 | 0 | int divisor = gcd(_par_width, _par_height); |
1019 | |
|
1020 | 0 | _par_width /= divisor; |
1021 | 0 | _par_height /= divisor; |
1022 | | |
1023 | | /* 2^8 precision maximum */ |
1024 | 0 | if (_par_width>255 || _par_height>255) { |
1025 | 0 | float div; |
1026 | 0 | emms(); |
1027 | 0 | if (_par_width>_par_height) |
1028 | 0 | div = (float)_par_width/255; |
1029 | 0 | else |
1030 | 0 | div = (float)_par_height/255; |
1031 | |
|
1032 | 0 | _par_width = (int)((float)_par_width/div); |
1033 | 0 | _par_height = (int)((float)_par_height/div); |
1034 | 0 | } |
1035 | |
|
1036 | 0 | *par_width = _par_width; |
1037 | 0 | *par_height = _par_height; |
1038 | |
|
1039 | 0 | return; |
1040 | 0 | } |
1041 | | |
1042 | | /***************************************************************************** |
1043 | | * IPB frame encoder entry point |
1044 | | * |
1045 | | * Returned values : |
1046 | | * - >0 - output bytes |
1047 | | * - 0 - no output |
1048 | | * - XVID_ERR_VERSION - wrong version passed to core |
1049 | | * - XVID_ERR_END - End of stream reached before end of coding |
1050 | | * - XVID_ERR_FORMAT - the image subsystem reported the image had a wrong |
1051 | | * format |
1052 | | ****************************************************************************/ |
1053 | | |
1054 | | |
1055 | | int |
1056 | | enc_encode(Encoder * pEnc, |
1057 | | xvid_enc_frame_t * xFrame, |
1058 | | xvid_enc_stats_t * stats) |
1059 | 0 | { |
1060 | 0 | xvid_enc_frame_t * frame; |
1061 | 0 | int type; |
1062 | 0 | Bitstream bs; |
1063 | |
|
1064 | 0 | if (XVID_VERSION_MAJOR(xFrame->version) != 1 || (stats && XVID_VERSION_MAJOR(stats->version) != 1)) /* v1.x.x */ |
1065 | 0 | return XVID_ERR_VERSION; |
1066 | | |
1067 | 0 | xFrame->out_flags = 0; |
1068 | |
|
1069 | 0 | start_global_timer(); |
1070 | 0 | BitstreamInit(&bs, xFrame->bitstream, 0); |
1071 | | |
1072 | | |
1073 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1074 | | * enqueue image to the encoding-queue |
1075 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1076 | |
|
1077 | 0 | if (xFrame->input.csp != XVID_CSP_NULL) |
1078 | 0 | { |
1079 | 0 | QUEUEINFO * q = &pEnc->queue[pEnc->queue_tail]; |
1080 | |
|
1081 | 0 | start_timer(); |
1082 | 0 | if (image_input |
1083 | 0 | (&q->image, pEnc->mbParam.width, pEnc->mbParam.height, |
1084 | 0 | pEnc->mbParam.edged_width, (uint8_t**)xFrame->input.plane, xFrame->input.stride, |
1085 | 0 | xFrame->input.csp, xFrame->vol_flags & XVID_VOL_INTERLACING)) |
1086 | 0 | { |
1087 | 0 | emms(); |
1088 | 0 | return XVID_ERR_FORMAT; |
1089 | 0 | } |
1090 | 0 | stop_conv_timer(); |
1091 | |
|
1092 | 0 | if ((xFrame->vop_flags & XVID_VOP_CHROMAOPT)) { |
1093 | 0 | image_chroma_optimize(&q->image, |
1094 | 0 | pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); |
1095 | 0 | } |
1096 | |
|
1097 | 0 | q->frame = *xFrame; |
1098 | |
|
1099 | 0 | if (xFrame->quant_intra_matrix) |
1100 | 0 | { |
1101 | 0 | memcpy(q->quant_intra_matrix, xFrame->quant_intra_matrix, 64*sizeof(unsigned char)); |
1102 | 0 | q->frame.quant_intra_matrix = q->quant_intra_matrix; |
1103 | 0 | } |
1104 | |
|
1105 | 0 | if (xFrame->quant_inter_matrix) |
1106 | 0 | { |
1107 | 0 | memcpy(q->quant_inter_matrix, xFrame->quant_inter_matrix, 64*sizeof(unsigned char)); |
1108 | 0 | q->frame.quant_inter_matrix = q->quant_inter_matrix; |
1109 | 0 | } |
1110 | |
|
1111 | 0 | pEnc->queue_tail = (pEnc->queue_tail + 1) % (pEnc->mbParam.max_bframes+1); |
1112 | 0 | pEnc->queue_size++; |
1113 | 0 | } |
1114 | | |
1115 | | |
1116 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1117 | | * bframe flush code |
1118 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1119 | | |
1120 | 0 | repeat: |
1121 | |
|
1122 | 0 | if (pEnc->flush_bframes) |
1123 | 0 | { |
1124 | 0 | if (pEnc->bframenum_head < pEnc->bframenum_tail) { |
1125 | |
|
1126 | 0 | DPRINTF(XVID_DEBUG_DEBUG,"*** BFRAME (flush) bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", |
1127 | 0 | pEnc->bframenum_head, pEnc->bframenum_tail, |
1128 | 0 | pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
1129 | |
|
1130 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { |
1131 | 0 | image_copy(&pEnc->sOriginal2, &pEnc->bframes[pEnc->bframenum_head]->image, |
1132 | 0 | pEnc->mbParam.edged_width, pEnc->mbParam.height); |
1133 | 0 | } |
1134 | |
|
1135 | 0 | FrameCodeB(pEnc, pEnc->bframes[pEnc->bframenum_head], &bs); |
1136 | 0 | call_plugins(pEnc, pEnc->bframes[pEnc->bframenum_head], &pEnc->sOriginal2, XVID_PLG_AFTER, NULL, NULL, stats); |
1137 | 0 | pEnc->bframenum_head++; |
1138 | |
|
1139 | 0 | goto done; |
1140 | 0 | } |
1141 | | |
1142 | | /* write an empty marker to the bitstream. |
1143 | | |
1144 | | for divx5 decoder compatibility, this marker must consist |
1145 | | of a not-coded p-vop, with a time_base of zero, and time_increment |
1146 | | indentical to the future-referece frame. |
1147 | | */ |
1148 | | |
1149 | 0 | if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED && pEnc->bframenum_tail > 0)) { |
1150 | 0 | int tmp; |
1151 | 0 | int bits; |
1152 | |
|
1153 | 0 | DPRINTF(XVID_DEBUG_DEBUG,"*** EMPTY bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", |
1154 | 0 | pEnc->bframenum_head, pEnc->bframenum_tail, |
1155 | 0 | pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
1156 | |
|
1157 | 0 | bits = BitstreamPos(&bs); |
1158 | |
|
1159 | 0 | tmp = pEnc->current->seconds; |
1160 | 0 | pEnc->current->seconds = 0; /* force time_base = 0 */ |
1161 | |
|
1162 | 0 | BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0, pEnc->current->quant); |
1163 | 0 | BitstreamPad(&bs); |
1164 | 0 | pEnc->current->seconds = tmp; |
1165 | | |
1166 | | /* add the not-coded length to the reference frame size */ |
1167 | 0 | pEnc->current->length += (BitstreamPos(&bs) - bits) / 8; |
1168 | 0 | call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats); |
1169 | | |
1170 | | /* flush complete: reset counters */ |
1171 | 0 | pEnc->flush_bframes = 0; |
1172 | 0 | pEnc->bframenum_head = pEnc->bframenum_tail = 0; |
1173 | 0 | goto done; |
1174 | |
|
1175 | 0 | } |
1176 | | |
1177 | | /* flush complete: reset counters */ |
1178 | 0 | pEnc->flush_bframes = 0; |
1179 | 0 | pEnc->bframenum_head = pEnc->bframenum_tail = 0; |
1180 | 0 | } |
1181 | | |
1182 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1183 | | * dequeue frame from the encoding queue |
1184 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1185 | | |
1186 | 0 | if (pEnc->queue_size == 0) /* empty */ |
1187 | 0 | { |
1188 | 0 | if (xFrame->input.csp == XVID_CSP_NULL) /* no futher input */ |
1189 | 0 | { |
1190 | |
|
1191 | 0 | DPRINTF(XVID_DEBUG_DEBUG,"*** FINISH bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", |
1192 | 0 | pEnc->bframenum_head, pEnc->bframenum_tail, |
1193 | 0 | pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
1194 | |
|
1195 | 0 | if (!(pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->mbParam.max_bframes > 0) { |
1196 | 0 | call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats); |
1197 | 0 | } |
1198 | | |
1199 | | /* if the very last frame is to be b-vop, we must change it to a p-vop */ |
1200 | 0 | if (pEnc->bframenum_tail > 0) { |
1201 | |
|
1202 | 0 | SWAP(FRAMEINFO*, pEnc->current, pEnc->reference); |
1203 | 0 | pEnc->bframenum_tail--; |
1204 | 0 | SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); |
1205 | | |
1206 | | /* convert B-VOP to P-VOP */ |
1207 | 0 | pEnc->current->quant = 100*pEnc->current->quant - pEnc->mbParam.bquant_offset; |
1208 | 0 | pEnc->current->quant += pEnc->mbParam.bquant_ratio - 1; /* to avoid rouding issues */ |
1209 | 0 | pEnc->current->quant /= pEnc->mbParam.bquant_ratio; |
1210 | |
|
1211 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { |
1212 | 0 | image_copy(&pEnc->sOriginal, &pEnc->current->image, |
1213 | 0 | pEnc->mbParam.edged_width, pEnc->mbParam.height); |
1214 | 0 | } |
1215 | |
|
1216 | 0 | DPRINTF(XVID_DEBUG_DEBUG,"*** PFRAME bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", |
1217 | 0 | pEnc->bframenum_head, pEnc->bframenum_tail, |
1218 | 0 | pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
1219 | 0 | pEnc->mbParam.frame_drop_ratio = -1; /* it must be a coded vop */ |
1220 | |
|
1221 | 0 | FrameCodeP(pEnc, &bs); |
1222 | | |
1223 | |
|
1224 | 0 | if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail==0) { |
1225 | 0 | call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats); |
1226 | 0 | }else{ |
1227 | 0 | pEnc->flush_bframes = 1; |
1228 | 0 | goto done; |
1229 | 0 | } |
1230 | 0 | } |
1231 | 0 | DPRINTF(XVID_DEBUG_DEBUG, "*** END\n"); |
1232 | |
|
1233 | 0 | emms(); |
1234 | 0 | return XVID_ERR_END; /* end of stream reached */ |
1235 | 0 | } |
1236 | 0 | goto done; /* nothing to encode yet; encoder lag */ |
1237 | 0 | } |
1238 | | |
1239 | | /* the current FRAME becomes the reference */ |
1240 | 0 | SWAP(FRAMEINFO*, pEnc->current, pEnc->reference); |
1241 | | |
1242 | | /* remove frame from encoding-queue (head), and move it into the current */ |
1243 | 0 | image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image); |
1244 | 0 | frame = &pEnc->queue[pEnc->queue_head].frame; |
1245 | 0 | pEnc->queue_head = (pEnc->queue_head + 1) % (pEnc->mbParam.max_bframes+1); |
1246 | 0 | pEnc->queue_size--; |
1247 | | |
1248 | | |
1249 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1250 | | * init pEnc->current fields |
1251 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1252 | |
|
1253 | 0 | pEnc->current->fincr = pEnc->mbParam.fincr>0 ? pEnc->mbParam.fincr : frame->fincr; |
1254 | 0 | inc_frame_num(pEnc); |
1255 | 0 | pEnc->current->vol_flags = frame->vol_flags; |
1256 | 0 | pEnc->current->vop_flags = frame->vop_flags; |
1257 | 0 | pEnc->current->motion_flags = frame->motion; |
1258 | 0 | pEnc->current->fcode = pEnc->mbParam.m_fcode; |
1259 | 0 | pEnc->current->bcode = pEnc->mbParam.m_fcode; |
1260 | | |
1261 | |
|
1262 | 0 | if ((xFrame->vop_flags & XVID_VOP_CHROMAOPT)) { |
1263 | 0 | image_chroma_optimize(&pEnc->current->image, |
1264 | 0 | pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); |
1265 | 0 | } |
1266 | | |
1267 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1268 | | * frame type & quant selection |
1269 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1270 | |
|
1271 | 0 | type = frame->type; |
1272 | 0 | pEnc->current->quant = frame->quant; |
1273 | |
|
1274 | 0 | call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_BEFORE, &type, (int*)&pEnc->current->quant, stats); |
1275 | |
|
1276 | 0 | if (type > 0){ /* XVID_TYPE_?VOP */ |
1277 | 0 | type = type2coding(type); /* convert XVID_TYPE_?VOP to bitstream coding type */ |
1278 | 0 | } else{ /* XVID_TYPE_AUTO */ |
1279 | 0 | if (pEnc->iFrameNum == 0 || (pEnc->mbParam.iMaxKeyInterval > 0 && pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval)){ |
1280 | 0 | pEnc->iFrameNum = 0; |
1281 | 0 | type = I_VOP; |
1282 | 0 | }else{ |
1283 | 0 | type = MEanalysis(&pEnc->reference->image, pEnc->current, |
1284 | 0 | &pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval, |
1285 | 0 | pEnc->iFrameNum, pEnc->bframenum_tail, xFrame->bframe_threshold, |
1286 | 0 | (pEnc->bframes) ? pEnc->bframes[pEnc->bframenum_head]->mbs: NULL); |
1287 | 0 | } |
1288 | 0 | } |
1289 | |
|
1290 | 0 | if (type != I_VOP) |
1291 | 0 | pEnc->current->vol_flags = pEnc->mbParam.vol_flags; /* don't allow VOL changes here */ |
1292 | | |
1293 | | /* bframes buffer overflow check */ |
1294 | 0 | if (type == B_VOP && pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) { |
1295 | 0 | type = P_VOP; |
1296 | 0 | } |
1297 | |
|
1298 | 0 | pEnc->iFrameNum++; |
1299 | |
|
1300 | 0 | if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { |
1301 | 0 | image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 5, |
1302 | 0 | "%d st:%lld if:%d", pEnc->current->frame_num, pEnc->current->stamp, pEnc->iFrameNum); |
1303 | 0 | } |
1304 | | |
1305 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1306 | | * encode this frame as a b-vop |
1307 | | * (we dont encode here, rather we store the frame in the bframes queue, to be encoded later) |
1308 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1309 | 0 | if (type == B_VOP) { |
1310 | 0 | if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { |
1311 | 0 | image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "BVOP"); |
1312 | 0 | } |
1313 | |
|
1314 | 0 | if (frame->quant < 1) { |
1315 | 0 | pEnc->current->quant = ((((pEnc->reference->quant + pEnc->current->quant) * |
1316 | 0 | pEnc->mbParam.bquant_ratio) / 2) + pEnc->mbParam.bquant_offset)/100; |
1317 | |
|
1318 | 0 | } else { |
1319 | 0 | pEnc->current->quant = frame->quant; |
1320 | 0 | } |
1321 | |
|
1322 | 0 | if (pEnc->current->quant < 1) |
1323 | 0 | pEnc->current->quant = 1; |
1324 | 0 | else if (pEnc->current->quant > 31) |
1325 | 0 | pEnc->current->quant = 31; |
1326 | |
|
1327 | 0 | DPRINTF(XVID_DEBUG_DEBUG,"*** BFRAME (store) bf: head=%i tail=%i queue: head=%i tail=%i size=%i quant=%i\n", |
1328 | 0 | pEnc->bframenum_head, pEnc->bframenum_tail, |
1329 | 0 | pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size,pEnc->current->quant); |
1330 | | |
1331 | | /* store frame into bframe buffer & swap ref back to current */ |
1332 | 0 | SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); |
1333 | 0 | SWAP(FRAMEINFO*, pEnc->current, pEnc->reference); |
1334 | |
|
1335 | 0 | pEnc->bframenum_tail++; |
1336 | |
|
1337 | 0 | goto repeat; |
1338 | 0 | } |
1339 | | |
1340 | | |
1341 | 0 | DPRINTF(XVID_DEBUG_DEBUG,"*** XXXXXX bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", |
1342 | 0 | pEnc->bframenum_head, pEnc->bframenum_tail, |
1343 | 0 | pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
1344 | | |
1345 | | /* for unpacked bframes, output the stats for the last encoded frame */ |
1346 | 0 | if (!(pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->mbParam.max_bframes > 0) |
1347 | 0 | { |
1348 | 0 | if (pEnc->current->stamp > 0) { |
1349 | 0 | call_plugins(pEnc, pEnc->reference, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats); |
1350 | 0 | } |
1351 | 0 | else if (stats) { |
1352 | 0 | stats->type = XVID_TYPE_NOTHING; |
1353 | 0 | } |
1354 | 0 | } |
1355 | | |
1356 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1357 | | * closed-gop |
1358 | | * if the frame prior to an iframe is scheduled as a bframe, we must change it to a pframe |
1359 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1360 | |
|
1361 | 0 | if (type == I_VOP && (pEnc->mbParam.global_flags & XVID_GLOBAL_CLOSED_GOP) && pEnc->bframenum_tail > 0) { |
1362 | | |
1363 | | /* place this frame back on the encoding-queue (head) */ |
1364 | | /* we will deal with it next time */ |
1365 | 0 | dec_frame_num(pEnc); |
1366 | 0 | pEnc->iFrameNum--; |
1367 | |
|
1368 | 0 | pEnc->queue_head = (pEnc->queue_head + (pEnc->mbParam.max_bframes+1) - 1) % (pEnc->mbParam.max_bframes+1); |
1369 | 0 | pEnc->queue_size++; |
1370 | 0 | image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image); |
1371 | | |
1372 | | /* grab the last frame from the bframe-queue */ |
1373 | |
|
1374 | 0 | pEnc->bframenum_tail--; |
1375 | 0 | SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); |
1376 | |
|
1377 | 0 | if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { |
1378 | 0 | image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "CLOSED GOP BVOP->PVOP"); |
1379 | 0 | } |
1380 | | |
1381 | | /* convert B-VOP quant to P-VOP */ |
1382 | 0 | pEnc->current->quant = 100*pEnc->current->quant - pEnc->mbParam.bquant_offset; |
1383 | 0 | pEnc->current->quant += pEnc->mbParam.bquant_ratio - 1; /* to avoid rouding issues */ |
1384 | 0 | pEnc->current->quant /= pEnc->mbParam.bquant_ratio; |
1385 | 0 | type = P_VOP; |
1386 | 0 | } |
1387 | | |
1388 | | |
1389 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1390 | | * encode this frame as an i-vop |
1391 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1392 | |
|
1393 | 0 | if (type == I_VOP) { |
1394 | |
|
1395 | 0 | DPRINTF(XVID_DEBUG_DEBUG,"*** IFRAME bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", |
1396 | 0 | pEnc->bframenum_head, pEnc->bframenum_tail, |
1397 | 0 | pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
1398 | |
|
1399 | 0 | if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { |
1400 | 0 | image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "IVOP"); |
1401 | 0 | } |
1402 | |
|
1403 | 0 | pEnc->iFrameNum = 1; |
1404 | | |
1405 | | /* ---- update vol flags at IVOP ----------- */ |
1406 | 0 | pEnc->mbParam.vol_flags = pEnc->current->vol_flags; |
1407 | | |
1408 | | /* Aspect ratio */ |
1409 | 0 | switch(frame->par) { |
1410 | 0 | case XVID_PAR_11_VGA: |
1411 | 0 | case XVID_PAR_43_PAL: |
1412 | 0 | case XVID_PAR_43_NTSC: |
1413 | 0 | case XVID_PAR_169_PAL: |
1414 | 0 | case XVID_PAR_169_NTSC: |
1415 | 0 | case XVID_PAR_EXT: |
1416 | 0 | pEnc->mbParam.par = frame->par; |
1417 | 0 | break; |
1418 | 0 | default: |
1419 | 0 | pEnc->mbParam.par = XVID_PAR_11_VGA; |
1420 | 0 | break; |
1421 | 0 | } |
1422 | | |
1423 | | /* For extended PAR only, we try to sanityse/simplify par values */ |
1424 | 0 | if (pEnc->mbParam.par == XVID_PAR_EXT) { |
1425 | 0 | pEnc->mbParam.par_width = frame->par_width; |
1426 | 0 | pEnc->mbParam.par_height = frame->par_height; |
1427 | 0 | simplify_par(&pEnc->mbParam.par_width, &pEnc->mbParam.par_height); |
1428 | 0 | } |
1429 | |
|
1430 | 0 | if ((pEnc->mbParam.vol_flags & XVID_VOL_MPEGQUANT)) { |
1431 | 0 | if (frame->quant_intra_matrix != NULL) |
1432 | 0 | set_intra_matrix(pEnc->mbParam.mpeg_quant_matrices, frame->quant_intra_matrix); |
1433 | 0 | if (frame->quant_inter_matrix != NULL) |
1434 | 0 | set_inter_matrix(pEnc->mbParam.mpeg_quant_matrices, frame->quant_inter_matrix); |
1435 | 0 | } |
1436 | | |
1437 | | /* prevent vol/vop misuse */ |
1438 | |
|
1439 | 0 | if (!(pEnc->current->vol_flags & XVID_VOL_INTERLACING)) |
1440 | 0 | pEnc->current->vop_flags &= ~(XVID_VOP_TOPFIELDFIRST|XVID_VOP_ALTERNATESCAN); |
1441 | | |
1442 | | /* ^^^------------------------ */ |
1443 | |
|
1444 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { |
1445 | 0 | image_copy(&pEnc->sOriginal, &pEnc->current->image, |
1446 | 0 | pEnc->mbParam.edged_width, pEnc->mbParam.height); |
1447 | 0 | } |
1448 | |
|
1449 | 0 | FrameCodeI(pEnc, &bs); |
1450 | 0 | xFrame->out_flags |= XVID_KEYFRAME; |
1451 | | |
1452 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1453 | | * encode this frame as an p-vop |
1454 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1455 | |
|
1456 | 0 | } else { /* (type == P_VOP || type == S_VOP) */ |
1457 | |
|
1458 | 0 | DPRINTF(XVID_DEBUG_DEBUG,"*** PFRAME bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", |
1459 | 0 | pEnc->bframenum_head, pEnc->bframenum_tail, |
1460 | 0 | pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
1461 | |
|
1462 | 0 | if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { |
1463 | 0 | image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "PVOP"); |
1464 | 0 | } |
1465 | |
|
1466 | 0 | if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { |
1467 | 0 | image_copy(&pEnc->sOriginal, &pEnc->current->image, |
1468 | 0 | pEnc->mbParam.edged_width, pEnc->mbParam.height); |
1469 | 0 | } |
1470 | |
|
1471 | 0 | if ( FrameCodeP(pEnc, &bs) == 0 ) { |
1472 | | /* N-VOP, we mustn't code b-frames yet */ |
1473 | 0 | if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) || |
1474 | 0 | pEnc->mbParam.max_bframes == 0) |
1475 | 0 | call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats); |
1476 | 0 | goto done; |
1477 | 0 | } |
1478 | 0 | } |
1479 | | |
1480 | | |
1481 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1482 | | * on next enc_encode call we must flush bframes |
1483 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1484 | | |
1485 | | /*done_flush:*/ |
1486 | | |
1487 | 0 | pEnc->flush_bframes = 1; |
1488 | | |
1489 | | /* packed & queued_bframes: dont bother outputting stats here, we do so after the flush */ |
1490 | 0 | if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail > 0) { |
1491 | 0 | goto repeat; |
1492 | 0 | } |
1493 | | |
1494 | | /* packed or no-bframes or no-bframes-queued: output stats */ |
1495 | 0 | if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) || pEnc->mbParam.max_bframes == 0 ) { |
1496 | 0 | call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, NULL, NULL, stats); |
1497 | 0 | } |
1498 | | |
1499 | | /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1500 | | * done; return number of bytes consumed |
1501 | | * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
1502 | |
|
1503 | 0 | done: |
1504 | |
|
1505 | 0 | stop_global_timer(); |
1506 | 0 | write_timer(); |
1507 | |
|
1508 | 0 | emms(); |
1509 | 0 | return BitstreamLength(&bs); |
1510 | 0 | } |
1511 | | |
1512 | | |
1513 | | static void SetMacroblockQuants(MBParam * const pParam, FRAMEINFO * frame) |
1514 | 0 | { |
1515 | 0 | unsigned int i; |
1516 | 0 | MACROBLOCK * pMB = frame->mbs; |
1517 | 0 | int quant = frame->mbs[0].quant; /* set by XVID_PLG_FRAME */ |
1518 | 0 | if (quant > 31) |
1519 | 0 | frame->quant = quant = 31; |
1520 | 0 | else if (quant < 1) |
1521 | 0 | frame->quant = quant = 1; |
1522 | |
|
1523 | 0 | for (i = 0; i < pParam->mb_height * pParam->mb_width; i++) { |
1524 | 0 | quant += pMB->dquant; |
1525 | 0 | if (quant > 31) |
1526 | 0 | quant = 31; |
1527 | 0 | else if (quant < 1) |
1528 | 0 | quant = 1; |
1529 | 0 | pMB->quant = quant; |
1530 | 0 | pMB++; |
1531 | 0 | } |
1532 | 0 | } |
1533 | | |
1534 | | |
1535 | | static __inline void |
1536 | | CodeIntraMB(MACROBLOCK * pMB) |
1537 | 0 | { |
1538 | 0 | pMB->mode = MODE_INTRA; |
1539 | | |
1540 | | /* zero mv statistics */ |
1541 | 0 | pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0; |
1542 | 0 | pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0; |
1543 | 0 | pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0; |
1544 | 0 | pMB->sad16 = 0; |
1545 | |
|
1546 | 0 | if (pMB->dquant != 0) { |
1547 | 0 | pMB->mode = MODE_INTRA_Q; |
1548 | 0 | } |
1549 | 0 | } |
1550 | | |
1551 | | static void |
1552 | | SliceCodeI(SMPData *data) |
1553 | 0 | { |
1554 | 0 | Encoder *pEnc = (Encoder *) data->pEnc; |
1555 | 0 | Bitstream *bs = (Bitstream *) data->bs; |
1556 | |
|
1557 | 0 | uint16_t x, y; |
1558 | 0 | int mb_width = pEnc->mbParam.mb_width; |
1559 | 0 | int mb_height = pEnc->mbParam.mb_height; |
1560 | |
|
1561 | 0 | int bound = 0, num_slices = pEnc->num_slices; |
1562 | 0 | FRAMEINFO *const current = pEnc->current; |
1563 | |
|
1564 | 0 | DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE); |
1565 | 0 | DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); |
1566 | |
|
1567 | 0 | if (data->start_y > 0) { /* write resync marker */ |
1568 | 0 | bound = data->start_y*mb_width; |
1569 | 0 | write_video_packet_header(bs, &pEnc->mbParam, current, bound); |
1570 | 0 | } |
1571 | |
|
1572 | 0 | for (y = data->start_y; y < data->stop_y; y++) { |
1573 | 0 | int new_bound = mb_width * ((((y*num_slices) / mb_height) * mb_height + (num_slices-1)) / num_slices); |
1574 | |
|
1575 | 0 | if (new_bound > bound) { |
1576 | 0 | bound = new_bound; |
1577 | 0 | BitstreamPadAlways(bs); |
1578 | 0 | write_video_packet_header(bs, &pEnc->mbParam, current, bound); |
1579 | 0 | } |
1580 | |
|
1581 | 0 | for (x = 0; x < mb_width; x++) { |
1582 | 0 | MACROBLOCK *pMB = ¤t->mbs[x + y * mb_width]; |
1583 | |
|
1584 | 0 | CodeIntraMB(pMB); |
1585 | |
|
1586 | 0 | MBTransQuantIntra(&pEnc->mbParam, current, pMB, x, y, |
1587 | 0 | dct_codes, qcoeff); |
1588 | |
|
1589 | 0 | start_timer(); |
1590 | 0 | MBPrediction(current, x, y, mb_width, qcoeff, bound); |
1591 | 0 | stop_prediction_timer(); |
1592 | |
|
1593 | 0 | start_timer(); |
1594 | 0 | MBCoding(current, pMB, qcoeff, bs, data->sStat); |
1595 | 0 | stop_coding_timer(); |
1596 | |
|
1597 | 0 | } |
1598 | 0 | } |
1599 | |
|
1600 | 0 | emms(); |
1601 | 0 | BitstreamPadAlways(bs); |
1602 | 0 | } |
1603 | | |
1604 | | static __inline void |
1605 | | SerializeBitstreams(Encoder *pEnc, FRAMEINFO *current, Bitstream *bs, int num_threads) |
1606 | 0 | { |
1607 | 0 | int k; |
1608 | 0 | uint32_t pos = BitstreamLength(bs); |
1609 | |
|
1610 | 0 | for (k = 1; k < num_threads; k++) { |
1611 | 0 | uint32_t len = BitstreamLength(pEnc->smpData[k].bs); |
1612 | |
|
1613 | 0 | memcpy((void *)((ptr_t)bs->start + pos), |
1614 | 0 | (void *)((ptr_t)pEnc->smpData[k].bs->start), len); |
1615 | |
|
1616 | 0 | current->length += len; |
1617 | 0 | pos += len; |
1618 | | |
1619 | | /* collect stats */ |
1620 | 0 | current->sStat.iTextBits += pEnc->smpData[k].sStat->iTextBits; |
1621 | 0 | current->sStat.kblks += pEnc->smpData[k].sStat->kblks; |
1622 | 0 | current->sStat.mblks += pEnc->smpData[k].sStat->mblks; |
1623 | 0 | current->sStat.ublks += pEnc->smpData[k].sStat->ublks; |
1624 | 0 | current->sStat.iMVBits += pEnc->smpData[k].sStat->iMVBits; |
1625 | 0 | } |
1626 | |
|
1627 | 0 | if (num_threads > 1) { |
1628 | 0 | uint32_t pos32 = pos>>2; |
1629 | 0 | bs->tail = bs->start + pos32; |
1630 | 0 | bs->pos = 8*(pos - (pos32<<2)); |
1631 | 0 | bs->buf = 0; |
1632 | |
|
1633 | 0 | if (bs->pos > 0) { |
1634 | 0 | uint32_t pos8 = bs->pos/8; |
1635 | 0 | memset((void *)((ptr_t)bs->tail+pos8), 0, (4-pos8)); |
1636 | 0 | pos = *bs->tail; |
1637 | 0 | #ifndef ARCH_IS_BIG_ENDIAN |
1638 | 0 | BSWAP(pos); |
1639 | 0 | #endif |
1640 | 0 | bs->buf = pos; |
1641 | 0 | } |
1642 | 0 | } |
1643 | 0 | } |
1644 | | |
1645 | | static int |
1646 | | FrameCodeI(Encoder * pEnc, |
1647 | | Bitstream * bs) |
1648 | 0 | { |
1649 | 0 | int bits = BitstreamPos(bs); |
1650 | 0 | int bound = 0, num_slices = pEnc->num_slices; |
1651 | 0 | int num_threads = MAX(1, MIN(pEnc->num_threads, num_slices)); |
1652 | 0 | int slices_per_thread = (num_slices*1024 / num_threads); |
1653 | 0 | int mb_height = pEnc->mbParam.mb_height; |
1654 | 0 | #ifdef HAVE_PTHREAD |
1655 | 0 | void * status = NULL; |
1656 | 0 | #endif |
1657 | 0 | uint16_t k; |
1658 | |
|
1659 | 0 | pEnc->mbParam.m_rounding_type = 1; |
1660 | 0 | pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type; |
1661 | 0 | pEnc->current->coding_type = I_VOP; |
1662 | |
|
1663 | 0 | call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_FRAME, NULL, NULL, NULL); |
1664 | |
|
1665 | 0 | SetMacroblockQuants(&pEnc->mbParam, pEnc->current); |
1666 | |
|
1667 | 0 | BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current, num_slices); |
1668 | |
|
1669 | 0 | set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase); |
1670 | |
|
1671 | 0 | BitstreamPad(bs); |
1672 | |
|
1673 | 0 | BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1, pEnc->current->mbs[0].quant); |
1674 | |
|
1675 | 0 | pEnc->current->sStat.iTextBits = 0; |
1676 | | |
1677 | | /* multithreaded intra coding - dispatch threads */ |
1678 | 0 | for (k = 0; k < num_threads; k++) { |
1679 | 0 | int add = ((slices_per_thread + 512) >> 10); |
1680 | |
|
1681 | 0 | slices_per_thread += ((num_slices*1024 / num_threads) - add*1024); |
1682 | |
|
1683 | 0 | pEnc->smpData[k].pEnc = (void *) pEnc; |
1684 | 0 | pEnc->smpData[k].stop_y = (((bound+add) * mb_height + (num_slices-1)) / num_slices); |
1685 | 0 | pEnc->smpData[k].start_y = ((bound * mb_height + (num_slices-1)) / num_slices); |
1686 | |
|
1687 | 0 | bound += add; |
1688 | |
|
1689 | 0 | if (k > 0) { |
1690 | 0 | BitstreamReset(pEnc->smpData[k].bs); |
1691 | 0 | pEnc->smpData[k].sStat->iTextBits = 0; |
1692 | 0 | } |
1693 | 0 | } |
1694 | 0 | pEnc->smpData[0].bs = bs; |
1695 | 0 | pEnc->smpData[0].sStat = &pEnc->current->sStat; |
1696 | |
|
1697 | 0 | #ifdef HAVE_PTHREAD |
1698 | | /* create threads */ |
1699 | 0 | for (k = 1; k < num_threads; k++) { |
1700 | 0 | pthread_create(&pEnc->smpData[k].handle, NULL, |
1701 | 0 | (void*)SliceCodeI, (void*)&pEnc->smpData[k]); |
1702 | 0 | } |
1703 | 0 | #endif |
1704 | |
|
1705 | 0 | SliceCodeI(&pEnc->smpData[0]); |
1706 | |
|
1707 | 0 | #ifdef HAVE_PTHREAD |
1708 | | /* wait until all threads are finished */ |
1709 | 0 | for (k = 1; k < num_threads; k++) { |
1710 | 0 | pthread_join(pEnc->smpData[k].handle, &status); |
1711 | 0 | } |
1712 | 0 | #endif |
1713 | |
|
1714 | 0 | pEnc->current->length = BitstreamLength(bs) - (bits/8); |
1715 | | |
1716 | | /* reassemble the pieces together */ |
1717 | 0 | SerializeBitstreams(pEnc, pEnc->current, bs, num_threads); |
1718 | |
|
1719 | 0 | pEnc->current->sStat.iMVBits = 0; |
1720 | 0 | pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0; |
1721 | 0 | pEnc->current->sStat.kblks = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height; |
1722 | |
|
1723 | 0 | pEnc->fMvPrevSigma = -1; |
1724 | 0 | pEnc->mbParam.m_fcode = 2; |
1725 | |
|
1726 | 0 | pEnc->current->is_edged = 0; /* not edged */ |
1727 | 0 | pEnc->current->is_interpolated = -1; /* not interpolated (fake rounding -1) */ |
1728 | |
|
1729 | 0 | return 1; /* intra */ |
1730 | 0 | } |
1731 | | |
1732 | | static __inline void |
1733 | | updateFcode(Statistics * sStat, Encoder * pEnc) |
1734 | 0 | { |
1735 | 0 | float fSigma; |
1736 | 0 | int iSearchRange; |
1737 | |
|
1738 | 0 | if (sStat->iMvCount == 0) |
1739 | 0 | sStat->iMvCount = 1; |
1740 | |
|
1741 | 0 | fSigma = (float) sqrt((float) sStat->iMvSum / sStat->iMvCount); |
1742 | |
|
1743 | 0 | iSearchRange = 16 << pEnc->mbParam.m_fcode; |
1744 | |
|
1745 | 0 | if ((3.0 * fSigma > iSearchRange) && (pEnc->mbParam.m_fcode <= 5) ) |
1746 | 0 | pEnc->mbParam.m_fcode++; |
1747 | | |
1748 | 0 | else if ((5.0 * fSigma < iSearchRange) |
1749 | 0 | && (4.0 * pEnc->fMvPrevSigma < iSearchRange) |
1750 | 0 | && (pEnc->mbParam.m_fcode >= 2) ) |
1751 | 0 | pEnc->mbParam.m_fcode--; |
1752 | |
|
1753 | 0 | pEnc->fMvPrevSigma = fSigma; |
1754 | 0 | } |
1755 | | |
1756 | 0 | #define BFRAME_SKIP_THRESHHOLD 30 |
1757 | | |
1758 | | static void |
1759 | | SliceCodeP(SMPData *data) |
1760 | 0 | { |
1761 | 0 | Encoder *pEnc = (Encoder *) data->pEnc; |
1762 | 0 | Bitstream *bs = (Bitstream *) data->bs; |
1763 | |
|
1764 | 0 | int x, y, k; |
1765 | 0 | FRAMEINFO *const current = pEnc->current; |
1766 | 0 | FRAMEINFO *const reference = pEnc->reference; |
1767 | 0 | MBParam * const pParam = &pEnc->mbParam; |
1768 | 0 | int mb_width = pParam->mb_width; |
1769 | 0 | int mb_height = pParam->mb_height; |
1770 | |
|
1771 | 0 | DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE); |
1772 | 0 | DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); |
1773 | |
|
1774 | 0 | int bound = 0, num_slices = pEnc->num_slices; |
1775 | |
|
1776 | 0 | if (data->start_y > 0) { /* write resync marker */ |
1777 | 0 | bound = data->start_y*mb_width; |
1778 | 0 | write_video_packet_header(bs, pParam, current, bound); |
1779 | 0 | } |
1780 | |
|
1781 | 0 | for (y = data->start_y; y < data->stop_y; y++) { |
1782 | 0 | int new_bound = mb_width * ((((y*num_slices) / mb_height) * mb_height + (num_slices-1)) / num_slices); |
1783 | |
|
1784 | 0 | if (new_bound > bound) { |
1785 | 0 | bound = new_bound; |
1786 | 0 | BitstreamPadAlways(bs); |
1787 | 0 | write_video_packet_header(bs, pParam, current, bound); |
1788 | 0 | } |
1789 | |
|
1790 | 0 | for (x = 0; x < mb_width; x++) { |
1791 | 0 | MACROBLOCK *pMB = ¤t->mbs[x + y * pParam->mb_width]; |
1792 | 0 | int skip_possible; |
1793 | |
|
1794 | 0 | if (pMB->mode == MODE_INTRA || pMB->mode == MODE_INTRA_Q) { |
1795 | 0 | CodeIntraMB(pMB); |
1796 | 0 | MBTransQuantIntra(pParam, current, pMB, x, y, |
1797 | 0 | dct_codes, qcoeff); |
1798 | |
|
1799 | 0 | start_timer(); |
1800 | 0 | MBPrediction(current, x, y, pParam->mb_width, qcoeff, bound); |
1801 | 0 | stop_prediction_timer(); |
1802 | |
|
1803 | 0 | data->sStat->kblks++; |
1804 | |
|
1805 | 0 | MBCoding(current, pMB, qcoeff, bs, data->sStat); |
1806 | 0 | stop_coding_timer(); |
1807 | 0 | continue; |
1808 | 0 | } |
1809 | | |
1810 | 0 | start_timer(); |
1811 | 0 | MBMotionCompensation(pMB, x, y, &reference->image, |
1812 | 0 | &pEnc->vInterH, &pEnc->vInterV, |
1813 | 0 | &pEnc->vInterHV, &pEnc->vGMC, |
1814 | 0 | ¤t->image, |
1815 | 0 | dct_codes, pParam->width, |
1816 | 0 | pParam->height, |
1817 | 0 | pParam->edged_width, |
1818 | 0 | (current->vol_flags & XVID_VOL_QUARTERPEL), |
1819 | 0 | current->rounding_type, |
1820 | 0 | data->RefQ); |
1821 | |
|
1822 | 0 | stop_comp_timer(); |
1823 | |
|
1824 | 0 | pMB->field_pred = 0; |
1825 | |
|
1826 | 0 | if (pMB->cbp != 0) { |
1827 | 0 | pMB->cbp = MBTransQuantInter(pParam, current, pMB, x, y, |
1828 | 0 | dct_codes, qcoeff); |
1829 | 0 | } |
1830 | |
|
1831 | 0 | if (pMB->dquant != 0) |
1832 | 0 | MBSetDquant(pMB, x, y, pParam); |
1833 | | |
1834 | |
|
1835 | 0 | if (pMB->cbp || pMB->mvs[0].x || pMB->mvs[0].y || |
1836 | 0 | pMB->mvs[1].x || pMB->mvs[1].y || pMB->mvs[2].x || |
1837 | 0 | pMB->mvs[2].y || pMB->mvs[3].x || pMB->mvs[3].y) { |
1838 | 0 | data->sStat->mblks++; |
1839 | 0 | } else { |
1840 | 0 | data->sStat->ublks++; |
1841 | 0 | } |
1842 | |
|
1843 | 0 | start_timer(); |
1844 | | |
1845 | | /* Finished processing the MB, now check if to CODE or SKIP */ |
1846 | |
|
1847 | 0 | skip_possible = (pMB->cbp == 0) && (pMB->mode == MODE_INTER); |
1848 | |
|
1849 | 0 | if (current->coding_type == S_VOP) |
1850 | 0 | skip_possible &= (pMB->mcsel == 1); |
1851 | 0 | else { /* PVOP */ |
1852 | 0 | const VECTOR * const mv = (pParam->vol_flags & XVID_VOL_QUARTERPEL) ? |
1853 | 0 | pMB->qmvs : pMB->mvs; |
1854 | 0 | skip_possible &= ((mv->x|mv->y) == 0); |
1855 | 0 | } |
1856 | |
|
1857 | 0 | if ((pMB->mode == MODE_NOT_CODED) || (skip_possible)) { |
1858 | | /* This is a candidate for SKIPping, but for P-VOPs check intermediate B-frames first */ |
1859 | 0 | int bSkip = 1; |
1860 | |
|
1861 | 0 | if (current->coding_type == P_VOP) { /* special rule for P-VOP's SKIP */ |
1862 | 0 | for (k = pEnc->bframenum_head; k < pEnc->bframenum_tail; k++) { |
1863 | 0 | int iSAD; |
1864 | 0 | iSAD = sad16(reference->image.y + 16*y*pParam->edged_width + 16*x, |
1865 | 0 | pEnc->bframes[k]->image.y + 16*y*pParam->edged_width + 16*x, |
1866 | 0 | pParam->edged_width, BFRAME_SKIP_THRESHHOLD * pMB->quant); |
1867 | 0 | if (iSAD >= BFRAME_SKIP_THRESHHOLD * pMB->quant || ((bound > 1) && |
1868 | 0 | ((y*mb_width+x == bound) || (y*mb_width+x == bound+1)))) { /* Some third-party decoders have problems with coloc skip MB before or after |
1869 | | resync marker in BVOP. We avoid any ambiguity and force no skip at slice boundary */ |
1870 | 0 | bSkip = 0; /* could not SKIP */ |
1871 | 0 | if (pParam->vol_flags & XVID_VOL_QUARTERPEL) { |
1872 | 0 | VECTOR predMV = get_qpmv2(current->mbs, pParam->mb_width, bound, x, y, 0); |
1873 | 0 | pMB->pmvs[0].x = - predMV.x; |
1874 | 0 | pMB->pmvs[0].y = - predMV.y; |
1875 | 0 | } else { |
1876 | 0 | VECTOR predMV = get_pmv2(current->mbs, pParam->mb_width, bound, x, y, 0); |
1877 | 0 | pMB->pmvs[0].x = - predMV.x; |
1878 | 0 | pMB->pmvs[0].y = - predMV.y; |
1879 | 0 | } |
1880 | 0 | pMB->mode = MODE_INTER; |
1881 | 0 | pMB->cbp = 0; |
1882 | 0 | break; |
1883 | 0 | } |
1884 | 0 | } |
1885 | 0 | } |
1886 | |
|
1887 | 0 | if (bSkip) { |
1888 | | /* do SKIP */ |
1889 | 0 | pMB->mode = MODE_NOT_CODED; |
1890 | 0 | MBSkip(bs); |
1891 | 0 | stop_coding_timer(); |
1892 | 0 | continue; /* next MB */ |
1893 | 0 | } |
1894 | 0 | } |
1895 | | |
1896 | | /* ordinary case: normal coded INTER/INTER4V block */ |
1897 | 0 | MBCoding(current, pMB, qcoeff, bs, data->sStat); |
1898 | 0 | stop_coding_timer(); |
1899 | 0 | } |
1900 | 0 | } |
1901 | |
|
1902 | 0 | BitstreamPadAlways(bs); /* next_start_code() at the end of VideoObjectPlane() */ |
1903 | 0 | emms(); |
1904 | 0 | } |
1905 | | |
1906 | | /* FrameCodeP also handles S(GMC)-VOPs */ |
1907 | | static int |
1908 | | FrameCodeP(Encoder * pEnc, Bitstream * bs) |
1909 | 0 | { |
1910 | 0 | int bits = BitstreamPos(bs); |
1911 | |
|
1912 | 0 | FRAMEINFO *const current = pEnc->current; |
1913 | 0 | FRAMEINFO *const reference = pEnc->reference; |
1914 | 0 | MBParam * const pParam = &pEnc->mbParam; |
1915 | 0 | int mb_width = pParam->mb_width; |
1916 | 0 | int mb_height = pParam->mb_height; |
1917 | 0 | int coded = 1; |
1918 | |
|
1919 | 0 | int k = 0, bound = 0, num_slices = pEnc->num_slices; |
1920 | 0 | int num_threads = MAX(1, MIN(pEnc->num_threads, num_slices)); |
1921 | 0 | #ifdef HAVE_PTHREAD |
1922 | 0 | void * status = NULL; |
1923 | 0 | int threads_per_slice = (pEnc->num_threads*1024 / num_threads); |
1924 | 0 | #endif |
1925 | 0 | int slices_per_thread = (num_slices*1024 / num_threads); |
1926 | |
|
1927 | 0 | IMAGE *pRef = &reference->image; |
1928 | |
|
1929 | 0 | if (!reference->is_edged) { |
1930 | 0 | start_timer(); |
1931 | 0 | image_setedges(pRef, pParam->edged_width, pParam->edged_height, |
1932 | 0 | pParam->width, pParam->height, XVID_BS_VERSION); |
1933 | 0 | stop_edges_timer(); |
1934 | 0 | reference->is_edged = 1; |
1935 | 0 | } |
1936 | |
|
1937 | 0 | pParam->m_rounding_type = 1 - pParam->m_rounding_type; |
1938 | 0 | current->rounding_type = pParam->m_rounding_type; |
1939 | 0 | current->fcode = pParam->m_fcode; |
1940 | |
|
1941 | 0 | if ((current->vop_flags & XVID_VOP_HALFPEL)) { |
1942 | 0 | if (reference->is_interpolated != current->rounding_type) { |
1943 | 0 | start_timer(); |
1944 | 0 | image_interpolate(pRef->y, pEnc->vInterH.y, pEnc->vInterV.y, |
1945 | 0 | pEnc->vInterHV.y, pParam->edged_width, |
1946 | 0 | pParam->edged_height, |
1947 | 0 | (pParam->vol_flags & XVID_VOL_QUARTERPEL), |
1948 | 0 | current->rounding_type); |
1949 | 0 | stop_inter_timer(); |
1950 | 0 | reference->is_interpolated = current->rounding_type; |
1951 | 0 | } |
1952 | 0 | } |
1953 | |
|
1954 | 0 | current->sStat.iTextBits = current->sStat.iMvSum = current->sStat.iMvCount = |
1955 | 0 | current->sStat.kblks = current->sStat.mblks = current->sStat.ublks = |
1956 | 0 | current->sStat.iMVBits = 0; |
1957 | |
|
1958 | 0 | current->coding_type = P_VOP; |
1959 | |
|
1960 | 0 | if (current->vop_flags & XVID_VOP_RD_PSNRHVSM) { |
1961 | 0 | image_block_variance(¤t->image, pParam->edged_width, current->mbs, |
1962 | 0 | pParam->mb_width, pParam->mb_height); |
1963 | 0 | } |
1964 | |
|
1965 | 0 | call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_FRAME, NULL, NULL, NULL); |
1966 | |
|
1967 | 0 | SetMacroblockQuants(&pEnc->mbParam, current); |
1968 | |
|
1969 | 0 | start_timer(); |
1970 | 0 | if (current->vol_flags & XVID_VOL_GMC) /* GMC only for S(GMC)-VOPs */ |
1971 | 0 | { int gmcval; |
1972 | 0 | current->warp = GlobalMotionEst( current->mbs, pParam, current, reference, |
1973 | 0 | &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV, num_slices); |
1974 | |
|
1975 | 0 | if (current->motion_flags & XVID_ME_GME_REFINE) { |
1976 | 0 | gmcval = GlobalMotionEstRefine(¤t->warp, |
1977 | 0 | current->mbs, pParam, |
1978 | 0 | current, reference, |
1979 | 0 | ¤t->image, |
1980 | 0 | &reference->image, |
1981 | 0 | &pEnc->vInterH, |
1982 | 0 | &pEnc->vInterV, |
1983 | 0 | &pEnc->vInterHV); |
1984 | 0 | } else { |
1985 | 0 | gmcval = globalSAD(¤t->warp, pParam, current->mbs, |
1986 | 0 | current, |
1987 | 0 | &reference->image, |
1988 | 0 | ¤t->image, |
1989 | 0 | pEnc->vGMC.y); |
1990 | 0 | } |
1991 | |
|
1992 | 0 | gmcval += /*current->quant*/ 2 * (int)(pParam->mb_width*pParam->mb_height); |
1993 | | |
1994 | | /* 1st '3': 3 warpoints, 2nd '3': 16th pel res (2<<3) */ |
1995 | 0 | generate_GMCparameters( 3, 3, ¤t->warp, |
1996 | 0 | pParam->width, pParam->height, |
1997 | 0 | ¤t->new_gmc_data); |
1998 | |
|
1999 | 0 | if ( (gmcval<0) && ( (current->warp.duv[1].x != 0) || (current->warp.duv[1].y != 0) || |
2000 | 0 | (current->warp.duv[2].x != 0) || (current->warp.duv[2].y != 0) ) ) |
2001 | 0 | { |
2002 | 0 | current->coding_type = S_VOP; |
2003 | |
|
2004 | 0 | generate_GMCimage(¤t->new_gmc_data, &reference->image, |
2005 | 0 | pParam->mb_width, pParam->mb_height, |
2006 | 0 | pParam->edged_width, pParam->edged_width/2, |
2007 | 0 | pParam->m_fcode, ((pParam->vol_flags & XVID_VOL_QUARTERPEL)?1:0), 0, |
2008 | 0 | current->rounding_type, current->mbs, &pEnc->vGMC); |
2009 | |
|
2010 | 0 | } else { |
2011 | |
|
2012 | 0 | generate_GMCimage(¤t->new_gmc_data, &reference->image, |
2013 | 0 | pParam->mb_width, pParam->mb_height, |
2014 | 0 | pParam->edged_width, pParam->edged_width/2, |
2015 | 0 | pParam->m_fcode, ((pParam->vol_flags & XVID_VOL_QUARTERPEL)?1:0), 0, |
2016 | 0 | current->rounding_type, current->mbs, NULL); /* no warping, just AMV */ |
2017 | 0 | } |
2018 | 0 | } |
2019 | |
|
2020 | 0 | #ifdef HAVE_PTHREAD |
2021 | 0 | if (pEnc->num_threads > 0) { |
2022 | | |
2023 | | /* multithreaded motion estimation - dispatch threads */ |
2024 | 0 | while (k < pEnc->num_threads) { |
2025 | 0 | int i, add_s = (slices_per_thread + 512) >> 10; |
2026 | 0 | int add_t = (threads_per_slice + 512) >> 10; |
2027 | | |
2028 | 0 | int start_y = (bound * mb_height + (num_slices-1)) / num_slices; |
2029 | 0 | int stop_y = ((bound+add_s) * mb_height + (num_slices-1)) / num_slices; |
2030 | 0 | int rows_per_thread = (stop_y - start_y + add_t - 1) / add_t; |
2031 | |
|
2032 | 0 | slices_per_thread += ((num_slices*1024 / num_threads) - add_s*1024); |
2033 | 0 | threads_per_slice += ((pEnc->num_threads*1024 / num_threads) - add_t*1024); |
2034 | |
|
2035 | 0 | for (i = 0; i < add_t; i++) { |
2036 | 0 | memset(pEnc->smpData[k+i].complete_count_self, 0, rows_per_thread * sizeof(int)); |
2037 | |
|
2038 | 0 | pEnc->smpData[k+i].pEnc = (void *) pEnc; |
2039 | 0 | pEnc->smpData[k+i].y_row = i; |
2040 | 0 | pEnc->smpData[k+i].y_step = add_t; |
2041 | 0 | pEnc->smpData[k+i].stop_y = stop_y; |
2042 | 0 | pEnc->smpData[k+i].start_y = start_y; |
2043 | | |
2044 | | /* todo: sort out temp space once and for all */ |
2045 | 0 | pEnc->smpData[k+i].RefQ = (((k+i)&1) ? pEnc->vInterV.u : pEnc->vInterV.v) + |
2046 | 0 | 16*((k+i)>>1)*pParam->edged_width; |
2047 | 0 | } |
2048 | | |
2049 | 0 | pEnc->smpData[k].complete_count_above = |
2050 | 0 | pEnc->smpData[k+add_t-1].complete_count_self - 1; |
2051 | |
|
2052 | 0 | bound += add_s; |
2053 | 0 | k += add_t; |
2054 | 0 | } |
2055 | |
|
2056 | 0 | for (k = 1; k < pEnc->num_threads; k++) { |
2057 | 0 | pthread_create(&pEnc->smpData[k].handle, NULL, |
2058 | 0 | (void*)MotionEstimateSMP, (void*)&pEnc->smpData[k]); |
2059 | 0 | } |
2060 | |
|
2061 | 0 | MotionEstimateSMP(&pEnc->smpData[0]); |
2062 | |
|
2063 | 0 | for (k = 1; k < pEnc->num_threads; k++) { |
2064 | 0 | pthread_join(pEnc->smpData[k].handle, &status); |
2065 | 0 | } |
2066 | |
|
2067 | 0 | current->fcode = 0; |
2068 | 0 | for (k = 0; k < pEnc->num_threads; k++) { |
2069 | 0 | current->sStat.iMvSum += pEnc->smpData[k].mvSum; |
2070 | 0 | current->sStat.iMvCount += pEnc->smpData[k].mvCount; |
2071 | 0 | if (pEnc->smpData[k].minfcode > current->fcode) |
2072 | 0 | current->fcode = pEnc->smpData[k].minfcode; |
2073 | 0 | } |
2074 | |
|
2075 | 0 | } else |
2076 | 0 | #endif |
2077 | 0 | { |
2078 | | |
2079 | | /* regular ME */ |
2080 | |
|
2081 | 0 | MotionEstimation(&pEnc->mbParam, current, reference, |
2082 | 0 | &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV, |
2083 | 0 | &pEnc->vGMC, 256*4096, num_slices); |
2084 | |
|
2085 | 0 | } |
2086 | |
|
2087 | 0 | stop_motion_timer(); |
2088 | |
|
2089 | 0 | set_timecodes(current,reference,pParam->fbase); |
2090 | |
|
2091 | 0 | BitstreamWriteVopHeader(bs, &pEnc->mbParam, current, 1, current->mbs[0].quant); |
2092 | | |
2093 | | /* multithreaded inter coding - dispatch threads */ |
2094 | |
|
2095 | 0 | bound = 0; |
2096 | 0 | slices_per_thread = (num_slices*1024 / num_threads); |
2097 | |
|
2098 | 0 | for (k = 0; k < num_threads; k++) { |
2099 | 0 | int add = ((slices_per_thread + 512) >> 10); |
2100 | |
|
2101 | 0 | slices_per_thread += ((num_slices*1024 / num_threads) - add*1024); |
2102 | |
|
2103 | 0 | pEnc->smpData[k].pEnc = (void *) pEnc; |
2104 | 0 | pEnc->smpData[k].stop_y = (((bound+add) * mb_height + (num_slices-1)) / num_slices); |
2105 | 0 | pEnc->smpData[k].start_y = ((bound * mb_height + (num_slices-1)) / num_slices); |
2106 | 0 | pEnc->smpData[k].RefQ = ((k&1) ? pEnc->vInterV.u : pEnc->vInterV.v) + 16*(k>>1)*pParam->edged_width; |
2107 | |
|
2108 | 0 | bound += add; |
2109 | |
|
2110 | 0 | if (k > 0) { |
2111 | 0 | pEnc->smpData[k].sStat->iTextBits = pEnc->smpData[k].sStat->kblks = |
2112 | 0 | pEnc->smpData[k].sStat->mblks = pEnc->smpData[k].sStat->ublks = |
2113 | 0 | pEnc->smpData[k].sStat->iMVBits = 0; |
2114 | | |
2115 | 0 | BitstreamReset(pEnc->smpData[k].bs); |
2116 | 0 | } |
2117 | 0 | } |
2118 | 0 | pEnc->smpData[0].bs = bs; |
2119 | 0 | pEnc->smpData[0].sStat = ¤t->sStat; |
2120 | |
|
2121 | 0 | #ifdef HAVE_PTHREAD |
2122 | | /* create threads */ |
2123 | 0 | for (k = 1; k < num_threads; k++) { |
2124 | 0 | pthread_create(&pEnc->smpData[k].handle, NULL, |
2125 | 0 | (void*)SliceCodeP, (void*)&pEnc->smpData[k]); |
2126 | 0 | } |
2127 | 0 | #endif |
2128 | |
|
2129 | 0 | SliceCodeP(&pEnc->smpData[0]); |
2130 | |
|
2131 | 0 | #ifdef HAVE_PTHREAD |
2132 | | /* wait until all threads are finished */ |
2133 | 0 | for (k = 1; k < num_threads; k++) { |
2134 | 0 | pthread_join(pEnc->smpData[k].handle, &status); |
2135 | 0 | } |
2136 | 0 | #endif |
2137 | |
|
2138 | 0 | current->length = BitstreamLength(bs) - (bits/8); |
2139 | | |
2140 | | /* reassemble the pieces together */ |
2141 | 0 | SerializeBitstreams(pEnc, pEnc->current, bs, num_threads); |
2142 | |
|
2143 | 0 | updateFcode(¤t->sStat, pEnc); |
2144 | | |
2145 | | /* frame drop code */ |
2146 | | #if 0 |
2147 | | DPRINTF(XVID_DEBUG_DEBUG, "kmu %i %i %i\n", current->sStat.kblks, current->sStat.mblks, current->sStat.ublks); |
2148 | | #endif |
2149 | |
|
2150 | 0 | if (current->sStat.kblks + current->sStat.mblks < |
2151 | 0 | (pParam->frame_drop_ratio * mb_width * mb_height) / 100 && |
2152 | 0 | ( (pEnc->bframenum_head >= pEnc->bframenum_tail) || !(pEnc->mbParam.global_flags & XVID_GLOBAL_CLOSED_GOP)) && |
2153 | 0 | (current->coding_type == P_VOP) ) |
2154 | 0 | { |
2155 | 0 | current->sStat.kblks = current->sStat.mblks = current->sStat.iTextBits = 0; |
2156 | 0 | current->sStat.ublks = mb_width * mb_height; |
2157 | |
|
2158 | 0 | BitstreamReset(bs); |
2159 | |
|
2160 | 0 | set_timecodes(current,reference,pParam->fbase); |
2161 | 0 | BitstreamWriteVopHeader(bs, &pEnc->mbParam, current, 0, current->mbs[0].quant); |
2162 | | |
2163 | | /* copy reference frame details into the current frame */ |
2164 | 0 | current->quant = reference->quant; |
2165 | 0 | current->motion_flags = reference->motion_flags; |
2166 | 0 | current->rounding_type = reference->rounding_type; |
2167 | 0 | current->fcode = reference->fcode; |
2168 | 0 | current->bcode = reference->bcode; |
2169 | 0 | current->stamp = reference->stamp; |
2170 | 0 | image_copy(¤t->image, &reference->image, pParam->edged_width, pParam->height); |
2171 | 0 | memcpy(current->mbs, reference->mbs, sizeof(MACROBLOCK) * mb_width * mb_height); |
2172 | 0 | coded = 0; |
2173 | | |
2174 | 0 | BitstreamPadAlways(bs); /* next_start_code() at the end of VideoObjectPlane() */ |
2175 | |
|
2176 | 0 | current->length = (BitstreamPos(bs) - bits) / 8; |
2177 | |
|
2178 | 0 | } else { |
2179 | |
|
2180 | 0 | pEnc->current->is_edged = 0; /* not edged */ |
2181 | 0 | pEnc->current->is_interpolated = -1; /* not interpolated (fake rounding -1) */ |
2182 | | |
2183 | | /* what was this frame's interpolated reference will become |
2184 | | forward (past) reference in b-frame coding */ |
2185 | |
|
2186 | 0 | image_swap(&pEnc->vInterH, &pEnc->f_refh); |
2187 | 0 | image_swap(&pEnc->vInterV, &pEnc->f_refv); |
2188 | 0 | image_swap(&pEnc->vInterHV, &pEnc->f_refhv); |
2189 | 0 | } |
2190 | | |
2191 | | /* XXX: debug |
2192 | | { |
2193 | | char s[100]; |
2194 | | sprintf(s, "\\%05i_cur.pgm", pEnc->m_framenum); |
2195 | | image_dump_yuvpgm(¤t->image, |
2196 | | pParam->edged_width, |
2197 | | pParam->width, pParam->height, s); |
2198 | | |
2199 | | sprintf(s, "\\%05i_ref.pgm", pEnc->m_framenum); |
2200 | | image_dump_yuvpgm(&reference->image, |
2201 | | pParam->edged_width, |
2202 | | pParam->width, pParam->height, s); |
2203 | | } |
2204 | | */ |
2205 | |
|
2206 | 0 | return coded; |
2207 | 0 | } |
2208 | | |
2209 | | static void |
2210 | | SliceCodeB(SMPData *data) |
2211 | 0 | { |
2212 | 0 | Encoder *pEnc = (Encoder *) data->pEnc; |
2213 | 0 | Bitstream *bs = (Bitstream *) data->bs; |
2214 | |
|
2215 | 0 | DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE); |
2216 | 0 | DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); |
2217 | |
|
2218 | 0 | int x, y; |
2219 | 0 | FRAMEINFO * const frame = (FRAMEINFO * const) data->current; |
2220 | 0 | MBParam * const pParam = &pEnc->mbParam; |
2221 | 0 | int mb_width = pParam->mb_width; |
2222 | 0 | int mb_height = pParam->mb_height; |
2223 | 0 | IMAGE *f_ref = &pEnc->reference->image; |
2224 | 0 | IMAGE *b_ref = &pEnc->current->image; |
2225 | |
|
2226 | 0 | int bound = data->start_y*mb_width; |
2227 | 0 | int num_slices = pEnc->num_slices; |
2228 | |
|
2229 | 0 | if (data->start_y > 0) { /* write resync marker */ |
2230 | 0 | write_video_packet_header(bs, pParam, frame, bound+1); |
2231 | 0 | } |
2232 | |
|
2233 | 0 | for (y = data->start_y; y < MIN(data->stop_y+1, mb_height); y++) { |
2234 | 0 | int new_bound = mb_width * ((((y*num_slices) / mb_height) * mb_height + (num_slices-1)) / num_slices); |
2235 | 0 | int stop_x = (y == data->stop_y) ? 1 : mb_width; |
2236 | 0 | int start_x = (y == data->start_y && y > 0) ? 1 : 0; |
2237 | |
|
2238 | 0 | for (x = start_x; x < stop_x; x++) { |
2239 | 0 | MACROBLOCK * const mb = &frame->mbs[x + y * pEnc->mbParam.mb_width]; |
2240 | | |
2241 | | /* decoder ignores mb when refence block is INTER(0,0), CBP=0 */ |
2242 | 0 | if (mb->mode == MODE_NOT_CODED) { |
2243 | 0 | if (pParam->plugin_flags & XVID_REQORIGINAL) { |
2244 | 0 | MBMotionCompensation(mb, x, y, f_ref, NULL, f_ref, NULL, NULL, &frame->image, |
2245 | 0 | NULL, 0, 0, pParam->edged_width, 0, 0, data->RefQ); |
2246 | 0 | } |
2247 | 0 | continue; |
2248 | 0 | } |
2249 | | |
2250 | 0 | if (new_bound > bound && x > 0) { |
2251 | 0 | bound = new_bound; |
2252 | 0 | BitstreamPadAlways(bs); |
2253 | 0 | write_video_packet_header(bs, pParam, frame, y*mb_width+x); |
2254 | 0 | } |
2255 | |
|
2256 | 0 | mb->quant = frame->quant; |
2257 | |
|
2258 | 0 | if (mb->cbp != 0 || pParam->plugin_flags & XVID_REQORIGINAL) { |
2259 | | /* we have to motion-compensate, transfer etc, |
2260 | | because there might be blocks to code */ |
2261 | |
|
2262 | 0 | MBMotionCompensationBVOP(pParam, mb, x, y, &frame->image, |
2263 | 0 | f_ref, &pEnc->f_refh, &pEnc->f_refv, |
2264 | 0 | &pEnc->f_refhv, b_ref, &pEnc->vInterH, |
2265 | 0 | &pEnc->vInterV, &pEnc->vInterHV, dct_codes, |
2266 | 0 | data->RefQ); |
2267 | |
|
2268 | 0 | mb->cbp = MBTransQuantInterBVOP(pParam, frame, mb, x, y, dct_codes, qcoeff); |
2269 | 0 | } |
2270 | | |
2271 | 0 | if (mb->mode == MODE_DIRECT_NO4V) |
2272 | 0 | mb->mode = MODE_DIRECT; |
2273 | |
|
2274 | 0 | if (mb->mode == MODE_DIRECT && (mb->cbp | mb->pmvs[3].x | mb->pmvs[3].y) == 0) |
2275 | 0 | mb->mode = MODE_DIRECT_NONE_MV; /* skipped */ |
2276 | 0 | else |
2277 | 0 | if (frame->vop_flags & XVID_VOP_GREYSCALE) |
2278 | | /* keep only bits 5-2 -- Chroma blocks will just be skipped by MBCodingBVOP */ |
2279 | 0 | mb->cbp &= 0x3C; |
2280 | |
|
2281 | 0 | start_timer(); |
2282 | 0 | MBCodingBVOP(frame, mb, qcoeff, frame->fcode, frame->bcode, bs, data->sStat); |
2283 | 0 | stop_coding_timer(); |
2284 | 0 | } |
2285 | 0 | } |
2286 | |
|
2287 | 0 | BitstreamPadAlways(bs); /* next_start_code() at the end of VideoObjectPlane() */ |
2288 | 0 | emms(); |
2289 | 0 | } |
2290 | | |
2291 | | static void |
2292 | | FrameCodeB(Encoder * pEnc, |
2293 | | FRAMEINFO * frame, |
2294 | | Bitstream * bs) |
2295 | 0 | { |
2296 | 0 | int bits = BitstreamPos(bs); |
2297 | 0 | int k = 0, bound = 0, num_slices = pEnc->num_slices; |
2298 | 0 | int num_threads = MAX(1, MIN(pEnc->num_threads, num_slices)); |
2299 | 0 | #ifdef HAVE_PTHREAD |
2300 | 0 | void * status = NULL; |
2301 | 0 | int threads_per_slice = (pEnc->num_threads*1024 / num_threads); |
2302 | 0 | #endif |
2303 | 0 | int slices_per_thread = (num_slices*1024 / num_threads); |
2304 | |
|
2305 | 0 | IMAGE *f_ref = &pEnc->reference->image; |
2306 | 0 | IMAGE *b_ref = &pEnc->current->image; |
2307 | |
|
2308 | 0 | MBParam * const pParam = &pEnc->mbParam; |
2309 | 0 | int mb_height = pParam->mb_height; |
2310 | |
|
2311 | | #ifdef BFRAMES_DEC_DEBUG |
2312 | | FILE *fp; |
2313 | | static char first=0; |
2314 | | #define BFRAME_DEBUG if (!first && fp){ \ |
2315 | | fprintf(fp,"Y=%3d X=%3d MB=%2d CBP=%02X\n",y,x,mb->mode,mb->cbp); \ |
2316 | | } |
2317 | | |
2318 | | if (!first){ |
2319 | | fp=fopen("C:\\XVIDDBGE.TXT","w"); |
2320 | | } |
2321 | | #endif |
2322 | | |
2323 | | /* forward */ |
2324 | 0 | if (!pEnc->reference->is_edged) { |
2325 | 0 | image_setedges(f_ref, pEnc->mbParam.edged_width, |
2326 | 0 | pEnc->mbParam.edged_height, pEnc->mbParam.width, |
2327 | 0 | pEnc->mbParam.height, XVID_BS_VERSION); |
2328 | 0 | pEnc->reference->is_edged = 1; |
2329 | 0 | } |
2330 | |
|
2331 | 0 | if (pEnc->reference->is_interpolated != 0) { |
2332 | 0 | start_timer(); |
2333 | 0 | image_interpolate(f_ref->y, pEnc->f_refh.y, pEnc->f_refv.y, pEnc->f_refhv.y, |
2334 | 0 | pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, |
2335 | 0 | (pEnc->mbParam.vol_flags & XVID_VOL_QUARTERPEL), 0); |
2336 | 0 | stop_inter_timer(); |
2337 | 0 | pEnc->reference->is_interpolated = 0; |
2338 | 0 | } |
2339 | | |
2340 | | /* backward */ |
2341 | 0 | if (!pEnc->current->is_edged) { |
2342 | 0 | image_setedges(b_ref, pEnc->mbParam.edged_width, |
2343 | 0 | pEnc->mbParam.edged_height, pEnc->mbParam.width, |
2344 | 0 | pEnc->mbParam.height, XVID_BS_VERSION); |
2345 | 0 | pEnc->current->is_edged = 1; |
2346 | 0 | } |
2347 | |
|
2348 | 0 | if (pEnc->current->is_interpolated != 0) { |
2349 | 0 | start_timer(); |
2350 | 0 | image_interpolate(b_ref->y, pEnc->vInterH.y, pEnc->vInterV.y, pEnc->vInterHV.y, |
2351 | 0 | pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, |
2352 | 0 | (pEnc->mbParam.vol_flags & XVID_VOL_QUARTERPEL), 0); |
2353 | 0 | stop_inter_timer(); |
2354 | 0 | pEnc->current->is_interpolated = 0; |
2355 | 0 | } |
2356 | |
|
2357 | 0 | frame->coding_type = B_VOP; |
2358 | |
|
2359 | 0 | if ((frame->vop_flags & XVID_VOP_RD_PSNRHVSM) && (frame->vop_flags & XVID_VOP_RD_BVOP)) { |
2360 | 0 | image_block_variance(&frame->image, pEnc->mbParam.edged_width, frame->mbs, |
2361 | 0 | pEnc->mbParam.mb_width, pEnc->mbParam.mb_height); |
2362 | 0 | } |
2363 | |
|
2364 | 0 | call_plugins(pEnc, frame, NULL, XVID_PLG_FRAME, NULL, NULL, NULL); |
2365 | |
|
2366 | 0 | frame->fcode = frame->bcode = pEnc->current->fcode; |
2367 | |
|
2368 | 0 | start_timer(); |
2369 | |
|
2370 | 0 | #ifdef HAVE_PTHREAD |
2371 | 0 | if (pEnc->num_threads > 0) { |
2372 | | |
2373 | | /* multithreaded motion estimation - dispatch threads */ |
2374 | 0 | while (k < pEnc->num_threads) { |
2375 | 0 | int i, add_s = (slices_per_thread + 512) >> 10; |
2376 | 0 | int add_t = (threads_per_slice + 512) >> 10; |
2377 | | |
2378 | 0 | int start_y = (bound * mb_height + (num_slices-1)) / num_slices; |
2379 | 0 | int stop_y = ((bound+add_s) * mb_height + (num_slices-1)) / num_slices; |
2380 | 0 | int rows_per_thread = (stop_y - start_y + add_t - 1) / add_t; |
2381 | |
|
2382 | 0 | slices_per_thread += ((num_slices*1024 / num_threads) - add_s*1024); |
2383 | 0 | threads_per_slice += ((pEnc->num_threads*1024 / num_threads) - add_t*1024); |
2384 | |
|
2385 | 0 | for (i = 0; i < add_t; i++) { |
2386 | 0 | memset(pEnc->smpData[k+i].complete_count_self, 0, rows_per_thread * sizeof(int)); |
2387 | |
|
2388 | 0 | pEnc->smpData[k+i].pEnc = (void *) pEnc; |
2389 | 0 | pEnc->smpData[k+i].current = frame; |
2390 | |
|
2391 | 0 | pEnc->smpData[k+i].y_row = i; |
2392 | 0 | pEnc->smpData[k+i].y_step = add_t; |
2393 | 0 | pEnc->smpData[k+i].stop_y = stop_y; |
2394 | 0 | pEnc->smpData[k+i].start_y = start_y; |
2395 | | |
2396 | | /* todo: sort out temp space once and for all */ |
2397 | 0 | pEnc->smpData[k+i].RefQ = (((k+i)&1) ? pEnc->vInterV.u : pEnc->vInterV.v) + |
2398 | 0 | 16*((k+i)>>1)*pParam->edged_width; |
2399 | 0 | } |
2400 | | |
2401 | 0 | pEnc->smpData[k].complete_count_above = |
2402 | 0 | pEnc->smpData[k+add_t-1].complete_count_self - 1; |
2403 | |
|
2404 | 0 | bound += add_s; |
2405 | 0 | k += add_t; |
2406 | 0 | } |
2407 | |
|
2408 | 0 | for (k = 1; k < pEnc->num_threads; k++) { |
2409 | 0 | pthread_create(&pEnc->smpData[k].handle, NULL, |
2410 | 0 | (void*)SMPMotionEstimationBVOP, (void*)&pEnc->smpData[k]); |
2411 | 0 | } |
2412 | |
|
2413 | 0 | SMPMotionEstimationBVOP(&pEnc->smpData[0]); |
2414 | |
|
2415 | 0 | for (k = 1; k < pEnc->num_threads; k++) { |
2416 | 0 | pthread_join(pEnc->smpData[k].handle, &status); |
2417 | 0 | } |
2418 | |
|
2419 | 0 | frame->fcode = frame->bcode = 0; |
2420 | 0 | for (k = 0; k < pEnc->num_threads; k++) { |
2421 | 0 | if (pEnc->smpData[k].minfcode > frame->fcode) |
2422 | 0 | frame->fcode = pEnc->smpData[k].minfcode; |
2423 | 0 | if (pEnc->smpData[k].minbcode > frame->bcode) |
2424 | 0 | frame->bcode = pEnc->smpData[k].minbcode; |
2425 | 0 | } |
2426 | 0 | } else |
2427 | 0 | #endif |
2428 | 0 | { |
2429 | |
|
2430 | 0 | MotionEstimationBVOP(&pEnc->mbParam, frame, |
2431 | 0 | ((int32_t)(pEnc->current->stamp - frame->stamp)), /* time_bp */ |
2432 | 0 | ((int32_t)(pEnc->current->stamp - pEnc->reference->stamp)), /* time_pp */ |
2433 | 0 | pEnc->reference->mbs, f_ref, |
2434 | 0 | &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv, |
2435 | 0 | pEnc->current, b_ref, &pEnc->vInterH, |
2436 | 0 | &pEnc->vInterV, &pEnc->vInterHV, |
2437 | 0 | pEnc->num_slices); |
2438 | 0 | } |
2439 | 0 | stop_motion_timer(); |
2440 | |
|
2441 | 0 | set_timecodes(frame, pEnc->reference,pEnc->mbParam.fbase); |
2442 | 0 | BitstreamWriteVopHeader(bs, &pEnc->mbParam, frame, 1, frame->quant); |
2443 | | |
2444 | | /* reset stats */ |
2445 | 0 | frame->sStat.iTextBits = 0; |
2446 | 0 | frame->sStat.iMVBits = 0; |
2447 | 0 | frame->sStat.iMvSum = 0; |
2448 | 0 | frame->sStat.iMvCount = 0; |
2449 | 0 | frame->sStat.kblks = frame->sStat.mblks = frame->sStat.ublks = 0; |
2450 | 0 | frame->sStat.mblks = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height; |
2451 | 0 | frame->sStat.kblks = frame->sStat.ublks = 0; |
2452 | | |
2453 | | /* multithreaded inter coding - dispatch threads */ |
2454 | 0 | bound = 0; |
2455 | 0 | slices_per_thread = (num_slices*1024 / num_threads); |
2456 | | |
2457 | 0 | for (k = 0; k < num_threads; k++) { |
2458 | 0 | int add = ((slices_per_thread + 512) >> 10); |
2459 | |
|
2460 | 0 | slices_per_thread += ((num_slices*1024 / num_threads) - add*1024); |
2461 | |
|
2462 | 0 | pEnc->smpData[k].pEnc = (void *) pEnc; |
2463 | 0 | pEnc->smpData[k].current = frame; |
2464 | 0 | pEnc->smpData[k].stop_y = (((bound+add) * mb_height + (num_slices-1)) / num_slices); |
2465 | 0 | pEnc->smpData[k].start_y = ((bound * mb_height + (num_slices-1)) / num_slices); |
2466 | 0 | bound += add; |
2467 | | |
2468 | | /* todo: sort out temp space once and for all */ |
2469 | 0 | pEnc->smpData[k].RefQ = ((k&1) ? pEnc->vInterV.u : pEnc->vInterV.v) + 16*(k>>1)*pParam->edged_width; |
2470 | |
|
2471 | 0 | if (k > 0) { |
2472 | 0 | BitstreamReset(pEnc->smpData[k].bs); |
2473 | 0 | pEnc->smpData[k].sStat->iTextBits = pEnc->smpData[k].sStat->kblks = |
2474 | 0 | pEnc->smpData[k].sStat->mblks = pEnc->smpData[k].sStat->ublks = pEnc->smpData[k].sStat->iMVBits = 0; |
2475 | 0 | } |
2476 | 0 | } |
2477 | |
|
2478 | 0 | #ifdef HAVE_PTHREAD |
2479 | 0 | for (k = 1; k < num_threads; k++) { |
2480 | 0 | pthread_create(&pEnc->smpData[k].handle, NULL, |
2481 | 0 | (void*)SliceCodeB, (void*)&pEnc->smpData[k]); |
2482 | 0 | } |
2483 | 0 | #endif |
2484 | |
|
2485 | 0 | pEnc->smpData[0].bs = bs; |
2486 | 0 | pEnc->smpData[0].sStat = &frame->sStat; |
2487 | 0 | SliceCodeB(&pEnc->smpData[0]); |
2488 | |
|
2489 | 0 | #ifdef HAVE_PTHREAD |
2490 | 0 | for (k = 1; k < num_threads; k++) { |
2491 | 0 | pthread_join(pEnc->smpData[k].handle, &status); |
2492 | 0 | } |
2493 | 0 | #endif |
2494 | |
|
2495 | 0 | frame->length = BitstreamLength(bs) - (bits/8); |
2496 | | |
2497 | | /* reassemble the pieces together */ |
2498 | 0 | SerializeBitstreams(pEnc, frame, bs, num_threads); |
2499 | |
|
2500 | | #ifdef BFRAMES_DEC_DEBUG |
2501 | | if (!first){ |
2502 | | first=1; |
2503 | | if (fp) |
2504 | | fclose(fp); |
2505 | | } |
2506 | | #endif |
2507 | 0 | } |