r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / quicktime / divx.c.2
blob7eb852b5e9ba478c1ed8c77b37c648670fadc2ec
1 #include "colormodels.h"
2 #include "funcprotos.h"
3 #include "quicktime.h"
4 #include "workarounds.h"
5 #include "divx.h"
8 #include <stdint.h>
9 #include <stdlib.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)
22         {
23                 pthread_mutex_lock(&encode_mutex);
24                 encore(codec->enc_param.handle,
25                         ENC_OPT_RELEASE,
26                         0,
27                         0);
28                 pthread_mutex_unlock(&encode_mutex);
29         }
30         if(codec->decode_initialized)
31         {
32                 pthread_mutex_lock(&decode_mutex);
33                 decore(codec->dec_param.handle,
34                         DEC_OPT_DESTROY,
35                         0,
36                         0);
37                 pthread_mutex_unlock(&decode_mutex);
38         }
39         if(codec->temp_frame) free(codec->temp_frame);
40         if(codec->work_buffer) free(codec->work_buffer);
41         free(codec);
42         return 0;
45 static int reads_colormodel(quicktime_t *file, 
46                 int colormodel, 
47                 int track)
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, 
66                 int colormodel, 
67                 int track)
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)
91         {
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);
97         }
104 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
106         int i;
107         longest bytes;
108         int result = 0;
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;
116         DEC_FRAME dec_frame;
117         int use_temp = 0;
118         int input_cmodel;
119         char *bmp_pointers[3];
121 //printf("decode 1\n");
123         init_mutex();
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)
131         {
132                 if(codec->work_buffer) free(codec->work_buffer);
133                 codec->buffer_size = bytes;
134                 codec->work_buffer = calloc(1, codec->buffer_size + 100);
135         }
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)
142         {
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);
149         }
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 &&
165                 file->in_x == 0 &&
166                 file->in_y == 0 &&
167                 file->in_w == width_i &&
168                 file->in_h == height_i)
169         {
170                 dec_frame.dst = row_pointers[0];
171                 use_temp = 0;
172         }
173         else
174         {
175                 if(!codec->temp_frame)
176                 {
177                         codec->temp_frame = malloc(width_i * height_i * 3 / 2);
178                 }
179                 dec_frame.dst = codec->temp_frame;
180                 use_temp = 1;
181         }
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);
192         if(use_temp)
193         {
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");
198                 
199                 
200                 cmodel_transfer(row_pointers, /* Leave NULL if non existent */
201                         input_rows,
202                         row_pointers[0], /* Leave NULL if non existent */
203                         row_pointers[1],
204                         row_pointers[2],
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 */
209                         file->in_y, 
210                         file->in_w, 
211                         file->in_h,
212                         0,       /* Dimensions to project on output frame */
213                         0, 
214                         file->out_w, 
215                         file->out_h,
216                         input_cmodel, 
217                         file->color_model,
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 */
220                         width);
221                 
222 //printf("decode 4\n");
223                 free(input_rows);
224         }
229 //printf("decode 2\n");
231         return result;
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;
251         int result = 0;
252         int i;
253         ENC_FRAME encore_input;
254         ENC_RESULT encore_result;
255 //printf("encode 1\n");
257         init_mutex();
258         pthread_mutex_lock(&encode_mutex);
260         if(!codec->encode_initialized)
261         {
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;
277                 
280                 encore(0, ENC_OPT_INIT, &codec->enc_param, NULL);
281         }
283 //printf("encode 1\n");
285 // Assume planes are contiguous
286         if(file->color_model == BC_YUV420P &&
287                 width == width_i &&
288                 height == height_i)
289         {
290                 encore_input.image = row_pointers[0];
291 //printf("encode 1\n");
292         }
293 // Convert to YUV420P
294         else
295         {
296 //printf("encode 2\n");
297                 if(!codec->temp_frame)
298                 {
299                         codec->temp_frame = malloc(width_i * height_i * 3 / 2);
300                 }
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 */
304                         row_pointers,
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 */
309                         row_pointers[1],
310                         row_pointers[2],
311                         0,        /* Dimensions to capture from input frame */
312                         0, 
313                         width, 
314                         height,
315                         0,       /* Dimensions to project on output frame */
316                         0, 
317                         width_i, 
318                         height_i,
319                         file->color_model, 
320                         BC_YUV420P,
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 */
323                         width_i);
324                 
325 //printf("encode 2\n");
326         
327                 encore_input.image = codec->temp_frame;
328         }
329 //printf("encode 1\n");
331         if(!codec->work_buffer)
332         {
333                 codec->buffer_size = width * height;
334                 codec->work_buffer = malloc(codec->buffer_size);
335         }
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, 
345                         ENC_OPT_ENCODE, 
346                         &encore_input,
347                         &encore_result);
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,
354                                                 offset,
355                                                 file->vtracks[track].current_chunk,
356                                                 file->vtracks[track].current_position,
357                                                 1,
358                                                 encore_input.length);
359 //printf("encode 1\n");
361         file->vtracks[track].current_chunk++;
362 //printf("encode 2\n");
364         return result;
367 static int set_parameter(quicktime_t *file, 
368                 int track, 
369                 char *key, 
370                 void *value)
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;
377         else
378         if(!strcasecmp(key, "v_rc_period"))
379                 codec->rc_period = *(int*)value;
380         else
381         if(!strcasecmp(key, "v_rc_reaction_ratio"))
382                 codec->rc_reaction_ratio = *(int*)value;
383         else
384         if(!strcasecmp(key, "v_rc_reaction_period"))
385                 codec->rc_reaction_period = *(int*)value;
386         else
387         if(!strcasecmp(key, "v_max_key_interval"))
388                 codec->max_key_interval = *(int*)value;
389         else
390         if(!strcasecmp(key, "v_max_quantizer"))
391                 codec->max_quantizer = *(int*)value;
392         else
393         if(!strcasecmp(key, "v_min_quantizer"))
394                 codec->min_quantizer = *(int*)value;
395         else
396         if(!strcasecmp(key, "v_search_range"))
397                 codec->search_range = *(int*)value;
401 void quicktime_init_codec_divx(quicktime_video_map_t *vtrack)
403         int i;
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;