r198: This commit was generated by cvs2svn to compensate for changes in r197,
[cinelerra_cv.git] / quicktime / divx.c.50
blob9e5f479250f8483ba05dd87623f4d55636557ae8
2 #include "colormodels.h"
3 #include ENCORE_DIR
4 #include "funcprotos.h"
5 #include "quicktime.h"
6 #include "workarounds.h"
7 #include "divx.h"
10 #include <stdint.h>
11 #include <stdlib.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)
26         {
27                 pthread_mutex_lock(&encode_mutex);
28                 encore(codec->handle,
29                         ENC_OPT_RELEASE,
30                         0,
31                         0);
32                 pthread_mutex_unlock(&encode_mutex);
33         }
34         if(codec->decode_initialized)
35         {
36                 pthread_mutex_lock(&decode_mutex);
37                 decore(codec->handle,
38                         DEC_OPT_RELEASE,
39                         0,
40                         0);
41                 pthread_mutex_unlock(&decode_mutex);
42         }
43         if(codec->temp_frame) free(codec->temp_frame);
44         if(codec->work_buffer) free(codec->work_buffer);
45         free(codec);
46         return 0;
49 static int reads_colormodel(quicktime_t *file, 
50                 int colormodel, 
51                 int track)
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, 
70                 int colormodel, 
71                 int track)
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)
95         {
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);
101         }
108 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
110         int i;
111         longest bytes;
112         int result = 0;
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;
120         DEC_FRAME dec_frame;
121         int use_temp = 0;
122         int input_cmodel;
123         char *bmp_pointers[3];
125 //printf("decode 1\n");
127         init_mutex();
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)
135         {
136                 if(codec->work_buffer) free(codec->work_buffer);
137                 codec->buffer_size = bytes;
138                 codec->work_buffer = calloc(1, codec->buffer_size + 100);
139         }
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)
146         {
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;
156                 
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);
169         }
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 &&
185                 file->in_x == 0 &&
186                 file->in_y == 0 &&
187                 file->in_w == width_i &&
188                 file->in_h == height_i)
189         {
190                 dec_frame.bmp = row_pointers[0];
191                 use_temp = 0;
192         }
193         else
194         {
195                 if(!codec->temp_frame)
196                 {
197                         codec->temp_frame = malloc(width_i * height_i * 3 / 2);
198                 }
199                 dec_frame.bmp = codec->temp_frame;
200                 use_temp = 1;
201         }
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);
212         if(use_temp)
213         {
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;
217                 
218                 
219                 cmodel_transfer(row_pointers, /* Leave NULL if non existent */
220                         input_rows,
221                         row_pointers[0], /* Leave NULL if non existent */
222                         row_pointers[1],
223                         row_pointers[2],
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 */
228                         file->in_y, 
229                         file->in_w, 
230                         file->in_h,
231                         0,       /* Dimensions to project on output frame */
232                         0, 
233                         file->out_w, 
234                         file->out_h,
235                         input_cmodel, 
236                         file->color_model,
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 */
239                         width);
240                 
241                 free(input_rows);
242         }
247 //printf("decode 2\n");
249         return result;
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;
269         int result = 0;
270         int i;
271         ENC_FRAME encore_input;
272         ENC_RESULT encore_result;
273 //printf("encode 1\n");
275         init_mutex();
276         pthread_mutex_lock(&encode_mutex);
278         if(!codec->encode_initialized)
279         {
280                 ENC_PARAM enc_param;
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);
297         }
299 //printf("encode 1\n");
301 // Assume planes are contiguous
302         if(file->color_model == BC_YUV420P &&
303                 width == width_i &&
304                 height == height_i)
305         {
306                 encore_input.image = row_pointers[0];
307 //printf("encode 1\n");
308         }
309 // Convert to YUV420P
310         else
311         {
312 //printf("encode 2\n");
313                 if(!codec->temp_frame)
314                 {
315                         codec->temp_frame = malloc(width_i * height_i * 3 / 2);
316                 }
317 //printf("encode 2 %d %d %d %d %d %d\n", file->color_model, width, height, width_i, height_i);
318                 
319                 cmodel_transfer(0, /* Leave NULL if non existent */
320                         row_pointers,
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 */
325                         row_pointers[1],
326                         row_pointers[2],
327                         0,        /* Dimensions to capture from input frame */
328                         0, 
329                         width, 
330                         height,
331                         0,       /* Dimensions to project on output frame */
332                         0, 
333                         width_i, 
334                         height_i,
335                         file->color_model, 
336                         BC_YUV420P,
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 */
339                         width_i);
340                 
341 //printf("encode 2\n");
342         
343                 encore_input.image = codec->temp_frame;
344         }
345 //printf("encode 1\n");
347         if(!codec->work_buffer)
348         {
349                 codec->buffer_size = width * height;
350                 codec->work_buffer = malloc(codec->buffer_size);
351         }
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,   
359                         0,      
360                         &encore_input,
361                         &encore_result);
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,
368                                                 offset,
369                                                 file->vtracks[track].current_chunk,
370                                                 file->vtracks[track].current_position,
371                                                 1,
372                                                 encore_input.length);
373 //printf("encode 1\n");
375         file->vtracks[track].current_chunk++;
376 //printf("encode 2\n");
378         return result;
381 static int set_parameter(quicktime_t *file, 
382                 int track, 
383                 char *key, 
384                 void *value)
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;
391         else
392         if(!strcasecmp(key, "v_rc_period"))
393                 codec->rc_period = *(int*)value;
394         else
395         if(!strcasecmp(key, "v_rc_reaction_ratio"))
396                 codec->rc_reaction_ratio = *(int*)value;
397         else
398         if(!strcasecmp(key, "v_rc_reaction_period"))
399                 codec->rc_reaction_period = *(int*)value;
400         else
401         if(!strcasecmp(key, "v_max_key_interval"))
402                 codec->max_key_interval = *(int*)value;
403         else
404         if(!strcasecmp(key, "v_max_quantizer"))
405                 codec->max_quantizer = *(int*)value;
406         else
407         if(!strcasecmp(key, "v_min_quantizer"))
408                 codec->min_quantizer = *(int*)value;
409         else
410         if(!strcasecmp(key, "v_search_range"))
411                 codec->search_range = *(int*)value;
415 void quicktime_init_codec_divx(quicktime_video_map_t *vtrack)
417         int i;
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;