[cvs] / xvidcore / src / encoder.c Repository:
ViewVC logotype

Annotation of /xvidcore/src/encoder.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.95.2.6 - (view) (download)

1 : edgomez 1.40 /*****************************************************************************
2 : edgomez 1.29 *
3 :     * XVID MPEG-4 VIDEO CODEC
4 : edgomez 1.91 * - Encoder main module -
5 : edgomez 1.29 *
6 : edgomez 1.91 * This program is an implementation of a part of one or more MPEG-4
7 :     * Video tools as specified in ISO/IEC 14496-2 standard. Those intending
8 :     * to use this software module in hardware or software products are
9 :     * advised that its use may infringe existing patents or copyrights, and
10 :     * any such use would be at such party's own risk. The original
11 :     * developer of this software module and his/her company, and subsequent
12 :     * editors and their companies, will have no liability for use of this
13 :     * software or modifications or derivatives thereof.
14 : edgomez 1.77 *
15 : edgomez 1.91 * This program is free software; you can redistribute it and/or modify
16 :     * it under the terms of the GNU General Public License as published by
17 : edgomez 1.29 * the Free Software Foundation; either version 2 of the License, or
18 :     * (at your option) any later version.
19 :     *
20 :     * This program is distributed in the hope that it will be useful,
21 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 :     * GNU General Public License for more details.
24 :     *
25 :     * You should have received a copy of the GNU General Public License
26 :     * along with this program; if not, write to the Free Software
27 :     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 : edgomez 1.79 *
29 : suxen_drol 1.95.2.6 * $Id: encoder.c,v 1.95.2.5 2003/03/15 14:32:56 suxen_drol Exp $
30 : edgomez 1.29 *
31 : edgomez 1.40 ****************************************************************************/
32 : chl 1.64
33 : Isibaar 1.1 #include <stdlib.h>
34 :     #include <stdio.h>
35 :     #include <math.h>
36 : edgomez 1.42 #include <string.h>
37 : Isibaar 1.1
38 :     #include "encoder.h"
39 :     #include "prediction/mbprediction.h"
40 :     #include "global.h"
41 :     #include "utils/timer.h"
42 :     #include "image/image.h"
43 : edgomez 1.91 #include "image/font.h"
44 :     #include "motion/sad.h"
45 : suxen_drol 1.32 #include "motion/motion.h"
46 : Isibaar 1.1 #include "bitstream/cbp.h"
47 :     #include "utils/mbfunctions.h"
48 :     #include "bitstream/bitstream.h"
49 :     #include "bitstream/mbcoding.h"
50 :     #include "utils/emms.h"
51 :     #include "bitstream/mbcoding.h"
52 :     #include "quant/adapt_quant.h"
53 : Isibaar 1.2 #include "quant/quant_matrix.h"
54 : Isibaar 1.7 #include "utils/mem_align.h"
55 : Isibaar 1.1
56 : edgomez 1.40 /*****************************************************************************
57 :     * Local macros
58 :     ****************************************************************************/
59 :    
60 : edgomez 1.91 #define SWAP(_T_,A,B) { _T_ tmp = A; A = B; B = tmp; }
61 : Isibaar 1.1
62 : edgomez 1.40 /*****************************************************************************
63 :     * Local function prototypes
64 :     ****************************************************************************/
65 :    
66 : edgomez 1.39 static int FrameCodeI(Encoder * pEnc,
67 : suxen_drol 1.95.2.1 Bitstream * bs);
68 : edgomez 1.39
69 :     static int FrameCodeP(Encoder * pEnc,
70 : edgomez 1.41 Bitstream * bs,
71 :     bool force_inter,
72 :     bool vol_header);
73 : Isibaar 1.1
74 : edgomez 1.91 static void FrameCodeB(Encoder * pEnc,
75 :     FRAMEINFO * frame,
76 : suxen_drol 1.95.2.1 Bitstream * bs);
77 : edgomez 1.91
78 : edgomez 1.40 /*****************************************************************************
79 :     * Local data
80 :     ****************************************************************************/
81 :    
82 : edgomez 1.41 static int DQtab[4] = {
83 : Isibaar 1.1 -1, -2, 1, 2
84 :     };
85 :    
86 : edgomez 1.41 static int iDQtab[5] = {
87 : Isibaar 1.1 1, 0, NO_CHANGE, 2, 3
88 :     };
89 :    
90 :    
91 : edgomez 1.40 /*****************************************************************************
92 :     * Encoder creation
93 :     *
94 :     * This function creates an Encoder instance, it allocates all necessary
95 : edgomez 1.91 * image buffers (reference, current and bframes) and initialize the internal
96 :     * xvid encoder paremeters according to the XVID_ENC_PARAM input parameter.
97 : edgomez 1.40 *
98 :     * The code seems to be very long but is very basic, mainly memory allocation
99 :     * and cleaning code.
100 :     *
101 :     * Returned values :
102 : suxen_drol 1.95.2.1 * - 0 - no errors
103 : edgomez 1.40 * - XVID_ERR_MEMORY - the libc could not allocate memory, the function
104 :     * cleans the structure before exiting.
105 :     * pParam->handle is also set to NULL.
106 :     *
107 :     ****************************************************************************/
108 :    
109 : suxen_drol 1.95.2.1 /*
110 :     * Simplify the "fincr/fbase" fraction
111 :     */
112 :     static void
113 :     simplify_time(int *inc, int *base)
114 : Isibaar 1.1 {
115 : suxen_drol 1.95.2.1 /* common factor */
116 :     int i = *inc;
117 : edgomez 1.41 while (i > 1) {
118 : suxen_drol 1.95.2.1 if (*inc % i == 0 && *base % i == 0) {
119 :     *inc /= i;
120 :     *base /= i;
121 :     i = *inc;
122 : Isibaar 1.1 continue;
123 :     }
124 :     i--;
125 :     }
126 :    
127 : suxen_drol 1.95.2.1 /* if neccessary, round to 65535 accuracy */
128 :     if (*base > 65535) {
129 :     float div = (float) *base / 65535;
130 :     *base = (int) (*base / div);
131 :     *inc = (int) (*inc / div);
132 : Isibaar 1.1 }
133 : suxen_drol 1.95.2.1 }
134 : Isibaar 1.1
135 :    
136 : suxen_drol 1.95.2.1 int
137 :     enc_create(xvid_enc_create_t * create, xvid_enc_rc_t * rc)
138 :     {
139 :     Encoder *pEnc;
140 :     int n;
141 : Isibaar 1.1
142 : suxen_drol 1.95.2.1 if (XVID_MAJOR(create->version) != 1 || (rc && XVID_MAJOR(rc->version) != 1)) /* v1.x.x */
143 :     return XVID_ERR_VERSION;
144 : edgomez 1.39
145 : suxen_drol 1.95.2.1 if (create->width%2 || create->height%2)
146 :     return XVID_ERR_FAIL;
147 : edgomez 1.39
148 : suxen_drol 1.95.2.1 /* allocate encoder struct */
149 : edgomez 1.41
150 : edgomez 1.39 pEnc = (Encoder *) xvid_malloc(sizeof(Encoder), CACHE_LINE);
151 :     if (pEnc == NULL)
152 : Isibaar 1.1 return XVID_ERR_MEMORY;
153 : edgomez 1.42 memset(pEnc, 0, sizeof(Encoder));
154 :    
155 : suxen_drol 1.95.2.1 /* global flags */
156 :     pEnc->mbParam.global_flags = create->global;
157 : Isibaar 1.1
158 : suxen_drol 1.95.2.1 /* width, height */
159 :     pEnc->mbParam.width = create->width;
160 :     pEnc->mbParam.height = create->height;
161 : Isibaar 1.1 pEnc->mbParam.mb_width = (pEnc->mbParam.width + 15) / 16;
162 :     pEnc->mbParam.mb_height = (pEnc->mbParam.height + 15) / 16;
163 : edgomez 1.41 pEnc->mbParam.edged_width = 16 * pEnc->mbParam.mb_width + 2 * EDGE_SIZE;
164 :     pEnc->mbParam.edged_height = 16 * pEnc->mbParam.mb_height + 2 * EDGE_SIZE;
165 : Isibaar 1.1
166 : suxen_drol 1.95.2.1 /* framerate */
167 :     pEnc->mbParam.fincr = MAX(create->fincr, 0);
168 :     pEnc->mbParam.fbase = create->fincr <= 0 ? 25 : create->fbase;
169 :     simplify_time(&pEnc->mbParam.fincr, &pEnc->mbParam.fbase);
170 :    
171 : suxen_drol 1.95.2.4 /* plugin */
172 :     pEnc->num_plugins = create->num_plugins;
173 :     pEnc->plugins = xvid_malloc(sizeof(xvid_enc_plugin_t) * pEnc->num_plugins, CACHE_LINE);
174 :     if (pEnc->plugins == NULL)
175 :     goto xvid_err_memory0;
176 :    
177 :     for (n=0; n<pEnc->num_plugins;n++) {
178 :     xvid_plg_create_t pcreate;
179 :     xvid_plg_info_t pinfo;
180 :    
181 :     memset(&pinfo, 0, sizeof(xvid_plg_info_t));
182 :     pinfo.version = XVID_VERSION;
183 :     if (create->plugins[n].func(0, XVID_PLG_INFO, &pinfo, 0) >= 0) {
184 : suxen_drol 1.95.2.5 pEnc->mbParam.plugin_flags |= pinfo.flags;
185 : suxen_drol 1.95.2.4 }
186 :    
187 :     memset(&pcreate, 0, sizeof(xvid_plg_create_t));
188 :     pcreate.version = XVID_VERSION;
189 :     pcreate.width = pEnc->mbParam.width;
190 :     pcreate.height = pEnc->mbParam.height;
191 :     pcreate.fincr = pEnc->mbParam.fincr;
192 :     pcreate.fbase = pEnc->mbParam.fbase;
193 :     pcreate.param = create->plugins[n].param;
194 :    
195 :     pEnc->plugins[n].func = NULL; /* disable plugins that fail */
196 :     if (create->plugins[n].func(0, XVID_PLG_CREATE, &pcreate, &pEnc->plugins[n].param) >= 0) {
197 :     pEnc->plugins[n].func = create->plugins[n].func;
198 :     }
199 :     }
200 :    
201 : suxen_drol 1.95.2.6 if ((pEnc->mbParam.global_flags & XVID_EXTRASTATS_ENABLE) ||
202 :     (pEnc->mbParam.plugin_flags & XVID_REQPSNR)) {
203 :     pEnc->mbParam.plugin_flags |= XVID_REQORIGINAL; /* psnr calculation requires the original */
204 :     }
205 :    
206 : suxen_drol 1.95.2.4 /* temp dquants */
207 :     pEnc->temp_dquants = (int *) xvid_malloc(pEnc->mbParam.mb_width *
208 :     pEnc->mbParam.mb_height * sizeof(int), CACHE_LINE);
209 :     /* XXX: error checking */
210 :    
211 : suxen_drol 1.95.2.1 /* bframes */
212 :     pEnc->mbParam.max_bframes = MAX(create->max_bframes, 0);
213 :     pEnc->mbParam.bquant_ratio = MAX(create->bquant_ratio, 0);
214 :     pEnc->mbParam.bquant_offset = create->bquant_offset;
215 :    
216 :     /* frame drop ratio */
217 :     pEnc->mbParam.frame_drop_ratio = MAX(create->frame_drop_ratio, 0);
218 : Isibaar 1.43
219 : suxen_drol 1.95.2.1 /* max keyframe interval */
220 :     pEnc->mbParam.iMaxKeyInterval = create->max_key_interval <=0 ? 250 : create->max_key_interval;
221 :     /*XXX: replace 250 hard code with "10seconds * framerate" */
222 : suxen_drol 1.32
223 : suxen_drol 1.95.2.1 /* Bitrate allocator defaults
224 :    
225 :     if ((create->min_quantizer <= 0) || (create->min_quantizer > 31))
226 :     create->min_quantizer = 1;
227 : Isibaar 1.1
228 : suxen_drol 1.95.2.1 if ((create->max_quantizer <= 0) || (create->max_quantizer > 31))
229 :     create->max_quantizer = 31;
230 : Isibaar 1.1
231 : suxen_drol 1.95.2.1 if (create->max_quantizer < create->min_quantizer)
232 : suxen_drol 1.95.2.5 create->max_quantizer = create->min_quantizer; */
233 : suxen_drol 1.95.2.1
234 : Isibaar 1.1
235 : suxen_drol 1.95.2.1 /* allocate working frame-image memory */
236 : h 1.16
237 : edgomez 1.39 pEnc->current = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);
238 :     pEnc->reference = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);
239 :    
240 : edgomez 1.41 if (pEnc->current == NULL || pEnc->reference == NULL)
241 : edgomez 1.39 goto xvid_err_memory1;
242 : suxen_drol 1.27
243 : suxen_drol 1.95.2.1 /* allocate macroblock memory */
244 : h 1.16
245 : edgomez 1.41 pEnc->current->mbs =
246 :     xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *
247 :     pEnc->mbParam.mb_height, CACHE_LINE);
248 :     pEnc->reference->mbs =
249 :     xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *
250 :     pEnc->mbParam.mb_height, CACHE_LINE);
251 : Isibaar 1.1
252 : edgomez 1.39 if (pEnc->current->mbs == NULL || pEnc->reference->mbs == NULL)
253 :     goto xvid_err_memory2;
254 : suxen_drol 1.27
255 : suxen_drol 1.95.2.1 /* allocate interpolation image memory */
256 : suxen_drol 1.27
257 : suxen_drol 1.95.2.5 if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
258 :     image_null(&pEnc->sOriginal);
259 :     image_null(&pEnc->sOriginal2);
260 :     }
261 : edgomez 1.91
262 :     image_null(&pEnc->f_refh);
263 :     image_null(&pEnc->f_refv);
264 :     image_null(&pEnc->f_refhv);
265 :    
266 : suxen_drol 1.27 image_null(&pEnc->current->image);
267 :     image_null(&pEnc->reference->image);
268 :     image_null(&pEnc->vInterH);
269 :     image_null(&pEnc->vInterV);
270 : edgomez 1.91 image_null(&pEnc->vInterVf);
271 : suxen_drol 1.27 image_null(&pEnc->vInterHV);
272 : edgomez 1.91 image_null(&pEnc->vInterHVf);
273 : edgomez 1.39
274 : suxen_drol 1.95.2.5 if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
275 :     if (image_create
276 : edgomez 1.91 (&pEnc->sOriginal, pEnc->mbParam.edged_width,
277 :     pEnc->mbParam.edged_height) < 0)
278 :     goto xvid_err_memory3;
279 : suxen_drol 1.95.2.5
280 :     if (image_create
281 :     (&pEnc->sOriginal2, pEnc->mbParam.edged_width,
282 :     pEnc->mbParam.edged_height) < 0)
283 :     goto xvid_err_memory3;
284 : edgomez 1.91 }
285 :    
286 :     if (image_create
287 :     (&pEnc->f_refh, pEnc->mbParam.edged_width,
288 :     pEnc->mbParam.edged_height) < 0)
289 :     goto xvid_err_memory3;
290 :     if (image_create
291 :     (&pEnc->f_refv, pEnc->mbParam.edged_width,
292 :     pEnc->mbParam.edged_height) < 0)
293 :     goto xvid_err_memory3;
294 : edgomez 1.41 if (image_create
295 : edgomez 1.91 (&pEnc->f_refhv, pEnc->mbParam.edged_width,
296 : edgomez 1.41 pEnc->mbParam.edged_height) < 0)
297 : edgomez 1.39 goto xvid_err_memory3;
298 : edgomez 1.91
299 : edgomez 1.41 if (image_create
300 :     (&pEnc->current->image, pEnc->mbParam.edged_width,
301 :     pEnc->mbParam.edged_height) < 0)
302 : edgomez 1.39 goto xvid_err_memory3;
303 : edgomez 1.41 if (image_create
304 :     (&pEnc->reference->image, pEnc->mbParam.edged_width,
305 :     pEnc->mbParam.edged_height) < 0)
306 : edgomez 1.39 goto xvid_err_memory3;
307 : edgomez 1.41 if (image_create
308 :     (&pEnc->vInterH, pEnc->mbParam.edged_width,
309 :     pEnc->mbParam.edged_height) < 0)
310 : edgomez 1.39 goto xvid_err_memory3;
311 : edgomez 1.41 if (image_create
312 :     (&pEnc->vInterV, pEnc->mbParam.edged_width,
313 :     pEnc->mbParam.edged_height) < 0)
314 : edgomez 1.39 goto xvid_err_memory3;
315 : edgomez 1.41 if (image_create
316 : edgomez 1.91 (&pEnc->vInterVf, pEnc->mbParam.edged_width,
317 :     pEnc->mbParam.edged_height) < 0)
318 :     goto xvid_err_memory3;
319 :     if (image_create
320 : edgomez 1.41 (&pEnc->vInterHV, pEnc->mbParam.edged_width,
321 :     pEnc->mbParam.edged_height) < 0)
322 : edgomez 1.39 goto xvid_err_memory3;
323 : edgomez 1.91 if (image_create
324 :     (&pEnc->vInterHVf, pEnc->mbParam.edged_width,
325 :     pEnc->mbParam.edged_height) < 0)
326 :     goto xvid_err_memory3;
327 :    
328 :     /* Create full bitplane for GMC, this might be wasteful */
329 :     if (image_create
330 :     (&pEnc->vGMC, pEnc->mbParam.edged_width,
331 :     pEnc->mbParam.edged_height) < 0)
332 :     goto xvid_err_memory3;
333 :    
334 : suxen_drol 1.95.2.1 /* init bframe image buffers */
335 : edgomez 1.91
336 : suxen_drol 1.95.2.1 pEnc->bframenum_head = 0;
337 :     pEnc->bframenum_tail = 0;
338 :     pEnc->flush_bframes = 0;
339 :     pEnc->closed_bframenum = -1;
340 : edgomez 1.91
341 :     /* B Frames specific init */
342 :     pEnc->bframes = NULL;
343 :    
344 :     if (pEnc->mbParam.max_bframes > 0) {
345 :    
346 :     pEnc->bframes =
347 :     xvid_malloc(pEnc->mbParam.max_bframes * sizeof(FRAMEINFO *),
348 :     CACHE_LINE);
349 :    
350 :     if (pEnc->bframes == NULL)
351 :     goto xvid_err_memory3;
352 :    
353 :     for (n = 0; n < pEnc->mbParam.max_bframes; n++)
354 :     pEnc->bframes[n] = NULL;
355 :    
356 :    
357 :     for (n = 0; n < pEnc->mbParam.max_bframes; n++) {
358 :     pEnc->bframes[n] = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);
359 :    
360 :     if (pEnc->bframes[n] == NULL)
361 :     goto xvid_err_memory4;
362 :    
363 :     pEnc->bframes[n]->mbs =
364 :     xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *
365 :     pEnc->mbParam.mb_height, CACHE_LINE);
366 :    
367 :     if (pEnc->bframes[n]->mbs == NULL)
368 :     goto xvid_err_memory4;
369 :    
370 :     image_null(&pEnc->bframes[n]->image);
371 :    
372 :     if (image_create
373 :     (&pEnc->bframes[n]->image, pEnc->mbParam.edged_width,
374 :     pEnc->mbParam.edged_height) < 0)
375 :     goto xvid_err_memory4;
376 :    
377 :     }
378 :     }
379 :    
380 : suxen_drol 1.95.2.1 /* init incoming frame queue */
381 :     pEnc->queue_head = 0;
382 :     pEnc->queue_tail = 0;
383 :     pEnc->queue_size = 0;
384 : edgomez 1.91
385 : suxen_drol 1.95.2.1 pEnc->queue =
386 :     xvid_malloc((pEnc->mbParam.max_bframes+1) * sizeof(QUEUEINFO),
387 :     CACHE_LINE);
388 : edgomez 1.91
389 : suxen_drol 1.95.2.1 if (pEnc->queue == NULL)
390 :     goto xvid_err_memory4;
391 : edgomez 1.91
392 : suxen_drol 1.95.2.1 for (n = 0; n < pEnc->mbParam.max_bframes+1; n++)
393 :     image_null(&pEnc->queue[n].image);
394 : edgomez 1.91
395 : suxen_drol 1.95.2.1
396 :     for (n = 0; n < pEnc->mbParam.max_bframes+1; n++)
397 :     {
398 :     if (image_create
399 :     (&pEnc->queue[n].image, pEnc->mbParam.edged_width,
400 :     pEnc->mbParam.edged_height) < 0)
401 :     goto xvid_err_memory5;
402 : edgomez 1.91
403 :     }
404 :    
405 :    
406 : suxen_drol 1.95.2.1 /* timestamp stuff */
407 : edgomez 1.91
408 : suxen_drol 1.95.2.1 pEnc->mbParam.m_stamp = 0;
409 : edgomez 1.91 pEnc->m_framenum = 0;
410 :     pEnc->current->stamp = 0;
411 :     pEnc->reference->stamp = 0;
412 : edgomez 1.39
413 : suxen_drol 1.95.2.1 /* other stuff */
414 : Isibaar 1.1
415 : suxen_drol 1.95.2.1 pEnc->iFrameNum = 0;
416 :     pEnc->fMvPrevSigma = -1;
417 :    
418 :     create->handle = (void *) pEnc;
419 : Isibaar 1.1
420 : Isibaar 1.6 init_timer();
421 : Isibaar 1.1
422 : suxen_drol 1.95.2.1 return 0; /* ok */
423 : edgomez 1.39
424 :     /*
425 :     * We handle all XVID_ERR_MEMORY here, this makes the code lighter
426 :     */
427 :    
428 : edgomez 1.91 xvid_err_memory5:
429 :    
430 :     if (pEnc->mbParam.max_bframes > 0) {
431 : suxen_drol 1.95.2.1 int i;
432 : edgomez 1.91
433 : suxen_drol 1.95.2.1 for (i = 0; i < pEnc->mbParam.max_bframes+1; i++) {
434 :     image_destroy(&pEnc->queue[i].image, pEnc->mbParam.edged_width,
435 : edgomez 1.91 pEnc->mbParam.edged_height);
436 :     }
437 :     xvid_free(pEnc->queue);
438 :     }
439 :    
440 :     xvid_err_memory4:
441 :    
442 :     if (pEnc->mbParam.max_bframes > 0) {
443 : suxen_drol 1.95.2.1 int i;
444 : edgomez 1.91
445 :     for (i = 0; i < pEnc->mbParam.max_bframes; i++) {
446 :    
447 :     if (pEnc->bframes[i] == NULL)
448 :     continue;
449 :    
450 :     image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width,
451 :     pEnc->mbParam.edged_height);
452 :    
453 :     xvid_free(pEnc->bframes[i]->mbs);
454 :    
455 :     xvid_free(pEnc->bframes[i]);
456 :    
457 :     }
458 :    
459 :     xvid_free(pEnc->bframes);
460 :     }
461 :    
462 : edgomez 1.41 xvid_err_memory3:
463 : edgomez 1.91
464 : suxen_drol 1.95.2.5 if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
465 :     image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width,
466 :     pEnc->mbParam.edged_height);
467 :     image_destroy(&pEnc->sOriginal2, pEnc->mbParam.edged_width,
468 : edgomez 1.91 pEnc->mbParam.edged_height);
469 :     }
470 :    
471 :     image_destroy(&pEnc->f_refh, pEnc->mbParam.edged_width,
472 :     pEnc->mbParam.edged_height);
473 :     image_destroy(&pEnc->f_refv, pEnc->mbParam.edged_width,
474 :     pEnc->mbParam.edged_height);
475 :     image_destroy(&pEnc->f_refhv, pEnc->mbParam.edged_width,
476 : edgomez 1.41 pEnc->mbParam.edged_height);
477 : edgomez 1.39
478 : edgomez 1.41 image_destroy(&pEnc->current->image, pEnc->mbParam.edged_width,
479 :     pEnc->mbParam.edged_height);
480 :     image_destroy(&pEnc->reference->image, pEnc->mbParam.edged_width,
481 :     pEnc->mbParam.edged_height);
482 :     image_destroy(&pEnc->vInterH, pEnc->mbParam.edged_width,
483 :     pEnc->mbParam.edged_height);
484 :     image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width,
485 :     pEnc->mbParam.edged_height);
486 : edgomez 1.91 image_destroy(&pEnc->vInterVf, pEnc->mbParam.edged_width,
487 :     pEnc->mbParam.edged_height);
488 : edgomez 1.41 image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width,
489 :     pEnc->mbParam.edged_height);
490 : edgomez 1.91 image_destroy(&pEnc->vInterHVf, pEnc->mbParam.edged_width,
491 :     pEnc->mbParam.edged_height);
492 :    
493 :     /* destroy GMC image */
494 :     image_destroy(&pEnc->vGMC, pEnc->mbParam.edged_width,
495 :     pEnc->mbParam.edged_height);
496 :    
497 : edgomez 1.39
498 : edgomez 1.41 xvid_err_memory2:
499 : edgomez 1.39 xvid_free(pEnc->current->mbs);
500 :     xvid_free(pEnc->reference->mbs);
501 :    
502 : edgomez 1.41 xvid_err_memory1:
503 : edgomez 1.39 xvid_free(pEnc->current);
504 :     xvid_free(pEnc->reference);
505 : suxen_drol 1.95.2.4
506 :     xvid_free(pEnc->temp_dquants);
507 :    
508 :     xvid_err_memory0:
509 :     for (n=0; n<pEnc->num_plugins;n++) {
510 :     if (pEnc->plugins[n].func) {
511 :     pEnc->plugins[n].func(pEnc->plugins[n].param, XVID_PLG_DESTROY, 0, 0);
512 :     }
513 :     }
514 :     xvid_free(pEnc->plugins);
515 :    
516 : edgomez 1.39 xvid_free(pEnc);
517 :    
518 : suxen_drol 1.95.2.1 create->handle = NULL;
519 : edgomez 1.40
520 : edgomez 1.39 return XVID_ERR_MEMORY;
521 : Isibaar 1.1 }
522 :    
523 : edgomez 1.40 /*****************************************************************************
524 :     * Encoder destruction
525 :     *
526 :     * This function destroy the entire encoder structure created by a previous
527 : suxen_drol 1.95.2.1 * successful enc_create call.
528 : edgomez 1.40 *
529 :     * Returned values (for now only one returned value) :
530 : suxen_drol 1.95.2.1 * - 0 - no errors
531 : edgomez 1.40 *
532 :     ****************************************************************************/
533 :    
534 :     int
535 : suxen_drol 1.95.2.1 enc_destroy(Encoder * pEnc)
536 : Isibaar 1.1 {
537 : edgomez 1.91 int i;
538 : suxen_drol 1.44
539 : edgomez 1.91 /* B Frames specific */
540 :     if (pEnc->mbParam.max_bframes > 0) {
541 :    
542 : suxen_drol 1.95.2.1 for (i = 0; i < pEnc->mbParam.max_bframes+1; i++) {
543 : edgomez 1.91
544 : suxen_drol 1.95.2.1 image_destroy(&pEnc->queue[i].image, pEnc->mbParam.edged_width,
545 : edgomez 1.91 pEnc->mbParam.edged_height);
546 :     }
547 :     xvid_free(pEnc->queue);
548 :     }
549 :    
550 :    
551 :     if (pEnc->mbParam.max_bframes > 0) {
552 :    
553 :     for (i = 0; i < pEnc->mbParam.max_bframes; i++) {
554 :    
555 :     if (pEnc->bframes[i] == NULL)
556 :     continue;
557 :    
558 :     image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width,
559 :     pEnc->mbParam.edged_height);
560 :    
561 :     xvid_free(pEnc->bframes[i]->mbs);
562 :    
563 :     xvid_free(pEnc->bframes[i]);
564 :     }
565 :    
566 :     xvid_free(pEnc->bframes);
567 :    
568 :     }
569 :    
570 : edgomez 1.39 /* All images, reference, current etc ... */
571 : edgomez 1.91
572 : edgomez 1.41 image_destroy(&pEnc->current->image, pEnc->mbParam.edged_width,
573 :     pEnc->mbParam.edged_height);
574 :     image_destroy(&pEnc->reference->image, pEnc->mbParam.edged_width,
575 :     pEnc->mbParam.edged_height);
576 :     image_destroy(&pEnc->vInterH, pEnc->mbParam.edged_width,
577 :     pEnc->mbParam.edged_height);
578 :     image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width,
579 :     pEnc->mbParam.edged_height);
580 : edgomez 1.91 image_destroy(&pEnc->vInterVf, pEnc->mbParam.edged_width,
581 :     pEnc->mbParam.edged_height);
582 : edgomez 1.41 image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width,
583 :     pEnc->mbParam.edged_height);
584 : edgomez 1.91 image_destroy(&pEnc->vInterHVf, pEnc->mbParam.edged_width,
585 :     pEnc->mbParam.edged_height);
586 : edgomez 1.78
587 : edgomez 1.91 image_destroy(&pEnc->f_refh, pEnc->mbParam.edged_width,
588 : edgomez 1.41 pEnc->mbParam.edged_height);
589 : edgomez 1.91 image_destroy(&pEnc->f_refv, pEnc->mbParam.edged_width,
590 :     pEnc->mbParam.edged_height);
591 :     image_destroy(&pEnc->f_refhv, pEnc->mbParam.edged_width,
592 :     pEnc->mbParam.edged_height);
593 :    
594 : suxen_drol 1.95.2.5 if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
595 :     image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width,
596 :     pEnc->mbParam.edged_height);
597 :     image_destroy(&pEnc->sOriginal2, pEnc->mbParam.edged_width,
598 : edgomez 1.91 pEnc->mbParam.edged_height);
599 :     }
600 : edgomez 1.39
601 :     /* Encoder structure */
602 : edgomez 1.91
603 : suxen_drol 1.27 xvid_free(pEnc->current->mbs);
604 :     xvid_free(pEnc->current);
605 :    
606 :     xvid_free(pEnc->reference->mbs);
607 :     xvid_free(pEnc->reference);
608 : suxen_drol 1.95.2.4
609 :     xvid_free(pEnc->temp_dquants);
610 :    
611 :     for (i=0; i<pEnc->num_plugins;i++) {
612 :     if (pEnc->plugins[i].func) {
613 :     pEnc->plugins[i].func(pEnc->plugins[i].param, XVID_PLG_DESTROY, 0, 0);
614 :     }
615 :     }
616 :     xvid_free(pEnc->plugins);
617 : suxen_drol 1.27
618 : Isibaar 1.7 xvid_free(pEnc);
619 : edgomez 1.39
620 : suxen_drol 1.95.2.1 return 0; /* ok */
621 : Isibaar 1.1 }
622 :    
623 : suxen_drol 1.44
624 : suxen_drol 1.95.2.4 /*
625 :     call the plugins
626 :     */
627 :    
628 : suxen_drol 1.95.2.6 static void call_plugins(Encoder * pEnc, FRAMEINFO * frame, IMAGE * original,
629 :     int opt, int * type, int * quant, xvid_enc_stats_t * stats)
630 : suxen_drol 1.95.2.4 {
631 :     int i;
632 :     xvid_plg_data_t data;
633 :    
634 :     memset(&data, 0, sizeof(xvid_plg_data_t));
635 :     data.version = XVID_VERSION;
636 :    
637 : suxen_drol 1.95.2.5 data.width = pEnc->mbParam.width;
638 :     data.height = pEnc->mbParam.height;
639 :     data.fincr = pEnc->mbParam.fincr;
640 :     data.fbase = pEnc->mbParam.fbase;
641 :    
642 : suxen_drol 1.95.2.4 data.reference.csp = XVID_CSP_USER;
643 :     data.reference.plane[0] = pEnc->reference->image.y;
644 :     data.reference.plane[1] = pEnc->reference->image.u;
645 :     data.reference.plane[2] = pEnc->reference->image.v;
646 :     data.reference.stride[0] = pEnc->mbParam.edged_width;
647 :     data.reference.stride[1] = pEnc->mbParam.edged_width/2;
648 :     data.reference.stride[2] = pEnc->mbParam.edged_width/2;
649 :    
650 :     data.current.csp = XVID_CSP_USER;
651 :     data.current.plane[0] = frame->image.y;
652 :     data.current.plane[1] = frame->image.u;
653 :     data.current.plane[2] = frame->image.v;
654 :     data.current.stride[0] = pEnc->mbParam.edged_width;
655 :     data.current.stride[1] = pEnc->mbParam.edged_width/2;
656 :     data.current.stride[2] = pEnc->mbParam.edged_width/2;
657 :    
658 : suxen_drol 1.95.2.5 data.frame_num = frame->frame_num;
659 : suxen_drol 1.95.2.4
660 :     if (opt == XVID_PLG_BEFORE) {
661 :     data.type = XVID_TYPE_AUTO;
662 :     data.quant = 2;
663 :     //memset(pEnc->temp_dquants, NO_CHANGE, pEnc->mbParam.width * pEnc->mbParam.height);
664 :     //data.qscale_stride = pEnc->mbParam.width;
665 :     //data.qscale_table = pEnc->temp_dquants;
666 :     /* todo: vol,vop,motion flags */
667 :    
668 :     } else { // XVID_PLG_AFTER
669 : suxen_drol 1.95.2.5 if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
670 :     data.original.csp = XVID_CSP_USER;
671 :     data.original.plane[0] = original->y;
672 :     data.original.plane[1] = original->u;
673 :     data.original.plane[2] = original->v;
674 :     data.original.stride[0] = pEnc->mbParam.edged_width;
675 :     data.original.stride[1] = pEnc->mbParam.edged_width/2;
676 :     data.original.stride[2] = pEnc->mbParam.edged_width/2;
677 :     }
678 : suxen_drol 1.95.2.4
679 : suxen_drol 1.95.2.6 if ((frame->vol_flags & XVID_EXTRASTATS) ||
680 :     (pEnc->mbParam.plugin_flags & XVID_REQPSNR)) {
681 :    
682 :     data.sse_y =
683 :     plane_sse( original->y, frame->image.y,
684 :     pEnc->mbParam.edged_width, pEnc->mbParam.width,
685 :     pEnc->mbParam.height);
686 :    
687 :     data.sse_u =
688 :     plane_sse( original->u, frame->image.u,
689 :     pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2,
690 :     pEnc->mbParam.height/2);
691 :    
692 :     data.sse_v =
693 :     plane_sse( original->v, frame->image.v,
694 :     pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2,
695 :     pEnc->mbParam.height/2);
696 :     }
697 :    
698 : suxen_drol 1.95.2.4 data.type = coding2type(frame->coding_type);
699 :     data.quant = frame->quant;
700 :     /* todo: data.qscale */
701 :     data.vol_flags = frame->vol_flags;
702 :     data.vop_flags = frame->vop_flags;
703 :     data.motion_flags = frame->motion_flags;
704 :    
705 :     data.length = frame->length;
706 :     data.kblks = frame->sStat.kblks;
707 :     data.mblks = frame->sStat.mblks;
708 :     data.ublks = frame->sStat.ublks;
709 : suxen_drol 1.95.2.6
710 :     if (stats)
711 :     {
712 :     stats->type = coding2type(frame->coding_type);
713 :     stats->quant = frame->quant;
714 :     stats->vol_flags = frame->vol_flags;
715 :     stats->vop_flags = frame->vop_flags;
716 :     stats->length = frame->length;
717 :     stats->hlength = frame->length - (frame->sStat.iTextBits / 8);
718 :     stats->kblks = frame->sStat.kblks;
719 :     stats->mblks = frame->sStat.mblks;
720 :     stats->ublks = frame->sStat.ublks;
721 :     stats->sse_y = data.sse_y;
722 :     stats->sse_u = data.sse_u;
723 :     stats->sse_v = data.sse_v;
724 :     }
725 : suxen_drol 1.95.2.4 }
726 :    
727 : suxen_drol 1.95.2.6 emms();
728 : suxen_drol 1.95.2.4 for (i=0; i<pEnc->num_plugins;i++) {
729 :     if (pEnc->plugins[i].func) {
730 :     if (pEnc->plugins[i].func(pEnc->plugins[i].param, opt, &data, 0) < 0) {
731 :     continue;
732 :     }
733 :     }
734 :     }
735 : suxen_drol 1.95.2.6 emms();
736 : suxen_drol 1.95.2.4
737 :     if (opt == XVID_PLG_BEFORE) {
738 :     *type = data.type;
739 :     *quant = data.quant;
740 :     /* todo: copy modified qscale,vol,vop,motion flags into the frame*/
741 :     }
742 :    
743 :     }
744 :    
745 :    
746 :    
747 :    
748 : edgomez 1.91 static __inline void inc_frame_num(Encoder * pEnc)
749 :     {
750 : suxen_drol 1.95.2.5 pEnc->current->frame_num = pEnc->m_framenum;
751 : edgomez 1.93 pEnc->current->stamp = pEnc->mbParam.m_stamp; /* first frame is zero */
752 : suxen_drol 1.95.2.5
753 :     pEnc->mbParam.m_stamp += pEnc->mbParam.fincr;
754 : suxen_drol 1.95.2.1 pEnc->m_framenum++; /* debug ticker */
755 :     }
756 : edgomez 1.91
757 : suxen_drol 1.95.2.5 static __inline void dec_frame_num(Encoder * pEnc)
758 :     {
759 :     pEnc->mbParam.m_stamp -= pEnc->mbParam.fincr;
760 :     pEnc->m_framenum--; /* debug ticker */
761 :     }
762 :    
763 : edgomez 1.92
764 : edgomez 1.91
765 :     static __inline void
766 :     set_timecodes(FRAMEINFO* pCur,FRAMEINFO *pRef, int32_t time_base)
767 :     {
768 :    
769 :     pCur->ticks = (int32_t)pCur->stamp % time_base;
770 :     pCur->seconds = ((int32_t)pCur->stamp / time_base) - ((int32_t)pRef->stamp / time_base) ;
771 :    
772 : edgomez 1.93 /* HEAVY DEBUG OUTPUT remove when timecodes prove to be stable */
773 : edgomez 1.91
774 :     /* fprintf(stderr,"WriteVop: %d - %d \n",
775 :     ((int32_t)pCur->stamp / time_base), ((int32_t)pRef->stamp / time_base));
776 :     fprintf(stderr,"set_timecodes: VOP %1d stamp=%lld ref_stamp=%lld base=%d\n",
777 :     pCur->coding_type, pCur->stamp, pRef->stamp, time_base);
778 :     fprintf(stderr,"set_timecodes: VOP %1d seconds=%d ticks=%d (ref-sec=%d ref-tick=%d)\n",
779 :     pCur->coding_type, pCur->seconds, pCur->ticks, pRef->seconds, pRef->ticks);
780 :    
781 :     */
782 :     }
783 :    
784 :    
785 :    
786 :     /*****************************************************************************
787 :     * IPB frame encoder entry point
788 :     *
789 :     * Returned values :
790 : suxen_drol 1.95.2.1 * - >0 - output bytes
791 :     * - 0 - no output
792 : edgomez 1.95.2.2 * - XVID_ERR_VERSION - wrong version passed to core
793 :     * - XVID_ERR_END - End of stream reached before end of coding
794 : suxen_drol 1.95.2.1 * - XVID_ERR_FORMAT - the image subsystem reported the image had a wrong
795 : edgomez 1.95.2.2 * format
796 : edgomez 1.91 ****************************************************************************/
797 :    
798 : suxen_drol 1.95.2.1
799 : edgomez 1.91 int
800 : suxen_drol 1.95.2.1 enc_encode(Encoder * pEnc,
801 :     xvid_enc_frame_t * xFrame,
802 :     xvid_enc_stats_t * stats)
803 : edgomez 1.91 {
804 : suxen_drol 1.95.2.1 xvid_enc_frame_t * frame;
805 :     int type;
806 : edgomez 1.91 Bitstream bs;
807 :    
808 : suxen_drol 1.95.2.1 if (XVID_MAJOR(xFrame->version) != 1 || (stats && XVID_MAJOR(stats->version) != 1)) /* v1.x.x */
809 :     return XVID_ERR_VERSION;
810 : edgomez 1.91
811 : suxen_drol 1.95.2.1 xFrame->out_flags = 0;
812 : edgomez 1.91
813 :     start_global_timer();
814 : suxen_drol 1.95.2.1 BitstreamInit(&bs, xFrame->bitstream, 0);
815 : edgomez 1.91
816 :    
817 : suxen_drol 1.95.2.1 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
818 :     * enqueue image to the encoding-queue
819 :     * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
820 : edgomez 1.91
821 : suxen_drol 1.95.2.1 if (xFrame->input.csp != XVID_CSP_NULL)
822 :     {
823 :     QUEUEINFO * q = &pEnc->queue[pEnc->queue_tail];
824 : edgomez 1.91
825 : suxen_drol 1.95.2.1 start_timer();
826 :     if (image_input
827 :     (&q->image, pEnc->mbParam.width, pEnc->mbParam.height,
828 :     pEnc->mbParam.edged_width, (uint8_t**)xFrame->input.plane, xFrame->input.stride,
829 :     xFrame->input.csp, xFrame->vol_flags & XVID_INTERLACING))
830 :     {
831 :     emms();
832 :     return XVID_ERR_FORMAT;
833 :     }
834 :     stop_conv_timer();
835 : edgomez 1.91
836 : suxen_drol 1.95.2.1 if ((xFrame->vop_flags & XVID_CHROMAOPT)) {
837 :     image_chroma_optimize(&q->image,
838 :     pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width);
839 :     }
840 :    
841 :     q->frame = *xFrame;
842 : edgomez 1.91
843 : suxen_drol 1.95.2.1 if (xFrame->quant_intra_matrix)
844 :     {
845 :     memcpy(q->quant_intra_matrix, xFrame->quant_intra_matrix, sizeof(xFrame->quant_intra_matrix));
846 :     q->frame.quant_intra_matrix = q->quant_intra_matrix;
847 :     }
848 : edgomez 1.91
849 : suxen_drol 1.95.2.1 if (xFrame->quant_inter_matrix)
850 :     {
851 :     memcpy(q->quant_inter_matrix, xFrame->quant_inter_matrix, sizeof(xFrame->quant_inter_matrix));
852 :     q->frame.quant_inter_matrix = q->quant_inter_matrix;
853 :     }
854 : edgomez 1.91
855 : suxen_drol 1.95.2.1 pEnc->queue_tail = (pEnc->queue_tail + 1) % (pEnc->mbParam.max_bframes+1);
856 :     pEnc->queue_size++;
857 :     }
858 : edgomez 1.91
859 :    
860 : suxen_drol 1.95.2.1 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861 : suxen_drol 1.95.2.5 * bframe flush code
862 : suxen_drol 1.95.2.1 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
863 : edgomez 1.91
864 : suxen_drol 1.95.2.1 repeat:
865 : edgomez 1.91
866 : suxen_drol 1.95.2.1 if (pEnc->flush_bframes)
867 :     {
868 : suxen_drol 1.95.2.5 if (pEnc->bframenum_head < pEnc->bframenum_tail) {
869 : edgomez 1.91
870 : suxen_drol 1.95.2.1 DPRINTF(DPRINTF_DEBUG,"*** BFRAME (flush) bf: head=%i tail=%i queue: head=%i tail=%i size=%i",
871 :     pEnc->bframenum_head, pEnc->bframenum_tail,
872 :     pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
873 : edgomez 1.91
874 : suxen_drol 1.95.2.5 if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
875 :     image_copy(&pEnc->sOriginal2, &pEnc->bframes[pEnc->bframenum_head]->image,
876 : edgomez 1.95.2.3 pEnc->mbParam.edged_width, pEnc->mbParam.height);
877 :     }
878 :    
879 : suxen_drol 1.95.2.1 FrameCodeB(pEnc, pEnc->bframes[pEnc->bframenum_head], &bs);
880 : suxen_drol 1.95.2.6 call_plugins(pEnc, pEnc->bframes[pEnc->bframenum_head], &pEnc->sOriginal2, XVID_PLG_AFTER, 0, 0, stats);
881 : suxen_drol 1.95.2.1 pEnc->bframenum_head++;
882 : edgomez 1.91
883 : suxen_drol 1.95.2.1 goto done;
884 :     }
885 : edgomez 1.91
886 :     /* write an empty marker to the bitstream.
887 : suxen_drol 1.95.2.1
888 : edgomez 1.91 for divx5 decoder compatibility, this marker must consist
889 :     of a not-coded p-vop, with a time_base of zero, and time_increment
890 :     indentical to the future-referece frame.
891 :     */
892 :    
893 : suxen_drol 1.95.2.5 if ((pEnc->mbParam.global_flags & XVID_PACKED && pEnc->bframenum_tail > 0)) {
894 : edgomez 1.91 int tmp;
895 : suxen_drol 1.95.2.1 int bits;
896 : edgomez 1.91
897 :     DPRINTF(DPRINTF_DEBUG,"*** EMPTY bf: head=%i tail=%i queue: head=%i tail=%i size=%i",
898 :     pEnc->bframenum_head, pEnc->bframenum_tail,
899 :     pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
900 :    
901 : suxen_drol 1.95.2.1 bits = BitstreamPos(&bs);
902 :    
903 : edgomez 1.91 tmp = pEnc->current->seconds;
904 :     pEnc->current->seconds = 0; /* force time_base = 0 */
905 :    
906 :     BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0);
907 : suxen_drol 1.95.2.1 BitstreamPad(&bs);
908 : edgomez 1.91 pEnc->current->seconds = tmp;
909 :    
910 : suxen_drol 1.95.2.1 /* add the not-coded length to the reference frame size */
911 :     pEnc->current->length += (BitstreamPos(&bs) - bits) / 8;
912 : suxen_drol 1.95.2.6 call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats);
913 : edgomez 1.91
914 : suxen_drol 1.95.2.5 /* flush complete: reset counters */
915 :     pEnc->flush_bframes = 0;
916 :     pEnc->bframenum_head = pEnc->bframenum_tail = 0;
917 : suxen_drol 1.95.2.1 goto done;
918 : edgomez 1.91
919 :     }
920 :    
921 : suxen_drol 1.95.2.5 /* flush complete: reset counters */
922 :     pEnc->flush_bframes = 0;
923 :     pEnc->bframenum_head = pEnc->bframenum_tail = 0;
924 :     }
925 : edgomez 1.91
926 : suxen_drol 1.95.2.1 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
927 :     * dequeue frame from the encoding queue
928 :     * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
929 : edgomez 1.91
930 : suxen_drol 1.95.2.1 if (pEnc->queue_size == 0) /* empty */
931 : edgomez 1.91 {
932 : suxen_drol 1.95.2.1 if (xFrame->input.csp == XVID_CSP_NULL) /* no futher input */
933 : edgomez 1.91 {
934 : suxen_drol 1.95.2.5
935 :     if (!(pEnc->mbParam.global_flags & XVID_PACKED) && pEnc->mbParam.max_bframes > 0) {
936 : suxen_drol 1.95.2.6 call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats);
937 : suxen_drol 1.95.2.5 }
938 :    
939 :     /* if the very last frame is to be b-vop, we must change it to a p-vop */
940 :     if (pEnc->bframenum_tail > 0)
941 : suxen_drol 1.95.2.1 {
942 : suxen_drol 1.95.2.5
943 : suxen_drol 1.95.2.1 SWAP(FRAMEINFO*, pEnc->current, pEnc->reference);
944 :     pEnc->bframenum_tail--;
945 :     SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]);
946 : edgomez 1.91
947 : suxen_drol 1.95.2.5 /* convert B-VOP to P-VOP */
948 :     pEnc->current->quant = ((pEnc->current->quant*100) - pEnc->mbParam.bquant_offset) / pEnc->mbParam.bquant_ratio;
949 :    
950 :     if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
951 :     image_copy(&pEnc->sOriginal, &pEnc->current->image,
952 :     pEnc->mbParam.edged_width, pEnc->mbParam.height);
953 :     }
954 : edgomez 1.91
955 : suxen_drol 1.95.2.1 FrameCodeP(pEnc, &bs, 1, 0);
956 : suxen_drol 1.95.2.5
957 : suxen_drol 1.95.2.1 goto done_flush;
958 :     }
959 : suxen_drol 1.95.2.5
960 : edgomez 1.91 emms();
961 : suxen_drol 1.95.2.1 return XVID_ERR_END; /* end of stream reached */
962 : edgomez 1.91 }
963 : suxen_drol 1.95.2.1 goto done; /* nothing to encode yet; encoder lag */
964 :     }
965 : edgomez 1.91
966 : suxen_drol 1.95.2.1 // the current FRAME becomes the reference
967 :     SWAP(FRAMEINFO*, pEnc->current, pEnc->reference);
968 : edgomez 1.92
969 : suxen_drol 1.95.2.1 // remove frame from encoding-queue (head), and move it into the current
970 :     image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image);
971 :     frame = &pEnc->queue[pEnc->queue_head].frame;
972 : suxen_drol 1.95.2.5 pEnc->queue_head = (pEnc->queue_head + 1) % (pEnc->mbParam.max_bframes+1);
973 : suxen_drol 1.95.2.1 pEnc->queue_size--;
974 : edgomez 1.91
975 :    
976 : suxen_drol 1.95.2.1 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977 : suxen_drol 1.95.2.5 * init pEnc->current fields
978 : suxen_drol 1.95.2.1 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
979 : edgomez 1.91
980 : suxen_drol 1.95.2.1 pEnc->current->vol_flags = pEnc->mbParam.vol_flags;
981 :     pEnc->current->vop_flags = frame->vop_flags;
982 :     pEnc->current->motion_flags = frame->motion;
983 :     pEnc->current->fcode = pEnc->mbParam.m_fcode;
984 :     pEnc->current->bcode = pEnc->mbParam.m_fcode;
985 : edgomez 1.91
986 : suxen_drol 1.95.2.1 if ((xFrame->vop_flags & XVID_CHROMAOPT)) {
987 :     image_chroma_optimize(&pEnc->current->image,
988 :     pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width);
989 :     }
990 :    
991 : suxen_drol 1.95.2.5 emms(); /* float-point region */
992 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_LUMIMASKING)) {
993 : suxen_drol 1.95.2.5 unsigned int x, y;
994 : edgomez 1.91
995 : suxen_drol 1.95.2.1 pEnc->current->quant =
996 :     adaptive_quantization(pEnc->current->image.y,
997 : suxen_drol 1.95.2.4 pEnc->mbParam.edged_width, pEnc->temp_dquants,
998 : suxen_drol 1.95.2.1 pEnc->current->quant, pEnc->current->quant,
999 :     2 * pEnc->current->quant,
1000 :     pEnc->mbParam.mb_width,
1001 :     pEnc->mbParam.mb_height);
1002 : edgomez 1.91
1003 : suxen_drol 1.95.2.1 for (y = 0; y < pEnc->mbParam.mb_height; y++) {
1004 : edgomez 1.91
1005 : suxen_drol 1.95.2.1 #define OFFSET(x,y) ((x) + (y)*pEnc->mbParam.mb_width)
1006 : edgomez 1.91
1007 : suxen_drol 1.95.2.1 for (x = 0; x < pEnc->mbParam.mb_width; x++) {
1008 :     MACROBLOCK *pMB = &pEnc->current->mbs[OFFSET(x, y)];
1009 :    
1010 : suxen_drol 1.95.2.4 pMB->dquant = iDQtab[pEnc->temp_dquants[OFFSET(x, y)] + 2];
1011 : edgomez 1.91 }
1012 :    
1013 : suxen_drol 1.95.2.1 #undef OFFSET
1014 : edgomez 1.91 }
1015 :    
1016 : suxen_drol 1.95.2.1 }
1017 : suxen_drol 1.95.2.6 emms(); /* END floating-point region */
1018 : edgomez 1.91
1019 : suxen_drol 1.95.2.5 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1020 :     * frame type & quant selection
1021 :     * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1022 :    
1023 : suxen_drol 1.95.2.6 call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_BEFORE, &type, &pEnc->current->quant, stats);
1024 : edgomez 1.91
1025 : suxen_drol 1.95.2.4 if (frame->type > 0)
1026 :     type = frame->type;
1027 :    
1028 :     if (frame->quant > 0)
1029 :     pEnc->current->quant = frame->quant;
1030 : edgomez 1.91
1031 : suxen_drol 1.95.2.5 if (type > 0){ /* XVID_TYPE_?VOP */
1032 : suxen_drol 1.95.2.1 type = type2coding(type); /* convert XVID_TYPE_?VOP to bitstream coding type */
1033 : suxen_drol 1.95.2.5 } else{ /* XVID_TYPE_AUTO */
1034 :     if (pEnc->iFrameNum == 0 || (pEnc->mbParam.iMaxKeyInterval > 0 && pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval)){
1035 : suxen_drol 1.95.2.1 pEnc->iFrameNum = 0;
1036 :     type = I_VOP;
1037 :     }else{
1038 :     type = MEanalysis(&pEnc->reference->image, pEnc->current,
1039 :     &pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval,
1040 :     pEnc->iFrameNum, pEnc->bframenum_tail);
1041 : suxen_drol 1.95.2.5
1042 :     if (type == B_VOP && !(pEnc->current->vop_flags & XVID_DYNAMIC_BFRAMES)) {
1043 :     type = P_VOP; /* disable dynamic bframes */
1044 :     }
1045 : edgomez 1.91 }
1046 : suxen_drol 1.95.2.1 }
1047 : suxen_drol 1.95.2.5
1048 :     /* bframes buffer overflow check */
1049 :     if (type != I_VOP) {
1050 :     if (pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) {
1051 :     type = P_VOP;
1052 :     }else{
1053 :     type = B_VOP;
1054 :     }
1055 :     }
1056 :    
1057 : suxen_drol 1.95.2.1 inc_frame_num(pEnc);
1058 :     pEnc->iFrameNum++;
1059 : edgomez 1.91
1060 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_DEBUG)) {
1061 :     image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 5,
1062 : suxen_drol 1.95.2.5 "%i st:%i if:%i", pEnc->current->frame_num, pEnc->current->stamp, pEnc->iFrameNum);
1063 : edgomez 1.91 }
1064 :    
1065 :     /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1066 : suxen_drol 1.95.2.5 * encode this frame as a b-vop
1067 :     * (we dont encode here, rather we store the frame in the bframes queue, to be encoded later)
1068 : edgomez 1.91 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1069 : suxen_drol 1.95.2.5 if (type == B_VOP) {
1070 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_DEBUG)) {
1071 : suxen_drol 1.95.2.5 image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "BVOP");
1072 : edgomez 1.91 }
1073 :    
1074 : suxen_drol 1.95.2.5 if (frame->bquant < 1) {
1075 :     pEnc->current->quant = ((((pEnc->reference->quant + pEnc->current->quant) *
1076 :     pEnc->mbParam.bquant_ratio) / 2) + pEnc->mbParam.bquant_offset)/100;
1077 : suxen_drol 1.95.2.1
1078 : suxen_drol 1.95.2.5 } else {
1079 :     pEnc->current->quant = frame->bquant;
1080 :     }
1081 : edgomez 1.91
1082 : suxen_drol 1.95.2.5 if (pEnc->current->quant < 1)
1083 :     pEnc->current->quant = 1;
1084 :     else if (pEnc->current->quant > 31)
1085 :     pEnc->current->quant = 31;
1086 :    
1087 :     DPRINTF(DPRINTF_DEBUG,"*** BFRAME (store) bf: head=%i tail=%i queue: head=%i tail=%i size=%i quant=%i",
1088 :     pEnc->bframenum_head, pEnc->bframenum_tail,
1089 :     pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size,pEnc->current->quant);
1090 : edgomez 1.91
1091 : suxen_drol 1.95.2.5 /* store frame into bframe buffer & swap ref back to current */
1092 :     SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]);
1093 :     SWAP(FRAMEINFO*, pEnc->current, pEnc->reference);
1094 : edgomez 1.91
1095 : suxen_drol 1.95.2.5 pEnc->bframenum_tail++;
1096 : edgomez 1.91
1097 : suxen_drol 1.95.2.5 goto repeat;
1098 :     }
1099 : suxen_drol 1.95.2.1
1100 : suxen_drol 1.95.2.5 /* for unpacked bframes, output the stats for the last encoded frame */
1101 :     if (!(pEnc->mbParam.global_flags & XVID_PACKED) && pEnc->bframenum_tail > 0)
1102 :     {
1103 :     if (pEnc->current->stamp > 0) {
1104 : suxen_drol 1.95.2.6 call_plugins(pEnc, pEnc->reference, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats);
1105 : suxen_drol 1.95.2.5 }
1106 :     else
1107 :     stats->type = XVID_TYPE_NOTHING;
1108 :     }
1109 : edgomez 1.91
1110 : suxen_drol 1.95.2.5 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111 :     * closed-gop
1112 :     * if the frame prior to an iframe is scheduled as a bframe, we must change it to a pframe
1113 :     * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1114 : edgomez 1.91
1115 : suxen_drol 1.95.2.5 if (type == I_VOP && (pEnc->mbParam.global_flags & XVID_CLOSED_GOP) && pEnc->bframenum_tail > 0) {
1116 : suxen_drol 1.95.2.1
1117 : suxen_drol 1.95.2.5 // place this frame back on the encoding-queue (head)
1118 :     // we will deal with it next time
1119 :     pEnc->queue_head = (pEnc->queue_head + (pEnc->mbParam.max_bframes+1) - 1) % (pEnc->mbParam.max_bframes+1);
1120 :     pEnc->queue_size++;
1121 :     image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image);
1122 : edgomez 1.91
1123 : suxen_drol 1.95.2.5 dec_frame_num(pEnc);
1124 :     pEnc->iFrameNum--;
1125 : edgomez 1.91
1126 : suxen_drol 1.95.2.5 // grab the last frame from the bframe-queue
1127 : suxen_drol 1.95.2.1
1128 : suxen_drol 1.95.2.5 pEnc->bframenum_tail--;
1129 :     SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]);
1130 : suxen_drol 1.95.2.1
1131 : suxen_drol 1.95.2.5 if ((pEnc->current->vop_flags & XVID_DEBUG)) {
1132 :     image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 BVOP->PVOP");
1133 : edgomez 1.91 }
1134 :    
1135 : suxen_drol 1.95.2.5 /* convert B-VOP quant to P-VOP */
1136 :     pEnc->current->quant = ((pEnc->current->quant*100) - pEnc->mbParam.bquant_offset) / pEnc->mbParam.bquant_ratio;
1137 :     type = P_VOP;
1138 :     }
1139 :    
1140 :    
1141 :     /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1142 :     * encode this frame as an i-vop
1143 :     * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1144 :    
1145 :     if (type == I_VOP) {
1146 : edgomez 1.91
1147 : suxen_drol 1.95.2.5 DPRINTF(DPRINTF_DEBUG,"*** IFRAME bf: head=%i tail=%i queue: head=%i tail=%i size=%i",
1148 : edgomez 1.91 pEnc->bframenum_head, pEnc->bframenum_tail,
1149 :     pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
1150 :    
1151 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_DEBUG)) {
1152 : suxen_drol 1.95.2.5 image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "IVOP");
1153 : edgomez 1.91 }
1154 :    
1155 :    
1156 : suxen_drol 1.95.2.5 /* ---- update vol flags at IVOP ----------- */
1157 :     pEnc->current->vol_flags = pEnc->mbParam.vol_flags = frame->vol_flags;
1158 : edgomez 1.91
1159 : suxen_drol 1.95.2.5 if ((pEnc->mbParam.vol_flags & XVID_MPEGQUANT)) {
1160 :     if (frame->quant_intra_matrix != NULL)
1161 :     set_intra_matrix(frame->quant_intra_matrix);
1162 :     if (frame->quant_inter_matrix != NULL)
1163 :     set_inter_matrix(frame->quant_inter_matrix);
1164 : edgomez 1.91 }
1165 :    
1166 : suxen_drol 1.95.2.5 /* prevent vol/vop misuse */
1167 : edgomez 1.91
1168 : suxen_drol 1.95.2.5 if (!(pEnc->current->vol_flags & XVID_REDUCED_ENABLE))
1169 :     pEnc->current->vop_flags &= ~XVID_REDUCED;
1170 : edgomez 1.91
1171 : suxen_drol 1.95.2.5 if (!(pEnc->current->vol_flags & XVID_INTERLACING))
1172 :     pEnc->current->vop_flags &= ~(XVID_TOPFIELDFIRST|XVID_ALTERNATESCAN);
1173 : edgomez 1.91
1174 : suxen_drol 1.95.2.5 /* ^^^------------------------ */
1175 : edgomez 1.91
1176 : suxen_drol 1.95.2.5 if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
1177 :     image_copy(&pEnc->sOriginal, &pEnc->current->image,
1178 :     pEnc->mbParam.edged_width, pEnc->mbParam.height);
1179 :     }
1180 : edgomez 1.91
1181 : suxen_drol 1.95.2.5 FrameCodeI(pEnc, &bs);
1182 :     xFrame->out_flags |= XVID_KEYFRAME;
1183 : Isibaar 1.1
1184 : suxen_drol 1.95.2.1 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 : suxen_drol 1.95.2.5 * encode this frame as an p-vop
1186 :     * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1187 :    
1188 :     } else { // (type == P_VOP || type == S_VOP)
1189 :    
1190 :     DPRINTF(DPRINTF_DEBUG,"*** PFRAME bf: head=%i tail=%i queue: head=%i tail=%i size=%i",
1191 :     pEnc->bframenum_head, pEnc->bframenum_tail,
1192 :     pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
1193 :    
1194 :     if ((pEnc->current->vop_flags & XVID_DEBUG)) {
1195 :     image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "PVOP");
1196 :     }
1197 :    
1198 :     if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) {
1199 :     image_copy(&pEnc->sOriginal, &pEnc->current->image,
1200 :     pEnc->mbParam.edged_width, pEnc->mbParam.height);
1201 :     }
1202 :    
1203 :     FrameCodeP(pEnc, &bs, 1, 0);
1204 :     }
1205 :    
1206 :    
1207 :     /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1208 :     * on next enc_encode call we must flush bframes
1209 : suxen_drol 1.95.2.1 * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1210 : Isibaar 1.1
1211 : suxen_drol 1.95.2.1 done_flush:
1212 : edgomez 1.40
1213 : suxen_drol 1.95.2.5 pEnc->flush_bframes = 1;
1214 : Isibaar 1.1
1215 : suxen_drol 1.95.2.5 /* packed & queued_bframes: dont bother outputting stats, we do so after the flush */
1216 : suxen_drol 1.95.2.1 if ((pEnc->mbParam.global_flags & XVID_PACKED) && pEnc->bframenum_tail > 0) {
1217 :     goto repeat;
1218 : edgomez 1.3 }
1219 : edgomez 1.41
1220 : suxen_drol 1.95.2.5 /* packed or no-bframes: output stats */
1221 : suxen_drol 1.95.2.6 if ((pEnc->mbParam.global_flags & XVID_PACKED) || pEnc->mbParam.max_bframes == 0) {
1222 :     call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats);
1223 : Isibaar 1.1 }
1224 :    
1225 : suxen_drol 1.95.2.1 /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1226 :     * done; return number of bytes consumed
1227 :     * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
1228 :    
1229 :     done:
1230 : edgomez 1.41
1231 : Isibaar 1.1 stop_global_timer();
1232 :     write_timer();
1233 :    
1234 : suxen_drol 1.95.2.1 emms();
1235 :     return BitstreamLength(&bs);
1236 : Isibaar 1.1 }
1237 :    
1238 :    
1239 : edgomez 1.41 static __inline void
1240 :     CodeIntraMB(Encoder * pEnc,
1241 :     MACROBLOCK * pMB)
1242 :     {
1243 : Isibaar 1.1
1244 :     pMB->mode = MODE_INTRA;
1245 :    
1246 : suxen_drol 1.27 /* zero mv statistics */
1247 :     pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
1248 :     pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
1249 :     pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0;
1250 :     pMB->sad16 = 0;
1251 :    
1252 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_LUMIMASKING)) {
1253 : edgomez 1.41 if (pMB->dquant != NO_CHANGE) {
1254 : Isibaar 1.1 pMB->mode = MODE_INTRA_Q;
1255 : suxen_drol 1.27 pEnc->current->quant += DQtab[pMB->dquant];
1256 : edgomez 1.41
1257 :     if (pEnc->current->quant > 31)
1258 :     pEnc->current->quant = 31;
1259 :     if (pEnc->current->quant < 1)
1260 :     pEnc->current->quant = 1;
1261 : Isibaar 1.1 }
1262 :     }
1263 :    
1264 : suxen_drol 1.27 pMB->quant = pEnc->current->quant;
1265 : Isibaar 1.1 }
1266 :    
1267 :    
1268 : h 1.20
1269 : edgomez 1.41 static int
1270 :     FrameCodeI(Encoder * pEnc,
1271 : suxen_drol 1.95.2.1 Bitstream * bs)
1272 : h 1.21 {
1273 : suxen_drol 1.95.2.1 int bits = BitstreamPos(bs);
1274 : edgomez 1.91 int mb_width = pEnc->mbParam.mb_width;
1275 :     int mb_height = pEnc->mbParam.mb_height;
1276 : suxen_drol 1.95.2.1
1277 : h 1.21 DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);
1278 : edgomez 1.41 DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);
1279 : h 1.21
1280 :     uint16_t x, y;
1281 :    
1282 : suxen_drol 1.95.2.1 if ((pEnc->current->vol_flags & XVID_REDUCED_ENABLE))
1283 : edgomez 1.91 {
1284 :     mb_width = (pEnc->mbParam.width + 31) / 32;
1285 :     mb_height = (pEnc->mbParam.height + 31) / 32;
1286 :    
1287 :     /* 16x16->8x8 downsample requires 1 additional edge pixel*/
1288 :     /* XXX: setedges is overkill */
1289 :     start_timer();
1290 :     image_setedges(&pEnc->current->image,
1291 :     pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,
1292 :     pEnc->mbParam.width, pEnc->mbParam.height);
1293 :     stop_edges_timer();
1294 :     }
1295 :    
1296 : suxen_drol 1.27 pEnc->mbParam.m_rounding_type = 1;
1297 :     pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type;
1298 :     pEnc->current->coding_type = I_VOP;
1299 : h 1.21
1300 : suxen_drol 1.95.2.1 BitstreamWriteVolHeader(bs, &pEnc->mbParam);
1301 : edgomez 1.78
1302 : edgomez 1.91 set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase);
1303 :    
1304 :     BitstreamPadAlways(bs);
1305 : suxen_drol 1.44 BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1);
1306 : h 1.21
1307 : edgomez 1.91 pEnc->current->sStat.iTextBits = 0;
1308 :     pEnc->current->sStat.kblks = mb_width * mb_height;
1309 :     pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0;
1310 : h 1.21
1311 : edgomez 1.91 for (y = 0; y < mb_height; y++)
1312 :     for (x = 0; x < mb_width; x++) {
1313 : edgomez 1.41 MACROBLOCK *pMB =
1314 :     &pEnc->current->mbs[x + y * pEnc->mbParam.mb_width];
1315 : h 1.21
1316 :     CodeIntraMB(pEnc, pMB);
1317 :    
1318 : edgomez 1.41 MBTransQuantIntra(&pEnc->mbParam, pEnc->current, pMB, x, y,
1319 :     dct_codes, qcoeff);
1320 : h 1.21
1321 :     start_timer();
1322 : suxen_drol 1.27 MBPrediction(pEnc->current, x, y, pEnc->mbParam.mb_width, qcoeff);
1323 : h 1.21 stop_prediction_timer();
1324 :    
1325 :     start_timer();
1326 : suxen_drol 1.95.2.1 if (pEnc->current->vop_flags & XVID_GREYSCALE)
1327 : chl 1.68 { pMB->cbp &= 0x3C; /* keep only bits 5-2 */
1328 :     qcoeff[4*64+0]=0; /* zero, because for INTRA MBs DC value is saved */
1329 :     qcoeff[5*64+0]=0;
1330 :     }
1331 : edgomez 1.91 MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);
1332 : h 1.21 stop_coding_timer();
1333 :     }
1334 :    
1335 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_REDUCED))
1336 : edgomez 1.91 {
1337 :     image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width,
1338 :     pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width,
1339 : suxen_drol 1.95.2.1 16, 0);
1340 : edgomez 1.91 }
1341 : h 1.21 emms();
1342 :    
1343 : suxen_drol 1.95.2.1 /* for divx5 compatibility, we must always pad between the packed p and b frames */
1344 :     if ((pEnc->mbParam.global_flags & XVID_PACKED) && pEnc->bframenum_tail > 0)
1345 :     BitstreamPadAlways(bs);
1346 :     else
1347 :     BitstreamPad(bs);
1348 :     pEnc->current->length = (BitstreamPos(bs) - bits) / 8;
1349 :    
1350 : edgomez 1.91 pEnc->fMvPrevSigma = -1;
1351 : suxen_drol 1.27 pEnc->mbParam.m_fcode = 2;
1352 : h 1.21
1353 : suxen_drol 1.95.2.1 /* XXX: hinted me
1354 : edgomez 1.41 if (pEnc->current->global_flags & XVID_HINTEDME_GET) {
1355 : h 1.21 HintedMEGet(pEnc, 1);
1356 : suxen_drol 1.95.2.1 }*/
1357 : h 1.21
1358 : edgomez 1.93 return 1; /* intra */
1359 : h 1.21 }
1360 :    
1361 :    
1362 : Isibaar 1.1 #define INTRA_THRESHOLD 0.5
1363 : edgomez 1.91 #define BFRAME_SKIP_THRESHHOLD 30
1364 :    
1365 : Isibaar 1.1
1366 : edgomez 1.91 /* FrameCodeP also handles S(GMC)-VOPs */
1367 : edgomez 1.41 static int
1368 :     FrameCodeP(Encoder * pEnc,
1369 :     Bitstream * bs,
1370 :     bool force_inter,
1371 :     bool vol_header)
1372 : Isibaar 1.1 {
1373 : edgomez 1.3 float fSigma;
1374 : suxen_drol 1.95.2.1 int bits = BitstreamPos(bs);
1375 : edgomez 1.13
1376 :     DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);
1377 : edgomez 1.41 DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);
1378 : Isibaar 1.8
1379 : edgomez 1.91 int mb_width = pEnc->mbParam.mb_width;
1380 :     int mb_height = pEnc->mbParam.mb_height;
1381 :    
1382 : Isibaar 1.1 int iLimit;
1383 : edgomez 1.91 int x, y, k;
1384 : edgomez 1.3 int iSearchRange;
1385 : edgomez 1.91 int bIntra, skip_possible;
1386 : suxen_drol 1.95.2.1
1387 : edgomez 1.29 /* IMAGE *pCurrent = &pEnc->current->image; */
1388 : suxen_drol 1.27 IMAGE *pRef = &pEnc->reference->image;
1389 : Isibaar 1.1
1390 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_REDUCED))
1391 : edgomez 1.91 {
1392 :     mb_width = (pEnc->mbParam.width + 31) / 32;
1393 :     mb_height = (pEnc->mbParam.height + 31) / 32;
1394 :     }
1395 :    
1396 :    
1397 : h 1.11 start_timer();
1398 : edgomez 1.41 image_setedges(pRef, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,
1399 : h 1.84 pEnc->mbParam.width, pEnc->mbParam.height);
1400 : h 1.11 stop_edges_timer();
1401 : Isibaar 1.1
1402 : suxen_drol 1.27 pEnc->mbParam.m_rounding_type = 1 - pEnc->mbParam.m_rounding_type;
1403 :     pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type;
1404 : suxen_drol 1.95.2.1 //pEnc->current->quarterpel = pEnc->mbParam.m_quarterpel;
1405 : suxen_drol 1.27 pEnc->current->fcode = pEnc->mbParam.m_fcode;
1406 : Isibaar 1.1
1407 :     if (!force_inter)
1408 : edgomez 1.91 iLimit = (int)(mb_width * mb_height * INTRA_THRESHOLD);
1409 : edgomez 1.3 else
1410 : edgomez 1.91 iLimit = mb_width * mb_height + 1;
1411 : Isibaar 1.1
1412 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_HALFPEL)) {
1413 : Isibaar 1.1 start_timer();
1414 : edgomez 1.41 image_interpolate(pRef, &pEnc->vInterH, &pEnc->vInterV,
1415 :     &pEnc->vInterHV, pEnc->mbParam.edged_width,
1416 :     pEnc->mbParam.edged_height,
1417 : suxen_drol 1.95.2.1 (pEnc->mbParam.vol_flags & XVID_QUARTERPEL),
1418 : edgomez 1.41 pEnc->current->rounding_type);
1419 : Isibaar 1.1 stop_inter_timer();
1420 :     }
1421 :    
1422 : edgomez 1.91 pEnc->current->coding_type = P_VOP;
1423 :    
1424 : Isibaar 1.1 start_timer();
1425 : suxen_drol 1.95.2.1 /*if (pEnc->current->global_flags & XVID_HINTEDME_SET)
1426 : h 1.20 HintedMESet(pEnc, &bIntra);
1427 : suxen_drol 1.95.2.1 else*/
1428 : suxen_drol 1.55 bIntra =
1429 :     MotionEstimation(&pEnc->mbParam, pEnc->current, pEnc->reference,
1430 :     &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV,
1431 :     iLimit);
1432 : edgomez 1.91
1433 : Isibaar 1.1 stop_motion_timer();
1434 :    
1435 : suxen_drol 1.95.2.1 if (bIntra == 1) return FrameCodeI(pEnc, bs);
1436 : edgomez 1.91
1437 : suxen_drol 1.95.2.1 if ( ( pEnc->current->vol_flags & XVID_GMC )
1438 : edgomez 1.91 && ( (pEnc->current->warp.duv[1].x != 0) || (pEnc->current->warp.duv[1].y != 0) ) )
1439 :     {
1440 :     pEnc->current->coding_type = S_VOP;
1441 :    
1442 :     generate_GMCparameters( 2, 16, &pEnc->current->warp,
1443 :     pEnc->mbParam.width, pEnc->mbParam.height,
1444 :     &pEnc->current->gmc_data);
1445 :    
1446 :     generate_GMCimage(&pEnc->current->gmc_data, &pEnc->reference->image,
1447 :     pEnc->mbParam.mb_width, pEnc->mbParam.mb_height,
1448 :     pEnc->mbParam.edged_width, pEnc->mbParam.edged_width/2,
1449 : suxen_drol 1.95.2.1 pEnc->mbParam.m_fcode, (pEnc->mbParam.vol_flags & XVID_QUARTERPEL), 0,
1450 : edgomez 1.91 pEnc->current->rounding_type, pEnc->current->mbs, &pEnc->vGMC);
1451 :    
1452 : h 1.20 }
1453 : Isibaar 1.1
1454 : edgomez 1.91 set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase);
1455 : edgomez 1.41 if (vol_header)
1456 : suxen_drol 1.95.2.1 { BitstreamWriteVolHeader(bs, &pEnc->mbParam);
1457 : edgomez 1.91 BitstreamPadAlways(bs);
1458 :     }
1459 : Isibaar 1.1
1460 : suxen_drol 1.44 BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1);
1461 : edgomez 1.3
1462 : edgomez 1.91 pEnc->current->sStat.iTextBits = pEnc->current->sStat.iMvSum = pEnc->current->sStat.iMvCount =
1463 :     pEnc->current->sStat.kblks = pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0;
1464 :    
1465 : Isibaar 1.1
1466 : edgomez 1.91 for (y = 0; y < mb_height; y++) {
1467 :     for (x = 0; x < mb_width; x++) {
1468 : edgomez 1.41 MACROBLOCK *pMB =
1469 :     &pEnc->current->mbs[x + y * pEnc->mbParam.mb_width];
1470 : Isibaar 1.1
1471 : edgomez 1.91 /* Mode decision: Check, if the block should be INTRA / INTER or GMC-coded */
1472 :     /* For a start, leave INTRA decision as is, only choose only between INTER/GMC - gruel, 9.1.2002 */
1473 :    
1474 : edgomez 1.3 bIntra = (pMB->mode == MODE_INTRA) || (pMB->mode == MODE_INTRA_Q);
1475 : Isibaar 1.1
1476 : edgomez 1.91 if (bIntra) {
1477 : Isibaar 1.1 CodeIntraMB(pEnc, pMB);
1478 : edgomez 1.41 MBTransQuantIntra(&pEnc->mbParam, pEnc->current, pMB, x, y,
1479 :     dct_codes, qcoeff);
1480 : chl 1.81
1481 :     start_timer();
1482 :     MBPrediction(pEnc->current, x, y, pEnc->mbParam.mb_width, qcoeff);
1483 :     stop_prediction_timer();
1484 : edgomez 1.91
1485 :     pEnc->current->sStat.kblks++;
1486 :    
1487 :     MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);
1488 :     stop_coding_timer();
1489 :     continue;
1490 :     }
1491 :    
1492 :     if (pEnc->current->coding_type == S_VOP) {
1493 :    
1494 :     int32_t iSAD = sad16(pEnc->current->image.y + 16*y*pEnc->mbParam.edged_width + 16*x,
1495 :     pEnc->vGMC.y + 16*y*pEnc->mbParam.edged_width + 16*x,
1496 :     pEnc->mbParam.edged_width, 65536);
1497 :    
1498 :     if (pEnc->current->motion_flags & PMV_CHROMA16) {
1499 :     iSAD += sad8(pEnc->current->image.u + 8*y*(pEnc->mbParam.edged_width/2) + 8*x,
1500 :     pEnc->vGMC.u + 8*y*(pEnc->mbParam.edged_width/2) + 8*x, pEnc->mbParam.edged_width/2);
1501 :    
1502 :     iSAD += sad8(pEnc->current->image.v + 8*y*(pEnc->mbParam.edged_width/2) + 8*x,
1503 :     pEnc->vGMC.v + 8*y*(pEnc->mbParam.edged_width/2) + 8*x, pEnc->mbParam.edged_width/2);
1504 :     }
1505 :    
1506 :     if (iSAD <= pMB->sad16) { /* mode decision GMC */
1507 :    
1508 : suxen_drol 1.95.2.1 if ((pEnc->mbParam.vol_flags & XVID_QUARTERPEL))
1509 : edgomez 1.91 pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = pMB->amv;
1510 :     else
1511 :     pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->amv;
1512 :    
1513 :     pMB->mode = MODE_INTER;
1514 :     pMB->mcsel = 1;
1515 :     pMB->sad16 = iSAD;
1516 :     } else {
1517 :     pMB->mcsel = 0;
1518 :     }
1519 :     } else {
1520 :     pMB->mcsel = 0; /* just a precaution */
1521 :     }
1522 :    
1523 :     start_timer();
1524 :     MBMotionCompensation(pMB, x, y, &pEnc->reference->image,
1525 :     &pEnc->vInterH, &pEnc->vInterV,
1526 :     &pEnc->vInterHV, &pEnc->vGMC,
1527 :     &pEnc->current->image,
1528 :     dct_codes, pEnc->mbParam.width,
1529 :     pEnc->mbParam.height,
1530 :     pEnc->mbParam.edged_width,
1531 : suxen_drol 1.95.2.1 (pEnc->current->vol_flags & XVID_QUARTERPEL),
1532 :     (pEnc->current->vop_flags & XVID_REDUCED),
1533 : edgomez 1.91 pEnc->current->rounding_type);
1534 :    
1535 :     stop_comp_timer();
1536 :    
1537 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_LUMIMASKING)) {
1538 : edgomez 1.91 if (pMB->dquant != NO_CHANGE) {
1539 :     pMB->mode = MODE_INTER_Q;
1540 :     pEnc->current->quant += DQtab[pMB->dquant];
1541 :     if (pEnc->current->quant > 31)
1542 :     pEnc->current->quant = 31;
1543 :     else if (pEnc->current->quant < 1)
1544 :     pEnc->current->quant = 1;
1545 :     }
1546 : Isibaar 1.1 }
1547 : edgomez 1.91 pMB->quant = pEnc->current->quant;
1548 : Isibaar 1.1
1549 : edgomez 1.91 pMB->field_pred = 0;
1550 :    
1551 :     if (pMB->mode != MODE_NOT_CODED)
1552 :     { pMB->cbp =
1553 :     MBTransQuantInter(&pEnc->mbParam, pEnc->current, pMB, x, y,
1554 :     dct_codes, qcoeff);
1555 :     }
1556 :    
1557 :     if (pMB->cbp || pMB->mvs[0].x || pMB->mvs[0].y ||
1558 :     pMB->mvs[1].x || pMB->mvs[1].y || pMB->mvs[2].x ||
1559 :     pMB->mvs[2].y || pMB->mvs[3].x || pMB->mvs[3].y) {
1560 :     pEnc->current->sStat.mblks++;
1561 : chl 1.64 } else {
1562 : edgomez 1.91 pEnc->current->sStat.ublks++;
1563 :     }
1564 :    
1565 : Isibaar 1.1 start_timer();
1566 : chl 1.65
1567 :     /* Finished processing the MB, now check if to CODE or SKIP */
1568 :    
1569 : edgomez 1.91 skip_possible = (pMB->cbp == 0) && (pMB->mode == MODE_INTER) &&
1570 :     (pMB->dquant == NO_CHANGE);
1571 :    
1572 :     if (pEnc->current->coding_type == S_VOP)
1573 :     skip_possible &= (pMB->mcsel == 1);
1574 :     else if (pEnc->current->coding_type == P_VOP) {
1575 : suxen_drol 1.95.2.1 if ((pEnc->mbParam.vol_flags & XVID_QUARTERPEL))
1576 : edgomez 1.91 skip_possible &= ( (pMB->qmvs[0].x == 0) && (pMB->qmvs[0].y == 0) );
1577 :     else
1578 :     skip_possible &= ( (pMB->mvs[0].x == 0) && (pMB->mvs[0].y == 0) );
1579 :     }
1580 :    
1581 :     if ( (pMB->mode == MODE_NOT_CODED) || (skip_possible)) {
1582 :    
1583 :     /* This is a candidate for SKIPping, but for P-VOPs check intermediate B-frames first */
1584 :    
1585 :     if (pEnc->current->coding_type == P_VOP) /* special rule for P-VOP's SKIP */
1586 :     {
1587 :     int bSkip = 1;
1588 :    
1589 :     for (k=pEnc->bframenum_head; k< pEnc->bframenum_tail; k++)
1590 :     {
1591 :     int iSAD;
1592 :     iSAD = sad16(pEnc->reference->image.y + 16*y*pEnc->mbParam.edged_width + 16*x,
1593 :     pEnc->bframes[k]->image.y + 16*y*pEnc->mbParam.edged_width + 16*x,
1594 :     pEnc->mbParam.edged_width,BFRAME_SKIP_THRESHHOLD);
1595 :     if (iSAD >= BFRAME_SKIP_THRESHHOLD * pMB->quant)
1596 :     { bSkip = 0;
1597 :     break;
1598 :     }
1599 :     }
1600 :    
1601 :     if (!bSkip) { /* no SKIP, but trivial block */
1602 : suxen_drol 1.95.2.1 if((pEnc->mbParam.vol_flags & XVID_QUARTERPEL)) {
1603 : edgomez 1.91 VECTOR predMV = get_qpmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0);
1604 :     pMB->pmvs[0].x = - predMV.x;
1605 :     pMB->pmvs[0].y = - predMV.y;
1606 :     }
1607 :     else {
1608 :     VECTOR predMV = get_pmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0);
1609 :     pMB->pmvs[0].x = - predMV.x;
1610 :     pMB->pmvs[0].y = - predMV.y;
1611 :     }
1612 :     pMB->mode = MODE_INTER;
1613 :     pMB->cbp = 0;
1614 :     MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);
1615 :     stop_coding_timer();
1616 :    
1617 :     continue; /* next MB */
1618 :     }
1619 :     }
1620 :     /* do SKIP */
1621 :    
1622 :     pMB->mode = MODE_NOT_CODED;
1623 :     MBSkip(bs);
1624 :     stop_coding_timer();
1625 :     continue; /* next MB */
1626 :     }
1627 :     /* ordinary case: normal coded INTER/INTER4V block */
1628 : chl 1.65
1629 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_GREYSCALE))
1630 : edgomez 1.91 { pMB->cbp &= 0x3C; /* keep only bits 5-2 */
1631 :     qcoeff[4*64+0]=0; /* zero, because DC for INTRA MBs DC value is saved */
1632 :     qcoeff[5*64+0]=0;
1633 :     }
1634 : chl 1.65
1635 : suxen_drol 1.95.2.1 if((pEnc->mbParam.vol_flags & XVID_QUARTERPEL)) {
1636 : edgomez 1.91 VECTOR predMV = get_qpmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0);
1637 :     pMB->pmvs[0].x = pMB->qmvs[0].x - predMV.x;
1638 :     pMB->pmvs[0].y = pMB->qmvs[0].y - predMV.y;
1639 :     DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[0].x, pMB->pmvs[0].y, predMV.x, predMV.y, pMB->mvs[0].x, pMB->mvs[0].y);
1640 :     } else {
1641 :     VECTOR predMV = get_pmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0);
1642 :     pMB->pmvs[0].x = pMB->mvs[0].x - predMV.x;
1643 :     pMB->pmvs[0].y = pMB->mvs[0].y - predMV.y;
1644 :     DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[0].x, pMB->pmvs[0].y, predMV.x, predMV.y, pMB->mvs[0].x, pMB->mvs[0].y);
1645 : edgomez 1.78 }
1646 : edgomez 1.91
1647 :    
1648 :     if (pMB->mode == MODE_INTER4V)
1649 :     { int k;
1650 :     for (k=1;k<4;k++)
1651 :     {
1652 : suxen_drol 1.95.2.1 if((pEnc->mbParam.vol_flags & XVID_QUARTERPEL)) {
1653 : edgomez 1.91 VECTOR predMV = get_qpmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, k);
1654 :     pMB->pmvs[k].x = pMB->qmvs[k].x - predMV.x;
1655 :     pMB->pmvs[k].y = pMB->qmvs[k].y - predMV.y;
1656 :     DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[k].x, pMB->pmvs[k].y, predMV.x, predMV.y, pMB->mvs[k].x, pMB->mvs[k].y);
1657 :     } else {
1658 :     VECTOR predMV = get_pmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, k);
1659 :     pMB->pmvs[k].x = pMB->mvs[k].x - predMV.x;
1660 :     pMB->pmvs[k].y = pMB->mvs[k].y - predMV.y;
1661 :     DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[k].x, pMB->pmvs[k].y, predMV.x, predMV.y, pMB->mvs[k].x, pMB->mvs[k].y);
1662 :     }
1663 :    
1664 : chl 1.68 }
1665 : chl 1.65 }
1666 : edgomez 1.91
1667 :     MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);
1668 :     stop_coding_timer();
1669 : chl 1.65
1670 : Isibaar 1.1 }
1671 :     }
1672 :    
1673 : suxen_drol 1.95.2.1 if ((pEnc->current->vop_flags & XVID_REDUCED))
1674 : edgomez 1.91 {
1675 :     image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width,
1676 :     pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width,
1677 : suxen_drol 1.95.2.1 16, 0);
1678 : edgomez 1.91 }
1679 :    
1680 : Isibaar 1.1 emms();
1681 : h 1.20
1682 : suxen_drol 1.95.2.1 /* XXX: hinted me
1683 : edgomez 1.41 if (pEnc->current->global_flags & XVID_HINTEDME_GET) {
1684 : h 1.20 HintedMEGet(pEnc, 0);
1685 : suxen_drol 1.95.2.1 }*/
1686 : Isibaar 1.1
1687 : edgomez 1.91 if (pEnc->current->sStat.iMvCount == 0)
1688 :     pEnc->current->sStat.iMvCount = 1;
1689 : Isibaar 1.1
1690 : edgomez 1.91 fSigma = (float) sqrt((float) pEnc->current->sStat.iMvSum / pEnc->current->sStat.iMvCount);
1691 : Isibaar 1.1
1692 : suxen_drol 1.27 iSearchRange = 1 << (3 + pEnc->mbParam.m_fcode);
1693 : Isibaar 1.1
1694 : edgomez 1.41 if ((fSigma > iSearchRange / 3)
1695 : suxen_drol 1.95.2.1 && (pEnc->mbParam.m_fcode <= (3 + (pEnc->mbParam.vol_flags & XVID_QUARTERPEL?1:0) ))) /* maximum search range 128 */
1696 : edgomez 1.3 {
1697 : suxen_drol 1.27 pEnc->mbParam.m_fcode++;
1698 : Isibaar 1.1 iSearchRange *= 2;
1699 : edgomez 1.41 } else if ((fSigma < iSearchRange / 6)
1700 : edgomez 1.91 && (pEnc->fMvPrevSigma >= 0)
1701 :     && (pEnc->fMvPrevSigma < iSearchRange / 6)
1702 : suxen_drol 1.95.2.1 && (pEnc->mbParam.m_fcode >= (2 + (pEnc->mbParam.vol_flags & XVID_QUARTERPEL?1:0) ))) /* minimum search range 16 */
1703 : edgomez 1.3 {
1704 : suxen_drol 1.27 pEnc->mbParam.m_fcode--;
1705 : Isibaar 1.1 iSearchRange /= 2;
1706 : edgomez 1.3 }
1707 : Isibaar 1.1
1708 : edgomez 1.91 pEnc->fMvPrevSigma = fSigma;
1709 :    
1710 :     /* frame drop code */
1711 :     DPRINTF(DPRINTF_DEBUG, "kmu %i %i %i", pEnc->current->sStat.kblks, pEnc->current->sStat.mblks, pEnc->current->sStat.ublks);
1712 :     if (pEnc->current->sStat.kblks + pEnc->current->sStat.mblks <
1713 :     (pEnc->mbParam.frame_drop_ratio * mb_width * mb_height) / 100)
1714 :     {
1715 :     pEnc->current->sStat.kblks = pEnc->current->sStat.mblks = 0;
1716 :     pEnc->current->sStat.ublks = mb_width * mb_height;
1717 :    
1718 :     BitstreamReset(bs);
1719 :    
1720 :     set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase);
1721 :     BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 0);
1722 :    
1723 : edgomez 1.93 /* copy reference frame details into the current frame */
1724 : edgomez 1.91 pEnc->current->quant = pEnc->reference->quant;
1725 :     pEnc->current->motion_flags = pEnc->reference->motion_flags;
1726 :     pEnc->current->rounding_type = pEnc->reference->rounding_type;
1727 : suxen_drol 1.95.2.1 //pEnc->current->quarterpel = pEnc->reference->quarterpel;
1728 : edgomez 1.91 pEnc->current->fcode = pEnc->reference->fcode;
1729 :     pEnc->current->bcode = pEnc->reference->bcode;
1730 :     image_copy(&pEnc->current->image, &pEnc->reference->image, pEnc->mbParam.edged_width, pEnc->mbParam.height);
1731 :     memcpy(pEnc->current->mbs, pEnc->reference->mbs, sizeof(MACROBLOCK) * mb_width * mb_height);
1732 :     }
1733 :    
1734 :     /* XXX: debug
1735 :     {
1736 :     char s[100];
1737 :     sprintf(s, "\\%05i_cur.pgm", pEnc->m_framenum);
1738 :     image_dump_yuvpgm(&pEnc->current->image,
1739 :     pEnc->mbParam.edged_width,
1740 :     pEnc->mbParam.width, pEnc->mbParam.height, s);
1741 :    
1742 :     sprintf(s, "\\%05i_ref.pgm", pEnc->m_framenum);
1743 :     image_dump_yuvpgm(&pEnc->reference->image,
1744 :     pEnc->mbParam.edged_width,
1745 :     pEnc->mbParam.width, pEnc->mbParam.height, s);
1746 :     }
1747 :     */
1748 :    
1749 : suxen_drol 1.95.2.1 /* for divx5 compatibility, we must always pad between the packed p and b frames */
1750 :     if ((pEnc->mbParam.global_flags & XVID_PACKED) && pEnc->bframenum_tail > 0)
1751 :     BitstreamPadAlways(bs);
1752 :     else
1753 :     BitstreamPad(bs);
1754 : suxen_drol 1.60
1755 : suxen_drol 1.95.2.1 pEnc->current->length = (BitstreamPos(bs) - bits) / 8;
1756 : Isibaar 1.1
1757 : edgomez 1.93 return 0; /* inter */
1758 : edgomez 1.91 }
1759 :    
1760 :    
1761 :     static void
1762 :     FrameCodeB(Encoder * pEnc,
1763 :     FRAMEINFO * frame,
1764 : suxen_drol 1.95.2.1 Bitstream * bs)
1765 : edgomez 1.91 {
1766 : suxen_drol 1.95.2.1 int bits = BitstreamPos(bs);
1767 : edgomez 1.91 DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);
1768 :     DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE);
1769 :     uint32_t x, y;
1770 :    
1771 :     IMAGE *f_ref = &pEnc->reference->image;
1772 :     IMAGE *b_ref = &pEnc->current->image;
1773 :    
1774 : suxen_drol 1.95.2.1 #ifdef BFRAMES_DEC_DEBUG
1775 : edgomez 1.91 FILE *fp;
1776 :     static char first=0;
1777 :     #define BFRAME_DEBUG if (!first && fp){ \
1778 :     fprintf(fp,"Y=%3d X=%3d MB=%2d CBP=%02X\n",y,x,mb->mode,mb->cbp); \
1779 :     }
1780 :    
1781 : suxen_drol 1.95.2.1 /* XXX: pEnc->current->global_flags &= ~XVID_REDUCED; reduced resoltion not yet supported */
1782 : edgomez 1.91
1783 :     if (!first){
1784 :     fp=fopen("C:\\XVIDDBGE.TXT","w");
1785 :     }
1786 :     #endif
1787 :    
1788 : suxen_drol 1.95.2.1 //frame->quarterpel = pEnc->mbParam.m_quarterpel;
1789 : edgomez 1.91
1790 : edgomez 1.93 /* forward */
1791 : edgomez 1.91 image_setedges(f_ref, pEnc->mbParam.edged_width,
1792 :     pEnc->mbParam.edged_height, pEnc->mbParam.width,
1793 :     pEnc->mbParam.height);
1794 :     start_timer();
1795 :     image_interpolate(f_ref, &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv,
1796 :     pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,
1797 : suxen_drol 1.95.2.1 (pEnc->mbParam.vol_flags & XVID_QUARTERPEL), 0);
1798 : edgomez 1.91 stop_inter_timer();
1799 :    
1800 : edgomez 1.93 /* backward */
1801 : edgomez 1.91 image_setedges(b_ref, pEnc->mbParam.edged_width,
1802 :     pEnc->mbParam.edged_height, pEnc->mbParam.width,
1803 :     pEnc->mbParam.height);
1804 :     start_timer();
1805 :     image_interpolate(b_ref, &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV,
1806 :     pEnc->mbParam.edged_width, pEnc->mbParam.edged_height,
1807 : suxen_drol 1.95.2.1 (pEnc->mbParam.vol_flags & XVID_QUARTERPEL), 0);
1808 : edgomez 1.91 stop_inter_timer();
1809 :    
1810 :     start_timer();
1811 :    
1812 :     MotionEstimationBVOP(&pEnc->mbParam, frame,
1813 : edgomez 1.93 ((int32_t)(pEnc->current->stamp - frame->stamp)), /* time_bp */
1814 :     ((int32_t)(pEnc->current->stamp - pEnc->reference->stamp)), /* time_pp */
1815 :     pEnc->reference->mbs, f_ref,
1816 : edgomez 1.91 &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv,
1817 :     pEnc->current, b_ref, &pEnc->vInterH,
1818 :     &pEnc->vInterV, &pEnc->vInterHV);
1819 :    
1820 :    
1821 :     stop_motion_timer();
1822 : suxen_drol 1.24
1823 : edgomez 1.93 /*
1824 :     if (test_quant_type(&pEnc->mbParam, pEnc->current)) {
1825 :     BitstreamWriteVolHeader(bs, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.quant_type);
1826 :     }
1827 :     */
1828 : edgomez 1.91
1829 :     frame->coding_type = B_VOP;
1830 :    
1831 :     set_timecodes(frame, pEnc->reference,pEnc->mbParam.fbase);
1832 :     BitstreamWriteVopHeader(bs, &pEnc->mbParam, frame, 1);
1833 :    
1834 :     frame->sStat.iTextBits = 0;
1835 :     frame->sStat.iMvSum = 0;
1836 :     frame->sStat.iMvCount = 0;
1837 :     frame->sStat.kblks = frame->sStat.mblks = frame->sStat.ublks = 0;
1838 : suxen_drol 1.95.2.1 frame->sStat.mblks = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height;
1839 :     frame->sStat.kblks = frame->sStat.ublks = 0;
1840 : edgomez 1.91
1841 :     for (y = 0; y < pEnc->mbParam.mb_height; y++) {
1842 :     for (x = 0; x < pEnc->mbParam.mb_width; x++) {
1843 :     MACROBLOCK * const mb = &frame->mbs[x + y * pEnc->mbParam.mb_width];
1844 : suxen_drol 1.95.2.1 int direction = frame->vop_flags & XVID_ALTERNATESCAN ? 2 : 0;
1845 : edgomez 1.91
1846 : edgomez 1.93 /* decoder ignores mb when refence block is INTER(0,0), CBP=0 */
1847 : edgomez 1.91 if (mb->mode == MODE_NOT_CODED) {
1848 : edgomez 1.93 /* mb->mvs[0].x = mb->mvs[0].y = mb->cbp = 0; */
1849 : edgomez 1.91 continue;
1850 :     }
1851 :    
1852 :     if (mb->mode != MODE_DIRECT_NONE_MV) {
1853 :     MBMotionCompensationBVOP(&pEnc->mbParam, mb, x, y, &frame->image,
1854 :     f_ref, &pEnc->f_refh, &pEnc->f_refv,
1855 :     &pEnc->f_refhv, b_ref, &pEnc->vInterH,
1856 :     &pEnc->vInterV, &pEnc->vInterHV,
1857 :     dct_codes);
1858 :    
1859 :     if (mb->mode == MODE_DIRECT_NO4V) mb->mode = MODE_DIRECT;
1860 :     mb->quant = frame->quant;
1861 :    
1862 :     mb->cbp =
1863 : edgomez 1.95.2.3 MBTransQuantInterBVOP(&pEnc->mbParam, frame, mb, x, y, dct_codes, qcoeff);
1864 : edgomez 1.91
1865 :     if ( (mb->mode == MODE_DIRECT) && (mb->cbp == 0)
1866 :     && (mb->pmvs[3].x == 0) && (mb->pmvs[3].y == 0) ) {
1867 : edgomez 1.93 mb->mode = MODE_DIRECT_NONE_MV; /* skipped */
1868 : edgomez 1.91 }
1869 :     }
1870 :    
1871 :     #ifdef BFRAMES_DEC_DEBUG
1872 :     BFRAME_DEBUG
1873 :     #endif
1874 :     start_timer();
1875 :     MBCodingBVOP(mb, qcoeff, frame->fcode, frame->bcode, bs,
1876 :     &frame->sStat, direction);
1877 :     stop_coding_timer();
1878 :     }
1879 :     }
1880 :    
1881 :     emms();
1882 :    
1883 : edgomez 1.93 /* TODO: dynamic fcode/bcode ??? */
1884 : edgomez 1.91
1885 : suxen_drol 1.95.2.1 BitstreamPad(bs);
1886 :     frame->length = (BitstreamPos(bs) - bits) / 8;
1887 : edgomez 1.91
1888 :     #ifdef BFRAMES_DEC_DEBUG
1889 :     if (!first){
1890 :     first=1;
1891 :     if (fp)
1892 :     fclose(fp);
1893 :     }
1894 :     #endif
1895 : suxen_drol 1.24 }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4