1 /*
2 libfame - Fast Assembly MPEG Encoder Library
3 Copyright (C) 2000-2001 Vivien Chappelier
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /**************************** mpeg decoder ***********************************/
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include "fame.h"
24 #include "fame_malloc.h"
25 #include "fame_decoder.h"
26 #include "fame_decoder_mpeg.h"
27 #include "table_scale.h"
28 #if defined(HAS_MMX)
29 #define arch_enter_state()
30 #define arch_leave_state() asm("emms")
31 #include "transpose_mmx.h"
32 #include "idct_mmx.h"
33 #include "dequantize_mmx.h"
34 #include "reconstruct_mmx.h"
35 #include "pad_int.h" /* TODO */
36 #include "half_mmx.h"
37 #else
38 #define arch_enter_state()
39 #define arch_leave_state()
40 #include "idct_float.h"
41 #include "dequantize_float.h"
42 #include "reconstruct_float.h"
43 #include "pad_int.h"
44 #include "half_int.h"
45 #endif
46
47 static void mpeg_init(fame_decoder_t *decoder,
48 int width,
49 int height,
50 unsigned char *intra_quantisation_table,
51 unsigned char *inter_quantisation_table,
52 unsigned char *intra_dc_y_scale_table,
53 unsigned char *intra_dc_c_scale_table,
54 fame_mismatch_t mismatch_type);
55 static void mpeg_enter(fame_decoder_t *decoder,
56 fame_yuv_t **past_ref,
57 fame_yuv_t **new_ref,
58 fame_yuv_t **future_ref,
59 fame_yuv_t *yuv,
60 unsigned char *shape);
61 static void mpeg_reconstruct_intra_mb(fame_decoder_t *decoder,
62 short x,
63 short y,
64 short *blocks[6],
65 unsigned char q,
66 fame_bab_t bab_type);
67 static void mpeg_reconstruct_inter_mb(fame_decoder_t *decoder,
68 short x,
69 short y,
70 short *blocks[6],
71 fame_motion_vector_t *forward,
72 fame_motion_vector_t *backward,
73 fame_motion_coding_t motion_coding,
74 unsigned char q,
75 fame_bab_t bab_type);
76 static void mpeg_pad(fame_decoder_t *decoder,
77 unsigned char *bab_map,
78 fame_box_t *box);
79 static void mpeg_interpolate(fame_decoder_t *decoder, int rounding);
80 static void mpeg_leave(fame_decoder_t *decoder);
81 #ifdef HAS_MMX
82 static void mpeg_close(fame_decoder_t *decoder);
83 #endif
84
FAME_CONSTRUCTOR(fame_decoder_mpeg_t)85 FAME_CONSTRUCTOR(fame_decoder_mpeg_t)
86 {
87 FAME_OBJECT(this)->name = "MPEG decoder";
88 FAME_DECODER(this)->init = mpeg_init;
89 FAME_DECODER(this)->enter = mpeg_enter;
90 FAME_DECODER(this)->reconstruct_intra_mb = mpeg_reconstruct_intra_mb;
91 FAME_DECODER(this)->reconstruct_inter_mb = mpeg_reconstruct_inter_mb;
92 FAME_DECODER(this)->pad = mpeg_pad;
93 FAME_DECODER(this)->interpolate = mpeg_interpolate;
94 FAME_DECODER(this)->leave = mpeg_leave;
95 #ifdef HAS_MMX
96 FAME_DECODER(this)->close = mpeg_close;
97 #else
98 FAME_DECODER(this)->close = NULL;
99 #endif
100 return(this);
101 }
102
103 /* mpeg_init */
104 /* */
105 /* Description: */
106 /* Initialize the decoder. */
107 /* */
108 /* Arguments: */
109 /* fame_decoder_t *decoder: the decoder to initialize */
110 /* int width: width of the frame */
111 /* int height: height of the frame */
112 /* unsigned char *intra_quantisation_table: quantisation matrix for intra */
113 /* unsigned char *inter_quantisation_table: quantisation matrix for inter */
114 /* unsigned char *intra_dc_y_scale_table: quantisation table for DC of Y */
115 /* unsigned char *intra_dc_c_scale_table: quantisation table for DC of C */
116 /* fame_mismatch_t mismatch_type: type of mismatch control */
117 /* */
118 /* Return value: */
119 /* None. */
120
mpeg_init(fame_decoder_t * decoder,int width,int height,unsigned char * iqtable,unsigned char * niqtable,unsigned char * intra_dc_y_scale_table,unsigned char * intra_dc_c_scale_table,fame_mismatch_t mismatch_type)121 static void mpeg_init(fame_decoder_t *decoder,
122 int width,
123 int height,
124 unsigned char *iqtable,
125 unsigned char *niqtable,
126 unsigned char *intra_dc_y_scale_table,
127 unsigned char *intra_dc_c_scale_table,
128 fame_mismatch_t mismatch_type)
129 {
130 fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder);
131 int i, q;
132
133 #ifdef HAS_MMX
134 asm("emms");
135 #endif
136
137 /* set width and height */
138 decoder_mpeg->width = width;
139 decoder_mpeg->height = height;
140 decoder_mpeg->mismatch = mismatch_type;
141 #ifdef HAS_MMX
142 if(mismatch_type == fame_mismatch_global)
143 for(i = 0; i < 6; i++) {
144 decoder_mpeg->mismatch_accumulator[i] =
145 (dct_t *) fame_malloc((decoder_mpeg->width>>3)*
146 (decoder_mpeg->height>>3)*sizeof(dct_t));
147 memset(decoder_mpeg->mismatch_accumulator[i], 0,
148 (decoder_mpeg->width>>3)*
149 (decoder_mpeg->height>>3)*sizeof(dct_t));
150 }
151 #endif
152
153 /* compute quantization matrixes */
154 for(q = 1; q < 32; q++) {
155 /* compute the intra quantisation and dequantisation DC scaler */
156 #ifdef HAS_MMX
157 decoder_mpeg->yidqmatrixes[q][0] =
158 (short) (intra_dc_y_scale_table[q] << 3);
159 decoder_mpeg->cidqmatrixes[q][0] =
160 (short) (intra_dc_c_scale_table[q] << 3);
161 #else
162 decoder_mpeg->yidqmatrixes[q][0] = intra_dc_y_scale_table[q];
163 decoder_mpeg->cidqmatrixes[q][0] = intra_dc_c_scale_table[q];
164 #endif
165
166 /* compute the intra quantisation and dequantisation matrix */
167 for(i = 1; i < 64; i++)
168 {
169 #ifdef HAS_MMX
170 decoder_mpeg->yidqmatrixes[q][i] = decoder_mpeg->cidqmatrixes[q][i] =
171 (short) q*iqtable[i];
172 #else
173 decoder_mpeg->yidqmatrixes[q][i] = decoder_mpeg->cidqmatrixes[q][i] =
174 q*iqtable[i];
175 #endif
176 }
177
178 /* compute the inter quantisation and dequantisation matrix */
179 for(i = 0; i < 64; i++)
180 {
181 #ifdef HAS_MMX
182 decoder_mpeg->nidqmatrixes[q][i] = (short) q*niqtable[i];
183 decoder_mpeg->psmatrix[i] = (short) ((double)(1UL << 16) * prescale[i] + 0.5);
184 #else
185 decoder_mpeg->nidqmatrixes[q][i] = q*niqtable[i];
186 decoder_mpeg->psmatrix[i] = prescale[i];
187 #endif
188 }
189 }
190 }
191
192 /* mpeg_enter */
193 /* */
194 /* Description: */
195 /* Start encoding a new picture. */
196 /* */
197 /* Arguments: */
198 /* fame_decoder_t *decoder: the decoder */
199 /* fame_yuv_t **past_ref: past reference images */
200 /* fame_yuv_t **new_ref: new reconstructed reference images */
201 /* fame_yuv_t **future_ref: future reference images */
202 /* fame_yuv_t *yuv: source image */
203 /* unsigned char *shape: shape binary mask */
204 /* */
205 /* Return value: */
206 /* None. */
207
mpeg_enter(fame_decoder_t * decoder,fame_yuv_t ** past_ref,fame_yuv_t ** new_ref,fame_yuv_t ** future_ref,fame_yuv_t * yuv,unsigned char * shape)208 static void mpeg_enter(fame_decoder_t *decoder,
209 fame_yuv_t **past_ref,
210 fame_yuv_t **new_ref,
211 fame_yuv_t **future_ref,
212 fame_yuv_t *yuv,
213 unsigned char *shape)
214 {
215 fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder);
216
217 /* Make pointers on the input frame and reference frame */
218 decoder_mpeg->input = yuv;
219 decoder_mpeg->past_ref = past_ref;
220 decoder_mpeg->new_ref = new_ref;
221 decoder_mpeg->future_ref = future_ref;
222 decoder_mpeg->shape = shape;
223 arch_enter_state();
224 }
225
226 /* mpeg_pad_mb */
227 /* */
228 /* Description: */
229 /* Perform repetitive padding for motion estimation on a border block. */
230 /* */
231 /* Arguments: */
232 /* fame_decoder_t *decoder: the decoder */
233 /* short x: the x location of the macroblock in macroblock units */
234 /* short y: the y location of the macroblock in macroblock units */
235 /* fame_box_t box: bounding box */
236 /* */
237 /* Return value: */
238 /* None. */
239
mpeg_pad_mb(fame_decoder_t * decoder,short x,short y)240 static void mpeg_pad_mb(fame_decoder_t *decoder,
241 short x,
242 short y)
243 {
244 fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder);
245 int spitch, rpitch;
246 unsigned char *shape, *Y, *U, *V;
247
248 /* Make offsets to blocks */
249 spitch = decoder_mpeg->input->p;
250 shape = decoder_mpeg->shape + (y << 4) * spitch + (x << 4);
251
252 /* Make offsets to blocks */
253 rpitch = decoder_mpeg->new_ref[0]->p;
254 Y = decoder_mpeg->new_ref[0]->y + (y << 4) * rpitch + (x << 4); /* Y */
255 U = decoder_mpeg->new_ref[0]->u + (y << 3) * (rpitch >> 1) + (x << 3); /*Cb*/
256 V = decoder_mpeg->new_ref[0]->v + (y << 3) * (rpitch >> 1) + (x << 3); /*Cr*/
257
258 repetitive_fill_Y(Y, shape, rpitch, spitch);
259 repetitive_fill_C(U, shape, rpitch, spitch);
260 repetitive_fill_C(V, shape, rpitch, spitch);
261 }
262
263 /* mpeg_reconstruct_intra_mb */
264 /* */
265 /* Description: */
266 /* Reconstruct an intra macroblock for further motion estimation. */
267 /* */
268 /* Arguments: */
269 /* fame_decoder_t *decoder: the decoder */
270 /* bitbuffer_t *bb: a bit buffer to write the resulting encoded data to. */
271 /* short x: the x location of the macroblock in macroblock units */
272 /* short y: the y location of the macroblock in macroblock units */
273 /* short *blocks[6]: the DCT coded blocks */
274 /* unsigned char q: the quantizer scale for this block */
275 /* fame_bab_t bab_type: binary alpha block type */
276 /* */
277 /* Return value: */
278 /* None. */
279
mpeg_reconstruct_intra_mb(fame_decoder_t * decoder,short x,short y,short * blocks[6],unsigned char q,fame_bab_t bab_type)280 static void mpeg_reconstruct_intra_mb(fame_decoder_t *decoder,
281 short x,
282 short y,
283 short *blocks[6],
284 unsigned char q,
285 fame_bab_t bab_type)
286 {
287 fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder);
288 unsigned long offset0,offset1,offset2,offset3,offset4,offset5;
289 int pitch;
290 void (* dequantize)(short *block,
291 dct_t *cache,
292 dct_t *dqmatrix,
293 dct_t *psmatrix,
294 dct_t *mismatch);
295 void (* idct_)(dct_t *block);
296 void (* reconstruct_)(unsigned char *plane,
297 dct_t *block,
298 int pitch);
299
300 pitch = decoder_mpeg->new_ref[0]->p;
301
302 /* Make offsets to blocks */
303 offset0 = (y << 4) * pitch + (x << 4); /* Y(0,0) */
304 offset1 = offset0 + 8; /* Y(0,1) */
305 offset2 = offset0 + (pitch << 3); /* Y(1,0) */
306 offset3 = offset2 + 8; /* Y(1,1) */
307 offset4 = (y << 3) * (pitch >> 1) + (x << 3); /* Cb */
308 offset5 = (y << 3) * (pitch >> 1) + (x << 3); /* Cr */
309
310 if(decoder_mpeg->mismatch == fame_mismatch_local)
311 dequantize = dequantize_intra_local;
312 else
313 dequantize = dequantize_intra_global;
314 idct_ = idct;
315 reconstruct_ = reconstruct;
316
317 /* Reconstruct blocks */
318 /* Y(0,0) */
319 dequantize(blocks[0],
320 decoder_mpeg->tmpblock,
321 decoder_mpeg->yidqmatrixes[q],
322 decoder_mpeg->psmatrix,
323 &decoder_mpeg->mismatch_accumulator[0][y*(pitch>>3)+x]);
324 idct_(decoder_mpeg->tmpblock);
325 reconstruct_(decoder_mpeg->new_ref[0]->y + offset0,
326 decoder_mpeg->tmpblock,
327 pitch);
328
329 dequantize(blocks[1],
330 decoder_mpeg->tmpblock,
331 decoder_mpeg->yidqmatrixes[q],
332 decoder_mpeg->psmatrix,
333 &decoder_mpeg->mismatch_accumulator[1][y*(pitch>>3)+x]);
334 idct_(decoder_mpeg->tmpblock);
335 reconstruct_(decoder_mpeg->new_ref[0]->y + offset1,
336 decoder_mpeg->tmpblock,
337 pitch);
338
339 dequantize(blocks[2],
340 decoder_mpeg->tmpblock,
341 decoder_mpeg->yidqmatrixes[q],
342 decoder_mpeg->psmatrix,
343 &decoder_mpeg->mismatch_accumulator[2][y*(pitch>>3)+x]);
344 idct_(decoder_mpeg->tmpblock);
345 reconstruct_(decoder_mpeg->new_ref[0]->y + offset2,
346 decoder_mpeg->tmpblock,
347 pitch);
348
349 dequantize(blocks[3],
350 decoder_mpeg->tmpblock,
351 decoder_mpeg->yidqmatrixes[q],
352 decoder_mpeg->psmatrix,
353 &decoder_mpeg->mismatch_accumulator[3][y*(pitch>>3)+x]);
354 idct_(decoder_mpeg->tmpblock);
355 reconstruct_(decoder_mpeg->new_ref[0]->y + offset3,
356 decoder_mpeg->tmpblock,
357 pitch);
358
359 /* U */
360 dequantize(blocks[4],
361 decoder_mpeg->tmpblock,
362 decoder_mpeg->cidqmatrixes[q],
363 decoder_mpeg->psmatrix,
364 &decoder_mpeg->mismatch_accumulator[4][y*(pitch>>3)+x]);
365 idct_(decoder_mpeg->tmpblock);
366 reconstruct_(decoder_mpeg->new_ref[0]->u + offset4,
367 decoder_mpeg->tmpblock,
368 pitch >> 1);
369
370 /* V */
371 dequantize(blocks[5],
372 decoder_mpeg->tmpblock,
373 decoder_mpeg->cidqmatrixes[q],
374 decoder_mpeg->psmatrix,
375 &decoder_mpeg->mismatch_accumulator[5][y*(pitch>>3)+x]);
376 idct_(decoder_mpeg->tmpblock);
377 reconstruct_(decoder_mpeg->new_ref[0]->v + offset5,
378 decoder_mpeg->tmpblock,
379 pitch >> 1);
380
381 /* fill the block if needed */
382 if(bab_type >= bab_border_16x16)
383 mpeg_pad_mb(decoder, x, y);
384 }
385
386 /* mpeg_reconstruct_inter_mb */
387 /* */
388 /* Description: */
389 /* Reconstruct an inter macroblock for further motion estimation. */
390 /* */
391 /* Arguments: */
392 /* fame_decoder_t *decoder: the decoder */
393 /* bitbuffer_t *bb: a bit buffer to write the resulting encoded data to. */
394 /* short x: the x location of the macroblock in macroblock units */
395 /* short y: the y location of the macroblock in macroblock units */
396 /* short *blocks[6]: the DCT coded blocks */
397 /* fame_motion_vector_t *forward: forward motion vectors */
398 /* fame_motion_vector_t *backward: backward motion vectors */
399 /* unsigned char q: the quantizer scale for this block */
400 /* fame_bab_t bab_type: binary alpha block type */
401 /* */
402 /* Return value: */
403 /* None. */
404
mpeg_reconstruct_inter_mb(fame_decoder_t * decoder,short x,short y,short * blocks[6],fame_motion_vector_t * forward,fame_motion_vector_t * backward,fame_motion_coding_t motion_coding,unsigned char q,fame_bab_t bab_type)405 static void mpeg_reconstruct_inter_mb(fame_decoder_t *decoder,
406 short x,
407 short y,
408 short *blocks[6],
409 fame_motion_vector_t *forward,
410 fame_motion_vector_t *backward,
411 fame_motion_coding_t motion_coding,
412 unsigned char q,
413 fame_bab_t bab_type)
414 {
415 fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder);
416 unsigned long offset[6];
417 signed long motion[6];
418 int coded[6];
419 signed long residual[6];
420 int i, j, pitch;
421 void (* dequantize)(short *block,
422 dct_t *cache,
423 dct_t *dqmatrix,
424 dct_t *psmatrix,
425 dct_t *mismatch);
426
427 pitch = decoder_mpeg->new_ref[0]->p;
428
429 /* Make offsets to blocks */
430 offset[0] = (y << 4) * pitch + (x << 4); /* Y(0,0) */
431 offset[1] = offset[0] + 8; /* Y(0,1) */
432 offset[2] = offset[0] + (pitch << 3); /* Y(1,0) */
433 offset[3] = offset[2] + 8; /* Y(1,1) */
434 offset[4] = (y << 3) * (pitch >> 1) + (x << 3); /* Cb */
435 offset[5] = (y << 3) * (pitch >> 1) + (x << 3); /* Cr */
436
437 /* Compute motion offsets (motion is half-pixel coded) */
438 for(i = 0; i < 4; i++) {
439 /* full-pel motion */
440 motion[i] = (forward[i].dy >> 1) * pitch + (forward[i].dx >> 1);
441 /* half-pel motion */
442 residual[i] = ((forward[i].dy & 1) << 1) | (forward[i].dx & 1);
443 }
444 for(i = 4; i < 6; i++) {
445 /* full-pel motion */
446 motion[i] = (forward[i].dy >> 1) * (pitch >> 1) + (forward[i].dx >> 1);
447 /* half-pel motion */
448 residual[i] = ((forward[i].dy & 1) << 1) | (forward[i].dx & 1);
449 }
450
451 /* check for not coded blocks */
452 for(j = 0; j < 6; j++) {
453 coded[j] = 0;
454 if(blocks[j] != NULL)
455 for(i = 0; i < 64; i++) {
456 coded[j] |= blocks[j][i];
457 }
458 }
459
460 if(decoder_mpeg->mismatch == fame_mismatch_local)
461 dequantize = dequantize_inter_local;
462 else
463 dequantize = dequantize_inter_global;
464
465 /* Reconstruct blocks */
466 for(i = 0; i < 4; i++) { /* Y */
467 if(coded[i]) {
468 dequantize(blocks[i],
469 decoder_mpeg->tmpblock,
470 decoder_mpeg->nidqmatrixes[q],
471 decoder_mpeg->psmatrix,
472 &decoder_mpeg->mismatch_accumulator[i][y*(pitch>>3)+x]);
473 idct(decoder_mpeg->tmpblock);
474 sum(decoder_mpeg->new_ref[0]->y + offset[i],
475 decoder_mpeg->future_ref[residual[i]]->y + offset[i] + motion[i],
476 &forward[i].error,
477 decoder_mpeg->tmpblock,
478 pitch);
479 } else {
480 move(decoder_mpeg->new_ref[0]->y + offset[i],
481 decoder_mpeg->future_ref[residual[i]]->y + offset[i] + motion[i],
482 pitch);
483 forward[i].error = 0;
484 }
485 }
486
487 /* U */
488 if(coded[4]) {
489 dequantize(blocks[4],
490 decoder_mpeg->tmpblock,
491 decoder_mpeg->nidqmatrixes[q],
492 decoder_mpeg->psmatrix,
493 &decoder_mpeg->mismatch_accumulator[4][y*(pitch>>3)+x]);
494 idct(decoder_mpeg->tmpblock);
495 sum(decoder_mpeg->new_ref[0]->u + offset[4],
496 decoder_mpeg->future_ref[residual[4]]->u + offset[4] + motion[4],
497 &forward[4].error,
498 decoder_mpeg->tmpblock,
499 pitch >> 1);
500 } else {
501 move(decoder_mpeg->new_ref[0]->u + offset[4],
502 decoder_mpeg->future_ref[residual[4]]->u + offset[4] + motion[4],
503 pitch >> 1);
504 forward[4].error = 0;
505 }
506
507 /* V */
508 if(coded[5]) {
509 dequantize(blocks[5],
510 decoder_mpeg->tmpblock,
511 decoder_mpeg->nidqmatrixes[q],
512 decoder_mpeg->psmatrix,
513 &decoder_mpeg->mismatch_accumulator[5][y*(pitch>>3)+x]);
514 idct(decoder_mpeg->tmpblock);
515 sum(decoder_mpeg->new_ref[0]->v + offset[5],
516 decoder_mpeg->future_ref[residual[5]]->v + offset[5] + motion[5],
517 &forward[5].error,
518 decoder_mpeg->tmpblock,
519 pitch >> 1);
520 } else {
521 move(decoder_mpeg->new_ref[0]->v + offset[5],
522 decoder_mpeg->future_ref[residual[5]]->v + offset[5] + motion[5],
523 pitch >> 1);
524 forward[5].error = 0;
525 }
526
527 /* fill the block if needed */
528 if(bab_type >= bab_border_16x16)
529 mpeg_pad_mb(decoder, x, y);
530 }
531
532 /* mpeg_pad */
533 /* */
534 /* Description: */
535 /* Perform extended padding for motion estimation. */
536 /* */
537 /* Arguments: */
538 /* fame_decoder_t *decoder: the decoder */
539 /* unsigned char *bab_map: binary alpha block type map */
540 /* fame_box_t box: bounding box */
541 /* */
542 /* Return value: */
543 /* None. */
544
mpeg_pad(fame_decoder_t * decoder,unsigned char * bab_map,fame_box_t * box)545 static void mpeg_pad(fame_decoder_t *decoder,
546 unsigned char *bab_map,
547 fame_box_t *box)
548 {
549 fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder);
550 int i;
551 void (* pad)(int i,
552 int width,
553 int height,
554 fame_yuv_t **frame,
555 unsigned char *shape, /* not used */
556 unsigned char *bab_map, /* not used */
557 fame_box_t *box);
558
559 if(decoder_mpeg->shape)
560 pad = extended_pad_withmask;
561 else
562 pad = extended_pad_withoutmask;
563
564 for(i = 0; i < 4; i++)
565 pad(i,
566 decoder_mpeg->width,
567 decoder_mpeg->height,
568 decoder_mpeg->new_ref,
569 decoder_mpeg->shape,
570 bab_map,
571 box);
572 }
573
574
575 /* mpeg_interpolate */
576 /* */
577 /* Description: */
578 /* Compute half-pel resolution frames from reference frame. */
579 /* */
580 /* Arguments: */
581 /* fame_decoder_t *decoder: the decoder */
582 /* */
583 /* Return value: */
584 /* None. */
585
mpeg_interpolate(fame_decoder_t * decoder,int rounding)586 static void mpeg_interpolate(fame_decoder_t *decoder, int rounding)
587 {
588 fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder);
589
590 half_interpolate(decoder_mpeg->width,
591 decoder_mpeg->height,
592 decoder_mpeg->new_ref,
593 rounding);
594 }
595
596 /* mpeg_leave */
597 /* */
598 /* Description: */
599 /* End the encoding of a picture. */
600 /* */
601 /* Arguments: */
602 /* fame_decoder_t *decoder: the decoder */
603 /* */
604 /* Return value: */
605 /* None. */
606
mpeg_leave(fame_decoder_t * decoder)607 static void mpeg_leave(fame_decoder_t *decoder)
608 {
609 arch_leave_state();
610 }
611
612 #ifdef HAS_MMX
613 /* mpeg_close */
614 /* */
615 /* Description: */
616 /* Release the decoder. */
617 /* */
618 /* Arguments: */
619 /* fame_decoder_t *decoder: the decoder */
620 /* */
621 /* Return value: */
622 /* None. */
623
mpeg_close(fame_decoder_t * decoder)624 static void mpeg_close(fame_decoder_t *decoder)
625 {
626 fame_decoder_mpeg_t *decoder_mpeg = FAME_DECODER_MPEG(decoder);
627
628 /* free mismatch accumulator */
629 {
630 int i;
631 if(decoder_mpeg->mismatch == fame_mismatch_global)
632 for(i = 0; i < 6; i++)
633 fame_free(decoder_mpeg->mismatch_accumulator[i]);
634 }
635 }
636 #endif
637