Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / cinelerra / filemov.C
blob72b588c1c94f54ee88ffea17ac0ad287bf8de1c1
1 #include "asset.h"
2 #include "bcsignals.h"
3 #include "bcwidgetgrid.h"
4 #include "bitspopup.h"
5 #include "byteorder.h"
6 #include "condition.h"
7 #include "edit.h"
8 #include "file.h"
9 #include "filemov.h"
10 #include "guicast.h"
11 #include "language.h"
12 #include "mutex.h"
13 #include "mwindow.inc"
14 #include "vframe.h"
15 #include "videodevice.inc"
16 #include "mainerror.h"
18 #include <unistd.h>
19 #include <libdv/dv.h>
21 #if 0
22 N_("MPEG-4")
23 N_("Dual H.264")
24 N_("Dual MPEG-4")
25 N_("H.264")
26 N_("H.263")
27 N_("Microsoft MPEG-4")
28 N_("DV")
29 N_("PNG")
30 N_("PNG with Alpha")
31 N_("Uncompressed RGB")
32 N_("Uncompressed RGBA")
33 N_("YUV 4:2:0 Planar")
34 N_("Component Y'CbCr 8-bit 4:2:2 (yuv2)")
35 N_("Component Y'CbCr 8-bit 4:2:2 (2vuy)")
36 N_("YUV 4:1:1 Packed")
37 N_("Component Y'CbCr 8-bit 4:4:4")
38 N_("Component Y'CbCrA 8-bit 4:4:4:4")
39 N_("Component Y'CbCr 10-bit 4:4:4")
40 N_("JPEG Photo")
41 N_("Motion JPEG A")
44 N_("Twos complement")
45 N_("Unsigned")
46 N_("IMA-4")
47 N_("U-Law")
48 N_("Vorbis")
49 N_("MP3")
50 N_("MPEG-4 Audio")
51 #endif
53 #define DIVX_NAME "MPEG-4"
54 #define HV64_NAME "Dual H.264"
55 #define MP4V_NAME "MPEG-4 Video"
56 #define H264_NAME "H.264"
57 #define H263_NAME "H.263"
58 #define HV60_NAME "Dual MPEG-4"
59 #define DIV3_NAME "Microsoft MPEG-4"
60 #define DV_NAME "DV"
61 #define PNG_NAME "PNG"
62 #define PNGA_NAME "PNG with Alpha"
63 #define RGB_NAME "Uncompressed RGB"
64 #define RGBA_NAME "Uncompressed RGBA"
65 #define YUV420_NAME "YUV 4:2:0 Planar"
66 #define YUV422_NAME "Component Y'CbCr 8-bit 4:2:2 (yuv2)"
67 #define TWOVUY_NAME "Component Y'CbCr 8-bit 4:2:2 (2vuy)"
68 #define YUV411_NAME "YUV 4:1:1 Packed"
69 #define YUV444_NAME "Component Y'CbCr 8-bit 4:4:4"
70 #define YUVA4444_NAME "Component Y'CbCrA 8-bit 4:4:4:4"
71 #define YUV444_10BIT_NAME "Component Y'CbCr 10-bit 4:4:4"
72 #define QTJPEG_NAME "JPEG Photo"
73 #define MJPA_NAME "Motion JPEG A"
75 #define TWOS_NAME "Twos complement"
76 #define RAW_NAME "Unsigned"
77 #define IMA4_NAME "IMA-4"
78 #define ULAW_NAME "U-Law"
79 //#define VORBIS_NAME "Vorbis"
80 #define MP3_NAME "MP3"
81 #define MP4A_NAME "MPEG-4 Audio"
82 #define VORBIS_NAME "OGG Vorbis"
88 FileMOV::FileMOV(Asset_GC asset, File *file)
89  : FileBase(asset, file)
91         reset_parameters();
92         if(asset->format == FILE_UNKNOWN)
93                 asset->format = FILE_MOV;
94         asset->byte_order = 0;
95         suffix_number = 0;
96         threadframe_lock = new Mutex("FileMOV::threadframe_lock");
99 FileMOV::~FileMOV()
101 SET_TRACE
102         close_file();
103 SET_TRACE
104         delete threadframe_lock;
105 SET_TRACE
108 void FileMOV::get_parameters(BC_WindowBase *parent_window, 
109         Asset_GC asset, 
110         BC_WindowBase* &format_window,
111         int audio_options,
112         int video_options,
113         char *locked_compressor)
115         fix_codecs(asset);
116         if(audio_options)
117         {
118                 MOVConfigAudio *window = new MOVConfigAudio(parent_window, asset);
119                 format_window = window;
120                 window->create_objects();
121                 window->run_window();
122                 delete window;
123         }
124         else
125         if(video_options)
126         {
127                 MOVConfigVideo *window = new MOVConfigVideo(parent_window, 
128                         asset, 
129                         locked_compressor);
130                 format_window = window;
131                 window->create_objects();
132                 window->run_window();
133                 delete window;
134         }
137 void FileMOV::fix_codecs(Asset_GC asset)
139         if(!strcasecmp(asset->vcodec, QUICKTIME_DV) ||
140            !strcasecmp(asset->vcodec, QUICKTIME_DVSD) ||
141            !strcasecmp(asset->vcodec, QUICKTIME_DVCP))
142         {
143 //        printf("AF: %i, AH: %i, VC: %s\n", asset->format, asset->height, asset->vcodec);
144         if (asset->format == FILE_AVI)
145                 strcpy (asset->vcodec, QUICKTIME_DVSD);
146         else if (asset->format == FILE_MOV && asset->height == 576)
147                 strcpy (asset->vcodec, QUICKTIME_DVCP);
148         else if (asset->format == FILE_MOV && asset->height == 480)
149                 strcpy (asset->vcodec, QUICKTIME_DV);
150         }
154 int FileMOV::check_codec_params(Asset_GC asset)
156         if(!strcasecmp(asset->vcodec, QUICKTIME_DV) ||
157            !strcasecmp(asset->vcodec, QUICKTIME_DVSD) ||
158            !strcasecmp(asset->vcodec, QUICKTIME_DVCP))
159         {
161                 if (!(asset->height == 576 && asset->width == 720) &&
162                     !(asset->height == 480 && asset->width == 720))
163                 {
164                         eprintf("DV in Quicktime container does not support following resolution: %ix%i\nAllowed resolutions are 720x576 (PAL) and 720x480 (NTSC)\n", asset->width, asset->height);
165                         return 1;
166                 }
167         }
168         return 0;
171 int FileMOV::check_sig(Asset_GC asset)
173         return quicktime_check_sig(asset->path);
177 int FileMOV::reset_parameters_derived()
179         fd = 0;
180         prev_track = 0;
181         quicktime_atracks = 0;
182         quicktime_vtracks = 0;
183         depth = 24;
184         threads = 0;
185         frames_correction = 0;
186         samples_correction = 0;
187         temp_float = 0;
188         temp_allocated = 0;
192 // Just create the Quicktime objects since this routine is also called
193 // for reopening.
194 int FileMOV::open_file(int rd, int wr)
197         this->rd = rd;
198         this->wr = wr;
200         if(suffix_number == 0) strcpy(prefix_path, asset->path);
202         if(!(fd = quicktime_open(asset->path, rd, wr)))
203         {
204                 eprintf("Error while opening file \"%s\". \n%m\n", asset->path);
205                 return 1;
206         }
208         quicktime_set_cpus(fd, file->cpus);
210         if(rd) format_to_asset();
212         if(wr) 
213         {
214                 asset_to_format();
215                 if (check_codec_params(asset))
216                         return 1;
217         }
218 // Set decoding parameter
219         quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking);
221 // Set timecode offset
222         quicktime_set_frame_start(fd, asset->tcstart);
224         return 0;
227 int FileMOV::close_file()
229 //printf("FileMOV::close_file 1 %s\n", asset->path);
230         if(fd)
231         {
232                 if(wr) quicktime_set_framerate(fd, asset->frame_rate);
233                 quicktime_close(fd);
234         }
236 //printf("FileMOV::close_file 1\n");
237         if(threads)
238         {
239                 for(int i = 0; i < file->cpus; i++)
240                 {
241                         threads[i]->stop_encoding();
242                         delete threads[i];
243                 }
244                 delete [] threads;
245                 threads = 0;
246         }
248 //printf("FileMOV::close_file 1\n");
249         threadframes.remove_all_objects();
252         if(temp_float) 
253         {
254                 for(int i = 0; i < asset->channels; i++)
255                         delete [] temp_float[i];
256                 delete [] temp_float;
257         }
259 //printf("FileMOV::close_file 1\n");
260         reset_parameters();
261         FileBase::close_file();
262 //printf("FileMOV::close_file 2\n");
263         return 0;
266 void FileMOV::set_frame_start(int64_t offset)
268         quicktime_set_frame_start(fd, offset);
271 void FileMOV::asset_to_format()
273         if(!fd) return;
274         char audio_codec[5];
276         fix_codecs(asset);
278 // Fix up the Quicktime file.
279         quicktime_set_copyright(fd, _("Made with Cinelerra for Linux"));
280         quicktime_set_info(fd, "Quicktime for Linux");
282         if(asset->audio_data)
283         {
284                 quicktime_atracks = quicktime_set_audio(fd, 
285                                 asset->channels, 
286                                 asset->sample_rate, 
287                                 asset->bits, 
288                                 asset->acodec);
289                 quicktime_set_parameter(fd, "vorbis_vbr", &asset->vorbis_vbr);
290                 quicktime_set_parameter(fd, "vorbis_min_bitrate", &asset->vorbis_min_bitrate);
291                 quicktime_set_parameter(fd, "vorbis_bitrate", &asset->vorbis_bitrate);
292                 quicktime_set_parameter(fd, "vorbis_max_bitrate", &asset->vorbis_max_bitrate);
293                 quicktime_set_parameter(fd, "mp3_bitrate", &asset->mp3_bitrate);
294                 quicktime_set_parameter(fd, "mp4a_bitrate", &asset->mp4a_bitrate);
295         }
297         if(asset->video_data)
298         {
299                 char string[16];
300 // Set up the alpha channel compressors
301                 if(!strcmp(asset->vcodec, MOV_RGBA))
302                 {
303                         strcpy(string, QUICKTIME_RAW);
304                         depth = 32;
305                 }
306                 else
307                 if(!strcmp(asset->vcodec, MOV_PNGA))
308                 {
309                         strcpy(string, QUICKTIME_PNG);
310                         depth = 32;
311                 }
312                 else
313                 if(!strcmp(asset->vcodec, QUICKTIME_YUVA4444))
314                 {
315                         strcpy(string, asset->vcodec);
316                         depth = 32;
317                 }
318                 else
319                 {
320                         strcpy(string, asset->vcodec);
321                         depth = 24;
322                 }
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         }
365         if(wr && asset->format == FILE_AVI)
366         {
367                 quicktime_set_avi(fd, 1);
368         }
372 void FileMOV::format_to_asset()
374         if(!fd) return;
376         if(quicktime_is_avi(fd)) asset->format = FILE_AVI;
377         asset->audio_data = quicktime_has_audio(fd);
378         if(asset->audio_data)
379         {
380                 asset->channels = 0;
381                 int qt_tracks = quicktime_audio_tracks(fd);
382                 for(int i = 0; i < qt_tracks; i++)
383                         asset->channels += quicktime_track_channels(fd, i);
384         
385                 if(!asset->sample_rate)
386                         asset->sample_rate = quicktime_sample_rate(fd, 0);
387                 asset->bits = quicktime_audio_bits(fd, 0);
388                 asset->audio_length = quicktime_audio_length(fd, 0);
389                 strncpy(asset->acodec, quicktime_audio_compressor(fd, 0), 4);
390         }
392 // determine if the video can be read before declaring video data
393         if(quicktime_has_video(fd) && quicktime_supported_video(fd, 0))
394                         asset->video_data = 1;
396         if(asset->video_data)
397         {
398                 depth = quicktime_video_depth(fd, 0);
399                 asset->layers = quicktime_video_tracks(fd);
400                 asset->width = quicktime_video_width(fd, 0);
401                 asset->height = quicktime_video_height(fd, 0);
402                 asset->video_length = quicktime_video_length(fd, 0);
403 // Don't want a user configured frame rate to get destroyed
404                 if(!asset->frame_rate)
405                         asset->frame_rate = quicktime_frame_rate(fd, 0);
406                 if(!asset->interlace_mode)
407                         asset->interlace_mode = quicktime_video_interlacemode(fd, 0);
409                 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
411                 // If DV stream, get the timecode 
412                 // This should become part of libquicktime functionality... for all formats
413                 if(match4(asset->vcodec, QUICKTIME_DV))
414                 {
415                         char tc[12];
416                         dv_decoder_t *tmp_decoder = dv_decoder_new(0,0,0);
417                         VFrame *frame = new VFrame(0, 0, 0, BC_COMPRESSED);
418                         
419                         read_frame(frame);
420                         set_video_position(0);
421                         
422                         if(dv_parse_header(tmp_decoder, frame->get_data()) > -1)
423                         {
424                                 dv_parse_packs(tmp_decoder, frame->get_data());
425                                 dv_get_timestamp(tmp_decoder, tc);
426 //                              printf("Timestamp %s\n", tc);
427                         
428                                 float seconds = Units::text_to_seconds(tc,
429                                                                                 1, // Use 1 as sample rate, doesn't matter
430                                                                                 TIME_HMSF,
431                                                                                 asset->frame_rate,
432                                                                                 0);
433                                 // Set tcstart if it hasn't been set yet, this is a bit problematic
434                                 // 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
435                                 if (asset->tcstart == 0)
436                                         asset->tcstart = int64_t(seconds * asset->frame_rate);
437                         }
438                         delete frame;
439                         dv_decoder_free(tmp_decoder);
440                         
441                 }
444         }
447 int64_t FileMOV::get_memory_usage()
449         if(rd && fd)
450         {
451                 int64_t result = quicktime_memory_usage(fd);
452 //printf("FileMOV::get_memory_usage 1 %d\n", result);
453                 return result;
454         }
455         return 0;
458 int FileMOV::colormodel_supported(int colormodel)
460         return colormodel;
463 int FileMOV::get_best_colormodel(Asset_GC asset, int driver)
465         switch(driver)
466         {
467                 case PLAYBACK_X11:
468                         return BC_RGB888;
469                         break;
470                 case PLAYBACK_X11_XV:
471                 case PLAYBACK_ASYNCHRONOUS:
472                         if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
473                         if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422;
474                         if(match4(asset->vcodec, QUICKTIME_2VUY)) return BC_YUV422;
475                         if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
476                         if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
477                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
478                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
479                         if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
480                         if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
481                         if(match4(asset->vcodec, QUICKTIME_DVCP)) return BC_YUV422;
482                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
483                         if(match4(asset->vcodec, QUICKTIME_MP4V)) return BC_YUV420P;
484                         if(match4(asset->vcodec, QUICKTIME_H263)) return BC_YUV420P;
485                         if(match4(asset->vcodec, QUICKTIME_H264)) return BC_YUV420P;
486                         if(match4(asset->vcodec, QUICKTIME_HV64)) return BC_YUV420P;
487                         if(match4(asset->vcodec, QUICKTIME_DIV3) ||
488                                 match4(asset->vcodec, QUICKTIME_SVQ3)) return BC_YUV420P;
489                         break;
490                 case PLAYBACK_X11_GL:
491                         if(match4(asset->vcodec, QUICKTIME_YUV420) ||
492                                 match4(asset->vcodec, QUICKTIME_YUV422) ||
493                                 match4(asset->vcodec, QUICKTIME_2VUY) ||
494                                 match4(asset->vcodec, QUICKTIME_JPEG) ||
495                                 match4(asset->vcodec, QUICKTIME_MJPA) ||
496                                 match4(asset->vcodec, QUICKTIME_DV) ||
497                                 match4(asset->vcodec, QUICKTIME_DVCP) ||
498                                 match4(asset->vcodec, QUICKTIME_DVSD) ||
499                                 match4(asset->vcodec, QUICKTIME_HV60) ||
500                                 match4(asset->vcodec, QUICKTIME_DIVX) ||
501                                 match4(asset->vcodec, QUICKTIME_DVSD) ||
502                                 match4(asset->vcodec, QUICKTIME_MP4V) ||
503                                 match4(asset->vcodec, QUICKTIME_H263) ||
504                                 match4(asset->vcodec, QUICKTIME_H264) ||
505                                 match4(asset->vcodec, QUICKTIME_HV64) ||
506                                 match4(asset->vcodec, QUICKTIME_DIV3) || 
507                                 match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV888;
508                         break;
509                 case PLAYBACK_DV1394:
510                 case PLAYBACK_FIREWIRE:
511                         if(match4(asset->vcodec, QUICKTIME_DV) || 
512                                 match4(asset->vcodec, QUICKTIME_DVSD) || 
513                                 match4(asset->vcodec, QUICKTIME_DVCP)) return BC_COMPRESSED;
514                         return BC_YUV422P;
515                         break;
516                 case PLAYBACK_LML:
517                 case PLAYBACK_BUZ:
518                         if(match4(asset->vcodec, QUICKTIME_MJPA)) 
519                                 return BC_COMPRESSED;
520                         else
521                                 return BC_YUV422P;
522                         break;
523                 case VIDEO4LINUX:
524                 case VIDEO4LINUX2:
525                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
526                         else
527                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
528                         else
529                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
530                         else
531                         if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
532                         else
533                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
534                         else
535                         if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
536                         else
537                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
538                         else
539                         if(!strncasecmp(asset->vcodec, QUICKTIME_H263, 4)) return BC_YUV420P;
540                         else
541                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
542                         break;
543                 case CAPTURE_BUZ:
544                 case CAPTURE_LML:
545                 case VIDEO4LINUX2JPEG:
546                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) 
547                                 return BC_COMPRESSED;
548                         else
549                                 return BC_YUV422;
550                         break;
551                 case CAPTURE_FIREWIRE:
552                 case CAPTURE_IEC61883:
553                         if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4) ||
554                                 !strncasecmp(asset->vcodec, QUICKTIME_DVSD, 4) ||
555                                 !strncasecmp(asset->vcodec, QUICKTIME_DVCP, 4)) 
556                                 return BC_COMPRESSED;
557                         else
558                                 return BC_YUV422;
559                         break;
560         }
561         return BC_RGB888;
564 int FileMOV::can_copy_from(Edit *edit, int64_t position)
566         if(!fd) return 0;
568 //printf("FileMOV::can_copy_from 1 %d %s %s\n", edit->asset->format, edit->asset->vcodec, this->asset->vcodec);
569         if(edit->asset->format == FILE_JPEG_LIST && 
570                 match4(this->asset->vcodec, QUICKTIME_JPEG))
571                 return 1;
572         else
573         if((edit->asset->format == FILE_MOV || 
574                 edit->asset->format == FILE_AVI))
575         {
576 //printf("FileMOV::can_copy_from %s %s\n", edit->asset->vcodec, this->asset->vcodec);
577                 if(match4(edit->asset->vcodec, this->asset->vcodec))
578                         return 1;
579 // there are combinations where the same codec has multiple fourcc codes
580 // check for DV...
581                 int is_edit_dv = 0;
582                 int is_this_dv = 0;
583                 if (match4(edit->asset->vcodec, QUICKTIME_DV) || 
584                         match4(edit->asset->vcodec, QUICKTIME_DVSD) || 
585                         match4(edit->asset->vcodec, QUICKTIME_DVCP))
586                         is_edit_dv = 1;
587                 if (match4(this->asset->vcodec, QUICKTIME_DV) || 
588                         match4(this->asset->vcodec, QUICKTIME_DVSD) || 
589                         match4(this->asset->vcodec, QUICKTIME_DVCP))
590                         is_this_dv = 1;
591                 if (is_this_dv && is_edit_dv)
592                         return 1;
593         }
594         else
595         if(edit->asset->format == FILE_RAWDV)
596         {
597                 if(match4(this->asset->vcodec, QUICKTIME_DV) || 
598                         match4(this->asset->vcodec, QUICKTIME_DVSD) || 
599                         match4(this->asset->vcodec, QUICKTIME_DVCP))
600                         return 1;
601         }
604         return 0;
608 int64_t FileMOV::get_audio_length()
610         if(!fd) return 0;
611         int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
613         return result;
616 int FileMOV::set_audio_position(int64_t x)
618         if(!fd) return 1;
619 // quicktime sets positions for each track seperately so store position in audio_position
620         if(x >= 0 && x < asset->audio_length)
621                 return quicktime_set_audio_position(fd, x, 0);
622         else
623                 return 1;
626 int FileMOV::set_video_position(int64_t x)
628         if(!fd) return 1;
629         if(x >= 0 && x < asset->video_length)
630         {
631                 int result = quicktime_set_video_position(fd, x, file->current_layer);
632                 return result;
633         }else
634                 return 1;
638 void FileMOV::new_audio_temp(int64_t len)
640         if(temp_allocated && temp_allocated < len)
641         {
642                 for(int i = 0; i < asset->channels; i++)
643                         delete [] temp_float[i];
644                 delete [] temp_float;
645                 temp_allocated = 0;
646         }
648         if(!temp_allocated)
649         {
650                 temp_allocated = len;
651                 temp_float = new float*[asset->channels];
652                 for(int i = 0; i < asset->channels; i++)
653                         temp_float[i] = new float[len];
654         }
659 int FileMOV::write_samples(double **buffer, int64_t len)
661         int i, j;
662         int64_t bytes;
663         int result = 0, track_channels = 0;
664         int chunk_size;
666         if(!fd) return 0;
668         if(quicktime_supported_audio(fd, 0))
669         {
670 // Use Quicktime's compressor. (Always used)
671 // Allocate temp buffer
672                 new_audio_temp(len);
674 // Copy to float buffer
675                 for(i = 0; i < asset->channels; i++)
676                 {
677                         for(j = 0; j < len; j++)
678                         {
679                                 temp_float[i][j] = buffer[i][j];
680                         }
681                 }
683 // Because of the way Quicktime's compressors work we want to limit the chunk
684 // size to speed up decompression.
685                 float **channel_ptr;
686                 channel_ptr = new float*[asset->channels];
688                 for(j = 0; j < len && !result; )
689                 {
690                         chunk_size = asset->sample_rate;
691                         if(j + chunk_size > len) chunk_size = len - j;
693                         for(i = 0; i < asset->channels; i++)
694                         {
695                                 channel_ptr[i] = &temp_float[i][j];
696                         }
698                         result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
699                         j += asset->sample_rate;
700                 }
702                 delete [] channel_ptr;
703         }
704         return result;
707 int FileMOV::write_frames(VFrame ***frames, int len)
709 //printf("FileMOV::write_frames 1\n");
710         int i, j, k, result = 0;
711         int default_compressor = 1;
712         if(!fd) return 0;
714         for(i = 0; i < asset->layers && !result; i++)
715         {
721 // Fix direct copy cases for format conversions.
722                 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
723                 {
724                         default_compressor = 0;
725                         for(j = 0; j < len && !result; j++)
726                         {
727                                 VFrame *frame = frames[i][j];
731 // Special handling for DIVX
732 // Determine keyframe status.
733 // Write VOL header in the first frame if none exists
734                                 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
735                                         !strcmp(asset->vcodec, QUICKTIME_H263) ||
736                                         !strcmp(asset->vcodec, QUICKTIME_HV60))
737                                 {
738                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
739                                                 frame->get_compressed_size(),
740                                                 asset->vcodec))
741                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
744 // Write header
745                                         if(!(file->current_frame + j) && 
746                                                 !quicktime_mpeg4_has_vol(frame->get_data()))
747                                         {
748                                                 VFrame *temp_frame = new VFrame;
750                                                 temp_frame->allocate_compressed_data(frame->get_compressed_size() + 
751                                                         0xff);
752                                                 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
753                                                         asset->width, 
754                                                         asset->height, 
755                                                         60000, 
756                                                         asset->frame_rate);
757                                                 memcpy(temp_frame->get_data() + bytes, 
758                                                         frame->get_data(), 
759                                                         frame->get_compressed_size());
760                                                 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
762                                                 result = quicktime_write_frame(fd,
763                                                         temp_frame->get_data(),
764                                                         temp_frame->get_compressed_size(),
765                                                         i);
767                                                 delete temp_frame;
770                                         }
771                                         else
772                                         {
773                                                 result = quicktime_write_frame(fd,
774                                                         frame->get_data(),
775                                                         frame->get_compressed_size(),
776                                                         i);
777                                         }
778                                 }
779                                 else
780 // Determine keyframe status
781                                 if(!strcmp(asset->vcodec, QUICKTIME_H264) ||
782                                         !strcmp(asset->vcodec, QUICKTIME_HV64) ||
783                                         !strcmp(asset->vcodec, QUICKTIME_MP4V))
784                                 {
785                                         if(frame->get_keyframe() || file->current_frame + j == 0)
786                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
788 // Write frame
789                                                 result = quicktime_write_frame(fd,
790                                                         frame->get_data(),
791                                                         frame->get_compressed_size(),
792                                                         i);
793                                 }
794                                 else
795                                 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
796                                 {
797                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
798                                                 frame->get_compressed_size(),
799                                                 asset->vcodec))
800                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
801                                         result = quicktime_write_frame(fd,
802                                                 frame->get_data(),
803                                                 frame->get_compressed_size(),
804                                                 i);
805                                 }
806                                 else
807                                 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
808                                 {
809                                         long field2_offset;
811 // Create extra space for markers
812                                         if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
813                                                 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
815                                         unsigned char *data = frame->get_data();
816                                         long data_size = frame->get_compressed_size();
817                                         long data_allocated = frame->get_compressed_allocated();
819 // Sometimes get 0 length frames
820                                         if(data_size)
821                                         {
822                                                 if(asset->format == FILE_MOV)
823                                                 {
824                                                         mjpeg_insert_quicktime_markers(&data,
825                                                                 &data_size,
826                                                                 &data_allocated,
827                                                                 2,
828                                                                 &field2_offset);
829                                                 }
830                                                 else
831                                                 {
832                                                         mjpeg_insert_avi_markers(&data,
833                                                                 &data_size,
834                                                                 &data_allocated,
835                                                                 2,
836                                                                 &field2_offset);
837                                                 }
838                                                 frame->set_compressed_size(data_size);
839                                                 result = quicktime_write_frame(fd,
840                                                         frame->get_data(),
841                                                         frame->get_compressed_size(),
842                                                         i);
843                                         }
844                                         else
845                                         {
846                                                 eprintf("data_size=%d\n", data_size);
847                                         }
848                                 }
849                                 else
850                                         result = quicktime_write_frame(fd,
851                                                 frame->get_data(),
852                                                 frame->get_compressed_size(),
853                                                 i);
854                                 
855                                 
856                         }
857                 }
858                 else
859                 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
860                         match4(asset->vcodec, QUICKTIME_2VUY) ||
861                         match4(asset->vcodec, QUICKTIME_YUV422) ||
862                         match4(asset->vcodec, QUICKTIME_RAW))
863                 {
864 // Direct copy planes where possible
865                         default_compressor = 0;
866                         for(j = 0; j < len && !result; j++)
867                         {
868                                 VFrame *frame = frames[i][j];
869 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
870                                 quicktime_set_cmodel(fd, frame->get_color_model());
871                                 if(cmodel_is_planar(frame->get_color_model()))
872                                 {
873                                         unsigned char *planes[3];
874                                         planes[0] = frame->get_y();
875                                         planes[1] = frame->get_u();
876                                         planes[2] = frame->get_v();
877                                         result = quicktime_encode_video(fd, planes, i);
878                                 }
879                                 else
880                                 {
881                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
882 //printf("FileMOV::write_frames 2 %d\n", result);
883                                 }
884 //printf("FileMOV::write_frames 2\n");
885                         }
886                 }
887                 else
888                 if(file->cpus > 1 && 
889                         (match4(asset->vcodec, QUICKTIME_JPEG) || 
890                         match4(asset->vcodec, QUICKTIME_MJPA)))
891                 {
892                         default_compressor = 0;
893 // Compress symmetrically on an SMP system.
894                         ThreadStruct *threadframe;
895                         int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
897 // Set up threads for symmetric compression.
898                         if(!threads)
899                         {
900                                 threads = new FileMOVThread*[file->cpus];
901                                 for(j = 0; j < file->cpus; j++)
902                                 {
903                                         threads[j] = new FileMOVThread(this, fields);
904                                         threads[j]->start_encoding();
905                                 }
906                         }
908 // Set up the frame structures for asynchronous compression.
909 // The mjpeg object must exist in each threadframe because it is where the output
910 // is stored.
911                         while(threadframes.total < len)
912                         {
913                                 threadframes.append(threadframe = new ThreadStruct);
914                         }
916 // Load thread frame structures with new frames.
917                         for(j = 0; j < len; j++)
918                         {
919                                 VFrame *frame = frames[i][j];
920                                 threadframes.values[j]->input = frame;
921                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
922                         }
923                         total_threadframes = len;
924                         current_threadframe = 0;
926 // Start the threads compressing
927                         for(j = 0; j < file->cpus; j++)
928                         {
929                                 threads[j]->encode_buffer();
930                         }
933 // Write the frames as they're finished
934                         for(j = 0; j < len; j++)
935                         {
936                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
937                                 threadframes.values[j]->completion_lock->unlock();
938                                 if(!result)
939                                 {
940                                         result = quicktime_write_frame(fd, 
941                                                 threadframes.values[j]->output,
942                                                 threadframes.values[j]->output_size,
943                                                 i);
944                                 }
945                         }
946                 }
948                 if(default_compressor)
949                 {
950 //printf("FileMOV::write_frames 3\n");
951 // Use the library's built in compressor.
952                         for(j = 0; j < len && !result; j++)
953                         {
954 //printf("FileMOV::write_frames 4\n");
955                                 VFrame *frame = frames[i][j];
956                                 quicktime_set_cmodel(fd, frame->get_color_model());
957 //printf("FileMOV::write_frames 5\n");
958                                 if(cmodel_is_planar(frame->get_color_model()))
959                                 {
960                                         unsigned char *planes[3];
961                                         planes[0] = frame->get_y();
962                                         planes[1] = frame->get_u();
963                                         planes[2] = frame->get_v();
964                                         result = quicktime_encode_video(fd, planes, i);
965                                 }
966                                 else
967                                 {
968                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
969                                 }
970                         }
971                 }
972 //printf("FileMOV::write_frames 4\n");
973         }
976 //printf("FileMOV::write_frames 100 %d\n", result);
977         return result;
982 int FileMOV::read_frame(VFrame *frame)
984         if(!fd) return 1;
985         int result = 0;
987         switch(frame->get_color_model())
988         {
989                 case BC_COMPRESSED:
990                         frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
991                         frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
992                         frame->set_keyframe((quicktime_get_keyframe_before(fd, 
993                                 file->current_frame, 
994                                 file->current_layer) == file->current_frame));
995 //printf("FileMOV::read_frame 1 %lld %d\n", file->current_frame, frame->get_keyframe());
996                         result = !quicktime_read_frame(fd, 
997                                 frame->get_data(), 
998                                 file->current_layer);
999                         break;
1001 // Progressive
1002                 case BC_YUV420P:
1003                 case BC_YUV422P:
1004                 {
1005                         unsigned char *row_pointers[3];
1006                         row_pointers[0] = frame->get_y();
1007                         row_pointers[1] = frame->get_u();
1008                         row_pointers[2] = frame->get_v();
1010                         quicktime_set_cmodel(fd, frame->get_color_model());
1011                         result = quicktime_decode_video(fd, 
1012                                 row_pointers,
1013                                 file->current_layer);
1014                 }
1015                         break;
1017 // Packed
1018                 default:
1019                         quicktime_set_cmodel(fd, frame->get_color_model());
1020                         result = quicktime_decode_video(fd, 
1021                                 frame->get_rows(),
1022                                 file->current_layer);
1023 //for(int i = 0; i < 10000; i++) frame->get_rows()[0][i] = 0xff;
1024                         break;
1025         }
1026         if (result)
1027         {
1028                 eprintf("quicktime_read_frame/quicktime_decode_video failed, result:\n");
1029         }
1033         return result;
1038 int64_t FileMOV::compressed_frame_size()
1040         if(!fd) return 0;
1041         return quicktime_frame_size(fd, file->current_frame, file->current_layer);
1044 int FileMOV::read_compressed_frame(VFrame *buffer)
1046         int64_t result;
1047         if(!fd) return 0;
1049         result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
1050         buffer->set_compressed_size(result);
1051         buffer->set_keyframe((quicktime_get_keyframe_before(fd, 
1052                 file->current_frame, 
1053                 file->current_layer) == file->current_frame));
1054         result = !result;
1055         return result;
1058 int FileMOV::write_compressed_frame(VFrame *buffer)
1060         int result = 0;
1061         if(!fd) return 0;
1063         result = quicktime_write_frame(fd, 
1064                 buffer->get_data(), 
1065                 buffer->get_compressed_size(), 
1066                 file->current_layer);
1067         return result;
1072 int FileMOV::read_raw(VFrame *frame, 
1073                 float in_x1, float in_y1, float in_x2, float in_y2,
1074                 float out_x1, float out_y1, float out_x2, float out_y2, 
1075                 int use_float, int interpolate)
1077         int64_t i, color_channels, result = 0;
1078         if(!fd) return 0;
1080         quicktime_set_video_position(fd, file->current_frame, file->current_layer);
1081 // Develop importing strategy
1082         switch(frame->get_color_model())
1083         {
1084                 case BC_RGB888:
1085                         result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
1086                         break;
1087                 case BC_RGBA8888:
1088                         break;
1089                 case BC_RGB161616:
1090                         break;
1091                 case BC_RGBA16161616:
1092                         break;
1093                 case BC_YUV888:
1094                         break;
1095                 case BC_YUVA8888:
1096                         break;
1097                 case BC_YUV161616:
1098                         break;
1099                 case BC_YUVA16161616:
1100                         break;
1101                 case BC_YUV420P:
1102                         break;
1103         }
1104         return result;
1107 // Overlay samples
1108 int FileMOV::read_samples(double *buffer, int64_t len)
1110         int qt_track, qt_channel;
1112         if(!fd) return 0;
1114         if(quicktime_track_channels(fd, 0) > file->current_channel &&
1115                 quicktime_supported_audio(fd, 0))
1116         {
1118 //printf("FileMOV::read_samples 2 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1119                 new_audio_temp(len);
1121 //printf("FileMOV::read_samples 3 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1122                 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
1123                 {
1124                         eprintf("quicktime_decode_audio failed\n");
1125                         return 1;
1126                 }
1127                 else
1128                 {
1129                         for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
1130                 }
1132 // if(file->current_channel == 0)
1133 // for(int i = 0; i < len; i++)
1134 // {
1135 //      int16_t value;
1136 //      value = (int16_t)(temp_float[0][i] * 32767);
1137 //      fwrite(&value, 2, 1, stdout);
1138 // }
1139 //printf("FileMOV::read_samples 4 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1140         }
1142         return 0;
1146 char* FileMOV::strtocompression(char *string)
1148         if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
1149         if(!strcasecmp(string, _(H264_NAME))) return QUICKTIME_H264;
1150         if(!strcasecmp(string, _(HV64_NAME))) return QUICKTIME_HV64;
1151         if(!strcasecmp(string, _(MP4V_NAME))) return QUICKTIME_MP4V;
1152         if(!strcasecmp(string, _(H263_NAME))) return QUICKTIME_H263;
1153         if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
1154         if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
1155 // Students say QUICKTIME_DV is required for compression even though
1156 // QUICKTIME_DVSD is produced by other software
1157 //      if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DVSD;
1158         if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
1159         if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
1160         if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
1161         if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
1162         if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
1163         if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
1164         if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
1165         if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
1166         if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
1167         if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
1168         if(!strcasecmp(string, _(TWOVUY_NAME))) return QUICKTIME_2VUY;
1169         if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
1170         if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
1171         if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
1173         if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
1174         if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
1175         if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
1176         if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
1177         if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
1178         if(!strcasecmp(string, _(MP4A_NAME))) return QUICKTIME_MP4A;
1179         if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
1183         return QUICKTIME_RAW;
1186 char* FileMOV::compressiontostr(char *string)
1188         if(match4(string, QUICKTIME_H263)) return _(H263_NAME);
1189         if(match4(string, QUICKTIME_H264)) return _(H264_NAME);
1190         if(match4(string, QUICKTIME_HV64)) return _(HV64_NAME);
1191         if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1192         if(match4(string, QUICKTIME_MP4V)) return _(MP4V_NAME);
1193         if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1194         if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1195         if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1196         if(match4(string, QUICKTIME_DVCP)) return _(DV_NAME);
1197         if(match4(string, QUICKTIME_DVSD)) return _(DV_NAME);
1198         if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1199         if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1200         if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1201         if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1202         if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1203         if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1204         if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1205         if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1206         if(match4(string, QUICKTIME_2VUY)) return _(TWOVUY_NAME);
1207         if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1208         if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1209         if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1215         if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1216         if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1217         if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1218         if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1219         if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1220         if(match4(string, QUICKTIME_MP4A)) return _(MP4A_NAME);
1221         if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1225         return _("Unknown");
1232 ThreadStruct::ThreadStruct()
1234         input = 0;
1235         output = 0;
1236         output_allocated = 0;
1237         output_size = 0;
1238         completion_lock = new Condition(1, "ThreadStruct::completion_lock");
1241 ThreadStruct::~ThreadStruct()
1243         if(output) delete [] output;
1244         delete completion_lock;
1247 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1249         if(output_allocated < mjpeg_output_size(mjpeg))
1250         {
1251                 delete [] output;
1252                 output = 0;
1253         }
1254         if(!output)
1255         {
1256                 output_allocated = mjpeg_output_size(mjpeg);
1257                 output = new unsigned char[output_allocated];
1258         }
1259         
1260         output_size = mjpeg_output_size(mjpeg);
1261         memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1265 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields) : Thread()
1267         this->filemov = filemov;
1268         this->fields = fields;
1269         mjpeg = 0;
1270         input_lock = new Condition(1, "FileMOVThread::input_lock");
1273 FileMOVThread::~FileMOVThread()
1275         delete input_lock;
1278 int FileMOVThread::start_encoding()
1280         mjpeg = mjpeg_new(filemov->asset->width, 
1281                 filemov->asset->height, 
1282                 fields);
1283         mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1284         mjpeg_set_float(mjpeg, 0);
1285         done = 0;
1286         set_synchronous(1);
1287         input_lock->lock("FileMOVThread::start_encoding");
1288         start();
1291 int FileMOVThread::stop_encoding()
1293         done = 1;
1294         input_lock->unlock();
1295         join();
1296         if(mjpeg) mjpeg_delete(mjpeg);
1299 int FileMOVThread::encode_buffer()
1301         input_lock->unlock();
1304 void FileMOVThread::run()
1306         while(!done)
1307         {
1308                 input_lock->lock("FileMOVThread::run");
1310                 if(!done)
1311                 {
1312 // Get a frame to compress.
1313                         filemov->threadframe_lock->lock("FileMOVThread::stop_encoding");
1314                         if(filemov->current_threadframe < filemov->total_threadframes)
1315                         {
1316 // Frame is available to process.
1317                                 input_lock->unlock();
1318                                 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1319                                 VFrame *frame = threadframe->input;
1321                                 filemov->current_threadframe++;
1322                                 filemov->threadframe_lock->unlock();
1324                                 mjpeg_compress(mjpeg, 
1325                                         frame->get_rows(), 
1326                                         frame->get_y(), 
1327                                         frame->get_u(), 
1328                                         frame->get_v(),
1329                                         frame->get_color_model(),
1330                                         1);
1332                                 if(fields > 1)
1333                                 {
1334                                         unsigned char *data = mjpeg_output_buffer(mjpeg);
1335                                         long data_size = mjpeg_output_size(mjpeg);
1336                                         long data_allocated = mjpeg_output_allocated(mjpeg);
1337                                         long field2_offset;
1339                                         if(filemov->asset->format == FILE_MOV)
1340                                         {
1341                                                 mjpeg_insert_quicktime_markers(&data,
1342                                                         &data_size,
1343                                                         &data_allocated,
1344                                                         2,
1345                                                         &field2_offset);
1346                                         }
1347                                         else
1348                                         {
1349                                                 mjpeg_insert_avi_markers(&data,
1350                                                         &data_size,
1351                                                         &data_allocated,
1352                                                         2,
1353                                                         &field2_offset);
1354                                         }
1355                                         mjpeg_set_output_size(mjpeg, data_size);
1356                                 }
1357                                 threadframe->load_output(mjpeg);
1358                                 threadframe->completion_lock->unlock();
1359                         }
1360                         else
1361                                 filemov->threadframe_lock->unlock();
1362                 }
1363         }
1371 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset_GC asset)
1372  : BC_Window(PROGRAM_NAME ": Audio Compression",
1373         parent_window->get_abs_cursor_x(1),
1374         parent_window->get_abs_cursor_y(1),
1375         350,
1376         250,
1377         350,
1378         250,
1379         0,
1380         1)
1382         this->parent_window = parent_window;
1383         this->asset = asset;
1384         compression_popup = 0;
1385         wg = 0; 
1386         wg_set = 0;
1387         reset();
1390 MOVConfigAudio::~MOVConfigAudio()
1392         if(compression_popup) delete compression_popup;
1393         if(bits_popup) delete bits_popup;
1394         compression_items.remove_all_objects();
1398 void MOVConfigAudio::reset()
1400         bits_popup = 0;
1401         bits_title = 0;
1402         dither = 0;
1403         vorbis_min_bitrate = 0;
1404         vorbis_bitrate = 0;
1405         vorbis_max_bitrate = 0;
1406         vorbis_vbr = 0;
1407         mp3_bitrate = 0;
1408         mp4a_bitrate = 0;
1409         mp4a_quantqual = 0;
1412 int MOVConfigAudio::create_objects()
1414         int x = 10, y = 10;
1416         BC_WidgetGrid *wg2;
1417         BC_RelocatableWidget *rw;
1418         int wg_row = 0;
1420         if(asset->format == FILE_MOV)
1421         {
1422                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1423                 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1424                 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1425                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1426                 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1427                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1428                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1429         }
1430         else
1431         {
1432                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1433                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1434                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1435                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1436         }
1438         rw =
1439         add_tool(new BC_Title(x, y, _("Compression:")));
1440         y += 25;
1441         compression_popup = new MOVConfigAudioPopup(this, x, y);
1442         compression_popup->create_objects();
1444         wg2 = add_widgetgrid(new BC_WidgetGrid(11, 10, 10, 10, 3, 3));
1445         wg2->add(rw, 0, 0);
1446         wg2->add(compression_popup, 0, 1);
1448         wg = add_widgetgrid(new BC_WidgetGrid(12, 10, 10, 10, 3, 15));
1449         wg->add(wg2, 0, 0);
1451         rw = 
1452         add_subwindow(new BC_OKButton(this));
1453         ok_height = rw->get_h();
1454         update_parameters();
1456         return 0;
1459 void MOVConfigAudio::update_parameters()
1461         int x = 10, y = 70;
1462         if(bits_title) delete bits_title;
1463         if(bits_popup) delete bits_popup;
1464         if(dither) delete dither;
1465         if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1466         if(vorbis_bitrate) delete vorbis_bitrate;
1467         if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1468         if(vorbis_vbr) delete vorbis_vbr;
1469         if(mp3_bitrate) delete mp3_bitrate;
1470         delete mp4a_bitrate;
1471         delete mp4a_quantqual;
1473         reset();
1475         // deletion of the old wg_set isn't required as the BC_WindowBase clean all created wg_sets
1476         wg_set = add_widgetgrid(new BC_WidgetGrid(10, 10, 10, 10, 10, 3));
1477         wg->add(wg_set, 1, 0);
1478         wg->set_align(1, 0, BC_WidgetGrid::VALIGN_TOP, BC_WidgetGrid::HALIGN_CENTER);
1479         int wg_row = 0;
1482         if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1483                 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1484         {
1485                 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1486                 bits_popup = new BitsPopup(this, 
1487                         x + 150, 
1488                         y, 
1489                         &asset->bits, 
1490                         0, 
1491                         0, 
1492                         0, 
1493                         0, 
1494                         0);
1495                 bits_popup->create_objects();
1496                 wg_set->add(bits_title, wg_row, 0);
1497                 wg_set->add(bits_popup, wg_row++, 1);
1498                 y += 40;
1499                 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1500                 wg_set->add(dither, wg_row++, 0);
1501         }
1502         else
1503         if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1504         {
1505         }
1506         else
1507         if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1508         {
1509                 mp3_bitrate = new MOVConfigAudioNum(this, 
1510                         _("Bitrate:"), 
1511                         x, 
1512                         y, 
1513                         &asset->mp3_bitrate);
1514                 mp3_bitrate->set_increment(1000);
1515                 mp3_bitrate->create_objects();
1516                 add_subwindow(mp3_bitrate->title = new BC_Title(x, y, _("Bitrate:")));
1517                 wg_set->add(mp3_bitrate->title, wg_row, 0);
1518                 wg_set->add(mp3_bitrate, wg_row++, 1);
1519         }
1520         else
1521         if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1522         {
1523         }
1524         else
1525         if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1526         {
1527                 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1528                         _("Variable bitrate"),
1529                         x,
1530                         y,
1531                         &asset->vorbis_vbr));
1532                 wg_set->add(vorbis_vbr, wg_row++, 1);
1533                 y += 35;
1534                 vorbis_min_bitrate = new MOVConfigAudioNum(this, 
1535                         _("Min bitrate:"), 
1536                         x, 
1537                         y, 
1538                         &asset->vorbis_min_bitrate);
1539                 vorbis_min_bitrate->set_increment(1000);
1540                 add_subwindow(vorbis_min_bitrate->title = new BC_Title(x, y, _("Min bitrate:")));
1541                 wg_set->add(vorbis_min_bitrate->title, wg_row, 0);
1542                 wg_set->add(vorbis_min_bitrate, wg_row++, 1);
1543                 y += 30;
1544                 vorbis_bitrate = new MOVConfigAudioNum(this, 
1545                         _("Avg bitrate:"), 
1546                         x, 
1547                         y, 
1548                         &asset->vorbis_bitrate);
1549                 vorbis_bitrate->set_increment(1000);
1550                 add_subwindow(vorbis_bitrate->title = new BC_Title(x, y, _("Avg bitrate:")));
1551                 wg_set->add(vorbis_bitrate->title, wg_row, 0);
1552                 wg_set->add(vorbis_bitrate, wg_row++, 1);
1553                 y += 30;
1554                 vorbis_max_bitrate = new MOVConfigAudioNum(this, 
1555                         _("Max bitrate:"), 
1556                         x, 
1557                         y, 
1558                         &asset->vorbis_max_bitrate);
1559                 vorbis_max_bitrate->set_increment(1000);
1560                 add_subwindow(vorbis_max_bitrate->title = new BC_Title(x, y, _("Max bitrate:")));
1561                 wg_set->add(vorbis_max_bitrate->title, wg_row, 0);
1562                 wg_set->add(vorbis_max_bitrate, wg_row++, 1);
1566                 vorbis_min_bitrate->create_objects();
1567                 vorbis_bitrate->create_objects();
1568                 vorbis_max_bitrate->create_objects();
1569         }
1570         else
1571         if(!strcasecmp(asset->acodec, QUICKTIME_MP4A))
1572         {
1573                 mp4a_bitrate = new MOVConfigAudioNum(this, 
1574                         _("Bitrate:"), 
1575                         x, 
1576                         y, 
1577                         &asset->mp4a_bitrate);
1578                 mp4a_bitrate->set_increment(1000);
1579                 mp4a_bitrate->create_objects();
1580                 add_subwindow(mp4a_bitrate->title = new BC_Title(x, y, _("Bitrate:")));
1581                 wg_set->add(mp4a_bitrate->title, wg_row, 0);
1582                 wg_set->add(mp4a_bitrate, wg_row++, 1);
1584                 y += 30;
1585                 mp4a_quantqual = new MOVConfigAudioNum(this, 
1586                         _("Quantization Quality (%):"), 
1587                         x, 
1588                         y, 
1589                         &asset->mp4a_quantqual);
1590                 mp4a_quantqual->set_increment(1);
1591                 mp4a_quantqual->create_objects();
1592                 add_subwindow(mp4a_quantqual->title = new BC_Title(x, y, _("Quantization Quality (%):")));
1593                 wg_set->add(mp4a_quantqual->title, wg_row, 0);
1594                 wg_set->add(mp4a_quantqual, wg_row++, 1);
1595         }
1596         wg->move_widgets();
1597         resize_window(wg->get_w_wm(), wg->get_h_wm() + ok_height);
1600 int MOVConfigAudio::close_event()
1602         set_done(0);
1603         return 1;
1610 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1611         char *title_text,
1612         int x,
1613         int y,
1614         int *output)
1615  : BC_CheckBox(x, y, *output, title_text)
1617         this->popup = popup;
1618         this->output = output;
1620 int MOVConfigAudioToggle::handle_event()
1622         *output = get_value();
1623         return 1;
1630 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1631  : BC_TumbleTextBox(popup, 
1632                 (int64_t)*output,
1633                 (int64_t)-1,
1634                 (int64_t)25000000,
1635                 popup->get_w() - 150, 
1636                 y, 
1637                 100)
1639         this->popup = popup;
1640         this->title_text = title_text;
1641         this->output = output;
1642         this->x = x;
1643         this->y = y;
1646 MOVConfigAudioNum::~MOVConfigAudioNum()
1648         if(!popup->get_deleting()) delete title;
1651 void MOVConfigAudioNum::create_objects()
1653         BC_TumbleTextBox::create_objects();
1656 int MOVConfigAudioNum::handle_event()
1658         *output = atol(get_text());
1659         return 1;
1669 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1670  : BC_PopupTextBox(popup, 
1671                 &popup->compression_items,
1672                 FileMOV::compressiontostr(popup->asset->acodec),
1673                 x, 
1674                 y, 
1675                 300,
1676                 300)
1678         this->popup = popup;
1681 int MOVConfigAudioPopup::handle_event()
1683         strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1684         popup->update_parameters();
1685         return 1;
1704 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window, 
1705         Asset_GC asset, 
1706         char *locked_compressor)
1707  : BC_Window(PROGRAM_NAME ": Video Compression",
1708         parent_window->get_abs_cursor_x(1),
1709         parent_window->get_abs_cursor_y(1),
1710         420,
1711         420,
1712         420,
1713         420,
1714         0,
1715         1)
1717         this->parent_window = parent_window;
1718         this->asset = asset;
1719         this->locked_compressor = locked_compressor;
1720         compression_popup = 0;
1721         wg = 0;
1722         wg_set = 0;
1724         reset();
1727 MOVConfigVideo::~MOVConfigVideo()
1729         if(compression_popup) delete compression_popup;
1730         compression_items.remove_all_objects();
1733 int MOVConfigVideo::create_objects()
1735         int x = 10, y = 10;
1736         BC_WidgetGrid *wg2;
1737         BC_RelocatableWidget *rw;
1738         int wg_row = 0;
1740         if(asset->format == FILE_MOV)
1741         {
1742                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1743                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1744 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1745                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1746                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1747                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1748                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1749                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1750                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1751                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1752                 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1753                 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1754                 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1755                 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1756                 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1757                 compression_items.append(new BC_ListBoxItem(_(TWOVUY_NAME)));
1758                 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1759                 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1760                 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1761         }
1762         else
1763         {
1764                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1765                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1766 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1767                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1768                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1769                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1770                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1771                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1772                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1773                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1774         }
1776         rw =
1777         add_subwindow(new BC_Title(x, y, _("Compression:")));
1778         y += 25;
1780         wg2 = add_widgetgrid(new BC_WidgetGrid(11, 10, 10, 10, 3, 3));
1781         wg2->add(rw, 0, 0);
1783         if(!locked_compressor)
1784         {
1785                 compression_popup = new MOVConfigVideoPopup(this, x, y);
1786                 compression_popup->create_objects();
1787                 wg2->add(compression_popup, 0, 1);
1788         }
1789         else
1790         {
1791                 rw =
1792                 add_subwindow(new BC_Title(x, 
1793                         y, 
1794                         FileMOV::compressiontostr(locked_compressor),
1795                         MEDIUMFONT,
1796                         RED,
1797                         0));
1798                 wg2->add(rw, 0, 1);
1799         }
1800         y += 40;
1802         wg = add_widgetgrid(new BC_WidgetGrid(12, 10, 10, 10, 3, 15));
1803         wg->add(wg2, 0, 0);
1805         param_x = x;
1806         param_y = y;
1808         rw =
1809         add_subwindow(new BC_OKButton(this));
1810         ok_height = rw->get_h();
1812         update_parameters();
1814         return 0;
1817 int MOVConfigVideo::close_event()
1819         set_done(0);
1820         return 1;
1824 void MOVConfigVideo::reset()
1826         jpeg_quality = 0;
1827         jpeg_quality_title = 0;
1829         divx_bitrate = 0;
1830         divx_rc_period = 0;
1831         divx_rc_reaction_ratio = 0;
1832         divx_rc_reaction_period = 0;
1833         divx_max_key_interval = 0;
1834         divx_max_quantizer = 0;
1835         divx_min_quantizer = 0;
1836         divx_quantizer = 0;
1837         divx_quality = 0;
1838         divx_fix_bitrate = 0;
1839         divx_fix_quant = 0;
1841         h264_bitrate = 0;
1842         h264_quantizer = 0;
1843         h264_fix_bitrate = 0;
1844         h264_fix_quant = 0;
1846         ms_bitrate = 0;
1847         ms_bitrate_tolerance = 0;
1848         ms_quantization = 0;
1849         ms_interlaced = 0;
1850         ms_gop_size = 0;
1851         ms_fix_bitrate = 0;
1852         ms_fix_quant = 0;
1855 void MOVConfigVideo::update_parameters()
1857         if(jpeg_quality)
1858         {
1859                 delete jpeg_quality_title;
1860                 delete jpeg_quality;
1861         }
1863         if(divx_bitrate) delete divx_bitrate;
1864         if(divx_rc_period) delete divx_rc_period;
1865         if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1866         if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1867         if(divx_max_key_interval) delete divx_max_key_interval;
1868         if(divx_max_quantizer) delete divx_max_quantizer;
1869         if(divx_min_quantizer) delete divx_min_quantizer;
1870         if(divx_quantizer) delete divx_quantizer;
1871         if(divx_quality) delete divx_quality;
1872         if(divx_fix_quant) delete divx_fix_quant;
1873         if(divx_fix_bitrate) delete divx_fix_bitrate;
1875         if(ms_bitrate) delete ms_bitrate;
1876         if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1877         if(ms_interlaced) delete ms_interlaced;
1878         if(ms_quantization) delete ms_quantization;
1879         if(ms_gop_size) delete ms_gop_size;
1880         if(ms_fix_bitrate) delete ms_fix_bitrate;
1881         if(ms_fix_quant) delete ms_fix_quant;
1883         delete h264_bitrate;
1884         delete h264_quantizer;
1885         delete h264_fix_bitrate;
1886         delete h264_fix_quant;
1888         reset();
1890         // deletion of the old wg_set isn't required as the BC_WindowBase clean all created wg_sets
1891         wg_set = add_widgetgrid(new BC_WidgetGrid(10, 10, 10, 10, 10, 3));
1892         wg->add(wg_set, 1, 0);
1893         wg->set_align(1, 0, BC_WidgetGrid::VALIGN_TOP, BC_WidgetGrid::HALIGN_CENTER);
1894         int wg_row = 0;
1896         char *vcodec = asset->vcodec;
1897         if(locked_compressor) vcodec = locked_compressor;
1900 // H264 parameters
1901         if(!strcmp(vcodec, QUICKTIME_H264) ||
1902                 !strcmp(vcodec, QUICKTIME_HV64))
1903         {
1904                 int x = param_x, y = param_y;
1905                 h264_bitrate = new MOVConfigVideoNum(this, 
1906                         _("Bitrate:"), 
1907                         x, 
1908                         y, 
1909                         &asset->h264_bitrate);
1910                 h264_bitrate->set_increment(1000000);
1911                 h264_bitrate->create_objects();
1912                 add_subwindow(h264_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260, 
1913                                 y,
1914                                 &asset->h264_fix_bitrate,
1915                                 1));
1916                 add_subwindow(h264_bitrate->title = new BC_Title(x, y, _("Bitrate:")));
1917                 wg_set->add(h264_bitrate->title, wg_row, 0);
1918                 wg_set->add(h264_bitrate, wg_row, 1);
1919                 wg_set->add(h264_fix_bitrate, wg_row++, 2);
1920                 y += 30;
1921                 h264_quantizer = new MOVConfigVideoNum(this, 
1922                         _("Quantization:"), 
1923                         x, 
1924                         y, 
1925                         0,
1926                         51,
1927                         &asset->h264_quantizer);
1928                 h264_quantizer->create_objects();
1929                 add_subwindow(h264_fix_quant = new MOVConfigVideoFixQuant(x + 260, 
1930                                 y,
1931                                 &asset->h264_fix_bitrate,
1932                                 0));
1933                 h264_fix_bitrate->opposite = h264_fix_quant;
1934                 h264_fix_quant->opposite = h264_fix_bitrate;
1935                 add_subwindow(h264_quantizer->title = new BC_Title(x, y, _("Quantization:")));
1936                 wg_set->add(h264_quantizer->title, wg_row, 0);
1937                 wg_set->add(h264_quantizer, wg_row, 1);
1938                 wg_set->add(h264_fix_quant, wg_row++, 2);
1939         }
1940         else
1941 // ffmpeg parameters
1942         if(!strcmp(vcodec, QUICKTIME_MP4V) ||
1943                 !strcmp(vcodec, QUICKTIME_DIV3))
1944         {
1945                 int x = param_x, y = param_y;
1946                 ms_bitrate = new MOVConfigVideoNum(this, 
1947                         _("Bitrate:"), 
1948                         x, 
1949                         y, 
1950                         &asset->ms_bitrate);
1951                 ms_bitrate->set_increment(1000000);
1952                 ms_bitrate->create_objects();
1953                 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260, 
1954                                 y,
1955                                 &asset->ms_fix_bitrate,
1956                                 1));
1957                 add_subwindow(ms_bitrate->title = new BC_Title(x, y, _("Bitrate:")));
1958                 wg_set->add(ms_bitrate->title, wg_row, 0);
1959                 wg_set->add(ms_bitrate, wg_row, 1);
1960                 wg_set->add(ms_fix_bitrate, wg_row++, 2);
1961                 y += 30;
1963                 ms_bitrate_tolerance = new MOVConfigVideoNum(this, 
1964                         _("Bitrate tolerance:"), 
1965                         x, 
1966                         y, 
1967                         &asset->ms_bitrate_tolerance);
1968                 ms_bitrate_tolerance->create_objects();
1969                 add_subwindow(ms_bitrate_tolerance->title = new BC_Title(x, y, _("Bitrate tolerance:")));
1970                 wg_set->add(ms_bitrate_tolerance->title, wg_row, 0);
1971                 wg_set->add(ms_bitrate_tolerance, wg_row++, 1);
1972                 y += 30;
1973                 ms_quantization = new MOVConfigVideoNum(this, 
1974                         _("Quantization:"), 
1975                         x, 
1976                         y, 
1977                         &asset->ms_quantization);
1978                 ms_quantization->create_objects();
1979                 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260, 
1980                                 y,
1981                                 &asset->ms_fix_bitrate,
1982                                 0));
1983                 ms_fix_bitrate->opposite = ms_fix_quant;
1984                 ms_fix_quant->opposite = ms_fix_bitrate;
1985                 add_subwindow(ms_quantization->title = new BC_Title(x, y, _("Quantization:")));
1986                 wg_set->add(ms_quantization->title, wg_row, 0);
1987                 wg_set->add(ms_quantization, wg_row, 1);
1988                 wg_set->add(ms_fix_quant, wg_row++, 2);
1991                 y += 30;
1992                 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"), 
1993                         x, 
1994                         y, 
1995                         &asset->ms_interlaced));
1996                 wg_set->add(ms_interlaced, wg_row++, 1);
1997                 y += 30;
1998                 ms_gop_size = new MOVConfigVideoNum(this, 
1999                         _("Keyframe interval:"), 
2000                         x, 
2001                         y, 
2002                         &asset->ms_gop_size);
2003                 ms_gop_size->create_objects();
2004                 add_subwindow(ms_gop_size->title = new BC_Title(x, y, _("Keyframe interval:")));
2005                 wg_set->add(ms_gop_size->title, wg_row, 0);
2006                 wg_set->add(ms_gop_size, wg_row++, 1);
2007         }
2008         else
2009 // OpenDivx parameters
2010         if(!strcmp(vcodec, QUICKTIME_DIVX) ||
2011                 !strcmp(vcodec, QUICKTIME_H263) ||
2012                 !strcmp(vcodec, QUICKTIME_HV60))
2013         {
2014                 int x = param_x, y = param_y;
2015                 divx_bitrate = new MOVConfigVideoNum(this, 
2016                         _("Bitrate:"), 
2017                         x, 
2018                         y, 
2019                         &asset->divx_bitrate);
2020                 divx_bitrate->set_increment(1000000);
2021                 divx_bitrate->create_objects();
2022                 add_subwindow(divx_fix_bitrate = 
2023                         new MOVConfigVideoFixBitrate(x + 260, 
2024                                 y,
2025                                 &asset->divx_fix_bitrate,
2026                                 1));
2027                 add_subwindow(divx_bitrate->title = new BC_Title(x, y, _("Bitrate:")));
2028                 wg_set->add(divx_bitrate->title, wg_row, 0);
2029                 wg_set->add(divx_bitrate, wg_row, 1);
2030                 wg_set->add(divx_fix_bitrate, wg_row++, 2);
2031                 y += 30;
2032                 divx_quantizer = new MOVConfigVideoNum(this, 
2033                         _("Quantizer:"), 
2034                         x, 
2035                         y, 
2036                         &asset->divx_quantizer);
2037                 divx_quantizer->create_objects();
2038                 add_subwindow(divx_fix_quant =
2039                         new MOVConfigVideoFixQuant(x + 260, 
2040                                 y,
2041                                 &asset->divx_fix_bitrate,
2042                                 0));
2043                 divx_fix_quant->opposite = divx_fix_bitrate;
2044                 divx_fix_bitrate->opposite = divx_fix_quant;
2045                 add_subwindow(divx_quantizer->title = new BC_Title(x, y, _("Quantizer:")));
2046                 wg_set->add(divx_quantizer->title, wg_row, 0);
2047                 wg_set->add(divx_quantizer, wg_row, 1);
2048                 wg_set->add(divx_fix_quant, wg_row++, 2);
2049                 y += 30;
2050                 divx_rc_period = new MOVConfigVideoNum(this, 
2051                         _("RC Period:"), 
2052                         x, 
2053                         y, 
2054                         &asset->divx_rc_period);
2055                 divx_rc_period->create_objects();
2056                 add_subwindow(divx_rc_period->title = new BC_Title(x, y, _("RC Period:")));
2057                 wg_set->add(divx_rc_period->title, wg_row, 0);
2058                 wg_set->add(divx_rc_period, wg_row++, 1);
2059                 y += 30;
2060                 divx_rc_reaction_ratio = new MOVConfigVideoNum(this, 
2061                         _("Reaction Ratio:"), 
2062                         x, 
2063                         y, 
2064                         &asset->divx_rc_reaction_ratio);
2065                 divx_rc_reaction_ratio->create_objects();
2066                 add_subwindow(divx_rc_reaction_ratio->title = new BC_Title(x, y, _("Reaction Ratio:")));
2067                 wg_set->add(divx_rc_reaction_ratio->title, wg_row, 0);
2068                 wg_set->add(divx_rc_reaction_ratio, wg_row++, 1);
2069                 y += 30;
2070                 divx_rc_reaction_period = new MOVConfigVideoNum(this, 
2071                         _("Reaction Period:"), 
2072                         x, 
2073                         y, 
2074                         &asset->divx_rc_reaction_period);
2075                 divx_rc_reaction_period->create_objects();
2076                 add_subwindow(divx_rc_reaction_period->title = new BC_Title(x, y, _("Reaction Period:")));
2077                 wg_set->add(divx_rc_reaction_period->title, wg_row, 0);
2078                 wg_set->add(divx_rc_reaction_period, wg_row++, 1);
2079                 y += 30;
2080                 divx_max_key_interval = new MOVConfigVideoNum(this, 
2081                         _("Max Key Interval:"), 
2082                         x, 
2083                         y, 
2084                         &asset->divx_max_key_interval);
2085                 divx_max_key_interval->create_objects();
2086                 add_subwindow(divx_max_key_interval->title = new BC_Title(x, y, _("Max Key Interval:")));
2087                 wg_set->add(divx_max_key_interval->title, wg_row, 0);
2088                 wg_set->add(divx_max_key_interval, wg_row++, 1);
2089                 y += 30;
2090                 divx_max_quantizer = new MOVConfigVideoNum(this, 
2091                         _("Max Quantizer:"), 
2092                         x, 
2093                         y, 
2094                         &asset->divx_max_quantizer);
2095                 divx_max_quantizer->create_objects();
2096                 add_subwindow(divx_max_quantizer->title = new BC_Title(x, y, _("Max Quantizer:")));
2097                 wg_set->add(divx_max_quantizer->title, wg_row, 0);
2098                 wg_set->add(divx_max_quantizer, wg_row++, 1);
2099                 y += 30;
2100                 divx_min_quantizer = new MOVConfigVideoNum(this, 
2101                         _("Min Quantizer:"), 
2102                         x, 
2103                         y, 
2104                         &asset->divx_min_quantizer);
2105                 divx_min_quantizer->create_objects();
2106                 add_subwindow(divx_min_quantizer->title = new BC_Title(x, y, _("Min Quantizer:")));
2107                 wg_set->add(divx_min_quantizer->title, wg_row, 0);
2108                 wg_set->add(divx_min_quantizer, wg_row++, 1);
2109                 y += 30;
2110                 divx_quality = new MOVConfigVideoNum(this, 
2111                         _("Quality:"), 
2112                         x, 
2113                         y, 
2114                         &asset->divx_quality);
2115                 divx_quality->create_objects();
2116                 add_subwindow(divx_quality->title = new BC_Title(x, y, _("Quality:")));
2117                 wg_set->add(divx_quality->title, wg_row, 0);
2118                 wg_set->add(divx_quality, wg_row++, 1);
2119         }
2120         else
2121         if(!strcmp(vcodec, QUICKTIME_JPEG) ||
2122                 !strcmp(vcodec, QUICKTIME_MJPA))
2123         {
2124                 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
2125                 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80, 
2126                         param_y,
2127                         0,
2128                         200,
2129                         200,
2130                         0,
2131                         100,
2132                         asset->jpeg_quality,
2133                         0,
2134                         0,
2135                         &asset->jpeg_quality));
2136                 wg_set->add(jpeg_quality_title, wg_row, 0);
2137                 wg_set->add(jpeg_quality, wg_row++, 1);
2138         }
2139         wg->move_widgets();
2140         resize_window(wg->get_w_wm(), wg->get_h_wm() + ok_height);
2147 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
2148  : BC_TumbleTextBox(popup, 
2149                 (int64_t)*output,
2150                 (int64_t)1,
2151                 (int64_t)25000000,
2152                 x + 130, 
2153                 y, 
2154                 100)
2156         this->popup = popup;
2157         this->title_text = title_text;
2158         this->output = output;
2159         this->x = x;
2160         this->y = y;
2163 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, 
2164         char *title_text, 
2165         int x, 
2166         int y, 
2167         int min,
2168         int max,
2169         int *output)
2170  : BC_TumbleTextBox(popup, 
2171                 (int64_t)*output,
2172                 (int64_t)min,
2173                 (int64_t)max,
2174                 x + 130, 
2175                 y, 
2176                 100)
2178         this->popup = popup;
2179         this->title_text = title_text;
2180         this->output = output;
2181         this->x = x;
2182         this->y = y;
2185 MOVConfigVideoNum::~MOVConfigVideoNum()
2187         if(!popup->get_deleting()) delete title;
2190 void MOVConfigVideoNum::create_objects()
2192 //      popup->add_subwindow(title = new BC_Title(x, y, title_text));
2193         BC_TumbleTextBox::create_objects();
2196 int MOVConfigVideoNum::handle_event()
2198         *output = atol(get_text());
2199         return 1;
2208 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
2209  : BC_CheckBox(x, y, *output, title_text)
2211         this->output = output;
2214 int MOVConfigVideoCheckBox::handle_event()
2216         *output = get_value();
2217         return 1;
2225 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x, 
2226         int y,
2227         int *output,
2228         int value)
2229  : BC_Radial(x, 
2230         y, 
2231         *output == value, 
2232         _("Fix bitrate"))
2234         this->output = output;
2235         this->value = value;
2238 int MOVConfigVideoFixBitrate::handle_event()
2240         *output = value;
2241         opposite->update(0);
2242         return 1;
2250 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x, 
2251         int y,
2252         int *output,
2253         int value)
2254  : BC_Radial(x, 
2255         y, 
2256         *output == value, 
2257         _("Fix quantization"))
2259         this->output = output;
2260         this->value = value;
2263 int MOVConfigVideoFixQuant::handle_event()
2265         *output = value;
2266         opposite->update(0);
2267         return 1;
2274 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
2275  : BC_PopupTextBox(popup, 
2276                 &popup->compression_items,
2277                 FileMOV::compressiontostr(popup->asset->vcodec),
2278                 x, 
2279                 y, 
2280                 300,
2281                 300)
2283         this->popup = popup;
2286 int MOVConfigVideoPopup::handle_event()
2288         strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
2289         popup->update_parameters();
2290         return 1;
2302 //      Local Variables:
2303 //      mode: C++
2304 //      c-file-style: "linux"
2305 //      End: