r553: Modern gccs require __attribute__((used)) for variables used only in assembly.
[cinelerra_cv.git] / cinelerra / filemov.C
blobcb1df69ac34879083093eddf00d410d8b80c47ac
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);
398                 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
399         }
402 int FileMOV::colormodel_supported(int colormodel)
404         return colormodel;
407 int FileMOV::get_best_colormodel(Asset *asset, int driver)
409         switch(driver)
410         {
411                 case PLAYBACK_X11:
412                         return BC_RGB888;
413                         break;
414                 case PLAYBACK_X11_XV:
415                         if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
416                         if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422P;
417                         if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
418                         if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
419                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
420                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
421                         if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
422                         if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
423                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
424                         if(match4(asset->vcodec, QUICKTIME_MP4V)) return BC_YUV420P;
425                         if(match4(asset->vcodec, QUICKTIME_H263)) return BC_YUV420P;
426                         if(match4(asset->vcodec, QUICKTIME_DIV3)) return BC_YUV420P;
427                         break;
428                 case PLAYBACK_DV1394:
429                 case PLAYBACK_FIREWIRE:
430                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_COMPRESSED;
431                         return BC_YUV422P;
432                         break;
433                 case PLAYBACK_LML:
434                 case PLAYBACK_BUZ:
435                         if(match4(asset->vcodec, QUICKTIME_MJPA)) 
436                                 return BC_COMPRESSED;
437                         else
438                                 return BC_YUV422P;
439                         break;
440                 case VIDEO4LINUX:
441                 case VIDEO4LINUX2:
442                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
443                         else
444                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
445                         else
446                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
447                         else
448                         if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
449                         else
450                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
451                         else
452                         if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
453                         else
454                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
455                         else
456                         if(!strncasecmp(asset->vcodec, QUICKTIME_H263, 4)) return BC_YUV420P;
457                         else
458                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
459                         break;
460                 case CAPTURE_BUZ:
461                 case CAPTURE_LML:
462                 case VIDEO4LINUX2JPEG:
463                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) 
464                                 return BC_COMPRESSED;
465                         else
466                                 return BC_YUV422;
467                         break;
468                 case CAPTURE_FIREWIRE:
469                         if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4)) 
470                                 return BC_COMPRESSED;
471                         else
472                                 return BC_YUV422;
473                         break;
474         }
475         return BC_RGB888;
478 int FileMOV::can_copy_from(Edit *edit, int64_t position)
480         if(!fd) return 0;
482 //printf("FileMOV::can_copy_from 1 %d %s %s\n", edit->asset->format, edit->asset->vcodec, this->asset->vcodec);
483         if(edit->asset->format == FILE_JPEG_LIST && 
484                 match4(this->asset->vcodec, QUICKTIME_JPEG))
485                 return 1;
486         else
487         if((edit->asset->format == FILE_MOV || 
488                 edit->asset->format == FILE_AVI))
489         {
490                 if(match4(edit->asset->vcodec, this->asset->vcodec))
491                         return 1;
492 // there are combinations where the same codec has multiple fourcc codes
493 // check for DV...
494                 int is_edit_dv = 0;
495                 int is_this_dv = 0;
496                 if (match4(edit->asset->vcodec, QUICKTIME_DV) || match4(edit->asset->vcodec, QUICKTIME_DVSD))
497                         is_edit_dv = 1;
498                 if (match4(this->asset->vcodec, QUICKTIME_DV) || match4(this->asset->vcodec, QUICKTIME_DVSD))
499                         is_this_dv = 1;
500                 if (is_this_dv && is_edit_dv)
501                         return 1;
502         }
503         else
504         if(edit->asset->format == FILE_RAWDV)
505         {
506                 if(match4(this->asset->vcodec, QUICKTIME_DV) || match4(this->asset->vcodec, QUICKTIME_DVSD))
507                         return 1;
508         }
511         return 0;
515 int64_t FileMOV::get_audio_length()
517         if(!fd) return 0;
518         int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
520         return result;
523 int FileMOV::set_audio_position(int64_t x)
525         if(!fd) return 1;
526 // quicktime sets positions for each track seperately so store position in audio_position
527         if(x >= 0 && x < asset->audio_length)
528                 return quicktime_set_audio_position(fd, x, 0);
529         else
530                 return 1;
533 int FileMOV::set_video_position(int64_t x)
535         if(!fd) return 1;
536         if(x >= 0 && x < asset->video_length)
537                 return quicktime_set_video_position(fd, x, file->current_layer);
538         else
539                 return 1;
543 void FileMOV::new_audio_temp(int64_t len)
545         if(temp_allocated && temp_allocated < len)
546         {
547                 for(int i = 0; i < asset->channels; i++)
548                         delete [] temp_float[i];
549                 delete [] temp_float;
550                 temp_allocated = 0;
551         }
553         if(!temp_allocated)
554         {
555                 temp_allocated = len;
556                 temp_float = new float*[asset->channels];
557                 for(int i = 0; i < asset->channels; i++)
558                         temp_float[i] = new float[len];
559         }
564 int FileMOV::write_samples(double **buffer, int64_t len)
566         int i, j;
567         int64_t bytes;
568         int result = 0, track_channels = 0;
569         int chunk_size;
571         if(!fd) return 0;
573         if(quicktime_supported_audio(fd, 0))
574         {
575 // Use Quicktime's compressor. (Always used)
576 // Allocate temp buffer
577                 new_audio_temp(len);
579 // Copy to float buffer
580                 for(i = 0; i < asset->channels; i++)
581                 {
582                         for(j = 0; j < len; j++)
583                         {
584                                 temp_float[i][j] = buffer[i][j];
585                         }
586                 }
588 // Because of the way Quicktime's compressors work we want to limit the chunk
589 // size to speed up decompression.
590                 float **channel_ptr;
591                 channel_ptr = new float*[asset->channels];
593                 for(j = 0; j < len && !result; )
594                 {
595                         chunk_size = asset->sample_rate;
596                         if(j + chunk_size > len) chunk_size = len - j;
598                         for(i = 0; i < asset->channels; i++)
599                         {
600                                 channel_ptr[i] = &temp_float[i][j];
601                         }
603                         result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
604                         j += asset->sample_rate;
605                 }
607                 delete [] channel_ptr;
608         }
609         return result;
612 int FileMOV::write_frames(VFrame ***frames, int len)
614 //printf("FileMOV::write_frames 1\n");
615         int i, j, k, result = 0;
616         int default_compressor = 1;
617         if(!fd) return 0;
619         for(i = 0; i < asset->layers && !result; i++)
620         {
626 // Fix direct copy cases for format conversions.
627                 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
628                 {
629                         default_compressor = 0;
630                         for(j = 0; j < len && !result; j++)
631                         {
632                                 VFrame *frame = frames[i][j];
636 // Special handling for DIVX
637 // Determine keyframe status.
638 // Write VOL header in the first frame if none exists
639                                 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
640                                         !strcmp(asset->vcodec, QUICKTIME_H263) ||
641                                         !strcmp(asset->vcodec, QUICKTIME_HV60))
642                                 {
643                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
644                                                 frame->get_compressed_size(),
645                                                 asset->vcodec))
646                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
650                                         if(!(file->current_frame + j) && 
651                                                 !quicktime_mpeg4_has_vol(frame->get_data()))
652                                         {
653                                                 VFrame *temp_frame = new VFrame;
655                                                 temp_frame->allocate_compressed_data(frame->get_compressed_size() + 
656                                                         0xff);
657                                                 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
658                                                         asset->width, 
659                                                         asset->height, 
660                                                         60000, 
661                                                         asset->frame_rate);
662                                                 memcpy(temp_frame->get_data() + bytes, 
663                                                         frame->get_data(), 
664                                                         frame->get_compressed_size());
665                                                 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
667                                                 result = quicktime_write_frame(fd,
668                                                         temp_frame->get_data(),
669                                                         temp_frame->get_compressed_size(),
670                                                         i);
672                                                 delete temp_frame;
675                                         }
676                                         else
677                                         {
678                                                 result = quicktime_write_frame(fd,
679                                                         frame->get_data(),
680                                                         frame->get_compressed_size(),
681                                                         i);
682                                         }
683                                 }
684                                 else
685                                 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
686                                 {
687                                         if(quicktime_mpeg4_is_key(frame->get_data(), 
688                                                 frame->get_compressed_size(),
689                                                 asset->vcodec))
690                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
691                                         result = quicktime_write_frame(fd,
692                                                 frame->get_data(),
693                                                 frame->get_compressed_size(),
694                                                 i);
695                                 }
696                                 else
697                                 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
698                                 {
699                                         long field2_offset;
701 // Create extra space for markers
702                                         if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
703                                                 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
705                                         unsigned char *data = frame->get_data();
706                                         long data_size = frame->get_compressed_size();
707                                         long data_allocated = frame->get_compressed_allocated();
709 // Sometimes get 0 length frames
710                                         if(data_size)
711                                         {
712                                                 if(asset->format == FILE_MOV)
713                                                 {
714                                                         mjpeg_insert_quicktime_markers(&data,
715                                                                 &data_size,
716                                                                 &data_allocated,
717                                                                 2,
718                                                                 &field2_offset);
719                                                 }
720                                                 else
721                                                 {
722                                                         mjpeg_insert_avi_markers(&data,
723                                                                 &data_size,
724                                                                 &data_allocated,
725                                                                 2,
726                                                                 &field2_offset);
727                                                 }
728                                                 frame->set_compressed_size(data_size);
729                                                 result = quicktime_write_frame(fd,
730                                                         frame->get_data(),
731                                                         frame->get_compressed_size(),
732                                                         i);
733                                         }
734                                         else
735                                                 printf("FileMOV::write_frames data_size=%d\n", data_size);
736                                 }
737                                 else
738                                         result = quicktime_write_frame(fd,
739                                                 frame->get_data(),
740                                                 frame->get_compressed_size(),
741                                                 i);
742                                 
743                                 
744                         }
745                 }
746                 else
747                 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
748                         match4(asset->vcodec, QUICKTIME_YUV422) ||
749                         match4(asset->vcodec, QUICKTIME_RAW))
750                 {
751 // Direct copy planes where possible
752                         default_compressor = 0;
753                         for(j = 0; j < len && !result; j++)
754                         {
755                                 VFrame *frame = frames[i][j];
756 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
757                                 quicktime_set_cmodel(fd, frame->get_color_model());
758                                 if(cmodel_is_planar(frame->get_color_model()))
759                                 {
760                                         unsigned char *planes[3];
761                                         planes[0] = frame->get_y();
762                                         planes[1] = frame->get_u();
763                                         planes[2] = frame->get_v();
764                                         result = quicktime_encode_video(fd, planes, i);
765                                 }
766                                 else
767                                 {
768                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
769 //printf("FileMOV::write_frames 2 %d\n", result);
770                                 }
771 //printf("FileMOV::write_frames 2\n");
772                         }
773                 }
774                 else
775                 if(file->cpus > 1 && 
776                         (match4(asset->vcodec, QUICKTIME_JPEG) || 
777                         match4(asset->vcodec, QUICKTIME_MJPA)))
778                 {
779                         default_compressor = 0;
780 // Compress symmetrically on an SMP system.
781                         ThreadStruct *threadframe;
782                         int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
784 // Set up threads for symmetric compression.
785                         if(!threads)
786                         {
787                                 threads = new FileMOVThread*[file->cpus];
788                                 for(j = 0; j < file->cpus; j++)
789                                 {
790                                         threads[j] = new FileMOVThread(this, fields);
791                                         threads[j]->start_encoding();
792                                 }
793                         }
795 // Set up the frame structures for asynchronous compression.
796 // The mjpeg object must exist in each threadframe because it is where the output
797 // is stored.
798                         while(threadframes.total < len)
799                         {
800                                 threadframes.append(threadframe = new ThreadStruct);
801                         }
803 // Load thread frame structures with new frames.
804                         for(j = 0; j < len; j++)
805                         {
806                                 VFrame *frame = frames[i][j];
807                                 threadframes.values[j]->input = frame;
808                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
809                         }
810                         total_threadframes = len;
811                         current_threadframe = 0;
813 // Start the threads compressing
814                         for(j = 0; j < file->cpus; j++)
815                         {
816                                 threads[j]->encode_buffer();
817                         }
820 // Write the frames as they're finished
821                         for(j = 0; j < len; j++)
822                         {
823                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
824                                 threadframes.values[j]->completion_lock->unlock();
825                                 if(!result)
826                                 {
827                                         result = quicktime_write_frame(fd, 
828                                                 threadframes.values[j]->output,
829                                                 threadframes.values[j]->output_size,
830                                                 i);
831                                 }
832                         }
833                 }
835                 if(default_compressor)
836                 {
837 //printf("FileMOV::write_frames 3\n");
838 // Use the library's built in compressor.
839                         for(j = 0; j < len && !result; j++)
840                         {
841 //printf("FileMOV::write_frames 4\n");
842                                 VFrame *frame = frames[i][j];
843                                 quicktime_set_cmodel(fd, frame->get_color_model());
844 //printf("FileMOV::write_frames 5\n");
845                                 if(cmodel_is_planar(frame->get_color_model()))
846                                 {
847                                         unsigned char *planes[3];
848                                         planes[0] = frame->get_y();
849                                         planes[1] = frame->get_u();
850                                         planes[2] = frame->get_v();
851                                         result = quicktime_encode_video(fd, planes, i);
852                                 }
853                                 else
854                                 {
855                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
856                                 }
857                         }
858                 }
859 //printf("FileMOV::write_frames 4\n");
860         }
863 //printf("FileMOV::write_frames 100\n");
864         return result;
869 int FileMOV::read_frame(VFrame *frame)
871         if(!fd) return 1;
872         int result = 0;
874         switch(frame->get_color_model())
875         {
876                 case BC_COMPRESSED:
877                         frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
878                         frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
879                         result = quicktime_read_frame(fd, 
880                                 frame->get_data(), 
881                                 file->current_layer);
882                         break;
884 // Progressive
885                 case BC_YUV420P:
886                 case BC_YUV422P:
887                 {
888                         unsigned char *row_pointers[3];
889                         row_pointers[0] = frame->get_y();
890                         row_pointers[1] = frame->get_u();
891                         row_pointers[2] = frame->get_v();
893                         quicktime_set_cmodel(fd, frame->get_color_model());
894                         quicktime_decode_video(fd, 
895                                 row_pointers,
896                                 file->current_layer);
897                 }
898                         break;
900 // Packed
901                 default:
902                         quicktime_set_cmodel(fd, frame->get_color_model());
903                         result = quicktime_decode_video(fd, 
904                                 frame->get_rows(),
905                                 file->current_layer);
906 //for(int i = 0; i < 10000; i++) frame->get_rows()[0][i] = 0xff;
907                         break;
908         }
912         return result;
917 int64_t FileMOV::compressed_frame_size()
919         if(!fd) return 0;
920         return quicktime_frame_size(fd, file->current_frame, file->current_layer);
923 int FileMOV::read_compressed_frame(VFrame *buffer)
925         int64_t result;
926         if(!fd) return 0;
928 //printf("FileMOV::read_compressed_frame 1\n");
929         result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
930         buffer->set_compressed_size(result);
931 //printf("FileMOV::read_compressed_frame 100\n");
932         result = !result;
933         return result;
936 int FileMOV::write_compressed_frame(VFrame *buffer)
938         int result = 0;
939         if(!fd) return 0;
941 TRACE("FileMOV::write_compressed_frame 1");
942         result = quicktime_write_frame(fd, 
943                 buffer->get_data(), 
944                 buffer->get_compressed_size(), 
945                 file->current_layer);
946 TRACE("FileMOV::write_compressed_frame 100");
947         return result;
952 int FileMOV::read_raw(VFrame *frame, 
953                 float in_x1, float in_y1, float in_x2, float in_y2,
954                 float out_x1, float out_y1, float out_x2, float out_y2, 
955                 int use_float, int interpolate)
957         int64_t i, color_channels, result = 0;
958         if(!fd) return 0;
960 //printf("FileMOV::read_raw 1\n");
961         quicktime_set_video_position(fd, file->current_frame, file->current_layer);
962 // Develop importing strategy
963         switch(frame->get_color_model())
964         {
965                 case BC_RGB888:
966                         result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
967                         break;
968                 case BC_RGBA8888:
969                         break;
970                 case BC_RGB161616:
971                         break;
972                 case BC_RGBA16161616:
973                         break;
974                 case BC_YUV888:
975                         break;
976                 case BC_YUVA8888:
977                         break;
978                 case BC_YUV161616:
979                         break;
980                 case BC_YUVA16161616:
981                         break;
982                 case BC_YUV420P:
983                         break;
984         }
985         return result;
988 // Overlay samples
989 int FileMOV::read_samples(double *buffer, int64_t len)
991         int qt_track, qt_channel;
993         if(!fd) return 0;
995 //printf("FileMOV::read_samples 1\n");
996         if(quicktime_track_channels(fd, 0) > file->current_channel &&
997                 quicktime_supported_audio(fd, 0))
998         {
1000 //printf("FileMOV::read_samples 2 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1001                 new_audio_temp(len);
1003 //printf("FileMOV::read_samples 3 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1004                 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
1005                 {
1006                         printf("FileMOV::read_samples: quicktime_decode_audio failed\n");
1007                         return 1;
1008                 }
1009                 else
1010                 {
1011                         for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
1012                 }
1014 // if(file->current_channel == 0)
1015 // for(int i = 0; i < len; i++)
1016 // {
1017 //      int16_t value;
1018 //      value = (int16_t)(temp_float[0][i] * 32767);
1019 //      fwrite(&value, 2, 1, stdout);
1020 // }
1021 //printf("FileMOV::read_samples 4 %ld %ld\n", file->current_sample, quicktime_audio_position(fd, 0));
1022         }
1024 //printf("FileMOV::read_samples 100\n");
1025         return 0;
1029 char* FileMOV::strtocompression(char *string)
1031         if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
1032         if(!strcasecmp(string, _(MP4V_NAME))) return QUICKTIME_MP4V;
1033         if(!strcasecmp(string, _(H263_NAME))) return QUICKTIME_H263;
1034         if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
1035         if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
1036         if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
1037         if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
1038         if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
1039         if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
1040         if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
1041         if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
1042         if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
1043         if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
1044         if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
1045         if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
1046         if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
1047         if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
1048         if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
1050         if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
1051         if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
1052         if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
1053         if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
1054         if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
1055         if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
1059         return QUICKTIME_RAW;
1062 char* FileMOV::compressiontostr(char *string)
1064         if(match4(string, QUICKTIME_H263)) return _(H263_NAME);
1065         if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1066         if(match4(string, QUICKTIME_MP4V)) return _(MP4V_NAME);
1067         if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1068         if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1069         if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1070         if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1071         if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1072         if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1073         if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1074         if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1075         if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1076         if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1077         if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1078         if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1079         if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1080         if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1086         if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1087         if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1088         if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1089         if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1090         if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1091         if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1095         return _("Unknown");
1102 ThreadStruct::ThreadStruct()
1104         input = 0;
1105         output = 0;
1106         output_allocated = 0;
1107         output_size = 0;
1108         completion_lock = new Condition(1, "ThreadStruct::completion_lock");
1111 ThreadStruct::~ThreadStruct()
1113         if(output) delete [] output;
1114         delete completion_lock;
1117 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1119         if(output_allocated < mjpeg_output_size(mjpeg))
1120         {
1121                 delete [] output;
1122                 output = 0;
1123         }
1124         if(!output)
1125         {
1126                 output_allocated = mjpeg_output_size(mjpeg);
1127                 output = new unsigned char[output_allocated];
1128         }
1129         
1130         output_size = mjpeg_output_size(mjpeg);
1131         memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1135 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields) : Thread()
1137         this->filemov = filemov;
1138         this->fields = fields;
1139         mjpeg = 0;
1140         input_lock = new Condition(1, "FileMOVThread::input_lock");
1143 FileMOVThread::~FileMOVThread()
1145         delete input_lock;
1148 int FileMOVThread::start_encoding()
1150         mjpeg = mjpeg_new(filemov->asset->width, 
1151                 filemov->asset->height, 
1152                 fields);
1153         mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1154         mjpeg_set_float(mjpeg, 0);
1155         done = 0;
1156         set_synchronous(1);
1157         input_lock->lock("FileMOVThread::start_encoding");
1158         start();
1161 int FileMOVThread::stop_encoding()
1163         done = 1;
1164         input_lock->unlock();
1165         join();
1166         if(mjpeg) mjpeg_delete(mjpeg);
1169 int FileMOVThread::encode_buffer()
1171         input_lock->unlock();
1174 void FileMOVThread::run()
1176         while(!done)
1177         {
1178                 input_lock->lock("FileMOVThread::run");
1180                 if(!done)
1181                 {
1182 // Get a frame to compress.
1183                         filemov->threadframe_lock->lock("FileMOVThread::stop_encoding");
1184                         if(filemov->current_threadframe < filemov->total_threadframes)
1185                         {
1186 // Frame is available to process.
1187                                 input_lock->unlock();
1188                                 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1189                                 VFrame *frame = threadframe->input;
1191                                 filemov->current_threadframe++;
1192                                 filemov->threadframe_lock->unlock();
1194                                 mjpeg_compress(mjpeg, 
1195                                         frame->get_rows(), 
1196                                         frame->get_y(), 
1197                                         frame->get_u(), 
1198                                         frame->get_v(),
1199                                         frame->get_color_model(),
1200                                         1);
1202                                 if(fields > 1)
1203                                 {
1204                                         unsigned char *data = mjpeg_output_buffer(mjpeg);
1205                                         long data_size = mjpeg_output_size(mjpeg);
1206                                         long data_allocated = mjpeg_output_allocated(mjpeg);
1207                                         long field2_offset;
1209                                         if(filemov->asset->format == FILE_MOV)
1210                                         {
1211                                                 mjpeg_insert_quicktime_markers(&data,
1212                                                         &data_size,
1213                                                         &data_allocated,
1214                                                         2,
1215                                                         &field2_offset);
1216                                         }
1217                                         else
1218                                         {
1219                                                 mjpeg_insert_avi_markers(&data,
1220                                                         &data_size,
1221                                                         &data_allocated,
1222                                                         2,
1223                                                         &field2_offset);
1224                                         }
1225                                         mjpeg_set_output_size(mjpeg, data_size);
1226                                 }
1227                                 threadframe->load_output(mjpeg);
1228                                 threadframe->completion_lock->unlock();
1229                         }
1230                         else
1231                                 filemov->threadframe_lock->unlock();
1232                 }
1233         }
1241 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1242  : BC_Window(PROGRAM_NAME ": Audio Compression",
1243         parent_window->get_abs_cursor_x(1),
1244         parent_window->get_abs_cursor_y(1),
1245         350,
1246         250)
1248         this->parent_window = parent_window;
1249         this->asset = asset;
1250         bits_popup = 0;
1251         bits_title = 0;
1252         dither = 0;
1253         vorbis_min_bitrate = 0;
1254         vorbis_bitrate = 0;
1255         vorbis_max_bitrate = 0;
1256         vorbis_vbr = 0;
1257         compression_popup = 0;
1258         mp3_bitrate = 0;
1261 MOVConfigAudio::~MOVConfigAudio()
1263         if(compression_popup) delete compression_popup;
1264         if(bits_popup) delete bits_popup;
1265         compression_items.remove_all_objects();
1268 int MOVConfigAudio::create_objects()
1270         int x = 10, y = 10;
1272         
1274         if(asset->format == FILE_MOV)
1275         {
1276                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1277                 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1278                 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1279 //              compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1280                 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1281                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1282         }
1283         else
1284         {
1285                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1286                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1287                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1288         }
1290         add_tool(new BC_Title(x, y, _("Compression:")));
1291         y += 25;
1292         compression_popup = new MOVConfigAudioPopup(this, x, y);
1293         compression_popup->create_objects();
1295         update_parameters();
1297         add_subwindow(new BC_OKButton(this));
1298         return 0;
1301 void MOVConfigAudio::update_parameters()
1303         int x = 10, y = 70;
1304         if(bits_title) delete bits_title;
1305         if(bits_popup) delete bits_popup;
1306         if(dither) delete dither;
1307         if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1308         if(vorbis_bitrate) delete vorbis_bitrate;
1309         if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1310         if(vorbis_vbr) delete vorbis_vbr;
1311         if(mp3_bitrate) delete mp3_bitrate;
1313         bits_popup = 0;
1314         bits_title = 0;
1315         dither = 0;
1316         vorbis_min_bitrate = 0;
1317         vorbis_bitrate = 0;
1318         vorbis_max_bitrate = 0;
1319         vorbis_vbr = 0;
1323         mp3_bitrate = 0;
1327         if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1328                 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1329         {
1330                 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1331                 bits_popup = new BitsPopup(this, 
1332                         x + 150, 
1333                         y, 
1334                         &asset->bits, 
1335                         0, 
1336                         0, 
1337                         0, 
1338                         0, 
1339                         0);
1340                 bits_popup->create_objects();
1341                 y += 40;
1342                 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1343         }
1344         else
1345         if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1346         {
1347         }
1348         else
1349         if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1350         {
1351                 mp3_bitrate = new MOVConfigAudioNum(this, 
1352                         _("Bitrate:"), 
1353                         x, 
1354                         y, 
1355                         &asset->mp3_bitrate);
1356                 mp3_bitrate->set_increment(1000);
1357                 mp3_bitrate->create_objects();
1358         }
1359         else
1360         if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1361         {
1362         }
1363         else
1364         if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1365         {
1366                 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1367                         _("Variable bitrate"),
1368                         x,
1369                         y,
1370                         &asset->vorbis_vbr));
1371                 y += 35;
1372                 vorbis_min_bitrate = new MOVConfigAudioNum(this, 
1373                         _("Min bitrate:"), 
1374                         x, 
1375                         y, 
1376                         &asset->vorbis_min_bitrate);
1377                 vorbis_min_bitrate->set_increment(1000);
1378                 y += 30;
1379                 vorbis_bitrate = new MOVConfigAudioNum(this, 
1380                         _("Avg bitrate:"), 
1381                         x, 
1382                         y, 
1383                         &asset->vorbis_bitrate);
1384                 vorbis_bitrate->set_increment(1000);
1385                 y += 30;
1386                 vorbis_max_bitrate = new MOVConfigAudioNum(this, 
1387                         _("Max bitrate:"), 
1388                         x, 
1389                         y, 
1390                         &asset->vorbis_max_bitrate);
1391                 vorbis_max_bitrate->set_increment(1000);
1395                 vorbis_min_bitrate->create_objects();
1396                 vorbis_bitrate->create_objects();
1397                 vorbis_max_bitrate->create_objects();
1398         }
1401 int MOVConfigAudio::close_event()
1403         set_done(0);
1404         return 1;
1411 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1412         char *title_text,
1413         int x,
1414         int y,
1415         int *output)
1416  : BC_CheckBox(x, y, *output, title_text)
1418         this->popup = popup;
1419         this->output = output;
1421 int MOVConfigAudioToggle::handle_event()
1423         *output = get_value();
1424         return 1;
1431 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1432  : BC_TumbleTextBox(popup, 
1433                 (int64_t)*output,
1434                 (int64_t)-1,
1435                 (int64_t)25000000,
1436                 x + 150, 
1437                 y, 
1438                 100)
1440         this->popup = popup;
1441         this->title_text = title_text;
1442         this->output = output;
1443         this->x = x;
1444         this->y = y;
1447 MOVConfigAudioNum::~MOVConfigAudioNum()
1449         if(!popup->get_deleting()) delete title;
1452 void MOVConfigAudioNum::create_objects()
1454         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1455         BC_TumbleTextBox::create_objects();
1458 int MOVConfigAudioNum::handle_event()
1460         *output = atol(get_text());
1461         return 1;
1471 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1472  : BC_PopupTextBox(popup, 
1473                 &popup->compression_items,
1474                 FileMOV::compressiontostr(popup->asset->acodec),
1475                 x, 
1476                 y, 
1477                 300,
1478                 300)
1480         this->popup = popup;
1483 int MOVConfigAudioPopup::handle_event()
1485         strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1486         popup->update_parameters();
1487         return 1;
1506 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window, 
1507         Asset *asset, 
1508         int lock_compressor)
1509  : BC_Window(PROGRAM_NAME ": Video Compression",
1510         parent_window->get_abs_cursor_x(1),
1511         parent_window->get_abs_cursor_y(1),
1512         420,
1513         420)
1515         this->parent_window = parent_window;
1516         this->asset = asset;
1517         this->lock_compressor = lock_compressor;
1518         compression_popup = 0;
1519         reset();
1522 MOVConfigVideo::~MOVConfigVideo()
1524         if(compression_popup) delete compression_popup;
1525         compression_items.remove_all_objects();
1528 int MOVConfigVideo::create_objects()
1530         int x = 10, y = 10;
1532         if(asset->format == FILE_MOV)
1533         {
1534                 compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1535 //              compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1536                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1537                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1538                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1539                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1540                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1541                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1542                 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1543                 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1544                 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1545                 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1546                 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1547                 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1548                 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1549                 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1550         }
1551         else
1552         {
1553                 compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1554                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1555                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1556                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1557                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1558                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1559                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1560         }
1562         add_subwindow(new BC_Title(x, y, _("Compression:")));
1563         y += 25;
1565         if(!lock_compressor)
1566         {
1567                 compression_popup = new MOVConfigVideoPopup(this, x, y);
1568                 compression_popup->create_objects();
1569         }
1570         else
1571         {
1572                 add_subwindow(new BC_Title(x, 
1573                         y, 
1574                         FileMOV::compressiontostr(asset->vcodec),
1575                         MEDIUMFONT,
1576                         RED,
1577                         0));
1578         }
1579         y += 40;
1581         param_x = x;
1582         param_y = y;
1583         update_parameters();
1585         add_subwindow(new BC_OKButton(this));
1586         return 0;
1589 int MOVConfigVideo::close_event()
1591         set_done(0);
1592         return 1;
1596 void MOVConfigVideo::reset()
1598         jpeg_quality = 0;
1599         jpeg_quality_title = 0;
1601         divx_bitrate = 0;
1602         divx_rc_period = 0;
1603         divx_rc_reaction_ratio = 0;
1604         divx_rc_reaction_period = 0;
1605         divx_max_key_interval = 0;
1606         divx_max_quantizer = 0;
1607         divx_min_quantizer = 0;
1608         divx_quantizer = 0;
1609         divx_quality = 0;
1610         divx_fix_bitrate = 0;
1611         divx_fix_quant = 0;
1613         ms_bitrate = 0;
1614         ms_bitrate_tolerance = 0;
1615         ms_quantization = 0;
1616         ms_interlaced = 0;
1617         ms_gop_size = 0;
1618         ms_fix_bitrate = 0;
1619         ms_fix_quant = 0;
1622 void MOVConfigVideo::update_parameters()
1624         if(jpeg_quality)
1625         {
1626                 delete jpeg_quality_title;
1627                 delete jpeg_quality;
1628         }
1630         if(divx_bitrate) delete divx_bitrate;
1631         if(divx_rc_period) delete divx_rc_period;
1632         if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1633         if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1634         if(divx_max_key_interval) delete divx_max_key_interval;
1635         if(divx_max_quantizer) delete divx_max_quantizer;
1636         if(divx_min_quantizer) delete divx_min_quantizer;
1637         if(divx_quantizer) delete divx_quantizer;
1638         if(divx_quality) delete divx_quality;
1639         if(divx_fix_quant) delete divx_fix_quant;
1640         if(divx_fix_bitrate) delete divx_fix_bitrate;
1642         if(ms_bitrate) delete ms_bitrate;
1643         if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1644         if(ms_interlaced) delete ms_interlaced;
1645         if(ms_quantization) delete ms_quantization;
1646         if(ms_gop_size) delete ms_gop_size;
1647         if(ms_fix_bitrate) delete ms_fix_bitrate;
1648         if(ms_fix_quant) delete ms_fix_quant;
1650         reset();
1652 // ffmpeg parameters
1653         if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
1654         {
1655                 int x = param_x, y = param_y;
1656                 ms_bitrate = new MOVConfigVideoNum(this, 
1657                         _("Bitrate:"), 
1658                         x, 
1659                         y, 
1660                         &asset->ms_bitrate);
1661                 ms_bitrate->set_increment(1000000);
1662                 ms_bitrate->create_objects();
1663                 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260, 
1664                                 y,
1665                                 &asset->ms_fix_bitrate,
1666                                 1));
1667                 y += 30;
1669                 ms_bitrate_tolerance = new MOVConfigVideoNum(this, 
1670                         _("Bitrate tolerance:"), 
1671                         x, 
1672                         y, 
1673                         &asset->ms_bitrate_tolerance);
1674                 ms_bitrate_tolerance->create_objects();
1675                 y += 30;
1676                 ms_quantization = new MOVConfigVideoNum(this, 
1677                         _("Quantization:"), 
1678                         x, 
1679                         y, 
1680                         &asset->ms_quantization);
1681                 ms_quantization->create_objects();
1682                 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260, 
1683                                 y,
1684                                 &asset->ms_fix_bitrate,
1685                                 0));
1686                 ms_fix_bitrate->opposite = ms_fix_quant;
1687                 ms_fix_quant->opposite = ms_fix_bitrate;
1690                 y += 30;
1691                 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"), 
1692                         x, 
1693                         y, 
1694                         &asset->ms_interlaced));
1695                 y += 30;
1696                 ms_gop_size = new MOVConfigVideoNum(this, 
1697                         _("Keyframe interval:"), 
1698                         x, 
1699                         y, 
1700                         &asset->ms_gop_size);
1701                 ms_gop_size->create_objects();
1702         }
1703         else
1704 // OpenDivx parameters
1705         if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
1706                 !strcmp(asset->vcodec, QUICKTIME_H263) ||
1707                 !strcmp(asset->vcodec, QUICKTIME_HV60))
1708         {
1709                 int x = param_x, y = param_y;
1710                 divx_bitrate = new MOVConfigVideoNum(this, 
1711                         _("Bitrate:"), 
1712                         x, 
1713                         y, 
1714                         &asset->divx_bitrate);
1715                 divx_bitrate->set_increment(1000000);
1716                 divx_bitrate->create_objects();
1717                 add_subwindow(divx_fix_bitrate = 
1718                         new MOVConfigVideoFixBitrate(x + 260, 
1719                                 y,
1720                                 &asset->divx_fix_bitrate,
1721                                 1));
1722                 y += 30;
1723                 divx_quantizer = new MOVConfigVideoNum(this, 
1724                         _("Quantizer:"), 
1725                         x, 
1726                         y, 
1727                         &asset->divx_quantizer);
1728                 divx_quantizer->create_objects();
1729                 add_subwindow(divx_fix_quant =
1730                         new MOVConfigVideoFixQuant(x + 260, 
1731                                 y,
1732                                 &asset->divx_fix_bitrate,
1733                                 0));
1734                 divx_fix_quant->opposite = divx_fix_bitrate;
1735                 divx_fix_bitrate->opposite = divx_fix_quant;
1736                 y += 30;
1737                 divx_rc_period = new MOVConfigVideoNum(this, 
1738                         _("RC Period:"), 
1739                         x, 
1740                         y, 
1741                         &asset->divx_rc_period);
1742                 divx_rc_period->create_objects();
1743                 y += 30;
1744                 divx_rc_reaction_ratio = new MOVConfigVideoNum(this, 
1745                         _("Reaction Ratio:"), 
1746                         x, 
1747                         y, 
1748                         &asset->divx_rc_reaction_ratio);
1749                 divx_rc_reaction_ratio->create_objects();
1750                 y += 30;
1751                 divx_rc_reaction_period = new MOVConfigVideoNum(this, 
1752                         _("Reaction Period:"), 
1753                         x, 
1754                         y, 
1755                         &asset->divx_rc_reaction_period);
1756                 divx_rc_reaction_period->create_objects();
1757                 y += 30;
1758                 divx_max_key_interval = new MOVConfigVideoNum(this, 
1759                         _("Max Key Interval:"), 
1760                         x, 
1761                         y, 
1762                         &asset->divx_max_key_interval);
1763                 divx_max_key_interval->create_objects();
1764                 y += 30;
1765                 divx_max_quantizer = new MOVConfigVideoNum(this, 
1766                         _("Max Quantizer:"), 
1767                         x, 
1768                         y, 
1769                         &asset->divx_max_quantizer);
1770                 divx_max_quantizer->create_objects();
1771                 y += 30;
1772                 divx_min_quantizer = new MOVConfigVideoNum(this, 
1773                         _("Min Quantizer:"), 
1774                         x, 
1775                         y, 
1776                         &asset->divx_min_quantizer);
1777                 divx_min_quantizer->create_objects();
1778                 y += 30;
1779                 divx_quality = new MOVConfigVideoNum(this, 
1780                         _("Quality:"), 
1781                         x, 
1782                         y, 
1783                         &asset->divx_quality);
1784                 divx_quality->create_objects();
1785         }
1786         else
1787         if(!strcmp(asset->vcodec, QUICKTIME_JPEG) ||
1788                 !strcmp(asset->vcodec, QUICKTIME_MJPA))
1789         {
1790                 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
1791                 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80, 
1792                         param_y,
1793                         0,
1794                         200,
1795                         200,
1796                         0,
1797                         100,
1798                         asset->jpeg_quality,
1799                         0,
1800                         0,
1801                         &asset->jpeg_quality));
1802         }
1809 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
1810  : BC_TumbleTextBox(popup, 
1811                 (int64_t)*output,
1812                 (int64_t)1,
1813                 (int64_t)25000000,
1814                 x + 130, 
1815                 y, 
1816                 100)
1818         this->popup = popup;
1819         this->title_text = title_text;
1820         this->output = output;
1821         this->x = x;
1822         this->y = y;
1825 MOVConfigVideoNum::~MOVConfigVideoNum()
1827         if(!popup->get_deleting()) delete title;
1830 void MOVConfigVideoNum::create_objects()
1832         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1833         BC_TumbleTextBox::create_objects();
1836 int MOVConfigVideoNum::handle_event()
1838         *output = atol(get_text());
1839         return 1;
1848 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
1849  : BC_CheckBox(x, y, *output, title_text)
1851         this->output = output;
1854 int MOVConfigVideoCheckBox::handle_event()
1856         *output = get_value();
1857         return 1;
1865 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x, 
1866         int y,
1867         int *output,
1868         int value)
1869  : BC_Radial(x, 
1870         y, 
1871         *output == value, 
1872         _("Fix bitrate"))
1874         this->output = output;
1875         this->value = value;
1878 int MOVConfigVideoFixBitrate::handle_event()
1880         *output = value;
1881         opposite->update(0);
1882         return 1;
1890 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x, 
1891         int y,
1892         int *output,
1893         int value)
1894  : BC_Radial(x, 
1895         y, 
1896         *output == value, 
1897         _("Fix quantization"))
1899         this->output = output;
1900         this->value = value;
1903 int MOVConfigVideoFixQuant::handle_event()
1905         *output = value;
1906         opposite->update(0);
1907         return 1;
1914 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
1915  : BC_PopupTextBox(popup, 
1916                 &popup->compression_items,
1917                 FileMOV::compressiontostr(popup->asset->vcodec),
1918                 x, 
1919                 y, 
1920                 300,
1921                 300)
1923         this->popup = popup;
1926 int MOVConfigVideoPopup::handle_event()
1928         strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
1929         popup->update_parameters();
1930         return 1;