1 #include "colormodels.h"
2 #include "funcprotos.h"
4 #include "workarounds.h"
12 static pthread_mutex_t encode_mutex;
13 static pthread_mutex_t decode_mutex;
14 static int mutex_initialized = 0;
16 static int delete_codec(quicktime_video_map_t *vtrack)
18 quicktime_divx_codec_t *codec;
20 codec = ((quicktime_codec_t*)vtrack->codec)->priv;
21 if(codec->encode_initialized)
23 pthread_mutex_lock(&encode_mutex);
24 encore(codec->enc_param.handle,
28 pthread_mutex_unlock(&encode_mutex);
30 if(codec->decode_initialized)
32 pthread_mutex_lock(&decode_mutex);
33 decore(codec->dec_param.handle,
37 pthread_mutex_unlock(&decode_mutex);
39 if(codec->temp_frame) free(codec->temp_frame);
40 if(codec->work_buffer) free(codec->work_buffer);
45 static int reads_colormodel(quicktime_t *file,
49 return (colormodel == BC_RGB888 ||
50 colormodel == BC_RGBA8888 ||
51 colormodel == BC_RGB161616 ||
52 colormodel == BC_RGBA16161616 ||
53 colormodel == BC_YUV888 ||
54 colormodel == BC_YUVA8888 ||
55 colormodel == BC_YUV161616 ||
56 colormodel == BC_YUVA16161616 ||
57 colormodel == BC_RGB8 ||
58 colormodel == BC_RGB565 ||
59 colormodel == BC_BGR888 ||
60 colormodel == BC_BGR8888 ||
61 colormodel == BC_YUV420P ||
62 colormodel == BC_YUV422);
65 static int writes_colormodel(quicktime_t *file,
69 return (colormodel == BC_RGB888 ||
70 colormodel == BC_RGBA8888 ||
71 colormodel == BC_RGB161616 ||
72 colormodel == BC_RGBA16161616 ||
73 colormodel == BC_YUV888 ||
74 colormodel == BC_YUVA8888 ||
75 colormodel == BC_YUV161616 ||
76 colormodel == BC_YUVA16161616 ||
77 colormodel == BC_YUV420P ||
78 colormodel == BC_YUV422);
88 static void init_mutex()
90 if(!mutex_initialized)
92 pthread_mutexattr_t attr;
93 mutex_initialized = 1;
94 pthread_mutexattr_init(&attr);
95 pthread_mutex_init(&decode_mutex, &attr);
96 pthread_mutex_init(&encode_mutex, &attr);
104 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
109 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
110 quicktime_trak_t *trak = vtrack->track;
111 quicktime_divx_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
112 int width = trak->tkhd.track_width;
113 int height = trak->tkhd.track_height;
114 int width_i = (int)((float)width / 2 + 0.5) * 2;
115 int height_i = (int)((float)height / 2 + 0.5) * 2;
119 char *bmp_pointers[3];
121 //printf("decode 1\n");
124 pthread_mutex_lock(&decode_mutex);
126 quicktime_set_video_position(file, vtrack->current_position, track);
127 bytes = quicktime_frame_size(file, vtrack->current_position, track);
128 //printf("decode 1\n");
130 if(!codec->work_buffer || codec->buffer_size < bytes)
132 if(codec->work_buffer) free(codec->work_buffer);
133 codec->buffer_size = bytes;
134 codec->work_buffer = calloc(1, codec->buffer_size + 100);
136 //printf("decode 1\n");
138 result = !quicktime_read_data(file, codec->work_buffer, bytes);
139 //printf("decode 1\n");
141 if(!codec->decode_initialized)
143 codec->decode_initialized = 1;
144 codec->dec_param.width = width_i;
145 codec->dec_param.height = height_i;
146 decore(0, DEC_OPT_CREATE, &codec->dec_param, NULL);
151 //printf("decode 1\n");
155 dec_frame.bitstream = codec->work_buffer;
156 dec_frame.length = bytes;
157 dec_frame.stride = width_i;
158 dec_frame.render = 1;
159 dec_frame.colorspace = DEC_CSP_YV12;
161 input_cmodel = BC_YUV420P;
162 if(file->color_model == input_cmodel &&
163 file->out_w == width_i &&
164 file->out_h == height_i &&
167 file->in_w == width_i &&
168 file->in_h == height_i)
170 dec_frame.dst = row_pointers[0];
175 if(!codec->temp_frame)
177 codec->temp_frame = malloc(width_i * height_i * 3 / 2);
179 dec_frame.dst = codec->temp_frame;
184 //printf("decode 1\n");
185 decore(codec->dec_param.handle, DEC_OPT_DECODE, &dec_frame, NULL);
186 //printf("decode 2\n");
189 pthread_mutex_unlock(&decode_mutex);
190 //printf("decode 1 %d %d\n", use_temp, file->color_model);
194 unsigned char **input_rows = malloc(sizeof(unsigned char*) * height_i);
195 for(i = 0; i < height_i; i++)
196 input_rows[i] = (char*)codec->temp_frame + width_i * 3;
197 //printf("decode 3\n");
200 cmodel_transfer(row_pointers, /* Leave NULL if non existent */
202 row_pointers[0], /* Leave NULL if non existent */
205 codec->temp_frame, /* Leave NULL if non existent */
206 codec->temp_frame + width_i * height_i,
207 codec->temp_frame + width_i * height_i + width_i * height_i / 4,
208 file->in_x, /* Dimensions to capture from input frame */
212 0, /* Dimensions to project on output frame */
218 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
219 width_i, /* For planar use the luma rowspan */
222 //printf("decode 4\n");
229 //printf("decode 2\n");
240 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
242 //printf("encode 1\n");
243 longest offset = quicktime_position(file);
244 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
245 quicktime_divx_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
246 quicktime_trak_t *trak = vtrack->track;
247 int width = trak->tkhd.track_width;
248 int height = trak->tkhd.track_height;
249 int width_i = (int)((float)width / 2 + 0.5) * 2;
250 int height_i = (int)((float)height / 2 + 0.5) * 2;
253 ENC_FRAME encore_input;
254 ENC_RESULT encore_result;
255 //printf("encode 1\n");
258 pthread_mutex_lock(&encode_mutex);
260 if(!codec->encode_initialized)
262 codec->encode_initialized = 1;
263 codec->enc_param.x_dim = width_i;
264 codec->enc_param.y_dim = height_i;
265 codec->enc_param.framerate = quicktime_frame_rate(file, track);
266 codec->enc_param.bitrate = codec->bitrate;
267 codec->enc_param.rc_period = codec->rc_period;
268 codec->enc_param.rc_reaction_period = codec->rc_reaction_period;
269 codec->enc_param.rc_reaction_ratio = codec->rc_reaction_ratio;
270 codec->enc_param.max_quantizer = codec->max_quantizer;
271 codec->enc_param.min_quantizer = codec->min_quantizer;
272 codec->enc_param.max_key_interval = codec->max_key_interval;
273 codec->enc_param.use_bidirect = 0;
274 codec->enc_param.deinterlace = 0;
275 codec->enc_param.quality = 5;
276 codec->enc_param.obmc = 0;
280 encore(0, ENC_OPT_INIT, &codec->enc_param, NULL);
283 //printf("encode 1\n");
285 // Assume planes are contiguous
286 if(file->color_model == BC_YUV420P &&
290 encore_input.image = row_pointers[0];
291 //printf("encode 1\n");
293 // Convert to YUV420P
296 //printf("encode 2\n");
297 if(!codec->temp_frame)
299 codec->temp_frame = malloc(width_i * height_i * 3 / 2);
301 //printf("encode 2 %d %d %d %d %d %d\n", file->color_model, width, height, width_i, height_i);
303 cmodel_transfer(0, /* Leave NULL if non existent */
305 codec->temp_frame, /* Leave NULL if non existent */
306 codec->temp_frame + width_i * height_i,
307 codec->temp_frame + width_i * height_i + width_i * height_i / 4,
308 row_pointers[0], /* Leave NULL if non existent */
311 0, /* Dimensions to capture from input frame */
315 0, /* Dimensions to project on output frame */
321 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
322 width, /* For planar use the luma rowspan */
325 //printf("encode 2\n");
327 encore_input.image = codec->temp_frame;
329 //printf("encode 1\n");
331 if(!codec->work_buffer)
333 codec->buffer_size = width * height;
334 codec->work_buffer = malloc(codec->buffer_size);
336 //printf("encode 1\n");
338 encore_input.bitstream = codec->work_buffer;
339 encore_input.length = codec->buffer_size;
340 encore_input.colorspace = ENC_CSP_YV12;
341 encore_input.quant = codec->enc_param.min_quantizer;
343 //printf("encode 1\n");
344 encore(codec->enc_param.handle,
348 pthread_mutex_unlock(&encode_mutex);
349 //printf("encode 1\n");
351 result = !quicktime_write_data(file, codec->work_buffer, encore_input.length);
352 quicktime_update_tables(file,
353 file->vtracks[track].track,
355 file->vtracks[track].current_chunk,
356 file->vtracks[track].current_position,
358 encore_input.length);
359 //printf("encode 1\n");
361 file->vtracks[track].current_chunk++;
362 //printf("encode 2\n");
367 static int set_parameter(quicktime_t *file,
372 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
373 quicktime_divx_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
375 if(!strcasecmp(key, "v_bitrate"))
376 codec->bitrate = *(int*)value;
378 if(!strcasecmp(key, "v_rc_period"))
379 codec->rc_period = *(int*)value;
381 if(!strcasecmp(key, "v_rc_reaction_ratio"))
382 codec->rc_reaction_ratio = *(int*)value;
384 if(!strcasecmp(key, "v_rc_reaction_period"))
385 codec->rc_reaction_period = *(int*)value;
387 if(!strcasecmp(key, "v_max_key_interval"))
388 codec->max_key_interval = *(int*)value;
390 if(!strcasecmp(key, "v_max_quantizer"))
391 codec->max_quantizer = *(int*)value;
393 if(!strcasecmp(key, "v_min_quantizer"))
394 codec->min_quantizer = *(int*)value;
396 if(!strcasecmp(key, "v_search_range"))
397 codec->search_range = *(int*)value;
401 void quicktime_init_codec_divx(quicktime_video_map_t *vtrack)
404 quicktime_divx_codec_t *codec;
406 /* Init public items */
407 ((quicktime_codec_t*)vtrack->codec)->priv = calloc(1, sizeof(quicktime_divx_codec_t));
408 ((quicktime_codec_t*)vtrack->codec)->delete_vcodec = delete_codec;
409 ((quicktime_codec_t*)vtrack->codec)->decode_video = decode;
410 ((quicktime_codec_t*)vtrack->codec)->encode_video = encode;
411 ((quicktime_codec_t*)vtrack->codec)->reads_colormodel = reads_colormodel;
412 ((quicktime_codec_t*)vtrack->codec)->writes_colormodel = writes_colormodel;
413 ((quicktime_codec_t*)vtrack->codec)->set_parameter = set_parameter;