r753: Add raise_window() commands when making various windows
[cinelerra_cv/mob.git] / cinelerra / filemov.C
blobe31b5afe6847e48952ad089112e8a20b5d6878cb
1 #include "asset.h"
2 #include "bcsignals.h"
3 #include "bitspopup.h"
4 #include "byteorder.h"
5 #include "condition.h"
6 #include "edit.h"
7 #include "file.h"
8 #include "filemov.h"
9 #include "guicast.h"
10 #include "language.h"
11 #include "mwindow.inc"
12 #include "vframe.h"
13 #include "videodevice.inc"
15 #include <unistd.h>
16 #include <libdv/dv.h>
18 #if 0
19 N_("MPEG-4")
20 N_("Dual H.264")
21 N_("Dual MPEG-4")
22 N_("H.264")
23 N_("H.263")
24 N_("Microsoft MPEG-4")
25 N_("DV")
26 N_("PNG")
27 N_("PNG with Alpha")
28 N_("Uncompressed RGB")
29 N_("Uncompressed RGBA")
30 N_("YUV 4:2:0 Planar")
31 N_("Component Video")
32 N_("YUV 4:1:1 Packed")
33 N_("Component Y'CbCr 8-bit 4:4:4")
34 N_("Component Y'CbCrA 8-bit 4:4:4:4")
35 N_("Component Y'CbCr 10-bit 4:4:4")
36 N_("JPEG Photo")
37 N_("Motion JPEG A")
40 N_("Twos complement")
41 N_("Unsigned")
42 N_("IMA-4")
43 N_("U-Law")
44 N_("Vorbis")
45 N_("MP3")
46 N_("MPEG-4 Audio")
47 #endif
49 #define DIVX_NAME "MPEG-4"
50 #define HV64_NAME "Dual H.264"
51 #define MP4V_NAME "MPEG-4 Video"
52 #define H264_NAME "H.264"
53 #define H263_NAME "H.263"
54 #define HV60_NAME "Dual MPEG-4"
55 #define DIV3_NAME "Microsoft MPEG-4"
56 #define DV_NAME "DV"
57 #define PNG_NAME "PNG"
58 #define PNGA_NAME "PNG with Alpha"
59 #define RGB_NAME "Uncompressed RGB"
60 #define RGBA_NAME "Uncompressed RGBA"
61 #define YUV420_NAME "YUV 4:2:0 Planar"
62 #define YUV422_NAME "Component Video"
63 #define YUV411_NAME "YUV 4:1:1 Packed"
64 #define YUV444_NAME "Component Y'CbCr 8-bit 4:4:4"
65 #define YUVA4444_NAME "Component Y'CbCrA 8-bit 4:4:4:4"
66 #define YUV444_10BIT_NAME "Component Y'CbCr 10-bit 4:4:4"
67 #define QTJPEG_NAME "JPEG Photo"
68 #define MJPA_NAME "Motion JPEG A"
70 #define TWOS_NAME "Twos complement"
71 #define RAW_NAME "Unsigned"
72 #define IMA4_NAME "IMA-4"
73 #define ULAW_NAME "U-Law"
74 //#define VORBIS_NAME "Vorbis"
75 #define MP3_NAME "MP3"
76 #define MP4A_NAME "MPEG-4 Audio"
77 #define VORBIS_NAME "OGG Vorbis"
83 FileMOV::FileMOV(Asset *asset, File *file)
84  : FileBase(asset, file)
86         reset_parameters();
87         if(asset->format == FILE_UNKNOWN)
88                 asset->format = FILE_MOV;
89         asset->byte_order = 0;
90         suffix_number = 0;
91         threadframe_lock = new Mutex("FileMOV::threadframe_lock");
94 FileMOV::~FileMOV()
96         close_file();
97         delete threadframe_lock;
100 void FileMOV::get_parameters(BC_WindowBase *parent_window, 
101         Asset *asset, 
102         BC_WindowBase* &format_window,
103         int audio_options,
104         int video_options,
105         int lock_compressor)
107         fix_codecs(asset);
108         if(audio_options)
109         {
110                 MOVConfigAudio *window = new MOVConfigAudio(parent_window, asset);
111                 format_window = window;
112                 window->create_objects();
113                 window->run_window();
114                 delete window;
115         }
116         else
117         if(video_options)
118         {
119                 MOVConfigVideo *window = new MOVConfigVideo(parent_window, 
120                         asset, 
121                         lock_compressor);
122                 format_window = window;
123                 window->create_objects();
124                 window->run_window();
125                 delete window;
126         }
129 void FileMOV::fix_codecs(Asset *asset)
131 //      if(asset->format == FILE_MOV)
132 //      {
133 //              if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
134 //                      strcpy(asset->acodec, QUICKTIME_TWOS);
135 //      }
136 //      else
137 //      {
138 //              if(strcasecmp(asset->vcodec, QUICKTIME_DIV3))
139 //              {
140 //                      strcpy(asset->vcodec, QUICKTIME_DIV3);
141 //              }
142 //              strcpy(asset->acodec, QUICKTIME_MP3);
143 //      }
146 int FileMOV::check_sig(Asset *asset)
148         return quicktime_check_sig(asset->path);
152 int FileMOV::reset_parameters_derived()
154         fd = 0;
155         prev_track = 0;
156         quicktime_atracks = 0;
157         quicktime_vtracks = 0;
158         depth = 24;
159         threads = 0;
160         frames_correction = 0;
161         samples_correction = 0;
162         temp_float = 0;
163         temp_allocated = 0;
167 // Just create the Quicktime objects since this routine is also called
168 // for reopening.
169 int FileMOV::open_file(int rd, int wr)
172         this->rd = rd;
173         this->wr = wr;
175         if(suffix_number == 0) strcpy(prefix_path, asset->path);
177         if(!(fd = quicktime_open(asset->path, rd, wr)))
178         {
179                 printf(_("FileMOV::open_file %s: No such file or directory\n"), asset->path);
180                 return 1;
181         }
183         quicktime_set_cpus(fd, file->cpus);
185         if(rd)
186         {
187                 format_to_asset();
188                 
189                 // If DV stream, get the timecode
190                 if(match4(asset->vcodec, QUICKTIME_DV))
191                 {
192                         char tc[12];
193                         dv_decoder_t *tmp_decoder = dv_decoder_new(0,0,0);
194                         VFrame *frame = new VFrame(0, 0, 0, BC_COMPRESSED);
195                         
196                         read_frame(frame);
197                         set_video_position(0);
198                         
199                         if(dv_parse_header(tmp_decoder, frame->get_data()) > -1)
200                         {
201                                 dv_parse_packs(tmp_decoder, frame->get_data());
202                                 dv_get_timestamp(tmp_decoder, tc);
203                                 printf("Timestamp %s\n", tc);
204                         
205                                 float seconds = Units::text_to_seconds(tc,
206                                                                                 1, // Use 1 as sample rate, doesn't matter
207                                                                                 TIME_HMSF,
208                                                                                 tmp_decoder->height == 576 ? 25 : 30, // FIXME
209                                                                                 0);
210                                 // Get frame number
211                                 asset->tcstart = int64_t(seconds * (tmp_decoder->height == 576 ? 25 : 30));
212                         }
213                         
214                 }
215         }
217         if(wr) asset_to_format();
219 // Set decoding parameter
220         quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking);
222 // Set timecode offset
223         quicktime_set_frame_start(fd, asset->tcstart);
225         return 0;
228 int FileMOV::close_file()
230 //printf("FileMOV::close_file 1 %s\n", asset->path);
231         if(fd)
232         {
233                 if(wr) quicktime_set_framerate(fd, asset->frame_rate);
234                 quicktime_close(fd);
235         }
237 //printf("FileMOV::close_file 1\n");
238         if(threads)
239         {
240                 for(int i = 0; i < file->cpus; i++)
241                 {
242                         threads[i]->stop_encoding();
243                         delete threads[i];
244                 }
245                 delete [] threads;
246                 threads = 0;
247         }
249 //printf("FileMOV::close_file 1\n");
250         threadframes.remove_all_objects();
253         if(temp_float) 
254         {
255                 for(int i = 0; i < asset->channels; i++)
256                         delete [] temp_float[i];
257                 delete [] temp_float;
258         }
260 //printf("FileMOV::close_file 1\n");
261         reset_parameters();
262         FileBase::close_file();
263 //printf("FileMOV::close_file 2\n");
264         return 0;
267 void FileMOV::set_frame_start(int64_t offset)
269         quicktime_set_frame_start(fd, offset);
272 void FileMOV::asset_to_format()
274         if(!fd) return;
275         char audio_codec[5];
277         fix_codecs(asset);
279 // Fix up the Quicktime file.
280         quicktime_set_copyright(fd, _("Made with Cinelerra for Linux"));
281         quicktime_set_info(fd, "Quicktime for Linux");
283         if(asset->audio_data)
284         {
285                 quicktime_atracks = quicktime_set_audio(fd, 
286                                 asset->channels, 
287                                 asset->sample_rate, 
288                                 asset->bits, 
289                                 asset->acodec);
290                 quicktime_set_parameter(fd, "vorbis_vbr", &asset->vorbis_vbr);
291                 quicktime_set_parameter(fd, "vorbis_min_bitrate", &asset->vorbis_min_bitrate);
292                 quicktime_set_parameter(fd, "vorbis_bitrate", &asset->vorbis_bitrate);
293                 quicktime_set_parameter(fd, "vorbis_max_bitrate", &asset->vorbis_max_bitrate);
294                 quicktime_set_parameter(fd, "mp3_bitrate", &asset->mp3_bitrate);
295                 quicktime_set_parameter(fd, "mp4a_bitrate", &asset->mp4a_bitrate);
296         }
298         if(asset->video_data)
299         {
300                 char string[16];
301 // Set up the alpha channel compressors
302                 if(!strcmp(asset->vcodec, MOV_RGBA))
303                 {
304                         strcpy(string, QUICKTIME_RAW);
305                         depth = 32;
306                 }
307                 else
308                 if(!strcmp(asset->vcodec, MOV_PNGA))
309                 {
310                         strcpy(string, QUICKTIME_PNG);
311                         depth = 32;
312                 }
313                 else
314                 if(!strcmp(asset->vcodec, QUICKTIME_YUVA4444))
315                 {
316                         strcpy(string, asset->vcodec);
317                         depth = 32;
318                 }
319                 else
320                 {
321                         strcpy(string, asset->vcodec);
322                         depth = 24;
323                 }
325                 quicktime_vtracks = quicktime_set_video(fd, 
326                                         asset->layers, 
327                                         asset->width, 
328                                         asset->height,
329                                         asset->frame_rate,
330                                         string);
334                 for(int i = 0; i < asset->layers; i++)
335                         quicktime_set_depth(fd, depth, i);
337                 quicktime_set_parameter(fd, "jpeg_quality", &asset->jpeg_quality);
339 // set the compression parameters if there are any
340                 quicktime_set_parameter(fd, "divx_bitrate", &asset->divx_bitrate);
341                 quicktime_set_parameter(fd, "divx_rc_period", &asset->divx_rc_period);
342                 quicktime_set_parameter(fd, "divx_rc_reaction_ratio", &asset->divx_rc_reaction_ratio);
343                 quicktime_set_parameter(fd, "divx_rc_reaction_period", &asset->divx_rc_reaction_period);
344                 quicktime_set_parameter(fd, "divx_max_key_interval", &asset->divx_max_key_interval);
345                 quicktime_set_parameter(fd, "divx_max_quantizer", &asset->divx_max_quantizer);
346                 quicktime_set_parameter(fd, "divx_min_quantizer", &asset->divx_min_quantizer);
347                 quicktime_set_parameter(fd, "divx_quantizer", &asset->divx_quantizer);
348                 quicktime_set_parameter(fd, "divx_quality", &asset->divx_quality);
349                 quicktime_set_parameter(fd, "divx_fix_bitrate", &asset->divx_fix_bitrate);
351                 quicktime_set_parameter(fd, "ffmpeg_bitrate", &asset->ms_bitrate);
352                 quicktime_set_parameter(fd, "ffmpeg_bitrate_tolerance", &asset->ms_bitrate_tolerance);
353                 quicktime_set_parameter(fd, "ffmpeg_interlaced", &asset->ms_interlaced);
354                 quicktime_set_parameter(fd, "ffmpeg_quantizer", &asset->ms_quantization);
355                 quicktime_set_parameter(fd, "ffmpeg_gop_size", &asset->ms_gop_size);
356                 quicktime_set_parameter(fd, "ffmpeg_fix_bitrate", &asset->ms_fix_bitrate);
358                 quicktime_set_parameter(fd, "h264_bitrate", &asset->h264_bitrate);
359                 quicktime_set_parameter(fd, "h264_quantizer", &asset->h264_quantizer);
360                 quicktime_set_parameter(fd, "h264_fix_bitrate", &asset->h264_fix_bitrate);
363         }
364 //printf("FileMOV::asset_to_format 3.4\n");
366 //printf("FileMOV::asset_to_format 4 %d %d\n", wr, 
367 //                              asset->format);
369         if(wr && asset->format == FILE_AVI)
370         {
371                 quicktime_set_avi(fd, 1);
372         }
376 void FileMOV::format_to_asset()
378         if(!fd) return;
380         if(quicktime_is_avi(fd)) asset->format = FILE_AVI;
381         asset->audio_data = quicktime_has_audio(fd);
382         if(asset->audio_data)
383         {
384                 asset->channels = 0;
385                 int qt_tracks = quicktime_audio_tracks(fd);
386                 for(int i = 0; i < qt_tracks; i++)
387                         asset->channels += quicktime_track_channels(fd, i);
388         
389                 if(!asset->sample_rate)
390                         asset->sample_rate = quicktime_sample_rate(fd, 0);
391                 asset->bits = quicktime_audio_bits(fd, 0);
392                 asset->audio_length = quicktime_audio_length(fd, 0);
393                 strncpy(asset->acodec, quicktime_audio_compressor(fd, 0), 4);
394         }
396 // determine if the video can be read before declaring video data
397         if(quicktime_has_video(fd) && quicktime_supported_video(fd, 0))
398                         asset->video_data = 1;
400         if(asset->video_data)
401         {
402                 depth = quicktime_video_depth(fd, 0);
403                 asset->layers = quicktime_video_tracks(fd);
404                 asset->width = quicktime_video_width(fd, 0);
405                 asset->height = quicktime_video_height(fd, 0);
406                 asset->video_length = quicktime_video_length(fd, 0);
407 // Don't want a user configured frame rate to get destroyed
408                 if(!asset->frame_rate)
409                         asset->frame_rate = quicktime_frame_rate(fd, 0);
410                 if(!asset->interlace_mode)
411                         asset->interlace_mode = quicktime_video_interlacemode(fd, 0);
413                 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
414         }
417 int FileMOV::colormodel_supported(int colormodel)
419         return colormodel;
422 int FileMOV::get_best_colormodel(Asset *asset, int driver)
424         switch(driver)
425         {
426                 case PLAYBACK_X11:
427                         return BC_RGB888;
428                         break;
429                 case PLAYBACK_X11_XV:
430                         if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
431                         if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422P;
432                         if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
433                         if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
434                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
435                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
436                         if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
437                         if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
438                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
439                         if(match4(asset->vcodec, QUICKTIME_MP4V)) return BC_YUV420P;
440                         if(match4(asset->vcodec, QUICKTIME_H263)) return BC_YUV420P;
441                         if(match4(asset->vcodec, QUICKTIME_H264)) return BC_YUV420P;
442                         if(match4(asset->vcodec, QUICKTIME_HV64)) return BC_YUV420P;
443                         if(match4(asset->vcodec, QUICKTIME_DIV3)) return BC_YUV420P;
444                         break;
445                 case PLAYBACK_DV1394:
446                 case PLAYBACK_FIREWIRE:
447                         if(match4(asset->vcodec, QUICKTIME_DV) || 
448                                 match4(asset->vcodec, QUICKTIME_DVSD)) return BC_COMPRESSED;
449                         return BC_YUV422P;
450                         break;
451                 case PLAYBACK_LML:
452                 case PLAYBACK_BUZ:
453                         if(match4(asset->vcodec, QUICKTIME_MJPA)) 
454                                 return BC_COMPRESSED;
455                         else
456                                 return BC_YUV422P;
457                         break;
458                 case VIDEO4LINUX:
459                 case VIDEO4LINUX2:
460                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
461                         else
462                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
463                         else
464                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
465                         else
466                         if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
467                         else
468                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
469                         else
470                         if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
471                         else
472                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
473                         else
474                         if(!strncasecmp(asset->vcodec, QUICKTIME_H263, 4)) return BC_YUV420P;
475                         else
476                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
477                         break;
478                 case CAPTURE_BUZ:
479                 case CAPTURE_LML:
480                 case VIDEO4LINUX2JPEG:
481                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) 
482                                 return BC_COMPRESSED;
483                         else
484                                 return BC_YUV422;
485                         break;
486                 case CAPTURE_FIREWIRE:
487                 case CAPTURE_IEC61883:
488                         if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4) ||
489                                 !strncasecmp(asset->vcodec, QUICKTIME_DVSD, 4)) 
490                                 return BC_COMPRESSED;
491                         else
492                                 return BC_YUV422;
493                         break;
494         }
495         return BC_RGB888;
498 int FileMOV::can_copy_from(Edit *edit, int64_t position)
500         if(!fd) return 0;
502 //printf("FileMOV::can_copy_from 1 %d %s %s\n", edit->asset->format, edit->asset->vcodec, this->asset->vcodec);
503         if(edit->asset->format == FILE_JPEG_LIST && 
504                 match4(this->asset->vcodec, QUICKTIME_JPEG))
505                 return 1;
506         else
507         if((edit->asset->format == FILE_MOV || 
508                 edit->asset->format == FILE_AVI))
509         {
510                 if(match4(edit->asset->vcodec, this->asset->vcodec))
511                         return 1;
512 // there are combinations where the same codec has multiple fourcc codes
513 // check for DV...
514                 int is_edit_dv = 0;
515                 int is_this_dv = 0;
516                 if (match4(edit->asset->vcodec, QUICKTIME_DV) || 
517                         match4(edit->asset->vcodec, QUICKTIME_DVSD))
518                         is_edit_dv = 1;
519                 if (match4(this->asset->vcodec, QUICKTIME_DV) || 
520                         match4(this->asset->vcodec, QUICKTIME_DVSD))
521                         is_this_dv = 1;
522                 if (is_this_dv && is_edit_dv)
523                         return 1;
524         }
525         else
526         if(edit->asset->format == FILE_RAWDV)
527         {
528                 if(match4(this->asset->vcodec, QUICKTIME_DV) || match4(this->asset->vcodec, QUICKTIME_DVSD))
529                         return 1;
530         }
533         return 0;
537 int64_t FileMOV::get_audio_length()
539         if(!fd) return 0;
540         int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
542         return result;
545 int FileMOV::set_audio_position(int64_t x)
547         if(!fd) return 1;
548 // quicktime sets positions for each track seperately so store position in audio_position
549         if(x >= 0 && x < asset->audio_length)
550                 return quicktime_set_audio_position(fd, x, 0);
551         else
552                 return 1;
555 int FileMOV::set_video_position(int64_t x)
557         if(!fd) return 1;
558         if(x >= 0 && x < asset->video_length)
559         {
560                 int result = quicktime_set_video_position(fd, x, file->current_layer);
561                 return result;
562         }else
563                 return 1;
567 void FileMOV::new_audio_temp(int64_t len)
569         if(temp_allocated && temp_allocated < len)
570         {
571                 for(int i = 0; i < asset->channels; i++)
572                         delete [] temp_float[i];
573                 delete [] temp_float;
574                 temp_allocated = 0;
575         }
577         if(!temp_allocated)
578         {
579                 temp_allocated = len;
580                 temp_float = new float*[asset->channels];
581                 for(int i = 0; i < asset->channels; i++)
582                         temp_float[i] = new float[len];
583         }
588 int FileMOV::write_samples(double **buffer, int64_t len)
590         int i, j;
591         int64_t bytes;
592         int result = 0, track_channels = 0;
593         int chunk_size;
595         if(!fd) return 0;
597         if(quicktime_supported_audio(fd, 0))
598         {
599 // Use Quicktime's compressor. (Always used)
600 // Allocate temp buffer
601                 new_audio_temp(len);
603 // Copy to float buffer
604                 for(i = 0; i < asset->channels; i++)
605                 {
606                         for(j = 0; j < len; j++)
607                         {
608                                 temp_float[i][j] = buffer[i][j];
609                         }
610                 }
612 // Because of the way Quicktime's compressors work we want to limit the chunk
613 // size to speed up decompression.
614                 float **channel_ptr;
615                 channel_ptr = new float*[asset->channels];
617                 for(j = 0; j < len && !result; )
618                 {
619                         chunk_size = asset->sample_rate;
620                         if(j + chunk_size > len) chunk_size = len - j;
622                         for(i = 0; i < asset->channels; i++)
623                         {
624                                 channel_ptr[i] = &temp_float[i][j];
625                         }
627                         result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
628                         j += asset->sample_rate;
629                 }
631                 delete [] channel_ptr;
632         }
633         return result;
636 int FileMOV::write_frames(VFrame ***frames, int len)
638 //printf("FileMOV::write_frames 1\n");
639         int i, j, k, result = 0;
640         int default_compressor = 1;
641         if(!fd) return 0;
643         for(i = 0; i < asset->layers && !result; i++)
644         {
650 // Fix direct copy cases for format conversions.
651                 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
652                 {
653                         default_compressor = 0;
654                         for(j = 0; j < len && !result; j++)
655                         {
656                                 VFrame *frame = frames[i][j];
660 // Special handling for DIVX
661 // Determine keyframe status.
662 // Write VOL header in the first frame if none exists
663                                 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
664                                         !strcmp(asset->vcodec, QUICKTIME_H263) ||
665                                         !strcmp(asset->vcodec, QUICKTIME_HV60))
666                                 {
667                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
668                                                 frame->get_compressed_size(),
669                                                 asset->vcodec))
670                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
673 // Write header
674                                         if(!(file->current_frame + j) && 
675                                                 !quicktime_mpeg4_has_vol(frame->get_data()))
676                                         {
677                                                 VFrame *temp_frame = new VFrame;
679                                                 temp_frame->allocate_compressed_data(frame->get_compressed_size() + 
680                                                         0xff);
681                                                 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
682                                                         asset->width, 
683                                                         asset->height, 
684                                                         60000, 
685                                                         asset->frame_rate);
686                                                 memcpy(temp_frame->get_data() + bytes, 
687                                                         frame->get_data(), 
688                                                         frame->get_compressed_size());
689                                                 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
691                                                 result = quicktime_write_frame(fd,
692                                                         temp_frame->get_data(),
693                                                         temp_frame->get_compressed_size(),
694                                                         i);
696                                                 delete temp_frame;
699                                         }
700                                         else
701                                         {
702                                                 result = quicktime_write_frame(fd,
703                                                         frame->get_data(),
704                                                         frame->get_compressed_size(),
705                                                         i);
706                                         }
707                                 }
708                                 else
709 // Determine keyframe status
710                                 if(!strcmp(asset->vcodec, QUICKTIME_H264) ||
711                                         !strcmp(asset->vcodec, QUICKTIME_HV64) ||
712                                         !strcmp(asset->vcodec, QUICKTIME_MP4V))
713                                 {
714                                         if(frame->get_keyframe() || file->current_frame + j == 0)
715                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
717 // Write frame
718                                                 result = quicktime_write_frame(fd,
719                                                         frame->get_data(),
720                                                         frame->get_compressed_size(),
721                                                         i);
722                                 }
723                                 else
724                                 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
725                                 {
726                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
727                                                 frame->get_compressed_size(),
728                                                 asset->vcodec))
729                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
730                                         result = quicktime_write_frame(fd,
731                                                 frame->get_data(),
732                                                 frame->get_compressed_size(),
733                                                 i);
734                                 }
735                                 else
736                                 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
737                                 {
738                                         long field2_offset;
740 // Create extra space for markers
741                                         if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
742                                                 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
744                                         unsigned char *data = frame->get_data();
745                                         long data_size = frame->get_compressed_size();
746                                         long data_allocated = frame->get_compressed_allocated();
748 // Sometimes get 0 length frames
749                                         if(data_size)
750                                         {
751                                                 if(asset->format == FILE_MOV)
752                                                 {
753                                                         mjpeg_insert_quicktime_markers(&data,
754                                                                 &data_size,
755                                                                 &data_allocated,
756                                                                 2,
757                                                                 &field2_offset);
758                                                 }
759                                                 else
760                                                 {
761                                                         mjpeg_insert_avi_markers(&data,
762                                                                 &data_size,
763                                                                 &data_allocated,
764                                                                 2,
765                                                                 &field2_offset);
766                                                 }
767                                                 frame->set_compressed_size(data_size);
768                                                 result = quicktime_write_frame(fd,
769                                                         frame->get_data(),
770                                                         frame->get_compressed_size(),
771                                                         i);
772                                         }
773                                         else
774                                                 printf("FileMOV::write_frames data_size=%d\n", data_size);
775                                 }
776                                 else
777                                         result = quicktime_write_frame(fd,
778                                                 frame->get_data(),
779                                                 frame->get_compressed_size(),
780                                                 i);
781                                 
782                                 
783                         }
784                 }
785                 else
786                 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
787                         match4(asset->vcodec, QUICKTIME_YUV422) ||
788                         match4(asset->vcodec, QUICKTIME_RAW))
789                 {
790 // Direct copy planes where possible
791                         default_compressor = 0;
792                         for(j = 0; j < len && !result; j++)
793                         {
794                                 VFrame *frame = frames[i][j];
795 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
796                                 quicktime_set_cmodel(fd, frame->get_color_model());
797                                 if(cmodel_is_planar(frame->get_color_model()))
798                                 {
799                                         unsigned char *planes[3];
800                                         planes[0] = frame->get_y();
801                                         planes[1] = frame->get_u();
802                                         planes[2] = frame->get_v();
803                                         result = quicktime_encode_video(fd, planes, i);
804                                 }
805                                 else
806                                 {
807                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
808 //printf("FileMOV::write_frames 2 %d\n", result);
809                                 }
810 //printf("FileMOV::write_frames 2\n");
811                         }
812                 }
813                 else
814                 if(file->cpus > 1 && 
815                         (match4(asset->vcodec, QUICKTIME_JPEG) || 
816                         match4(asset->vcodec, QUICKTIME_MJPA)))
817                 {
818                         default_compressor = 0;
819 // Compress symmetrically on an SMP system.
820                         ThreadStruct *threadframe;
821                         int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
823 // Set up threads for symmetric compression.
824                         if(!threads)
825                         {
826                                 threads = new FileMOVThread*[file->cpus];
827                                 for(j = 0; j < file->cpus; j++)
828                                 {
829                                         threads[j] = new FileMOVThread(this, fields);
830                                         threads[j]->start_encoding();
831                                 }
832                         }
834 // Set up the frame structures for asynchronous compression.
835 // The mjpeg object must exist in each threadframe because it is where the output
836 // is stored.
837                         while(threadframes.total < len)
838                         {
839                                 threadframes.append(threadframe = new ThreadStruct);
840                         }
842 // Load thread frame structures with new frames.
843                         for(j = 0; j < len; j++)
844                         {
845                                 VFrame *frame = frames[i][j];
846                                 threadframes.values[j]->input = frame;
847                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
848                         }
849                         total_threadframes = len;
850                         current_threadframe = 0;
852 // Start the threads compressing
853                         for(j = 0; j < file->cpus; j++)
854                         {
855                                 threads[j]->encode_buffer();
856                         }
859 // Write the frames as they're finished
860                         for(j = 0; j < len; j++)
861                         {
862                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
863                                 threadframes.values[j]->completion_lock->unlock();
864                                 if(!result)
865                                 {
866                                         result = quicktime_write_frame(fd, 
867                                                 threadframes.values[j]->output,
868                                                 threadframes.values[j]->output_size,
869                                                 i);
870                                 }
871                         }
872                 }
874                 if(default_compressor)
875                 {
876 //printf("FileMOV::write_frames 3\n");
877 // Use the library's built in compressor.
878                         for(j = 0; j < len && !result; j++)
879                         {
880 //printf("FileMOV::write_frames 4\n");
881                                 VFrame *frame = frames[i][j];
882                                 quicktime_set_cmodel(fd, frame->get_color_model());
883 //printf("FileMOV::write_frames 5\n");
884                                 if(cmodel_is_planar(frame->get_color_model()))
885                                 {
886                                         unsigned char *planes[3];
887                                         planes[0] = frame->get_y();
888                                         planes[1] = frame->get_u();
889                                         planes[2] = frame->get_v();
890                                         result = quicktime_encode_video(fd, planes, i);
891                                 }
892                                 else
893                                 {
894                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
895                                 }
896                         }
897                 }
898 //printf("FileMOV::write_frames 4\n");
899         }
902 //printf("FileMOV::write_frames 100\n");
903         return result;
908 int FileMOV::read_frame(VFrame *frame)
910         if(!fd) return 1;
911         int result = 0;
913         switch(frame->get_color_model())
914         {
915                 case BC_COMPRESSED:
916                         frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
917                         frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
918                         frame->set_keyframe((quicktime_get_keyframe_before(fd, 
919                                 file->current_frame, 
920                                 file->current_layer) == file->current_frame));
921 //printf("FileMOV::read_frame 1 %lld %d\n", file->current_frame, frame->get_keyframe());
922                         result = quicktime_read_frame(fd, 
923                                 frame->get_data(), 
924                                 file->current_layer);
925                         break;
927 // Progressive
928                 case BC_YUV420P:
929                 case BC_YUV422P:
930                 {
931                         unsigned char *row_pointers[3];
932                         row_pointers[0] = frame->get_y();
933                         row_pointers[1] = frame->get_u();
934                         row_pointers[2] = frame->get_v();
936                         quicktime_set_cmodel(fd, frame->get_color_model());
937                         quicktime_decode_video(fd, 
938                                 row_pointers,
939                                 file->current_layer);
940                 }
941                         break;
943 // Packed
944                 default:
945                         quicktime_set_cmodel(fd, frame->get_color_model());
946                         result = quicktime_decode_video(fd, 
947                                 frame->get_rows(),
948                                 file->current_layer);
949 //for(int i = 0; i < 10000; i++) frame->get_rows()[0][i] = 0xff;
950                         break;
951         }
955         return result;
960 int64_t FileMOV::compressed_frame_size()
962         if(!fd) return 0;
963         return quicktime_frame_size(fd, file->current_frame, file->current_layer);
966 int FileMOV::read_compressed_frame(VFrame *buffer)
968         int64_t result;
969         if(!fd) return 0;
971         result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
972         buffer->set_compressed_size(result);
973         buffer->set_keyframe((quicktime_get_keyframe_before(fd, 
974                 file->current_frame, 
975                 file->current_layer) == file->current_frame));
976         result = !result;
977         return result;
980 int FileMOV::write_compressed_frame(VFrame *buffer)
982         int result = 0;
983         if(!fd) return 0;
985         result = quicktime_write_frame(fd, 
986                 buffer->get_data(), 
987                 buffer->get_compressed_size(), 
988                 file->current_layer);
989         return result;
994 int FileMOV::read_raw(VFrame *frame, 
995                 float in_x1, float in_y1, float in_x2, float in_y2,
996                 float out_x1, float out_y1, float out_x2, float out_y2, 
997                 int use_float, int interpolate)
999         int64_t i, color_channels, result = 0;
1000         if(!fd) return 0;
1002         quicktime_set_video_position(fd, file->current_frame, file->current_layer);
1003 // Develop importing strategy
1004         switch(frame->get_color_model())
1005         {
1006                 case BC_RGB888:
1007                         result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
1008                         break;
1009                 case BC_RGBA8888:
1010                         break;
1011                 case BC_RGB161616:
1012                         break;
1013                 case BC_RGBA16161616:
1014                         break;
1015                 case BC_YUV888:
1016                         break;
1017                 case BC_YUVA8888:
1018                         break;
1019                 case BC_YUV161616:
1020                         break;
1021                 case BC_YUVA16161616:
1022                         break;
1023                 case BC_YUV420P:
1024                         break;
1025         }
1026         return result;
1029 // Overlay samples
1030 int FileMOV::read_samples(double *buffer, int64_t len)
1032         int qt_track, qt_channel;
1034         if(!fd) return 0;
1036         if(quicktime_track_channels(fd, 0) > file->current_channel &&
1037                 quicktime_supported_audio(fd, 0))
1038         {
1040 //printf("FileMOV::read_samples 2 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1041                 new_audio_temp(len);
1043 //printf("FileMOV::read_samples 3 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1044                 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
1045                 {
1046                         printf("FileMOV::read_samples: quicktime_decode_audio failed\n");
1047                         return 1;
1048                 }
1049                 else
1050                 {
1051                         for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
1052                 }
1054 // if(file->current_channel == 0)
1055 // for(int i = 0; i < len; i++)
1056 // {
1057 //      int16_t value;
1058 //      value = (int16_t)(temp_float[0][i] * 32767);
1059 //      fwrite(&value, 2, 1, stdout);
1060 // }
1061 //printf("FileMOV::read_samples 4 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1062         }
1064         return 0;
1068 char* FileMOV::strtocompression(char *string)
1070         if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
1071         if(!strcasecmp(string, _(H264_NAME))) return QUICKTIME_H264;
1072         if(!strcasecmp(string, _(HV64_NAME))) return QUICKTIME_HV64;
1073         if(!strcasecmp(string, _(MP4V_NAME))) return QUICKTIME_MP4V;
1074         if(!strcasecmp(string, _(H263_NAME))) return QUICKTIME_H263;
1075         if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
1076         if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
1077         if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DVSD;
1078 //      if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
1079         if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
1080         if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
1081         if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
1082         if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
1083         if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
1084         if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
1085         if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
1086         if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
1087         if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
1088         if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
1089         if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
1090         if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
1092         if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
1093         if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
1094         if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
1095         if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
1096         if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
1097         if(!strcasecmp(string, _(MP4A_NAME))) return QUICKTIME_MP4A;
1098         if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
1102         return QUICKTIME_RAW;
1105 char* FileMOV::compressiontostr(char *string)
1107         if(match4(string, QUICKTIME_H263)) return _(H263_NAME);
1108         if(match4(string, QUICKTIME_H264)) return _(H264_NAME);
1109         if(match4(string, QUICKTIME_HV64)) return _(HV64_NAME);
1110         if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1111         if(match4(string, QUICKTIME_MP4V)) return _(MP4V_NAME);
1112         if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1113         if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1114         if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1115         if(match4(string, QUICKTIME_DVSD)) return _(DV_NAME);
1116         if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1117         if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1118         if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1119         if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1120         if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1121         if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1122         if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1123         if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1124         if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1125         if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1126         if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1132         if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1133         if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1134         if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1135         if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1136         if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1137         if(match4(string, QUICKTIME_MP4A)) return _(MP4A_NAME);
1138         if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1142         return _("Unknown");
1149 ThreadStruct::ThreadStruct()
1151         input = 0;
1152         output = 0;
1153         output_allocated = 0;
1154         output_size = 0;
1155         completion_lock = new Condition(1, "ThreadStruct::completion_lock");
1158 ThreadStruct::~ThreadStruct()
1160         if(output) delete [] output;
1161         delete completion_lock;
1164 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1166         if(output_allocated < mjpeg_output_size(mjpeg))
1167         {
1168                 delete [] output;
1169                 output = 0;
1170         }
1171         if(!output)
1172         {
1173                 output_allocated = mjpeg_output_size(mjpeg);
1174                 output = new unsigned char[output_allocated];
1175         }
1176         
1177         output_size = mjpeg_output_size(mjpeg);
1178         memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1182 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields) : Thread()
1184         this->filemov = filemov;
1185         this->fields = fields;
1186         mjpeg = 0;
1187         input_lock = new Condition(1, "FileMOVThread::input_lock");
1190 FileMOVThread::~FileMOVThread()
1192         delete input_lock;
1195 int FileMOVThread::start_encoding()
1197         mjpeg = mjpeg_new(filemov->asset->width, 
1198                 filemov->asset->height, 
1199                 fields);
1200         mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1201         mjpeg_set_float(mjpeg, 0);
1202         done = 0;
1203         set_synchronous(1);
1204         input_lock->lock("FileMOVThread::start_encoding");
1205         start();
1208 int FileMOVThread::stop_encoding()
1210         done = 1;
1211         input_lock->unlock();
1212         join();
1213         if(mjpeg) mjpeg_delete(mjpeg);
1216 int FileMOVThread::encode_buffer()
1218         input_lock->unlock();
1221 void FileMOVThread::run()
1223         while(!done)
1224         {
1225                 input_lock->lock("FileMOVThread::run");
1227                 if(!done)
1228                 {
1229 // Get a frame to compress.
1230                         filemov->threadframe_lock->lock("FileMOVThread::stop_encoding");
1231                         if(filemov->current_threadframe < filemov->total_threadframes)
1232                         {
1233 // Frame is available to process.
1234                                 input_lock->unlock();
1235                                 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1236                                 VFrame *frame = threadframe->input;
1238                                 filemov->current_threadframe++;
1239                                 filemov->threadframe_lock->unlock();
1241                                 mjpeg_compress(mjpeg, 
1242                                         frame->get_rows(), 
1243                                         frame->get_y(), 
1244                                         frame->get_u(), 
1245                                         frame->get_v(),
1246                                         frame->get_color_model(),
1247                                         1);
1249                                 if(fields > 1)
1250                                 {
1251                                         unsigned char *data = mjpeg_output_buffer(mjpeg);
1252                                         long data_size = mjpeg_output_size(mjpeg);
1253                                         long data_allocated = mjpeg_output_allocated(mjpeg);
1254                                         long field2_offset;
1256                                         if(filemov->asset->format == FILE_MOV)
1257                                         {
1258                                                 mjpeg_insert_quicktime_markers(&data,
1259                                                         &data_size,
1260                                                         &data_allocated,
1261                                                         2,
1262                                                         &field2_offset);
1263                                         }
1264                                         else
1265                                         {
1266                                                 mjpeg_insert_avi_markers(&data,
1267                                                         &data_size,
1268                                                         &data_allocated,
1269                                                         2,
1270                                                         &field2_offset);
1271                                         }
1272                                         mjpeg_set_output_size(mjpeg, data_size);
1273                                 }
1274                                 threadframe->load_output(mjpeg);
1275                                 threadframe->completion_lock->unlock();
1276                         }
1277                         else
1278                                 filemov->threadframe_lock->unlock();
1279                 }
1280         }
1288 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1289  : BC_Window(PROGRAM_NAME ": Audio Compression",
1290         parent_window->get_abs_cursor_x(1),
1291         parent_window->get_abs_cursor_y(1),
1292         350,
1293         250)
1295         this->parent_window = parent_window;
1296         this->asset = asset;
1297         compression_popup = 0;
1298         reset();
1301 MOVConfigAudio::~MOVConfigAudio()
1303         if(compression_popup) delete compression_popup;
1304         if(bits_popup) delete bits_popup;
1305         compression_items.remove_all_objects();
1309 void MOVConfigAudio::reset()
1311         bits_popup = 0;
1312         bits_title = 0;
1313         dither = 0;
1314         vorbis_min_bitrate = 0;
1315         vorbis_bitrate = 0;
1316         vorbis_max_bitrate = 0;
1317         vorbis_vbr = 0;
1318         mp3_bitrate = 0;
1319         mp4a_bitrate = 0;
1320         mp4a_quantqual = 0;
1323 int MOVConfigAudio::create_objects()
1325         int x = 10, y = 10;
1328         if(asset->format == FILE_MOV)
1329         {
1330                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1331                 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1332                 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1333                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1334                 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1335                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1336                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1337         }
1338         else
1339         {
1340                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1341                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1342                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1343                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1344         }
1346         add_tool(new BC_Title(x, y, _("Compression:")));
1347         y += 25;
1348         compression_popup = new MOVConfigAudioPopup(this, x, y);
1349         compression_popup->create_objects();
1351         update_parameters();
1353         add_subwindow(new BC_OKButton(this));
1354         return 0;
1357 void MOVConfigAudio::update_parameters()
1359         int x = 10, y = 70;
1360         if(bits_title) delete bits_title;
1361         if(bits_popup) delete bits_popup;
1362         if(dither) delete dither;
1363         if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1364         if(vorbis_bitrate) delete vorbis_bitrate;
1365         if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1366         if(vorbis_vbr) delete vorbis_vbr;
1367         if(mp3_bitrate) delete mp3_bitrate;
1368         delete mp4a_bitrate;
1369         delete mp4a_quantqual;
1371         reset();
1375         if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1376                 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1377         {
1378                 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1379                 bits_popup = new BitsPopup(this, 
1380                         x + 150, 
1381                         y, 
1382                         &asset->bits, 
1383                         0, 
1384                         0, 
1385                         0, 
1386                         0, 
1387                         0);
1388                 bits_popup->create_objects();
1389                 y += 40;
1390                 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1391         }
1392         else
1393         if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1394         {
1395         }
1396         else
1397         if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1398         {
1399                 mp3_bitrate = new MOVConfigAudioNum(this, 
1400                         _("Bitrate:"), 
1401                         x, 
1402                         y, 
1403                         &asset->mp3_bitrate);
1404                 mp3_bitrate->set_increment(1000);
1405                 mp3_bitrate->create_objects();
1406         }
1407         else
1408         if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1409         {
1410         }
1411         else
1412         if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1413         {
1414                 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1415                         _("Variable bitrate"),
1416                         x,
1417                         y,
1418                         &asset->vorbis_vbr));
1419                 y += 35;
1420                 vorbis_min_bitrate = new MOVConfigAudioNum(this, 
1421                         _("Min bitrate:"), 
1422                         x, 
1423                         y, 
1424                         &asset->vorbis_min_bitrate);
1425                 vorbis_min_bitrate->set_increment(1000);
1426                 y += 30;
1427                 vorbis_bitrate = new MOVConfigAudioNum(this, 
1428                         _("Avg bitrate:"), 
1429                         x, 
1430                         y, 
1431                         &asset->vorbis_bitrate);
1432                 vorbis_bitrate->set_increment(1000);
1433                 y += 30;
1434                 vorbis_max_bitrate = new MOVConfigAudioNum(this, 
1435                         _("Max bitrate:"), 
1436                         x, 
1437                         y, 
1438                         &asset->vorbis_max_bitrate);
1439                 vorbis_max_bitrate->set_increment(1000);
1443                 vorbis_min_bitrate->create_objects();
1444                 vorbis_bitrate->create_objects();
1445                 vorbis_max_bitrate->create_objects();
1446         }
1447         else
1448         if(!strcasecmp(asset->acodec, QUICKTIME_MP4A))
1449         {
1450                 mp4a_bitrate = new MOVConfigAudioNum(this, 
1451                         _("Bitrate:"), 
1452                         x, 
1453                         y, 
1454                         &asset->mp4a_bitrate);
1455                 mp4a_bitrate->set_increment(1000);
1456                 mp4a_bitrate->create_objects();
1458                 y += 30;
1459                 mp4a_quantqual = new MOVConfigAudioNum(this, 
1460                         _("Quantization Quality (%):"), 
1461                         x, 
1462                         y, 
1463                         &asset->mp4a_quantqual);
1464                 mp4a_quantqual->set_increment(1);
1465                 mp4a_quantqual->create_objects();
1466         }
1469 int MOVConfigAudio::close_event()
1471         set_done(0);
1472         return 1;
1479 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1480         char *title_text,
1481         int x,
1482         int y,
1483         int *output)
1484  : BC_CheckBox(x, y, *output, title_text)
1486         this->popup = popup;
1487         this->output = output;
1489 int MOVConfigAudioToggle::handle_event()
1491         *output = get_value();
1492         return 1;
1499 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1500  : BC_TumbleTextBox(popup, 
1501                 (int64_t)*output,
1502                 (int64_t)-1,
1503                 (int64_t)25000000,
1504                 popup->get_w() - 150, 
1505                 y, 
1506                 100)
1508         this->popup = popup;
1509         this->title_text = title_text;
1510         this->output = output;
1511         this->x = x;
1512         this->y = y;
1515 MOVConfigAudioNum::~MOVConfigAudioNum()
1517         if(!popup->get_deleting()) delete title;
1520 void MOVConfigAudioNum::create_objects()
1522         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1523         BC_TumbleTextBox::create_objects();
1526 int MOVConfigAudioNum::handle_event()
1528         *output = atol(get_text());
1529         return 1;
1539 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1540  : BC_PopupTextBox(popup, 
1541                 &popup->compression_items,
1542                 FileMOV::compressiontostr(popup->asset->acodec),
1543                 x, 
1544                 y, 
1545                 300,
1546                 300)
1548         this->popup = popup;
1551 int MOVConfigAudioPopup::handle_event()
1553         strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1554         popup->update_parameters();
1555         return 1;
1574 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window, 
1575         Asset *asset, 
1576         int lock_compressor)
1577  : BC_Window(PROGRAM_NAME ": Video Compression",
1578         parent_window->get_abs_cursor_x(1),
1579         parent_window->get_abs_cursor_y(1),
1580         420,
1581         420)
1583         this->parent_window = parent_window;
1584         this->asset = asset;
1585         this->lock_compressor = lock_compressor;
1586         compression_popup = 0;
1587         reset();
1590 MOVConfigVideo::~MOVConfigVideo()
1592         if(compression_popup) delete compression_popup;
1593         compression_items.remove_all_objects();
1596 int MOVConfigVideo::create_objects()
1598         int x = 10, y = 10;
1600         if(asset->format == FILE_MOV)
1601         {
1602                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1603                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1604 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1605                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1606                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1607                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1608                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1609                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1610                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1611                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1612                 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1613                 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1614                 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1615                 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1616                 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1617                 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1618                 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1619                 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1620         }
1621         else
1622         {
1623                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1624                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1625 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1626                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1627                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1628                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1629                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1630                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1631                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1632                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1633         }
1635         add_subwindow(new BC_Title(x, y, _("Compression:")));
1636         y += 25;
1638         if(!lock_compressor)
1639         {
1640                 compression_popup = new MOVConfigVideoPopup(this, x, y);
1641                 compression_popup->create_objects();
1642         }
1643         else
1644         {
1645                 add_subwindow(new BC_Title(x, 
1646                         y, 
1647                         FileMOV::compressiontostr(asset->vcodec),
1648                         MEDIUMFONT,
1649                         RED,
1650                         0));
1651         }
1652         y += 40;
1654         param_x = x;
1655         param_y = y;
1656         update_parameters();
1658         add_subwindow(new BC_OKButton(this));
1659         return 0;
1662 int MOVConfigVideo::close_event()
1664         set_done(0);
1665         return 1;
1669 void MOVConfigVideo::reset()
1671         jpeg_quality = 0;
1672         jpeg_quality_title = 0;
1674         divx_bitrate = 0;
1675         divx_rc_period = 0;
1676         divx_rc_reaction_ratio = 0;
1677         divx_rc_reaction_period = 0;
1678         divx_max_key_interval = 0;
1679         divx_max_quantizer = 0;
1680         divx_min_quantizer = 0;
1681         divx_quantizer = 0;
1682         divx_quality = 0;
1683         divx_fix_bitrate = 0;
1684         divx_fix_quant = 0;
1686         h264_bitrate = 0;
1687         h264_quantizer = 0;
1688         h264_fix_bitrate = 0;
1689         h264_fix_quant = 0;
1691         ms_bitrate = 0;
1692         ms_bitrate_tolerance = 0;
1693         ms_quantization = 0;
1694         ms_interlaced = 0;
1695         ms_gop_size = 0;
1696         ms_fix_bitrate = 0;
1697         ms_fix_quant = 0;
1700 void MOVConfigVideo::update_parameters()
1702         if(jpeg_quality)
1703         {
1704                 delete jpeg_quality_title;
1705                 delete jpeg_quality;
1706         }
1708         if(divx_bitrate) delete divx_bitrate;
1709         if(divx_rc_period) delete divx_rc_period;
1710         if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1711         if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1712         if(divx_max_key_interval) delete divx_max_key_interval;
1713         if(divx_max_quantizer) delete divx_max_quantizer;
1714         if(divx_min_quantizer) delete divx_min_quantizer;
1715         if(divx_quantizer) delete divx_quantizer;
1716         if(divx_quality) delete divx_quality;
1717         if(divx_fix_quant) delete divx_fix_quant;
1718         if(divx_fix_bitrate) delete divx_fix_bitrate;
1720         if(ms_bitrate) delete ms_bitrate;
1721         if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1722         if(ms_interlaced) delete ms_interlaced;
1723         if(ms_quantization) delete ms_quantization;
1724         if(ms_gop_size) delete ms_gop_size;
1725         if(ms_fix_bitrate) delete ms_fix_bitrate;
1726         if(ms_fix_quant) delete ms_fix_quant;
1728         delete h264_bitrate;
1729         delete h264_quantizer;
1730         delete h264_fix_bitrate;
1731         delete h264_fix_quant;
1733         reset();
1736 // H264 parameters
1737         if(!strcmp(asset->vcodec, QUICKTIME_H264) ||
1738                 !strcmp(asset->vcodec, QUICKTIME_HV64))
1739         {
1740                 int x = param_x, y = param_y;
1741                 h264_bitrate = new MOVConfigVideoNum(this, 
1742                         _("Bitrate:"), 
1743                         x, 
1744                         y, 
1745                         &asset->h264_bitrate);
1746                 h264_bitrate->set_increment(1000000);
1747                 h264_bitrate->create_objects();
1748                 add_subwindow(h264_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260, 
1749                                 y,
1750                                 &asset->h264_fix_bitrate,
1751                                 1));
1752                 y += 30;
1753                 h264_quantizer = new MOVConfigVideoNum(this, 
1754                         _("Quantization:"), 
1755                         x, 
1756                         y, 
1757                         0,
1758                         51,
1759                         &asset->h264_quantizer);
1760                 h264_quantizer->create_objects();
1761                 add_subwindow(h264_fix_quant = new MOVConfigVideoFixQuant(x + 260, 
1762                                 y,
1763                                 &asset->h264_fix_bitrate,
1764                                 0));
1765                 h264_fix_bitrate->opposite = h264_fix_quant;
1766                 h264_fix_quant->opposite = h264_fix_bitrate;
1767         }
1768         else
1769 // ffmpeg parameters
1770         if(!strcmp(asset->vcodec, QUICKTIME_MP4V) ||
1771                 !strcmp(asset->vcodec, QUICKTIME_DIV3))
1772         {
1773                 int x = param_x, y = param_y;
1774                 ms_bitrate = new MOVConfigVideoNum(this, 
1775                         _("Bitrate:"), 
1776                         x, 
1777                         y, 
1778                         &asset->ms_bitrate);
1779                 ms_bitrate->set_increment(1000000);
1780                 ms_bitrate->create_objects();
1781                 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260, 
1782                                 y,
1783                                 &asset->ms_fix_bitrate,
1784                                 1));
1785                 y += 30;
1787                 ms_bitrate_tolerance = new MOVConfigVideoNum(this, 
1788                         _("Bitrate tolerance:"), 
1789                         x, 
1790                         y, 
1791                         &asset->ms_bitrate_tolerance);
1792                 ms_bitrate_tolerance->create_objects();
1793                 y += 30;
1794                 ms_quantization = new MOVConfigVideoNum(this, 
1795                         _("Quantization:"), 
1796                         x, 
1797                         y, 
1798                         &asset->ms_quantization);
1799                 ms_quantization->create_objects();
1800                 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260, 
1801                                 y,
1802                                 &asset->ms_fix_bitrate,
1803                                 0));
1804                 ms_fix_bitrate->opposite = ms_fix_quant;
1805                 ms_fix_quant->opposite = ms_fix_bitrate;
1808                 y += 30;
1809                 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"), 
1810                         x, 
1811                         y, 
1812                         &asset->ms_interlaced));
1813                 y += 30;
1814                 ms_gop_size = new MOVConfigVideoNum(this, 
1815                         _("Keyframe interval:"), 
1816                         x, 
1817                         y, 
1818                         &asset->ms_gop_size);
1819                 ms_gop_size->create_objects();
1820         }
1821         else
1822 // OpenDivx parameters
1823         if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
1824                 !strcmp(asset->vcodec, QUICKTIME_H263) ||
1825                 !strcmp(asset->vcodec, QUICKTIME_HV60))
1826         {
1827                 int x = param_x, y = param_y;
1828                 divx_bitrate = new MOVConfigVideoNum(this, 
1829                         _("Bitrate:"), 
1830                         x, 
1831                         y, 
1832                         &asset->divx_bitrate);
1833                 divx_bitrate->set_increment(1000000);
1834                 divx_bitrate->create_objects();
1835                 add_subwindow(divx_fix_bitrate = 
1836                         new MOVConfigVideoFixBitrate(x + 260, 
1837                                 y,
1838                                 &asset->divx_fix_bitrate,
1839                                 1));
1840                 y += 30;
1841                 divx_quantizer = new MOVConfigVideoNum(this, 
1842                         _("Quantizer:"), 
1843                         x, 
1844                         y, 
1845                         &asset->divx_quantizer);
1846                 divx_quantizer->create_objects();
1847                 add_subwindow(divx_fix_quant =
1848                         new MOVConfigVideoFixQuant(x + 260, 
1849                                 y,
1850                                 &asset->divx_fix_bitrate,
1851                                 0));
1852                 divx_fix_quant->opposite = divx_fix_bitrate;
1853                 divx_fix_bitrate->opposite = divx_fix_quant;
1854                 y += 30;
1855                 divx_rc_period = new MOVConfigVideoNum(this, 
1856                         _("RC Period:"), 
1857                         x, 
1858                         y, 
1859                         &asset->divx_rc_period);
1860                 divx_rc_period->create_objects();
1861                 y += 30;
1862                 divx_rc_reaction_ratio = new MOVConfigVideoNum(this, 
1863                         _("Reaction Ratio:"), 
1864                         x, 
1865                         y, 
1866                         &asset->divx_rc_reaction_ratio);
1867                 divx_rc_reaction_ratio->create_objects();
1868                 y += 30;
1869                 divx_rc_reaction_period = new MOVConfigVideoNum(this, 
1870                         _("Reaction Period:"), 
1871                         x, 
1872                         y, 
1873                         &asset->divx_rc_reaction_period);
1874                 divx_rc_reaction_period->create_objects();
1875                 y += 30;
1876                 divx_max_key_interval = new MOVConfigVideoNum(this, 
1877                         _("Max Key Interval:"), 
1878                         x, 
1879                         y, 
1880                         &asset->divx_max_key_interval);
1881                 divx_max_key_interval->create_objects();
1882                 y += 30;
1883                 divx_max_quantizer = new MOVConfigVideoNum(this, 
1884                         _("Max Quantizer:"), 
1885                         x, 
1886                         y, 
1887                         &asset->divx_max_quantizer);
1888                 divx_max_quantizer->create_objects();
1889                 y += 30;
1890                 divx_min_quantizer = new MOVConfigVideoNum(this, 
1891                         _("Min Quantizer:"), 
1892                         x, 
1893                         y, 
1894                         &asset->divx_min_quantizer);
1895                 divx_min_quantizer->create_objects();
1896                 y += 30;
1897                 divx_quality = new MOVConfigVideoNum(this, 
1898                         _("Quality:"), 
1899                         x, 
1900                         y, 
1901                         &asset->divx_quality);
1902                 divx_quality->create_objects();
1903         }
1904         else
1905         if(!strcmp(asset->vcodec, QUICKTIME_JPEG) ||
1906                 !strcmp(asset->vcodec, QUICKTIME_MJPA))
1907         {
1908                 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
1909                 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80, 
1910                         param_y,
1911                         0,
1912                         200,
1913                         200,
1914                         0,
1915                         100,
1916                         asset->jpeg_quality,
1917                         0,
1918                         0,
1919                         &asset->jpeg_quality));
1920         }
1927 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
1928  : BC_TumbleTextBox(popup, 
1929                 (int64_t)*output,
1930                 (int64_t)1,
1931                 (int64_t)25000000,
1932                 x + 130, 
1933                 y, 
1934                 100)
1936         this->popup = popup;
1937         this->title_text = title_text;
1938         this->output = output;
1939         this->x = x;
1940         this->y = y;
1943 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, 
1944         char *title_text, 
1945         int x, 
1946         int y, 
1947         int min,
1948         int max,
1949         int *output)
1950  : BC_TumbleTextBox(popup, 
1951                 (int64_t)*output,
1952                 (int64_t)min,
1953                 (int64_t)max,
1954                 x + 130, 
1955                 y, 
1956                 100)
1958         this->popup = popup;
1959         this->title_text = title_text;
1960         this->output = output;
1961         this->x = x;
1962         this->y = y;
1965 MOVConfigVideoNum::~MOVConfigVideoNum()
1967         if(!popup->get_deleting()) delete title;
1970 void MOVConfigVideoNum::create_objects()
1972         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1973         BC_TumbleTextBox::create_objects();
1976 int MOVConfigVideoNum::handle_event()
1978         *output = atol(get_text());
1979         return 1;
1988 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
1989  : BC_CheckBox(x, y, *output, title_text)
1991         this->output = output;
1994 int MOVConfigVideoCheckBox::handle_event()
1996         *output = get_value();
1997         return 1;
2005 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x, 
2006         int y,
2007         int *output,
2008         int value)
2009  : BC_Radial(x, 
2010         y, 
2011         *output == value, 
2012         _("Fix bitrate"))
2014         this->output = output;
2015         this->value = value;
2018 int MOVConfigVideoFixBitrate::handle_event()
2020         *output = value;
2021         opposite->update(0);
2022         return 1;
2030 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x, 
2031         int y,
2032         int *output,
2033         int value)
2034  : BC_Radial(x, 
2035         y, 
2036         *output == value, 
2037         _("Fix quantization"))
2039         this->output = output;
2040         this->value = value;
2043 int MOVConfigVideoFixQuant::handle_event()
2045         *output = value;
2046         opposite->update(0);
2047         return 1;
2054 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
2055  : BC_PopupTextBox(popup, 
2056                 &popup->compression_items,
2057                 FileMOV::compressiontostr(popup->asset->vcodec),
2058                 x, 
2059                 y, 
2060                 300,
2061                 300)
2063         this->popup = popup;
2066 int MOVConfigVideoPopup::handle_event()
2068         strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
2069         popup->update_parameters();
2070         return 1;