update internationalization data
[goodguy/history.git] / cinelerra-5.0 / cinelerra / filemov.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "asset.h"
23 #include "bcsignals.h"
24 #include "bitspopup.h"
25 #include "byteorder.h"
26 #include "clip.h"
27 #include "condition.h"
28 #include "edit.h"
29 #include "file.h"
30 #include "filemov.h"
31 #include "format.inc"
32 #include "guicast.h"
33 #include "language.h"
34 #include "mutex.h"
35 #include "mwindow.inc"
36 #include "preferences.h"
37 #include "vframe.h"
38 #include "videodevice.inc"
39 #include "mainerror.h"
40
41 #include <unistd.h>
42 #include <libdv/dv.h>
43 #include <string.h>
44
45 #if 0
46 N_("MPEG-4")
47 N_("Dual H.264")
48 N_("Dual MPEG-4")
49 N_("H.264")
50 N_("H.263")
51 N_("Microsoft MPEG-4")
52 N_("DV")
53 N_("PNG")
54 N_("PNG with Alpha")
55 N_("Uncompressed RGB")
56 N_("Uncompressed RGBA")
57 N_("YUV 4:2:0 Planar")
58 N_("Component Y'CbCr 8-bit 4:2:2 (yuv2)")
59 N_("Component Y'CbCr 8-bit 4:2:2 (2vuy)")
60 N_("YUV 4:1:1 Packed")
61 N_("Component Y'CbCr 8-bit 4:4:4")
62 N_("Component Y'CbCrA 8-bit 4:4:4:4")
63 N_("Component Y'CbCr 10-bit 4:4:4")
64 N_("JPEG Photo")
65 N_("Motion JPEG A")
66
67
68 N_("Twos complement")
69 N_("Unsigned")
70 N_("IMA-4")
71 N_("U-Law")
72 N_("Vorbis")
73 N_("MP3")
74 N_("MPEG-4 Audio")
75 #endif
76
77 #define DIVX_NAME "MPEG-4"
78 #define HV64_NAME "Dual H.264"
79 #define MP4V_NAME "MPEG-4 Video"
80 #define H264_NAME "H.264"
81 #define H263_NAME "H.263"
82 #define HV60_NAME "Dual MPEG-4"
83 #define DIV3_NAME "Microsoft MPEG-4"
84 #define DV_NAME "DV"
85 #define PNG_NAME "PNG"
86 #define PNGA_NAME "PNG with Alpha"
87 #define RGB_NAME "Uncompressed RGB"
88 #define RGBA_NAME "Uncompressed RGBA"
89 #define YUV420_NAME "YUV 4:2:0 Planar"
90 #define YUV422_NAME "Component Y'CbCr 8-bit 4:2:2 (yuv2)"
91 #define TWOVUY_NAME "Component Y'CbCr 8-bit 4:2:2 (2vuy)"
92 #define YUV411_NAME "YUV 4:1:1 Packed"
93 #define YUV444_NAME "Component Y'CbCr 8-bit 4:4:4"
94 #define YUVA4444_NAME "Component Y'CbCrA 8-bit 4:4:4:4"
95 #define YUV444_10BIT_NAME "Component Y'CbCr 10-bit 4:4:4"
96 #define QTJPEG_NAME "JPEG Photo"
97 #define QTMJPEGP_NAME "MJPEG Photo"
98 #define MJPA_NAME "Motion JPEG A"
99
100 #define TWOS_NAME "Twos complement"
101 #define RAW_NAME "Unsigned"
102 #define IMA4_NAME "IMA-4"
103 #define ULAW_NAME "U-Law"
104 //#define VORBIS_NAME "Vorbis"
105 #define MP3_NAME "MP3"
106 #define MP4A_NAME "MPEG-4 Audio"
107 #define VORBIS_NAME "OGG Vorbis"
108
109
110
111
112
113 FileMOV::FileMOV(Asset *asset, File *file)
114  : FileBase(asset, file)
115 {
116         reset_parameters();
117         if(asset->format == FILE_UNKNOWN)
118                 asset->format = FILE_MOV;
119         asset->byte_order = 0;
120         suffix_number = 0;
121         threadframe_lock = new Mutex("FileMOV::threadframe_lock");
122 }
123
124 FileMOV::~FileMOV()
125 {
126         close_file();
127         delete threadframe_lock;
128 }
129
130 void FileMOV::get_parameters(BC_WindowBase *parent_window,
131         Asset *asset,
132         BC_WindowBase* &format_window,
133         int audio_options,
134         int video_options,
135         const char *locked_compressor)
136 {
137         fix_codecs(asset);
138         if(audio_options)
139         {
140                 MOVConfigAudio *window = new MOVConfigAudio(parent_window, asset);
141                 format_window = window;
142                 window->create_objects();
143                 window->run_window();
144                 delete window;
145         }
146         else
147         if(video_options)
148         {
149                 MOVConfigVideo *window = new MOVConfigVideo(parent_window,
150                         asset,
151                         locked_compressor);
152                 format_window = window;
153                 window->create_objects();
154                 window->run_window();
155                 delete window;
156         }
157 }
158
159 void FileMOV::fix_codecs(Asset *asset)
160 {
161         if(!strcasecmp(asset->vcodec, QUICKTIME_DV) ||
162            !strcasecmp(asset->vcodec, QUICKTIME_DVSD) ||
163            !strcasecmp(asset->vcodec, QUICKTIME_DVCP))
164         {
165 //        printf("AF: %i, AH: %i, VC: %s\n", asset->format, asset->height, asset->vcodec);
166         if (asset->format == FILE_AVI)
167                 strcpy (asset->vcodec, QUICKTIME_DVSD);
168         else if (asset->format == FILE_MOV && asset->height == 576)
169                 strcpy (asset->vcodec, QUICKTIME_DVCP);
170         else if (asset->format == FILE_MOV && asset->height == 480)
171                 strcpy (asset->vcodec, QUICKTIME_DV);
172         }
173 }
174
175 int FileMOV::check_codec_params(Asset *asset)
176 {
177         if(!strcasecmp(asset->vcodec, QUICKTIME_DV) ||
178            !strcasecmp(asset->vcodec, QUICKTIME_DVSD) ||
179            !strcasecmp(asset->vcodec, QUICKTIME_DVCP))
180         {
181                 if (!(asset->height == 576 && asset->width == 720) &&
182                     !(asset->height == 480 && asset->width == 720))
183                 {
184                         eprintf(_("DV in Quicktime container does not support following resolution: %ix%i\n"
185                                 "Allowed resolutions are 720x576 (PAL) and 720x480 (NTSC)\n"),
186                                  asset->width, asset->height);
187                         return 1;
188                 }
189         }
190         return 0;
191 }
192
193
194 int FileMOV::check_sig(Asset *asset)
195 {
196         int result = quicktime_check_sig(asset->path);
197         if(result == 2) result = 0;
198         return result;
199 }
200
201 int FileMOV::reset_parameters_derived()
202 {
203         fd = 0;
204         prev_track = 0;
205         quicktime_atracks = 0;
206         quicktime_vtracks = 0;
207         depth = 24;
208         threads = 0;
209         frames_correction = 0;
210         samples_correction = 0;
211         temp_float = 0;
212         temp_allocated = 0;
213         return 0;
214 }
215
216
217 // Just create the Quicktime objects since this routine is also called
218 // for reopening.
219 int FileMOV::open_file(int rd, int wr)
220 {
221
222         if(suffix_number == 0) strcpy(prefix_path, asset->path);
223
224         if(!(fd = quicktime_open(asset->path, rd, wr)))
225         {
226                 eprintf(_("Error while opening file \"%s\". \n%m\n"), asset->path);
227                 return 1;
228         }
229
230         if( !strcmp(asset->vcodec, QUICKTIME_DIV3) )
231                 file->cpus = 1;
232         quicktime_set_cpus(fd, file->cpus);
233         quicktime_set_cache_max(fd, file->preferences->cache_size);
234 //printf("FileMOV::open_file %d %d\n", __LINE__, file->preferences->cache_size);
235
236         if(rd) format_to_asset();
237
238         if(wr)
239         {
240                 asset_to_format();
241                 if (check_codec_params(asset))
242                         return 1;
243         }
244
245 // Set decoding parameter
246         quicktime_set_parameter(fd, "divx_use_deblocking", &asset->divx_use_deblocking);
247 // Set timecode offset
248         quicktime_set_frame_start(fd, 0);
249
250         return 0;
251 }
252
253 int FileMOV::close_file()
254 {
255 //printf("FileMOV::close_file 1 %s\n", asset->path);
256         if(fd)
257         {
258                 if(file->wr) quicktime_set_framerate(fd, asset->frame_rate);
259                 quicktime_close(fd);
260         }
261
262 //printf("FileMOV::close_file 1\n");
263         if(threads)
264         {
265                 for(int i = 0; i < file->cpus; i++)
266                 {
267                         threads[i]->stop_encoding();
268                         delete threads[i];
269                 }
270                 delete [] threads;
271                 threads = 0;
272         }
273
274 //printf("FileMOV::close_file 1\n");
275         threadframes.remove_all_objects();
276
277
278         if(temp_float)
279         {
280                 for(int i = 0; i < asset->channels; i++)
281                         delete [] temp_float[i];
282                 delete [] temp_float;
283         }
284
285 //printf("FileMOV::close_file 1\n");
286         reset_parameters();
287         FileBase::close_file();
288 //printf("FileMOV::close_file 2\n");
289         return 0;
290 }
291
292 void FileMOV::set_frame_start(int64_t offset)
293 {
294         quicktime_set_frame_start(fd, offset);
295 }
296
297 void FileMOV::asset_to_format()
298 {
299         if(!fd) return;
300
301         fix_codecs(asset);
302
303 // Fix up the Quicktime file.
304         quicktime_set_copyright(fd, _("Made with Cinelerra for Linux"));
305         quicktime_set_info(fd, "Quicktime for Linux");
306
307         if(asset->audio_data)
308         {
309                 quicktime_atracks = quicktime_set_audio(fd,
310                                 asset->channels,
311                                 asset->sample_rate,
312                                 asset->bits,
313                                 asset->acodec);
314                 quicktime_set_parameter(fd, "vorbis_vbr", &asset->vorbis_vbr);
315                 quicktime_set_parameter(fd, "vorbis_min_bitrate", &asset->vorbis_min_bitrate);
316                 quicktime_set_parameter(fd, "vorbis_bitrate", &asset->vorbis_bitrate);
317                 quicktime_set_parameter(fd, "vorbis_max_bitrate", &asset->vorbis_max_bitrate);
318                 quicktime_set_parameter(fd, "mp3_bitrate", &asset->mp3_bitrate);
319                 quicktime_set_parameter(fd, "mp4a_bitrate", &asset->mp4a_bitrate);
320         }
321
322         if(asset->video_data)
323         {
324                 char string[16];
325 // Set up the alpha channel compressors
326                 if(!strcmp(asset->vcodec, MOV_RGBA))
327                 {
328                         strcpy(string, QUICKTIME_RAW);
329                         depth = 32;
330                 }
331                 else
332                 if(!strcmp(asset->vcodec, MOV_PNGA))
333                 {
334                         strcpy(string, QUICKTIME_PNG);
335                         depth = 32;
336                 }
337                 else
338                 if(!strcmp(asset->vcodec, QUICKTIME_YUVA4444))
339                 {
340                         strcpy(string, asset->vcodec);
341                         depth = 32;
342                 }
343                 else
344                 {
345                         strcpy(string, asset->vcodec);
346                         depth = 24;
347                 }
348
349
350                 quicktime_vtracks = quicktime_set_video(fd,
351                                         asset->layers,
352                                         asset->width,
353                                         asset->height,
354                                         asset->frame_rate,
355                                         string);
356
357
358
359                 for(int i = 0; i < asset->layers; i++)
360                         quicktime_set_depth(fd, depth, i);
361
362                 quicktime_set_parameter(fd, "jpeg_quality", &asset->jpeg_quality);
363
364 // set the compression parameters if there are any
365                 quicktime_set_parameter(fd, "divx_bitrate", &asset->divx_bitrate);
366                 quicktime_set_parameter(fd, "divx_rc_period", &asset->divx_rc_period);
367                 quicktime_set_parameter(fd, "divx_rc_reaction_ratio", &asset->divx_rc_reaction_ratio);
368                 quicktime_set_parameter(fd, "divx_rc_reaction_period", &asset->divx_rc_reaction_period);
369                 quicktime_set_parameter(fd, "divx_max_key_interval", &asset->divx_max_key_interval);
370                 quicktime_set_parameter(fd, "divx_max_quantizer", &asset->divx_max_quantizer);
371                 quicktime_set_parameter(fd, "divx_min_quantizer", &asset->divx_min_quantizer);
372                 quicktime_set_parameter(fd, "divx_quantizer", &asset->divx_quantizer);
373                 quicktime_set_parameter(fd, "divx_quality", &asset->divx_quality);
374                 quicktime_set_parameter(fd, "divx_fix_bitrate", &asset->divx_fix_bitrate);
375
376 // printf("FileMOV::asset_to_format %d\n",
377 // __LINE__);
378 // asset->dump();
379                 quicktime_set_parameter(fd, "ffmpeg_bitrate", &asset->ms_bitrate);
380                 quicktime_set_parameter(fd, "ffmpeg_bitrate_tolerance", &asset->ms_bitrate_tolerance);
381                 quicktime_set_parameter(fd, "ffmpeg_interlaced", &asset->ms_interlaced);
382                 quicktime_set_parameter(fd, "ffmpeg_quantizer", &asset->ms_quantization);
383                 quicktime_set_parameter(fd, "ffmpeg_gop_size", &asset->ms_gop_size);
384                 quicktime_set_parameter(fd, "ffmpeg_fix_bitrate", &asset->ms_fix_bitrate);
385
386                 quicktime_set_parameter(fd, "h264_bitrate", &asset->h264_bitrate);
387                 quicktime_set_parameter(fd, "h264_quantizer", &asset->h264_quantizer);
388                 quicktime_set_parameter(fd, "h264_fix_bitrate", &asset->h264_fix_bitrate);
389
390
391         }
392
393         if(file->wr && asset->format == FILE_AVI)
394         {
395                 quicktime_set_avi(fd, 1);
396         }
397 }
398
399
400 void FileMOV::format_to_asset()
401 {
402         if(!fd) return;
403
404         if(quicktime_is_avi(fd)) asset->format = FILE_AVI;
405         asset->audio_data = quicktime_has_audio(fd);
406         if(asset->audio_data)
407         {
408                 asset->channels = 0;
409                 int qt_tracks = quicktime_audio_tracks(fd);
410                 for(int i = 0; i < qt_tracks; i++)
411                         asset->channels += quicktime_track_channels(fd, i);
412
413                 if(!asset->sample_rate)
414                         asset->sample_rate = quicktime_sample_rate(fd, 0);
415                 asset->bits = quicktime_audio_bits(fd, 0);
416                 asset->audio_length = quicktime_audio_length(fd, 0);
417                 strncpy(asset->acodec, quicktime_audio_compressor(fd, 0), 4);
418         }
419
420 // determine if the video can be read before declaring video data
421         if(quicktime_has_video(fd) && quicktime_supported_video(fd, 0))
422                         asset->video_data = 1;
423
424         if(asset->video_data)
425         {
426                 depth = quicktime_video_depth(fd, 0);
427                 asset->layers = quicktime_video_tracks(fd);
428                 asset->width = quicktime_video_width(fd, 0);
429                 asset->height = quicktime_video_height(fd, 0);
430                 asset->video_length = quicktime_video_length(fd, 0);
431 // Don't want a user configured frame rate to get destroyed
432                 if(EQUIV(asset->frame_rate, 0))
433                         asset->frame_rate = quicktime_frame_rate(fd, 0);
434
435                 strncpy(asset->vcodec, quicktime_video_compressor(fd, 0), 4);
436
437                 // If DV stream, get the timecode
438                 // This should become part of libquicktime functionality... for all formats
439                 if(match4(asset->vcodec, QUICKTIME_DV))
440                 {
441                         char tc[12];
442                         dv_decoder_t *tmp_decoder = dv_decoder_new(0,0,0);
443                         VFrame *frame = new VFrame(0, 0, BC_COMPRESSED);
444                         read_frame(frame);
445                         set_video_position(0);
446                         if(dv_parse_header(tmp_decoder, frame->get_data()) > -1)
447                         {
448                                 dv_parse_packs(tmp_decoder, frame->get_data());
449                                 dv_get_timestamp(tmp_decoder, tc);
450 //                              printf("Timestamp %s\n", tc);
451                         }
452                         delete frame;
453                         dv_decoder_free(tmp_decoder);
454                 }
455         }
456 }
457
458
459 int64_t FileMOV::get_memory_usage()
460 {
461         if(file->rd && fd)
462         {
463                 int64_t result = quicktime_memory_usage(fd);
464 //printf("FileMOV::get_memory_usage 1 %d\n", result);
465                 return result;
466         }
467         return 0;
468 }
469
470
471 int FileMOV::colormodel_supported(int colormodel)
472 {
473         return colormodel;
474 }
475
476 int FileMOV::get_best_colormodel(Asset *asset, int driver)
477 {
478         switch(driver)
479         {
480                 case PLAYBACK_X11:
481                         return BC_RGB888;
482                         break;
483                 case PLAYBACK_X11_XV:
484                 case PLAYBACK_ASYNCHRONOUS:
485                         if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
486                         if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422;
487                         if(match4(asset->vcodec, QUICKTIME_2VUY)) return BC_YUV422;
488                         if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
489                         if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
490                         if(match4(asset->vcodec, QUICKTIME_MJPG)) return BC_YUV422P;
491                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
492                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
493                         if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
494                         if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
495                         if(match4(asset->vcodec, QUICKTIME_DVCP)) return BC_YUV422;
496                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
497                         if(match4(asset->vcodec, QUICKTIME_MP4V)) return BC_YUV420P;
498                         if(match4(asset->vcodec, QUICKTIME_H263)) return BC_YUV420P;
499                         if(match4(asset->vcodec, QUICKTIME_H264)) return BC_YUV420P;
500                         if(match4(asset->vcodec, QUICKTIME_HV64)) return BC_YUV420P;
501                         if(match4(asset->vcodec, QUICKTIME_DIV3) ||
502                                 match4(asset->vcodec, QUICKTIME_SVQ3)) return BC_YUV420P;
503                         break;
504                 case PLAYBACK_X11_GL:
505                         if(match4(asset->vcodec, QUICKTIME_YUV420) ||
506                                 match4(asset->vcodec, QUICKTIME_YUV422) ||
507                                 match4(asset->vcodec, QUICKTIME_2VUY) ||
508                                 match4(asset->vcodec, QUICKTIME_JPEG) ||
509                                 match4(asset->vcodec, QUICKTIME_MJPA) ||
510                                 match4(asset->vcodec, QUICKTIME_MJPG) ||
511                                 match4(asset->vcodec, QUICKTIME_DV) ||
512                                 match4(asset->vcodec, QUICKTIME_DVCP) ||
513                                 match4(asset->vcodec, QUICKTIME_DVSD) ||
514                                 match4(asset->vcodec, QUICKTIME_HV60) ||
515                                 match4(asset->vcodec, QUICKTIME_DIVX) ||
516                                 match4(asset->vcodec, QUICKTIME_DVSD) ||
517                                 match4(asset->vcodec, QUICKTIME_MP4V) ||
518                                 match4(asset->vcodec, QUICKTIME_H263) ||
519                                 match4(asset->vcodec, QUICKTIME_H264) ||
520                                 match4(asset->vcodec, QUICKTIME_HV64) ||
521                                 match4(asset->vcodec, QUICKTIME_DIV3) ||
522                                 match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV888;
523                         break;
524                 case PLAYBACK_DV1394:
525                 case PLAYBACK_FIREWIRE:
526                         if(match4(asset->vcodec, QUICKTIME_DV) ||
527                                 match4(asset->vcodec, QUICKTIME_DVSD) ||
528                                 match4(asset->vcodec, QUICKTIME_DVCP)) return BC_COMPRESSED;
529                         return BC_YUV422P;
530                         break;
531                 case PLAYBACK_LML:
532                 case PLAYBACK_BUZ:
533                         if(match4(asset->vcodec, QUICKTIME_MJPA))
534                                 return BC_COMPRESSED;
535                         else
536                                 return BC_YUV422P;
537                         break;
538                 case VIDEO4LINUX:
539                 case VIDEO4LINUX2:
540                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
541                         else
542                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
543                         else
544                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
545                         else
546                         if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
547                         else
548                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
549                         else
550                         if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
551                         else
552                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
553                         else
554                         if(!strncasecmp(asset->vcodec, QUICKTIME_H263, 4)) return BC_YUV420P;
555                         else
556                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
557                         else
558                         if(!strncasecmp(asset->vcodec, QUICKTIME_MP4V, 4)) return BC_YUV422P;
559                         break;
560
561                 case CAPTURE_BUZ:
562                 case CAPTURE_LML:
563                 case VIDEO4LINUX2JPEG:
564                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4))
565                                 return BC_COMPRESSED;
566                         else
567                                 return BC_YUV422;
568                         break;
569
570                 case CAPTURE_JPEG_WEBCAM:
571                         return BC_COMPRESSED;
572                         break;
573
574                 case CAPTURE_YUYV_WEBCAM:
575                         return BC_YUV422;
576                         break;
577
578                 case CAPTURE_FIREWIRE:
579                 case CAPTURE_IEC61883:
580                         if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4) ||
581                                 !strncasecmp(asset->vcodec, QUICKTIME_DVSD, 4) ||
582                                 !strncasecmp(asset->vcodec, QUICKTIME_DVCP, 4))
583                                 return BC_COMPRESSED;
584                         else
585                                 return BC_YUV422;
586                         break;
587                 case CAPTURE_DVB:
588                 case VIDEO4LINUX2MPEG:
589                         return BC_YUV422P;
590                         break;
591         }
592         return BC_RGB888;
593 }
594
595 int FileMOV::can_copy_from(Edit *edit, int64_t position)
596 {
597         if(!fd) return 0;
598         Indexable *source = edit->get_source();
599         if( !source->is_asset ) return 0;
600         Asset *asset = (Asset *)source;
601
602 //printf("FileMOV::can_copy_from 1 %d %s %s\n", asset->format, asset->vcodec, this->asset->vcodec);
603         if(asset->format == FILE_JPEG_LIST &&
604                 match4(this->asset->vcodec, QUICKTIME_JPEG))
605                 return 1;
606         else
607         if((asset->format == FILE_MOV ||
608                 asset->format == FILE_AVI))
609         {
610 //printf("FileMOV::can_copy_from %s %s\n", asset->vcodec, this->asset->vcodec);
611                 if(match4(asset->vcodec, this->asset->vcodec))
612                         return 1;
613 // there are combinations where the same codec has multiple fourcc codes
614 // check for DV...
615                 int is_edit_dv = 0;
616                 int is_this_dv = 0;
617                 if (match4(asset->vcodec, QUICKTIME_DV) ||
618                         match4(asset->vcodec, QUICKTIME_DVSD) ||
619                         match4(asset->vcodec, QUICKTIME_DVCP))
620                         is_edit_dv = 1;
621                 if (match4(this->asset->vcodec, QUICKTIME_DV) ||
622                         match4(this->asset->vcodec, QUICKTIME_DVSD) ||
623                         match4(this->asset->vcodec, QUICKTIME_DVCP))
624                         is_this_dv = 1;
625                 if (is_this_dv && is_edit_dv)
626                         return 1;
627         }
628         else
629         if(edit->asset->format == FILE_RAWDV)
630         {
631                 if(match4(this->asset->vcodec, QUICKTIME_DV) ||
632                         match4(this->asset->vcodec, QUICKTIME_DVSD) ||
633                         match4(this->asset->vcodec, QUICKTIME_DVCP))
634                         return 1;
635         }
636
637         return 0;
638 }
639
640
641 int64_t FileMOV::get_audio_length()
642 {
643         if(!fd) return 0;
644         int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
645
646         return result;
647 }
648
649 int FileMOV::set_audio_position(int64_t x)
650 {
651         if(!fd) return 1;
652 // quicktime sets positions for each track seperately so store position in audio_position
653         if(x >= 0 && x < asset->audio_length)
654                 return quicktime_set_audio_position(fd, x, 0);
655         else
656                 return 1;
657 }
658
659 int FileMOV::set_video_position(int64_t x)
660 {
661         if(!fd) return 1;
662         if(x >= 0 && x < asset->video_length)
663         {
664                 int result = quicktime_set_video_position(fd, x, file->current_layer);
665                 return result;
666         }else
667                 return 1;
668 }
669
670
671 void FileMOV::new_audio_temp(int64_t len)
672 {
673         if(temp_allocated && temp_allocated < len)
674         {
675                 for(int i = 0; i < asset->channels; i++)
676                         delete [] temp_float[i];
677                 delete [] temp_float;
678                 temp_allocated = 0;
679         }
680
681         if(!temp_allocated)
682         {
683                 temp_allocated = len;
684                 temp_float = new float*[asset->channels];
685                 for(int i = 0; i < asset->channels; i++)
686                         temp_float[i] = new float[len];
687         }
688 }
689
690
691
692 int FileMOV::write_samples(double **buffer, int64_t len)
693 {
694         int i, j;
695         int result = 0;
696         int chunk_size;
697
698         if(!fd) return 0;
699
700         if(quicktime_supported_audio(fd, 0))
701         {
702 // Use Quicktime's compressor. (Always used)
703 // Allocate temp buffer
704                 new_audio_temp(len);
705
706 // Copy to float buffer
707                 for(i = 0; i < asset->channels; i++)
708                 {
709                         for(j = 0; j < len; j++)
710                         {
711                                 temp_float[i][j] = buffer[i][j];
712                         }
713                 }
714
715 // Because of the way Quicktime's compressors work we want to limit the chunk
716 // size to speed up decompression.
717                 float **channel_ptr;
718                 channel_ptr = new float*[asset->channels];
719
720                 for(j = 0; j < len && !result; )
721                 {
722                         chunk_size = asset->sample_rate;
723                         if(j + chunk_size > len) chunk_size = len - j;
724
725                         for(i = 0; i < asset->channels; i++)
726                         {
727                                 channel_ptr[i] = &temp_float[i][j];
728                         }
729
730                         result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
731                         j += asset->sample_rate;
732                 }
733
734                 delete [] channel_ptr;
735         }
736         return result;
737 }
738
739 int FileMOV::write_frames(VFrame ***frames, int len)
740 {
741         int i, j, result = 0;
742         int default_compressor = 1;
743         const int debug = 0;
744 if(debug) printf("FileMOV::write_frames %d\n", __LINE__);
745         if(!fd) return 0;
746 if(debug) printf("FileMOV::write_frames %d layers=%d\n", __LINE__, asset->layers);
747
748         for(i = 0; i < asset->layers && !result; i++)
749         {
750
751
752 if(debug) printf("FileMOV::write_frames %d colormodel=%d size=" _LD "\n",
753   __LINE__, frames[i][0]->get_color_model(), frames[i][0]->get_compressed_size());
754
755
756
757 // Fix direct copy cases for format conversions.
758                 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
759                 {
760 if(debug) printf("FileMOV::write_frames %d len=%d\n", __LINE__, len);
761                         default_compressor = 0;
762                         for(j = 0; j < len && !result; j++)
763                         {
764                                 VFrame *frame = frames[i][j];
765
766
767 if(debug) printf("FileMOV::write_frames %d %d colormodel=%d size=%d %02x %02x %02x %02x %02x %02x %02x %02x\n",
768 __LINE__,
769 frame->get_shmid(),
770 (int)frame->get_color_model(),
771 (int)frame->get_compressed_size(),
772 frames[i][j]->get_data()[0],
773 frames[i][j]->get_data()[1],
774 frames[i][j]->get_data()[2],
775 frames[i][j]->get_data()[3],
776 frames[i][j]->get_data()[4],
777 frames[i][j]->get_data()[5],
778 frames[i][j]->get_data()[6],
779 frames[i][j]->get_data()[7]);
780
781 // Special handling for DIVX
782 // Determine keyframe status.
783 // Write VOL header in the first frame if none exists
784                                 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
785                                         !strcmp(asset->vcodec, QUICKTIME_H263) ||
786                                         !strcmp(asset->vcodec, QUICKTIME_HV60))
787                                 {
788                                         if(quicktime_mpeg4_is_key(frame->get_data(),
789                                                 frame->get_compressed_size(),
790                                                 asset->vcodec))
791                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
792
793
794 // Write header
795                                         if(!(file->current_frame + j) &&
796                                                 !quicktime_mpeg4_has_vol(frame->get_data()))
797                                         {
798                                                 VFrame *temp_frame = new VFrame;
799
800                                                 temp_frame->allocate_compressed_data(frame->get_compressed_size() +
801                                                         0xff);
802                                                 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
803                                                         asset->width,
804                                                         asset->height,
805                                                         60000,
806                                                         asset->frame_rate);
807                                                 memcpy(temp_frame->get_data() + bytes,
808                                                         frame->get_data(),
809                                                         frame->get_compressed_size());
810                                                 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
811
812                                                 result = quicktime_write_frame(fd,
813                                                         temp_frame->get_data(),
814                                                         temp_frame->get_compressed_size(),
815                                                         i);
816
817                                                 delete temp_frame;
818
819
820                                         }
821                                         else
822                                         {
823                                                 result = quicktime_write_frame(fd,
824                                                         frame->get_data(),
825                                                         frame->get_compressed_size(),
826                                                         i);
827                                         }
828                                 }
829                                 else
830 // Determine keyframe status
831                                 if(!strcmp(asset->vcodec, QUICKTIME_H264) ||
832                                         !strcmp(asset->vcodec, QUICKTIME_HV64) ||
833                                         !strcmp(asset->vcodec, QUICKTIME_MP4V))
834                                 {
835                                         if(frame->get_keyframe() || file->current_frame + j == 0)
836                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
837
838 // Write frame
839 if(debug) printf("FileMOV::write_frames %d result=%d data=%p size=%ld\n",
840 __LINE__,
841 result,
842 frame->get_data(),
843 frame->get_compressed_size());
844                                                 result = quicktime_write_frame(fd,
845                                                         frame->get_data(),
846                                                         frame->get_compressed_size(),
847                                                         i);
848
849 if(debug) printf("FileMOV::write_frames %d result=%d\n", __LINE__, result);
850                                 }
851                                 else
852                                 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
853                                 {
854                                         if(quicktime_mpeg4_is_key(frame->get_data(),
855                                                 frame->get_compressed_size(),
856                                                 asset->vcodec))
857                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
858                                         result = quicktime_write_frame(fd,
859                                                 frame->get_data(),
860                                                 frame->get_compressed_size(),
861                                                 i);
862                                 }
863                                 else
864                                 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
865                                 {
866                                         long field2_offset;
867
868 // Create extra space for markers
869                                         if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
870                                                 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
871
872                                         unsigned char *data = frame->get_data();
873                                         long data_size = frame->get_compressed_size();
874                                         long data_allocated = frame->get_compressed_allocated();
875
876 // Sometimes get 0 length frames
877                                         if(data_size)
878                                         {
879                                                 if(asset->format == FILE_MOV)
880                                                 {
881                                                         mjpeg_insert_quicktime_markers(&data,
882                                                                 &data_size,
883                                                                 &data_allocated,
884                                                                 2,
885                                                                 &field2_offset);
886                                                 }
887                                                 else
888                                                 {
889                                                         mjpeg_insert_avi_markers(&data,
890                                                                 &data_size,
891                                                                 &data_allocated,
892                                                                 2,
893                                                                 &field2_offset);
894                                                 }
895                                                 frame->set_compressed_size(data_size);
896                                                 result = quicktime_write_frame(fd,
897                                                         frame->get_data(),
898                                                         frame->get_compressed_size(),
899                                                         i);
900                                         }
901                                         else
902                                                 printf("FileMOV::write_frames data_size=%ld\n", data_size);
903                                 }
904                                 else
905                                         result = quicktime_write_frame(fd,
906                                                 frame->get_data(),
907                                                 frame->get_compressed_size(),
908                                                 i);
909                         }
910 if(debug) printf("FileMOV::write_frames %d result=%d\n", __LINE__, result);
911                 }
912                 else
913                 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
914                         match4(asset->vcodec, QUICKTIME_2VUY) ||
915                         match4(asset->vcodec, QUICKTIME_YUV422) ||
916                         match4(asset->vcodec, QUICKTIME_RAW))
917                 {
918 // Direct copy planes where possible
919                         default_compressor = 0;
920                         for(j = 0; j < len && !result; j++)
921                         {
922                                 VFrame *frame = frames[i][j];
923 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
924                                 quicktime_set_cmodel(fd, frame->get_color_model());
925                                 if(cmodel_is_planar(frame->get_color_model()))
926                                 {
927                                         unsigned char *planes[3];
928                                         planes[0] = frame->get_y();
929                                         planes[1] = frame->get_u();
930                                         planes[2] = frame->get_v();
931                                         result = quicktime_encode_video(fd, planes, i);
932                                 }
933                                 else
934                                 {
935                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
936 //printf("FileMOV::write_frames 2 %d\n", result);
937                                 }
938 //printf("FileMOV::write_frames 2\n");
939                         }
940                 }
941                 else
942                 if(file->cpus > 1 &&
943                         (match4(asset->vcodec, QUICKTIME_JPEG) ||
944                         match4(asset->vcodec, QUICKTIME_MJPA)))
945                 {
946                         default_compressor = 0;
947 // Compress symmetrically on an SMP system.
948                         ThreadStruct *threadframe;
949                         int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
950
951 // Set up threads for symmetric compression.
952                         if(!threads)
953                         {
954                                 threads = new FileMOVThread*[file->cpus];
955                                 for(j = 0; j < file->cpus; j++)
956                                 {
957                                         threads[j] = new FileMOVThread(this, fields);
958                                         threads[j]->start_encoding();
959                                 }
960                         }
961
962 // Set up the frame structures for asynchronous compression.
963 // The mjpeg object must exist in each threadframe because it is where the output
964 // is stored.
965                         while(threadframes.total < len)
966                         {
967                                 threadframes.append(threadframe = new ThreadStruct);
968                         }
969
970 // Load thread frame structures with new frames.
971                         for(j = 0; j < len; j++)
972                         {
973                                 VFrame *frame = frames[i][j];
974                                 threadframes.values[j]->input = frame;
975                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
976                         }
977                         total_threadframes = len;
978                         current_threadframe = 0;
979
980 // Start the threads compressing
981                         for(j = 0; j < file->cpus; j++)
982                         {
983                                 threads[j]->encode_buffer();
984                         }
985
986
987 // Write the frames as they're finished
988                         for(j = 0; j < len; j++)
989                         {
990                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
991                                 threadframes.values[j]->completion_lock->unlock();
992                                 if(!result)
993                                 {
994                                         result = quicktime_write_frame(fd,
995                                                 threadframes.values[j]->output,
996                                                 threadframes.values[j]->output_size,
997                                                 i);
998                                 }
999                         }
1000                 }
1001
1002                 if(default_compressor)
1003                 {
1004 //printf("FileMOV::write_frames 3\n");
1005 // Use the library's built in compressor.
1006                         for(j = 0; j < len && !result; j++)
1007                         {
1008 //printf("FileMOV::write_frames 4\n");
1009                                 VFrame *frame = frames[i][j];
1010                                 quicktime_set_cmodel(fd, frame->get_color_model());
1011 //printf("FileMOV::write_frames 5\n");
1012                                 if(cmodel_is_planar(frame->get_color_model()))
1013                                 {
1014                                         unsigned char *planes[3];
1015                                         planes[0] = frame->get_y();
1016                                         planes[1] = frame->get_u();
1017                                         planes[2] = frame->get_v();
1018                                         result = quicktime_encode_video(fd, planes, i);
1019                                 }
1020                                 else
1021                                 {
1022 if(debug) printf("FileMOV::write_frames 1\n");
1023                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
1024 if(debug) printf("FileMOV::write_frames 10\n");
1025                                 }
1026                         }
1027                 }
1028 //printf("FileMOV::write_frames 4\n");
1029         }
1030
1031
1032         return result;
1033 }
1034
1035
1036
1037 int FileMOV::read_frame(VFrame *frame)
1038 {
1039         if(!fd) return 1;
1040         int result = 0;
1041         const int debug = 0;
1042
1043 if(debug) printf("FileMOV::read_frame %d frame=" _LD " color_model=%d\n",
1044   __LINE__, file->current_frame, frame->get_color_model());
1045         switch(frame->get_color_model())
1046         {
1047                 case BC_COMPRESSED:
1048                         frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
1049                         frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
1050                         frame->set_keyframe((quicktime_get_keyframe_before(fd,
1051                                 file->current_frame,
1052                                 file->current_layer) == file->current_frame));
1053 // printf("FileMOV::read_frame 1 " _LD " %d %p %d\n",
1054 // file->current_frame,
1055 // frame->get_keyframe(),
1056 // frame->get_data(),
1057 // frame->get_compressed_size());
1058                         result = quicktime_read_frame(fd,
1059                                 frame->get_data(),
1060                                 file->current_layer);
1061                         break;
1062
1063 // Progressive
1064                 case BC_YUV420P:
1065                 case BC_YUV422P:
1066                 {
1067                         unsigned char *row_pointers[3];
1068                         row_pointers[0] = frame->get_y();
1069                         row_pointers[1] = frame->get_u();
1070                         row_pointers[2] = frame->get_v();
1071
1072                         quicktime_set_cmodel(fd, frame->get_color_model());
1073                         result = quicktime_decode_video(fd,
1074                                 row_pointers,
1075                                 file->current_layer);
1076                 }
1077                 break;
1078
1079 // Packed
1080                 default:
1081                         quicktime_set_cmodel(fd, frame->get_color_model());
1082                         result = quicktime_decode_video(fd,
1083                                 frame->get_rows(),
1084                                 file->current_layer);
1085                         break;
1086         }
1087
1088
1089 if(debug) printf("FileMOV::read_frame %d\n", __LINE__);
1090         if (result)
1091                 printf("quicktime_read_frame/quicktime_decode_video failed, result:\n");
1092
1093         return result;
1094 }
1095
1096
1097
1098 int64_t FileMOV::compressed_frame_size()
1099 {
1100         if(!fd) return 0;
1101         return quicktime_frame_size(fd, file->current_frame, file->current_layer);
1102 }
1103
1104 int FileMOV::read_compressed_frame(VFrame *buffer)
1105 {
1106         int64_t result;
1107         if(!fd) return 0;
1108
1109         result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
1110         buffer->set_compressed_size(result);
1111         buffer->set_keyframe((quicktime_get_keyframe_before(fd,
1112                 file->current_frame,
1113                 file->current_layer) == file->current_frame));
1114         result = !result;
1115         return result;
1116 }
1117
1118 int FileMOV::write_compressed_frame(VFrame *buffer)
1119 {
1120         int result = 0;
1121         if(!fd) return 0;
1122
1123         result = quicktime_write_frame(fd,
1124                 buffer->get_data(),
1125                 buffer->get_compressed_size(),
1126                 file->current_layer);
1127         return result;
1128 }
1129
1130
1131
1132 int FileMOV::read_raw(VFrame *frame,
1133                 float in_x1, float in_y1, float in_x2, float in_y2,
1134                 float out_x1, float out_y1, float out_x2, float out_y2,
1135                 int use_float, int interpolate)
1136 {
1137         int64_t result = 1;
1138         if(!fd) return 1;
1139
1140         quicktime_set_video_position(fd, file->current_frame, file->current_layer);
1141 // Develop importing strategy
1142         switch(frame->get_color_model())
1143         {
1144                 case BC_RGB888:
1145                         result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
1146                         break;
1147                 case BC_RGBA8888:
1148                 case BC_RGB161616:
1149                 case BC_RGBA16161616:
1150                 case BC_YUV888:
1151                 case BC_YUVA8888:
1152                 case BC_YUV161616:
1153                 case BC_YUVA16161616:
1154                 case BC_YUV420P:
1155                         eprintf("FileMOV::read_raw: unknown colormodel\n");
1156                         break;
1157         }
1158         return result;
1159 }
1160
1161 // Overlay samples
1162 int FileMOV::read_samples(double *buffer, int64_t len)
1163 {
1164         if(!fd) return 1;
1165
1166         if(quicktime_track_channels(fd, 0) > file->current_channel &&
1167                 quicktime_supported_audio(fd, 0))
1168         {
1169
1170 //printf("FileMOV::read_samples 2 " _LD " " _LD "\n", file->current_sample, quicktime_audio_position(fd, 0));
1171                 new_audio_temp(len);
1172
1173 //printf("FileMOV::read_samples 3 " _LD " " _LD "\n", file->current_sample, quicktime_audio_position(fd, 0));
1174                 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
1175                 {
1176                         printf(_("quicktime_decode_audio failed\n"));
1177                         return 1;
1178                 }
1179                 else
1180                 {
1181                         for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
1182                 }
1183
1184 // if(file->current_channel == 0)
1185 // for(int i = 0; i < len; i++)
1186 // {
1187 //      int16_t value;
1188 //      value = (int16_t)(temp_float[0][i] * 32767);
1189 //      fwrite(&value, 2, 1, stdout);
1190 // }
1191 //printf("FileMOV::read_samples 4 " _LD " " _LD "\n", file->current_sample, quicktime_audio_position(fd, 0));
1192         }
1193
1194         return 0;
1195 }
1196
1197
1198 const char* FileMOV::strtocompression(const char *string)
1199 {
1200         if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
1201         if(!strcasecmp(string, _(H264_NAME))) return QUICKTIME_H264;
1202         if(!strcasecmp(string, _(HV64_NAME))) return QUICKTIME_HV64;
1203         if(!strcasecmp(string, _(MP4V_NAME))) return QUICKTIME_MP4V;
1204         if(!strcasecmp(string, _(H263_NAME))) return QUICKTIME_H263;
1205         if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
1206         if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
1207 // Students say QUICKTIME_DV is required for compression even though
1208 // QUICKTIME_DVSD is produced by other software
1209 //      if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DVSD;
1210         if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
1211         if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
1212         if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
1213         if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
1214         if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
1215         if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
1216         if(!strcasecmp(string, _(QTMJPEGP_NAME))) return QUICKTIME_MJPG;
1217         if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
1218         if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
1219         if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
1220         if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
1221         if(!strcasecmp(string, _(TWOVUY_NAME))) return QUICKTIME_2VUY;
1222         if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
1223         if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
1224         if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
1225
1226         if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
1227         if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
1228         if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
1229         if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
1230         if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
1231         if(!strcasecmp(string, _(MP4A_NAME))) return QUICKTIME_MP4A;
1232         if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
1233
1234
1235
1236         return QUICKTIME_RAW;
1237 }
1238
1239 const char* FileMOV::compressiontostr(const char *string)
1240 {
1241         if(match4(string, QUICKTIME_H263)) return _(H263_NAME);
1242         if(match4(string, QUICKTIME_H264)) return _(H264_NAME);
1243         if(match4(string, QUICKTIME_HV64)) return _(HV64_NAME);
1244         if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1245         if(match4(string, QUICKTIME_MP4V)) return _(MP4V_NAME);
1246         if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1247         if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1248         if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1249         if(match4(string, QUICKTIME_DVCP)) return _(DV_NAME);
1250         if(match4(string, QUICKTIME_DVSD)) return _(DV_NAME);
1251         if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1252         if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1253         if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1254         if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1255         if(match4(string, QUICKTIME_MJPG)) return _(QTMJPEGP_NAME);
1256         if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1257         if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1258         if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1259         if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1260         if(match4(string, QUICKTIME_2VUY)) return _(TWOVUY_NAME);
1261         if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1262         if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1263         if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1264
1265
1266
1267
1268
1269         if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1270         if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1271         if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1272         if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1273         if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1274         if(match4(string, QUICKTIME_MP4A)) return _(MP4A_NAME);
1275         if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1276
1277
1278
1279         return _("Unknown");
1280 }
1281
1282
1283
1284
1285
1286 ThreadStruct::ThreadStruct()
1287 {
1288         input = 0;
1289         output = 0;
1290         output_allocated = 0;
1291         output_size = 0;
1292         completion_lock = new Condition(1, "ThreadStruct::completion_lock");
1293 }
1294
1295 ThreadStruct::~ThreadStruct()
1296 {
1297         if(output) delete [] output;
1298         delete completion_lock;
1299 }
1300
1301 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1302 {
1303         if(output_allocated < mjpeg_output_size(mjpeg))
1304         {
1305                 delete [] output;
1306                 output = 0;
1307         }
1308         if(!output)
1309         {
1310                 output_allocated = mjpeg_output_size(mjpeg);
1311                 output = new unsigned char[output_allocated];
1312         }
1313
1314         output_size = mjpeg_output_size(mjpeg);
1315         memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1316 }
1317
1318
1319 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields)
1320  : Thread(1, 0, 0)
1321 {
1322         this->filemov = filemov;
1323         this->fields = fields;
1324         mjpeg = 0;
1325         input_lock = new Condition(1, "FileMOVThread::input_lock");
1326 }
1327
1328 FileMOVThread::~FileMOVThread()
1329 {
1330         delete input_lock;
1331 }
1332
1333 int FileMOVThread::start_encoding()
1334 {
1335         mjpeg = mjpeg_new(filemov->asset->width,
1336                 filemov->asset->height,
1337                 fields);
1338         mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1339         mjpeg_set_float(mjpeg, 0);
1340         done = 0;
1341         set_synchronous(1);
1342         input_lock->lock("FileMOVThread::start_encoding");
1343         start();
1344         return 0;
1345 }
1346
1347 int FileMOVThread::stop_encoding()
1348 {
1349         done = 1;
1350         input_lock->unlock();
1351         join();
1352         if(mjpeg) mjpeg_delete(mjpeg);
1353         return 0;
1354 }
1355
1356 int FileMOVThread::encode_buffer()
1357 {
1358         input_lock->unlock();
1359         return 0;
1360 }
1361
1362 void FileMOVThread::run()
1363 {
1364         while(!done)
1365         {
1366                 input_lock->lock("FileMOVThread::run");
1367
1368                 if(!done)
1369                 {
1370 // Get a frame to compress.
1371                         filemov->threadframe_lock->lock("FileMOVThread::stop_encoding");
1372                         if(filemov->current_threadframe < filemov->total_threadframes)
1373                         {
1374 // Frame is available to process.
1375                                 input_lock->unlock();
1376                                 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1377                                 VFrame *frame = threadframe->input;
1378
1379                                 filemov->current_threadframe++;
1380                                 filemov->threadframe_lock->unlock();
1381
1382                                 mjpeg_compress(mjpeg,
1383                                         frame->get_rows(),
1384                                         frame->get_y(),
1385                                         frame->get_u(),
1386                                         frame->get_v(),
1387                                         frame->get_color_model(),
1388                                         1);
1389
1390                                 if(fields > 1)
1391                                 {
1392                                         unsigned char *data = mjpeg_output_buffer(mjpeg);
1393                                         long data_size = mjpeg_output_size(mjpeg);
1394                                         long data_allocated = mjpeg_output_allocated(mjpeg);
1395                                         long field2_offset;
1396
1397                                         if(filemov->asset->format == FILE_MOV)
1398                                         {
1399                                                 mjpeg_insert_quicktime_markers(&data,
1400                                                         &data_size,
1401                                                         &data_allocated,
1402                                                         2,
1403                                                         &field2_offset);
1404                                         }
1405                                         else
1406                                         {
1407                                                 mjpeg_insert_avi_markers(&data,
1408                                                         &data_size,
1409                                                         &data_allocated,
1410                                                         2,
1411                                                         &field2_offset);
1412                                         }
1413                                         mjpeg_set_output_size(mjpeg, data_size);
1414                                 }
1415                                 threadframe->load_output(mjpeg);
1416                                 threadframe->completion_lock->unlock();
1417                         }
1418                         else
1419                                 filemov->threadframe_lock->unlock();
1420                 }
1421         }
1422 }
1423
1424
1425
1426
1427
1428
1429 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1430  : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
1431         parent_window->get_abs_cursor_x(1),
1432         parent_window->get_abs_cursor_y(1),
1433         350,
1434         250)
1435 {
1436         this->parent_window = parent_window;
1437         this->asset = asset;
1438         compression_popup = 0;
1439         reset();
1440 }
1441
1442 MOVConfigAudio::~MOVConfigAudio()
1443 {
1444         lock_window("MOVConfigAudio::~MOVConfigAudio");
1445         if(compression_popup) delete compression_popup;
1446         if(bits_popup) delete bits_popup;
1447         compression_items.remove_all_objects();
1448         unlock_window();
1449 }
1450
1451
1452 void MOVConfigAudio::reset()
1453 {
1454         bits_popup = 0;
1455         bits_title = 0;
1456         dither = 0;
1457         vorbis_min_bitrate = 0;
1458         vorbis_bitrate = 0;
1459         vorbis_max_bitrate = 0;
1460         vorbis_vbr = 0;
1461         mp3_bitrate = 0;
1462         mp4a_bitrate = 0;
1463         mp4a_quantqual = 0;
1464 }
1465
1466 void MOVConfigAudio::create_objects()
1467 {
1468         int x = 10, y = 10;
1469         lock_window("MOVConfigAudio::create_objects");
1470
1471         if(asset->format == FILE_MOV)
1472         {
1473                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1474                 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1475                 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1476                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1477                 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1478                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1479                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1480         }
1481         else
1482         {
1483                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1484                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1485                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1486                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1487         }
1488
1489         add_tool(new BC_Title(x, y, _("Compression:")));
1490         y += 25;
1491         compression_popup = new MOVConfigAudioPopup(this, x, y);
1492         compression_popup->create_objects();
1493
1494         update_parameters();
1495
1496         add_subwindow(new BC_OKButton(this));
1497         show_window(1);
1498         unlock_window();
1499 }
1500
1501 void MOVConfigAudio::update_parameters()
1502 {
1503         int x = 10, y = 70;
1504         if(bits_title) delete bits_title;
1505         if(bits_popup) delete bits_popup;
1506         if(dither) delete dither;
1507         if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1508         if(vorbis_bitrate) delete vorbis_bitrate;
1509         if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1510         if(vorbis_vbr) delete vorbis_vbr;
1511         if(mp3_bitrate) delete mp3_bitrate;
1512         delete mp4a_bitrate;
1513         delete mp4a_quantqual;
1514
1515         reset();
1516
1517
1518
1519         if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1520                 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1521         {
1522                 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1523                 bits_popup = new BitsPopup(this,
1524                         x + 150,
1525                         y,
1526                         &asset->bits,
1527                         0,
1528                         0,
1529                         0,
1530                         0,
1531                         0);
1532                 bits_popup->create_objects();
1533                 y += 40;
1534                 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1535         }
1536         else
1537         if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1538         {
1539         }
1540         else
1541         if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1542         {
1543                 mp3_bitrate = new MOVConfigAudioNum(this,
1544                         _("Bitrate:"),
1545                         x,
1546                         y,
1547                         &asset->mp3_bitrate);
1548                 mp3_bitrate->set_increment(64000);
1549                 mp3_bitrate->create_objects();
1550         }
1551         else
1552         if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1553         {
1554         }
1555         else
1556         if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1557         {
1558                 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1559                         _("Variable bitrate"),
1560                         x,
1561                         y,
1562                         &asset->vorbis_vbr));
1563                 y += 35;
1564                 vorbis_min_bitrate = new MOVConfigAudioNum(this,
1565                         _("Min bitrate:"),
1566                         x,
1567                         y,
1568                         &asset->vorbis_min_bitrate);
1569                 vorbis_min_bitrate->set_increment(1000);
1570                 y += 30;
1571                 vorbis_bitrate = new MOVConfigAudioNum(this,
1572                         _("Avg bitrate:"),
1573                         x,
1574                         y,
1575                         &asset->vorbis_bitrate);
1576                 vorbis_bitrate->set_increment(1000);
1577                 y += 30;
1578                 vorbis_max_bitrate = new MOVConfigAudioNum(this,
1579                         _("Max bitrate:"),
1580                         x,
1581                         y,
1582                         &asset->vorbis_max_bitrate);
1583                 vorbis_max_bitrate->set_increment(1000);
1584
1585
1586
1587                 vorbis_min_bitrate->create_objects();
1588                 vorbis_bitrate->create_objects();
1589                 vorbis_max_bitrate->create_objects();
1590         }
1591         else
1592         if(!strcasecmp(asset->acodec, QUICKTIME_MP4A))
1593         {
1594                 mp4a_bitrate = new MOVConfigAudioNum(this,
1595                         _("Bitrate:"),
1596                         x,
1597                         y,
1598                         &asset->mp4a_bitrate);
1599                 mp4a_bitrate->set_increment(64000);
1600                 mp4a_bitrate->create_objects();
1601
1602                 y += 30;
1603                 mp4a_quantqual = new MOVConfigAudioNum(this,
1604                         _("Quantization Quality (%):"),
1605                         x,
1606                         y,
1607                         &asset->mp4a_quantqual);
1608                 mp4a_quantqual->set_increment(1);
1609                 mp4a_quantqual->create_objects();
1610         }
1611         show_window(1);
1612 }
1613
1614 int MOVConfigAudio::close_event()
1615 {
1616         set_done(0);
1617         return 1;
1618 }
1619
1620
1621
1622
1623
1624 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1625         char *title_text,
1626         int x,
1627         int y,
1628         int *output)
1629  : BC_CheckBox(x, y, *output, title_text)
1630 {
1631         this->popup = popup;
1632         this->output = output;
1633 }
1634 int MOVConfigAudioToggle::handle_event()
1635 {
1636         *output = get_value();
1637         return 1;
1638 }
1639
1640
1641
1642
1643
1644 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1645  : BC_TumbleTextBox(popup,
1646                 (int64_t)*output,
1647                 (int64_t)-1,
1648                 (int64_t)25000000,
1649                 popup->get_w() - 150,
1650                 y,
1651                 100)
1652 {
1653         this->popup = popup;
1654         this->title_text = title_text;
1655         this->output = output;
1656         this->x = x;
1657         this->y = y;
1658 }
1659
1660 MOVConfigAudioNum::~MOVConfigAudioNum()
1661 {
1662         if(!popup->get_deleting()) delete title;
1663 }
1664
1665 void MOVConfigAudioNum::create_objects()
1666 {
1667         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1668         BC_TumbleTextBox::create_objects();
1669 }
1670
1671 int MOVConfigAudioNum::handle_event()
1672 {
1673         *output = atol(get_text());
1674         return 1;
1675 }
1676
1677
1678
1679
1680
1681
1682
1683
1684 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1685  : BC_PopupTextBox(popup,
1686                 &popup->compression_items,
1687                 FileMOV::compressiontostr(popup->asset->acodec),
1688                 x,
1689                 y,
1690                 300,
1691                 300)
1692 {
1693         this->popup = popup;
1694 }
1695
1696 int MOVConfigAudioPopup::handle_event()
1697 {
1698         strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1699         popup->update_parameters();
1700         return 1;
1701 }
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window,
1720         Asset *asset,
1721         const char *locked_compressor)
1722  : BC_Window(_(PROGRAM_NAME ": Video Compression"),
1723         parent_window->get_abs_cursor_x(1),
1724         parent_window->get_abs_cursor_y(1),
1725         420,
1726         420)
1727 {
1728         this->parent_window = parent_window;
1729         this->asset = asset;
1730         this->locked_compressor = locked_compressor;
1731         compression_popup = 0;
1732
1733         reset();
1734 }
1735
1736 MOVConfigVideo::~MOVConfigVideo()
1737 {
1738         lock_window("MOVConfigVideo::~MOVConfigVideo");
1739         if(compression_popup) delete compression_popup;
1740         compression_items.remove_all_objects();
1741         unlock_window();
1742 }
1743
1744 void MOVConfigVideo::create_objects()
1745 {
1746         int x = 10, y = 10;
1747         lock_window("MOVConfigVideo::create_objects");
1748
1749         if(asset->format == FILE_MOV)
1750         {
1751                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1752                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1753 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1754                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1755                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1756                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1757                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1758                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1759                 compression_items.append(new BC_ListBoxItem(_(QTMJPEGP_NAME)));
1760                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1761                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1762                 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1763                 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1764                 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1765                 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1766                 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1767                 compression_items.append(new BC_ListBoxItem(_(TWOVUY_NAME)));
1768                 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1769                 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1770                 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1771         }
1772         else
1773         {
1774                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1775                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1776 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1777                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1778                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1779                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1780                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1781                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1782                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1783                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1784         }
1785
1786         add_subwindow(new BC_Title(x, y, _("Compression:")));
1787         y += 25;
1788
1789         if(!locked_compressor)
1790         {
1791                 compression_popup = new MOVConfigVideoPopup(this, x, y);
1792                 compression_popup->create_objects();
1793         }
1794         else
1795         {
1796                 add_subwindow(new BC_Title(x,
1797                         y,
1798                         FileMOV::compressiontostr(locked_compressor),
1799                         MEDIUMFONT,
1800                         RED,
1801                         0));
1802         }
1803         y += 40;
1804
1805         param_x = x;
1806         param_y = y;
1807         update_parameters();
1808
1809         add_subwindow(new BC_OKButton(this));
1810         show_window(1);
1811         unlock_window();
1812 }
1813
1814 int MOVConfigVideo::close_event()
1815 {
1816         set_done(0);
1817         return 1;
1818 }
1819
1820
1821 void MOVConfigVideo::reset()
1822 {
1823         jpeg_quality = 0;
1824         jpeg_quality_title = 0;
1825
1826         divx_bitrate = 0;
1827         divx_rc_period = 0;
1828         divx_rc_reaction_ratio = 0;
1829         divx_rc_reaction_period = 0;
1830         divx_max_key_interval = 0;
1831         divx_max_quantizer = 0;
1832         divx_min_quantizer = 0;
1833         divx_quantizer = 0;
1834         divx_quality = 0;
1835         divx_fix_bitrate = 0;
1836         divx_fix_quant = 0;
1837
1838         h264_bitrate = 0;
1839         h264_quantizer = 0;
1840         h264_fix_bitrate = 0;
1841         h264_fix_quant = 0;
1842
1843         ms_bitrate = 0;
1844         ms_bitrate_tolerance = 0;
1845         ms_quantization = 0;
1846         ms_interlaced = 0;
1847         ms_gop_size = 0;
1848         ms_fix_bitrate = 0;
1849         ms_fix_quant = 0;
1850 }
1851
1852 void MOVConfigVideo::update_parameters()
1853 {
1854         if(jpeg_quality)
1855         {
1856                 delete jpeg_quality_title;
1857                 delete jpeg_quality;
1858         }
1859
1860         if(divx_bitrate) delete divx_bitrate;
1861         if(divx_rc_period) delete divx_rc_period;
1862         if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1863         if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1864         if(divx_max_key_interval) delete divx_max_key_interval;
1865         if(divx_max_quantizer) delete divx_max_quantizer;
1866         if(divx_min_quantizer) delete divx_min_quantizer;
1867         if(divx_quantizer) delete divx_quantizer;
1868         if(divx_quality) delete divx_quality;
1869         if(divx_fix_quant) delete divx_fix_quant;
1870         if(divx_fix_bitrate) delete divx_fix_bitrate;
1871
1872         if(ms_bitrate) delete ms_bitrate;
1873         if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1874         if(ms_interlaced) delete ms_interlaced;
1875         if(ms_quantization) delete ms_quantization;
1876         if(ms_gop_size) delete ms_gop_size;
1877         if(ms_fix_bitrate) delete ms_fix_bitrate;
1878         if(ms_fix_quant) delete ms_fix_quant;
1879
1880         delete h264_bitrate;
1881         delete h264_quantizer;
1882         delete h264_fix_bitrate;
1883         delete h264_fix_quant;
1884
1885         reset();
1886
1887
1888         const char *vcodec = asset->vcodec;
1889         if(locked_compressor) vcodec = locked_compressor;
1890
1891
1892 // H264 parameters
1893         if(!strcmp(vcodec, QUICKTIME_H264) ||
1894                 !strcmp(vcodec, QUICKTIME_HV64))
1895         {
1896                 int x = param_x, y = param_y;
1897                 h264_bitrate = new MOVConfigVideoNum(this,
1898                         _("Bitrate:"),
1899                         x,
1900                         y,
1901                         &asset->h264_bitrate);
1902                 h264_bitrate->set_increment(1000000);
1903                 h264_bitrate->create_objects();
1904                 add_subwindow(h264_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260,
1905                                 y,
1906                                 &asset->h264_fix_bitrate,
1907                                 1));
1908                 y += 30;
1909                 h264_quantizer = new MOVConfigVideoNum(this,
1910                         _("Quantization:"),
1911                         x,
1912                         y,
1913                         0,
1914                         51,
1915                         &asset->h264_quantizer);
1916                 h264_quantizer->create_objects();
1917                 add_subwindow(h264_fix_quant = new MOVConfigVideoFixQuant(x + 260,
1918                                 y,
1919                                 &asset->h264_fix_bitrate,
1920                                 0));
1921                 h264_fix_bitrate->opposite = h264_fix_quant;
1922                 h264_fix_quant->opposite = h264_fix_bitrate;
1923         }
1924         else
1925 // ffmpeg parameters
1926         if(!strcmp(vcodec, QUICKTIME_MP4V) ||
1927                 !strcmp(vcodec, QUICKTIME_DIV3))
1928         {
1929                 int x = param_x, y = param_y;
1930                 ms_bitrate = new MOVConfigVideoNum(this,
1931                         _("Bitrate:"),
1932                         x,
1933                         y,
1934                         &asset->ms_bitrate);
1935                 ms_bitrate->set_increment(1000000);
1936                 ms_bitrate->create_objects();
1937                 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260,
1938                                 y,
1939                                 &asset->ms_fix_bitrate,
1940                                 1));
1941                 y += 30;
1942
1943                 ms_bitrate_tolerance = new MOVConfigVideoNum(this,
1944                         _("Bitrate tolerance:"),
1945                         x,
1946                         y,
1947                         &asset->ms_bitrate_tolerance);
1948                 ms_bitrate_tolerance->create_objects();
1949                 y += 30;
1950
1951
1952
1953                 ms_quantization = new MOVConfigVideoNum(this,
1954                         _("Quantization:"),
1955                         x,
1956                         y,
1957                         &asset->ms_quantization);
1958                 ms_quantization->create_objects();
1959                 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260,
1960                                 y,
1961                                 &asset->ms_fix_bitrate,
1962                                 0));
1963                 ms_fix_bitrate->opposite = ms_fix_quant;
1964                 ms_fix_quant->opposite = ms_fix_bitrate;
1965
1966
1967                 y += 30;
1968                 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"),
1969                         x,
1970                         y,
1971                         &asset->ms_interlaced));
1972                 y += 30;
1973                 ms_gop_size = new MOVConfigVideoNum(this,
1974                         _("Keyframe interval:"),
1975                         x,
1976                         y,
1977                         &asset->ms_gop_size);
1978                 ms_gop_size->create_objects();
1979         }
1980         else
1981 // OpenDivx parameters
1982         if(!strcmp(vcodec, QUICKTIME_DIVX) ||
1983                 !strcmp(vcodec, QUICKTIME_H263) ||
1984                 !strcmp(vcodec, QUICKTIME_HV60))
1985         {
1986                 int x = param_x, y = param_y;
1987                 divx_bitrate = new MOVConfigVideoNum(this,
1988                         _("Bitrate:"),
1989                         x,
1990                         y,
1991                         &asset->divx_bitrate);
1992                 divx_bitrate->set_increment(1000000);
1993                 divx_bitrate->create_objects();
1994                 add_subwindow(divx_fix_bitrate =
1995                         new MOVConfigVideoFixBitrate(x + 260,
1996                                 y,
1997                                 &asset->divx_fix_bitrate,
1998                                 1));
1999                 y += 30;
2000                 divx_quantizer = new MOVConfigVideoNum(this,
2001                         _("Quantizer:"),
2002                         x,
2003                         y,
2004                         &asset->divx_quantizer);
2005                 divx_quantizer->create_objects();
2006                 add_subwindow(divx_fix_quant =
2007                         new MOVConfigVideoFixQuant(x + 260,
2008                                 y,
2009                                 &asset->divx_fix_bitrate,
2010                                 0));
2011                 divx_fix_quant->opposite = divx_fix_bitrate;
2012                 divx_fix_bitrate->opposite = divx_fix_quant;
2013                 y += 30;
2014                 divx_rc_period = new MOVConfigVideoNum(this,
2015                         _("RC Period:"),
2016                         x,
2017                         y,
2018                         &asset->divx_rc_period);
2019                 divx_rc_period->create_objects();
2020                 y += 30;
2021                 divx_rc_reaction_ratio = new MOVConfigVideoNum(this,
2022                         _("Reaction Ratio:"),
2023                         x,
2024                         y,
2025                         &asset->divx_rc_reaction_ratio);
2026                 divx_rc_reaction_ratio->create_objects();
2027                 y += 30;
2028                 divx_rc_reaction_period = new MOVConfigVideoNum(this,
2029                         _("Reaction Period:"),
2030                         x,
2031                         y,
2032                         &asset->divx_rc_reaction_period);
2033                 divx_rc_reaction_period->create_objects();
2034                 y += 30;
2035                 divx_max_key_interval = new MOVConfigVideoNum(this,
2036                         _("Max Key Interval:"),
2037                         x,
2038                         y,
2039                         &asset->divx_max_key_interval);
2040                 divx_max_key_interval->create_objects();
2041                 y += 30;
2042                 divx_max_quantizer = new MOVConfigVideoNum(this,
2043                         _("Max Quantizer:"),
2044                         x,
2045                         y,
2046                         &asset->divx_max_quantizer);
2047                 divx_max_quantizer->create_objects();
2048                 y += 30;
2049                 divx_min_quantizer = new MOVConfigVideoNum(this,
2050                         _("Min Quantizer:"),
2051                         x,
2052                         y,
2053                         &asset->divx_min_quantizer);
2054                 divx_min_quantizer->create_objects();
2055                 y += 30;
2056                 divx_quality = new MOVConfigVideoNum(this,
2057                         _("Quality:"),
2058                         x,
2059                         y,
2060                         &asset->divx_quality);
2061                 divx_quality->create_objects();
2062         }
2063         else
2064         if(!strcmp(vcodec, QUICKTIME_JPEG) ||
2065                 !strcmp(vcodec, QUICKTIME_MJPA))
2066         {
2067                 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
2068                 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80,
2069                         param_y,
2070                         0,
2071                         200,
2072                         200,
2073                         0,
2074                         100,
2075                         asset->jpeg_quality,
2076                         0,
2077                         0,
2078                         &asset->jpeg_quality));
2079         }
2080         show_window(1);
2081 }
2082
2083
2084
2085
2086
2087 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
2088  : BC_TumbleTextBox(popup,
2089                 (int64_t)*output,
2090                 (int64_t)1,
2091                 (int64_t)25000000,
2092                 x + 130,
2093                 y,
2094                 100)
2095 {
2096         this->popup = popup;
2097         this->title_text = title_text;
2098         this->output = output;
2099         this->x = x;
2100         this->y = y;
2101 }
2102
2103 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup,
2104         char *title_text,
2105         int x,
2106         int y,
2107         int min,
2108         int max,
2109         int *output)
2110  : BC_TumbleTextBox(popup,
2111                 (int64_t)*output,
2112                 (int64_t)min,
2113                 (int64_t)max,
2114                 x + 130,
2115                 y,
2116                 100)
2117 {
2118         this->popup = popup;
2119         this->title_text = title_text;
2120         this->output = output;
2121         this->x = x;
2122         this->y = y;
2123 }
2124
2125 MOVConfigVideoNum::~MOVConfigVideoNum()
2126 {
2127         if(!popup->get_deleting()) delete title;
2128 }
2129
2130 void MOVConfigVideoNum::create_objects()
2131 {
2132         popup->add_subwindow(title = new BC_Title(x, y, title_text));
2133         BC_TumbleTextBox::create_objects();
2134 }
2135
2136 int MOVConfigVideoNum::handle_event()
2137 {
2138         *output = atol(get_text());
2139         return 1;
2140 }
2141
2142
2143
2144
2145
2146
2147
2148 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
2149  : BC_CheckBox(x, y, *output, title_text)
2150 {
2151         this->output = output;
2152 }
2153
2154 int MOVConfigVideoCheckBox::handle_event()
2155 {
2156         *output = get_value();
2157         return 1;
2158 }
2159
2160
2161
2162
2163
2164
2165 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x,
2166         int y,
2167         int *output,
2168         int value)
2169  : BC_Radial(x,
2170         y,
2171         *output == value,
2172         _("Fix bitrate"))
2173 {
2174         this->output = output;
2175         this->value = value;
2176 }
2177
2178 int MOVConfigVideoFixBitrate::handle_event()
2179 {
2180         *output = value;
2181         opposite->update(0);
2182         return 1;
2183 }
2184
2185
2186
2187
2188
2189
2190 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x,
2191         int y,
2192         int *output,
2193         int value)
2194  : BC_Radial(x,
2195         y,
2196         *output == value,
2197         _("Fix quantization"))
2198 {
2199         this->output = output;
2200         this->value = value;
2201 }
2202
2203 int MOVConfigVideoFixQuant::handle_event()
2204 {
2205         *output = value;
2206         opposite->update(0);
2207         return 1;
2208 }
2209
2210
2211
2212
2213
2214 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
2215  : BC_PopupTextBox(popup,
2216                 &popup->compression_items,
2217                 FileMOV::compressiontostr(popup->asset->vcodec),
2218                 x,
2219                 y,
2220                 300,
2221                 300)
2222 {
2223         this->popup = popup;
2224 }
2225
2226 int MOVConfigVideoPopup::handle_event()
2227 {
2228         strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
2229         popup->update_parameters();
2230         return 1;
2231 }
2232
2233
2234
2235
2236
2237
2238
2239
2240