vop_code.c
上传用户:enenge
上传日期:2007-01-08
资源大小:96k
文件大小:11k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /**************************************************************************
  2.  *                                                                        *
  3.  * This code is developed by Adam Li.  This software is an                *
  4.  * implementation of a part of one or more MPEG-4 Video tools as          *
  5.  * specified in ISO/IEC 14496-2 standard.  Those intending to use this    *
  6.  * software module in hardware or software products are advised that its  *
  7.  * use may infringe existing patents or copyrights, and any such use      *
  8.  * would be at such party's own risk.  The original developer of this     *
  9.  * software module and his/her company, and subsequent editors and their  *
  10.  * companies (including Project Mayo), will have no liability for use of  *
  11.  * this software or modifications or derivatives thereof.                 *
  12.  *                                                                        *
  13.  * Project Mayo gives users of the Codec a license to this software       *
  14.  * module or modifications thereof for use in hardware or software        *
  15.  * products claiming conformance to the MPEG-4 Video Standard as          *
  16.  * described in the Open DivX license.                                    *
  17.  *                                                                        *
  18.  * The complete Open DivX license can be found at                         *
  19.  * http://www.projectmayo.com/opendivx/license.php .                      *
  20.  *                                                                        *
  21.  **************************************************************************/
  22. /**************************************************************************
  23.  *
  24.  *  vop_code.c
  25.  *
  26.  *  Copyright (C) 2001  Project Mayo
  27.  *
  28.  *  Adam Li
  29.  *
  30.  *  DivX Advance Research Center <darc@projectmayo.com>
  31.  *
  32.  **************************************************************************/
  33. /* This file contains some functions to do coding of one VOP.            */
  34. #include "vop_code.h"
  35. #include "mot_est_comp.h"
  36. //#include "rc_q2.h"
  37. #include "bitstream.h"
  38. #include "rate_ctl.h"
  39. #define SCENE_CHANGE_THREADHOLD 50
  40. #define MB_RATIO_THREADHOLD 0.40
  41. extern FILE *ftrace;
  42. UInt   BitstreamPutVopHeader ( Vop *vop,
  43. Float time,
  44. VolConfig *vol_config
  45. );
  46. Void ImageRepetitivePadding(Image *image, Int edge);
  47. Double compute_MAD(Vop *vop);
  48. /***********************************************************CommentBegin******
  49.  *
  50.  * -- VopCode -- Shape, texture and motion coding of the vop
  51.  *
  52.  * Purpose :
  53.  * This function performs shape, texture and motion coding of the
  54.  * vop passed to it. The input vop is assumed to be BOUNDED.
  55.  *
  56.  * Arguments in :
  57.  * Vop *curr - pointer to vop to be coded
  58.  * Vop *prev - pointer the last occurence of this vop
  59.  * Vop *rec_prev - pointer to last coded occurence of this vop
  60.  * Int enable_8x8_mv - 8x8 motion vectors flag (SpSc)
  61.  * Int intra_dcpred_disable - disable intradc prediction
  62.  * Float time -
  63.  * VolConfig *vol_config -
  64.  *
  65.  * Arguments in/out :
  66.  * Vop *rec_curr - coded vop
  67.  * Bitcount num_bits - BitCount structures 
  68.  *
  69.  ***********************************************************CommentEnd********/
  70. Void VopCode(Vop *curr,
  71. Vop *reference,
  72. Vop *reconstruct,
  73. Vop *error,
  74. Int enable_8x8_mv,
  75. Float time,
  76. VolConfig *vol_config)
  77. {
  78. ImageF    *mot_x=NULL, *mot_y=NULL;
  79. Image     *MB_decisions=NULL;
  80. Int       edge,f_code_for=1;
  81. Vop       *error_vop=NULL;
  82. Int       vop_quantizer;
  83. Float   mad_P = 0., mad_I = 0.;
  84. Float   IntraMBRatio = 1.;
  85. Int   numberMB, i, IntraMB;
  86. edge = 0;
  87. f_code_for = curr->fcode_for;
  88. if (curr->prediction_type == P_VOP) 
  89. {
  90. /* Carry out motion estimation and compensation*/
  91. MotionEstimationCompensation(curr, reference,
  92. enable_8x8_mv, edge ,f_code_for,
  93. reconstruct, &mad_P, &mot_x,&mot_y,&MB_decisions);
  94. /* Calculate the percentage of the MBs that are Intra */
  95. IntraMB = 0;
  96. numberMB = MB_decisions->x * MB_decisions->y;
  97. for (i = 0; i < numberMB; i ++)
  98. if (MB_decisions->f[i] == MBM_INTRA) IntraMB ++;
  99. IntraMBRatio = (float)IntraMB / (float)numberMB;
  100. #ifdef _RC_
  101. fprintf(ftrace, "ME with MAD : %fn", mad_P);
  102. fprintf(ftrace, "%4.2f of the MBs are I-MBs.n", IntraMBRatio);
  103. #endif
  104. }
  105. else
  106. mad_P = SCENE_CHANGE_THREADHOLD * 2;
  107. if ((mad_P < SCENE_CHANGE_THREADHOLD / 3) || 
  108. ((mad_P < SCENE_CHANGE_THREADHOLD) && (IntraMBRatio < MB_RATIO_THREADHOLD)))
  109. {
  110. // mad is fine. continue to code as P_VOP
  111. curr->prediction_type = P_VOP;
  112. error->prediction_type = P_VOP;
  113. #ifdef _RC_
  114. fprintf(ftrace, "Coding mode : INTERn");
  115. #endif
  116. vop_quantizer = RateCtlGetQ(mad_P);
  117. curr->quantizer = vop_quantizer;
  118. error->quantizer = vop_quantizer;
  119. #ifdef _RC_DEBUG_
  120. fprintf(stdout, "RC: >>>>> New quantizer= %dn", vop_quantizer);
  121. #endif
  122. SubImage(curr->y_chan, reconstruct->y_chan, error->y_chan);
  123. SubImage(curr->u_chan, reconstruct->u_chan, error->u_chan);
  124. SubImage(curr->v_chan, reconstruct->v_chan, error->v_chan); 
  125. BitstreamPutVopHeader(curr,time,vol_config);
  126. VopShapeMotText(error, reconstruct, MB_decisions,
  127. mot_x, mot_y, f_code_for, 
  128. GetVopIntraACDCPredDisable(curr), reference,
  129. NULL/*mottext_bitstream*/);
  130. } else {
  131. // mad is too large. 
  132. // the coding mode should be I_VOP
  133. curr->prediction_type = I_VOP;
  134. curr->rounding_type = 1;
  135. #ifdef _RC_
  136. fprintf(ftrace, "Coding mode : INTRAn");
  137. #endif
  138. // We need to recalculate MAD here, since the last MAD was calculated by assuming
  139. // INTER coding, though the actual difference might not be significant to coding.
  140. if (mad_I == 0.) mad_I = (Float) compute_MAD(curr);
  141. vop_quantizer = RateCtlGetQ(mad_I);
  142. curr->intra_quantizer = vop_quantizer;
  143. curr->rounding_type = 1;
  144. BitstreamPutVopHeader(curr,time,vol_config);
  145. /* Code Texture in Intra mode */
  146. VopCodeShapeTextIntraCom(curr,
  147. reference,
  148. NULL/*texture_bitstream*/
  149. );
  150. if (MB_decisions) FreeImage(MB_decisions);
  151. if (mot_x) FreeImage(mot_x);
  152. if (mot_y) FreeImage(mot_y);
  153. ImageRepetitivePadding(reference->y_chan, 16);
  154. ImageRepetitivePadding(reference->u_chan, 8);
  155. ImageRepetitivePadding(reference->v_chan, 8);
  156. Bitstream_NextStartCode();   
  157. return;
  158. }   /* CodeVop() */
  159. /***********************************************************CommentBegin******
  160.  *
  161.  * -- BitstreamPutVopHeader -- Writes all fields of the vop header syntax
  162.  *
  163.  * Purpose :
  164.  * This function writes all fields of the vop header syntax to the
  165.  * bitstream disk file.
  166.  *
  167.  * Arguments in :
  168.  * Vop *vop - pointer to vop containing header information
  169.  *
  170.  * Return values :
  171.  * UInt num_bits - number of bits written
  172.  *
  173.  * Description :
  174.  * The vop header (start_code, vop_ID, etc.) is first
  175.  * written to an intermediate integer level bitstream data structure.
  176.  * This intermediate bitstream data structure is then written to disk.
  177.  *
  178.  ***********************************************************CommentEnd********/
  179. UInt
  180. BitstreamPutVopHeader(Vop *vop,
  181. Float time, 
  182. VolConfig *vol_config)
  183. {
  184. Image *buffer = NULL;
  185. Int bits;
  186. Int   time_modulo;
  187. Float time_inc;
  188. Int   index;
  189. UInt  num_bits_header=0;
  190. /* 
  191.  *
  192.  * Write all syntax fields in vop header to data structure
  193.  *
  194.  */
  195. BitstreamPutBits(buffer,VOP_START_CODE,VOP_START_CODE_LENGTH);
  196. BitstreamPutBits(buffer,GetVopPredictionType(vop),2);
  197. index = GetVolConfigModTimeBase(vol_config, 1);
  198. time_modulo = (int)time - index*1000;
  199. while(time_modulo >= 1000)
  200. {
  201. BitstreamPutBits(buffer,1,1);
  202. time_modulo = time_modulo - 1000;
  203. index++;
  204. printf("time modulo : 1n");
  205. }
  206. BitstreamPutBits(buffer,0,1);
  207. /* Store this modulo time base */
  208. PutVolConfigModTimeBase(index,vol_config);
  209. time_inc = (time - index*1000);
  210. bits = (int)ceil(log((double)GetVopTimeIncrementResolution(vop))/log(2.0));
  211. if (bits<1) bits=1;
  212. time_inc=time_inc*GetVopTimeIncrementResolution(vop)/1000.0f;
  213. /* marker bit */
  214. BitstreamPutBits(buffer,1,1);
  215. BitstreamPutBits(buffer,(Int)(time_inc+0.001),bits);
  216. /* marker bit */
  217. BitstreamPutBits(buffer,1,1);
  218. if (GetVopWidth(vop)==0)
  219. {
  220. printf("Empty VOP at %.2fn",time);   /* MW 30-NOV-1998 */
  221. BitstreamPutBits(buffer,0L,1L);
  222. num_bits_header += Bitstream_NextStartCode();
  223. return(num_bits_header);
  224. }
  225. else
  226. BitstreamPutBits(buffer,1L,1L);
  227. if( GetVopPredictionType(vop) == P_VOP )
  228. BitstreamPutBits(buffer,GetVopRoundingType(vop),1);
  229. BitstreamPutBits(buffer,GetVopIntraDCVlcThr(vop),3);
  230. if (GetVopPredictionType(vop) == I_VOP)   /* I_VOP */
  231. BitstreamPutBits(buffer,GetVopIntraQuantizer(vop),GetVopQuantPrecision(vop));
  232. else   /* P_VOP */
  233. BitstreamPutBits(buffer,GetVopQuantizer(vop),GetVopQuantPrecision(vop));
  234. if (GetVopPredictionType(vop)!=I_VOP)
  235. {
  236. BitstreamPutBits(buffer,GetVopFCodeFor(vop),3);
  237. }
  238. return(num_bits_header);
  239. }
  240. // do repetitive padding for image
  241. // make sure set edge = 16 for Y and 8 for UV
  242. Void ImageRepetitivePadding(Image *image, Int edge)
  243. {
  244. SInt *p, left, right;
  245. Int width, height, x, y;
  246. p = image->f;
  247. width = image->x;
  248. height = image->y;
  249. /* Horizontal Padding */
  250. for( y=edge; y<height-edge; y++)
  251.     {
  252. left = p[y*width+edge];
  253. right = p[y*width+width-edge-1];
  254. for(x=0; x<edge; x++)
  255. {
  256. p[y*width+x] = left;
  257. p[y*width+width-edge+x] = right;
  258. }
  259.     }
  260. /* Vertical Padding */
  261.     for(y=0; y<edge; y++)
  262.         for(x=0; x<width; x++)
  263.             p[y*width+x] = p[edge*width+x];
  264. for(y=height-edge; y<height; y++)
  265. for(x=0; x<width; x++)
  266. p[y*width+x] = p[(height-1-edge)*width+x];
  267. return;
  268. }
  269. /***********************************************************CommentBegin******
  270.  *
  271.  * -- compute_MAD --
  272.  *
  273.  * Purpose :
  274.  *      Calculate the MAD of a VOP
  275.  *
  276.  * Arguments in :
  277.  *      Vop    *error_vop  - Vop with error residue
  278.  *
  279.  ***********************************************************CommentEnd********/
  280. // This function is now only called when the coding mode is I_VOP.
  281. Double compute_MAD(
  282. Vop  *error_vop
  283. )
  284. {
  285. SInt  *curr_in,
  286. *curr_end;
  287. Float *curr_fin,
  288. *curr_fend;
  289. UInt   sxy_in;
  290. Double mad=0.0, dc = 0.0;
  291. Int    cnt=0;
  292. /* Calculate the MAD */
  293. switch (GetImageType(error_vop->y_chan))
  294. {
  295. case SHORT_TYPE:
  296. /* change to AC MAD */
  297. /* calculate average first */
  298. curr_in = (SInt*)GetImageData(error_vop->y_chan);
  299. sxy_in = GetImageSize(error_vop->y_chan);
  300. curr_end = curr_in + sxy_in;
  301. cnt = 0;
  302. while (curr_in != curr_end)
  303. {
  304. dc += *curr_in; //abs(*curr_in);
  305. cnt++;
  306. curr_in++;
  307. }
  308. dc /= cnt;
  309. curr_in = (SInt*)GetImageData(error_vop->y_chan);
  310. sxy_in = GetImageSize(error_vop->y_chan);
  311. curr_end = curr_in + sxy_in;
  312. cnt = 0;
  313. while (curr_in != curr_end)
  314. {
  315. mad += fabs(*curr_in - dc);
  316. cnt++;
  317. curr_in++;
  318. }
  319. mad /= cnt;
  320. break;
  321. case FLOAT_TYPE:
  322. curr_fin = (Float*)GetImageData(error_vop->y_chan);
  323. sxy_in = GetImageSize(error_vop->y_chan);
  324. curr_fend = curr_fin + sxy_in;
  325. cnt = 0;
  326. while (curr_fin != curr_fend)
  327. {
  328. mad += fabs(*curr_fin);
  329. cnt++;
  330. curr_fin++;
  331. }
  332. mad /= cnt;
  333. break;
  334. default: break;
  335. }
  336. #ifdef _RC_
  337. fprintf(ftrace, "The MAD of the VOP to be coded is %f.n", mad);
  338. #endif
  339. return mad;
  340. }