2 #include "colormodels.h"
4 #include "funcprotos.h"
6 #include "workarounds.h"
14 static pthread_mutex_t encode_mutex;
15 static pthread_mutex_t decode_mutex;
16 static int mutex_initialized = 0;
17 static int decode_handle = 1;
18 static int encode_handle = 0;
20 static int delete_codec(quicktime_video_map_t *vtrack)
22 quicktime_divx_codec_t *codec;
24 codec = ((quicktime_codec_t*)vtrack->codec)->priv;
25 if(codec->encode_initialized)
27 pthread_mutex_lock(&encode_mutex);
32 pthread_mutex_unlock(&encode_mutex);
34 if(codec->decode_initialized)
36 pthread_mutex_lock(&decode_mutex);
41 pthread_mutex_unlock(&decode_mutex);
43 if(codec->temp_frame) free(codec->temp_frame);
44 if(codec->work_buffer) free(codec->work_buffer);
49 static int reads_colormodel(quicktime_t *file,
53 return (colormodel == BC_RGB888 ||
54 colormodel == BC_RGBA8888 ||
55 colormodel == BC_RGB161616 ||
56 colormodel == BC_RGBA16161616 ||
57 colormodel == BC_YUV888 ||
58 colormodel == BC_YUVA8888 ||
59 colormodel == BC_YUV161616 ||
60 colormodel == BC_YUVA16161616 ||
61 colormodel == BC_RGB8 ||
62 colormodel == BC_RGB565 ||
63 colormodel == BC_BGR888 ||
64 colormodel == BC_BGR8888 ||
65 colormodel == BC_YUV420P ||
66 colormodel == BC_YUV422);
69 static int writes_colormodel(quicktime_t *file,
73 return (colormodel == BC_RGB888 ||
74 colormodel == BC_RGBA8888 ||
75 colormodel == BC_RGB161616 ||
76 colormodel == BC_RGBA16161616 ||
77 colormodel == BC_YUV888 ||
78 colormodel == BC_YUVA8888 ||
79 colormodel == BC_YUV161616 ||
80 colormodel == BC_YUVA16161616 ||
81 colormodel == BC_YUV420P ||
82 colormodel == BC_YUV422);
92 static void init_mutex()
94 if(!mutex_initialized)
96 pthread_mutexattr_t attr;
97 mutex_initialized = 1;
98 pthread_mutexattr_init(&attr);
99 pthread_mutex_init(&decode_mutex, &attr);
100 pthread_mutex_init(&encode_mutex, &attr);
108 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
113 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
114 quicktime_trak_t *trak = vtrack->track;
115 quicktime_divx_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
116 int width = trak->tkhd.track_width;
117 int height = trak->tkhd.track_height;
118 int width_i = (int)((float)width / 2 + 0.5) * 2;
119 int height_i = (int)((float)height / 2 + 0.5) * 2;
123 char *bmp_pointers[3];
125 //printf("decode 1\n");
128 pthread_mutex_lock(&decode_mutex);
130 quicktime_set_video_position(file, vtrack->current_position, track);
131 bytes = quicktime_frame_size(file, vtrack->current_position, track);
132 //printf("decode 1\n");
134 if(!codec->work_buffer || codec->buffer_size < bytes)
136 if(codec->work_buffer) free(codec->work_buffer);
137 codec->buffer_size = bytes;
138 codec->work_buffer = calloc(1, codec->buffer_size + 100);
140 //printf("decode 1\n");
142 result = !quicktime_read_data(file, codec->work_buffer, bytes);
143 //printf("decode 1\n");
145 if(!codec->decode_initialized)
147 DEC_MEM_REQS dec_mem_reqs;
149 codec->decode_initialized = 1;
150 // decore requires handle to be > 1
151 codec->handle = decode_handle++;
152 codec->dec_param.x_dim = width_i;
153 codec->dec_param.y_dim = height_i;
154 codec->dec_param.output_format = DEC_420;
155 codec->dec_param.time_incr = 0;
157 decore(codec->handle, DEC_OPT_MEMORY_REQS, &codec->dec_param, &dec_mem_reqs);
158 codec->dec_param.buffers.mp4_edged_ref_buffers = calloc(1, dec_mem_reqs.mp4_edged_ref_buffers_size);
159 codec->dec_param.buffers.mp4_edged_for_buffers = calloc(1, dec_mem_reqs.mp4_edged_for_buffers_size);
160 codec->dec_param.buffers.mp4_display_buffers = calloc(1, dec_mem_reqs.mp4_display_buffers_size);
161 codec->dec_param.buffers.mp4_state = calloc(1, dec_mem_reqs.mp4_state_size);
162 codec->dec_param.buffers.mp4_tables = calloc(1, dec_mem_reqs.mp4_tables_size);
163 codec->dec_param.buffers.mp4_stream = calloc(1, dec_mem_reqs.mp4_stream_size);
164 decore(codec->handle, DEC_OPT_INIT, &codec->dec_param, NULL);
171 //printf("decode 1\n");
175 dec_frame.bitstream = codec->work_buffer;
176 dec_frame.length = bytes;
177 dec_frame.render_flag = 1;
179 dec_frame.stride = width_i;
181 input_cmodel = BC_YUV420P;
182 if(file->color_model == input_cmodel &&
183 file->out_w == width_i &&
184 file->out_h == height_i &&
187 file->in_w == width_i &&
188 file->in_h == height_i)
190 dec_frame.bmp = row_pointers[0];
195 if(!codec->temp_frame)
197 codec->temp_frame = malloc(width_i * height_i * 3 / 2);
199 dec_frame.bmp = codec->temp_frame;
204 //printf("decode 1\n");
205 decore(codec->handle, 0, &dec_frame, NULL);
206 //printf("decode 2\n");
209 pthread_mutex_unlock(&decode_mutex);
210 //printf("decode 1 %d %d\n", use_temp, file->color_model);
214 unsigned char **input_rows = malloc(sizeof(unsigned char*) * height_i);
215 for(i = 0; i < height_i; i++)
216 input_rows[i] = codec->temp_frame + width_i * 3;
219 cmodel_transfer(row_pointers, /* Leave NULL if non existent */
221 row_pointers[0], /* Leave NULL if non existent */
224 codec->temp_frame, /* Leave NULL if non existent */
225 codec->temp_frame + width_i * height_i,
226 codec->temp_frame + width_i * height_i + width_i * height_i / 4,
227 file->in_x, /* Dimensions to capture from input frame */
231 0, /* Dimensions to project on output frame */
237 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
238 width_i, /* For planar use the luma rowspan */
247 //printf("decode 2\n");
258 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
260 //printf("encode 1\n");
261 longest offset = quicktime_position(file);
262 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
263 quicktime_divx_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
264 quicktime_trak_t *trak = vtrack->track;
265 int width = trak->tkhd.track_width;
266 int height = trak->tkhd.track_height;
267 int width_i = (int)((float)width / 2 + 0.5) * 2;
268 int height_i = (int)((float)height / 2 + 0.5) * 2;
271 ENC_FRAME encore_input;
272 ENC_RESULT encore_result;
273 //printf("encode 1\n");
276 pthread_mutex_lock(&encode_mutex);
278 if(!codec->encode_initialized)
282 codec->encode_initialized = 1;
283 codec->handle = encode_handle++;
284 enc_param.framerate = quicktime_frame_rate(file, track);
285 enc_param.bitrate = codec->bitrate;
286 enc_param.rc_period = codec->rc_period;
287 enc_param.rc_reaction_period = codec->rc_reaction_period;
288 enc_param.rc_reaction_ratio = codec->rc_reaction_ratio;
289 enc_param.x_dim = width_i;
290 enc_param.y_dim = height_i;
291 enc_param.max_key_interval = codec->max_key_interval;
292 enc_param.search_range = codec->search_range;
293 enc_param.max_quantizer = codec->max_quantizer;
294 enc_param.min_quantizer = codec->min_quantizer;
296 encore(track, ENC_OPT_INIT, &enc_param, NULL);
299 //printf("encode 1\n");
301 // Assume planes are contiguous
302 if(file->color_model == BC_YUV420P &&
306 encore_input.image = row_pointers[0];
307 //printf("encode 1\n");
309 // Convert to YUV420P
312 //printf("encode 2\n");
313 if(!codec->temp_frame)
315 codec->temp_frame = malloc(width_i * height_i * 3 / 2);
317 //printf("encode 2 %d %d %d %d %d %d\n", file->color_model, width, height, width_i, height_i);
319 cmodel_transfer(0, /* Leave NULL if non existent */
321 codec->temp_frame, /* Leave NULL if non existent */
322 codec->temp_frame + width_i * height_i,
323 codec->temp_frame + width_i * height_i + width_i * height_i / 4,
324 row_pointers[0], /* Leave NULL if non existent */
327 0, /* Dimensions to capture from input frame */
331 0, /* Dimensions to project on output frame */
337 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
338 width, /* For planar use the luma rowspan */
341 //printf("encode 2\n");
343 encore_input.image = codec->temp_frame;
345 //printf("encode 1\n");
347 if(!codec->work_buffer)
349 codec->buffer_size = width * height;
350 codec->work_buffer = malloc(codec->buffer_size);
352 //printf("encode 1\n");
354 encore_input.bitstream = codec->work_buffer;
355 encore_input.length = codec->buffer_size;
357 //printf("encode 1\n");
358 encore(codec->handle,
362 pthread_mutex_unlock(&encode_mutex);
363 //printf("encode 1\n");
365 result = !quicktime_write_data(file, codec->work_buffer, encore_input.length);
366 quicktime_update_tables(file,
367 file->vtracks[track].track,
369 file->vtracks[track].current_chunk,
370 file->vtracks[track].current_position,
372 encore_input.length);
373 //printf("encode 1\n");
375 file->vtracks[track].current_chunk++;
376 //printf("encode 2\n");
381 static int set_parameter(quicktime_t *file,
386 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
387 quicktime_divx_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
389 if(!strcasecmp(key, "v_bitrate"))
390 codec->bitrate = *(int*)value;
392 if(!strcasecmp(key, "v_rc_period"))
393 codec->rc_period = *(int*)value;
395 if(!strcasecmp(key, "v_rc_reaction_ratio"))
396 codec->rc_reaction_ratio = *(int*)value;
398 if(!strcasecmp(key, "v_rc_reaction_period"))
399 codec->rc_reaction_period = *(int*)value;
401 if(!strcasecmp(key, "v_max_key_interval"))
402 codec->max_key_interval = *(int*)value;
404 if(!strcasecmp(key, "v_max_quantizer"))
405 codec->max_quantizer = *(int*)value;
407 if(!strcasecmp(key, "v_min_quantizer"))
408 codec->min_quantizer = *(int*)value;
410 if(!strcasecmp(key, "v_search_range"))
411 codec->search_range = *(int*)value;
415 void quicktime_init_codec_divx(quicktime_video_map_t *vtrack)
418 quicktime_divx_codec_t *codec;
420 /* Init public items */
421 ((quicktime_codec_t*)vtrack->codec)->priv = calloc(1, sizeof(quicktime_divx_codec_t));
422 ((quicktime_codec_t*)vtrack->codec)->delete_vcodec = delete_codec;
423 ((quicktime_codec_t*)vtrack->codec)->decode_video = decode;
424 ((quicktime_codec_t*)vtrack->codec)->encode_video = encode;
425 ((quicktime_codec_t*)vtrack->codec)->reads_colormodel = reads_colormodel;
426 ((quicktime_codec_t*)vtrack->codec)->writes_colormodel = writes_colormodel;
427 ((quicktime_codec_t*)vtrack->codec)->set_parameter = set_parameter;