r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / filemov.C
blobd798a5260619ac3e30e0610f439d2c529dcef941
1 #include "assets.h"
2 #include "bitspopup.h"
3 #include "byteorder.h"
4 #include "edit.h"
5 #include "file.h"
6 #include "filemov.h"
7 #include "guicast.h"
8 #include "mwindow.inc"
9 #include "vframe.h"
10 #include "videodevice.inc"
12 #include <libintl.h>
13 #define _(String) gettext(String)
14 #define gettext_noop(String) String
15 #define N_(String) gettext_noop (String)
18 #if 0
19 N_("MPEG-4")
20 N_("Heroine 60")
21 N_("Microsoft MPEG-4")
22 N_("DV")
23 N_("PNG")
24 N_("PNG with Alpha")
25 N_("Uncompressed RGB")
26 N_("Uncompressed RGBA")
27 N_("YUV 4:2:0 Planar")
28 N_("Component Video")
29 N_("YUV 4:1:1 Packed")
30 N_("Component Y'CbCr 8-bit 4:4:4")
31 N_("Component Y'CbCrA 8-bit 4:4:4:4")
32 N_("Component Y'CbCr 10-bit 4:4:4")
33 N_("JPEG Photo")
34 N_("Motion JPEG A")
37 N_("Twos complement")
38 N_("Unsigned")
39 N_("IMA-4")
40 N_("U-Law")
41 N_("Vorbis")
42 N_("MP3")
43 #endif
45 #define DIVX_NAME "MPEG-4"
46 #define HV60_NAME "Heroine 60"
47 #define DIV3_NAME "Microsoft MPEG-4"
48 #define DV_NAME "DV"
49 #define PNG_NAME "PNG"
50 #define PNGA_NAME "PNG with Alpha"
51 #define RGB_NAME "Uncompressed RGB"
52 #define RGBA_NAME "Uncompressed RGBA"
53 #define YUV420_NAME "YUV 4:2:0 Planar"
54 #define YUV422_NAME "Component Video"
55 #define YUV411_NAME "YUV 4:1:1 Packed"
56 #define YUV444_NAME "Component Y'CbCr 8-bit 4:4:4"
57 #define YUVA4444_NAME "Component Y'CbCrA 8-bit 4:4:4:4"
58 #define YUV444_10BIT_NAME "Component Y'CbCr 10-bit 4:4:4"
59 #define QTJPEG_NAME "JPEG Photo"
60 #define MJPA_NAME "Motion JPEG A"
63 #define TWOS_NAME "Twos complement"
64 #define RAW_NAME "Unsigned"
65 #define IMA4_NAME "IMA-4"
66 #define ULAW_NAME "U-Law"
67 //#define VORBIS_NAME "Vorbis"
68 #define MP3_NAME "MP3"
74 FileMOV::FileMOV(Asset *asset, File *file)
75  : FileBase(asset, file)
77         reset_parameters();
78         if(asset->format == FILE_UNKNOWN)
79                 asset->format = FILE_MOV;
80         asset->byte_order = 0;
81         suffix_number = 0;
84 FileMOV::~FileMOV()
86         close_file();
89 void FileMOV::get_parameters(BC_WindowBase *parent_window, 
90         Asset *asset, 
91         BC_WindowBase* &format_window,
92         int audio_options,
93         int video_options,
94         int lock_compressor)
96         fix_codecs(asset);
97         if(audio_options)
98         {
99                 MOVConfigAudio *window = new MOVConfigAudio(parent_window, asset);
100                 format_window = window;
101                 window->create_objects();
102                 window->run_window();
103                 delete window;
104         }
105         else
106         if(video_options)
107         {
108                 MOVConfigVideo *window = new MOVConfigVideo(parent_window, 
109                         asset, 
110                         lock_compressor);
111                 format_window = window;
112                 window->create_objects();
113                 window->run_window();
114                 delete window;
115         }
118 void FileMOV::fix_codecs(Asset *asset)
120 //      if(asset->format == FILE_MOV)
121 //      {
122 //              if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
123 //                      strcpy(asset->acodec, QUICKTIME_TWOS);
124 //      }
125 //      else
126 //      {
127 //              if(strcasecmp(asset->vcodec, QUICKTIME_DIV3))
128 //              {
129 //                      strcpy(asset->vcodec, QUICKTIME_DIV3);
130 //              }
131 //              strcpy(asset->acodec, QUICKTIME_MP3);
132 //      }
135 int FileMOV::check_sig(Asset *asset)
137         return quicktime_check_sig(asset->path);
141 int FileMOV::reset_parameters_derived()
143         fd = 0;
144         prev_track = 0;
145         frame = 0;
146         temp_frame = 0;
147         quicktime_atracks = 0;
148         quicktime_vtracks = 0;
149         depth = 24;
150         threads = 0;
151         frames_correction = 0;
152         samples_correction = 0;
153         temp_float = 0;
154         temp_allocated = 0;
158 // Just create the Quicktime objects since this routine is also called
159 // for reopening.
160 int FileMOV::open_file(int rd, int wr)
162         this->rd = rd;
163         this->wr = wr;
166         if(suffix_number == 0) strcpy(prefix_path, asset->path);
168         if(!(fd = quicktime_open(asset->path, rd, wr)))
169         {
170                 printf(_("FileMOV::open_file %s: No such file or directory\n"), asset->path);
171                 return 1;
172         }
174         quicktime_set_cpus(fd, file->cpus);
176         if(rd) format_to_asset();
178         if(wr) asset_to_format();
180 // Set decoding parameter
181         quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking);
183         return 0;
186 int FileMOV::close_file()
188 //printf("FileMOV::close_file 1 %s\n", asset->path);
189         if(fd)
190         {
191                 if(wr) quicktime_set_framerate(fd, asset->frame_rate);
192                 quicktime_close(fd);
193         }
195 //printf("FileMOV::close_file 1\n");
196         if(frame)
197                 delete frame;
198         if(temp_frame)
199                 delete temp_frame;
201 //printf("FileMOV::close_file 1\n");
202         if(threads)
203         {
204                 for(int i = 0; i < file->cpus; i++)
205                 {
206                         threads[i]->stop_encoding();
207                         delete threads[i];
208                 }
209                 delete [] threads;
210                 threads = 0;
211         }
213 //printf("FileMOV::close_file 1\n");
214         threadframes.remove_all_objects();
217         if(temp_float) 
218         {
219                 for(int i = 0; i < asset->channels; i++)
220                         delete [] temp_float[i];
221                 delete [] temp_float;
222         }
224 //printf("FileMOV::close_file 1\n");
225         reset_parameters();
226         FileBase::close_file();
227 //printf("FileMOV::close_file 2\n");
228         return 0;
231 void FileMOV::asset_to_format()
233         if(!fd) return;
234         char audio_codec[5];
236         fix_codecs(asset);
238 // Fix up the Quicktime file.
239         quicktime_set_copyright(fd, _("Made with Cinelerra for Linux"));
240         quicktime_set_info(fd, "Quicktime for Linux");
242         if(asset->audio_data)
243         {
244                 quicktime_atracks = quicktime_set_audio(fd, 
245                                 asset->channels, 
246                                 asset->sample_rate, 
247                                 asset->bits, 
248                                 asset->acodec);
249                 quicktime_set_parameter(fd, "vorbis_vbr", &asset->vorbis_vbr);
250                 quicktime_set_parameter(fd, "vorbis_min_bitrate", &asset->vorbis_min_bitrate);
251                 quicktime_set_parameter(fd, "vorbis_bitrate", &asset->vorbis_bitrate);
252                 quicktime_set_parameter(fd, "vorbis_max_bitrate", &asset->vorbis_max_bitrate);
253                 quicktime_set_parameter(fd, "mp3_bitrate", &asset->mp3_bitrate);
254         }
256         if(asset->video_data)
257         {
258                 char string[16];
259 // Set up the alpha channel compressors
260                 if(!strcmp(asset->vcodec, MOV_RGBA))
261                 {
262                         strcpy(string, QUICKTIME_RAW);
263                         depth = 32;
264                 }
265                 else
266                 if(!strcmp(asset->vcodec, MOV_PNGA))
267                 {
268                         strcpy(string, QUICKTIME_PNG);
269                         depth = 32;
270                 }
271                 else
272                 if(!strcmp(asset->vcodec, QUICKTIME_YUVA4444))
273                 {
274                         strcpy(string, asset->vcodec);
275                         depth = 32;
276                 }
277                 else
278                 {
279                         strcpy(string, asset->vcodec);
280                         depth = 24;
281                 }
283                 quicktime_vtracks = quicktime_set_video(fd, 
284                                         asset->layers, 
285                                         asset->width, 
286                                         asset->height,
287                                         asset->frame_rate,
288                                         string);
292                 for(int i = 0; i < asset->layers; i++)
293                         quicktime_set_depth(fd, depth, i);
295                 quicktime_set_parameter(fd, "jpeg_quality", &asset->jpeg_quality);
297 // set the compression parameters if there are any
298                 quicktime_set_parameter(fd, "divx_bitrate", &asset->divx_bitrate);
299                 quicktime_set_parameter(fd, "divx_rc_period", &asset->divx_rc_period);
300                 quicktime_set_parameter(fd, "divx_rc_reaction_ratio", &asset->divx_rc_reaction_ratio);
301                 quicktime_set_parameter(fd, "divx_rc_reaction_period", &asset->divx_rc_reaction_period);
302                 quicktime_set_parameter(fd, "divx_max_key_interval", &asset->divx_max_key_interval);
303                 quicktime_set_parameter(fd, "divx_max_quantizer", &asset->divx_max_quantizer);
304                 quicktime_set_parameter(fd, "divx_min_quantizer", &asset->divx_min_quantizer);
305                 quicktime_set_parameter(fd, "divx_quantizer", &asset->divx_quantizer);
306                 quicktime_set_parameter(fd, "divx_quality", &asset->divx_quality);
307                 quicktime_set_parameter(fd, "divx_fix_bitrate", &asset->divx_fix_bitrate);
309                 quicktime_set_parameter(fd, "div3_bitrate", &asset->ms_bitrate);
310                 quicktime_set_parameter(fd, "div3_bitrate_tolerance", &asset->ms_bitrate_tolerance);
311                 quicktime_set_parameter(fd, "div3_interlaced", &asset->ms_interlaced);
312                 quicktime_set_parameter(fd, "div3_quantizer", &asset->ms_quantization);
313                 quicktime_set_parameter(fd, "div3_gop_size", &asset->ms_gop_size);
314                 quicktime_set_parameter(fd, "div3_fix_bitrate", &asset->ms_fix_bitrate);
316 //printf("FileMOV::asset_to_format 3.3\n");
317         }
318 //printf("FileMOV::asset_to_format 3.4\n");
320 //printf("FileMOV::asset_to_format 4 %d %d\n", wr, 
321 //                              asset->format);
323         if(wr && asset->format == FILE_AVI)
324         {
325                 quicktime_set_avi(fd, 1);
326         }
330 void FileMOV::format_to_asset()
332         if(!fd) return;
334         if(quicktime_is_avi(fd)) asset->format = FILE_AVI;
335         asset->audio_data = quicktime_has_audio(fd);
336         if(asset->audio_data)
337         {
338                 asset->channels = 0;
339                 int qt_tracks = quicktime_audio_tracks(fd);
340                 for(int i = 0; i < qt_tracks; i++)
341                         asset->channels += quicktime_track_channels(fd, i);
342         
343                 if(!asset->sample_rate)
344                         asset->sample_rate = quicktime_sample_rate(fd, 0);
345                 asset->bits = quicktime_audio_bits(fd, 0);
346                 asset->audio_length = quicktime_audio_length(fd, 0);
347                 strncpy(asset->acodec, quicktime_audio_compressor(fd, 0), 4);
348         }
350 // determine if the video can be read before declaring video data
351         if(quicktime_has_video(fd) && quicktime_supported_video(fd, 0))
352                         asset->video_data = 1;
354         if(asset->video_data)
355         {
356                 depth = quicktime_video_depth(fd, 0);
357                 asset->layers = quicktime_video_tracks(fd);
358                 asset->width = quicktime_video_width(fd, 0);
359                 asset->height = quicktime_video_height(fd, 0);
360                 asset->video_length = quicktime_video_length(fd, 0);
361 // Don't want a user configured frame rate to get destroyed
362                 if(!asset->frame_rate)
363                         asset->frame_rate = quicktime_frame_rate(fd, 0);
365                 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
366         }
369 int FileMOV::colormodel_supported(int colormodel)
371         return colormodel;
374 int FileMOV::get_best_colormodel(Asset *asset, int driver)
376         switch(driver)
377         {
378                 case PLAYBACK_X11:
379                         return BC_RGB888;
380                         break;
381                 case PLAYBACK_X11_XV:
382                         if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
383                         if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422P;
384                         if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
385                         if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
386                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
387                         if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
388                         if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
389                         if(match4(asset->vcodec, QUICKTIME_DIV3)) return BC_YUV420P;
390                         break;
391                 case PLAYBACK_FIREWIRE:
392                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_COMPRESSED;
393                         return BC_YUV422P;
394                         break;
395                 case PLAYBACK_LML:
396                 case PLAYBACK_BUZ:
397                         if(match4(asset->vcodec, QUICKTIME_MJPA)) 
398                                 return BC_COMPRESSED;
399                         else
400                                 return BC_YUV422P;
401                         break;
402                 case VIDEO4LINUX:
403                 case VIDEO4LINUX2:
404                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
405                         else
406                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
407                         else
408                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
409                         else
410                         if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
411                         else
412                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
413                         else
414                         if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
415                         else
416                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
417                         else
418                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
419                         break;
420                 case CAPTURE_BUZ:
421                 case CAPTURE_LML:
422                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) 
423                                 return BC_COMPRESSED;
424                         else
425                                 return BC_YUV422;
426                         break;
427                 case CAPTURE_FIREWIRE:
428                         if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4)) 
429                                 return BC_COMPRESSED;
430                         else
431                                 return BC_YUV422;
432                         break;
433         }
434         return BC_RGB888;
437 int FileMOV::can_copy_from(Edit *edit, int64_t position)
439         if(!fd) return 0;
441 //printf("FileMOV::can_copy_from 1 %d %s %s\n", edit->asset->format, edit->asset->vcodec, this->asset->vcodec);
442         if(edit->asset->format == FILE_JPEG_LIST && 
443                 match4(this->asset->vcodec, QUICKTIME_JPEG))
444                 return 1;
445         else
446         if((edit->asset->format == FILE_MOV || 
447                 edit->asset->format == FILE_AVI)
448                 && 
449                 (match4(edit->asset->vcodec, this->asset->vcodec)))
450                 return 1;
452         return 0;
456 int64_t FileMOV::get_audio_length()
458         if(!fd) return 0;
459         int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
461         return result;
464 int FileMOV::set_audio_position(int64_t x)
466         if(!fd) return 1;
467 // quicktime sets positions for each track seperately so store position in audio_position
468         if(x >= 0 && x < asset->audio_length)
469                 return quicktime_set_audio_position(fd, x, 0);
470         else
471                 return 1;
474 int FileMOV::set_video_position(int64_t x)
476         if(!fd) return 1;
477 //printf("FileMOV::set_video_position 1 %d %d\n", x, asset->video_length);
478         if(x >= 0 && x < asset->video_length)
479                 return quicktime_set_video_position(fd, x, file->current_layer);
480         else
481                 return 1;
485 void FileMOV::new_audio_temp(int64_t len)
487         if(temp_allocated && temp_allocated < len)
488         {
489                 for(int i = 0; i < asset->channels; i++)
490                         delete [] temp_float[i];
491                 delete [] temp_float;
492                 temp_allocated = 0;
493         }
495         if(!temp_allocated)
496         {
497                 temp_allocated = len;
498                 temp_float = new float*[asset->channels];
499                 for(int i = 0; i < asset->channels; i++)
500                         temp_float[i] = new float[len];
501         }
506 int FileMOV::write_samples(double **buffer, int64_t len)
508         int i, j;
509         int64_t bytes;
510         int result = 0, track_channels = 0;
511         int chunk_size;
513         if(!fd) return 0;
515         if(quicktime_supported_audio(fd, 0))
516         {
517 // Use Quicktime's compressor. (Always used)
518 // Allocate temp buffer
519                 new_audio_temp(len);
521 // Copy to float buffer
522                 for(i = 0; i < asset->channels; i++)
523                 {
524                         for(j = 0; j < len; j++)
525                         {
526                                 temp_float[i][j] = buffer[i][j];
527                         }
528                 }
530 // Because of the way Quicktime's compressors work we want to limit the chunk
531 // size to speed up decompression.
532                 float **channel_ptr;
533                 channel_ptr = new float*[asset->channels];
535                 for(j = 0; j < len && !result; )
536                 {
537                         chunk_size = asset->sample_rate;
538                         if(j + chunk_size > len) chunk_size = len - j;
540                         for(i = 0; i < asset->channels; i++)
541                         {
542                                 channel_ptr[i] = &temp_float[i][j];
543                         }
545                         result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
546                         j += asset->sample_rate;
547                 }
549                 delete [] channel_ptr;
550         }
551         return result;
554 int FileMOV::write_frames(VFrame ***frames, int len)
556         int i, j, k, result = 0;
557         int default_compressor = 1;
559         if(!fd) return 0;
560 //printf("FileMOV::write_frames 1\n");
561         for(i = 0; i < asset->layers && !result; i++)
562         {
568 // Fix direct copy cases for format conversions.
569                 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
570                 {
571                         default_compressor = 0;
572                         for(j = 0; j < len && !result; j++)
573                         {
574                                 VFrame *frame = frames[i][j];
578 // Special handling for DIVX
579 // Determine keyframe status.
580 // Write VOL header in the first frame if none exists
581                                 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
582                                         !strcmp(asset->vcodec, QUICKTIME_HV60))
583                                 {
584                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
585                                                 frame->get_compressed_size(),
586                                                 asset->vcodec))
587                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
591                                         if(!(file->current_frame + j) && 
592                                                 !quicktime_mpeg4_has_vol(frame->get_data()))
593                                         {
594                                                 VFrame *temp_frame = new VFrame;
596                                                 temp_frame->allocate_compressed_data(frame->get_compressed_size() + 
597                                                         0xff);
598                                                 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
599                                                         asset->width, 
600                                                         asset->height, 
601                                                         30000, 
602                                                         asset->frame_rate);
603                                                 memcpy(temp_frame->get_data() + bytes, 
604                                                         frame->get_data(), 
605                                                         frame->get_compressed_size());
606                                                 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
608                                                 result = quicktime_write_frame(fd,
609                                                         temp_frame->get_data(),
610                                                         temp_frame->get_compressed_size(),
611                                                         i);
613                                                 delete temp_frame;
616                                         }
617                                         else
618                                         {
619                                                 result = quicktime_write_frame(fd,
620                                                         frame->get_data(),
621                                                         frame->get_compressed_size(),
622                                                         i);
623                                         }
624                                 }
625                                 else
626                                 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
627                                 {
628                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
629                                                 frame->get_compressed_size(),
630                                                 asset->vcodec))
631                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
632                                         result = quicktime_write_frame(fd,
633                                                 frame->get_data(),
634                                                 frame->get_compressed_size(),
635                                                 i);
636                                 }
637                                 else
638                                 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
639                                 {
640                                         long field2_offset;
641 // Create extra space for markers
642                                         if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
643                                                 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
645                                         unsigned char *data = frame->get_data();
646                                         long data_size = frame->get_compressed_size();
647                                         long data_allocated = frame->get_compressed_allocated();
649                                         if(asset->format == FILE_MOV)
650                                         {
651                                                 mjpeg_insert_quicktime_markers(&data,
652                                                         &data_size,
653                                                         &data_allocated,
654                                                         2,
655                                                         &field2_offset);
656                                         }
657                                         else
658                                         {
659                                                 mjpeg_insert_avi_markers(&data,
660                                                         &data_size,
661                                                         &data_allocated,
662                                                         2,
663                                                         &field2_offset);
664                                         }
665                                         frame->set_compressed_size(data_size);
666                                         result = quicktime_write_frame(fd,
667                                                 frame->get_data(),
668                                                 frame->get_compressed_size(),
669                                                 i);
670                                 }
671                                 else
672                                         result = quicktime_write_frame(fd,
673                                                 frame->get_data(),
674                                                 frame->get_compressed_size(),
675                                                 i);
676                                 
677                                 
678                         }
679                 }
680                 else
681                 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
682                         match4(asset->vcodec, QUICKTIME_YUV422) ||
683                         match4(asset->vcodec, QUICKTIME_RAW))
684                 {
685 // Direct copy planes where possible
686                         default_compressor = 0;
687                         for(j = 0; j < len && !result; j++)
688                         {
689                                 VFrame *frame = frames[i][j];
690 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
691                                 quicktime_set_cmodel(fd, frame->get_color_model());
692 //printf("FileMOV::write_frames 1 %d\n", cmodel_is_planar(frame->get_color_model()));
693                                 if(cmodel_is_planar(frame->get_color_model()))
694                                 {
695                                         unsigned char *planes[3];
696                                         planes[0] = frame->get_y();
697                                         planes[1] = frame->get_u();
698                                         planes[2] = frame->get_v();
699                                         result = quicktime_encode_video(fd, planes, i);
700                                 }
701                                 else
702                                 {
703                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
704 //printf("FileMOV::write_frames 2 %d\n", result);
705                                 }
706 //printf("FileMOV::write_frames 2\n");
707                         }
708                 }
709                 else
710                 if(file->cpus > 1 && 
711                         (match4(asset->vcodec, QUICKTIME_JPEG) || 
712                         match4(asset->vcodec, QUICKTIME_MJPA)))
713                 {
714                         default_compressor = 0;
715 // Compress symmetrically on an SMP system.
716                         ThreadStruct *threadframe;
717                         int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
719 // Set up threads for symmetric compression.
720                         if(!threads)
721                         {
722                                 threads = new FileMOVThread*[file->cpus];
723                                 for(j = 0; j < file->cpus; j++)
724                                 {
725                                         threads[j] = new FileMOVThread(this, fields);
726                                         threads[j]->start_encoding();
727                                 }
728                         }
730 // Set up the frame structures for asynchronous compression.
731 // The mjpeg object must exist in each threadframe because it is where the output
732 // is stored.
733                         while(threadframes.total < len)
734                         {
735                                 threadframes.append(threadframe = new ThreadStruct);
736                         }
738 // Load thread frame structures with new frames.
739                         for(j = 0; j < len; j++)
740                         {
741                                 VFrame *frame = frames[i][j];
742                                 threadframes.values[j]->input = frame;
743                                 threadframes.values[j]->completion_lock.lock();
744                         }
745                         total_threadframes = len;
746                         current_threadframe = 0;
748 // Start the threads compressing
749                         for(j = 0; j < file->cpus; j++)
750                         {
751                                 threads[j]->encode_buffer();
752                         }
754 // Write the frames as they're finished
755                         for(j = 0; j < len; j++)
756                         {
757                                 threadframes.values[j]->completion_lock.lock();
758                                 threadframes.values[j]->completion_lock.unlock();
759 //printf("filemov 1\n");
760                                 if(!result)
761                                 {
762                                         result = quicktime_write_frame(fd, 
763                                                 threadframes.values[j]->output,
764                                                 threadframes.values[j]->output_size,
765                                                 i);
766                                 }
767                         }
768                 }
770                 if(default_compressor)
771                 {
772 //printf("FileMOV::write_frames 3\n");
773 // Use the library's built in compressor.
774                         for(j = 0; j < len && !result; j++)
775                         {
776 //printf("FileMOV::write_frames 4\n");
777                                 VFrame *frame = frames[i][j];
778                                 quicktime_set_cmodel(fd, frame->get_color_model());
779 //printf("FileMOV::write_frames 5\n");
780                                 if(cmodel_is_planar(frame->get_color_model()))
781                                 {
782                                         unsigned char *planes[3];
783                                         planes[0] = frame->get_y();
784                                         planes[1] = frame->get_u();
785                                         planes[2] = frame->get_v();
786 //printf("FileMOV::write_frames 6\n");
787                                         result = quicktime_encode_video(fd, planes, i);
788 //printf("FileMOV::write_frames 7\n");
789                                 }
790                                 else
791                                 {
792 //printf("FileMOV::write_frames 8\n");
793                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
794 //printf("FileMOV::write_frames 9\n");
795                                 }
796                         }
797                 }
798 //printf("FileMOV::write_frames 4\n");
799         }
802 //printf("FileMOV::write_frames 100 %d\n", result);
803         return result;
808 int FileMOV::read_frame(VFrame *frame)
810         if(!fd) return 1;
811         int result = 0;
813 //printf("FileMOV::read_frame 1\n");
814         switch(frame->get_color_model())
815         {
816                 case BC_COMPRESSED:
817                         frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
818                         frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
819                         result = quicktime_read_frame(fd, 
820                                 frame->get_data(), 
821                                 file->current_layer);
822                         break;
824 // Progressive
825                 case BC_YUV420P:
826                 case BC_YUV422P:
827                 {
828                         unsigned char *row_pointers[3];
829                         row_pointers[0] = frame->get_y();
830                         row_pointers[1] = frame->get_u();
831                         row_pointers[2] = frame->get_v();
833                         quicktime_set_cmodel(fd, frame->get_color_model());
834                         quicktime_decode_video(fd, 
835                                 row_pointers,
836                                 file->current_layer);
837                 }
838                         break;
840 // Packed
841                 default:
842                         quicktime_set_cmodel(fd, frame->get_color_model());
843                         result = quicktime_decode_video(fd, 
844                                 frame->get_rows(),
845                                 file->current_layer);
846 //for(int i = 0; i < 10000; i++) frame->get_rows()[0][i] = 0xff;
847                         break;
848         }
852 //printf("FileMOV::read_frame 100\n");
853         return result;
858 int64_t FileMOV::compressed_frame_size()
860         if(!fd) return 0;
861         return quicktime_frame_size(fd, file->current_frame, file->current_layer);
864 int FileMOV::read_compressed_frame(VFrame *buffer)
866         int64_t result;
867         if(!fd) return 0;
869 //printf("FileMOV::read_compressed_frame 1\n");
870         result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
871         buffer->set_compressed_size(result);
872 //printf("FileMOV::read_compressed_frame 100\n");
873         result = !result;
874         return result;
877 int FileMOV::write_compressed_frame(VFrame *buffer)
879         int result = 0;
880         if(!fd) return 0;
882 //printf("FileMOV::write_compressed_frame 1\n");
883         result = quicktime_write_frame(fd, 
884                 buffer->get_data(), 
885                 buffer->get_compressed_size(), 
886                 file->current_layer);
887 //printf("FileMOV::write_compressed_frame 100\n");
888         return result;
893 int FileMOV::read_raw(VFrame *frame, 
894                 float in_x1, float in_y1, float in_x2, float in_y2,
895                 float out_x1, float out_y1, float out_x2, float out_y2, 
896                 int use_float, int interpolate)
898         int64_t i, color_channels, result = 0;
899         if(!fd) return 0;
900         quicktime_set_video_position(fd, file->current_frame, file->current_layer);
901 // Develop importing strategy
902         switch(frame->get_color_model())
903         {
904                 case BC_RGB888:
905                         result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
906                         break;
907                 case BC_RGBA8888:
908                         break;
909                 case BC_RGB161616:
910                         break;
911                 case BC_RGBA16161616:
912                         break;
913                 case BC_YUV888:
914                         break;
915                 case BC_YUVA8888:
916                         break;
917                 case BC_YUV161616:
918                         break;
919                 case BC_YUVA16161616:
920                         break;
921                 case BC_YUV420P:
922                         break;
923         }
924         return result;
927 // Overlay samples
928 int FileMOV::read_samples(double *buffer, int64_t len)
930         int qt_track, qt_channel;
932         if(!fd) return 0;
934 //printf("FileMOV::read_samples 1\n");
935         if(quicktime_track_channels(fd, 0) > file->current_channel &&
936                 quicktime_supported_audio(fd, 0))
937         {
939 //printf("FileMOV::read_samples 2 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
940                 new_audio_temp(len);
942 //printf("FileMOV::read_samples 3 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
943                 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
944                 {
945                         printf("FileMOV::read_samples: quicktime_decode_audio failed\n");
946                         return 1;
947                 }
948                 else
949                 {
950                         for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
951                 }
953 // if(file->current_channel == 0)
954 // for(int i = 0; i < len; i++)
955 // {
956 //      int16_t value;
957 //      value = (int16_t)(temp_float[0][i] * 32767);
958 //      fwrite(&value, 2, 1, stdout);
959 // }
960 //printf("FileMOV::read_samples 4 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
961         }
963 //printf("FileMOV::read_samples 100\n");
964         return 0;
968 char* FileMOV::strtocompression(char *string)
970         if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
971         if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
972         if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
973         if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
974         if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
975         if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
976         if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
977         if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
978         if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
979         if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
980         if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
981         if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
982         if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
983         if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
984         if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
985         if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
987         if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
988         if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
989         if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
990         if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
991         if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
992         if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
996         return QUICKTIME_RAW;
999 char* FileMOV::compressiontostr(char *string)
1001         if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1002         if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1003         if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1004         if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1005         if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1006         if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1007         if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1008         if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1009         if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1010         if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1011         if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1012         if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1013         if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1014         if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1015         if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1021         if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1022         if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1023         if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1024         if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1025         if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1026         if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1030         return _("Unknown");
1037 ThreadStruct::ThreadStruct()
1039         input = 0;
1040         output = 0;
1041         output_allocated = 0;
1042         output_size = 0;
1045 ThreadStruct::~ThreadStruct()
1047         if(output) delete [] output;
1050 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1052         if(output_allocated < mjpeg_output_size(mjpeg))
1053         {
1054                 delete [] output;
1055                 output = 0;
1056         }
1057         if(!output)
1058         {
1059                 output_allocated = mjpeg_output_size(mjpeg);
1060                 output = new unsigned char[output_allocated];
1061         }
1062         
1063         output_size = mjpeg_output_size(mjpeg);
1064         memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1068 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields) : Thread()
1070         this->filemov = filemov;
1071         this->fields = fields;
1072         mjpeg = 0;
1074 FileMOVThread::~FileMOVThread()
1078 int FileMOVThread::start_encoding()
1080 //printf("FileMOVThread::start_encoding 1 %d\n", fields);
1081         mjpeg = mjpeg_new(filemov->asset->width, 
1082                 filemov->asset->height, 
1083                 fields);
1084         mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1085         mjpeg_set_float(mjpeg, 0);
1086         done = 0;
1087         set_synchronous(1);
1088         input_lock.lock();
1089         start();
1092 int FileMOVThread::stop_encoding()
1094         done = 1;
1095         input_lock.unlock();
1096         join();
1097         if(mjpeg) mjpeg_delete(mjpeg);
1100 int FileMOVThread::encode_buffer()
1102         input_lock.unlock();
1105 void FileMOVThread::run()
1107         while(!done)
1108         {
1109                 input_lock.lock();
1111                 if(!done)
1112                 {
1113 // Get a frame to compress.
1114                         filemov->threadframe_lock.lock();
1115                         if(filemov->current_threadframe < filemov->total_threadframes)
1116                         {
1117 // Frame is available to process.
1118                                 input_lock.unlock();
1119                                 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1120                                 VFrame *frame = threadframe->input;
1122                                 filemov->current_threadframe++;
1123                                 filemov->threadframe_lock.unlock();
1125 //printf("FileMOVThread 1 %02x%02x\n", mjpeg_output_buffer(mjpeg)[0], mjpeg_output_buffer(mjpeg)[1]);
1126                                 mjpeg_compress(mjpeg, 
1127                                         frame->get_rows(), 
1128                                         frame->get_y(), 
1129                                         frame->get_u(), 
1130                                         frame->get_v(),
1131                                         frame->get_color_model(),
1132                                         1);
1134 //printf("FileMOVThread 1 %02x%02x\n", mjpeg_output_buffer(mjpeg)[0], mjpeg_output_buffer(mjpeg)[1]);
1135 //printf("FileMOVThread 1\n");
1136                                 if(fields > 1)
1137                                 {
1138                                         long field2_offset;
1139 // Create extra space for markers
1140                                         if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
1141                                                 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
1143                                         unsigned char *data = frame->get_data();
1144                                         long data_size = frame->get_compressed_size();
1145                                         long data_allocated = frame->get_compressed_allocated();
1147                                         if(filemov->asset->format == FILE_MOV)
1148                                         {
1149                                                 mjpeg_insert_quicktime_markers(&data,
1150                                                         &data_size,
1151                                                         &data_allocated,
1152                                                         2,
1153                                                         &field2_offset);
1154                                         }
1155                                         else
1156                                         {
1157                                                 mjpeg_insert_avi_markers(&data,
1158                                                         &data_size,
1159                                                         &data_allocated,
1160                                                         2,
1161                                                         &field2_offset);
1162                                         }
1163                                         frame->set_compressed_size(data_size);
1164                                 }
1165                                 threadframe->load_output(mjpeg);
1166 //printf("FileMOVThread 2 %02x%02x\n", mjpeg_output_buffer(mjpeg)[0], mjpeg_output_buffer(mjpeg)[1]);
1168 //printf("FileMOVThread 2 %p\n", this);
1169                                 threadframe->completion_lock.unlock();
1170                         }
1171                         else
1172                                 filemov->threadframe_lock.unlock();
1173                 }
1174         }
1182 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1183  : BC_Window(PROGRAM_NAME ": Audio Compression",
1184         parent_window->get_abs_cursor_x(),
1185         parent_window->get_abs_cursor_y(),
1186         350,
1187         250)
1189         this->parent_window = parent_window;
1190         this->asset = asset;
1191         bits_popup = 0;
1192         bits_title = 0;
1193         dither = 0;
1194         vorbis_min_bitrate = 0;
1195         vorbis_bitrate = 0;
1196         vorbis_max_bitrate = 0;
1197         vorbis_vbr = 0;
1198         compression_popup = 0;
1199         mp3_bitrate = 0;
1202 MOVConfigAudio::~MOVConfigAudio()
1204         if(compression_popup) delete compression_popup;
1205         if(bits_popup) delete bits_popup;
1206         compression_items.remove_all_objects();
1209 int MOVConfigAudio::create_objects()
1211         int x = 10, y = 10;
1213         
1215         if(asset->format == FILE_MOV)
1216         {
1217                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1218                 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1219                 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1220                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1221                 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1222                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1223         }
1224         else
1225         {
1226                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1227                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1228                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1229         }
1231         add_tool(new BC_Title(x, y, _("Compression:")));
1232         y += 25;
1233         compression_popup = new MOVConfigAudioPopup(this, x, y);
1234         compression_popup->create_objects();
1236         update_parameters();
1238         add_subwindow(new BC_OKButton(this));
1239         return 0;
1242 void MOVConfigAudio::update_parameters()
1244         int x = 10, y = 70;
1245         if(bits_title) delete bits_title;
1246         if(bits_popup) delete bits_popup;
1247         if(dither) delete dither;
1248         if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1249         if(vorbis_bitrate) delete vorbis_bitrate;
1250         if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1251         if(vorbis_vbr) delete vorbis_vbr;
1252         if(mp3_bitrate) delete mp3_bitrate;
1254         bits_popup = 0;
1255         bits_title = 0;
1256         dither = 0;
1257         vorbis_min_bitrate = 0;
1258         vorbis_bitrate = 0;
1259         vorbis_max_bitrate = 0;
1260         vorbis_vbr = 0;
1264         mp3_bitrate = 0;
1268         if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1269                 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1270         {
1271                 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1272                 bits_popup = new BitsPopup(this, 
1273                         x + 150, 
1274                         y, 
1275                         &asset->bits, 
1276                         0, 
1277                         0, 
1278                         0, 
1279                         0, 
1280                         0);
1281                 bits_popup->create_objects();
1282                 y += 40;
1283                 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1284         }
1285         else
1286         if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1287         {
1288         }
1289         else
1290         if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1291         {
1292                 mp3_bitrate = new MOVConfigAudioNum(this, 
1293                         _("Bitrate:"), 
1294                         x, 
1295                         y, 
1296                         &asset->mp3_bitrate);
1297                 mp3_bitrate->set_increment(1000);
1298                 mp3_bitrate->create_objects();
1299         }
1300         else
1301         if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1302         {
1303         }
1304         else
1305         if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1306         {
1307                 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1308                         _("Variable bitrate"),
1309                         x,
1310                         y,
1311                         &asset->vorbis_vbr));
1312                 y += 35;
1313                 vorbis_min_bitrate = new MOVConfigAudioNum(this, 
1314                         _("Min bitrate:"), 
1315                         x, 
1316                         y, 
1317                         &asset->vorbis_min_bitrate);
1318                 y += 30;
1319                 vorbis_bitrate = new MOVConfigAudioNum(this, 
1320                         _("Avg bitrate:"), 
1321                         x, 
1322                         y, 
1323                         &asset->vorbis_bitrate);
1324                 y += 30;
1325                 vorbis_max_bitrate = new MOVConfigAudioNum(this, 
1326                         _("Max bitrate:"), 
1327                         x, 
1328                         y, 
1329                         &asset->vorbis_max_bitrate);
1333                 vorbis_min_bitrate->create_objects();
1334                 vorbis_bitrate->create_objects();
1335                 vorbis_max_bitrate->create_objects();
1336         }
1339 int MOVConfigAudio::close_event()
1341         set_done(0);
1342         return 1;
1349 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1350         char *title_text,
1351         int x,
1352         int y,
1353         int *output)
1354  : BC_CheckBox(x, y, *output, title_text)
1356         this->popup = popup;
1357         this->output = output;
1359 int MOVConfigAudioToggle::handle_event()
1361         *output = get_value();
1362         return 1;
1369 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1370  : BC_TumbleTextBox(popup, 
1371                 (int64_t)*output,
1372                 (int64_t)-1,
1373                 (int64_t)25000000,
1374                 x + 150, 
1375                 y, 
1376                 100)
1378         this->popup = popup;
1379         this->title_text = title_text;
1380         this->output = output;
1381         this->x = x;
1382         this->y = y;
1385 MOVConfigAudioNum::~MOVConfigAudioNum()
1387         delete title;
1390 void MOVConfigAudioNum::create_objects()
1392         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1393         BC_TumbleTextBox::create_objects();
1396 int MOVConfigAudioNum::handle_event()
1398         *output = atol(get_text());
1399         return 1;
1409 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1410  : BC_PopupTextBox(popup, 
1411                 &popup->compression_items,
1412                 FileMOV::compressiontostr(popup->asset->acodec),
1413                 x, 
1414                 y, 
1415                 300,
1416                 300)
1418         this->popup = popup;
1421 int MOVConfigAudioPopup::handle_event()
1423         strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1424         popup->update_parameters();
1425         return 1;
1444 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window, 
1445         Asset *asset, 
1446         int lock_compressor)
1447  : BC_Window(PROGRAM_NAME ": Video Compression",
1448         parent_window->get_abs_cursor_x(),
1449         parent_window->get_abs_cursor_y(),
1450         420,
1451         420)
1453         this->parent_window = parent_window;
1454         this->asset = asset;
1455         this->lock_compressor = lock_compressor;
1456         compression_popup = 0;
1458         reset();
1461 MOVConfigVideo::~MOVConfigVideo()
1463         if(compression_popup) delete compression_popup;
1464         compression_items.remove_all_objects();
1467 int MOVConfigVideo::create_objects()
1469         int x = 10, y = 10;
1471         if(asset->format == FILE_MOV)
1472         {
1473                 compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1474                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1475                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1476                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1477                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1478                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1479                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1480                 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1481                 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1482                 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1483                 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1484                 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1485                 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1486                 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1487                 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1488         }
1489         else
1490         {
1491                 compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1492                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1493                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1494                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1495                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1496                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1497                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1498         }
1500         add_subwindow(new BC_Title(x, y, _("Compression:")));
1501         y += 25;
1503         if(!lock_compressor)
1504         {
1505                 compression_popup = new MOVConfigVideoPopup(this, x, y);
1506                 compression_popup->create_objects();
1507         }
1508         else
1509         {
1510                 add_subwindow(new BC_Title(x, 
1511                         y, 
1512                         FileMOV::compressiontostr(asset->vcodec),
1513                         MEDIUMFONT,
1514                         RED,
1515                         0));
1516         }
1517         y += 40;
1519         param_x = x;
1520         param_y = y;
1521         update_parameters();
1523         add_subwindow(new BC_OKButton(this));
1524         return 0;
1527 int MOVConfigVideo::close_event()
1529         set_done(0);
1530         return 1;
1534 void MOVConfigVideo::reset()
1536         jpeg_quality = 0;
1537         jpeg_quality_title = 0;
1539         divx_bitrate = 0;
1540         divx_rc_period = 0;
1541         divx_rc_reaction_ratio = 0;
1542         divx_rc_reaction_period = 0;
1543         divx_max_key_interval = 0;
1544         divx_max_quantizer = 0;
1545         divx_min_quantizer = 0;
1546         divx_quantizer = 0;
1547         divx_quality = 0;
1548         divx_fix_bitrate = 0;
1549         divx_fix_quant = 0;
1551         ms_bitrate = 0;
1552         ms_bitrate_tolerance = 0;
1553         ms_quantization = 0;
1554         ms_interlaced = 0;
1555         ms_gop_size = 0;
1556         ms_fix_bitrate = 0;
1557         ms_fix_quant = 0;
1560 void MOVConfigVideo::update_parameters()
1562         if(jpeg_quality)
1563         {
1564                 delete jpeg_quality_title;
1565                 delete jpeg_quality;
1566         }
1568         if(divx_bitrate) delete divx_bitrate;
1569         if(divx_rc_period) delete divx_rc_period;
1570         if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1571         if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1572         if(divx_max_key_interval) delete divx_max_key_interval;
1573         if(divx_max_quantizer) delete divx_max_quantizer;
1574         if(divx_min_quantizer) delete divx_min_quantizer;
1575         if(divx_quantizer) delete divx_quantizer;
1576         if(divx_quality) delete divx_quality;
1577         if(divx_fix_quant) delete divx_fix_quant;
1578         if(divx_fix_bitrate) delete divx_fix_bitrate;
1580         if(ms_bitrate) delete ms_bitrate;
1581         if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1582         if(ms_interlaced) delete ms_interlaced;
1583         if(ms_quantization) delete ms_quantization;
1584         if(ms_gop_size) delete ms_gop_size;
1585         if(ms_fix_bitrate) delete ms_fix_bitrate;
1586         if(ms_fix_quant) delete ms_fix_quant;
1588         reset();
1590 // ffmpeg parameters
1591         if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
1592         {
1593                 int x = param_x, y = param_y;
1594                 ms_bitrate = new MOVConfigVideoNum(this, 
1595                         _("Bitrate:"), 
1596                         x, 
1597                         y, 
1598                         &asset->ms_bitrate);
1599                 ms_bitrate->set_increment(1000000);
1600                 ms_bitrate->create_objects();
1601                 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260, 
1602                                 y,
1603                                 &asset->ms_fix_bitrate,
1604                                 1));
1605                 y += 30;
1607                 ms_bitrate_tolerance = new MOVConfigVideoNum(this, 
1608                         _("Bitrate tolerance:"), 
1609                         x, 
1610                         y, 
1611                         &asset->ms_bitrate_tolerance);
1612                 ms_bitrate_tolerance->create_objects();
1613                 y += 30;
1614                 ms_quantization = new MOVConfigVideoNum(this, 
1615                         _("Quantization:"), 
1616                         x, 
1617                         y, 
1618                         &asset->ms_quantization);
1619                 ms_quantization->create_objects();
1620                 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260, 
1621                                 y,
1622                                 &asset->ms_fix_bitrate,
1623                                 0));
1624                 ms_fix_bitrate->opposite = ms_fix_quant;
1625                 ms_fix_quant->opposite = ms_fix_bitrate;
1628                 y += 30;
1629                 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"), 
1630                         x, 
1631                         y, 
1632                         &asset->ms_interlaced));
1633                 y += 30;
1634                 ms_gop_size = new MOVConfigVideoNum(this, 
1635                         _("Keyframe interval:"), 
1636                         x, 
1637                         y, 
1638                         &asset->ms_gop_size);
1639                 ms_gop_size->create_objects();
1640         }
1641         else
1642 // OpenDivx parameters
1643         if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
1644                 !strcmp(asset->vcodec, QUICKTIME_HV60))
1645         {
1646                 int x = param_x, y = param_y;
1647                 divx_bitrate = new MOVConfigVideoNum(this, 
1648                         _("Bitrate:"), 
1649                         x, 
1650                         y, 
1651                         &asset->divx_bitrate);
1652                 divx_bitrate->set_increment(1000000);
1653                 divx_bitrate->create_objects();
1654                 add_subwindow(divx_fix_bitrate = 
1655                         new MOVConfigVideoFixBitrate(x + 260, 
1656                                 y,
1657                                 &asset->divx_fix_bitrate,
1658                                 1));
1659                 y += 30;
1660                 divx_quantizer = new MOVConfigVideoNum(this, 
1661                         _("Quantizer:"), 
1662                         x, 
1663                         y, 
1664                         &asset->divx_quantizer);
1665                 divx_quantizer->create_objects();
1666                 add_subwindow(divx_fix_quant =
1667                         new MOVConfigVideoFixQuant(x + 260, 
1668                                 y,
1669                                 &asset->divx_fix_bitrate,
1670                                 0));
1671                 divx_fix_quant->opposite = divx_fix_bitrate;
1672                 divx_fix_bitrate->opposite = divx_fix_quant;
1673                 y += 30;
1674                 divx_rc_period = new MOVConfigVideoNum(this, 
1675                         _("RC Period:"), 
1676                         x, 
1677                         y, 
1678                         &asset->divx_rc_period);
1679                 divx_rc_period->create_objects();
1680                 y += 30;
1681                 divx_rc_reaction_ratio = new MOVConfigVideoNum(this, 
1682                         _("Reaction Ratio:"), 
1683                         x, 
1684                         y, 
1685                         &asset->divx_rc_reaction_ratio);
1686                 divx_rc_reaction_ratio->create_objects();
1687                 y += 30;
1688                 divx_rc_reaction_period = new MOVConfigVideoNum(this, 
1689                         _("Reaction Period:"), 
1690                         x, 
1691                         y, 
1692                         &asset->divx_rc_reaction_period);
1693                 divx_rc_reaction_period->create_objects();
1694                 y += 30;
1695                 divx_max_key_interval = new MOVConfigVideoNum(this, 
1696                         _("Max Key Interval:"), 
1697                         x, 
1698                         y, 
1699                         &asset->divx_max_key_interval);
1700                 divx_max_key_interval->create_objects();
1701                 y += 30;
1702                 divx_max_quantizer = new MOVConfigVideoNum(this, 
1703                         _("Max Quantizer:"), 
1704                         x, 
1705                         y, 
1706                         &asset->divx_max_quantizer);
1707                 divx_max_quantizer->create_objects();
1708                 y += 30;
1709                 divx_min_quantizer = new MOVConfigVideoNum(this, 
1710                         _("Min Quantizer:"), 
1711                         x, 
1712                         y, 
1713                         &asset->divx_min_quantizer);
1714                 divx_min_quantizer->create_objects();
1715                 y += 30;
1716                 divx_quality = new MOVConfigVideoNum(this, 
1717                         _("Quality:"), 
1718                         x, 
1719                         y, 
1720                         &asset->divx_quality);
1721                 divx_quality->create_objects();
1722         }
1723         else
1724         if(!strcmp(asset->vcodec, QUICKTIME_JPEG) ||
1725                 !strcmp(asset->vcodec, QUICKTIME_MJPA))
1726         {
1727                 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
1728                 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80, 
1729                         param_y,
1730                         0,
1731                         200,
1732                         200,
1733                         0,
1734                         100,
1735                         asset->jpeg_quality,
1736                         0,
1737                         0,
1738                         &asset->jpeg_quality));
1739         }
1746 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
1747  : BC_TumbleTextBox(popup, 
1748                 (int64_t)*output,
1749                 (int64_t)1,
1750                 (int64_t)25000000,
1751                 x + 130, 
1752                 y, 
1753                 100)
1755         this->popup = popup;
1756         this->title_text = title_text;
1757         this->output = output;
1758         this->x = x;
1759         this->y = y;
1762 MOVConfigVideoNum::~MOVConfigVideoNum()
1764         delete title;
1767 void MOVConfigVideoNum::create_objects()
1769         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1770         BC_TumbleTextBox::create_objects();
1773 int MOVConfigVideoNum::handle_event()
1775         *output = atol(get_text());
1776         return 1;
1785 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
1786  : BC_CheckBox(x, y, *output, title_text)
1788         this->output = output;
1791 int MOVConfigVideoCheckBox::handle_event()
1793         *output = get_value();
1794         return 1;
1802 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x, 
1803         int y,
1804         int *output,
1805         int value)
1806  : BC_Radial(x, 
1807         y, 
1808         *output == value, 
1809         _("Fix bitrate"))
1811         this->output = output;
1812         this->value = value;
1815 int MOVConfigVideoFixBitrate::handle_event()
1817         *output = value;
1818         opposite->update(0);
1819         return 1;
1827 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x, 
1828         int y,
1829         int *output,
1830         int value)
1831  : BC_Radial(x, 
1832         y, 
1833         *output == value, 
1834         _("Fix quantization"))
1836         this->output = output;
1837         this->value = value;
1840 int MOVConfigVideoFixQuant::handle_event()
1842         *output = value;
1843         opposite->update(0);
1844         return 1;
1851 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
1852  : BC_PopupTextBox(popup, 
1853                 &popup->compression_items,
1854                 FileMOV::compressiontostr(popup->asset->vcodec),
1855                 x, 
1856                 y, 
1857                 300,
1858                 300)
1860         this->popup = popup;
1863 int MOVConfigVideoPopup::handle_event()
1865         strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
1866         popup->update_parameters();
1867         return 1;