r1026: Videoscope layout tweaks.
[cinelerra_cv/ct.git] / quicktime / encore50 / encore.c
blob65e365f33a21c6d409c7463d362627a9c68b8d85
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 * encore.c, MPEG-4 Encoder Core Engine
28 * Copyright (C) 2001 Project Mayo
30 * Adam Li
32 * DivX Advance Research Center <darc@projectmayo.com>
34 **************************************************************************/
36 /* This file contains encore(), which is the main entrance function for */
37 /* Encoder Core Engine. It also contains the functions to initialize the */
38 /* parameters, and redirect the output stream */
40 #include "encore.h"
42 #include "vop_code.h"
43 #include "text_dct.h"
44 //#include "rc_q2.h"
45 #include "bitstream.h"
46 #include "vm_common_defs.h"
48 #include "rate_ctl.h"
50 typedef struct _REFERENCE
52 unsigned long handle;
53 float framerate;
54 long bitrate;
55 long rc_period;
56 long rc_reaction_period;
57 long rc_reaction_ratio;
58 long max_key_interval;
59 int x_dim, y_dim;
60 int prev_rounding;
61 int search_range;
62 int max_quantizer;
63 int min_quantizer;
65 long seq;
66 long curr_run; /* the current run before the last key frame */
68 Vop *current; /* the current frame to be encoded */
69 Vop *reference; /* the reference frame - reconstructed previous frame */
70 Vop *reconstruct; /* intermediate reconstructed frame - used in inter */
71 Vop *error; /* intermediate error frame - used in inter to hold prediction error */
73 struct _REFERENCE *pnext;
74 } REFERENCE;
76 FILE *ftrace = NULL;
77 int max_quantizer, min_quantizer;
79 /* private functions used only in this file */
80 void init_vol_config(VolConfig *vol_config);
81 void init_vop(Vop *vop);
82 Int get_fcode (Int sr);
83 int PutVoVolHeader(int vol_width, int vol_height, int time_increment_resolution, float frame_rate);
84 int YUV2YUV (int x_dim, int y_dim, void *yuv, void *y_out, void *u_out, void *v_out);
87 // Set global variables for an encoding session
88 void encore_set_global(ENC_PARAM *param)
93 int encore(unsigned long handle,
94 unsigned long enc_opt,
95 void *param1,
96 void *param2)
98 static REFERENCE *ref = NULL;
99 static VolConfig *vol_config;
100 // a link list to keep the reference frame for all instances
102 REFERENCE *ref_curr, *ref_last = NULL;
103 int x_dim, y_dim, size, length;
104 int headerbits = 0;
105 Vop *curr;
107 ref_curr = ref_last = ref;
109 //printf("encore 1\n");
110 while (ref_curr != NULL)
112 if (ref_curr->handle == handle) break;
113 ref_last = ref_curr;
114 ref_curr = ref_last->pnext;
116 // create a reference for the new handle when no match is found
117 if (ref_curr == NULL)
119 if (enc_opt & ENC_OPT_RELEASE) return ENC_OK;
120 ref_curr = (REFERENCE *)malloc(sizeof(REFERENCE));
121 ref_curr->handle = handle;
122 ref_curr->seq = 0;
123 ref_curr->curr_run = 0;
124 ref_curr->pnext = NULL;
125 if (ref) ref_last->pnext = ref_curr;
126 else ref = ref_curr;
128 //printf("encore 1\n");
129 // initialize for a handle if requested
130 if (enc_opt & ENC_OPT_INIT)
132 #ifdef _RC_
133 ftrace = fopen("trace.txt", "w");
134 fflush(ftrace);
135 #endif
137 init_fdct_enc();
138 init_idct_enc();
140 // initializing rate control
141 ref_curr->framerate = ((ENC_PARAM *)param1)->framerate;
142 ref_curr->bitrate = ((ENC_PARAM *)param1)->bitrate;
143 ref_curr->rc_period = ((ENC_PARAM *)param1)->rc_period;
144 ref_curr->rc_reaction_period = ((ENC_PARAM *)param1)->rc_reaction_period;
145 ref_curr->rc_reaction_ratio = ((ENC_PARAM *)param1)->rc_reaction_ratio;
146 ref_curr->x_dim = ((ENC_PARAM *)param1)->x_dim;
147 ref_curr->y_dim = ((ENC_PARAM *)param1)->y_dim;
148 ref_curr->max_key_interval = ((ENC_PARAM *)param1)->max_key_interval;
149 ref_curr->search_range = ((ENC_PARAM *)param1)->search_range;
150 ref_curr->max_quantizer = ((ENC_PARAM *)param1)->max_quantizer;
151 ref_curr->min_quantizer = ((ENC_PARAM *)param1)->min_quantizer;
153 ref_curr->current = AllocVop(ref_curr->x_dim, ref_curr->y_dim);
154 ref_curr->reference = AllocVop(ref_curr->x_dim + 2 * 16,
155 ref_curr->y_dim + 2 * 16);
156 ref_curr->reconstruct = AllocVop(ref_curr->x_dim, ref_curr->y_dim);
157 ref_curr->error = AllocVop(ref_curr->x_dim, ref_curr->y_dim);
158 init_vop(ref_curr->current);
159 init_vop(ref_curr->reference);
160 init_vop(ref_curr->reconstruct);
161 init_vop(ref_curr->error);
162 ref_curr->reference->hor_spat_ref = -16;
163 ref_curr->reference->ver_spat_ref = -16;
164 SetConstantImage(ref_curr->reference->y_chan, 0);
166 vol_config = (VolConfig *)malloc(sizeof(VolConfig));
167 init_vol_config(vol_config);
168 vol_config->frame_rate = ref_curr->framerate;
169 vol_config->bit_rate = ref_curr->bitrate;
171 RateCtlInit(8 /* initial quant*/, vol_config->bit_rate / vol_config->frame_rate,
172 ref_curr->rc_period, ref_curr->rc_reaction_period, ref_curr->rc_reaction_ratio);
174 return ENC_OK;
176 //printf("encore 1\n");
177 // release the reference associated with the handle if requested
178 if (enc_opt & ENC_OPT_RELEASE)
180 if (ref_curr == ref) ref = NULL;
181 else ref_last->pnext = ref_curr->pnext;
183 if (ref_curr->current) FreeVop(ref_curr->current);
184 if (ref_curr->reference) FreeVop(ref_curr->reference);
185 if (ref_curr->reconstruct) FreeVop(ref_curr->reconstruct);
186 if (ref_curr->error) FreeVop(ref_curr->error);
188 free(ref_curr);
189 free(vol_config);
190 if (ftrace) {
191 fclose(ftrace);
192 ftrace = NULL;
194 return ENC_OK;
197 //printf("encore 1\n");
198 // initialize the parameters (need to be cleaned later)
200 max_quantizer = ref_curr->max_quantizer;
201 min_quantizer = ref_curr->min_quantizer;
203 x_dim = ref_curr->x_dim;
204 y_dim = ref_curr->y_dim;
205 size = x_dim * y_dim;
207 curr = ref_curr->current;
208 curr->width = x_dim;
209 curr->height = y_dim;
210 curr->sr_for = ref_curr->search_range;
211 curr->fcode_for = get_fcode(curr->sr_for);
213 // do transformation for the input image
214 // this is needed because the legacy MoMuSys code uses short int for each data
215 YUV2YUV(x_dim, y_dim, ((ENC_FRAME *)param1)->image,
216 curr->y_chan->f,
217 curr->u_chan->f,
218 curr->v_chan->f);
220 // adjust the rounding_type for the current image
221 curr->rounding_type = 1 - ref_curr->prev_rounding;
222 //printf("encore 1\n");
224 Bitstream_Init((void *)(((ENC_FRAME *)param1)->bitstream));
225 //printf("encore 1\n");
227 if (ref_curr->seq == 0)
229 headerbits = PutVoVolHeader(x_dim,
230 y_dim,
231 curr->time_increment_resolution,
232 ref_curr->framerate);
234 //printf("encore 1\n");
236 #ifdef _RC_
237 fflush(ftrace);
238 fprintf(ftrace, "\nCoding frame #%d\n", ref_curr->seq);
239 #endif
240 //printf("encore 1 %p %p\n", ref_curr, curr);
242 if (ref_curr->curr_run % ref_curr->max_key_interval == 0) {
243 curr->prediction_type = I_VOP;
244 #ifdef _RC_
245 fprintf(ftrace, "This frame is forced to be coded in INTRA.\n");
246 fprintf(ftrace, "It has been %d frame since the last INTRA.\n", ref_curr->curr_run);
247 #endif
249 else curr->prediction_type = P_VOP;
259 //printf("encore 1\n");
260 // Code the image data (YUV) of the current image
261 VopCode(curr,
262 ref_curr->reference,
263 ref_curr->reconstruct,
264 ref_curr->error,
265 1, //enable_8x8_mv,
266 (float)ref_curr->seq/ref_curr->framerate, // time
267 vol_config,
268 ((ENC_FRAME *)param1)->quant);
276 length = Bitstream_Close();
277 ((ENC_FRAME *)param1)->length = length;
279 //printf("encore 2\n");
280 // update the rate control parameters
281 RateCtlUpdate(length * 8);
283 ref_curr->prev_rounding = curr->rounding_type;
284 ref_curr->seq ++;
285 ref_curr->curr_run ++;
287 if (curr->prediction_type == I_VOP) {
288 ((ENC_RESULT *)param2)->isKeyFrame = 1;
289 ref_curr->curr_run = 1;
290 } else
291 ((ENC_RESULT *)param2)->isKeyFrame = 0;
292 //printf("encore 3\n");
294 return ENC_OK;
298 void init_vol_config(VolConfig *vol_config)
300 /* configure VOL */
301 vol_config->M = 1;
302 vol_config->frame_skip = 1;
303 vol_config->quantizer = 8;
304 vol_config->intra_quantizer = 8;
305 vol_config->modulo_time_base[0] =0;
306 vol_config->modulo_time_base[1] =0;
307 vol_config->frame_rate = 30;
308 vol_config->bit_rate = 800000;
312 void init_vop(Vop *vop)
314 /* initialize VOPs */
315 vop->quant_precision = 5;
316 vop->bits_per_pixel = 8;
317 // vop->time_increment_resolution = 15 ;
318 vop->time_increment_resolution = 30000;
319 vop->intra_acdc_pred_disable = 0;
320 vop->intra_dc_vlc_thr = 0;
322 vop->sr_for = 512;
323 vop->fcode_for = get_fcode(512);
325 vop->y_chan->type = SHORT_TYPE;
326 vop->u_chan->type = SHORT_TYPE;
327 vop->v_chan->type = SHORT_TYPE;
329 vop->hor_spat_ref = 0;
330 vop->ver_spat_ref = 0;
334 Int get_fcode (Int sr)
336 if (sr<=16) return 1;
337 else if (sr<=32) return 2;
338 else if (sr<=64) return 3;
339 else if (sr<=128) return 4;
340 else if (sr<=256) return 5;
341 else if (sr<=512) return 6;
342 else if (sr<=1024) return 7;
343 else return (-1);
346 int PutVoVolHeader(int vol_width,
347 int vol_height,
348 int time_increment_resolution,
349 float frame_rate)
351 int written = 0;
352 int bits, fixed_vop_time_increment;
354 Bitstream_PutBits(VO_START_CODE_LENGTH, VO_START_CODE);
355 Bitstream_PutBits(5, 0); /* vo_id = 0 */
356 written += VO_START_CODE_LENGTH + 5;
358 Bitstream_PutBits(VOL_START_CODE_LENGTH, VOL_START_CODE);
359 Bitstream_PutBits(4, 0); /* vol_id = 0 */
360 written += VOL_START_CODE_LENGTH + 4;
362 Bitstream_PutBits(1, 0); /* random_accessible_vol = 0 */
363 Bitstream_PutBits(8, 1); /* video_object_type_indication = 1 video */
364 Bitstream_PutBits(1, 1); /* is_object_layer_identifier = 1 */
365 Bitstream_PutBits(4, 2); /* visual_object_layer_ver_id = 2 */
366 Bitstream_PutBits(3, 1); /* visual_object_layer_priority = 1 */
367 written += 1 + 8 + 1 + 4 + 3;
369 Bitstream_PutBits(4, 1); /* aspect_ratio_info = 1 */
377 Bitstream_PutBits(1, 0); /* vol_control_parameter = 0 */
378 Bitstream_PutBits(2, 0); /* vol_shape = 0 rectangular */
379 Bitstream_PutBits(1, 1); /* marker */
380 written += 4 + 1 + 2 + 1;
382 Bitstream_PutBits(16, time_increment_resolution);
383 Bitstream_PutBits(1, 1); /* marker */
384 Bitstream_PutBits(1, 1); /* fixed_vop_rate = 1 */
385 bits = (int)ceil(log((double)time_increment_resolution)/log(2.0));
386 if (bits<1) bits=1;
387 fixed_vop_time_increment = (int)(time_increment_resolution / frame_rate + 0.1);
388 Bitstream_PutBits(bits, fixed_vop_time_increment);
389 Bitstream_PutBits(1, 1); /* marker */
390 written += 16 + 1 + 1 + bits + 1;
392 Bitstream_PutBits(13, vol_width);
393 Bitstream_PutBits(1, 1); /* marker */
394 Bitstream_PutBits(13, vol_height);
395 Bitstream_PutBits(1, 1); /* marker */
396 written += 13 + 1 + 13 + 1;
398 Bitstream_PutBits(1, 0); /* interlaced = 0 */
399 Bitstream_PutBits(1, 1); /* OBMC_disabled = 1 */
400 Bitstream_PutBits(2, 0); /* vol_sprite_usage = 0 */
401 Bitstream_PutBits(1, 0); /* not_8_bit = 0 */
402 written += 1 + 1 + 2 + 1;
404 Bitstream_PutBits(1, 0); /* vol_quant_type = 0 */
405 Bitstream_PutBits(1, 0); /* vol_quarter_pixel = 0 */
406 Bitstream_PutBits(1, 1); /* complexity_estimation_disabled = 1 */
407 Bitstream_PutBits(1, 1); /* resync_marker_disabled = 1 */
408 Bitstream_PutBits(1, 0); /* data_partitioning_enabled = 0 */
409 Bitstream_PutBits(1, 0); /* scalability = 0 */
410 written += 1 + 1 + 1 + 1 + 1 + 1;
412 written += Bitstream_NextStartCode();
414 return(written);
417 int YUV2YUV (int x_dim, int y_dim, void *yuv, void *y_out, void *u_out, void *v_out)
419 // All this conversion does is to turn data from unsigned char to short int,
420 // since legacy MoMuSys uses short int.
421 unsigned char *in;
422 short int *out;
423 long size;
425 in = yuv;
427 out = y_out;
428 size = x_dim * y_dim;
429 while (size --) *(out ++) = *(in ++);
431 out = u_out;
432 size = x_dim * y_dim / 4;
433 while (size --) *(out ++) = *(in ++);
435 out = v_out;
436 size = x_dim * y_dim / 4;
437 while (size --) *(out ++) = *(in ++);
439 return 0;