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

流媒体/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.  *  encore.c, MPEG-4 Encoder Core Engine
  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 encore(), which is the main entrance function for   */
  34. /* Encoder Core Engine. It also contains the functions to initialize the  */
  35. /* parameters, and redirect the output stream                             */
  36. #include "encore.h"
  37. #include "vop_code.h"
  38. #include "text_dct.h"
  39. //#include "rc_q2.h"
  40. #include "bitstream.h"
  41. #include "vm_common_defs.h"
  42. #include "rate_ctl.h"
  43. typedef struct _REFERENCE
  44. {
  45. unsigned long handle;
  46. float framerate;
  47. long bitrate;
  48. long rc_period;
  49. long rc_reaction_period;
  50. long rc_reaction_ratio;
  51. long max_key_interval;
  52. int x_dim, y_dim;
  53. int prev_rounding;
  54. int search_range;
  55. int max_quantizer;
  56. int min_quantizer;
  57. long seq;
  58. long curr_run;       /* the current run before the last key frame */
  59. Vop *current;        /* the current frame to be encoded */
  60. Vop *reference;      /* the reference frame - reconstructed previous frame */
  61. Vop *reconstruct;    /* intermediate reconstructed frame - used in inter */
  62. Vop *error;          /* intermediate error frame - used in inter to hold prediction error */
  63. struct _REFERENCE *pnext;
  64. } REFERENCE;
  65. FILE *ftrace = NULL;
  66. int max_quantizer, min_quantizer;
  67. /* private functions used only in this file */
  68. void init_vol_config(VolConfig *vol_config);
  69. void init_vop(Vop *vop);
  70. Int get_fcode (Int sr);
  71. int PutVoVolHeader(int vol_width, int vol_height, int time_increment_resolution, float frame_rate);
  72. int YUV2YUV (int x_dim, int y_dim, void *yuv, void *y_out, void *u_out, void *v_out);
  73. int encore(unsigned long handle, unsigned long enc_opt, void *param1, void *param2)
  74. {
  75. static REFERENCE *ref = NULL;
  76. static VolConfig *vol_config;
  77. // a link list to keep the reference frame for all instances
  78. REFERENCE *ref_curr, *ref_last = NULL;
  79. int x_dim, y_dim, size, length;
  80. int headerbits = 0;
  81. Vop *curr;
  82. ref_curr = ref_last = ref;
  83. while (ref_curr != NULL)
  84. {
  85. if (ref_curr->handle == handle) break;
  86. ref_last = ref_curr;
  87. ref_curr = ref_last->pnext;
  88. }
  89. // create a reference for the new handle when no match is found
  90. if (ref_curr == NULL)
  91. {
  92. if (enc_opt & ENC_OPT_RELEASE) return ENC_OK;
  93. ref_curr = (REFERENCE *)malloc(sizeof(REFERENCE));
  94. ref_curr->handle = handle;
  95. ref_curr->seq = 0;
  96. ref_curr->curr_run = 0;
  97. ref_curr->pnext = NULL;
  98. if (ref) ref_last->pnext = ref_curr;
  99. else ref = ref_curr;
  100. }
  101. // initialize for a handle if requested
  102. if (enc_opt & ENC_OPT_INIT)
  103. {
  104. #ifdef _RC_
  105. ftrace = fopen("trace.txt", "w");
  106. fflush(ftrace);
  107. #endif
  108. init_fdct_enc();
  109. init_idct_enc();
  110. // initializing rate control
  111. ref_curr->framerate = ((ENC_PARAM *)param1)->framerate;
  112. ref_curr->bitrate = ((ENC_PARAM *)param1)->bitrate;
  113. ref_curr->rc_period = ((ENC_PARAM *)param1)->rc_period;
  114. ref_curr->rc_reaction_period = ((ENC_PARAM *)param1)->rc_reaction_period;
  115. ref_curr->rc_reaction_ratio = ((ENC_PARAM *)param1)->rc_reaction_ratio;
  116. ref_curr->x_dim = ((ENC_PARAM *)param1)->x_dim;
  117. ref_curr->y_dim = ((ENC_PARAM *)param1)->y_dim;
  118. ref_curr->max_key_interval = ((ENC_PARAM *)param1)->max_key_interval;
  119. ref_curr->search_range = ((ENC_PARAM *)param1)->search_range;
  120. ref_curr->max_quantizer = ((ENC_PARAM *)param1)->max_quantizer;
  121. ref_curr->min_quantizer = ((ENC_PARAM *)param1)->min_quantizer;
  122. ref_curr->current = AllocVop(ref_curr->x_dim, ref_curr->y_dim);
  123. ref_curr->reference = AllocVop(ref_curr->x_dim + 2 * 16, 
  124. ref_curr->y_dim + 2 * 16);
  125. ref_curr->reconstruct = AllocVop(ref_curr->x_dim, ref_curr->y_dim);
  126. ref_curr->error = AllocVop(ref_curr->x_dim, ref_curr->y_dim);
  127. init_vop(ref_curr->current);
  128. init_vop(ref_curr->reference);
  129. init_vop(ref_curr->reconstruct);
  130. init_vop(ref_curr->error);
  131. ref_curr->reference->hor_spat_ref = -16;
  132. ref_curr->reference->ver_spat_ref = -16;
  133. SetConstantImage(ref_curr->reference->y_chan, 0);
  134. vol_config = (VolConfig *)malloc(sizeof(VolConfig));
  135. init_vol_config(vol_config);
  136. vol_config->frame_rate = ref_curr->framerate;
  137. vol_config->bit_rate = ref_curr->bitrate;
  138. RateCtlInit(8 /* initial quant*/, vol_config->bit_rate / vol_config->frame_rate,
  139. ref_curr->rc_period, ref_curr->rc_reaction_period, ref_curr->rc_reaction_ratio);
  140. return ENC_OK;
  141. }
  142. // release the reference associated with the handle if requested
  143. if (enc_opt & ENC_OPT_RELEASE)
  144. {
  145. if (ref_curr == ref) ref = NULL;
  146. else ref_last->pnext = ref_curr->pnext;
  147. if (ref_curr->current) FreeVop(ref_curr->current);
  148. if (ref_curr->reference) FreeVop(ref_curr->reference);
  149. if (ref_curr->reconstruct) FreeVop(ref_curr->reconstruct);
  150. if (ref_curr->error) FreeVop(ref_curr->error);
  151. free(ref_curr);
  152. free(vol_config);
  153. if (ftrace) {
  154. fclose(ftrace);
  155. ftrace = NULL;
  156. };
  157. return ENC_OK;
  158. }
  159. // initialize the parameters (need to be cleaned later)
  160. max_quantizer = ref_curr->max_quantizer;
  161. min_quantizer = ref_curr->min_quantizer;
  162. x_dim = ref_curr->x_dim;
  163. y_dim = ref_curr->y_dim;
  164. size = x_dim * y_dim;
  165. curr = ref_curr->current;
  166. curr->width = x_dim;
  167. curr->height = y_dim;
  168. curr->sr_for = ref_curr->search_range;
  169. curr->fcode_for = get_fcode(curr->sr_for);
  170. // do transformation for the input image
  171. // this is needed because the legacy MoMuSys code uses short int for each data
  172. YUV2YUV(x_dim, y_dim, ((ENC_FRAME *)param1)->image,
  173. curr->y_chan->f, curr->u_chan->f, curr->v_chan->f);
  174. // adjust the rounding_type for the current image
  175. curr->rounding_type = 1 - ref_curr->prev_rounding;
  176. Bitstream_Init((void *)(((ENC_FRAME *)param1)->bitstream));
  177. if (ref_curr->seq == 0) {
  178. headerbits = PutVoVolHeader(x_dim, y_dim, curr->time_increment_resolution, ref_curr->framerate);
  179. }
  180. #ifdef _RC_
  181. fflush(ftrace);
  182. fprintf(ftrace, "nCoding frame #%dn", ref_curr->seq);
  183. #endif
  184. if (ref_curr->curr_run % ref_curr->max_key_interval == 0) {
  185. curr->prediction_type = I_VOP;
  186. #ifdef _RC_
  187. fprintf(ftrace, "This frame is forced to be coded in INTRA.n");
  188. fprintf(ftrace, "It has been %d frame since the last INTRA.n", ref_curr->curr_run);
  189. #endif
  190. }
  191. else curr->prediction_type = P_VOP;
  192. // Code the image data (YUV) of the current image
  193. VopCode(curr,
  194. ref_curr->reference,
  195. ref_curr->reconstruct,
  196. ref_curr->error,
  197. 1, //enable_8x8_mv,
  198. (float)ref_curr->seq/ref_curr->framerate,  // time
  199. vol_config);
  200. length = Bitstream_Close();
  201. ((ENC_FRAME *)param1)->length = length;
  202. // update the rate control parameters
  203. RateCtlUpdate(length * 8);
  204. ref_curr->prev_rounding = curr->rounding_type;
  205. ref_curr->seq ++;
  206. ref_curr->curr_run ++;
  207. if (curr->prediction_type == I_VOP) {
  208. ((ENC_RESULT *)param2)->isKeyFrame = 1;
  209. ref_curr->curr_run = 1;
  210. } else 
  211. ((ENC_RESULT *)param2)->isKeyFrame = 0;
  212. return ENC_OK;
  213. }
  214. void init_vol_config(VolConfig *vol_config)
  215. {
  216. /* configure VOL */
  217. vol_config->M = 1;
  218. vol_config->frame_skip = 1;
  219. vol_config->quantizer = 8;
  220. vol_config->intra_quantizer = 8;
  221. vol_config->modulo_time_base[0] =0;
  222. vol_config->modulo_time_base[1] =0;
  223. vol_config->frame_rate = 30;
  224. vol_config->bit_rate = 800000;
  225. }
  226. void init_vop(Vop *vop)
  227. {
  228. /* initialize VOPs */
  229. vop->quant_precision = 5;
  230. vop->bits_per_pixel = 8;
  231. // vop->time_increment_resolution = 15 ;
  232. vop->time_increment_resolution = 30000;
  233. vop->intra_acdc_pred_disable = 0;
  234. vop->intra_dc_vlc_thr = 0;
  235. vop->sr_for = 512;
  236. vop->fcode_for = get_fcode(512);
  237. vop->y_chan->type = SHORT_TYPE;
  238. vop->u_chan->type = SHORT_TYPE;
  239. vop->v_chan->type = SHORT_TYPE;
  240. vop->hor_spat_ref = 0;
  241. vop->ver_spat_ref = 0;
  242. }
  243. Int get_fcode (Int sr)
  244. {
  245. if (sr<=16) return 1;
  246. else if (sr<=32) return 2;
  247. else if (sr<=64) return 3;
  248. else if (sr<=128) return 4;
  249. else if (sr<=256) return 5;
  250. else if (sr<=512) return 6;
  251. else if (sr<=1024) return 7;
  252. else return (-1);
  253. }
  254. int PutVoVolHeader(int vol_width, int vol_height, int time_increment_resolution, float frame_rate)
  255. {
  256. int written = 0;
  257. int bits, fixed_vop_time_increment;
  258. Bitstream_PutBits(VO_START_CODE_LENGTH, VO_START_CODE);
  259. Bitstream_PutBits(5, 0); /* vo_id = 0 */
  260. written += VO_START_CODE_LENGTH + 5;
  261. Bitstream_PutBits(VOL_START_CODE_LENGTH, VOL_START_CODE);
  262. Bitstream_PutBits(4, 0); /* vol_id = 0 */
  263. written += VOL_START_CODE_LENGTH + 4;
  264. Bitstream_PutBits(1, 0); /* random_accessible_vol = 0 */
  265. Bitstream_PutBits(8, 1); /* video_object_type_indication = 1 video */
  266. Bitstream_PutBits(1, 1); /* is_object_layer_identifier = 1 */
  267. Bitstream_PutBits(4, 2); /* visual_object_layer_ver_id = 2 */
  268. Bitstream_PutBits(3, 1); /* visual_object_layer_priority = 1 */
  269. written += 1 + 8 + 1 + 4 + 3;
  270. Bitstream_PutBits(4, 1); /* aspect_ratio_info = 1 */
  271. Bitstream_PutBits(1, 0); /* vol_control_parameter = 0 */
  272. Bitstream_PutBits(2, 0); /* vol_shape = 0 rectangular */
  273. Bitstream_PutBits(1, 1); /* marker */
  274. written += 4 + 1 + 2 + 1;
  275. Bitstream_PutBits(16, time_increment_resolution);
  276. Bitstream_PutBits(1, 1); /* marker */
  277. Bitstream_PutBits(1, 1); /* fixed_vop_rate = 1 */
  278. bits = (int)ceil(log((double)time_increment_resolution)/log(2.0));
  279.     if (bits<1) bits=1;
  280. fixed_vop_time_increment = (int)(time_increment_resolution / frame_rate + 0.1);
  281. Bitstream_PutBits(bits, fixed_vop_time_increment);
  282. Bitstream_PutBits(1, 1); /* marker */
  283. written += 16 + 1 + 1 + bits + 1;
  284. Bitstream_PutBits(13, vol_width);
  285. Bitstream_PutBits(1, 1); /* marker */
  286. Bitstream_PutBits(13, vol_height);
  287. Bitstream_PutBits(1, 1); /* marker */
  288. written += 13 + 1 + 13 + 1;
  289. Bitstream_PutBits(1, 0); /* interlaced = 0 */
  290. Bitstream_PutBits(1, 1); /* OBMC_disabled = 1 */
  291. Bitstream_PutBits(2, 0); /* vol_sprite_usage = 0 */
  292. Bitstream_PutBits(1, 0); /* not_8_bit = 0 */
  293. written += 1 + 1 + 2 + 1;
  294. Bitstream_PutBits(1, 0); /* vol_quant_type = 0 */
  295. Bitstream_PutBits(1, 0); /* vol_quarter_pixel = 0 */
  296. Bitstream_PutBits(1, 1); /* complexity_estimation_disabled = 1 */
  297. Bitstream_PutBits(1, 1); /* resync_marker_disabled = 1 */
  298. Bitstream_PutBits(1, 0); /* data_partitioning_enabled = 0 */
  299. Bitstream_PutBits(1, 0); /* scalability = 0 */
  300. written += 1 + 1 + 1 + 1 + 1 + 1;
  301. written += Bitstream_NextStartCode();
  302. return(written);
  303. }
  304. int YUV2YUV (int x_dim, int y_dim, void *yuv, void *y_out, void *u_out, void *v_out)
  305. {
  306. // All this conversion does is to turn data from unsigned char to short int,
  307. // since legacy MoMuSys uses short int.
  308. unsigned char *in;
  309. short int *out;
  310. long size;
  311. in = yuv;
  312. out = y_out;
  313. size = x_dim * y_dim;
  314. while (size --) *(out ++) = *(in ++);
  315. out = u_out;
  316. size = x_dim * y_dim / 4;
  317. while (size --) *(out ++) = *(in ++);
  318. out = v_out;
  319. size = x_dim * y_dim / 4;
  320. while (size --) *(out ++) = *(in ++);
  321. return 0;
  322. }