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