10 #include "videodevice.inc"
13 #define _(String) gettext(String)
14 #define gettext_noop(String) String
15 #define N_(String) gettext_noop (String)
21 N_("Microsoft MPEG-4")
25 N_("Uncompressed RGB")
26 N_("Uncompressed RGBA")
27 N_("YUV 4:2:0 Planar")
29 N_("YUV 4:1:1 Packed")
30 N_("Component Y'CbCr 8-bit 4:4:4")
31 N_("Component Y'CbCrA 8-bit 4:4:4:4")
32 N_("Component Y'CbCr 10-bit 4:4:4")
45 #define DIVX_NAME "MPEG-4"
46 #define HV60_NAME "Heroine 60"
47 #define DIV3_NAME "Microsoft MPEG-4"
49 #define PNG_NAME "PNG"
50 #define PNGA_NAME "PNG with Alpha"
51 #define RGB_NAME "Uncompressed RGB"
52 #define RGBA_NAME "Uncompressed RGBA"
53 #define YUV420_NAME "YUV 4:2:0 Planar"
54 #define YUV422_NAME "Component Video"
55 #define YUV411_NAME "YUV 4:1:1 Packed"
56 #define YUV444_NAME "Component Y'CbCr 8-bit 4:4:4"
57 #define YUVA4444_NAME "Component Y'CbCrA 8-bit 4:4:4:4"
58 #define YUV444_10BIT_NAME "Component Y'CbCr 10-bit 4:4:4"
59 #define QTJPEG_NAME "JPEG Photo"
60 #define MJPA_NAME "Motion JPEG A"
63 #define TWOS_NAME "Twos complement"
64 #define RAW_NAME "Unsigned"
65 #define IMA4_NAME "IMA-4"
66 #define ULAW_NAME "U-Law"
67 //#define VORBIS_NAME "Vorbis"
68 #define MP3_NAME "MP3"
74 FileMOV::FileMOV(Asset *asset, File *file)
75 : FileBase(asset, file)
78 if(asset->format == FILE_UNKNOWN)
79 asset->format = FILE_MOV;
80 asset->byte_order = 0;
89 void FileMOV::get_parameters(BC_WindowBase *parent_window,
91 BC_WindowBase* &format_window,
99 MOVConfigAudio *window = new MOVConfigAudio(parent_window, asset);
100 format_window = window;
101 window->create_objects();
102 window->run_window();
108 MOVConfigVideo *window = new MOVConfigVideo(parent_window,
111 format_window = window;
112 window->create_objects();
113 window->run_window();
118 void FileMOV::fix_codecs(Asset *asset)
120 // if(asset->format == FILE_MOV)
122 // if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
123 // strcpy(asset->acodec, QUICKTIME_TWOS);
127 // if(strcasecmp(asset->vcodec, QUICKTIME_DIV3))
129 // strcpy(asset->vcodec, QUICKTIME_DIV3);
131 // strcpy(asset->acodec, QUICKTIME_MP3);
135 int FileMOV::check_sig(Asset *asset)
137 return quicktime_check_sig(asset->path);
141 int FileMOV::reset_parameters_derived()
147 quicktime_atracks = 0;
148 quicktime_vtracks = 0;
151 frames_correction = 0;
152 samples_correction = 0;
158 // Just create the Quicktime objects since this routine is also called
160 int FileMOV::open_file(int rd, int wr)
166 if(suffix_number == 0) strcpy(prefix_path, asset->path);
168 if(!(fd = quicktime_open(asset->path, rd, wr)))
170 printf(_("FileMOV::open_file %s: No such file or directory\n"), asset->path);
174 quicktime_set_cpus(fd, file->cpus);
176 if(rd) format_to_asset();
178 if(wr) asset_to_format();
180 // Set decoding parameter
181 quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking);
186 int FileMOV::close_file()
188 //printf("FileMOV::close_file 1 %s\n", asset->path);
191 if(wr) quicktime_set_framerate(fd, asset->frame_rate);
195 //printf("FileMOV::close_file 1\n");
201 //printf("FileMOV::close_file 1\n");
204 for(int i = 0; i < file->cpus; i++)
206 threads[i]->stop_encoding();
213 //printf("FileMOV::close_file 1\n");
214 threadframes.remove_all_objects();
219 for(int i = 0; i < asset->channels; i++)
220 delete [] temp_float[i];
221 delete [] temp_float;
224 //printf("FileMOV::close_file 1\n");
226 FileBase::close_file();
227 //printf("FileMOV::close_file 2\n");
231 void FileMOV::asset_to_format()
238 // Fix up the Quicktime file.
239 quicktime_set_copyright(fd, _("Made with Cinelerra for Linux"));
240 quicktime_set_info(fd, "Quicktime for Linux");
242 if(asset->audio_data)
244 quicktime_atracks = quicktime_set_audio(fd,
249 quicktime_set_parameter(fd, "vorbis_vbr", &asset->vorbis_vbr);
250 quicktime_set_parameter(fd, "vorbis_min_bitrate", &asset->vorbis_min_bitrate);
251 quicktime_set_parameter(fd, "vorbis_bitrate", &asset->vorbis_bitrate);
252 quicktime_set_parameter(fd, "vorbis_max_bitrate", &asset->vorbis_max_bitrate);
253 quicktime_set_parameter(fd, "mp3_bitrate", &asset->mp3_bitrate);
256 if(asset->video_data)
259 // Set up the alpha channel compressors
260 if(!strcmp(asset->vcodec, MOV_RGBA))
262 strcpy(string, QUICKTIME_RAW);
266 if(!strcmp(asset->vcodec, MOV_PNGA))
268 strcpy(string, QUICKTIME_PNG);
272 if(!strcmp(asset->vcodec, QUICKTIME_YUVA4444))
274 strcpy(string, asset->vcodec);
279 strcpy(string, asset->vcodec);
283 quicktime_vtracks = quicktime_set_video(fd,
292 for(int i = 0; i < asset->layers; i++)
293 quicktime_set_depth(fd, depth, i);
295 quicktime_set_parameter(fd, "jpeg_quality", &asset->jpeg_quality);
297 // set the compression parameters if there are any
298 quicktime_set_parameter(fd, "divx_bitrate", &asset->divx_bitrate);
299 quicktime_set_parameter(fd, "divx_rc_period", &asset->divx_rc_period);
300 quicktime_set_parameter(fd, "divx_rc_reaction_ratio", &asset->divx_rc_reaction_ratio);
301 quicktime_set_parameter(fd, "divx_rc_reaction_period", &asset->divx_rc_reaction_period);
302 quicktime_set_parameter(fd, "divx_max_key_interval", &asset->divx_max_key_interval);
303 quicktime_set_parameter(fd, "divx_max_quantizer", &asset->divx_max_quantizer);
304 quicktime_set_parameter(fd, "divx_min_quantizer", &asset->divx_min_quantizer);
305 quicktime_set_parameter(fd, "divx_quantizer", &asset->divx_quantizer);
306 quicktime_set_parameter(fd, "divx_quality", &asset->divx_quality);
307 quicktime_set_parameter(fd, "divx_fix_bitrate", &asset->divx_fix_bitrate);
309 quicktime_set_parameter(fd, "div3_bitrate", &asset->ms_bitrate);
310 quicktime_set_parameter(fd, "div3_bitrate_tolerance", &asset->ms_bitrate_tolerance);
311 quicktime_set_parameter(fd, "div3_interlaced", &asset->ms_interlaced);
312 quicktime_set_parameter(fd, "div3_quantizer", &asset->ms_quantization);
313 quicktime_set_parameter(fd, "div3_gop_size", &asset->ms_gop_size);
314 quicktime_set_parameter(fd, "div3_fix_bitrate", &asset->ms_fix_bitrate);
316 //printf("FileMOV::asset_to_format 3.3\n");
318 //printf("FileMOV::asset_to_format 3.4\n");
320 //printf("FileMOV::asset_to_format 4 %d %d\n", wr,
323 if(wr && asset->format == FILE_AVI)
325 quicktime_set_avi(fd, 1);
330 void FileMOV::format_to_asset()
334 if(quicktime_is_avi(fd)) asset->format = FILE_AVI;
335 asset->audio_data = quicktime_has_audio(fd);
336 if(asset->audio_data)
339 int qt_tracks = quicktime_audio_tracks(fd);
340 for(int i = 0; i < qt_tracks; i++)
341 asset->channels += quicktime_track_channels(fd, i);
343 if(!asset->sample_rate)
344 asset->sample_rate = quicktime_sample_rate(fd, 0);
345 asset->bits = quicktime_audio_bits(fd, 0);
346 asset->audio_length = quicktime_audio_length(fd, 0);
347 strncpy(asset->acodec, quicktime_audio_compressor(fd, 0), 4);
350 // determine if the video can be read before declaring video data
351 if(quicktime_has_video(fd) && quicktime_supported_video(fd, 0))
352 asset->video_data = 1;
354 if(asset->video_data)
356 depth = quicktime_video_depth(fd, 0);
357 asset->layers = quicktime_video_tracks(fd);
358 asset->width = quicktime_video_width(fd, 0);
359 asset->height = quicktime_video_height(fd, 0);
360 asset->video_length = quicktime_video_length(fd, 0);
361 // Don't want a user configured frame rate to get destroyed
362 if(!asset->frame_rate)
363 asset->frame_rate = quicktime_frame_rate(fd, 0);
365 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
369 int FileMOV::colormodel_supported(int colormodel)
374 int FileMOV::get_best_colormodel(Asset *asset, int driver)
381 case PLAYBACK_X11_XV:
382 if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
383 if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422P;
384 if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
385 if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
386 if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
387 if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
388 if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
389 if(match4(asset->vcodec, QUICKTIME_DIV3)) return BC_YUV420P;
391 case PLAYBACK_FIREWIRE:
392 if(match4(asset->vcodec, QUICKTIME_DV)) return BC_COMPRESSED;
397 if(match4(asset->vcodec, QUICKTIME_MJPA))
398 return BC_COMPRESSED;
404 if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
406 if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
408 if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
410 if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
412 if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
414 if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
416 if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
418 if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
422 if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4))
423 return BC_COMPRESSED;
427 case CAPTURE_FIREWIRE:
428 if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4))
429 return BC_COMPRESSED;
437 int FileMOV::can_copy_from(Edit *edit, int64_t position)
441 //printf("FileMOV::can_copy_from 1 %d %s %s\n", edit->asset->format, edit->asset->vcodec, this->asset->vcodec);
442 if(edit->asset->format == FILE_JPEG_LIST &&
443 match4(this->asset->vcodec, QUICKTIME_JPEG))
446 if((edit->asset->format == FILE_MOV ||
447 edit->asset->format == FILE_AVI)
449 (match4(edit->asset->vcodec, this->asset->vcodec)))
456 int64_t FileMOV::get_audio_length()
459 int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
464 int FileMOV::set_audio_position(int64_t x)
467 // quicktime sets positions for each track seperately so store position in audio_position
468 if(x >= 0 && x < asset->audio_length)
469 return quicktime_set_audio_position(fd, x, 0);
474 int FileMOV::set_video_position(int64_t x)
477 //printf("FileMOV::set_video_position 1 %d %d\n", x, asset->video_length);
478 if(x >= 0 && x < asset->video_length)
479 return quicktime_set_video_position(fd, x, file->current_layer);
485 void FileMOV::new_audio_temp(int64_t len)
487 if(temp_allocated && temp_allocated < len)
489 for(int i = 0; i < asset->channels; i++)
490 delete [] temp_float[i];
491 delete [] temp_float;
497 temp_allocated = len;
498 temp_float = new float*[asset->channels];
499 for(int i = 0; i < asset->channels; i++)
500 temp_float[i] = new float[len];
506 int FileMOV::write_samples(double **buffer, int64_t len)
510 int result = 0, track_channels = 0;
515 if(quicktime_supported_audio(fd, 0))
517 // Use Quicktime's compressor. (Always used)
518 // Allocate temp buffer
521 // Copy to float buffer
522 for(i = 0; i < asset->channels; i++)
524 for(j = 0; j < len; j++)
526 temp_float[i][j] = buffer[i][j];
530 // Because of the way Quicktime's compressors work we want to limit the chunk
531 // size to speed up decompression.
533 channel_ptr = new float*[asset->channels];
535 for(j = 0; j < len && !result; )
537 chunk_size = asset->sample_rate;
538 if(j + chunk_size > len) chunk_size = len - j;
540 for(i = 0; i < asset->channels; i++)
542 channel_ptr[i] = &temp_float[i][j];
545 result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
546 j += asset->sample_rate;
549 delete [] channel_ptr;
554 int FileMOV::write_frames(VFrame ***frames, int len)
556 int i, j, k, result = 0;
557 int default_compressor = 1;
560 //printf("FileMOV::write_frames 1\n");
561 for(i = 0; i < asset->layers && !result; i++)
568 // Fix direct copy cases for format conversions.
569 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
571 default_compressor = 0;
572 for(j = 0; j < len && !result; j++)
574 VFrame *frame = frames[i][j];
578 // Special handling for DIVX
579 // Determine keyframe status.
580 // Write VOL header in the first frame if none exists
581 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
582 !strcmp(asset->vcodec, QUICKTIME_HV60))
584 if(quicktime_mpeg4_is_key(frame->get_data(),
585 frame->get_compressed_size(),
587 quicktime_insert_keyframe(fd, file->current_frame + j, i);
591 if(!(file->current_frame + j) &&
592 !quicktime_mpeg4_has_vol(frame->get_data()))
594 VFrame *temp_frame = new VFrame;
596 temp_frame->allocate_compressed_data(frame->get_compressed_size() +
598 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
603 memcpy(temp_frame->get_data() + bytes,
605 frame->get_compressed_size());
606 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
608 result = quicktime_write_frame(fd,
609 temp_frame->get_data(),
610 temp_frame->get_compressed_size(),
619 result = quicktime_write_frame(fd,
621 frame->get_compressed_size(),
626 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
628 if(quicktime_mpeg4_is_key(frame->get_data(),
629 frame->get_compressed_size(),
631 quicktime_insert_keyframe(fd, file->current_frame + j, i);
632 result = quicktime_write_frame(fd,
634 frame->get_compressed_size(),
638 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
641 // Create extra space for markers
642 if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
643 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
645 unsigned char *data = frame->get_data();
646 long data_size = frame->get_compressed_size();
647 long data_allocated = frame->get_compressed_allocated();
649 if(asset->format == FILE_MOV)
651 mjpeg_insert_quicktime_markers(&data,
659 mjpeg_insert_avi_markers(&data,
665 frame->set_compressed_size(data_size);
666 result = quicktime_write_frame(fd,
668 frame->get_compressed_size(),
672 result = quicktime_write_frame(fd,
674 frame->get_compressed_size(),
681 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
682 match4(asset->vcodec, QUICKTIME_YUV422) ||
683 match4(asset->vcodec, QUICKTIME_RAW))
685 // Direct copy planes where possible
686 default_compressor = 0;
687 for(j = 0; j < len && !result; j++)
689 VFrame *frame = frames[i][j];
690 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
691 quicktime_set_cmodel(fd, frame->get_color_model());
692 //printf("FileMOV::write_frames 1 %d\n", cmodel_is_planar(frame->get_color_model()));
693 if(cmodel_is_planar(frame->get_color_model()))
695 unsigned char *planes[3];
696 planes[0] = frame->get_y();
697 planes[1] = frame->get_u();
698 planes[2] = frame->get_v();
699 result = quicktime_encode_video(fd, planes, i);
703 result = quicktime_encode_video(fd, frame->get_rows(), i);
704 //printf("FileMOV::write_frames 2 %d\n", result);
706 //printf("FileMOV::write_frames 2\n");
711 (match4(asset->vcodec, QUICKTIME_JPEG) ||
712 match4(asset->vcodec, QUICKTIME_MJPA)))
714 default_compressor = 0;
715 // Compress symmetrically on an SMP system.
716 ThreadStruct *threadframe;
717 int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
719 // Set up threads for symmetric compression.
722 threads = new FileMOVThread*[file->cpus];
723 for(j = 0; j < file->cpus; j++)
725 threads[j] = new FileMOVThread(this, fields);
726 threads[j]->start_encoding();
730 // Set up the frame structures for asynchronous compression.
731 // The mjpeg object must exist in each threadframe because it is where the output
733 while(threadframes.total < len)
735 threadframes.append(threadframe = new ThreadStruct);
738 // Load thread frame structures with new frames.
739 for(j = 0; j < len; j++)
741 VFrame *frame = frames[i][j];
742 threadframes.values[j]->input = frame;
743 threadframes.values[j]->completion_lock.lock();
745 total_threadframes = len;
746 current_threadframe = 0;
748 // Start the threads compressing
749 for(j = 0; j < file->cpus; j++)
751 threads[j]->encode_buffer();
754 // Write the frames as they're finished
755 for(j = 0; j < len; j++)
757 threadframes.values[j]->completion_lock.lock();
758 threadframes.values[j]->completion_lock.unlock();
759 //printf("filemov 1\n");
762 result = quicktime_write_frame(fd,
763 threadframes.values[j]->output,
764 threadframes.values[j]->output_size,
770 if(default_compressor)
772 //printf("FileMOV::write_frames 3\n");
773 // Use the library's built in compressor.
774 for(j = 0; j < len && !result; j++)
776 //printf("FileMOV::write_frames 4\n");
777 VFrame *frame = frames[i][j];
778 quicktime_set_cmodel(fd, frame->get_color_model());
779 //printf("FileMOV::write_frames 5\n");
780 if(cmodel_is_planar(frame->get_color_model()))
782 unsigned char *planes[3];
783 planes[0] = frame->get_y();
784 planes[1] = frame->get_u();
785 planes[2] = frame->get_v();
786 //printf("FileMOV::write_frames 6\n");
787 result = quicktime_encode_video(fd, planes, i);
788 //printf("FileMOV::write_frames 7\n");
792 //printf("FileMOV::write_frames 8\n");
793 result = quicktime_encode_video(fd, frame->get_rows(), i);
794 //printf("FileMOV::write_frames 9\n");
798 //printf("FileMOV::write_frames 4\n");
802 //printf("FileMOV::write_frames 100 %d\n", result);
808 int FileMOV::read_frame(VFrame *frame)
813 //printf("FileMOV::read_frame 1\n");
814 switch(frame->get_color_model())
817 frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
818 frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
819 result = quicktime_read_frame(fd,
821 file->current_layer);
828 unsigned char *row_pointers[3];
829 row_pointers[0] = frame->get_y();
830 row_pointers[1] = frame->get_u();
831 row_pointers[2] = frame->get_v();
833 quicktime_set_cmodel(fd, frame->get_color_model());
834 quicktime_decode_video(fd,
836 file->current_layer);
842 quicktime_set_cmodel(fd, frame->get_color_model());
843 result = quicktime_decode_video(fd,
845 file->current_layer);
846 //for(int i = 0; i < 10000; i++) frame->get_rows()[0][i] = 0xff;
852 //printf("FileMOV::read_frame 100\n");
858 int64_t FileMOV::compressed_frame_size()
861 return quicktime_frame_size(fd, file->current_frame, file->current_layer);
864 int FileMOV::read_compressed_frame(VFrame *buffer)
869 //printf("FileMOV::read_compressed_frame 1\n");
870 result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
871 buffer->set_compressed_size(result);
872 //printf("FileMOV::read_compressed_frame 100\n");
877 int FileMOV::write_compressed_frame(VFrame *buffer)
882 //printf("FileMOV::write_compressed_frame 1\n");
883 result = quicktime_write_frame(fd,
885 buffer->get_compressed_size(),
886 file->current_layer);
887 //printf("FileMOV::write_compressed_frame 100\n");
893 int FileMOV::read_raw(VFrame *frame,
894 float in_x1, float in_y1, float in_x2, float in_y2,
895 float out_x1, float out_y1, float out_x2, float out_y2,
896 int use_float, int interpolate)
898 int64_t i, color_channels, result = 0;
900 quicktime_set_video_position(fd, file->current_frame, file->current_layer);
901 // Develop importing strategy
902 switch(frame->get_color_model())
905 result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
911 case BC_RGBA16161616:
919 case BC_YUVA16161616:
928 int FileMOV::read_samples(double *buffer, int64_t len)
930 int qt_track, qt_channel;
934 //printf("FileMOV::read_samples 1\n");
935 if(quicktime_track_channels(fd, 0) > file->current_channel &&
936 quicktime_supported_audio(fd, 0))
939 //printf("FileMOV::read_samples 2 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
942 //printf("FileMOV::read_samples 3 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
943 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
945 printf("FileMOV::read_samples: quicktime_decode_audio failed\n");
950 for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
953 // if(file->current_channel == 0)
954 // for(int i = 0; i < len; i++)
957 // value = (int16_t)(temp_float[0][i] * 32767);
958 // fwrite(&value, 2, 1, stdout);
960 //printf("FileMOV::read_samples 4 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
963 //printf("FileMOV::read_samples 100\n");
968 char* FileMOV::strtocompression(char *string)
970 if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
971 if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
972 if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
973 if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
974 if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
975 if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
976 if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
977 if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
978 if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
979 if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
980 if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
981 if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
982 if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
983 if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
984 if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
985 if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
987 if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
988 if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
989 if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
990 if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
991 if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
992 if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
996 return QUICKTIME_RAW;
999 char* FileMOV::compressiontostr(char *string)
1001 if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1002 if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1003 if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1004 if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1005 if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1006 if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1007 if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1008 if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1009 if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1010 if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1011 if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1012 if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1013 if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1014 if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1015 if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1021 if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1022 if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1023 if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1024 if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1025 if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1026 if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1030 return _("Unknown");
1037 ThreadStruct::ThreadStruct()
1041 output_allocated = 0;
1045 ThreadStruct::~ThreadStruct()
1047 if(output) delete [] output;
1050 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1052 if(output_allocated < mjpeg_output_size(mjpeg))
1059 output_allocated = mjpeg_output_size(mjpeg);
1060 output = new unsigned char[output_allocated];
1063 output_size = mjpeg_output_size(mjpeg);
1064 memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1068 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields) : Thread()
1070 this->filemov = filemov;
1071 this->fields = fields;
1074 FileMOVThread::~FileMOVThread()
1078 int FileMOVThread::start_encoding()
1080 //printf("FileMOVThread::start_encoding 1 %d\n", fields);
1081 mjpeg = mjpeg_new(filemov->asset->width,
1082 filemov->asset->height,
1084 mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1085 mjpeg_set_float(mjpeg, 0);
1092 int FileMOVThread::stop_encoding()
1095 input_lock.unlock();
1097 if(mjpeg) mjpeg_delete(mjpeg);
1100 int FileMOVThread::encode_buffer()
1102 input_lock.unlock();
1105 void FileMOVThread::run()
1113 // Get a frame to compress.
1114 filemov->threadframe_lock.lock();
1115 if(filemov->current_threadframe < filemov->total_threadframes)
1117 // Frame is available to process.
1118 input_lock.unlock();
1119 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1120 VFrame *frame = threadframe->input;
1122 filemov->current_threadframe++;
1123 filemov->threadframe_lock.unlock();
1125 //printf("FileMOVThread 1 %02x%02x\n", mjpeg_output_buffer(mjpeg)[0], mjpeg_output_buffer(mjpeg)[1]);
1126 mjpeg_compress(mjpeg,
1131 frame->get_color_model(),
1134 //printf("FileMOVThread 1 %02x%02x\n", mjpeg_output_buffer(mjpeg)[0], mjpeg_output_buffer(mjpeg)[1]);
1135 //printf("FileMOVThread 1\n");
1139 // Create extra space for markers
1140 if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
1141 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
1143 unsigned char *data = frame->get_data();
1144 long data_size = frame->get_compressed_size();
1145 long data_allocated = frame->get_compressed_allocated();
1147 if(filemov->asset->format == FILE_MOV)
1149 mjpeg_insert_quicktime_markers(&data,
1157 mjpeg_insert_avi_markers(&data,
1163 frame->set_compressed_size(data_size);
1165 threadframe->load_output(mjpeg);
1166 //printf("FileMOVThread 2 %02x%02x\n", mjpeg_output_buffer(mjpeg)[0], mjpeg_output_buffer(mjpeg)[1]);
1168 //printf("FileMOVThread 2 %p\n", this);
1169 threadframe->completion_lock.unlock();
1172 filemov->threadframe_lock.unlock();
1182 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1183 : BC_Window(PROGRAM_NAME ": Audio Compression",
1184 parent_window->get_abs_cursor_x(),
1185 parent_window->get_abs_cursor_y(),
1189 this->parent_window = parent_window;
1190 this->asset = asset;
1194 vorbis_min_bitrate = 0;
1196 vorbis_max_bitrate = 0;
1198 compression_popup = 0;
1202 MOVConfigAudio::~MOVConfigAudio()
1204 if(compression_popup) delete compression_popup;
1205 if(bits_popup) delete bits_popup;
1206 compression_items.remove_all_objects();
1209 int MOVConfigAudio::create_objects()
1215 if(asset->format == FILE_MOV)
1217 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1218 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1219 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1220 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1221 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1222 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1226 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1227 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1228 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1231 add_tool(new BC_Title(x, y, _("Compression:")));
1233 compression_popup = new MOVConfigAudioPopup(this, x, y);
1234 compression_popup->create_objects();
1236 update_parameters();
1238 add_subwindow(new BC_OKButton(this));
1242 void MOVConfigAudio::update_parameters()
1245 if(bits_title) delete bits_title;
1246 if(bits_popup) delete bits_popup;
1247 if(dither) delete dither;
1248 if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1249 if(vorbis_bitrate) delete vorbis_bitrate;
1250 if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1251 if(vorbis_vbr) delete vorbis_vbr;
1252 if(mp3_bitrate) delete mp3_bitrate;
1257 vorbis_min_bitrate = 0;
1259 vorbis_max_bitrate = 0;
1268 if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1269 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1271 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1272 bits_popup = new BitsPopup(this,
1281 bits_popup->create_objects();
1283 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1286 if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1290 if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1292 mp3_bitrate = new MOVConfigAudioNum(this,
1296 &asset->mp3_bitrate);
1297 mp3_bitrate->set_increment(1000);
1298 mp3_bitrate->create_objects();
1301 if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1305 if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1307 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1308 _("Variable bitrate"),
1311 &asset->vorbis_vbr));
1313 vorbis_min_bitrate = new MOVConfigAudioNum(this,
1317 &asset->vorbis_min_bitrate);
1319 vorbis_bitrate = new MOVConfigAudioNum(this,
1323 &asset->vorbis_bitrate);
1325 vorbis_max_bitrate = new MOVConfigAudioNum(this,
1329 &asset->vorbis_max_bitrate);
1333 vorbis_min_bitrate->create_objects();
1334 vorbis_bitrate->create_objects();
1335 vorbis_max_bitrate->create_objects();
1339 int MOVConfigAudio::close_event()
1349 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1354 : BC_CheckBox(x, y, *output, title_text)
1356 this->popup = popup;
1357 this->output = output;
1359 int MOVConfigAudioToggle::handle_event()
1361 *output = get_value();
1369 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1370 : BC_TumbleTextBox(popup,
1378 this->popup = popup;
1379 this->title_text = title_text;
1380 this->output = output;
1385 MOVConfigAudioNum::~MOVConfigAudioNum()
1390 void MOVConfigAudioNum::create_objects()
1392 popup->add_subwindow(title = new BC_Title(x, y, title_text));
1393 BC_TumbleTextBox::create_objects();
1396 int MOVConfigAudioNum::handle_event()
1398 *output = atol(get_text());
1409 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1410 : BC_PopupTextBox(popup,
1411 &popup->compression_items,
1412 FileMOV::compressiontostr(popup->asset->acodec),
1418 this->popup = popup;
1421 int MOVConfigAudioPopup::handle_event()
1423 strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1424 popup->update_parameters();
1444 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window,
1446 int lock_compressor)
1447 : BC_Window(PROGRAM_NAME ": Video Compression",
1448 parent_window->get_abs_cursor_x(),
1449 parent_window->get_abs_cursor_y(),
1453 this->parent_window = parent_window;
1454 this->asset = asset;
1455 this->lock_compressor = lock_compressor;
1456 compression_popup = 0;
1461 MOVConfigVideo::~MOVConfigVideo()
1463 if(compression_popup) delete compression_popup;
1464 compression_items.remove_all_objects();
1467 int MOVConfigVideo::create_objects()
1471 if(asset->format == FILE_MOV)
1473 compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1474 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1475 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1476 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1477 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1478 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1479 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1480 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1481 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1482 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1483 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1484 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1485 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1486 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1487 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1491 compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1492 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1493 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1494 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1495 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1496 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1497 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1500 add_subwindow(new BC_Title(x, y, _("Compression:")));
1503 if(!lock_compressor)
1505 compression_popup = new MOVConfigVideoPopup(this, x, y);
1506 compression_popup->create_objects();
1510 add_subwindow(new BC_Title(x,
1512 FileMOV::compressiontostr(asset->vcodec),
1521 update_parameters();
1523 add_subwindow(new BC_OKButton(this));
1527 int MOVConfigVideo::close_event()
1534 void MOVConfigVideo::reset()
1537 jpeg_quality_title = 0;
1541 divx_rc_reaction_ratio = 0;
1542 divx_rc_reaction_period = 0;
1543 divx_max_key_interval = 0;
1544 divx_max_quantizer = 0;
1545 divx_min_quantizer = 0;
1548 divx_fix_bitrate = 0;
1552 ms_bitrate_tolerance = 0;
1553 ms_quantization = 0;
1560 void MOVConfigVideo::update_parameters()
1564 delete jpeg_quality_title;
1565 delete jpeg_quality;
1568 if(divx_bitrate) delete divx_bitrate;
1569 if(divx_rc_period) delete divx_rc_period;
1570 if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1571 if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1572 if(divx_max_key_interval) delete divx_max_key_interval;
1573 if(divx_max_quantizer) delete divx_max_quantizer;
1574 if(divx_min_quantizer) delete divx_min_quantizer;
1575 if(divx_quantizer) delete divx_quantizer;
1576 if(divx_quality) delete divx_quality;
1577 if(divx_fix_quant) delete divx_fix_quant;
1578 if(divx_fix_bitrate) delete divx_fix_bitrate;
1580 if(ms_bitrate) delete ms_bitrate;
1581 if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1582 if(ms_interlaced) delete ms_interlaced;
1583 if(ms_quantization) delete ms_quantization;
1584 if(ms_gop_size) delete ms_gop_size;
1585 if(ms_fix_bitrate) delete ms_fix_bitrate;
1586 if(ms_fix_quant) delete ms_fix_quant;
1590 // ffmpeg parameters
1591 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
1593 int x = param_x, y = param_y;
1594 ms_bitrate = new MOVConfigVideoNum(this,
1598 &asset->ms_bitrate);
1599 ms_bitrate->set_increment(1000000);
1600 ms_bitrate->create_objects();
1601 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260,
1603 &asset->ms_fix_bitrate,
1607 ms_bitrate_tolerance = new MOVConfigVideoNum(this,
1608 _("Bitrate tolerance:"),
1611 &asset->ms_bitrate_tolerance);
1612 ms_bitrate_tolerance->create_objects();
1614 ms_quantization = new MOVConfigVideoNum(this,
1618 &asset->ms_quantization);
1619 ms_quantization->create_objects();
1620 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260,
1622 &asset->ms_fix_bitrate,
1624 ms_fix_bitrate->opposite = ms_fix_quant;
1625 ms_fix_quant->opposite = ms_fix_bitrate;
1629 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"),
1632 &asset->ms_interlaced));
1634 ms_gop_size = new MOVConfigVideoNum(this,
1635 _("Keyframe interval:"),
1638 &asset->ms_gop_size);
1639 ms_gop_size->create_objects();
1642 // OpenDivx parameters
1643 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
1644 !strcmp(asset->vcodec, QUICKTIME_HV60))
1646 int x = param_x, y = param_y;
1647 divx_bitrate = new MOVConfigVideoNum(this,
1651 &asset->divx_bitrate);
1652 divx_bitrate->set_increment(1000000);
1653 divx_bitrate->create_objects();
1654 add_subwindow(divx_fix_bitrate =
1655 new MOVConfigVideoFixBitrate(x + 260,
1657 &asset->divx_fix_bitrate,
1660 divx_quantizer = new MOVConfigVideoNum(this,
1664 &asset->divx_quantizer);
1665 divx_quantizer->create_objects();
1666 add_subwindow(divx_fix_quant =
1667 new MOVConfigVideoFixQuant(x + 260,
1669 &asset->divx_fix_bitrate,
1671 divx_fix_quant->opposite = divx_fix_bitrate;
1672 divx_fix_bitrate->opposite = divx_fix_quant;
1674 divx_rc_period = new MOVConfigVideoNum(this,
1678 &asset->divx_rc_period);
1679 divx_rc_period->create_objects();
1681 divx_rc_reaction_ratio = new MOVConfigVideoNum(this,
1682 _("Reaction Ratio:"),
1685 &asset->divx_rc_reaction_ratio);
1686 divx_rc_reaction_ratio->create_objects();
1688 divx_rc_reaction_period = new MOVConfigVideoNum(this,
1689 _("Reaction Period:"),
1692 &asset->divx_rc_reaction_period);
1693 divx_rc_reaction_period->create_objects();
1695 divx_max_key_interval = new MOVConfigVideoNum(this,
1696 _("Max Key Interval:"),
1699 &asset->divx_max_key_interval);
1700 divx_max_key_interval->create_objects();
1702 divx_max_quantizer = new MOVConfigVideoNum(this,
1703 _("Max Quantizer:"),
1706 &asset->divx_max_quantizer);
1707 divx_max_quantizer->create_objects();
1709 divx_min_quantizer = new MOVConfigVideoNum(this,
1710 _("Min Quantizer:"),
1713 &asset->divx_min_quantizer);
1714 divx_min_quantizer->create_objects();
1716 divx_quality = new MOVConfigVideoNum(this,
1720 &asset->divx_quality);
1721 divx_quality->create_objects();
1724 if(!strcmp(asset->vcodec, QUICKTIME_JPEG) ||
1725 !strcmp(asset->vcodec, QUICKTIME_MJPA))
1727 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
1728 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80,
1735 asset->jpeg_quality,
1738 &asset->jpeg_quality));
1746 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
1747 : BC_TumbleTextBox(popup,
1755 this->popup = popup;
1756 this->title_text = title_text;
1757 this->output = output;
1762 MOVConfigVideoNum::~MOVConfigVideoNum()
1767 void MOVConfigVideoNum::create_objects()
1769 popup->add_subwindow(title = new BC_Title(x, y, title_text));
1770 BC_TumbleTextBox::create_objects();
1773 int MOVConfigVideoNum::handle_event()
1775 *output = atol(get_text());
1785 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
1786 : BC_CheckBox(x, y, *output, title_text)
1788 this->output = output;
1791 int MOVConfigVideoCheckBox::handle_event()
1793 *output = get_value();
1802 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x,
1811 this->output = output;
1812 this->value = value;
1815 int MOVConfigVideoFixBitrate::handle_event()
1818 opposite->update(0);
1827 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x,
1834 _("Fix quantization"))
1836 this->output = output;
1837 this->value = value;
1840 int MOVConfigVideoFixQuant::handle_event()
1843 opposite->update(0);
1851 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
1852 : BC_PopupTextBox(popup,
1853 &popup->compression_items,
1854 FileMOV::compressiontostr(popup->asset->vcodec),
1860 this->popup = popup;
1863 int MOVConfigVideoPopup::handle_event()
1865 strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
1866 popup->update_parameters();