r827: Fix a crash when no audio output device can be opened.
[cinelerra_cv.git] / cinelerra / filemov.C
blob687af5aa20bbf79beccd59477a1612bb4cf7f2d6
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 Y'CbCr 8-bit 4:2:2 (yuv2)")
32 N_("Component Y'CbCr 8-bit 4:2:2 (2vuy)")
33 N_("YUV 4:1:1 Packed")
34 N_("Component Y'CbCr 8-bit 4:4:4")
35 N_("Component Y'CbCrA 8-bit 4:4:4:4")
36 N_("Component Y'CbCr 10-bit 4:4:4")
37 N_("JPEG Photo")
38 N_("Motion JPEG A")
41 N_("Twos complement")
42 N_("Unsigned")
43 N_("IMA-4")
44 N_("U-Law")
45 N_("Vorbis")
46 N_("MP3")
47 N_("MPEG-4 Audio")
48 #endif
50 #define DIVX_NAME "MPEG-4"
51 #define HV64_NAME "Dual H.264"
52 #define MP4V_NAME "MPEG-4 Video"
53 #define H264_NAME "H.264"
54 #define H263_NAME "H.263"
55 #define HV60_NAME "Dual MPEG-4"
56 #define DIV3_NAME "Microsoft MPEG-4"
57 #define DV_NAME "DV"
58 #define PNG_NAME "PNG"
59 #define PNGA_NAME "PNG with Alpha"
60 #define RGB_NAME "Uncompressed RGB"
61 #define RGBA_NAME "Uncompressed RGBA"
62 #define YUV420_NAME "YUV 4:2:0 Planar"
63 #define YUV422_NAME "Component Y'CbCr 8-bit 4:2:2 (yuv2)"
64 #define TWOVUY_NAME "Component Y'CbCr 8-bit 4:2:2 (2vuy)"
65 #define YUV411_NAME "YUV 4:1:1 Packed"
66 #define YUV444_NAME "Component Y'CbCr 8-bit 4:4:4"
67 #define YUVA4444_NAME "Component Y'CbCrA 8-bit 4:4:4:4"
68 #define YUV444_10BIT_NAME "Component Y'CbCr 10-bit 4:4:4"
69 #define QTJPEG_NAME "JPEG Photo"
70 #define MJPA_NAME "Motion JPEG A"
72 #define TWOS_NAME "Twos complement"
73 #define RAW_NAME "Unsigned"
74 #define IMA4_NAME "IMA-4"
75 #define ULAW_NAME "U-Law"
76 //#define VORBIS_NAME "Vorbis"
77 #define MP3_NAME "MP3"
78 #define MP4A_NAME "MPEG-4 Audio"
79 #define VORBIS_NAME "OGG Vorbis"
85 FileMOV::FileMOV(Asset *asset, File *file)
86  : FileBase(asset, file)
88         reset_parameters();
89         if(asset->format == FILE_UNKNOWN)
90                 asset->format = FILE_MOV;
91         asset->byte_order = 0;
92         suffix_number = 0;
93         threadframe_lock = new Mutex("FileMOV::threadframe_lock");
96 FileMOV::~FileMOV()
98         close_file();
99         delete threadframe_lock;
102 void FileMOV::get_parameters(BC_WindowBase *parent_window, 
103         Asset *asset, 
104         BC_WindowBase* &format_window,
105         int audio_options,
106         int video_options,
107         int lock_compressor)
109         if(audio_options)
110         {
111                 MOVConfigAudio *window = new MOVConfigAudio(parent_window, asset);
112                 format_window = window;
113                 window->create_objects();
114                 window->run_window();
115                 delete window;
116         }
117         else
118         if(video_options)
119         {
120                 MOVConfigVideo *window = new MOVConfigVideo(parent_window, 
121                         asset, 
122                         lock_compressor);
123                 format_window = window;
124                 window->create_objects();
125                 window->run_window();
126                 delete window;
127         }
130 void FileMOV::fix_codecs_for_writing(Asset *asset)
132         if(!strcasecmp(asset->vcodec, QUICKTIME_DV) ||
133            !strcasecmp(asset->vcodec, QUICKTIME_DVSD) || 
134            !strcasecmp(asset->vcodec, QUICKTIME_DVCP))
135         {
136                 printf("AF: %i, AH: %i, VC: %s\n", asset->format, asset->height, asset->vcodec);
137                 if (asset->format == FILE_AVI)
138                         strcpy (asset->vcodec, QUICKTIME_DVSD);
139                 else if (asset->format == FILE_MOV && asset->height == 576) 
140                         strcpy (asset->vcodec, QUICKTIME_DVCP);
141                 else if (asset->format == FILE_MOV && asset->height == 480)
142                         strcpy (asset->vcodec, QUICKTIME_DV);
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         }
191         if(wr) asset_to_format();
193 // Set decoding parameter
194         quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking);
196 // Set timecode offset
197         quicktime_set_frame_start(fd, asset->tcstart);
199         return 0;
202 int FileMOV::close_file()
204 //printf("FileMOV::close_file 1 %s\n", asset->path);
205         if(fd)
206         {
207                 if(wr) quicktime_set_framerate(fd, asset->frame_rate);
208                 quicktime_close(fd);
209         }
211 //printf("FileMOV::close_file 1\n");
212         if(threads)
213         {
214                 for(int i = 0; i < file->cpus; i++)
215                 {
216                         threads[i]->stop_encoding();
217                         delete threads[i];
218                 }
219                 delete [] threads;
220                 threads = 0;
221         }
223 //printf("FileMOV::close_file 1\n");
224         threadframes.remove_all_objects();
227         if(temp_float) 
228         {
229                 for(int i = 0; i < asset->channels; i++)
230                         delete [] temp_float[i];
231                 delete [] temp_float;
232         }
234 //printf("FileMOV::close_file 1\n");
235         reset_parameters();
236         FileBase::close_file();
237 //printf("FileMOV::close_file 2\n");
238         return 0;
241 void FileMOV::set_frame_start(int64_t offset)
243         quicktime_set_frame_start(fd, offset);
246 void FileMOV::asset_to_format()
248         if(!fd) return;
250         fix_codecs_for_writing(asset);
252 // Fix up the Quicktime file.
253         quicktime_set_copyright(fd, _("Made with Cinelerra for Linux"));
254         quicktime_set_info(fd, "Quicktime for Linux");
256         if(asset->audio_data)
257         {
258                 quicktime_atracks = quicktime_set_audio(fd, 
259                                 asset->channels, 
260                                 asset->sample_rate, 
261                                 asset->bits, 
262                                 asset->acodec);
263                 quicktime_set_parameter(fd, "vorbis_vbr", &asset->vorbis_vbr);
264                 quicktime_set_parameter(fd, "vorbis_min_bitrate", &asset->vorbis_min_bitrate);
265                 quicktime_set_parameter(fd, "vorbis_bitrate", &asset->vorbis_bitrate);
266                 quicktime_set_parameter(fd, "vorbis_max_bitrate", &asset->vorbis_max_bitrate);
267                 quicktime_set_parameter(fd, "mp3_bitrate", &asset->mp3_bitrate);
268                 quicktime_set_parameter(fd, "mp4a_bitrate", &asset->mp4a_bitrate);
269         }
271         if(asset->video_data)
272         {
273                 char string[16];
274 // Set up the alpha channel compressors
275                 if(!strcmp(asset->vcodec, MOV_RGBA))
276                 {
277                         strcpy(string, QUICKTIME_RAW);
278                         depth = 32;
279                 }
280                 else
281                 if(!strcmp(asset->vcodec, MOV_PNGA))
282                 {
283                         strcpy(string, QUICKTIME_PNG);
284                         depth = 32;
285                 }
286                 else
287                 if(!strcmp(asset->vcodec, QUICKTIME_YUVA4444))
288                 {
289                         strcpy(string, asset->vcodec);
290                         depth = 32;
291                 }
292                 else
293                 {
294                         strcpy(string, asset->vcodec);
295                         depth = 24;
296                 }
298                 quicktime_vtracks = quicktime_set_video(fd, 
299                                         asset->layers, 
300                                         asset->width, 
301                                         asset->height,
302                                         asset->frame_rate,
303                                         string);
307                 for(int i = 0; i < asset->layers; i++)
308                         quicktime_set_depth(fd, depth, i);
310                 quicktime_set_parameter(fd, "jpeg_quality", &asset->jpeg_quality);
312 // set the compression parameters if there are any
313                 quicktime_set_parameter(fd, "divx_bitrate", &asset->divx_bitrate);
314                 quicktime_set_parameter(fd, "divx_rc_period", &asset->divx_rc_period);
315                 quicktime_set_parameter(fd, "divx_rc_reaction_ratio", &asset->divx_rc_reaction_ratio);
316                 quicktime_set_parameter(fd, "divx_rc_reaction_period", &asset->divx_rc_reaction_period);
317                 quicktime_set_parameter(fd, "divx_max_key_interval", &asset->divx_max_key_interval);
318                 quicktime_set_parameter(fd, "divx_max_quantizer", &asset->divx_max_quantizer);
319                 quicktime_set_parameter(fd, "divx_min_quantizer", &asset->divx_min_quantizer);
320                 quicktime_set_parameter(fd, "divx_quantizer", &asset->divx_quantizer);
321                 quicktime_set_parameter(fd, "divx_quality", &asset->divx_quality);
322                 quicktime_set_parameter(fd, "divx_fix_bitrate", &asset->divx_fix_bitrate);
324                 quicktime_set_parameter(fd, "ffmpeg_bitrate", &asset->ms_bitrate);
325                 quicktime_set_parameter(fd, "ffmpeg_bitrate_tolerance", &asset->ms_bitrate_tolerance);
326                 quicktime_set_parameter(fd, "ffmpeg_interlaced", &asset->ms_interlaced);
327                 quicktime_set_parameter(fd, "ffmpeg_quantizer", &asset->ms_quantization);
328                 quicktime_set_parameter(fd, "ffmpeg_gop_size", &asset->ms_gop_size);
329                 quicktime_set_parameter(fd, "ffmpeg_fix_bitrate", &asset->ms_fix_bitrate);
331                 quicktime_set_parameter(fd, "h264_bitrate", &asset->h264_bitrate);
332                 quicktime_set_parameter(fd, "h264_quantizer", &asset->h264_quantizer);
333                 quicktime_set_parameter(fd, "h264_fix_bitrate", &asset->h264_fix_bitrate);
336         }
337 //printf("FileMOV::asset_to_format 3.4\n");
339 //printf("FileMOV::asset_to_format 4 %d %d\n", wr, 
340 //                              asset->format);
342         if(wr && asset->format == FILE_AVI)
343         {
344                 quicktime_set_avi(fd, 1);
345         }
349 void FileMOV::format_to_asset()
351         if(!fd) return;
353         if(quicktime_is_avi(fd)) asset->format = FILE_AVI;
354         asset->audio_data = quicktime_has_audio(fd);
355         if(asset->audio_data)
356         {
357                 asset->channels = 0;
358                 int qt_tracks = quicktime_audio_tracks(fd);
359                 for(int i = 0; i < qt_tracks; i++)
360                         asset->channels += quicktime_track_channels(fd, i);
361         
362                 if(!asset->sample_rate)
363                         asset->sample_rate = quicktime_sample_rate(fd, 0);
364                 asset->bits = quicktime_audio_bits(fd, 0);
365                 asset->audio_length = quicktime_audio_length(fd, 0);
366                 strncpy(asset->acodec, quicktime_audio_compressor(fd, 0), 4);
367         }
369 // determine if the video can be read before declaring video data
370         if(quicktime_has_video(fd) && quicktime_supported_video(fd, 0))
371                         asset->video_data = 1;
373         if(asset->video_data)
374         {
375                 depth = quicktime_video_depth(fd, 0);
376                 asset->layers = quicktime_video_tracks(fd);
377                 asset->width = quicktime_video_width(fd, 0);
378                 asset->height = quicktime_video_height(fd, 0);
379                 asset->video_length = quicktime_video_length(fd, 0);
380 // Don't want a user configured frame rate to get destroyed
381                 if(!asset->frame_rate)
382                         asset->frame_rate = quicktime_frame_rate(fd, 0);
383                 if(!asset->interlace_mode)
384                         asset->interlace_mode = quicktime_video_interlacemode(fd, 0);
386                 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
388                 // If DV stream, get the timecode 
389                 // This should become part of libquicktime functionality... for all formats
390                 if(match4(asset->vcodec, QUICKTIME_DV))
391                 {
392                         char tc[12];
393                         dv_decoder_t *tmp_decoder = dv_decoder_new(0,0,0);
394                         VFrame *frame = new VFrame(0, 0, 0, BC_COMPRESSED);
395                         
396                         read_frame(frame);
397                         set_video_position(0);
398                         
399                         if(dv_parse_header(tmp_decoder, frame->get_data()) > -1)
400                         {
401                                 dv_parse_packs(tmp_decoder, frame->get_data());
402                                 dv_get_timestamp(tmp_decoder, tc);
403 //                              printf("Timestamp %s\n", tc);
404                         
405                                 float seconds = Units::text_to_seconds(tc,
406                                                                                 1, // Use 1 as sample rate, doesn't matter
407                                                                                 TIME_HMSF,
408                                                                                 asset->frame_rate,
409                                                                                 0);
410                                 // Set tcstart if it hasn't been set yet, this is a bit problematic
411                                 // FIXME: The problem arises if file has nonzero tcstart and user manualy sets it to zero - every time project will load it will be set to nonzero
412                                 if (asset->tcstart == 0)
413                                         asset->tcstart = int64_t(seconds * asset->frame_rate);
414                         }
415                         delete frame;
416                         dv_decoder_free(tmp_decoder);
417                         
418                 }
421         }
424 int FileMOV::colormodel_supported(int colormodel)
426         return colormodel;
429 int FileMOV::get_best_colormodel(Asset *asset, int driver)
431         switch(driver)
432         {
433                 case PLAYBACK_X11:
434                         return BC_RGB888;
435                         break;
436                 case PLAYBACK_X11_XV:
437                         if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
438                         if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422;
439                         if(match4(asset->vcodec, QUICKTIME_2VUY)) return BC_YUV422;
440                         if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
441                         if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
442                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
443                         if(match4(asset->vcodec, QUICKTIME_DVCP)) return BC_YUV422;
444                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
445                         if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
446                         if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
447                         if(match4(asset->vcodec, QUICKTIME_MP4V)) return BC_YUV420P;
448                         if(match4(asset->vcodec, QUICKTIME_H263)) return BC_YUV420P;
449                         if(match4(asset->vcodec, QUICKTIME_H264)) return BC_YUV420P;
450                         if(match4(asset->vcodec, QUICKTIME_HV64)) return BC_YUV420P;
451                         if(match4(asset->vcodec, QUICKTIME_DIV3)) return BC_YUV420P;
452                         break;
453                 case PLAYBACK_DV1394:
454                 case PLAYBACK_FIREWIRE:
455                         if(match4(asset->vcodec, QUICKTIME_DV) || 
456                                 match4(asset->vcodec, QUICKTIME_DVSD) ||
457                                 match4(asset->vcodec, QUICKTIME_DVCP)) return BC_COMPRESSED;
458                         return BC_YUV422P;
459                         break;
460                 case PLAYBACK_LML:
461                 case PLAYBACK_BUZ:
462                         if(match4(asset->vcodec, QUICKTIME_MJPA)) 
463                                 return BC_COMPRESSED;
464                         else
465                                 return BC_YUV422P;
466                         break;
467                 case VIDEO4LINUX:
468                 case VIDEO4LINUX2:
469                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
470                         else
471                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
472                         else
473                         if(!strncasecmp(asset->vcodec, QUICKTIME_2VUY, 4)) return BC_YUV422;
474                         else
475                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
476                         else
477                         if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
478                         else
479                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
480                         else
481                         if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
482                         else
483                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
484                         else
485                         if(!strncasecmp(asset->vcodec, QUICKTIME_H263, 4)) return BC_YUV420P;
486                         else
487                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
488                         break;
489                 case CAPTURE_BUZ:
490                 case CAPTURE_LML:
491                 case VIDEO4LINUX2JPEG:
492                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) 
493                                 return BC_COMPRESSED;
494                         else
495                                 return BC_YUV422;
496                         break;
497                 case CAPTURE_FIREWIRE:
498                 case CAPTURE_IEC61883:
499                         if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4) ||
500                                 !strncasecmp(asset->vcodec, QUICKTIME_DVSD, 4) ||
501                                 !strncasecmp(asset->vcodec, QUICKTIME_DVCP, 4)) 
502                                 return BC_COMPRESSED;
503                         else
504                                 return BC_YUV422;
505                         break;
506         }
507         return BC_RGB888;
510 int FileMOV::can_copy_from(Edit *edit, int64_t position)
512         if(!fd) return 0;
514 //printf("FileMOV::can_copy_from 1 %d %s %s\n", edit->asset->format, edit->asset->vcodec, this->asset->vcodec);
515         if(edit->asset->format == FILE_JPEG_LIST && 
516                 match4(this->asset->vcodec, QUICKTIME_JPEG))
517                 return 1;
518         else
519         if((edit->asset->format == FILE_MOV || 
520                 edit->asset->format == FILE_AVI))
521         {
522                 if(match4(edit->asset->vcodec, this->asset->vcodec))
523                         return 1;
524 // there are combinations where the same codec has multiple fourcc codes
525 // check for DV...
526                 int is_edit_dv = 0;
527                 int is_this_dv = 0;
528                 if (match4(edit->asset->vcodec, QUICKTIME_DV) || 
529                         match4(edit->asset->vcodec, QUICKTIME_DVSD) ||
530                         match4(edit->asset->vcodec, QUICKTIME_DVCP))
531                         is_edit_dv = 1;
532                 if (match4(this->asset->vcodec, QUICKTIME_DV) || 
533                         match4(this->asset->vcodec, QUICKTIME_DVSD) ||
534                         match4(this->asset->vcodec, QUICKTIME_DVCP))
535                         is_this_dv = 1;
536                 if (is_this_dv && is_edit_dv)
537                         return 1;
538         }
539         else
540         if(edit->asset->format == FILE_RAWDV)
541         {
542                 if(match4(this->asset->vcodec, QUICKTIME_DV) || 
543                         match4(this->asset->vcodec, QUICKTIME_DVSD) || 
544                         match4(this->asset->vcodec, QUICKTIME_DVCP))
545                         return 1;
546         }
549         return 0;
553 int64_t FileMOV::get_audio_length()
555         if(!fd) return 0;
556         int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
558         return result;
561 int FileMOV::set_audio_position(int64_t x)
563         if(!fd) return 1;
564 // quicktime sets positions for each track seperately so store position in audio_position
565         if(x >= 0 && x < asset->audio_length)
566                 return quicktime_set_audio_position(fd, x, 0);
567         else
568                 return 1;
571 int FileMOV::set_video_position(int64_t x)
573         if(!fd) return 1;
574         if(x >= 0 && x < asset->video_length)
575         {
576                 int result = quicktime_set_video_position(fd, x, file->current_layer);
577                 return result;
578         }else
579                 return 1;
583 void FileMOV::new_audio_temp(int64_t len)
585         if(temp_allocated && temp_allocated < len)
586         {
587                 for(int i = 0; i < asset->channels; i++)
588                         delete [] temp_float[i];
589                 delete [] temp_float;
590                 temp_allocated = 0;
591         }
593         if(!temp_allocated)
594         {
595                 temp_allocated = len;
596                 temp_float = new float*[asset->channels];
597                 for(int i = 0; i < asset->channels; i++)
598                         temp_float[i] = new float[len];
599         }
604 int FileMOV::write_samples(double **buffer, int64_t len)
606         int i, j;
607         int64_t bytes;
608         int result = 0, track_channels = 0;
609         int chunk_size;
611         if(!fd) return 0;
613         if(quicktime_supported_audio(fd, 0))
614         {
615 // Use Quicktime's compressor. (Always used)
616 // Allocate temp buffer
617                 new_audio_temp(len);
619 // Copy to float buffer
620                 for(i = 0; i < asset->channels; i++)
621                 {
622                         for(j = 0; j < len; j++)
623                         {
624                                 temp_float[i][j] = buffer[i][j];
625                         }
626                 }
628 // Because of the way Quicktime's compressors work we want to limit the chunk
629 // size to speed up decompression.
630                 float **channel_ptr;
631                 channel_ptr = new float*[asset->channels];
633                 for(j = 0; j < len && !result; )
634                 {
635                         chunk_size = asset->sample_rate;
636                         if(j + chunk_size > len) chunk_size = len - j;
638                         for(i = 0; i < asset->channels; i++)
639                         {
640                                 channel_ptr[i] = &temp_float[i][j];
641                         }
643                         result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
644                         j += asset->sample_rate;
645                 }
647                 delete [] channel_ptr;
648         }
649         return result;
652 int FileMOV::write_frames(VFrame ***frames, int len)
654 //printf("FileMOV::write_frames 1\n");
655         int i, j, k, result = 0;
656         int default_compressor = 1;
657         if(!fd) return 0;
659         for(i = 0; i < asset->layers && !result; i++)
660         {
666 // Fix direct copy cases for format conversions.
667                 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
668                 {
669                         default_compressor = 0;
670                         for(j = 0; j < len && !result; j++)
671                         {
672                                 VFrame *frame = frames[i][j];
676 // Special handling for DIVX
677 // Determine keyframe status.
678 // Write VOL header in the first frame if none exists
679                                 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
680                                         !strcmp(asset->vcodec, QUICKTIME_H263) ||
681                                         !strcmp(asset->vcodec, QUICKTIME_HV60))
682                                 {
683                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
684                                                 frame->get_compressed_size(),
685                                                 asset->vcodec))
686                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
689 // Write header
690                                         if(!(file->current_frame + j) && 
691                                                 !quicktime_mpeg4_has_vol(frame->get_data()))
692                                         {
693                                                 VFrame *temp_frame = new VFrame;
695                                                 temp_frame->allocate_compressed_data(frame->get_compressed_size() + 
696                                                         0xff);
697                                                 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
698                                                         asset->width, 
699                                                         asset->height, 
700                                                         60000, 
701                                                         asset->frame_rate);
702                                                 memcpy(temp_frame->get_data() + bytes, 
703                                                         frame->get_data(), 
704                                                         frame->get_compressed_size());
705                                                 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
707                                                 result = quicktime_write_frame(fd,
708                                                         temp_frame->get_data(),
709                                                         temp_frame->get_compressed_size(),
710                                                         i);
712                                                 delete temp_frame;
715                                         }
716                                         else
717                                         {
718                                                 result = quicktime_write_frame(fd,
719                                                         frame->get_data(),
720                                                         frame->get_compressed_size(),
721                                                         i);
722                                         }
723                                 }
724                                 else
725 // Determine keyframe status
726                                 if(!strcmp(asset->vcodec, QUICKTIME_H264) ||
727                                         !strcmp(asset->vcodec, QUICKTIME_HV64) ||
728                                         !strcmp(asset->vcodec, QUICKTIME_MP4V))
729                                 {
730                                         if(frame->get_keyframe() || file->current_frame + j == 0)
731                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
733 // Write frame
734                                                 result = quicktime_write_frame(fd,
735                                                         frame->get_data(),
736                                                         frame->get_compressed_size(),
737                                                         i);
738                                 }
739                                 else
740                                 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
741                                 {
742                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
743                                                 frame->get_compressed_size(),
744                                                 asset->vcodec))
745                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
746                                         result = quicktime_write_frame(fd,
747                                                 frame->get_data(),
748                                                 frame->get_compressed_size(),
749                                                 i);
750                                 }
751                                 else
752                                 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
753                                 {
754                                         long field2_offset;
756 // Create extra space for markers
757                                         if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
758                                                 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
760                                         unsigned char *data = frame->get_data();
761                                         long data_size = frame->get_compressed_size();
762                                         long data_allocated = frame->get_compressed_allocated();
764 // Sometimes get 0 length frames
765                                         if(data_size)
766                                         {
767                                                 if(asset->format == FILE_MOV)
768                                                 {
769                                                         mjpeg_insert_quicktime_markers(&data,
770                                                                 &data_size,
771                                                                 &data_allocated,
772                                                                 2,
773                                                                 &field2_offset);
774                                                 }
775                                                 else
776                                                 {
777                                                         mjpeg_insert_avi_markers(&data,
778                                                                 &data_size,
779                                                                 &data_allocated,
780                                                                 2,
781                                                                 &field2_offset);
782                                                 }
783                                                 frame->set_compressed_size(data_size);
784                                                 result = quicktime_write_frame(fd,
785                                                         frame->get_data(),
786                                                         frame->get_compressed_size(),
787                                                         i);
788                                         }
789                                         else
790                                                 printf("FileMOV::write_frames data_size=%d\n", data_size);
791                                 }
792                                 else
793                                         result = quicktime_write_frame(fd,
794                                                 frame->get_data(),
795                                                 frame->get_compressed_size(),
796                                                 i);
797                                 
798                                 
799                         }
800                 }
801                 else
802                 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
803                         match4(asset->vcodec, QUICKTIME_2VUY) ||
804                         match4(asset->vcodec, QUICKTIME_YUV422) ||
805                         match4(asset->vcodec, QUICKTIME_RAW))
806                 {
807 // Direct copy planes where possible
808                         default_compressor = 0;
809                         for(j = 0; j < len && !result; j++)
810                         {
811                                 VFrame *frame = frames[i][j];
812 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
813                                 quicktime_set_cmodel(fd, frame->get_color_model());
814                                 if(cmodel_is_planar(frame->get_color_model()))
815                                 {
816                                         unsigned char *planes[3];
817                                         planes[0] = frame->get_y();
818                                         planes[1] = frame->get_u();
819                                         planes[2] = frame->get_v();
820                                         result = quicktime_encode_video(fd, planes, i);
821                                 }
822                                 else
823                                 {
824                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
825 //printf("FileMOV::write_frames 2 %d\n", result);
826                                 }
827 //printf("FileMOV::write_frames 2\n");
828                         }
829                 }
830                 else
831                 if(file->cpus > 1 && 
832                         (match4(asset->vcodec, QUICKTIME_JPEG) || 
833                         match4(asset->vcodec, QUICKTIME_MJPA)))
834                 {
835                         default_compressor = 0;
836 // Compress symmetrically on an SMP system.
837                         ThreadStruct *threadframe;
838                         int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
840 // Set up threads for symmetric compression.
841                         if(!threads)
842                         {
843                                 threads = new FileMOVThread*[file->cpus];
844                                 for(j = 0; j < file->cpus; j++)
845                                 {
846                                         threads[j] = new FileMOVThread(this, fields);
847                                         threads[j]->start_encoding();
848                                 }
849                         }
851 // Set up the frame structures for asynchronous compression.
852 // The mjpeg object must exist in each threadframe because it is where the output
853 // is stored.
854                         while(threadframes.total < len)
855                         {
856                                 threadframes.append(threadframe = new ThreadStruct);
857                         }
859 // Load thread frame structures with new frames.
860                         for(j = 0; j < len; j++)
861                         {
862                                 VFrame *frame = frames[i][j];
863                                 threadframes.values[j]->input = frame;
864                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
865                         }
866                         total_threadframes = len;
867                         current_threadframe = 0;
869 // Start the threads compressing
870                         for(j = 0; j < file->cpus; j++)
871                         {
872                                 threads[j]->encode_buffer();
873                         }
876 // Write the frames as they're finished
877                         for(j = 0; j < len; j++)
878                         {
879                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
880                                 threadframes.values[j]->completion_lock->unlock();
881                                 if(!result)
882                                 {
883                                         result = quicktime_write_frame(fd, 
884                                                 threadframes.values[j]->output,
885                                                 threadframes.values[j]->output_size,
886                                                 i);
887                                 }
888                         }
889                 }
891                 if(default_compressor)
892                 {
893 //printf("FileMOV::write_frames 3\n");
894 // Use the library's built in compressor.
895                         for(j = 0; j < len && !result; j++)
896                         {
897 //printf("FileMOV::write_frames 4\n");
898                                 VFrame *frame = frames[i][j];
899                                 quicktime_set_cmodel(fd, frame->get_color_model());
900 //printf("FileMOV::write_frames 5\n");
901                                 if(cmodel_is_planar(frame->get_color_model()))
902                                 {
903                                         unsigned char *planes[3];
904                                         planes[0] = frame->get_y();
905                                         planes[1] = frame->get_u();
906                                         planes[2] = frame->get_v();
907                                         result = quicktime_encode_video(fd, planes, i);
908                                 }
909                                 else
910                                 {
911                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
912                                 }
913                         }
914                 }
915 //printf("FileMOV::write_frames 4\n");
916         }
919 //printf("FileMOV::write_frames 100\n");
920         return result;
925 int FileMOV::read_frame(VFrame *frame)
927         if(!fd) return 1;
928         int result = 0;
930         switch(frame->get_color_model())
931         {
932                 case BC_COMPRESSED:
933                         frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
934                         frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
935                         frame->set_keyframe((quicktime_get_keyframe_before(fd, 
936                                 file->current_frame, 
937                                 file->current_layer) == file->current_frame));
938 //printf("FileMOV::read_frame 1 %lld %d\n", file->current_frame, frame->get_keyframe());
939                         result = quicktime_read_frame(fd, 
940                                 frame->get_data(), 
941                                 file->current_layer);
942                         break;
944 // Progressive
945                 case BC_YUV420P:
946                 case BC_YUV422P:
947                 {
948                         unsigned char *row_pointers[3];
949                         row_pointers[0] = frame->get_y();
950                         row_pointers[1] = frame->get_u();
951                         row_pointers[2] = frame->get_v();
953                         quicktime_set_cmodel(fd, frame->get_color_model());
954                         quicktime_decode_video(fd, 
955                                 row_pointers,
956                                 file->current_layer);
957                 }
958                         break;
960 // Packed
961                 default:
962                         quicktime_set_cmodel(fd, frame->get_color_model());
963                         result = quicktime_decode_video(fd, 
964                                 frame->get_rows(),
965                                 file->current_layer);
966 //for(int i = 0; i < 10000; i++) frame->get_rows()[0][i] = 0xff;
967                         break;
968         }
972         return result;
977 int64_t FileMOV::compressed_frame_size()
979         if(!fd) return 0;
980         return quicktime_frame_size(fd, file->current_frame, file->current_layer);
983 int FileMOV::read_compressed_frame(VFrame *buffer)
985         int64_t result;
986         if(!fd) return 0;
988         result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
989         buffer->set_compressed_size(result);
990         buffer->set_keyframe((quicktime_get_keyframe_before(fd, 
991                 file->current_frame, 
992                 file->current_layer) == file->current_frame));
993         result = !result;
994         return result;
997 int FileMOV::write_compressed_frame(VFrame *buffer)
999         int result = 0;
1000         if(!fd) return 0;
1002         result = quicktime_write_frame(fd, 
1003                 buffer->get_data(), 
1004                 buffer->get_compressed_size(), 
1005                 file->current_layer);
1006         return result;
1011 int FileMOV::read_raw(VFrame *frame, 
1012                 float in_x1, float in_y1, float in_x2, float in_y2,
1013                 float out_x1, float out_y1, float out_x2, float out_y2, 
1014                 int use_float, int interpolate)
1016         int64_t i, color_channels, result = 0;
1017         if(!fd) return 0;
1019         quicktime_set_video_position(fd, file->current_frame, file->current_layer);
1020 // Develop importing strategy
1021         switch(frame->get_color_model())
1022         {
1023                 case BC_RGB888:
1024                         result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
1025                         break;
1026                 case BC_RGBA8888:
1027                         break;
1028                 case BC_RGB161616:
1029                         break;
1030                 case BC_RGBA16161616:
1031                         break;
1032                 case BC_YUV888:
1033                         break;
1034                 case BC_YUVA8888:
1035                         break;
1036                 case BC_YUV161616:
1037                         break;
1038                 case BC_YUVA16161616:
1039                         break;
1040                 case BC_YUV420P:
1041                         break;
1042         }
1043         return result;
1046 // Overlay samples
1047 int FileMOV::read_samples(double *buffer, int64_t len)
1049         int qt_track, qt_channel;
1051         if(!fd) return 0;
1053         if(quicktime_track_channels(fd, 0) > file->current_channel &&
1054                 quicktime_supported_audio(fd, 0))
1055         {
1057 //printf("FileMOV::read_samples 2 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1058                 new_audio_temp(len);
1060 //printf("FileMOV::read_samples 3 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1061                 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
1062                 {
1063                         printf("FileMOV::read_samples: quicktime_decode_audio failed\n");
1064                         return 1;
1065                 }
1066                 else
1067                 {
1068                         for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
1069                 }
1071 // if(file->current_channel == 0)
1072 // for(int i = 0; i < len; i++)
1073 // {
1074 //      int16_t value;
1075 //      value = (int16_t)(temp_float[0][i] * 32767);
1076 //      fwrite(&value, 2, 1, stdout);
1077 // }
1078 //printf("FileMOV::read_samples 4 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1079         }
1081         return 0;
1085 char* FileMOV::strtocompression(char *string)
1087         if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
1088         if(!strcasecmp(string, _(H264_NAME))) return QUICKTIME_H264;
1089         if(!strcasecmp(string, _(HV64_NAME))) return QUICKTIME_HV64;
1090         if(!strcasecmp(string, _(MP4V_NAME))) return QUICKTIME_MP4V;
1091         if(!strcasecmp(string, _(H263_NAME))) return QUICKTIME_H263;
1092         if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
1093         if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
1094         if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
1095         if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
1096         if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
1097         if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
1098         if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
1099         if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
1100         if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
1101         if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
1102         if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
1103         if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
1104         if(!strcasecmp(string, _(TWOVUY_NAME))) return QUICKTIME_2VUY;
1105         if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
1106         if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
1107         if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
1109         if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
1110         if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
1111         if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
1112         if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
1113         if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
1114         if(!strcasecmp(string, _(MP4A_NAME))) return QUICKTIME_MP4A;
1115         if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
1119         return QUICKTIME_RAW;
1122 char* FileMOV::compressiontostr(char *string)
1124         if(match4(string, QUICKTIME_H263)) return _(H263_NAME);
1125         if(match4(string, QUICKTIME_H264)) return _(H264_NAME);
1126         if(match4(string, QUICKTIME_HV64)) return _(HV64_NAME);
1127         if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1128         if(match4(string, QUICKTIME_MP4V)) return _(MP4V_NAME);
1129         if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1130         if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1131         if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1132         if(match4(string, QUICKTIME_DVCP)) return _(DV_NAME);
1133         if(match4(string, QUICKTIME_DVSD)) return _(DV_NAME);
1134         if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1135         if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1136         if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1137         if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1138         if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1139         if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1140         if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1141         if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1142         if(match4(string, QUICKTIME_2VUY)) return _(TWOVUY_NAME);
1143         if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1144         if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1145         if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1151         if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1152         if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1153         if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1154         if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1155         if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1156         if(match4(string, QUICKTIME_MP4A)) return _(MP4A_NAME);
1157         if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1161         return _("Unknown");
1168 ThreadStruct::ThreadStruct()
1170         input = 0;
1171         output = 0;
1172         output_allocated = 0;
1173         output_size = 0;
1174         completion_lock = new Condition(1, "ThreadStruct::completion_lock");
1177 ThreadStruct::~ThreadStruct()
1179         if(output) delete [] output;
1180         delete completion_lock;
1183 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1185         if(output_allocated < mjpeg_output_size(mjpeg))
1186         {
1187                 delete [] output;
1188                 output = 0;
1189         }
1190         if(!output)
1191         {
1192                 output_allocated = mjpeg_output_size(mjpeg);
1193                 output = new unsigned char[output_allocated];
1194         }
1195         
1196         output_size = mjpeg_output_size(mjpeg);
1197         memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1201 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields) : Thread()
1203         this->filemov = filemov;
1204         this->fields = fields;
1205         mjpeg = 0;
1206         input_lock = new Condition(1, "FileMOVThread::input_lock");
1209 FileMOVThread::~FileMOVThread()
1211         delete input_lock;
1214 int FileMOVThread::start_encoding()
1216         mjpeg = mjpeg_new(filemov->asset->width, 
1217                 filemov->asset->height, 
1218                 fields);
1219         mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1220         mjpeg_set_float(mjpeg, 0);
1221         done = 0;
1222         set_synchronous(1);
1223         input_lock->lock("FileMOVThread::start_encoding");
1224         start();
1227 int FileMOVThread::stop_encoding()
1229         done = 1;
1230         input_lock->unlock();
1231         join();
1232         if(mjpeg) mjpeg_delete(mjpeg);
1235 int FileMOVThread::encode_buffer()
1237         input_lock->unlock();
1240 void FileMOVThread::run()
1242         while(!done)
1243         {
1244                 input_lock->lock("FileMOVThread::run");
1246                 if(!done)
1247                 {
1248 // Get a frame to compress.
1249                         filemov->threadframe_lock->lock("FileMOVThread::stop_encoding");
1250                         if(filemov->current_threadframe < filemov->total_threadframes)
1251                         {
1252 // Frame is available to process.
1253                                 input_lock->unlock();
1254                                 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1255                                 VFrame *frame = threadframe->input;
1257                                 filemov->current_threadframe++;
1258                                 filemov->threadframe_lock->unlock();
1260                                 mjpeg_compress(mjpeg, 
1261                                         frame->get_rows(), 
1262                                         frame->get_y(), 
1263                                         frame->get_u(), 
1264                                         frame->get_v(),
1265                                         frame->get_color_model(),
1266                                         1);
1268                                 if(fields > 1)
1269                                 {
1270                                         unsigned char *data = mjpeg_output_buffer(mjpeg);
1271                                         long data_size = mjpeg_output_size(mjpeg);
1272                                         long data_allocated = mjpeg_output_allocated(mjpeg);
1273                                         long field2_offset;
1275                                         if(filemov->asset->format == FILE_MOV)
1276                                         {
1277                                                 mjpeg_insert_quicktime_markers(&data,
1278                                                         &data_size,
1279                                                         &data_allocated,
1280                                                         2,
1281                                                         &field2_offset);
1282                                         }
1283                                         else
1284                                         {
1285                                                 mjpeg_insert_avi_markers(&data,
1286                                                         &data_size,
1287                                                         &data_allocated,
1288                                                         2,
1289                                                         &field2_offset);
1290                                         }
1291                                         mjpeg_set_output_size(mjpeg, data_size);
1292                                 }
1293                                 threadframe->load_output(mjpeg);
1294                                 threadframe->completion_lock->unlock();
1295                         }
1296                         else
1297                                 filemov->threadframe_lock->unlock();
1298                 }
1299         }
1307 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1308  : BC_Window(PROGRAM_NAME ": Audio Compression",
1309         parent_window->get_abs_cursor_x(1),
1310         parent_window->get_abs_cursor_y(1),
1311         350,
1312         250)
1314         this->parent_window = parent_window;
1315         this->asset = asset;
1316         compression_popup = 0;
1317         reset();
1320 MOVConfigAudio::~MOVConfigAudio()
1322         if(compression_popup) delete compression_popup;
1323         if(bits_popup) delete bits_popup;
1324         compression_items.remove_all_objects();
1328 void MOVConfigAudio::reset()
1330         bits_popup = 0;
1331         bits_title = 0;
1332         dither = 0;
1333         vorbis_min_bitrate = 0;
1334         vorbis_bitrate = 0;
1335         vorbis_max_bitrate = 0;
1336         vorbis_vbr = 0;
1337         mp3_bitrate = 0;
1338         mp4a_bitrate = 0;
1339         mp4a_quantqual = 0;
1342 int MOVConfigAudio::create_objects()
1344         int x = 10, y = 10;
1347         if(asset->format == FILE_MOV)
1348         {
1349                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1350                 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1351                 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1352                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1353                 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1354                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1355                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1356         }
1357         else
1358         {
1359                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1360                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1361                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1362                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1363         }
1365         add_tool(new BC_Title(x, y, _("Compression:")));
1366         y += 25;
1367         compression_popup = new MOVConfigAudioPopup(this, x, y);
1368         compression_popup->create_objects();
1370         update_parameters();
1372         add_subwindow(new BC_OKButton(this));
1373         return 0;
1376 void MOVConfigAudio::update_parameters()
1378         int x = 10, y = 70;
1379         if(bits_title) delete bits_title;
1380         if(bits_popup) delete bits_popup;
1381         if(dither) delete dither;
1382         if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1383         if(vorbis_bitrate) delete vorbis_bitrate;
1384         if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1385         if(vorbis_vbr) delete vorbis_vbr;
1386         if(mp3_bitrate) delete mp3_bitrate;
1387         delete mp4a_bitrate;
1388         delete mp4a_quantqual;
1390         reset();
1394         if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1395                 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1396         {
1397                 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1398                 bits_popup = new BitsPopup(this, 
1399                         x + 150, 
1400                         y, 
1401                         &asset->bits, 
1402                         0, 
1403                         0, 
1404                         0, 
1405                         0, 
1406                         0);
1407                 bits_popup->create_objects();
1408                 y += 40;
1409                 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1410         }
1411         else
1412         if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1413         {
1414         }
1415         else
1416         if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1417         {
1418                 mp3_bitrate = new MOVConfigAudioNum(this, 
1419                         _("Bitrate:"), 
1420                         x, 
1421                         y, 
1422                         &asset->mp3_bitrate);
1423                 mp3_bitrate->set_increment(1000);
1424                 mp3_bitrate->create_objects();
1425         }
1426         else
1427         if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1428         {
1429         }
1430         else
1431         if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1432         {
1433                 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1434                         _("Variable bitrate"),
1435                         x,
1436                         y,
1437                         &asset->vorbis_vbr));
1438                 y += 35;
1439                 vorbis_min_bitrate = new MOVConfigAudioNum(this, 
1440                         _("Min bitrate:"), 
1441                         x, 
1442                         y, 
1443                         &asset->vorbis_min_bitrate);
1444                 vorbis_min_bitrate->set_increment(1000);
1445                 y += 30;
1446                 vorbis_bitrate = new MOVConfigAudioNum(this, 
1447                         _("Avg bitrate:"), 
1448                         x, 
1449                         y, 
1450                         &asset->vorbis_bitrate);
1451                 vorbis_bitrate->set_increment(1000);
1452                 y += 30;
1453                 vorbis_max_bitrate = new MOVConfigAudioNum(this, 
1454                         _("Max bitrate:"), 
1455                         x, 
1456                         y, 
1457                         &asset->vorbis_max_bitrate);
1458                 vorbis_max_bitrate->set_increment(1000);
1462                 vorbis_min_bitrate->create_objects();
1463                 vorbis_bitrate->create_objects();
1464                 vorbis_max_bitrate->create_objects();
1465         }
1466         else
1467         if(!strcasecmp(asset->acodec, QUICKTIME_MP4A))
1468         {
1469                 mp4a_bitrate = new MOVConfigAudioNum(this, 
1470                         _("Bitrate:"), 
1471                         x, 
1472                         y, 
1473                         &asset->mp4a_bitrate);
1474                 mp4a_bitrate->set_increment(1000);
1475                 mp4a_bitrate->create_objects();
1477                 y += 30;
1478                 mp4a_quantqual = new MOVConfigAudioNum(this, 
1479                         _("Quantization Quality (%):"), 
1480                         x, 
1481                         y, 
1482                         &asset->mp4a_quantqual);
1483                 mp4a_quantqual->set_increment(1);
1484                 mp4a_quantqual->create_objects();
1485         }
1488 int MOVConfigAudio::close_event()
1490         set_done(0);
1491         return 1;
1498 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1499         char *title_text,
1500         int x,
1501         int y,
1502         int *output)
1503  : BC_CheckBox(x, y, *output, title_text)
1505         this->popup = popup;
1506         this->output = output;
1508 int MOVConfigAudioToggle::handle_event()
1510         *output = get_value();
1511         return 1;
1518 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1519  : BC_TumbleTextBox(popup, 
1520                 (int64_t)*output,
1521                 (int64_t)-1,
1522                 (int64_t)25000000,
1523                 popup->get_w() - 150, 
1524                 y, 
1525                 100)
1527         this->popup = popup;
1528         this->title_text = title_text;
1529         this->output = output;
1530         this->x = x;
1531         this->y = y;
1534 MOVConfigAudioNum::~MOVConfigAudioNum()
1536         if(!popup->get_deleting()) delete title;
1539 void MOVConfigAudioNum::create_objects()
1541         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1542         BC_TumbleTextBox::create_objects();
1545 int MOVConfigAudioNum::handle_event()
1547         *output = atol(get_text());
1548         return 1;
1558 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1559  : BC_PopupTextBox(popup, 
1560                 &popup->compression_items,
1561                 FileMOV::compressiontostr(popup->asset->acodec),
1562                 x, 
1563                 y, 
1564                 300,
1565                 300)
1567         this->popup = popup;
1570 int MOVConfigAudioPopup::handle_event()
1572         strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1573         popup->update_parameters();
1574         return 1;
1593 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window, 
1594         Asset *asset, 
1595         int lock_compressor)
1596  : BC_Window(PROGRAM_NAME ": Video Compression",
1597         parent_window->get_abs_cursor_x(1),
1598         parent_window->get_abs_cursor_y(1),
1599         420,
1600         420)
1602         this->parent_window = parent_window;
1603         this->asset = asset;
1604         this->lock_compressor = lock_compressor;
1605         compression_popup = 0;
1606         reset();
1609 MOVConfigVideo::~MOVConfigVideo()
1611         if(compression_popup) delete compression_popup;
1612         compression_items.remove_all_objects();
1615 int MOVConfigVideo::create_objects()
1617         int x = 10, y = 10;
1619         if(asset->format == FILE_MOV)
1620         {
1621                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1622                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1623 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1624                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1625                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1626                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1627                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1628                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1629                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1630                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1631                 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1632                 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1633                 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1634                 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1635                 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1636                 compression_items.append(new BC_ListBoxItem(_(TWOVUY_NAME)));
1637                 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1638                 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1639                 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1640         }
1641         else
1642         {
1643                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1644                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1645 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1646                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1647                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1648                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1649                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1650                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1651                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1652                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1653         }
1655         add_subwindow(new BC_Title(x, y, _("Compression:")));
1656         y += 25;
1658         if(!lock_compressor)
1659         {
1660                 compression_popup = new MOVConfigVideoPopup(this, x, y);
1661                 compression_popup->create_objects();
1662         }
1663         else
1664         {
1665                 add_subwindow(new BC_Title(x, 
1666                         y, 
1667                         FileMOV::compressiontostr(asset->vcodec),
1668                         MEDIUMFONT,
1669                         RED,
1670                         0));
1671         }
1672         y += 40;
1674         param_x = x;
1675         param_y = y;
1676         update_parameters();
1678         add_subwindow(new BC_OKButton(this));
1679         return 0;
1682 int MOVConfigVideo::close_event()
1684         set_done(0);
1685         return 1;
1689 void MOVConfigVideo::reset()
1691         jpeg_quality = 0;
1692         jpeg_quality_title = 0;
1694         divx_bitrate = 0;
1695         divx_rc_period = 0;
1696         divx_rc_reaction_ratio = 0;
1697         divx_rc_reaction_period = 0;
1698         divx_max_key_interval = 0;
1699         divx_max_quantizer = 0;
1700         divx_min_quantizer = 0;
1701         divx_quantizer = 0;
1702         divx_quality = 0;
1703         divx_fix_bitrate = 0;
1704         divx_fix_quant = 0;
1706         h264_bitrate = 0;
1707         h264_quantizer = 0;
1708         h264_fix_bitrate = 0;
1709         h264_fix_quant = 0;
1711         ms_bitrate = 0;
1712         ms_bitrate_tolerance = 0;
1713         ms_quantization = 0;
1714         ms_interlaced = 0;
1715         ms_gop_size = 0;
1716         ms_fix_bitrate = 0;
1717         ms_fix_quant = 0;
1720 void MOVConfigVideo::update_parameters()
1722         if(jpeg_quality)
1723         {
1724                 delete jpeg_quality_title;
1725                 delete jpeg_quality;
1726         }
1728         if(divx_bitrate) delete divx_bitrate;
1729         if(divx_rc_period) delete divx_rc_period;
1730         if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1731         if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1732         if(divx_max_key_interval) delete divx_max_key_interval;
1733         if(divx_max_quantizer) delete divx_max_quantizer;
1734         if(divx_min_quantizer) delete divx_min_quantizer;
1735         if(divx_quantizer) delete divx_quantizer;
1736         if(divx_quality) delete divx_quality;
1737         if(divx_fix_quant) delete divx_fix_quant;
1738         if(divx_fix_bitrate) delete divx_fix_bitrate;
1740         if(ms_bitrate) delete ms_bitrate;
1741         if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1742         if(ms_interlaced) delete ms_interlaced;
1743         if(ms_quantization) delete ms_quantization;
1744         if(ms_gop_size) delete ms_gop_size;
1745         if(ms_fix_bitrate) delete ms_fix_bitrate;
1746         if(ms_fix_quant) delete ms_fix_quant;
1748         delete h264_bitrate;
1749         delete h264_quantizer;
1750         delete h264_fix_bitrate;
1751         delete h264_fix_quant;
1753         reset();
1756 // H264 parameters
1757         if(!strcmp(asset->vcodec, QUICKTIME_H264) ||
1758                 !strcmp(asset->vcodec, QUICKTIME_HV64))
1759         {
1760                 int x = param_x, y = param_y;
1761                 h264_bitrate = new MOVConfigVideoNum(this, 
1762                         _("Bitrate:"), 
1763                         x, 
1764                         y, 
1765                         &asset->h264_bitrate);
1766                 h264_bitrate->set_increment(1000000);
1767                 h264_bitrate->create_objects();
1768                 add_subwindow(h264_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260, 
1769                                 y,
1770                                 &asset->h264_fix_bitrate,
1771                                 1));
1772                 y += 30;
1773                 h264_quantizer = new MOVConfigVideoNum(this, 
1774                         _("Quantization:"), 
1775                         x, 
1776                         y, 
1777                         0,
1778                         51,
1779                         &asset->h264_quantizer);
1780                 h264_quantizer->create_objects();
1781                 add_subwindow(h264_fix_quant = new MOVConfigVideoFixQuant(x + 260, 
1782                                 y,
1783                                 &asset->h264_fix_bitrate,
1784                                 0));
1785                 h264_fix_bitrate->opposite = h264_fix_quant;
1786                 h264_fix_quant->opposite = h264_fix_bitrate;
1787         }
1788         else
1789 // ffmpeg parameters
1790         if(!strcmp(asset->vcodec, QUICKTIME_MP4V) ||
1791                 !strcmp(asset->vcodec, QUICKTIME_DIV3))
1792         {
1793                 int x = param_x, y = param_y;
1794                 ms_bitrate = new MOVConfigVideoNum(this, 
1795                         _("Bitrate:"), 
1796                         x, 
1797                         y, 
1798                         &asset->ms_bitrate);
1799                 ms_bitrate->set_increment(1000000);
1800                 ms_bitrate->create_objects();
1801                 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260, 
1802                                 y,
1803                                 &asset->ms_fix_bitrate,
1804                                 1));
1805                 y += 30;
1807                 ms_bitrate_tolerance = new MOVConfigVideoNum(this, 
1808                         _("Bitrate tolerance:"), 
1809                         x, 
1810                         y, 
1811                         &asset->ms_bitrate_tolerance);
1812                 ms_bitrate_tolerance->create_objects();
1813                 y += 30;
1814                 ms_quantization = new MOVConfigVideoNum(this, 
1815                         _("Quantization:"), 
1816                         x, 
1817                         y, 
1818                         &asset->ms_quantization);
1819                 ms_quantization->create_objects();
1820                 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260, 
1821                                 y,
1822                                 &asset->ms_fix_bitrate,
1823                                 0));
1824                 ms_fix_bitrate->opposite = ms_fix_quant;
1825                 ms_fix_quant->opposite = ms_fix_bitrate;
1828                 y += 30;
1829                 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"), 
1830                         x, 
1831                         y, 
1832                         &asset->ms_interlaced));
1833                 y += 30;
1834                 ms_gop_size = new MOVConfigVideoNum(this, 
1835                         _("Keyframe interval:"), 
1836                         x, 
1837                         y, 
1838                         &asset->ms_gop_size);
1839                 ms_gop_size->create_objects();
1840         }
1841         else
1842 // OpenDivx parameters
1843         if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
1844                 !strcmp(asset->vcodec, QUICKTIME_H263) ||
1845                 !strcmp(asset->vcodec, QUICKTIME_HV60))
1846         {
1847                 int x = param_x, y = param_y;
1848                 divx_bitrate = new MOVConfigVideoNum(this, 
1849                         _("Bitrate:"), 
1850                         x, 
1851                         y, 
1852                         &asset->divx_bitrate);
1853                 divx_bitrate->set_increment(1000000);
1854                 divx_bitrate->create_objects();
1855                 add_subwindow(divx_fix_bitrate = 
1856                         new MOVConfigVideoFixBitrate(x + 260, 
1857                                 y,
1858                                 &asset->divx_fix_bitrate,
1859                                 1));
1860                 y += 30;
1861                 divx_quantizer = new MOVConfigVideoNum(this, 
1862                         _("Quantizer:"), 
1863                         x, 
1864                         y, 
1865                         &asset->divx_quantizer);
1866                 divx_quantizer->create_objects();
1867                 add_subwindow(divx_fix_quant =
1868                         new MOVConfigVideoFixQuant(x + 260, 
1869                                 y,
1870                                 &asset->divx_fix_bitrate,
1871                                 0));
1872                 divx_fix_quant->opposite = divx_fix_bitrate;
1873                 divx_fix_bitrate->opposite = divx_fix_quant;
1874                 y += 30;
1875                 divx_rc_period = new MOVConfigVideoNum(this, 
1876                         _("RC Period:"), 
1877                         x, 
1878                         y, 
1879                         &asset->divx_rc_period);
1880                 divx_rc_period->create_objects();
1881                 y += 30;
1882                 divx_rc_reaction_ratio = new MOVConfigVideoNum(this, 
1883                         _("Reaction Ratio:"), 
1884                         x, 
1885                         y, 
1886                         &asset->divx_rc_reaction_ratio);
1887                 divx_rc_reaction_ratio->create_objects();
1888                 y += 30;
1889                 divx_rc_reaction_period = new MOVConfigVideoNum(this, 
1890                         _("Reaction Period:"), 
1891                         x, 
1892                         y, 
1893                         &asset->divx_rc_reaction_period);
1894                 divx_rc_reaction_period->create_objects();
1895                 y += 30;
1896                 divx_max_key_interval = new MOVConfigVideoNum(this, 
1897                         _("Max Key Interval:"), 
1898                         x, 
1899                         y, 
1900                         &asset->divx_max_key_interval);
1901                 divx_max_key_interval->create_objects();
1902                 y += 30;
1903                 divx_max_quantizer = new MOVConfigVideoNum(this, 
1904                         _("Max Quantizer:"), 
1905                         x, 
1906                         y, 
1907                         &asset->divx_max_quantizer);
1908                 divx_max_quantizer->create_objects();
1909                 y += 30;
1910                 divx_min_quantizer = new MOVConfigVideoNum(this, 
1911                         _("Min Quantizer:"), 
1912                         x, 
1913                         y, 
1914                         &asset->divx_min_quantizer);
1915                 divx_min_quantizer->create_objects();
1916                 y += 30;
1917                 divx_quality = new MOVConfigVideoNum(this, 
1918                         _("Quality:"), 
1919                         x, 
1920                         y, 
1921                         &asset->divx_quality);
1922                 divx_quality->create_objects();
1923         }
1924         else
1925         if(!strcmp(asset->vcodec, QUICKTIME_JPEG) ||
1926                 !strcmp(asset->vcodec, QUICKTIME_MJPA))
1927         {
1928                 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
1929                 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80, 
1930                         param_y,
1931                         0,
1932                         200,
1933                         200,
1934                         0,
1935                         100,
1936                         asset->jpeg_quality,
1937                         0,
1938                         0,
1939                         &asset->jpeg_quality));
1940         }
1947 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
1948  : BC_TumbleTextBox(popup, 
1949                 (int64_t)*output,
1950                 (int64_t)1,
1951                 (int64_t)25000000,
1952                 x + 130, 
1953                 y, 
1954                 100)
1956         this->popup = popup;
1957         this->title_text = title_text;
1958         this->output = output;
1959         this->x = x;
1960         this->y = y;
1963 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, 
1964         char *title_text, 
1965         int x, 
1966         int y, 
1967         int min,
1968         int max,
1969         int *output)
1970  : BC_TumbleTextBox(popup, 
1971                 (int64_t)*output,
1972                 (int64_t)min,
1973                 (int64_t)max,
1974                 x + 130, 
1975                 y, 
1976                 100)
1978         this->popup = popup;
1979         this->title_text = title_text;
1980         this->output = output;
1981         this->x = x;
1982         this->y = y;
1985 MOVConfigVideoNum::~MOVConfigVideoNum()
1987         if(!popup->get_deleting()) delete title;
1990 void MOVConfigVideoNum::create_objects()
1992         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1993         BC_TumbleTextBox::create_objects();
1996 int MOVConfigVideoNum::handle_event()
1998         *output = atol(get_text());
1999         return 1;
2008 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
2009  : BC_CheckBox(x, y, *output, title_text)
2011         this->output = output;
2014 int MOVConfigVideoCheckBox::handle_event()
2016         *output = get_value();
2017         return 1;
2025 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x, 
2026         int y,
2027         int *output,
2028         int value)
2029  : BC_Radial(x, 
2030         y, 
2031         *output == value, 
2032         _("Fix bitrate"))
2034         this->output = output;
2035         this->value = value;
2038 int MOVConfigVideoFixBitrate::handle_event()
2040         *output = value;
2041         opposite->update(0);
2042         return 1;
2050 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x, 
2051         int y,
2052         int *output,
2053         int value)
2054  : BC_Radial(x, 
2055         y, 
2056         *output == value, 
2057         _("Fix quantization"))
2059         this->output = output;
2060         this->value = value;
2063 int MOVConfigVideoFixQuant::handle_event()
2065         *output = value;
2066         opposite->update(0);
2067         return 1;
2074 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
2075  : BC_PopupTextBox(popup, 
2076                 &popup->compression_items,
2077                 FileMOV::compressiontostr(popup->asset->vcodec),
2078                 x, 
2079                 y, 
2080                 300,
2081                 300)
2083         this->popup = popup;
2086 int MOVConfigVideoPopup::handle_event()
2088         strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
2089         popup->update_parameters();
2090         return 1;