r1026: Videoscope layout tweaks.
[cinelerra_cv/ct.git] / quicktime / encore50 / vop_code.c
blob63e2948dffdcf37ff28f0f341db6ff60d831a18d
2 /**************************************************************************
3 * *
4 * This code is developed by Adam Li. This software is an *
5 * implementation of a part of one or more MPEG-4 Video tools as *
6 * specified in ISO/IEC 14496-2 standard. Those intending to use this *
7 * software module in hardware or software products are advised that its *
8 * use may infringe existing patents or copyrights, and any such use *
9 * would be at such party's own risk. The original developer of this *
10 * software module and his/her company, and subsequent editors and their *
11 * companies (including Project Mayo), will have no liability for use of *
12 * this software or modifications or derivatives thereof. *
13 * *
14 * Project Mayo gives users of the Codec a license to this software *
15 * module or modifications thereof for use in hardware or software *
16 * products claiming conformance to the MPEG-4 Video Standard as *
17 * described in the Open DivX license. *
18 * *
19 * The complete Open DivX license can be found at *
20 * http://www.projectmayo.com/opendivx/license.php . *
21 * *
22 **************************************************************************/
24 /**************************************************************************
26 * vop_code.c
28 * Copyright (C) 2001 Project Mayo
30 * Adam Li
32 * DivX Advance Research Center <darc@projectmayo.com>
34 **************************************************************************/
36 /* This file contains some functions to do coding of one VOP. */
38 #include "vop_code.h"
39 #include "mot_est_comp.h"
40 //#include "rc_q2.h"
41 #include "bitstream.h"
43 #include "rate_ctl.h"
45 #define SCENE_CHANGE_THREADHOLD 50
46 #define MB_RATIO_THREADHOLD 0.40
48 extern FILE *ftrace;
50 UInt BitstreamPutVopHeader ( Vop *vop,
51 Float time,
52 VolConfig *vol_config
54 Void ImageRepetitivePadding(Image *image, Int edge);
55 Double compute_MAD(Vop *vop);
58 /***********************************************************CommentBegin******
60 * -- VopCode -- Shape, texture and motion coding of the vop
62 * Purpose :
63 * This function performs shape, texture and motion coding of the
64 * vop passed to it. The input vop is assumed to be BOUNDED.
66 * Arguments in :
67 * Vop *curr - pointer to vop to be coded
68 * Vop *prev - pointer the last occurence of this vop
69 * Vop *rec_prev - pointer to last coded occurence of this vop
70 * Int enable_8x8_mv - 8x8 motion vectors flag (SpSc)
71 * Int intra_dcpred_disable - disable intradc prediction
72 * Float time -
73 * VolConfig *vol_config -
75 * Arguments in/out :
76 * Vop *rec_curr - coded vop
77 * Bitcount num_bits - BitCount structures
79 ***********************************************************CommentEnd********/
81 Void VopCode(Vop *curr,
82 Vop *reference,
83 Vop *reconstruct,
84 Vop *error,
85 Int enable_8x8_mv,
86 Float time,
87 VolConfig *vol_config,
88 int quant)
90 ImageF *mot_x=NULL, *mot_y=NULL;
91 Image *MB_decisions=NULL;
92 Int edge,f_code_for=1;
93 Vop *error_vop=NULL;
94 Int vop_quantizer;
96 Float mad_P = 0., mad_I = 0.;
97 Float IntraMBRatio = 1.;
98 Int numberMB, i, IntraMB;
100 edge = 0;
101 f_code_for = curr->fcode_for;
103 if (curr->prediction_type == P_VOP)
105 /* Carry out motion estimation and compensation*/
106 MotionEstimationCompensation(curr, reference,
107 enable_8x8_mv, edge ,f_code_for,
108 reconstruct, &mad_P, &mot_x,&mot_y,&MB_decisions);
110 /* Calculate the percentage of the MBs that are Intra */
111 IntraMB = 0;
112 numberMB = MB_decisions->x * MB_decisions->y;
113 for (i = 0; i < numberMB; i ++)
114 if (MB_decisions->f[i] == MBM_INTRA) IntraMB ++;
115 IntraMBRatio = (float)IntraMB / (float)numberMB;
117 #ifdef _RC_
118 fprintf(ftrace, "ME with MAD : %f\n", mad_P);
119 fprintf(ftrace, "%4.2f of the MBs are I-MBs.\n", IntraMBRatio);
120 #endif
122 else
123 mad_P = SCENE_CHANGE_THREADHOLD * 2;
125 if ((mad_P < SCENE_CHANGE_THREADHOLD / 3) ||
126 ((mad_P < SCENE_CHANGE_THREADHOLD) && (IntraMBRatio < MB_RATIO_THREADHOLD)))
128 // mad is fine. continue to code as P_VOP
129 curr->prediction_type = P_VOP;
130 error->prediction_type = P_VOP;
132 #ifdef _RC_
133 fprintf(ftrace, "Coding mode : INTER\n");
134 #endif
136 vop_quantizer = (quant > 0) ? quant : RateCtlGetQ(mad_P);
138 curr->quantizer = vop_quantizer;
139 error->quantizer = vop_quantizer;
141 #ifdef _RC_DEBUG_
142 fprintf(stdout, "RC: >>>>> New quantizer= %d\n", vop_quantizer);
143 #endif
145 SubImage(curr->y_chan, reconstruct->y_chan, error->y_chan);
146 SubImage(curr->u_chan, reconstruct->u_chan, error->u_chan);
147 SubImage(curr->v_chan, reconstruct->v_chan, error->v_chan);
149 BitstreamPutVopHeader(curr,time,vol_config);
151 VopShapeMotText(error, reconstruct, MB_decisions,
152 mot_x, mot_y, f_code_for,
153 GetVopIntraACDCPredDisable(curr), reference,
154 NULL/*mottext_bitstream*/);
155 } else {
156 // mad is too large.
157 // the coding mode should be I_VOP
158 curr->prediction_type = I_VOP;
159 curr->rounding_type = 1;
161 #ifdef _RC_
162 fprintf(ftrace, "Coding mode : INTRA\n");
163 #endif
165 // We need to recalculate MAD here, since the last MAD was calculated by assuming
166 // INTER coding, though the actual difference might not be significant to coding.
167 if (mad_I == 0.) mad_I = (Float) compute_MAD(curr);
169 vop_quantizer = (quant > 0) ? quant : RateCtlGetQ(mad_I);
171 curr->intra_quantizer = vop_quantizer;
172 curr->rounding_type = 1;
174 BitstreamPutVopHeader(curr,time,vol_config);
176 /* Code Texture in Intra mode */
177 VopCodeShapeTextIntraCom(curr,
178 reference,
179 NULL/*texture_bitstream*/
184 if (MB_decisions) FreeImage(MB_decisions);
185 if (mot_x) FreeImage(mot_x);
186 if (mot_y) FreeImage(mot_y);
188 ImageRepetitivePadding(reference->y_chan, 16);
189 ImageRepetitivePadding(reference->u_chan, 8);
190 ImageRepetitivePadding(reference->v_chan, 8);
192 Bitstream_NextStartCode();
194 return;
195 } /* CodeVop() */
198 /***********************************************************CommentBegin******
200 * -- BitstreamPutVopHeader -- Writes all fields of the vop header syntax
202 * Purpose :
203 * This function writes all fields of the vop header syntax to the
204 * bitstream disk file.
206 * Arguments in :
207 * Vop *vop - pointer to vop containing header information
209 * Return values :
210 * UInt num_bits - number of bits written
212 * Description :
213 * The vop header (start_code, vop_ID, etc.) is first
214 * written to an intermediate integer level bitstream data structure.
215 * This intermediate bitstream data structure is then written to disk.
217 ***********************************************************CommentEnd********/
219 UInt
220 BitstreamPutVopHeader(Vop *vop,
221 Float time,
222 VolConfig *vol_config)
224 Image *buffer = NULL;
225 Int bits;
226 Int time_modulo;
227 Float time_inc;
229 Int index;
231 UInt num_bits_header=0;
235 * Write all syntax fields in vop header to data structure
239 BitstreamPutBits(buffer,VOP_START_CODE,VOP_START_CODE_LENGTH);
241 BitstreamPutBits(buffer,GetVopPredictionType(vop),2);
243 index = GetVolConfigModTimeBase(vol_config, 1);
245 time_modulo = (int)time - index*1000;
246 while(time_modulo >= 1000)
248 BitstreamPutBits(buffer,1,1);
249 time_modulo = time_modulo - 1000;
250 index++;
251 printf("time modulo : 1\n");
253 BitstreamPutBits(buffer,0,1);
255 /* Store this modulo time base */
256 PutVolConfigModTimeBase(index,vol_config);
258 time_inc = (time - index*1000);
260 bits = (int)ceil(log((double)GetVopTimeIncrementResolution(vop))/log(2.0));
261 if (bits<1) bits=1;
262 time_inc=time_inc*GetVopTimeIncrementResolution(vop)/1000.0f;
264 /* marker bit */
265 BitstreamPutBits(buffer,1,1);
267 BitstreamPutBits(buffer,(Int)(time_inc+0.001),bits);
269 /* marker bit */
270 BitstreamPutBits(buffer,1,1);
272 if (GetVopWidth(vop)==0)
274 printf("Empty VOP at %.2f\n",time); /* MW 30-NOV-1998 */
275 BitstreamPutBits(buffer,0L,1L);
276 num_bits_header += Bitstream_NextStartCode();
277 return(num_bits_header);
279 else
280 BitstreamPutBits(buffer,1L,1L);
282 if( GetVopPredictionType(vop) == P_VOP )
283 BitstreamPutBits(buffer,GetVopRoundingType(vop),1);
285 BitstreamPutBits(buffer,GetVopIntraDCVlcThr(vop),3);
287 if (GetVopPredictionType(vop) == I_VOP) /* I_VOP */
288 BitstreamPutBits(buffer,GetVopIntraQuantizer(vop),GetVopQuantPrecision(vop));
289 else /* P_VOP */
290 BitstreamPutBits(buffer,GetVopQuantizer(vop),GetVopQuantPrecision(vop));
292 if (GetVopPredictionType(vop)!=I_VOP)
294 BitstreamPutBits(buffer,GetVopFCodeFor(vop),3);
297 return(num_bits_header);
300 // do repetitive padding for image
301 // make sure set edge = 16 for Y and 8 for UV
302 Void ImageRepetitivePadding(Image *image, Int edge)
304 SInt *p, left, right;
305 Int width, height, x, y;
307 p = image->f;
308 width = image->x;
309 height = image->y;
311 /* Horizontal Padding */
312 for( y=edge; y<height-edge; y++)
314 left = p[y*width+edge];
315 right = p[y*width+width-edge-1];
316 for(x=0; x<edge; x++)
318 p[y*width+x] = left;
319 p[y*width+width-edge+x] = right;
323 /* Vertical Padding */
324 for(y=0; y<edge; y++)
325 for(x=0; x<width; x++)
326 p[y*width+x] = p[edge*width+x];
328 for(y=height-edge; y<height; y++)
329 for(x=0; x<width; x++)
330 p[y*width+x] = p[(height-1-edge)*width+x];
332 return;
336 /***********************************************************CommentBegin******
338 * -- compute_MAD --
340 * Purpose :
341 * Calculate the MAD of a VOP
343 * Arguments in :
344 * Vop *error_vop - Vop with error residue
346 ***********************************************************CommentEnd********/
348 // This function is now only called when the coding mode is I_VOP.
349 Double compute_MAD(
350 Vop *error_vop
353 SInt *curr_in,
354 *curr_end;
355 Float *curr_fin,
356 *curr_fend;
357 UInt sxy_in;
358 Double mad=0.0, dc = 0.0;
359 Int cnt=0;
361 /* Calculate the MAD */
362 switch (GetImageType(error_vop->y_chan))
364 case SHORT_TYPE:
365 /* change to AC MAD */
366 /* calculate average first */
367 curr_in = (SInt*)GetImageData(error_vop->y_chan);
368 sxy_in = GetImageSize(error_vop->y_chan);
369 curr_end = curr_in + sxy_in;
370 cnt = 0;
371 while (curr_in != curr_end)
373 dc += *curr_in; //abs(*curr_in);
374 cnt++;
375 curr_in++;
377 dc /= cnt;
379 curr_in = (SInt*)GetImageData(error_vop->y_chan);
380 sxy_in = GetImageSize(error_vop->y_chan);
381 curr_end = curr_in + sxy_in;
382 cnt = 0;
383 while (curr_in != curr_end)
385 mad += fabs(*curr_in - dc);
386 cnt++;
387 curr_in++;
389 mad /= cnt;
390 break;
391 case FLOAT_TYPE:
392 curr_fin = (Float*)GetImageData(error_vop->y_chan);
393 sxy_in = GetImageSize(error_vop->y_chan);
394 curr_fend = curr_fin + sxy_in;
395 cnt = 0;
396 while (curr_fin != curr_fend)
398 mad += fabs(*curr_fin);
399 cnt++;
400 curr_fin++;
402 mad /= cnt;
403 break;
404 default: break;
407 #ifdef _RC_
408 fprintf(ftrace, "The MAD of the VOP to be coded is %f.\n", mad);
409 #endif
411 return mad;