2 /**************************************************************************
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. *
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. *
19 * The complete Open DivX license can be found at *
20 * http://www.projectmayo.com/opendivx/license.php . *
22 **************************************************************************/
24 /**************************************************************************
28 * Copyright (C) 2001 Project Mayo
32 * DivX Advance Research Center <darc@projectmayo.com>
34 **************************************************************************/
36 /* This file contains some functions to do coding of one VOP. */
39 #include "mot_est_comp.h"
41 #include "bitstream.h"
45 #define SCENE_CHANGE_THREADHOLD 50
46 #define MB_RATIO_THREADHOLD 0.40
50 UInt
BitstreamPutVopHeader ( Vop
*vop
,
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
63 * This function performs shape, texture and motion coding of the
64 * vop passed to it. The input vop is assumed to be BOUNDED.
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
73 * VolConfig *vol_config -
76 * Vop *rec_curr - coded vop
77 * Bitcount num_bits - BitCount structures
79 ***********************************************************CommentEnd********/
81 Void
VopCode(Vop
*curr
,
87 VolConfig
*vol_config
,
90 ImageF
*mot_x
=NULL
, *mot_y
=NULL
;
91 Image
*MB_decisions
=NULL
;
92 Int edge
,f_code_for
=1;
96 Float mad_P
= 0., mad_I
= 0.;
97 Float IntraMBRatio
= 1.;
98 Int numberMB
, i
, IntraMB
;
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 */
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
;
118 fprintf(ftrace
, "ME with MAD : %f\n", mad_P
);
119 fprintf(ftrace
, "%4.2f of the MBs are I-MBs.\n", IntraMBRatio
);
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
;
133 fprintf(ftrace
, "Coding mode : INTER\n");
136 vop_quantizer
= (quant
> 0) ? quant
: RateCtlGetQ(mad_P
);
138 curr
->quantizer
= vop_quantizer
;
139 error
->quantizer
= vop_quantizer
;
142 fprintf(stdout
, "RC: >>>>> New quantizer= %d\n", vop_quantizer
);
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*/);
157 // the coding mode should be I_VOP
158 curr
->prediction_type
= I_VOP
;
159 curr
->rounding_type
= 1;
162 fprintf(ftrace
, "Coding mode : INTRA\n");
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
,
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();
198 /***********************************************************CommentBegin******
200 * -- BitstreamPutVopHeader -- Writes all fields of the vop header syntax
203 * This function writes all fields of the vop header syntax to the
204 * bitstream disk file.
207 * Vop *vop - pointer to vop containing header information
210 * UInt num_bits - number of bits written
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********/
220 BitstreamPutVopHeader(Vop
*vop
,
222 VolConfig
*vol_config
)
224 Image
*buffer
= NULL
;
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;
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));
262 time_inc
=time_inc
*GetVopTimeIncrementResolution(vop
)/1000.0f
;
265 BitstreamPutBits(buffer
,1,1);
267 BitstreamPutBits(buffer
,(Int
)(time_inc
+0.001),bits
);
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
);
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
));
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
;
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
++)
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
];
336 /***********************************************************CommentBegin******
341 * Calculate the MAD of a VOP
344 * Vop *error_vop - Vop with error residue
346 ***********************************************************CommentEnd********/
348 // This function is now only called when the coding mode is I_VOP.
358 Double mad
=0.0, dc
= 0.0;
361 /* Calculate the MAD */
362 switch (GetImageType(error_vop
->y_chan
))
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
;
371 while (curr_in
!= curr_end
)
373 dc
+= *curr_in
; //abs(*curr_in);
379 curr_in
= (SInt
*)GetImageData(error_vop
->y_chan
);
380 sxy_in
= GetImageSize(error_vop
->y_chan
);
381 curr_end
= curr_in
+ sxy_in
;
383 while (curr_in
!= curr_end
)
385 mad
+= fabs(*curr_in
- dc
);
392 curr_fin
= (Float
*)GetImageData(error_vop
->y_chan
);
393 sxy_in
= GetImageSize(error_vop
->y_chan
);
394 curr_fend
= curr_fin
+ sxy_in
;
396 while (curr_fin
!= curr_fend
)
398 mad
+= fabs(*curr_fin
);
408 fprintf(ftrace
, "The MAD of the VOP to be coded is %f.\n", mad
);