r602: Fix baver's code... don't insert timecode when show_tc is not set
[cinelerra_cv/mob.git] / cinelerra / filemov.C
blob9a619cbd92a5987cd6fd04206798d020575e719f
1 #include "asset.h"
2 #include "bcsignals.h"
3 #include "bitspopup.h"
4 #include "byteorder.h"
5 #include "condition.h"
6 #include "edit.h"
7 #include "file.h"
8 #include "filemov.h"
9 #include "guicast.h"
10 #include "language.h"
11 #include "mwindow.inc"
12 #include "vframe.h"
13 #include "videodevice.inc"
15 #include <unistd.h>
16 #include <libdv/dv.h>
18 #if 0
19 N_("MPEG-4")
20 N_("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 MP4V_NAME "MPEG-4 Video"
47 #define H263_NAME "H.263"
48 #define HV60_NAME "Heroine 60"
49 #define DIV3_NAME "Microsoft MPEG-4"
50 #define DV_NAME "DV"
51 #define PNG_NAME "PNG"
52 #define PNGA_NAME "PNG with Alpha"
53 #define RGB_NAME "Uncompressed RGB"
54 #define RGBA_NAME "Uncompressed RGBA"
55 #define YUV420_NAME "YUV 4:2:0 Planar"
56 #define YUV422_NAME "Component Video"
57 #define YUV411_NAME "YUV 4:1:1 Packed"
58 #define YUV444_NAME "Component Y'CbCr 8-bit 4:4:4"
59 #define YUVA4444_NAME "Component Y'CbCrA 8-bit 4:4:4:4"
60 #define YUV444_10BIT_NAME "Component Y'CbCr 10-bit 4:4:4"
61 #define QTJPEG_NAME "JPEG Photo"
62 #define MJPA_NAME "Motion JPEG A"
65 #define TWOS_NAME "Twos complement"
66 #define RAW_NAME "Unsigned"
67 #define IMA4_NAME "IMA-4"
68 #define ULAW_NAME "U-Law"
69 //#define VORBIS_NAME "Vorbis"
70 #define MP3_NAME "MP3"
76 FileMOV::FileMOV(Asset *asset, File *file)
77  : FileBase(asset, file)
79         reset_parameters();
80         if(asset->format == FILE_UNKNOWN)
81                 asset->format = FILE_MOV;
82         asset->byte_order = 0;
83         suffix_number = 0;
84         threadframe_lock = new Mutex("FileMOV::threadframe_lock");
87 FileMOV::~FileMOV()
89         close_file();
90         delete threadframe_lock;
93 void FileMOV::get_parameters(BC_WindowBase *parent_window, 
94         Asset *asset, 
95         BC_WindowBase* &format_window,
96         int audio_options,
97         int video_options,
98         int lock_compressor)
100         fix_codecs(asset);
101         if(audio_options)
102         {
103                 MOVConfigAudio *window = new MOVConfigAudio(parent_window, asset);
104                 format_window = window;
105                 window->create_objects();
106                 window->run_window();
107                 delete window;
108         }
109         else
110         if(video_options)
111         {
112                 MOVConfigVideo *window = new MOVConfigVideo(parent_window, 
113                         asset, 
114                         lock_compressor);
115                 format_window = window;
116                 window->create_objects();
117                 window->run_window();
118                 delete window;
119         }
122 void FileMOV::fix_codecs(Asset *asset)
124 //      if(asset->format == FILE_MOV)
125 //      {
126 //              if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
127 //                      strcpy(asset->acodec, QUICKTIME_TWOS);
128 //      }
129 //      else
130 //      {
131 //              if(strcasecmp(asset->vcodec, QUICKTIME_DIV3))
132 //              {
133 //                      strcpy(asset->vcodec, QUICKTIME_DIV3);
134 //              }
135 //              strcpy(asset->acodec, QUICKTIME_MP3);
136 //      }
139 int FileMOV::check_sig(Asset *asset)
141         return quicktime_check_sig(asset->path);
145 int FileMOV::reset_parameters_derived()
147         fd = 0;
148         prev_track = 0;
149         quicktime_atracks = 0;
150         quicktime_vtracks = 0;
151         depth = 24;
152         threads = 0;
153         frames_correction = 0;
154         samples_correction = 0;
155         temp_float = 0;
156         temp_allocated = 0;
160 // Just create the Quicktime objects since this routine is also called
161 // for reopening.
162 int FileMOV::open_file(int rd, int wr)
164         this->rd = rd;
165         this->wr = wr;
167         if(suffix_number == 0) strcpy(prefix_path, asset->path);
169         if(!(fd = quicktime_open(asset->path, rd, wr)))
170         {
171                 printf(_("FileMOV::open_file %s: No such file or directory\n"), asset->path);
172                 return 1;
173         }
175         quicktime_set_cpus(fd, file->cpus);
177         if(rd)
178         {
179                 format_to_asset();
180                 
181                 // If DV stream, get the timecode
182                 if(match4(asset->vcodec, QUICKTIME_DV))
183                 {
184                         char tc[12];
185                         dv_decoder_t *tmp_decoder = dv_decoder_new(0,0,0);
186                         VFrame *frame = new VFrame(0, 0, 0, BC_COMPRESSED);
187                         
188                         read_frame(frame);
189                         set_video_position(0);
190                         
191                         if(dv_parse_header(tmp_decoder, frame->get_data()) > -1)
192                         {
193                                 dv_parse_packs(tmp_decoder, frame->get_data());
194                                 dv_get_timestamp(tmp_decoder, tc);
195                                 printf("Timestamp %s\n", tc);
196                         
197                                 float seconds = Units::text_to_seconds(tc,
198                                                                                 1, // Use 1 as sample rate, doesn't matter
199                                                                                 TIME_HMSF,
200                                                                                 tmp_decoder->height == 576 ? 25 : 30, // FIXME
201                                                                                 0);
202                                 // Get frame number
203                                 asset->tcstart = seconds * (tmp_decoder->height == 576 ? 25 : 30);
204                         }
205                         
206                 }
207         }
209         if(wr) asset_to_format();
211 // Set decoding parameter
212         quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking);
214 // Set timecode offset
215         quicktime_set_frame_start(fd, asset->tcstart);
217         return 0;
220 int FileMOV::close_file()
222 //printf("FileMOV::close_file 1 %s\n", asset->path);
223         if(fd)
224         {
225                 if(wr) quicktime_set_framerate(fd, asset->frame_rate);
226                 quicktime_close(fd);
227         }
229 //printf("FileMOV::close_file 1\n");
230         if(threads)
231         {
232                 for(int i = 0; i < file->cpus; i++)
233                 {
234                         threads[i]->stop_encoding();
235                         delete threads[i];
236                 }
237                 delete [] threads;
238                 threads = 0;
239         }
241 //printf("FileMOV::close_file 1\n");
242         threadframes.remove_all_objects();
245         if(temp_float) 
246         {
247                 for(int i = 0; i < asset->channels; i++)
248                         delete [] temp_float[i];
249                 delete [] temp_float;
250         }
252 //printf("FileMOV::close_file 1\n");
253         reset_parameters();
254         FileBase::close_file();
255 //printf("FileMOV::close_file 2\n");
256         return 0;
259 void FileMOV::set_frame_start(int64_t offset)
261         quicktime_set_frame_start(fd, offset);
264 void FileMOV::asset_to_format()
266         if(!fd) return;
267         char audio_codec[5];
269         fix_codecs(asset);
271 // Fix up the Quicktime file.
272         quicktime_set_copyright(fd, _("Made with Cinelerra for Linux"));
273         quicktime_set_info(fd, "Quicktime for Linux");
275         if(asset->audio_data)
276         {
277                 quicktime_atracks = quicktime_set_audio(fd, 
278                                 asset->channels, 
279                                 asset->sample_rate, 
280                                 asset->bits, 
281                                 asset->acodec);
282                 quicktime_set_parameter(fd, "vorbis_vbr", &asset->vorbis_vbr);
283                 quicktime_set_parameter(fd, "vorbis_min_bitrate", &asset->vorbis_min_bitrate);
284                 quicktime_set_parameter(fd, "vorbis_bitrate", &asset->vorbis_bitrate);
285                 quicktime_set_parameter(fd, "vorbis_max_bitrate", &asset->vorbis_max_bitrate);
286                 quicktime_set_parameter(fd, "mp3_bitrate", &asset->mp3_bitrate);
287         }
289         if(asset->video_data)
290         {
291                 char string[16];
292 // Set up the alpha channel compressors
293                 if(!strcmp(asset->vcodec, MOV_RGBA))
294                 {
295                         strcpy(string, QUICKTIME_RAW);
296                         depth = 32;
297                 }
298                 else
299                 if(!strcmp(asset->vcodec, MOV_PNGA))
300                 {
301                         strcpy(string, QUICKTIME_PNG);
302                         depth = 32;
303                 }
304                 else
305                 if(!strcmp(asset->vcodec, QUICKTIME_YUVA4444))
306                 {
307                         strcpy(string, asset->vcodec);
308                         depth = 32;
309                 }
310                 else
311                 {
312                         strcpy(string, asset->vcodec);
313                         depth = 24;
314                 }
316                 quicktime_vtracks = quicktime_set_video(fd, 
317                                         asset->layers, 
318                                         asset->width, 
319                                         asset->height,
320                                         asset->frame_rate,
321                                         string);
325                 for(int i = 0; i < asset->layers; i++)
326                         quicktime_set_depth(fd, depth, i);
328                 quicktime_set_parameter(fd, "jpeg_quality", &asset->jpeg_quality);
330 // set the compression parameters if there are any
331                 quicktime_set_parameter(fd, "divx_bitrate", &asset->divx_bitrate);
332                 quicktime_set_parameter(fd, "divx_rc_period", &asset->divx_rc_period);
333                 quicktime_set_parameter(fd, "divx_rc_reaction_ratio", &asset->divx_rc_reaction_ratio);
334                 quicktime_set_parameter(fd, "divx_rc_reaction_period", &asset->divx_rc_reaction_period);
335                 quicktime_set_parameter(fd, "divx_max_key_interval", &asset->divx_max_key_interval);
336                 quicktime_set_parameter(fd, "divx_max_quantizer", &asset->divx_max_quantizer);
337                 quicktime_set_parameter(fd, "divx_min_quantizer", &asset->divx_min_quantizer);
338                 quicktime_set_parameter(fd, "divx_quantizer", &asset->divx_quantizer);
339                 quicktime_set_parameter(fd, "divx_quality", &asset->divx_quality);
340                 quicktime_set_parameter(fd, "divx_fix_bitrate", &asset->divx_fix_bitrate);
342                 quicktime_set_parameter(fd, "div3_bitrate", &asset->ms_bitrate);
343                 quicktime_set_parameter(fd, "div3_bitrate_tolerance", &asset->ms_bitrate_tolerance);
344                 quicktime_set_parameter(fd, "div3_interlaced", &asset->ms_interlaced);
345                 quicktime_set_parameter(fd, "div3_quantizer", &asset->ms_quantization);
346                 quicktime_set_parameter(fd, "div3_gop_size", &asset->ms_gop_size);
347                 quicktime_set_parameter(fd, "div3_fix_bitrate", &asset->ms_fix_bitrate);
349 //printf("FileMOV::asset_to_format 3.3\n");
350         }
351 //printf("FileMOV::asset_to_format 3.4\n");
353 //printf("FileMOV::asset_to_format 4 %d %d\n", wr, 
354 //                              asset->format);
356         if(wr && asset->format == FILE_AVI)
357         {
358                 quicktime_set_avi(fd, 1);
359         }
363 void FileMOV::format_to_asset()
365         if(!fd) return;
367         if(quicktime_is_avi(fd)) asset->format = FILE_AVI;
368         asset->audio_data = quicktime_has_audio(fd);
369         if(asset->audio_data)
370         {
371                 asset->channels = 0;
372                 int qt_tracks = quicktime_audio_tracks(fd);
373                 for(int i = 0; i < qt_tracks; i++)
374                         asset->channels += quicktime_track_channels(fd, i);
375         
376                 if(!asset->sample_rate)
377                         asset->sample_rate = quicktime_sample_rate(fd, 0);
378                 asset->bits = quicktime_audio_bits(fd, 0);
379                 asset->audio_length = quicktime_audio_length(fd, 0);
380                 strncpy(asset->acodec, quicktime_audio_compressor(fd, 0), 4);
381         }
383 // determine if the video can be read before declaring video data
384         if(quicktime_has_video(fd) && quicktime_supported_video(fd, 0))
385                         asset->video_data = 1;
387         if(asset->video_data)
388         {
389                 depth = quicktime_video_depth(fd, 0);
390                 asset->layers = quicktime_video_tracks(fd);
391                 asset->width = quicktime_video_width(fd, 0);
392                 asset->height = quicktime_video_height(fd, 0);
393                 asset->video_length = quicktime_video_length(fd, 0);
394 // Don't want a user configured frame rate to get destroyed
395                 if(!asset->frame_rate)
396                         asset->frame_rate = quicktime_frame_rate(fd, 0);
397                 if(!asset->interlace_mode)
398                         asset->interlace_mode = quicktime_video_interlacemode(fd, 0);
400                 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
401         }
404 int FileMOV::colormodel_supported(int colormodel)
406         return colormodel;
409 int FileMOV::get_best_colormodel(Asset *asset, int driver)
411         switch(driver)
412         {
413                 case PLAYBACK_X11:
414                         return BC_RGB888;
415                         break;
416                 case PLAYBACK_X11_XV:
417                         if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
418                         if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422P;
419                         if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
420                         if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
421                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
422                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
423                         if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
424                         if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
425                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
426                         if(match4(asset->vcodec, QUICKTIME_MP4V)) return BC_YUV420P;
427                         if(match4(asset->vcodec, QUICKTIME_H263)) return BC_YUV420P;
428                         if(match4(asset->vcodec, QUICKTIME_DIV3)) return BC_YUV420P;
429                         break;
430                 case PLAYBACK_DV1394:
431                 case PLAYBACK_FIREWIRE:
432                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_COMPRESSED;
433                         return BC_YUV422P;
434                         break;
435                 case PLAYBACK_LML:
436                 case PLAYBACK_BUZ:
437                         if(match4(asset->vcodec, QUICKTIME_MJPA)) 
438                                 return BC_COMPRESSED;
439                         else
440                                 return BC_YUV422P;
441                         break;
442                 case VIDEO4LINUX:
443                 case VIDEO4LINUX2:
444                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
445                         else
446                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
447                         else
448                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
449                         else
450                         if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
451                         else
452                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
453                         else
454                         if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
455                         else
456                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
457                         else
458                         if(!strncasecmp(asset->vcodec, QUICKTIME_H263, 4)) return BC_YUV420P;
459                         else
460                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
461                         break;
462                 case CAPTURE_BUZ:
463                 case CAPTURE_LML:
464                 case VIDEO4LINUX2JPEG:
465                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) 
466                                 return BC_COMPRESSED;
467                         else
468                                 return BC_YUV422;
469                         break;
470                 case CAPTURE_FIREWIRE:
471                         if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4)) 
472                                 return BC_COMPRESSED;
473                         else
474                                 return BC_YUV422;
475                         break;
476         }
477         return BC_RGB888;
480 int FileMOV::can_copy_from(Edit *edit, int64_t position)
482         if(!fd) return 0;
484 //printf("FileMOV::can_copy_from 1 %d %s %s\n", edit->asset->format, edit->asset->vcodec, this->asset->vcodec);
485         if(edit->asset->format == FILE_JPEG_LIST && 
486                 match4(this->asset->vcodec, QUICKTIME_JPEG))
487                 return 1;
488         else
489         if((edit->asset->format == FILE_MOV || 
490                 edit->asset->format == FILE_AVI))
491         {
492                 if(match4(edit->asset->vcodec, this->asset->vcodec))
493                         return 1;
494 // there are combinations where the same codec has multiple fourcc codes
495 // check for DV...
496                 int is_edit_dv = 0;
497                 int is_this_dv = 0;
498                 if (match4(edit->asset->vcodec, QUICKTIME_DV) || match4(edit->asset->vcodec, QUICKTIME_DVSD))
499                         is_edit_dv = 1;
500                 if (match4(this->asset->vcodec, QUICKTIME_DV) || match4(this->asset->vcodec, QUICKTIME_DVSD))
501                         is_this_dv = 1;
502                 if (is_this_dv && is_edit_dv)
503                         return 1;
504         }
505         else
506         if(edit->asset->format == FILE_RAWDV)
507         {
508                 if(match4(this->asset->vcodec, QUICKTIME_DV) || match4(this->asset->vcodec, QUICKTIME_DVSD))
509                         return 1;
510         }
513         return 0;
517 int64_t FileMOV::get_audio_length()
519         if(!fd) return 0;
520         int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
522         return result;
525 int FileMOV::set_audio_position(int64_t x)
527         if(!fd) return 1;
528 // quicktime sets positions for each track seperately so store position in audio_position
529         if(x >= 0 && x < asset->audio_length)
530                 return quicktime_set_audio_position(fd, x, 0);
531         else
532                 return 1;
535 int FileMOV::set_video_position(int64_t x)
537         if(!fd) return 1;
538         if(x >= 0 && x < asset->video_length)
539                 return quicktime_set_video_position(fd, x, file->current_layer);
540         else
541                 return 1;
545 void FileMOV::new_audio_temp(int64_t len)
547         if(temp_allocated && temp_allocated < len)
548         {
549                 for(int i = 0; i < asset->channels; i++)
550                         delete [] temp_float[i];
551                 delete [] temp_float;
552                 temp_allocated = 0;
553         }
555         if(!temp_allocated)
556         {
557                 temp_allocated = len;
558                 temp_float = new float*[asset->channels];
559                 for(int i = 0; i < asset->channels; i++)
560                         temp_float[i] = new float[len];
561         }
566 int FileMOV::write_samples(double **buffer, int64_t len)
568         int i, j;
569         int64_t bytes;
570         int result = 0, track_channels = 0;
571         int chunk_size;
573         if(!fd) return 0;
575         if(quicktime_supported_audio(fd, 0))
576         {
577 // Use Quicktime's compressor. (Always used)
578 // Allocate temp buffer
579                 new_audio_temp(len);
581 // Copy to float buffer
582                 for(i = 0; i < asset->channels; i++)
583                 {
584                         for(j = 0; j < len; j++)
585                         {
586                                 temp_float[i][j] = buffer[i][j];
587                         }
588                 }
590 // Because of the way Quicktime's compressors work we want to limit the chunk
591 // size to speed up decompression.
592                 float **channel_ptr;
593                 channel_ptr = new float*[asset->channels];
595                 for(j = 0; j < len && !result; )
596                 {
597                         chunk_size = asset->sample_rate;
598                         if(j + chunk_size > len) chunk_size = len - j;
600                         for(i = 0; i < asset->channels; i++)
601                         {
602                                 channel_ptr[i] = &temp_float[i][j];
603                         }
605                         result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
606                         j += asset->sample_rate;
607                 }
609                 delete [] channel_ptr;
610         }
611         return result;
614 int FileMOV::write_frames(VFrame ***frames, int len)
616 //printf("FileMOV::write_frames 1\n");
617         int i, j, k, result = 0;
618         int default_compressor = 1;
619         if(!fd) return 0;
621         for(i = 0; i < asset->layers && !result; i++)
622         {
628 // Fix direct copy cases for format conversions.
629                 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
630                 {
631                         default_compressor = 0;
632                         for(j = 0; j < len && !result; j++)
633                         {
634                                 VFrame *frame = frames[i][j];
638 // Special handling for DIVX
639 // Determine keyframe status.
640 // Write VOL header in the first frame if none exists
641                                 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
642                                         !strcmp(asset->vcodec, QUICKTIME_H263) ||
643                                         !strcmp(asset->vcodec, QUICKTIME_HV60))
644                                 {
645                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
646                                                 frame->get_compressed_size(),
647                                                 asset->vcodec))
648                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
652                                         if(!(file->current_frame + j) && 
653                                                 !quicktime_mpeg4_has_vol(frame->get_data()))
654                                         {
655                                                 VFrame *temp_frame = new VFrame;
657                                                 temp_frame->allocate_compressed_data(frame->get_compressed_size() + 
658                                                         0xff);
659                                                 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
660                                                         asset->width, 
661                                                         asset->height, 
662                                                         60000, 
663                                                         asset->frame_rate);
664                                                 memcpy(temp_frame->get_data() + bytes, 
665                                                         frame->get_data(), 
666                                                         frame->get_compressed_size());
667                                                 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
669                                                 result = quicktime_write_frame(fd,
670                                                         temp_frame->get_data(),
671                                                         temp_frame->get_compressed_size(),
672                                                         i);
674                                                 delete temp_frame;
677                                         }
678                                         else
679                                         {
680                                                 result = quicktime_write_frame(fd,
681                                                         frame->get_data(),
682                                                         frame->get_compressed_size(),
683                                                         i);
684                                         }
685                                 }
686                                 else
687                                 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
688                                 {
689                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
690                                                 frame->get_compressed_size(),
691                                                 asset->vcodec))
692                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
693                                         result = quicktime_write_frame(fd,
694                                                 frame->get_data(),
695                                                 frame->get_compressed_size(),
696                                                 i);
697                                 }
698                                 else
699                                 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
700                                 {
701                                         long field2_offset;
703 // Create extra space for markers
704                                         if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
705                                                 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
707                                         unsigned char *data = frame->get_data();
708                                         long data_size = frame->get_compressed_size();
709                                         long data_allocated = frame->get_compressed_allocated();
711 // Sometimes get 0 length frames
712                                         if(data_size)
713                                         {
714                                                 if(asset->format == FILE_MOV)
715                                                 {
716                                                         mjpeg_insert_quicktime_markers(&data,
717                                                                 &data_size,
718                                                                 &data_allocated,
719                                                                 2,
720                                                                 &field2_offset);
721                                                 }
722                                                 else
723                                                 {
724                                                         mjpeg_insert_avi_markers(&data,
725                                                                 &data_size,
726                                                                 &data_allocated,
727                                                                 2,
728                                                                 &field2_offset);
729                                                 }
730                                                 frame->set_compressed_size(data_size);
731                                                 result = quicktime_write_frame(fd,
732                                                         frame->get_data(),
733                                                         frame->get_compressed_size(),
734                                                         i);
735                                         }
736                                         else
737                                                 printf("FileMOV::write_frames data_size=%d\n", data_size);
738                                 }
739                                 else
740                                         result = quicktime_write_frame(fd,
741                                                 frame->get_data(),
742                                                 frame->get_compressed_size(),
743                                                 i);
744                                 
745                                 
746                         }
747                 }
748                 else
749                 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
750                         match4(asset->vcodec, QUICKTIME_YUV422) ||
751                         match4(asset->vcodec, QUICKTIME_RAW))
752                 {
753 // Direct copy planes where possible
754                         default_compressor = 0;
755                         for(j = 0; j < len && !result; j++)
756                         {
757                                 VFrame *frame = frames[i][j];
758 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
759                                 quicktime_set_cmodel(fd, frame->get_color_model());
760                                 if(cmodel_is_planar(frame->get_color_model()))
761                                 {
762                                         unsigned char *planes[3];
763                                         planes[0] = frame->get_y();
764                                         planes[1] = frame->get_u();
765                                         planes[2] = frame->get_v();
766                                         result = quicktime_encode_video(fd, planes, i);
767                                 }
768                                 else
769                                 {
770                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
771 //printf("FileMOV::write_frames 2 %d\n", result);
772                                 }
773 //printf("FileMOV::write_frames 2\n");
774                         }
775                 }
776                 else
777                 if(file->cpus > 1 && 
778                         (match4(asset->vcodec, QUICKTIME_JPEG) || 
779                         match4(asset->vcodec, QUICKTIME_MJPA)))
780                 {
781                         default_compressor = 0;
782 // Compress symmetrically on an SMP system.
783                         ThreadStruct *threadframe;
784                         int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
786 // Set up threads for symmetric compression.
787                         if(!threads)
788                         {
789                                 threads = new FileMOVThread*[file->cpus];
790                                 for(j = 0; j < file->cpus; j++)
791                                 {
792                                         threads[j] = new FileMOVThread(this, fields);
793                                         threads[j]->start_encoding();
794                                 }
795                         }
797 // Set up the frame structures for asynchronous compression.
798 // The mjpeg object must exist in each threadframe because it is where the output
799 // is stored.
800                         while(threadframes.total < len)
801                         {
802                                 threadframes.append(threadframe = new ThreadStruct);
803                         }
805 // Load thread frame structures with new frames.
806                         for(j = 0; j < len; j++)
807                         {
808                                 VFrame *frame = frames[i][j];
809                                 threadframes.values[j]->input = frame;
810                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
811                         }
812                         total_threadframes = len;
813                         current_threadframe = 0;
815 // Start the threads compressing
816                         for(j = 0; j < file->cpus; j++)
817                         {
818                                 threads[j]->encode_buffer();
819                         }
822 // Write the frames as they're finished
823                         for(j = 0; j < len; j++)
824                         {
825                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
826                                 threadframes.values[j]->completion_lock->unlock();
827                                 if(!result)
828                                 {
829                                         result = quicktime_write_frame(fd, 
830                                                 threadframes.values[j]->output,
831                                                 threadframes.values[j]->output_size,
832                                                 i);
833                                 }
834                         }
835                 }
837                 if(default_compressor)
838                 {
839 //printf("FileMOV::write_frames 3\n");
840 // Use the library's built in compressor.
841                         for(j = 0; j < len && !result; j++)
842                         {
843 //printf("FileMOV::write_frames 4\n");
844                                 VFrame *frame = frames[i][j];
845                                 quicktime_set_cmodel(fd, frame->get_color_model());
846 //printf("FileMOV::write_frames 5\n");
847                                 if(cmodel_is_planar(frame->get_color_model()))
848                                 {
849                                         unsigned char *planes[3];
850                                         planes[0] = frame->get_y();
851                                         planes[1] = frame->get_u();
852                                         planes[2] = frame->get_v();
853                                         result = quicktime_encode_video(fd, planes, i);
854                                 }
855                                 else
856                                 {
857                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
858                                 }
859                         }
860                 }
861 //printf("FileMOV::write_frames 4\n");
862         }
865 //printf("FileMOV::write_frames 100\n");
866         return result;
871 int FileMOV::read_frame(VFrame *frame)
873         if(!fd) return 1;
874         int result = 0;
876         switch(frame->get_color_model())
877         {
878                 case BC_COMPRESSED:
879                         frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
880                         frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
881                         result = quicktime_read_frame(fd, 
882                                 frame->get_data(), 
883                                 file->current_layer);
884                         break;
886 // Progressive
887                 case BC_YUV420P:
888                 case BC_YUV422P:
889                 {
890                         unsigned char *row_pointers[3];
891                         row_pointers[0] = frame->get_y();
892                         row_pointers[1] = frame->get_u();
893                         row_pointers[2] = frame->get_v();
895                         quicktime_set_cmodel(fd, frame->get_color_model());
896                         quicktime_decode_video(fd, 
897                                 row_pointers,
898                                 file->current_layer);
899                 }
900                         break;
902 // Packed
903                 default:
904                         quicktime_set_cmodel(fd, frame->get_color_model());
905                         result = quicktime_decode_video(fd, 
906                                 frame->get_rows(),
907                                 file->current_layer);
908 //for(int i = 0; i < 10000; i++) frame->get_rows()[0][i] = 0xff;
909                         break;
910         }
914         return result;
919 int64_t FileMOV::compressed_frame_size()
921         if(!fd) return 0;
922         return quicktime_frame_size(fd, file->current_frame, file->current_layer);
925 int FileMOV::read_compressed_frame(VFrame *buffer)
927         int64_t result;
928         if(!fd) return 0;
930 //printf("FileMOV::read_compressed_frame 1\n");
931         result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
932         buffer->set_compressed_size(result);
933 //printf("FileMOV::read_compressed_frame 100\n");
934         result = !result;
935         return result;
938 int FileMOV::write_compressed_frame(VFrame *buffer)
940         int result = 0;
941         if(!fd) return 0;
943 TRACE("FileMOV::write_compressed_frame 1");
944         result = quicktime_write_frame(fd, 
945                 buffer->get_data(), 
946                 buffer->get_compressed_size(), 
947                 file->current_layer);
948 TRACE("FileMOV::write_compressed_frame 100");
949         return result;
954 int FileMOV::read_raw(VFrame *frame, 
955                 float in_x1, float in_y1, float in_x2, float in_y2,
956                 float out_x1, float out_y1, float out_x2, float out_y2, 
957                 int use_float, int interpolate)
959         int64_t i, color_channels, result = 0;
960         if(!fd) return 0;
962 //printf("FileMOV::read_raw 1\n");
963         quicktime_set_video_position(fd, file->current_frame, file->current_layer);
964 // Develop importing strategy
965         switch(frame->get_color_model())
966         {
967                 case BC_RGB888:
968                         result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
969                         break;
970                 case BC_RGBA8888:
971                         break;
972                 case BC_RGB161616:
973                         break;
974                 case BC_RGBA16161616:
975                         break;
976                 case BC_YUV888:
977                         break;
978                 case BC_YUVA8888:
979                         break;
980                 case BC_YUV161616:
981                         break;
982                 case BC_YUVA16161616:
983                         break;
984                 case BC_YUV420P:
985                         break;
986         }
987         return result;
990 // Overlay samples
991 int FileMOV::read_samples(double *buffer, int64_t len)
993         int qt_track, qt_channel;
995         if(!fd) return 0;
997 //printf("FileMOV::read_samples 1\n");
998         if(quicktime_track_channels(fd, 0) > file->current_channel &&
999                 quicktime_supported_audio(fd, 0))
1000         {
1002 //printf("FileMOV::read_samples 2 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1003                 new_audio_temp(len);
1005 //printf("FileMOV::read_samples 3 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1006                 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
1007                 {
1008                         printf("FileMOV::read_samples: quicktime_decode_audio failed\n");
1009                         return 1;
1010                 }
1011                 else
1012                 {
1013                         for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
1014                 }
1016 // if(file->current_channel == 0)
1017 // for(int i = 0; i < len; i++)
1018 // {
1019 //      int16_t value;
1020 //      value = (int16_t)(temp_float[0][i] * 32767);
1021 //      fwrite(&value, 2, 1, stdout);
1022 // }
1023 //printf("FileMOV::read_samples 4 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1024         }
1026 //printf("FileMOV::read_samples 100\n");
1027         return 0;
1031 char* FileMOV::strtocompression(char *string)
1033         if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
1034         if(!strcasecmp(string, _(MP4V_NAME))) return QUICKTIME_MP4V;
1035         if(!strcasecmp(string, _(H263_NAME))) return QUICKTIME_H263;
1036         if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
1037         if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
1038         if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
1039         if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
1040         if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
1041         if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
1042         if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
1043         if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
1044         if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
1045         if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
1046         if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
1047         if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
1048         if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
1049         if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
1050         if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
1052         if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
1053         if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
1054         if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
1055         if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
1056         if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
1057         if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
1061         return QUICKTIME_RAW;
1064 char* FileMOV::compressiontostr(char *string)
1066         if(match4(string, QUICKTIME_H263)) return _(H263_NAME);
1067         if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1068         if(match4(string, QUICKTIME_MP4V)) return _(MP4V_NAME);
1069         if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1070         if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1071         if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1072         if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1073         if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1074         if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1075         if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1076         if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1077         if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1078         if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1079         if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1080         if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1081         if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1082         if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1088         if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1089         if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1090         if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1091         if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1092         if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1093         if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1097         return _("Unknown");
1104 ThreadStruct::ThreadStruct()
1106         input = 0;
1107         output = 0;
1108         output_allocated = 0;
1109         output_size = 0;
1110         completion_lock = new Condition(1, "ThreadStruct::completion_lock");
1113 ThreadStruct::~ThreadStruct()
1115         if(output) delete [] output;
1116         delete completion_lock;
1119 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1121         if(output_allocated < mjpeg_output_size(mjpeg))
1122         {
1123                 delete [] output;
1124                 output = 0;
1125         }
1126         if(!output)
1127         {
1128                 output_allocated = mjpeg_output_size(mjpeg);
1129                 output = new unsigned char[output_allocated];
1130         }
1131         
1132         output_size = mjpeg_output_size(mjpeg);
1133         memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1137 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields) : Thread()
1139         this->filemov = filemov;
1140         this->fields = fields;
1141         mjpeg = 0;
1142         input_lock = new Condition(1, "FileMOVThread::input_lock");
1145 FileMOVThread::~FileMOVThread()
1147         delete input_lock;
1150 int FileMOVThread::start_encoding()
1152         mjpeg = mjpeg_new(filemov->asset->width, 
1153                 filemov->asset->height, 
1154                 fields);
1155         mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1156         mjpeg_set_float(mjpeg, 0);
1157         done = 0;
1158         set_synchronous(1);
1159         input_lock->lock("FileMOVThread::start_encoding");
1160         start();
1163 int FileMOVThread::stop_encoding()
1165         done = 1;
1166         input_lock->unlock();
1167         join();
1168         if(mjpeg) mjpeg_delete(mjpeg);
1171 int FileMOVThread::encode_buffer()
1173         input_lock->unlock();
1176 void FileMOVThread::run()
1178         while(!done)
1179         {
1180                 input_lock->lock("FileMOVThread::run");
1182                 if(!done)
1183                 {
1184 // Get a frame to compress.
1185                         filemov->threadframe_lock->lock("FileMOVThread::stop_encoding");
1186                         if(filemov->current_threadframe < filemov->total_threadframes)
1187                         {
1188 // Frame is available to process.
1189                                 input_lock->unlock();
1190                                 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1191                                 VFrame *frame = threadframe->input;
1193                                 filemov->current_threadframe++;
1194                                 filemov->threadframe_lock->unlock();
1196                                 mjpeg_compress(mjpeg, 
1197                                         frame->get_rows(), 
1198                                         frame->get_y(), 
1199                                         frame->get_u(), 
1200                                         frame->get_v(),
1201                                         frame->get_color_model(),
1202                                         1);
1204                                 if(fields > 1)
1205                                 {
1206                                         unsigned char *data = mjpeg_output_buffer(mjpeg);
1207                                         long data_size = mjpeg_output_size(mjpeg);
1208                                         long data_allocated = mjpeg_output_allocated(mjpeg);
1209                                         long field2_offset;
1211                                         if(filemov->asset->format == FILE_MOV)
1212                                         {
1213                                                 mjpeg_insert_quicktime_markers(&data,
1214                                                         &data_size,
1215                                                         &data_allocated,
1216                                                         2,
1217                                                         &field2_offset);
1218                                         }
1219                                         else
1220                                         {
1221                                                 mjpeg_insert_avi_markers(&data,
1222                                                         &data_size,
1223                                                         &data_allocated,
1224                                                         2,
1225                                                         &field2_offset);
1226                                         }
1227                                         mjpeg_set_output_size(mjpeg, data_size);
1228                                 }
1229                                 threadframe->load_output(mjpeg);
1230                                 threadframe->completion_lock->unlock();
1231                         }
1232                         else
1233                                 filemov->threadframe_lock->unlock();
1234                 }
1235         }
1243 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1244  : BC_Window(PROGRAM_NAME ": Audio Compression",
1245         parent_window->get_abs_cursor_x(1),
1246         parent_window->get_abs_cursor_y(1),
1247         350,
1248         250)
1250         this->parent_window = parent_window;
1251         this->asset = asset;
1252         bits_popup = 0;
1253         bits_title = 0;
1254         dither = 0;
1255         vorbis_min_bitrate = 0;
1256         vorbis_bitrate = 0;
1257         vorbis_max_bitrate = 0;
1258         vorbis_vbr = 0;
1259         compression_popup = 0;
1260         mp3_bitrate = 0;
1263 MOVConfigAudio::~MOVConfigAudio()
1265         if(compression_popup) delete compression_popup;
1266         if(bits_popup) delete bits_popup;
1267         compression_items.remove_all_objects();
1270 int MOVConfigAudio::create_objects()
1272         int x = 10, y = 10;
1274         
1276         if(asset->format == FILE_MOV)
1277         {
1278                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1279                 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1280                 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1281 //              compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1282                 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1283                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1284         }
1285         else
1286         {
1287                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1288                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1289                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1290         }
1292         add_tool(new BC_Title(x, y, _("Compression:")));
1293         y += 25;
1294         compression_popup = new MOVConfigAudioPopup(this, x, y);
1295         compression_popup->create_objects();
1297         update_parameters();
1299         add_subwindow(new BC_OKButton(this));
1300         return 0;
1303 void MOVConfigAudio::update_parameters()
1305         int x = 10, y = 70;
1306         if(bits_title) delete bits_title;
1307         if(bits_popup) delete bits_popup;
1308         if(dither) delete dither;
1309         if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1310         if(vorbis_bitrate) delete vorbis_bitrate;
1311         if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1312         if(vorbis_vbr) delete vorbis_vbr;
1313         if(mp3_bitrate) delete mp3_bitrate;
1315         bits_popup = 0;
1316         bits_title = 0;
1317         dither = 0;
1318         vorbis_min_bitrate = 0;
1319         vorbis_bitrate = 0;
1320         vorbis_max_bitrate = 0;
1321         vorbis_vbr = 0;
1325         mp3_bitrate = 0;
1329         if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1330                 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1331         {
1332                 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1333                 bits_popup = new BitsPopup(this, 
1334                         x + 150, 
1335                         y, 
1336                         &asset->bits, 
1337                         0, 
1338                         0, 
1339                         0, 
1340                         0, 
1341                         0);
1342                 bits_popup->create_objects();
1343                 y += 40;
1344                 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1345         }
1346         else
1347         if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1348         {
1349         }
1350         else
1351         if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1352         {
1353                 mp3_bitrate = new MOVConfigAudioNum(this, 
1354                         _("Bitrate:"), 
1355                         x, 
1356                         y, 
1357                         &asset->mp3_bitrate);
1358                 mp3_bitrate->set_increment(1000);
1359                 mp3_bitrate->create_objects();
1360         }
1361         else
1362         if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1363         {
1364         }
1365         else
1366         if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1367         {
1368                 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1369                         _("Variable bitrate"),
1370                         x,
1371                         y,
1372                         &asset->vorbis_vbr));
1373                 y += 35;
1374                 vorbis_min_bitrate = new MOVConfigAudioNum(this, 
1375                         _("Min bitrate:"), 
1376                         x, 
1377                         y, 
1378                         &asset->vorbis_min_bitrate);
1379                 vorbis_min_bitrate->set_increment(1000);
1380                 y += 30;
1381                 vorbis_bitrate = new MOVConfigAudioNum(this, 
1382                         _("Avg bitrate:"), 
1383                         x, 
1384                         y, 
1385                         &asset->vorbis_bitrate);
1386                 vorbis_bitrate->set_increment(1000);
1387                 y += 30;
1388                 vorbis_max_bitrate = new MOVConfigAudioNum(this, 
1389                         _("Max bitrate:"), 
1390                         x, 
1391                         y, 
1392                         &asset->vorbis_max_bitrate);
1393                 vorbis_max_bitrate->set_increment(1000);
1397                 vorbis_min_bitrate->create_objects();
1398                 vorbis_bitrate->create_objects();
1399                 vorbis_max_bitrate->create_objects();
1400         }
1403 int MOVConfigAudio::close_event()
1405         set_done(0);
1406         return 1;
1413 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1414         char *title_text,
1415         int x,
1416         int y,
1417         int *output)
1418  : BC_CheckBox(x, y, *output, title_text)
1420         this->popup = popup;
1421         this->output = output;
1423 int MOVConfigAudioToggle::handle_event()
1425         *output = get_value();
1426         return 1;
1433 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1434  : BC_TumbleTextBox(popup, 
1435                 (int64_t)*output,
1436                 (int64_t)-1,
1437                 (int64_t)25000000,
1438                 x + 150, 
1439                 y, 
1440                 100)
1442         this->popup = popup;
1443         this->title_text = title_text;
1444         this->output = output;
1445         this->x = x;
1446         this->y = y;
1449 MOVConfigAudioNum::~MOVConfigAudioNum()
1451         if(!popup->get_deleting()) delete title;
1454 void MOVConfigAudioNum::create_objects()
1456         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1457         BC_TumbleTextBox::create_objects();
1460 int MOVConfigAudioNum::handle_event()
1462         *output = atol(get_text());
1463         return 1;
1473 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1474  : BC_PopupTextBox(popup, 
1475                 &popup->compression_items,
1476                 FileMOV::compressiontostr(popup->asset->acodec),
1477                 x, 
1478                 y, 
1479                 300,
1480                 300)
1482         this->popup = popup;
1485 int MOVConfigAudioPopup::handle_event()
1487         strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1488         popup->update_parameters();
1489         return 1;
1508 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window, 
1509         Asset *asset, 
1510         int lock_compressor)
1511  : BC_Window(PROGRAM_NAME ": Video Compression",
1512         parent_window->get_abs_cursor_x(1),
1513         parent_window->get_abs_cursor_y(1),
1514         420,
1515         420)
1517         this->parent_window = parent_window;
1518         this->asset = asset;
1519         this->lock_compressor = lock_compressor;
1520         compression_popup = 0;
1521         reset();
1524 MOVConfigVideo::~MOVConfigVideo()
1526         if(compression_popup) delete compression_popup;
1527         compression_items.remove_all_objects();
1530 int MOVConfigVideo::create_objects()
1532         int x = 10, y = 10;
1534         if(asset->format == FILE_MOV)
1535         {
1536                 compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1537 //              compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1538                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1539                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1540                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1541                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1542                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1543                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1544                 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1545                 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1546                 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1547                 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1548                 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1549                 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1550                 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1551                 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1552         }
1553         else
1554         {
1555                 compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1556                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1557                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1558                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1559                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1560                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1561                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1562         }
1564         add_subwindow(new BC_Title(x, y, _("Compression:")));
1565         y += 25;
1567         if(!lock_compressor)
1568         {
1569                 compression_popup = new MOVConfigVideoPopup(this, x, y);
1570                 compression_popup->create_objects();
1571         }
1572         else
1573         {
1574                 add_subwindow(new BC_Title(x, 
1575                         y, 
1576                         FileMOV::compressiontostr(asset->vcodec),
1577                         MEDIUMFONT,
1578                         RED,
1579                         0));
1580         }
1581         y += 40;
1583         param_x = x;
1584         param_y = y;
1585         update_parameters();
1587         add_subwindow(new BC_OKButton(this));
1588         return 0;
1591 int MOVConfigVideo::close_event()
1593         set_done(0);
1594         return 1;
1598 void MOVConfigVideo::reset()
1600         jpeg_quality = 0;
1601         jpeg_quality_title = 0;
1603         divx_bitrate = 0;
1604         divx_rc_period = 0;
1605         divx_rc_reaction_ratio = 0;
1606         divx_rc_reaction_period = 0;
1607         divx_max_key_interval = 0;
1608         divx_max_quantizer = 0;
1609         divx_min_quantizer = 0;
1610         divx_quantizer = 0;
1611         divx_quality = 0;
1612         divx_fix_bitrate = 0;
1613         divx_fix_quant = 0;
1615         ms_bitrate = 0;
1616         ms_bitrate_tolerance = 0;
1617         ms_quantization = 0;
1618         ms_interlaced = 0;
1619         ms_gop_size = 0;
1620         ms_fix_bitrate = 0;
1621         ms_fix_quant = 0;
1624 void MOVConfigVideo::update_parameters()
1626         if(jpeg_quality)
1627         {
1628                 delete jpeg_quality_title;
1629                 delete jpeg_quality;
1630         }
1632         if(divx_bitrate) delete divx_bitrate;
1633         if(divx_rc_period) delete divx_rc_period;
1634         if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1635         if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1636         if(divx_max_key_interval) delete divx_max_key_interval;
1637         if(divx_max_quantizer) delete divx_max_quantizer;
1638         if(divx_min_quantizer) delete divx_min_quantizer;
1639         if(divx_quantizer) delete divx_quantizer;
1640         if(divx_quality) delete divx_quality;
1641         if(divx_fix_quant) delete divx_fix_quant;
1642         if(divx_fix_bitrate) delete divx_fix_bitrate;
1644         if(ms_bitrate) delete ms_bitrate;
1645         if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1646         if(ms_interlaced) delete ms_interlaced;
1647         if(ms_quantization) delete ms_quantization;
1648         if(ms_gop_size) delete ms_gop_size;
1649         if(ms_fix_bitrate) delete ms_fix_bitrate;
1650         if(ms_fix_quant) delete ms_fix_quant;
1652         reset();
1654 // ffmpeg parameters
1655         if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
1656         {
1657                 int x = param_x, y = param_y;
1658                 ms_bitrate = new MOVConfigVideoNum(this, 
1659                         _("Bitrate:"), 
1660                         x, 
1661                         y, 
1662                         &asset->ms_bitrate);
1663                 ms_bitrate->set_increment(1000000);
1664                 ms_bitrate->create_objects();
1665                 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260, 
1666                                 y,
1667                                 &asset->ms_fix_bitrate,
1668                                 1));
1669                 y += 30;
1671                 ms_bitrate_tolerance = new MOVConfigVideoNum(this, 
1672                         _("Bitrate tolerance:"), 
1673                         x, 
1674                         y, 
1675                         &asset->ms_bitrate_tolerance);
1676                 ms_bitrate_tolerance->create_objects();
1677                 y += 30;
1678                 ms_quantization = new MOVConfigVideoNum(this, 
1679                         _("Quantization:"), 
1680                         x, 
1681                         y, 
1682                         &asset->ms_quantization);
1683                 ms_quantization->create_objects();
1684                 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260, 
1685                                 y,
1686                                 &asset->ms_fix_bitrate,
1687                                 0));
1688                 ms_fix_bitrate->opposite = ms_fix_quant;
1689                 ms_fix_quant->opposite = ms_fix_bitrate;
1692                 y += 30;
1693                 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"), 
1694                         x, 
1695                         y, 
1696                         &asset->ms_interlaced));
1697                 y += 30;
1698                 ms_gop_size = new MOVConfigVideoNum(this, 
1699                         _("Keyframe interval:"), 
1700                         x, 
1701                         y, 
1702                         &asset->ms_gop_size);
1703                 ms_gop_size->create_objects();
1704         }
1705         else
1706 // OpenDivx parameters
1707         if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
1708                 !strcmp(asset->vcodec, QUICKTIME_H263) ||
1709                 !strcmp(asset->vcodec, QUICKTIME_HV60))
1710         {
1711                 int x = param_x, y = param_y;
1712                 divx_bitrate = new MOVConfigVideoNum(this, 
1713                         _("Bitrate:"), 
1714                         x, 
1715                         y, 
1716                         &asset->divx_bitrate);
1717                 divx_bitrate->set_increment(1000000);
1718                 divx_bitrate->create_objects();
1719                 add_subwindow(divx_fix_bitrate = 
1720                         new MOVConfigVideoFixBitrate(x + 260, 
1721                                 y,
1722                                 &asset->divx_fix_bitrate,
1723                                 1));
1724                 y += 30;
1725                 divx_quantizer = new MOVConfigVideoNum(this, 
1726                         _("Quantizer:"), 
1727                         x, 
1728                         y, 
1729                         &asset->divx_quantizer);
1730                 divx_quantizer->create_objects();
1731                 add_subwindow(divx_fix_quant =
1732                         new MOVConfigVideoFixQuant(x + 260, 
1733                                 y,
1734                                 &asset->divx_fix_bitrate,
1735                                 0));
1736                 divx_fix_quant->opposite = divx_fix_bitrate;
1737                 divx_fix_bitrate->opposite = divx_fix_quant;
1738                 y += 30;
1739                 divx_rc_period = new MOVConfigVideoNum(this, 
1740                         _("RC Period:"), 
1741                         x, 
1742                         y, 
1743                         &asset->divx_rc_period);
1744                 divx_rc_period->create_objects();
1745                 y += 30;
1746                 divx_rc_reaction_ratio = new MOVConfigVideoNum(this, 
1747                         _("Reaction Ratio:"), 
1748                         x, 
1749                         y, 
1750                         &asset->divx_rc_reaction_ratio);
1751                 divx_rc_reaction_ratio->create_objects();
1752                 y += 30;
1753                 divx_rc_reaction_period = new MOVConfigVideoNum(this, 
1754                         _("Reaction Period:"), 
1755                         x, 
1756                         y, 
1757                         &asset->divx_rc_reaction_period);
1758                 divx_rc_reaction_period->create_objects();
1759                 y += 30;
1760                 divx_max_key_interval = new MOVConfigVideoNum(this, 
1761                         _("Max Key Interval:"), 
1762                         x, 
1763                         y, 
1764                         &asset->divx_max_key_interval);
1765                 divx_max_key_interval->create_objects();
1766                 y += 30;
1767                 divx_max_quantizer = new MOVConfigVideoNum(this, 
1768                         _("Max Quantizer:"), 
1769                         x, 
1770                         y, 
1771                         &asset->divx_max_quantizer);
1772                 divx_max_quantizer->create_objects();
1773                 y += 30;
1774                 divx_min_quantizer = new MOVConfigVideoNum(this, 
1775                         _("Min Quantizer:"), 
1776                         x, 
1777                         y, 
1778                         &asset->divx_min_quantizer);
1779                 divx_min_quantizer->create_objects();
1780                 y += 30;
1781                 divx_quality = new MOVConfigVideoNum(this, 
1782                         _("Quality:"), 
1783                         x, 
1784                         y, 
1785                         &asset->divx_quality);
1786                 divx_quality->create_objects();
1787         }
1788         else
1789         if(!strcmp(asset->vcodec, QUICKTIME_JPEG) ||
1790                 !strcmp(asset->vcodec, QUICKTIME_MJPA))
1791         {
1792                 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
1793                 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80, 
1794                         param_y,
1795                         0,
1796                         200,
1797                         200,
1798                         0,
1799                         100,
1800                         asset->jpeg_quality,
1801                         0,
1802                         0,
1803                         &asset->jpeg_quality));
1804         }
1811 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
1812  : BC_TumbleTextBox(popup, 
1813                 (int64_t)*output,
1814                 (int64_t)1,
1815                 (int64_t)25000000,
1816                 x + 130, 
1817                 y, 
1818                 100)
1820         this->popup = popup;
1821         this->title_text = title_text;
1822         this->output = output;
1823         this->x = x;
1824         this->y = y;
1827 MOVConfigVideoNum::~MOVConfigVideoNum()
1829         if(!popup->get_deleting()) delete title;
1832 void MOVConfigVideoNum::create_objects()
1834         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1835         BC_TumbleTextBox::create_objects();
1838 int MOVConfigVideoNum::handle_event()
1840         *output = atol(get_text());
1841         return 1;
1850 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
1851  : BC_CheckBox(x, y, *output, title_text)
1853         this->output = output;
1856 int MOVConfigVideoCheckBox::handle_event()
1858         *output = get_value();
1859         return 1;
1867 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x, 
1868         int y,
1869         int *output,
1870         int value)
1871  : BC_Radial(x, 
1872         y, 
1873         *output == value, 
1874         _("Fix bitrate"))
1876         this->output = output;
1877         this->value = value;
1880 int MOVConfigVideoFixBitrate::handle_event()
1882         *output = value;
1883         opposite->update(0);
1884         return 1;
1892 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x, 
1893         int y,
1894         int *output,
1895         int value)
1896  : BC_Radial(x, 
1897         y, 
1898         *output == value, 
1899         _("Fix quantization"))
1901         this->output = output;
1902         this->value = value;
1905 int MOVConfigVideoFixQuant::handle_event()
1907         *output = value;
1908         opposite->update(0);
1909         return 1;
1916 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
1917  : BC_PopupTextBox(popup, 
1918                 &popup->compression_items,
1919                 FileMOV::compressiontostr(popup->asset->vcodec),
1920                 x, 
1921                 y, 
1922                 300,
1923                 300)
1925         this->popup = popup;
1928 int MOVConfigVideoPopup::handle_event()
1930         strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
1931         popup->update_parameters();
1932         return 1;