4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bcsignals.h"
24 #include "bitspopup.h"
25 #include "byteorder.h"
27 #include "condition.h"
35 #include "mwindow.inc"
36 #include "preferences.h"
38 #include "videodevice.inc"
39 #include "mainerror.h"
51 N_("Microsoft MPEG-4")
55 N_("Uncompressed RGB")
56 N_("Uncompressed RGBA")
57 N_("YUV 4:2:0 Planar")
58 N_("Component Y'CbCr 8-bit 4:2:2 (yuv2)")
59 N_("Component Y'CbCr 8-bit 4:2:2 (2vuy)")
60 N_("YUV 4:1:1 Packed")
61 N_("Component Y'CbCr 8-bit 4:4:4")
62 N_("Component Y'CbCrA 8-bit 4:4:4:4")
63 N_("Component Y'CbCr 10-bit 4:4:4")
77 #define DIVX_NAME "MPEG-4"
78 #define HV64_NAME "Dual H.264"
79 #define MP4V_NAME "MPEG-4 Video"
80 #define H264_NAME "H.264"
81 #define H263_NAME "H.263"
82 #define HV60_NAME "Dual MPEG-4"
83 #define DIV3_NAME "Microsoft MPEG-4"
85 #define PNG_NAME "PNG"
86 #define PNGA_NAME "PNG with Alpha"
87 #define RGB_NAME "Uncompressed RGB"
88 #define RGBA_NAME "Uncompressed RGBA"
89 #define YUV420_NAME "YUV 4:2:0 Planar"
90 #define YUV422_NAME "Component Y'CbCr 8-bit 4:2:2 (yuv2)"
91 #define TWOVUY_NAME "Component Y'CbCr 8-bit 4:2:2 (2vuy)"
92 #define YUV411_NAME "YUV 4:1:1 Packed"
93 #define YUV444_NAME "Component Y'CbCr 8-bit 4:4:4"
94 #define YUVA4444_NAME "Component Y'CbCrA 8-bit 4:4:4:4"
95 #define YUV444_10BIT_NAME "Component Y'CbCr 10-bit 4:4:4"
96 #define QTJPEG_NAME "JPEG Photo"
97 #define QTMJPEGP_NAME "MJPEG Photo"
98 #define MJPA_NAME "Motion JPEG A"
100 #define TWOS_NAME "Twos complement"
101 #define RAW_NAME "Unsigned"
102 #define IMA4_NAME "IMA-4"
103 #define ULAW_NAME "U-Law"
104 //#define VORBIS_NAME "Vorbis"
105 #define MP3_NAME "MP3"
106 #define MP4A_NAME "MPEG-4 Audio"
107 #define VORBIS_NAME "OGG Vorbis"
113 FileMOV::FileMOV(Asset *asset, File *file)
114 : FileBase(asset, file)
117 if(asset->format == FILE_UNKNOWN)
118 asset->format = FILE_MOV;
119 asset->byte_order = 0;
121 threadframe_lock = new Mutex("FileMOV::threadframe_lock");
127 delete threadframe_lock;
130 void FileMOV::get_parameters(BC_WindowBase *parent_window,
132 BC_WindowBase* &format_window,
135 const char *locked_compressor)
140 MOVConfigAudio *window = new MOVConfigAudio(parent_window, asset);
141 format_window = window;
142 window->create_objects();
143 window->run_window();
149 MOVConfigVideo *window = new MOVConfigVideo(parent_window,
152 format_window = window;
153 window->create_objects();
154 window->run_window();
159 void FileMOV::fix_codecs(Asset *asset)
161 if(!strcasecmp(asset->vcodec, QUICKTIME_DV) ||
162 !strcasecmp(asset->vcodec, QUICKTIME_DVSD) ||
163 !strcasecmp(asset->vcodec, QUICKTIME_DVCP))
165 // printf("AF: %i, AH: %i, VC: %s\n", asset->format, asset->height, asset->vcodec);
166 if (asset->format == FILE_AVI)
167 strcpy (asset->vcodec, QUICKTIME_DVSD);
168 else if (asset->format == FILE_MOV && asset->height == 576)
169 strcpy (asset->vcodec, QUICKTIME_DVCP);
170 else if (asset->format == FILE_MOV && asset->height == 480)
171 strcpy (asset->vcodec, QUICKTIME_DV);
175 int FileMOV::check_codec_params(Asset *asset)
177 if(!strcasecmp(asset->vcodec, QUICKTIME_DV) ||
178 !strcasecmp(asset->vcodec, QUICKTIME_DVSD) ||
179 !strcasecmp(asset->vcodec, QUICKTIME_DVCP))
181 if (!(asset->height == 576 && asset->width == 720) &&
182 !(asset->height == 480 && asset->width == 720))
184 eprintf("DV in Quicktime container does not support following resolution: %ix%i\n"
185 "Allowed resolutions are 720x576 (PAL) and 720x480 (NTSC)\n",
186 asset->width, asset->height);
194 int FileMOV::check_sig(Asset *asset)
196 int result = quicktime_check_sig(asset->path);
197 if(result == 2) result = 0;
201 int FileMOV::reset_parameters_derived()
205 quicktime_atracks = 0;
206 quicktime_vtracks = 0;
209 frames_correction = 0;
210 samples_correction = 0;
217 // Just create the Quicktime objects since this routine is also called
219 int FileMOV::open_file(int rd, int wr)
222 if(suffix_number == 0) strcpy(prefix_path, asset->path);
224 if(!(fd = quicktime_open(asset->path, rd, wr)))
226 eprintf("Error while opening file \"%s\". \n%m\n", asset->path);
230 if( !strcmp(asset->vcodec, QUICKTIME_DIV3) )
232 quicktime_set_cpus(fd, file->cpus);
233 quicktime_set_cache_max(fd, file->preferences->cache_size);
234 //printf("FileMOV::open_file %d %d\n", __LINE__, file->preferences->cache_size);
236 if(rd) format_to_asset();
241 if (check_codec_params(asset))
245 // Set decoding parameter
246 quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking);
247 // Set timecode offset
248 quicktime_set_frame_start(fd, asset->tcstart);
253 int FileMOV::close_file()
255 //printf("FileMOV::close_file 1 %s\n", asset->path);
258 if(file->wr) quicktime_set_framerate(fd, asset->frame_rate);
262 //printf("FileMOV::close_file 1\n");
265 for(int i = 0; i < file->cpus; i++)
267 threads[i]->stop_encoding();
274 //printf("FileMOV::close_file 1\n");
275 threadframes.remove_all_objects();
280 for(int i = 0; i < asset->channels; i++)
281 delete [] temp_float[i];
282 delete [] temp_float;
285 //printf("FileMOV::close_file 1\n");
287 FileBase::close_file();
288 //printf("FileMOV::close_file 2\n");
292 void FileMOV::set_frame_start(int64_t offset)
294 quicktime_set_frame_start(fd, offset);
297 void FileMOV::asset_to_format()
303 // Fix up the Quicktime file.
304 quicktime_set_copyright(fd, _("Made with Cinelerra for Linux"));
305 quicktime_set_info(fd, "Quicktime for Linux");
307 if(asset->audio_data)
309 quicktime_atracks = quicktime_set_audio(fd,
314 quicktime_set_parameter(fd, "vorbis_vbr", &asset->vorbis_vbr);
315 quicktime_set_parameter(fd, "vorbis_min_bitrate", &asset->vorbis_min_bitrate);
316 quicktime_set_parameter(fd, "vorbis_bitrate", &asset->vorbis_bitrate);
317 quicktime_set_parameter(fd, "vorbis_max_bitrate", &asset->vorbis_max_bitrate);
318 quicktime_set_parameter(fd, "mp3_bitrate", &asset->mp3_bitrate);
319 quicktime_set_parameter(fd, "mp4a_bitrate", &asset->mp4a_bitrate);
322 if(asset->video_data)
325 // Set up the alpha channel compressors
326 if(!strcmp(asset->vcodec, MOV_RGBA))
328 strcpy(string, QUICKTIME_RAW);
332 if(!strcmp(asset->vcodec, MOV_PNGA))
334 strcpy(string, QUICKTIME_PNG);
338 if(!strcmp(asset->vcodec, QUICKTIME_YUVA4444))
340 strcpy(string, asset->vcodec);
345 strcpy(string, asset->vcodec);
350 quicktime_vtracks = quicktime_set_video(fd,
359 for(int i = 0; i < asset->layers; i++)
360 quicktime_set_depth(fd, depth, i);
362 quicktime_set_parameter(fd, "jpeg_quality", &asset->jpeg_quality);
364 // set the compression parameters if there are any
365 quicktime_set_parameter(fd, "divx_bitrate", &asset->divx_bitrate);
366 quicktime_set_parameter(fd, "divx_rc_period", &asset->divx_rc_period);
367 quicktime_set_parameter(fd, "divx_rc_reaction_ratio", &asset->divx_rc_reaction_ratio);
368 quicktime_set_parameter(fd, "divx_rc_reaction_period", &asset->divx_rc_reaction_period);
369 quicktime_set_parameter(fd, "divx_max_key_interval", &asset->divx_max_key_interval);
370 quicktime_set_parameter(fd, "divx_max_quantizer", &asset->divx_max_quantizer);
371 quicktime_set_parameter(fd, "divx_min_quantizer", &asset->divx_min_quantizer);
372 quicktime_set_parameter(fd, "divx_quantizer", &asset->divx_quantizer);
373 quicktime_set_parameter(fd, "divx_quality", &asset->divx_quality);
374 quicktime_set_parameter(fd, "divx_fix_bitrate", &asset->divx_fix_bitrate);
376 // printf("FileMOV::asset_to_format %d\n",
379 quicktime_set_parameter(fd, "ffmpeg_bitrate", &asset->ms_bitrate);
380 quicktime_set_parameter(fd, "ffmpeg_bitrate_tolerance", &asset->ms_bitrate_tolerance);
381 quicktime_set_parameter(fd, "ffmpeg_interlaced", &asset->ms_interlaced);
382 quicktime_set_parameter(fd, "ffmpeg_quantizer", &asset->ms_quantization);
383 quicktime_set_parameter(fd, "ffmpeg_gop_size", &asset->ms_gop_size);
384 quicktime_set_parameter(fd, "ffmpeg_fix_bitrate", &asset->ms_fix_bitrate);
386 quicktime_set_parameter(fd, "h264_bitrate", &asset->h264_bitrate);
387 quicktime_set_parameter(fd, "h264_quantizer", &asset->h264_quantizer);
388 quicktime_set_parameter(fd, "h264_fix_bitrate", &asset->h264_fix_bitrate);
393 if(file->wr && asset->format == FILE_AVI)
395 quicktime_set_avi(fd, 1);
400 void FileMOV::format_to_asset()
404 if(quicktime_is_avi(fd)) asset->format = FILE_AVI;
405 asset->audio_data = quicktime_has_audio(fd);
406 if(asset->audio_data)
409 int qt_tracks = quicktime_audio_tracks(fd);
410 for(int i = 0; i < qt_tracks; i++)
411 asset->channels += quicktime_track_channels(fd, i);
413 if(!asset->sample_rate)
414 asset->sample_rate = quicktime_sample_rate(fd, 0);
415 asset->bits = quicktime_audio_bits(fd, 0);
416 asset->audio_length = quicktime_audio_length(fd, 0);
417 strncpy(asset->acodec, quicktime_audio_compressor(fd, 0), 4);
420 // determine if the video can be read before declaring video data
421 if(quicktime_has_video(fd) && quicktime_supported_video(fd, 0))
422 asset->video_data = 1;
424 if(asset->video_data)
426 depth = quicktime_video_depth(fd, 0);
427 asset->layers = quicktime_video_tracks(fd);
428 asset->width = quicktime_video_width(fd, 0);
429 asset->height = quicktime_video_height(fd, 0);
430 asset->video_length = quicktime_video_length(fd, 0);
431 // Don't want a user configured frame rate to get destroyed
432 if(EQUIV(asset->frame_rate, 0))
433 asset->frame_rate = quicktime_frame_rate(fd, 0);
435 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
437 // If DV stream, get the timecode
438 // This should become part of libquicktime functionality... for all formats
439 if(match4(asset->vcodec, QUICKTIME_DV))
442 dv_decoder_t *tmp_decoder = dv_decoder_new(0,0,0);
443 VFrame *frame = new VFrame(0, 0, BC_COMPRESSED);
445 set_video_position(0);
446 if(dv_parse_header(tmp_decoder, frame->get_data()) > -1)
448 dv_parse_packs(tmp_decoder, frame->get_data());
449 dv_get_timestamp(tmp_decoder, tc);
450 // printf("Timestamp %s\n", tc);
452 float seconds = Units::text_to_seconds(tc,
453 1, // Use 1 as sample rate, doesn't matter
454 TIME_HMSF, asset->frame_rate, 0);
455 // Set tcstart if it hasn't been set yet, this is a bit problematic
456 // FIXME: The problem arises if file has nonzero tcstart and user
457 // manualy sets it to zero - every time project will load it will
459 if (asset->tcstart == 0)
460 asset->tcstart = int64_t(seconds * asset->frame_rate);
463 dv_decoder_free(tmp_decoder);
469 int64_t FileMOV::get_memory_usage()
473 int64_t result = quicktime_memory_usage(fd);
474 //printf("FileMOV::get_memory_usage 1 %d\n", result);
481 int FileMOV::colormodel_supported(int colormodel)
486 int FileMOV::get_best_colormodel(Asset *asset, int driver)
493 case PLAYBACK_X11_XV:
494 case PLAYBACK_ASYNCHRONOUS:
495 if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
496 if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422;
497 if(match4(asset->vcodec, QUICKTIME_2VUY)) return BC_YUV422;
498 if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
499 if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
500 if(match4(asset->vcodec, QUICKTIME_MJPG)) return BC_YUV422P;
501 if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
502 if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
503 if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
504 if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
505 if(match4(asset->vcodec, QUICKTIME_DVCP)) return BC_YUV422;
506 if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
507 if(match4(asset->vcodec, QUICKTIME_MP4V)) return BC_YUV420P;
508 if(match4(asset->vcodec, QUICKTIME_H263)) return BC_YUV420P;
509 if(match4(asset->vcodec, QUICKTIME_H264)) return BC_YUV420P;
510 if(match4(asset->vcodec, QUICKTIME_HV64)) return BC_YUV420P;
511 if(match4(asset->vcodec, QUICKTIME_DIV3) ||
512 match4(asset->vcodec, QUICKTIME_SVQ3)) return BC_YUV420P;
514 case PLAYBACK_X11_GL:
515 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
516 match4(asset->vcodec, QUICKTIME_YUV422) ||
517 match4(asset->vcodec, QUICKTIME_2VUY) ||
518 match4(asset->vcodec, QUICKTIME_JPEG) ||
519 match4(asset->vcodec, QUICKTIME_MJPA) ||
520 match4(asset->vcodec, QUICKTIME_MJPG) ||
521 match4(asset->vcodec, QUICKTIME_DV) ||
522 match4(asset->vcodec, QUICKTIME_DVCP) ||
523 match4(asset->vcodec, QUICKTIME_DVSD) ||
524 match4(asset->vcodec, QUICKTIME_HV60) ||
525 match4(asset->vcodec, QUICKTIME_DIVX) ||
526 match4(asset->vcodec, QUICKTIME_DVSD) ||
527 match4(asset->vcodec, QUICKTIME_MP4V) ||
528 match4(asset->vcodec, QUICKTIME_H263) ||
529 match4(asset->vcodec, QUICKTIME_H264) ||
530 match4(asset->vcodec, QUICKTIME_HV64) ||
531 match4(asset->vcodec, QUICKTIME_DIV3) ||
532 match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV888;
534 case PLAYBACK_DV1394:
535 case PLAYBACK_FIREWIRE:
536 if(match4(asset->vcodec, QUICKTIME_DV) ||
537 match4(asset->vcodec, QUICKTIME_DVSD) ||
538 match4(asset->vcodec, QUICKTIME_DVCP)) return BC_COMPRESSED;
543 if(match4(asset->vcodec, QUICKTIME_MJPA))
544 return BC_COMPRESSED;
550 if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
552 if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
554 if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
556 if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
558 if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
560 if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
562 if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
564 if(!strncasecmp(asset->vcodec, QUICKTIME_H263, 4)) return BC_YUV420P;
566 if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
568 if(!strncasecmp(asset->vcodec, QUICKTIME_MP4V, 4)) return BC_YUV422P;
573 case VIDEO4LINUX2JPEG:
574 if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4))
575 return BC_COMPRESSED;
580 case CAPTURE_JPEG_WEBCAM:
581 return BC_COMPRESSED;
584 case CAPTURE_YUYV_WEBCAM:
588 case CAPTURE_FIREWIRE:
589 case CAPTURE_IEC61883:
590 if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4) ||
591 !strncasecmp(asset->vcodec, QUICKTIME_DVSD, 4) ||
592 !strncasecmp(asset->vcodec, QUICKTIME_DVCP, 4))
593 return BC_COMPRESSED;
598 case VIDEO4LINUX2MPEG:
605 int FileMOV::can_copy_from(Edit *edit, int64_t position)
608 Indexable *source = edit->get_source();
609 if( !source->is_asset ) return 0;
610 Asset *asset = (Asset *)source;
612 //printf("FileMOV::can_copy_from 1 %d %s %s\n", asset->format, asset->vcodec, this->asset->vcodec);
613 if(asset->format == FILE_JPEG_LIST &&
614 match4(this->asset->vcodec, QUICKTIME_JPEG))
617 if((asset->format == FILE_MOV ||
618 asset->format == FILE_AVI))
620 //printf("FileMOV::can_copy_from %s %s\n", asset->vcodec, this->asset->vcodec);
621 if(match4(asset->vcodec, this->asset->vcodec))
623 // there are combinations where the same codec has multiple fourcc codes
627 if (match4(asset->vcodec, QUICKTIME_DV) ||
628 match4(asset->vcodec, QUICKTIME_DVSD) ||
629 match4(asset->vcodec, QUICKTIME_DVCP))
631 if (match4(this->asset->vcodec, QUICKTIME_DV) ||
632 match4(this->asset->vcodec, QUICKTIME_DVSD) ||
633 match4(this->asset->vcodec, QUICKTIME_DVCP))
635 if (is_this_dv && is_edit_dv)
639 if(edit->asset->format == FILE_RAWDV)
641 if(match4(this->asset->vcodec, QUICKTIME_DV) ||
642 match4(this->asset->vcodec, QUICKTIME_DVSD) ||
643 match4(this->asset->vcodec, QUICKTIME_DVCP))
651 int64_t FileMOV::get_audio_length()
654 int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
659 int FileMOV::set_audio_position(int64_t x)
662 // quicktime sets positions for each track seperately so store position in audio_position
663 if(x >= 0 && x < asset->audio_length)
664 return quicktime_set_audio_position(fd, x, 0);
669 int FileMOV::set_video_position(int64_t x)
672 if(x >= 0 && x < asset->video_length)
674 int result = quicktime_set_video_position(fd, x, file->current_layer);
681 void FileMOV::new_audio_temp(int64_t len)
683 if(temp_allocated && temp_allocated < len)
685 for(int i = 0; i < asset->channels; i++)
686 delete [] temp_float[i];
687 delete [] temp_float;
693 temp_allocated = len;
694 temp_float = new float*[asset->channels];
695 for(int i = 0; i < asset->channels; i++)
696 temp_float[i] = new float[len];
702 int FileMOV::write_samples(double **buffer, int64_t len)
710 if(quicktime_supported_audio(fd, 0))
712 // Use Quicktime's compressor. (Always used)
713 // Allocate temp buffer
716 // Copy to float buffer
717 for(i = 0; i < asset->channels; i++)
719 for(j = 0; j < len; j++)
721 temp_float[i][j] = buffer[i][j];
725 // Because of the way Quicktime's compressors work we want to limit the chunk
726 // size to speed up decompression.
728 channel_ptr = new float*[asset->channels];
730 for(j = 0; j < len && !result; )
732 chunk_size = asset->sample_rate;
733 if(j + chunk_size > len) chunk_size = len - j;
735 for(i = 0; i < asset->channels; i++)
737 channel_ptr[i] = &temp_float[i][j];
740 result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
741 j += asset->sample_rate;
744 delete [] channel_ptr;
749 int FileMOV::write_frames(VFrame ***frames, int len)
751 int i, j, result = 0;
752 int default_compressor = 1;
754 if(debug) printf("FileMOV::write_frames %d\n", __LINE__);
756 if(debug) printf("FileMOV::write_frames %d layers=%d\n", __LINE__, asset->layers);
758 for(i = 0; i < asset->layers && !result; i++)
762 if(debug) printf("FileMOV::write_frames %d colormodel=%d size=" _LD "\n",
763 __LINE__, frames[i][0]->get_color_model(), frames[i][0]->get_compressed_size());
767 // Fix direct copy cases for format conversions.
768 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
770 if(debug) printf("FileMOV::write_frames %d len=%d\n", __LINE__, len);
771 default_compressor = 0;
772 for(j = 0; j < len && !result; j++)
774 VFrame *frame = frames[i][j];
777 if(debug) printf("FileMOV::write_frames %d %d colormodel=%d size=%d %02x %02x %02x %02x %02x %02x %02x %02x\n",
780 (int)frame->get_color_model(),
781 (int)frame->get_compressed_size(),
782 frames[i][j]->get_data()[0],
783 frames[i][j]->get_data()[1],
784 frames[i][j]->get_data()[2],
785 frames[i][j]->get_data()[3],
786 frames[i][j]->get_data()[4],
787 frames[i][j]->get_data()[5],
788 frames[i][j]->get_data()[6],
789 frames[i][j]->get_data()[7]);
791 // Special handling for DIVX
792 // Determine keyframe status.
793 // Write VOL header in the first frame if none exists
794 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
795 !strcmp(asset->vcodec, QUICKTIME_H263) ||
796 !strcmp(asset->vcodec, QUICKTIME_HV60))
798 if(quicktime_mpeg4_is_key(frame->get_data(),
799 frame->get_compressed_size(),
801 quicktime_insert_keyframe(fd, file->current_frame + j, i);
805 if(!(file->current_frame + j) &&
806 !quicktime_mpeg4_has_vol(frame->get_data()))
808 VFrame *temp_frame = new VFrame;
810 temp_frame->allocate_compressed_data(frame->get_compressed_size() +
812 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
817 memcpy(temp_frame->get_data() + bytes,
819 frame->get_compressed_size());
820 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
822 result = quicktime_write_frame(fd,
823 temp_frame->get_data(),
824 temp_frame->get_compressed_size(),
833 result = quicktime_write_frame(fd,
835 frame->get_compressed_size(),
840 // Determine keyframe status
841 if(!strcmp(asset->vcodec, QUICKTIME_H264) ||
842 !strcmp(asset->vcodec, QUICKTIME_HV64) ||
843 !strcmp(asset->vcodec, QUICKTIME_MP4V))
845 if(frame->get_keyframe() || file->current_frame + j == 0)
846 quicktime_insert_keyframe(fd, file->current_frame + j, i);
849 if(debug) printf("FileMOV::write_frames %d result=%d data=%p size=%ld\n",
853 frame->get_compressed_size());
854 result = quicktime_write_frame(fd,
856 frame->get_compressed_size(),
859 if(debug) printf("FileMOV::write_frames %d result=%d\n", __LINE__, result);
862 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
864 if(quicktime_mpeg4_is_key(frame->get_data(),
865 frame->get_compressed_size(),
867 quicktime_insert_keyframe(fd, file->current_frame + j, i);
868 result = quicktime_write_frame(fd,
870 frame->get_compressed_size(),
874 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
878 // Create extra space for markers
879 if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
880 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
882 unsigned char *data = frame->get_data();
883 long data_size = frame->get_compressed_size();
884 long data_allocated = frame->get_compressed_allocated();
886 // Sometimes get 0 length frames
889 if(asset->format == FILE_MOV)
891 mjpeg_insert_quicktime_markers(&data,
899 mjpeg_insert_avi_markers(&data,
905 frame->set_compressed_size(data_size);
906 result = quicktime_write_frame(fd,
908 frame->get_compressed_size(),
912 printf("FileMOV::write_frames data_size=%ld\n", data_size);
915 result = quicktime_write_frame(fd,
917 frame->get_compressed_size(),
920 if(debug) printf("FileMOV::write_frames %d result=%d\n", __LINE__, result);
923 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
924 match4(asset->vcodec, QUICKTIME_2VUY) ||
925 match4(asset->vcodec, QUICKTIME_YUV422) ||
926 match4(asset->vcodec, QUICKTIME_RAW))
928 // Direct copy planes where possible
929 default_compressor = 0;
930 for(j = 0; j < len && !result; j++)
932 VFrame *frame = frames[i][j];
933 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
934 quicktime_set_cmodel(fd, frame->get_color_model());
935 if(cmodel_is_planar(frame->get_color_model()))
937 unsigned char *planes[3];
938 planes[0] = frame->get_y();
939 planes[1] = frame->get_u();
940 planes[2] = frame->get_v();
941 result = quicktime_encode_video(fd, planes, i);
945 result = quicktime_encode_video(fd, frame->get_rows(), i);
946 //printf("FileMOV::write_frames 2 %d\n", result);
948 //printf("FileMOV::write_frames 2\n");
953 (match4(asset->vcodec, QUICKTIME_JPEG) ||
954 match4(asset->vcodec, QUICKTIME_MJPA)))
956 default_compressor = 0;
957 // Compress symmetrically on an SMP system.
958 ThreadStruct *threadframe;
959 int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
961 // Set up threads for symmetric compression.
964 threads = new FileMOVThread*[file->cpus];
965 for(j = 0; j < file->cpus; j++)
967 threads[j] = new FileMOVThread(this, fields);
968 threads[j]->start_encoding();
972 // Set up the frame structures for asynchronous compression.
973 // The mjpeg object must exist in each threadframe because it is where the output
975 while(threadframes.total < len)
977 threadframes.append(threadframe = new ThreadStruct);
980 // Load thread frame structures with new frames.
981 for(j = 0; j < len; j++)
983 VFrame *frame = frames[i][j];
984 threadframes.values[j]->input = frame;
985 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
987 total_threadframes = len;
988 current_threadframe = 0;
990 // Start the threads compressing
991 for(j = 0; j < file->cpus; j++)
993 threads[j]->encode_buffer();
997 // Write the frames as they're finished
998 for(j = 0; j < len; j++)
1000 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
1001 threadframes.values[j]->completion_lock->unlock();
1004 result = quicktime_write_frame(fd,
1005 threadframes.values[j]->output,
1006 threadframes.values[j]->output_size,
1012 if(default_compressor)
1014 //printf("FileMOV::write_frames 3\n");
1015 // Use the library's built in compressor.
1016 for(j = 0; j < len && !result; j++)
1018 //printf("FileMOV::write_frames 4\n");
1019 VFrame *frame = frames[i][j];
1020 quicktime_set_cmodel(fd, frame->get_color_model());
1021 //printf("FileMOV::write_frames 5\n");
1022 if(cmodel_is_planar(frame->get_color_model()))
1024 unsigned char *planes[3];
1025 planes[0] = frame->get_y();
1026 planes[1] = frame->get_u();
1027 planes[2] = frame->get_v();
1028 result = quicktime_encode_video(fd, planes, i);
1032 if(debug) printf("FileMOV::write_frames 1\n");
1033 result = quicktime_encode_video(fd, frame->get_rows(), i);
1034 if(debug) printf("FileMOV::write_frames 10\n");
1038 //printf("FileMOV::write_frames 4\n");
1047 int FileMOV::read_frame(VFrame *frame)
1051 const int debug = 0;
1053 if(debug) printf("FileMOV::read_frame %d frame=" _LD " color_model=%d\n",
1054 __LINE__, file->current_frame, frame->get_color_model());
1055 switch(frame->get_color_model())
1058 frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
1059 frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
1060 frame->set_keyframe((quicktime_get_keyframe_before(fd,
1061 file->current_frame,
1062 file->current_layer) == file->current_frame));
1063 // printf("FileMOV::read_frame 1 " _LD " %d %p %d\n",
1064 // file->current_frame,
1065 // frame->get_keyframe(),
1066 // frame->get_data(),
1067 // frame->get_compressed_size());
1068 result = quicktime_read_frame(fd,
1070 file->current_layer);
1077 unsigned char *row_pointers[3];
1078 row_pointers[0] = frame->get_y();
1079 row_pointers[1] = frame->get_u();
1080 row_pointers[2] = frame->get_v();
1082 quicktime_set_cmodel(fd, frame->get_color_model());
1083 result = quicktime_decode_video(fd,
1085 file->current_layer);
1091 quicktime_set_cmodel(fd, frame->get_color_model());
1092 result = quicktime_decode_video(fd,
1094 file->current_layer);
1099 if(debug) printf("FileMOV::read_frame %d\n", __LINE__);
1101 printf("quicktime_read_frame/quicktime_decode_video failed, result:\n");
1108 int64_t FileMOV::compressed_frame_size()
1111 return quicktime_frame_size(fd, file->current_frame, file->current_layer);
1114 int FileMOV::read_compressed_frame(VFrame *buffer)
1119 result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
1120 buffer->set_compressed_size(result);
1121 buffer->set_keyframe((quicktime_get_keyframe_before(fd,
1122 file->current_frame,
1123 file->current_layer) == file->current_frame));
1128 int FileMOV::write_compressed_frame(VFrame *buffer)
1133 result = quicktime_write_frame(fd,
1135 buffer->get_compressed_size(),
1136 file->current_layer);
1142 int FileMOV::read_raw(VFrame *frame,
1143 float in_x1, float in_y1, float in_x2, float in_y2,
1144 float out_x1, float out_y1, float out_x2, float out_y2,
1145 int use_float, int interpolate)
1150 quicktime_set_video_position(fd, file->current_frame, file->current_layer);
1151 // Develop importing strategy
1152 switch(frame->get_color_model())
1155 result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
1159 case BC_RGBA16161616:
1163 case BC_YUVA16161616:
1165 eprintf("FileMOV::read_raw: unknown colormodel\n");
1172 int FileMOV::read_samples(double *buffer, int64_t len)
1176 if(quicktime_track_channels(fd, 0) > file->current_channel &&
1177 quicktime_supported_audio(fd, 0))
1180 //printf("FileMOV::read_samples 2 " _LD " " _LD "\n", file->current_sample, quicktime_audio_position(fd, 0));
1181 new_audio_temp(len);
1183 //printf("FileMOV::read_samples 3 " _LD " " _LD "\n", file->current_sample, quicktime_audio_position(fd, 0));
1184 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
1186 printf("quicktime_decode_audio failed\n");
1191 for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
1194 // if(file->current_channel == 0)
1195 // for(int i = 0; i < len; i++)
1198 // value = (int16_t)(temp_float[0][i] * 32767);
1199 // fwrite(&value, 2, 1, stdout);
1201 //printf("FileMOV::read_samples 4 " _LD " " _LD "\n", file->current_sample, quicktime_audio_position(fd, 0));
1208 const char* FileMOV::strtocompression(const char *string)
1210 if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
1211 if(!strcasecmp(string, _(H264_NAME))) return QUICKTIME_H264;
1212 if(!strcasecmp(string, _(HV64_NAME))) return QUICKTIME_HV64;
1213 if(!strcasecmp(string, _(MP4V_NAME))) return QUICKTIME_MP4V;
1214 if(!strcasecmp(string, _(H263_NAME))) return QUICKTIME_H263;
1215 if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
1216 if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
1217 // Students say QUICKTIME_DV is required for compression even though
1218 // QUICKTIME_DVSD is produced by other software
1219 // if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DVSD;
1220 if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
1221 if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
1222 if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
1223 if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
1224 if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
1225 if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
1226 if(!strcasecmp(string, _(QTMJPEGP_NAME))) return QUICKTIME_MJPG;
1227 if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
1228 if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
1229 if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
1230 if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
1231 if(!strcasecmp(string, _(TWOVUY_NAME))) return QUICKTIME_2VUY;
1232 if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
1233 if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
1234 if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
1236 if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
1237 if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
1238 if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
1239 if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
1240 if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
1241 if(!strcasecmp(string, _(MP4A_NAME))) return QUICKTIME_MP4A;
1242 if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
1246 return QUICKTIME_RAW;
1249 const char* FileMOV::compressiontostr(const char *string)
1251 if(match4(string, QUICKTIME_H263)) return _(H263_NAME);
1252 if(match4(string, QUICKTIME_H264)) return _(H264_NAME);
1253 if(match4(string, QUICKTIME_HV64)) return _(HV64_NAME);
1254 if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1255 if(match4(string, QUICKTIME_MP4V)) return _(MP4V_NAME);
1256 if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1257 if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1258 if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1259 if(match4(string, QUICKTIME_DVCP)) return _(DV_NAME);
1260 if(match4(string, QUICKTIME_DVSD)) return _(DV_NAME);
1261 if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1262 if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1263 if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1264 if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1265 if(match4(string, QUICKTIME_MJPG)) return _(QTMJPEGP_NAME);
1266 if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1267 if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1268 if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1269 if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1270 if(match4(string, QUICKTIME_2VUY)) return _(TWOVUY_NAME);
1271 if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1272 if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1273 if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1279 if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1280 if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1281 if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1282 if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1283 if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1284 if(match4(string, QUICKTIME_MP4A)) return _(MP4A_NAME);
1285 if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1289 return _("Unknown");
1296 ThreadStruct::ThreadStruct()
1300 output_allocated = 0;
1302 completion_lock = new Condition(1, "ThreadStruct::completion_lock");
1305 ThreadStruct::~ThreadStruct()
1307 if(output) delete [] output;
1308 delete completion_lock;
1311 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1313 if(output_allocated < mjpeg_output_size(mjpeg))
1320 output_allocated = mjpeg_output_size(mjpeg);
1321 output = new unsigned char[output_allocated];
1324 output_size = mjpeg_output_size(mjpeg);
1325 memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1329 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields)
1332 this->filemov = filemov;
1333 this->fields = fields;
1335 input_lock = new Condition(1, "FileMOVThread::input_lock");
1338 FileMOVThread::~FileMOVThread()
1343 int FileMOVThread::start_encoding()
1345 mjpeg = mjpeg_new(filemov->asset->width,
1346 filemov->asset->height,
1348 mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1349 mjpeg_set_float(mjpeg, 0);
1352 input_lock->lock("FileMOVThread::start_encoding");
1357 int FileMOVThread::stop_encoding()
1360 input_lock->unlock();
1362 if(mjpeg) mjpeg_delete(mjpeg);
1366 int FileMOVThread::encode_buffer()
1368 input_lock->unlock();
1372 void FileMOVThread::run()
1376 input_lock->lock("FileMOVThread::run");
1380 // Get a frame to compress.
1381 filemov->threadframe_lock->lock("FileMOVThread::stop_encoding");
1382 if(filemov->current_threadframe < filemov->total_threadframes)
1384 // Frame is available to process.
1385 input_lock->unlock();
1386 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1387 VFrame *frame = threadframe->input;
1389 filemov->current_threadframe++;
1390 filemov->threadframe_lock->unlock();
1392 mjpeg_compress(mjpeg,
1397 frame->get_color_model(),
1402 unsigned char *data = mjpeg_output_buffer(mjpeg);
1403 long data_size = mjpeg_output_size(mjpeg);
1404 long data_allocated = mjpeg_output_allocated(mjpeg);
1407 if(filemov->asset->format == FILE_MOV)
1409 mjpeg_insert_quicktime_markers(&data,
1417 mjpeg_insert_avi_markers(&data,
1423 mjpeg_set_output_size(mjpeg, data_size);
1425 threadframe->load_output(mjpeg);
1426 threadframe->completion_lock->unlock();
1429 filemov->threadframe_lock->unlock();
1439 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1440 : BC_Window(PROGRAM_NAME ": Audio Compression",
1441 parent_window->get_abs_cursor_x(1),
1442 parent_window->get_abs_cursor_y(1),
1446 this->parent_window = parent_window;
1447 this->asset = asset;
1448 compression_popup = 0;
1452 MOVConfigAudio::~MOVConfigAudio()
1454 lock_window("MOVConfigAudio::~MOVConfigAudio");
1455 if(compression_popup) delete compression_popup;
1456 if(bits_popup) delete bits_popup;
1457 compression_items.remove_all_objects();
1462 void MOVConfigAudio::reset()
1467 vorbis_min_bitrate = 0;
1469 vorbis_max_bitrate = 0;
1476 void MOVConfigAudio::create_objects()
1479 lock_window("MOVConfigAudio::create_objects");
1481 if(asset->format == FILE_MOV)
1483 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1484 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1485 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1486 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1487 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1488 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1489 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1493 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1494 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1495 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1496 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1499 add_tool(new BC_Title(x, y, _("Compression:")));
1501 compression_popup = new MOVConfigAudioPopup(this, x, y);
1502 compression_popup->create_objects();
1504 update_parameters();
1506 add_subwindow(new BC_OKButton(this));
1511 void MOVConfigAudio::update_parameters()
1514 if(bits_title) delete bits_title;
1515 if(bits_popup) delete bits_popup;
1516 if(dither) delete dither;
1517 if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1518 if(vorbis_bitrate) delete vorbis_bitrate;
1519 if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1520 if(vorbis_vbr) delete vorbis_vbr;
1521 if(mp3_bitrate) delete mp3_bitrate;
1522 delete mp4a_bitrate;
1523 delete mp4a_quantqual;
1529 if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1530 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1532 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1533 bits_popup = new BitsPopup(this,
1542 bits_popup->create_objects();
1544 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1547 if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1551 if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1553 mp3_bitrate = new MOVConfigAudioNum(this,
1557 &asset->mp3_bitrate);
1558 mp3_bitrate->set_increment(64000);
1559 mp3_bitrate->create_objects();
1562 if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1566 if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1568 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1569 _("Variable bitrate"),
1572 &asset->vorbis_vbr));
1574 vorbis_min_bitrate = new MOVConfigAudioNum(this,
1578 &asset->vorbis_min_bitrate);
1579 vorbis_min_bitrate->set_increment(1000);
1581 vorbis_bitrate = new MOVConfigAudioNum(this,
1585 &asset->vorbis_bitrate);
1586 vorbis_bitrate->set_increment(1000);
1588 vorbis_max_bitrate = new MOVConfigAudioNum(this,
1592 &asset->vorbis_max_bitrate);
1593 vorbis_max_bitrate->set_increment(1000);
1597 vorbis_min_bitrate->create_objects();
1598 vorbis_bitrate->create_objects();
1599 vorbis_max_bitrate->create_objects();
1602 if(!strcasecmp(asset->acodec, QUICKTIME_MP4A))
1604 mp4a_bitrate = new MOVConfigAudioNum(this,
1608 &asset->mp4a_bitrate);
1609 mp4a_bitrate->set_increment(64000);
1610 mp4a_bitrate->create_objects();
1613 mp4a_quantqual = new MOVConfigAudioNum(this,
1614 _("Quantization Quality (%):"),
1617 &asset->mp4a_quantqual);
1618 mp4a_quantqual->set_increment(1);
1619 mp4a_quantqual->create_objects();
1624 int MOVConfigAudio::close_event()
1634 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1639 : BC_CheckBox(x, y, *output, title_text)
1641 this->popup = popup;
1642 this->output = output;
1644 int MOVConfigAudioToggle::handle_event()
1646 *output = get_value();
1654 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1655 : BC_TumbleTextBox(popup,
1659 popup->get_w() - 150,
1663 this->popup = popup;
1664 this->title_text = title_text;
1665 this->output = output;
1670 MOVConfigAudioNum::~MOVConfigAudioNum()
1672 if(!popup->get_deleting()) delete title;
1675 void MOVConfigAudioNum::create_objects()
1677 popup->add_subwindow(title = new BC_Title(x, y, title_text));
1678 BC_TumbleTextBox::create_objects();
1681 int MOVConfigAudioNum::handle_event()
1683 *output = atol(get_text());
1694 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1695 : BC_PopupTextBox(popup,
1696 &popup->compression_items,
1697 FileMOV::compressiontostr(popup->asset->acodec),
1703 this->popup = popup;
1706 int MOVConfigAudioPopup::handle_event()
1708 strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1709 popup->update_parameters();
1729 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window,
1731 const char *locked_compressor)
1732 : BC_Window(PROGRAM_NAME ": Video Compression",
1733 parent_window->get_abs_cursor_x(1),
1734 parent_window->get_abs_cursor_y(1),
1738 this->parent_window = parent_window;
1739 this->asset = asset;
1740 this->locked_compressor = locked_compressor;
1741 compression_popup = 0;
1746 MOVConfigVideo::~MOVConfigVideo()
1748 lock_window("MOVConfigVideo::~MOVConfigVideo");
1749 if(compression_popup) delete compression_popup;
1750 compression_items.remove_all_objects();
1754 void MOVConfigVideo::create_objects()
1757 lock_window("MOVConfigVideo::create_objects");
1759 if(asset->format == FILE_MOV)
1761 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1762 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1763 // compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1764 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1765 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1766 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1767 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1768 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1769 compression_items.append(new BC_ListBoxItem(_(QTMJPEGP_NAME)));
1770 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1771 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1772 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1773 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1774 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1775 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1776 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1777 compression_items.append(new BC_ListBoxItem(_(TWOVUY_NAME)));
1778 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1779 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1780 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1784 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1785 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1786 // compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1787 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1788 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1789 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1790 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1791 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1792 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1793 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1796 add_subwindow(new BC_Title(x, y, _("Compression:")));
1799 if(!locked_compressor)
1801 compression_popup = new MOVConfigVideoPopup(this, x, y);
1802 compression_popup->create_objects();
1806 add_subwindow(new BC_Title(x,
1808 FileMOV::compressiontostr(locked_compressor),
1817 update_parameters();
1819 add_subwindow(new BC_OKButton(this));
1824 int MOVConfigVideo::close_event()
1831 void MOVConfigVideo::reset()
1834 jpeg_quality_title = 0;
1838 divx_rc_reaction_ratio = 0;
1839 divx_rc_reaction_period = 0;
1840 divx_max_key_interval = 0;
1841 divx_max_quantizer = 0;
1842 divx_min_quantizer = 0;
1845 divx_fix_bitrate = 0;
1850 h264_fix_bitrate = 0;
1854 ms_bitrate_tolerance = 0;
1855 ms_quantization = 0;
1862 void MOVConfigVideo::update_parameters()
1866 delete jpeg_quality_title;
1867 delete jpeg_quality;
1870 if(divx_bitrate) delete divx_bitrate;
1871 if(divx_rc_period) delete divx_rc_period;
1872 if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1873 if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1874 if(divx_max_key_interval) delete divx_max_key_interval;
1875 if(divx_max_quantizer) delete divx_max_quantizer;
1876 if(divx_min_quantizer) delete divx_min_quantizer;
1877 if(divx_quantizer) delete divx_quantizer;
1878 if(divx_quality) delete divx_quality;
1879 if(divx_fix_quant) delete divx_fix_quant;
1880 if(divx_fix_bitrate) delete divx_fix_bitrate;
1882 if(ms_bitrate) delete ms_bitrate;
1883 if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1884 if(ms_interlaced) delete ms_interlaced;
1885 if(ms_quantization) delete ms_quantization;
1886 if(ms_gop_size) delete ms_gop_size;
1887 if(ms_fix_bitrate) delete ms_fix_bitrate;
1888 if(ms_fix_quant) delete ms_fix_quant;
1890 delete h264_bitrate;
1891 delete h264_quantizer;
1892 delete h264_fix_bitrate;
1893 delete h264_fix_quant;
1898 const char *vcodec = asset->vcodec;
1899 if(locked_compressor) vcodec = locked_compressor;
1903 if(!strcmp(vcodec, QUICKTIME_H264) ||
1904 !strcmp(vcodec, QUICKTIME_HV64))
1906 int x = param_x, y = param_y;
1907 h264_bitrate = new MOVConfigVideoNum(this,
1911 &asset->h264_bitrate);
1912 h264_bitrate->set_increment(1000000);
1913 h264_bitrate->create_objects();
1914 add_subwindow(h264_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260,
1916 &asset->h264_fix_bitrate,
1919 h264_quantizer = new MOVConfigVideoNum(this,
1925 &asset->h264_quantizer);
1926 h264_quantizer->create_objects();
1927 add_subwindow(h264_fix_quant = new MOVConfigVideoFixQuant(x + 260,
1929 &asset->h264_fix_bitrate,
1931 h264_fix_bitrate->opposite = h264_fix_quant;
1932 h264_fix_quant->opposite = h264_fix_bitrate;
1935 // ffmpeg parameters
1936 if(!strcmp(vcodec, QUICKTIME_MP4V) ||
1937 !strcmp(vcodec, QUICKTIME_DIV3))
1939 int x = param_x, y = param_y;
1940 ms_bitrate = new MOVConfigVideoNum(this,
1944 &asset->ms_bitrate);
1945 ms_bitrate->set_increment(1000000);
1946 ms_bitrate->create_objects();
1947 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260,
1949 &asset->ms_fix_bitrate,
1953 ms_bitrate_tolerance = new MOVConfigVideoNum(this,
1954 _("Bitrate tolerance:"),
1957 &asset->ms_bitrate_tolerance);
1958 ms_bitrate_tolerance->create_objects();
1963 ms_quantization = new MOVConfigVideoNum(this,
1967 &asset->ms_quantization);
1968 ms_quantization->create_objects();
1969 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260,
1971 &asset->ms_fix_bitrate,
1973 ms_fix_bitrate->opposite = ms_fix_quant;
1974 ms_fix_quant->opposite = ms_fix_bitrate;
1978 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"),
1981 &asset->ms_interlaced));
1983 ms_gop_size = new MOVConfigVideoNum(this,
1984 _("Keyframe interval:"),
1987 &asset->ms_gop_size);
1988 ms_gop_size->create_objects();
1991 // OpenDivx parameters
1992 if(!strcmp(vcodec, QUICKTIME_DIVX) ||
1993 !strcmp(vcodec, QUICKTIME_H263) ||
1994 !strcmp(vcodec, QUICKTIME_HV60))
1996 int x = param_x, y = param_y;
1997 divx_bitrate = new MOVConfigVideoNum(this,
2001 &asset->divx_bitrate);
2002 divx_bitrate->set_increment(1000000);
2003 divx_bitrate->create_objects();
2004 add_subwindow(divx_fix_bitrate =
2005 new MOVConfigVideoFixBitrate(x + 260,
2007 &asset->divx_fix_bitrate,
2010 divx_quantizer = new MOVConfigVideoNum(this,
2014 &asset->divx_quantizer);
2015 divx_quantizer->create_objects();
2016 add_subwindow(divx_fix_quant =
2017 new MOVConfigVideoFixQuant(x + 260,
2019 &asset->divx_fix_bitrate,
2021 divx_fix_quant->opposite = divx_fix_bitrate;
2022 divx_fix_bitrate->opposite = divx_fix_quant;
2024 divx_rc_period = new MOVConfigVideoNum(this,
2028 &asset->divx_rc_period);
2029 divx_rc_period->create_objects();
2031 divx_rc_reaction_ratio = new MOVConfigVideoNum(this,
2032 _("Reaction Ratio:"),
2035 &asset->divx_rc_reaction_ratio);
2036 divx_rc_reaction_ratio->create_objects();
2038 divx_rc_reaction_period = new MOVConfigVideoNum(this,
2039 _("Reaction Period:"),
2042 &asset->divx_rc_reaction_period);
2043 divx_rc_reaction_period->create_objects();
2045 divx_max_key_interval = new MOVConfigVideoNum(this,
2046 _("Max Key Interval:"),
2049 &asset->divx_max_key_interval);
2050 divx_max_key_interval->create_objects();
2052 divx_max_quantizer = new MOVConfigVideoNum(this,
2053 _("Max Quantizer:"),
2056 &asset->divx_max_quantizer);
2057 divx_max_quantizer->create_objects();
2059 divx_min_quantizer = new MOVConfigVideoNum(this,
2060 _("Min Quantizer:"),
2063 &asset->divx_min_quantizer);
2064 divx_min_quantizer->create_objects();
2066 divx_quality = new MOVConfigVideoNum(this,
2070 &asset->divx_quality);
2071 divx_quality->create_objects();
2074 if(!strcmp(vcodec, QUICKTIME_JPEG) ||
2075 !strcmp(vcodec, QUICKTIME_MJPA))
2077 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
2078 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80,
2085 asset->jpeg_quality,
2088 &asset->jpeg_quality));
2097 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
2098 : BC_TumbleTextBox(popup,
2106 this->popup = popup;
2107 this->title_text = title_text;
2108 this->output = output;
2113 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup,
2120 : BC_TumbleTextBox(popup,
2128 this->popup = popup;
2129 this->title_text = title_text;
2130 this->output = output;
2135 MOVConfigVideoNum::~MOVConfigVideoNum()
2137 if(!popup->get_deleting()) delete title;
2140 void MOVConfigVideoNum::create_objects()
2142 popup->add_subwindow(title = new BC_Title(x, y, title_text));
2143 BC_TumbleTextBox::create_objects();
2146 int MOVConfigVideoNum::handle_event()
2148 *output = atol(get_text());
2158 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
2159 : BC_CheckBox(x, y, *output, title_text)
2161 this->output = output;
2164 int MOVConfigVideoCheckBox::handle_event()
2166 *output = get_value();
2175 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x,
2184 this->output = output;
2185 this->value = value;
2188 int MOVConfigVideoFixBitrate::handle_event()
2191 opposite->update(0);
2200 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x,
2207 _("Fix quantization"))
2209 this->output = output;
2210 this->value = value;
2213 int MOVConfigVideoFixQuant::handle_event()
2216 opposite->update(0);
2224 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
2225 : BC_PopupTextBox(popup,
2226 &popup->compression_items,
2227 FileMOV::compressiontostr(popup->asset->vcodec),
2233 this->popup = popup;
2236 int MOVConfigVideoPopup::handle_event()
2238 strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
2239 popup->update_parameters();