r499: This commit was manufactured by cvs2svn to create tag 'r1_2_1-last'.
[cinelerra_cv/mob.git] / hvirtual / quicktime / divx.c
blob86a896519dc4e3f137739346e1be19d7b199168e
1 // Divx for encore50
4 #include "colormodels.h"
5 #include "funcprotos.h"
6 #include "quicktime.h"
7 #include "workarounds.h"
8 #include "encore50/encore.h"
9 #include "decore50/decore.h"
11 #include <pthread.h>
12 #include <stdint.h>
13 #include <stdlib.h>
16 typedef struct
18 #define FIELDS 2
19 unsigned char *work_buffer;
20 char *temp_frame;
21 long buffer_size;
22 int decode_initialized[FIELDS];
23 int encode_initialized[FIELDS];
24 // For heroine 60 encoding, we want different streams for each field.
25 int total_fields;
26 int bitrate;
27 long rc_period; // the intended rate control averaging period
28 long rc_reaction_period; // the reation period for rate control
29 long rc_reaction_ratio; // the ratio for down/up rate control
30 long max_key_interval; // the maximum interval between key frames
31 int max_quantizer; // the upper limit of the quantizer
32 int min_quantizer; // the lower limit of the quantizer
33 int quantizer; // For vbr
34 int quality; // the forward search range for motion estimation
35 int fix_bitrate;
36 int use_deblocking;
38 // Last frame decoded
39 long last_frame[FIELDS];
40 int encode_handle[FIELDS];
42 DEC_PARAM dec_param[FIELDS];
43 ENC_PARAM enc_param[FIELDS];
45 int decode_handle[FIELDS];
46 // Must count pframes in VBR
47 int p_count[FIELDS];
48 } quicktime_divx_codec_t;
50 static pthread_mutex_t encode_mutex;
51 static pthread_mutex_t decode_mutex;
52 static int mutex_initialized = 0;
53 static int decode_handle = 1;
54 static int encode_handle = 0;
56 static int delete_codec(quicktime_video_map_t *vtrack)
58 quicktime_divx_codec_t *codec;
59 int i;
60 //printf("delete_codec 1\n");
63 codec = ((quicktime_codec_t*)vtrack->codec)->priv;
64 for(i = 0; i < codec->total_fields; i++)
66 if(codec->encode_initialized[i])
68 pthread_mutex_lock(&encode_mutex);
69 encore(codec->encode_handle[i],
70 ENC_OPT_RELEASE,
72 0);
73 pthread_mutex_unlock(&encode_mutex);
76 if(codec->decode_initialized[i])
78 pthread_mutex_lock(&decode_mutex);
80 decore_set_global(&codec->dec_param[i]);
81 decore(codec->decode_handle[i],
82 DEC_OPT_RELEASE,
84 0);
86 free(codec->dec_param[i].buffers.mp4_edged_ref_buffers);
87 free(codec->dec_param[i].buffers.mp4_edged_for_buffers);
88 free(codec->dec_param[i].buffers.mp4_display_buffers);
89 free(codec->dec_param[i].buffers.mp4_state);
90 free(codec->dec_param[i].buffers.mp4_tables);
91 free(codec->dec_param[i].buffers.mp4_stream);
93 pthread_mutex_unlock(&decode_mutex);
96 pthread_mutex_unlock(&decode_mutex);
99 if(codec->temp_frame) free(codec->temp_frame);
100 if(codec->work_buffer) free(codec->work_buffer);
103 free(codec);
104 //printf("delete_codec 100\n");
105 return 0;
108 static int reads_colormodel(quicktime_t *file,
109 int colormodel,
110 int track)
112 return (colormodel == BC_YUV420P);
115 static int writes_colormodel(quicktime_t *file,
116 int colormodel,
117 int track)
119 return (colormodel == BC_RGB888 ||
120 colormodel == BC_RGBA8888 ||
121 colormodel == BC_RGB161616 ||
122 colormodel == BC_RGBA16161616 ||
123 colormodel == BC_YUV888 ||
124 colormodel == BC_YUVA8888 ||
125 colormodel == BC_YUV161616 ||
126 colormodel == BC_YUVA16161616 ||
127 colormodel == BC_YUV420P ||
128 colormodel == BC_YUV422 ||
129 colormodel == BC_COMPRESSED);
139 static void init_mutex()
141 if(!mutex_initialized)
143 pthread_mutexattr_t attr;
144 mutex_initialized = 1;
145 pthread_mutexattr_init(&attr);
146 pthread_mutex_init(&decode_mutex, &attr);
147 pthread_mutex_init(&encode_mutex, &attr);
154 // Determine of the compressed frame is a keyframe for direct copy
155 int quicktime_divx_is_key(unsigned char *data, long size)
157 int result = 0;
158 int i;
160 for(i = 0; i < size - 5; i++)
162 if( data[i] == 0x00 &&
163 data[i + 1] == 0x00 &&
164 data[i + 2] == 0x01 &&
165 data[i + 3] == 0xb6)
167 if((data[i + 4] & 0xc0) == 0x0)
168 return 1;
169 else
170 return 0;
174 return result;
178 // Test for VOL header in frame
179 int quicktime_divx_has_vol(unsigned char *data)
181 if( data[0] == 0x00 &&
182 data[1] == 0x00 &&
183 data[2] == 0x01 &&
184 data[3] == 0x00 &&
185 data[4] == 0x00 &&
186 data[5] == 0x00 &&
187 data[6] == 0x01 &&
188 data[7] == 0x20)
189 return 1;
190 else
191 return 0;
197 static void putbits(unsigned char **data,
198 int *bit_pos,
199 uint64_t *bit_store,
200 int *total,
201 int count,
202 uint64_t value)
204 value &= 0xffffffffffffffff >> (64 - count);
206 while(64 - *bit_pos < count)
208 *(*data)++ = (*bit_store) >> 56;
209 (*bit_store) <<= 8;
210 (*bit_pos) -= 8;
213 (*bit_store) |= value << (64 - count - *bit_pos);
214 (*bit_pos) += count;
215 (*total) += count;
219 static void flushbits(unsigned char **data,
220 int *bit_pos,
221 uint64_t *bit_store)
223 //printf("flushbits %llx\n", (*bit_store));
224 while((*bit_pos) > 0)
226 *(*data)++ = (*bit_store) >> 56;
227 (*bit_store) <<= 8;
228 (*bit_pos) -= 8;
235 #define VO_START_CODE 0x8
236 #define VO_START_CODE_LENGTH 27
237 #define VOL_START_CODE 0x12 /* 25-MAR-97 JDL : according to WD2 */
238 #define VOL_START_CODE_LENGTH 28
242 int quicktime_divx_write_vol(unsigned char *data_start,
243 int vol_width,
244 int vol_height,
245 int time_increment_resolution,
246 double frame_rate)
248 int written = 0;
249 int bits, fixed_vop_time_increment;
250 unsigned char *data = data_start;
251 int bit_pos;
252 uint64_t bit_store;
253 int i, j;
255 bit_store = 0;
256 bit_pos = 0;
257 vol_width = (int)((float)vol_width / 16 + 0.5) * 16;
258 vol_height = (int)((float)vol_height / 16 + 0.5) * 16;
261 putbits(&data,
262 &bit_pos,
263 &bit_store,
264 &written,
265 VO_START_CODE_LENGTH, VO_START_CODE);
266 putbits(&data,
267 &bit_pos,
268 &bit_store,
269 &written,
270 5, 0); /* vo_id = 0 */
272 putbits(&data,
273 &bit_pos,
274 &bit_store,
275 &written,
276 VOL_START_CODE_LENGTH, VOL_START_CODE);
281 putbits(&data,
282 &bit_pos,
283 &bit_store,
284 &written,
285 4, 0); /* vol_id = 0 */
287 putbits(&data,
288 &bit_pos,
289 &bit_store,
290 &written,
291 1, 0); /* random_accessible_vol = 0 */
292 putbits(&data,
293 &bit_pos,
294 &bit_store,
295 &written,
296 8, 1); /* video_object_type_indication = 1 video */
297 putbits(&data,
298 &bit_pos,
299 &bit_store,
300 &written,
301 1, 1); /* is_object_layer_identifier = 1 */
302 putbits(&data,
303 &bit_pos,
304 &bit_store,
305 &written,
306 4, 2); /* visual_object_layer_ver_id = 2 */
307 putbits(&data,
308 &bit_pos,
309 &bit_store,
310 &written,
311 3, 1); /* visual_object_layer_priority = 1 */
312 putbits(&data,
313 &bit_pos,
314 &bit_store,
315 &written,
316 4, 1); /* aspect_ratio_info = 1 */
324 putbits(&data,
325 &bit_pos,
326 &bit_store,
327 &written,
328 1, 0); /* vol_control_parameter = 0 */
329 putbits(&data,
330 &bit_pos,
331 &bit_store,
332 &written,
333 2, 0); /* vol_shape = 0 rectangular */
334 putbits(&data,
335 &bit_pos,
336 &bit_store,
337 &written,
338 1, 1); /* marker */
346 putbits(&data,
347 &bit_pos,
348 &bit_store,
349 &written,
350 16, time_increment_resolution);
351 putbits(&data,
352 &bit_pos,
353 &bit_store,
354 &written,
355 1, 1); /* marker */
356 putbits(&data,
357 &bit_pos,
358 &bit_store,
359 &written,
360 1, 1); /* fixed_vop_rate = 1 */
363 bits = 1;
364 while((1 << bits) < time_increment_resolution) bits++;
366 // Log calculation fails for some reason
367 // bits = (int)ceil(log((double)time_increment_resolution) / log(2.0));
368 // if (bits < 1) bits=1;
370 fixed_vop_time_increment =
371 (int)(time_increment_resolution / frame_rate + 0.1);
373 putbits(&data,
374 &bit_pos,
375 &bit_store,
376 &written,
377 bits, fixed_vop_time_increment);
379 putbits(&data,
380 &bit_pos,
381 &bit_store,
382 &written,
383 1, 1); /* marker */
385 putbits(&data,
386 &bit_pos,
387 &bit_store,
388 &written,
389 13, vol_width);
390 putbits(&data,
391 &bit_pos,
392 &bit_store,
393 &written,
394 1, 1); /* marker */
395 putbits(&data,
396 &bit_pos,
397 &bit_store,
398 &written,
399 13, vol_height);
400 putbits(&data,
401 &bit_pos,
402 &bit_store,
403 &written,
404 1, 1); /* marker */
406 putbits(&data,
407 &bit_pos,
408 &bit_store,
409 &written,
410 1, 0); /* interlaced = 0 */
411 putbits(&data,
412 &bit_pos,
413 &bit_store,
414 &written,
415 1, 1); /* OBMC_disabled = 1 */
416 putbits(&data,
417 &bit_pos,
418 &bit_store,
419 &written,
420 2, 0); /* vol_sprite_usage = 0 */
421 putbits(&data,
422 &bit_pos,
423 &bit_store,
424 &written,
425 1, 0); /* not_8_bit = 0 */
427 putbits(&data,
428 &bit_pos,
429 &bit_store,
430 &written,
431 1, 0); /* vol_quant_type = 0 */
432 putbits(&data,
433 &bit_pos,
434 &bit_store,
435 &written,
436 1, 0); /* vol_quarter_pixel = 0 */
437 putbits(&data,
438 &bit_pos,
439 &bit_store,
440 &written,
441 1, 1); /* complexity_estimation_disabled = 1 */
442 putbits(&data,
443 &bit_pos,
444 &bit_store,
445 &written,
446 1, 1); /* resync_marker_disabled = 1 */
447 putbits(&data,
448 &bit_pos,
449 &bit_store,
450 &written,
451 1, 0); /* data_partitioning_enabled = 0 */
452 putbits(&data,
453 &bit_pos,
454 &bit_store,
455 &written,
456 1, 0); /* scalability = 0 */
458 flushbits(&data,
459 &bit_pos,
460 &bit_store);
465 * for(i = 0; i < data - data_start; i++)
466 * for(j = 0x80; j >= 1; j /= 2)
467 * printf("%d", (data_start[i] & j) ? 1 : 0);
468 * printf("\n");
473 return data - data_start;
480 #define READ_RAW(framenum) \
482 quicktime_set_video_position(file, framenum, track); \
483 bytes = quicktime_frame_size(file, framenum, track); \
484 if(!codec->work_buffer || codec->buffer_size < bytes) \
486 if(codec->work_buffer) free(codec->work_buffer); \
487 codec->buffer_size = bytes; \
488 codec->work_buffer = calloc(1, codec->buffer_size + 100); \
490 result = !quicktime_read_data(file, codec->work_buffer, bytes); \
497 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
499 int i;
500 longest bytes;
501 int result = 0;
502 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
503 quicktime_trak_t *trak = vtrack->track;
504 quicktime_divx_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
505 int width = trak->tkhd.track_width;
506 int height = trak->tkhd.track_height;
507 int width_i = (int)((float)width / 16 + 0.5) * 16;
508 int height_i = (int)((float)height / 16 + 0.5) * 16;
509 DEC_FRAME dec_frame;
510 int use_temp = 0;
511 int input_cmodel;
512 char *bmp_pointers[3];
513 long temp_position;
514 int current_field = vtrack->current_position % codec->total_fields;
518 init_mutex();
519 pthread_mutex_lock(&decode_mutex);
527 * printf("decode 1 %d %d %d\n",
528 * vtrack->current_position,
529 * current_field,
530 * codec->decode_initialized[current_field]);
537 if(!codec->decode_initialized[current_field])
539 DEC_MEM_REQS dec_mem_reqs;
542 if(!codec->temp_frame)
543 codec->temp_frame = malloc(width_i * height_i * 3 / 2);
545 // decore requires handle to be > 1
546 codec->decode_handle[current_field] = decode_handle++;
547 codec->last_frame[current_field] = -1;
548 codec->dec_param[current_field].x_dim = width_i;
549 codec->dec_param[current_field].y_dim = height_i;
550 codec->dec_param[current_field].output_format = DEC_420;
551 codec->dec_param[current_field].time_incr = 0;
553 decore(codec->decode_handle[current_field],
554 DEC_OPT_MEMORY_REQS,
555 &codec->dec_param[current_field],
556 &dec_mem_reqs);
557 codec->dec_param[current_field].buffers.mp4_edged_ref_buffers =
558 calloc(1, dec_mem_reqs.mp4_edged_ref_buffers_size);
559 codec->dec_param[current_field].buffers.mp4_edged_for_buffers =
560 calloc(1, dec_mem_reqs.mp4_edged_for_buffers_size);
561 codec->dec_param[current_field].buffers.mp4_display_buffers =
562 calloc(1, dec_mem_reqs.mp4_display_buffers_size);
563 codec->dec_param[current_field].buffers.mp4_state =
564 calloc(1, dec_mem_reqs.mp4_state_size);
565 codec->dec_param[current_field].buffers.mp4_tables =
566 calloc(1, dec_mem_reqs.mp4_tables_size);
567 codec->dec_param[current_field].buffers.mp4_stream =
568 calloc(1, dec_mem_reqs.mp4_stream_size);
569 //printf("decode 2\n");
570 decore(codec->decode_handle[current_field],
571 DEC_OPT_INIT,
572 &codec->dec_param[current_field],
573 NULL);
575 //printf("decode 3\n");
579 // Must decode frame with VOL header first but only the first frame in the
580 // field sequence has a VOL header.
581 temp_position = vtrack->current_position;
582 READ_RAW(current_field);
583 vtrack->current_position = temp_position;
584 dec_frame.bitstream = codec->work_buffer;
585 dec_frame.length = bytes;
586 dec_frame.stride = width_i;
587 dec_frame.render_flag = 0;
588 dec_frame.bmp[0] = codec->temp_frame;
589 dec_frame.bmp[1] = codec->temp_frame + width_i * height_i;
590 dec_frame.bmp[2] = codec->temp_frame + width_i * height_i * 5 / 4;
591 decore(codec->decode_handle[current_field], 0, &dec_frame, NULL);
594 //printf("decode 9\n");
596 codec->decode_initialized[current_field] = 1;
597 decore_save_global(&codec->dec_param[current_field]);
599 //printf("decode 10\n");
601 decore_set_global(&codec->dec_param[current_field]);
603 // Enable deblocking. This doesn't make much difference at high bitrates.
604 DEC_SET dec_set_arg;
605 dec_set_arg.postproc_level = (codec->use_deblocking ? 100 : 0);
606 decore(codec->decode_handle[current_field],
607 DEC_OPT_SETPP,
608 &dec_set_arg,
609 NULL);
610 //printf("decode 30\n");
614 input_cmodel = BC_YUV420P;
616 // Decode directly into return values
617 if(file->color_model == input_cmodel &&
618 file->out_w == width_i &&
619 file->out_h == height_i &&
620 file->in_x == 0 &&
621 file->in_y == 0 &&
622 file->in_w == width_i &&
623 file->in_h == height_i)
625 // dec_frame.dst = row_pointers[0];
626 dec_frame.bmp[0] = row_pointers[0];
627 dec_frame.bmp[1] = row_pointers[1];
628 dec_frame.bmp[2] = row_pointers[2];
629 use_temp = 0;
631 else
632 // Decode into temporaries
634 dec_frame.bmp[0] = codec->temp_frame;
635 dec_frame.bmp[1] = codec->temp_frame + width_i * height_i;
636 dec_frame.bmp[2] = codec->temp_frame + width_i * height_i * 5 / 4;
637 use_temp = 1;
640 //printf("decode 40\n");
641 dec_frame.stride = width_i;
654 //printf("decode 1 %d %d\n", codec->last_frame, vtrack->current_position);
656 if(quicktime_has_keyframes(file, track) &&
657 vtrack->current_position !=
658 codec->last_frame[current_field] + codec->total_fields)
660 int frame1, frame2 = vtrack->current_position, current_frame = frame2;
662 // Get first keyframe of same field
665 frame1 = quicktime_get_keyframe_before(file,
666 current_frame--,
667 track);
668 }while(frame1 > 0 && (frame1 % codec->total_fields) != current_field);
671 // Keyframe is before last decoded frame and current frame is after last decoded
672 // frame, so instead of rerendering from the last keyframe we can rerender from
673 // the last decoded frame.
674 if(frame1 < codec->last_frame[current_field] &&
675 frame2 > codec->last_frame[current_field])
676 frame1 = codec->last_frame[current_field] + codec->total_fields;
678 // Render up to current position
679 while(frame1 < frame2)
681 READ_RAW(frame1);
683 dec_frame.bitstream = codec->work_buffer;
684 dec_frame.length = bytes;
685 dec_frame.render_flag = 0;
686 decore(codec->decode_handle[current_field],
688 &dec_frame,
689 NULL);
690 frame1 += codec->total_fields;
694 vtrack->current_position = frame2;
701 //printf("decode 50\n");
711 codec->last_frame[current_field] = vtrack->current_position;
712 //printf("decode 1\n");
715 READ_RAW(vtrack->current_position);
719 //printf("decode 6\n");
722 dec_frame.bitstream = codec->work_buffer;
723 dec_frame.length = bytes;
724 dec_frame.render_flag = 1;
726 //printf("decode 60\n");
727 decore(codec->decode_handle[current_field], 0, &dec_frame, NULL);
728 //printf("decode 100\n");
732 // Now line average the Y buffer, doubling its height
733 // while keeping the UV buffers the same.
735 * if(codec->total_fields == 2)
737 * unsigned char *bitmap = dec_frame.bmp[0];
738 * unsigned char *in_row1 = bitmap + width_i * height_i / 2 - width_i * 2;
739 * unsigned char *in_row2 = in_row1 + width_i;
740 * unsigned char *out_row1 = bitmap + width_i * height_i - width_i * 2;
741 * unsigned char *out_row2 = out_row1 + width_i;
743 * while(in_row1 >= bitmap)
745 * unsigned char *in_ptr1 = in_row1;
746 * unsigned char *in_ptr2 = in_row2;
747 * unsigned char *out_ptr1 = out_row1;
748 * unsigned char *out_ptr2 = out_row2;
749 * if(current_field == 0)
750 * for(i = 0; i < width_i; i++)
752 * *out_ptr1++ = ((int64_t)*in_ptr1 + (int64_t)*in_ptr2) >> 1;
753 * *out_ptr2++ = *in_ptr2;
754 * in_ptr1++;
755 * in_ptr2++;
757 * else
758 * for(i = 0; i < width_i; i++)
760 * *out_ptr1++ = *in_ptr1;
761 * *out_ptr2++ = ((int64_t)*in_ptr1 + (int64_t)*in_ptr2) >> 1;
762 * in_ptr1++;
763 * in_ptr2++;
765 * in_row1 -= width_i;
766 * in_row2 -= width_i;
767 * out_row1 -= width_i * 2;
768 * out_row2 -= width_i * 2;
773 //printf("decode 110\n");
775 // Convert to output colorspace
776 if(use_temp)
778 unsigned char **input_rows = malloc(sizeof(unsigned char*) * height_i);
779 for(i = 0; i < height_i; i++)
780 input_rows[i] = codec->temp_frame + width_i * 3;
783 cmodel_transfer(row_pointers, /* Leave NULL if non existent */
784 input_rows,
785 row_pointers[0], /* Leave NULL if non existent */
786 row_pointers[1],
787 row_pointers[2],
788 codec->temp_frame, /* Leave NULL if non existent */
789 codec->temp_frame + width_i * height_i,
790 codec->temp_frame + width_i * height_i + width_i * height_i / 4,
791 file->in_x, /* Dimensions to capture from input frame */
792 file->in_y,
793 file->in_w,
794 file->in_h,
795 0, /* Dimensions to project on output frame */
797 file->out_w,
798 file->out_h,
799 input_cmodel,
800 file->color_model,
801 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
802 width_i, /* For planar use the luma rowspan */
803 width);
805 free(input_rows);
809 decore_save_global(&codec->dec_param[current_field]);
810 pthread_mutex_unlock(&decode_mutex);
813 //printf("decode 120\n");
815 return result;
820 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
822 longest offset = quicktime_position(file);
823 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
824 quicktime_divx_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
825 quicktime_trak_t *trak = vtrack->track;
826 int width = trak->tkhd.track_width;
827 int height = trak->tkhd.track_height;
828 int width_i = (int)((float)width / 16 + 0.5) * 16;
829 int height_i = (int)((float)height / 16 + 0.5) * 16;
830 int result = 0;
831 int i;
832 ENC_FRAME encore_input;
833 ENC_RESULT encore_result;
834 int current_field = vtrack->current_position % codec->total_fields;
836 init_mutex();
837 pthread_mutex_lock(&encode_mutex);
839 if(!codec->encode_initialized[current_field])
841 codec->encode_initialized[current_field] = 1;
842 codec->encode_handle[current_field] = encode_handle++;
843 codec->enc_param[current_field].x_dim = width_i;
844 codec->enc_param[current_field].y_dim = height_i;
845 codec->enc_param[current_field].framerate =
846 quicktime_frame_rate(file, track) / codec->total_fields;
847 codec->enc_param[current_field].bitrate =
848 codec->bitrate / codec->total_fields;
849 codec->enc_param[current_field].rc_period = codec->rc_period;
850 codec->enc_param[current_field].rc_reaction_period = codec->rc_reaction_period;
851 codec->enc_param[current_field].rc_reaction_ratio = codec->rc_reaction_ratio;
852 codec->enc_param[current_field].max_quantizer = codec->max_quantizer;
853 codec->enc_param[current_field].min_quantizer = codec->min_quantizer;
854 codec->enc_param[current_field].max_key_interval = codec->max_key_interval;
856 codec->enc_param[current_field].search_range = codec->quality * 3;
857 if(codec->enc_param[current_field].search_range > 15)
858 codec->enc_param[current_field].search_range = 15;
860 encore(codec->encode_handle[current_field],
861 ENC_OPT_INIT,
862 &codec->enc_param[current_field], NULL);
866 // Assume planes are contiguous.
867 // Encode directly from function arguments
868 if(file->color_model == BC_YUV420P &&
869 width == width_i &&
870 height == height_i)
872 encore_input.image = row_pointers[0];
874 // Convert to YUV420P
875 // Encode from temporary.
876 else
878 if(!codec->temp_frame)
880 codec->temp_frame = malloc(width_i * height_i * 3 / 2);
883 cmodel_transfer(0, /* Leave NULL if non existent */
884 row_pointers,
885 codec->temp_frame, /* Leave NULL if non existent */
886 codec->temp_frame + width_i * height_i,
887 codec->temp_frame + width_i * height_i + width_i * height_i / 4,
888 row_pointers[0], /* Leave NULL if non existent */
889 row_pointers[1],
890 row_pointers[2],
891 0, /* Dimensions to capture from input frame */
893 width,
894 height,
895 0, /* Dimensions to project on output frame */
897 width,
898 height,
899 file->color_model,
900 BC_YUV420P,
901 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
902 width, /* For planar use the luma rowspan */
903 width_i);
906 encore_input.image = codec->temp_frame;
909 // Now shrink the Y buffer by half to contain just one field
911 * if(codec->total_fields == 2)
913 * unsigned char *out_ptr = encore_input.image;
914 * unsigned char *in_ptr = encore_input.image + current_field * width_i;
915 * int size = width_i * height_i;
916 * while(in_ptr < (unsigned char*)encore_input.image + size)
918 * for(i = 0; i < width_i; i++)
919 * *out_ptr++ = *in_ptr++;
920 * in_ptr += width_i;
922 * bzero(out_ptr, (unsigned char*)encore_input.image + size - out_ptr);
929 if(!codec->work_buffer)
931 codec->buffer_size = width * height;
932 codec->work_buffer = malloc(codec->buffer_size);
936 bzero(codec->work_buffer, codec->buffer_size);
937 encore_input.bitstream = codec->work_buffer;
938 encore_input.length = 0;
939 encore_input.quant = !codec->fix_bitrate ? codec->quantizer : 0;
941 if(codec->p_count == 0)
943 codec->p_count[current_field]++;
945 else
947 codec->p_count[current_field]++;
948 if(codec->p_count[current_field] >= codec->max_key_interval)
949 codec->p_count[current_field] = 0;
952 encore(codec->encode_handle[current_field],
954 &encore_input,
955 &encore_result);
956 pthread_mutex_unlock(&encode_mutex);
958 result = !quicktime_write_data(file,
959 codec->work_buffer,
960 encore_input.length);
961 quicktime_update_tables(file,
962 trak,
963 offset,
964 vtrack->current_chunk,
965 vtrack->current_position,
967 encore_input.length);
969 if(encore_result.isKeyFrame)
970 quicktime_insert_keyframe(file, file->vtracks[track].current_position, track);
972 file->vtracks[track].current_chunk++;
975 return result;
978 static int set_parameter(quicktime_t *file,
979 int track,
980 char *key,
981 void *value)
983 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
984 quicktime_divx_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
986 if(!strcasecmp(key, "divx_bitrate"))
987 codec->bitrate = *(int*)value;
988 else
989 if(!strcasecmp(key, "divx_rc_period"))
990 codec->rc_period = *(int*)value;
991 else
992 if(!strcasecmp(key, "divx_rc_reaction_ratio"))
993 codec->rc_reaction_ratio = *(int*)value;
994 else
995 if(!strcasecmp(key, "divx_rc_reaction_period"))
996 codec->rc_reaction_period = *(int*)value;
997 else
998 if(!strcasecmp(key, "divx_max_key_interval"))
999 codec->max_key_interval = *(int*)value;
1000 else
1001 if(!strcasecmp(key, "divx_max_quantizer"))
1002 codec->max_quantizer = *(int*)value;
1003 else
1004 if(!strcasecmp(key, "divx_min_quantizer"))
1005 codec->min_quantizer = *(int*)value;
1006 else
1007 if(!strcasecmp(key, "divx_quantizer"))
1008 codec->quantizer = *(int*)value;
1009 else
1010 if(!strcasecmp(key, "divx_quality"))
1011 codec->quality = *(int*)value;
1012 else
1013 if(!strcasecmp(key, "divx_fix_bitrate"))
1014 codec->fix_bitrate = *(int*)value;
1015 else
1016 if(!strcasecmp(key, "divx_use_deblocking"))
1017 codec->use_deblocking = *(int*)value;
1018 return 0;
1022 void quicktime_init_codec_divx(quicktime_video_map_t *vtrack)
1024 quicktime_divx_codec_t *codec;
1026 /* Init public items */
1027 ((quicktime_codec_t*)vtrack->codec)->priv = calloc(1, sizeof(quicktime_divx_codec_t));
1028 ((quicktime_codec_t*)vtrack->codec)->delete_vcodec = delete_codec;
1029 ((quicktime_codec_t*)vtrack->codec)->decode_video = decode;
1030 ((quicktime_codec_t*)vtrack->codec)->encode_video = encode;
1031 ((quicktime_codec_t*)vtrack->codec)->reads_colormodel = reads_colormodel;
1032 ((quicktime_codec_t*)vtrack->codec)->writes_colormodel = writes_colormodel;
1033 ((quicktime_codec_t*)vtrack->codec)->set_parameter = set_parameter;
1035 codec = ((quicktime_codec_t*)vtrack->codec)->priv;
1037 codec->bitrate = 1000000;
1038 codec->rc_period = 50;
1039 codec->rc_reaction_ratio = 45;
1040 codec->rc_reaction_period = 10;
1041 codec->max_key_interval = 45;
1042 codec->max_quantizer = 31;
1043 codec->min_quantizer = 1;
1044 codec->quantizer = 10;
1045 codec->quality = 5;
1046 codec->fix_bitrate = 1;
1047 codec->total_fields = 1;
1050 void quicktime_init_codec_hv60(quicktime_video_map_t *vtrack)
1052 quicktime_init_codec_divx(vtrack);
1053 quicktime_divx_codec_t *codec;
1055 codec = ((quicktime_codec_t*)vtrack->codec)->priv;
1057 codec->total_fields = 2;