initial commit
[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, asset->tcstart);
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                                 float seconds = Units::text_to_seconds(tc,
453                                         1, // Use 1 as sample rate, doesn't matter
454                                         TIME_HMSF, asset->frame_rate, 0);
455                                 // Set tcstart if it hasn't been set yet, this is a bit problematic
456                                 // FIXME: The problem arises if file has nonzero tcstart and user
457                                 // manualy sets it to zero - every time project will load it will
458                                 // be set to nonzero
459                                 if (asset->tcstart == 0)
460                                         asset->tcstart = int64_t(seconds * asset->frame_rate);
461                         }
462                         delete frame;
463                         dv_decoder_free(tmp_decoder);
464                 }
465         }
466 }
467
468
469 int64_t FileMOV::get_memory_usage()
470 {
471         if(file->rd && fd)
472         {
473                 int64_t result = quicktime_memory_usage(fd);
474 //printf("FileMOV::get_memory_usage 1 %d\n", result);
475                 return result;
476         }
477         return 0;
478 }
479
480
481 int FileMOV::colormodel_supported(int colormodel)
482 {
483         return colormodel;
484 }
485
486 int FileMOV::get_best_colormodel(Asset *asset, int driver)
487 {
488         switch(driver)
489         {
490                 case PLAYBACK_X11:
491                         return BC_RGB888;
492                         break;
493                 case PLAYBACK_X11_XV:
494                 case PLAYBACK_ASYNCHRONOUS:
495                         if(match4(asset->vcodec, QUICKTIME_YUV420)) return BC_YUV420P;
496                         if(match4(asset->vcodec, QUICKTIME_YUV422)) return BC_YUV422;
497                         if(match4(asset->vcodec, QUICKTIME_2VUY)) return BC_YUV422;
498                         if(match4(asset->vcodec, QUICKTIME_JPEG)) return BC_YUV420P;
499                         if(match4(asset->vcodec, QUICKTIME_MJPA)) return BC_YUV422P;
500                         if(match4(asset->vcodec, QUICKTIME_MJPG)) return BC_YUV422P;
501                         if(match4(asset->vcodec, QUICKTIME_DV)) return BC_YUV422;
502                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
503                         if(match4(asset->vcodec, QUICKTIME_HV60)) return BC_YUV420P;
504                         if(match4(asset->vcodec, QUICKTIME_DIVX)) return BC_YUV420P;
505                         if(match4(asset->vcodec, QUICKTIME_DVCP)) return BC_YUV422;
506                         if(match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV422;
507                         if(match4(asset->vcodec, QUICKTIME_MP4V)) return BC_YUV420P;
508                         if(match4(asset->vcodec, QUICKTIME_H263)) return BC_YUV420P;
509                         if(match4(asset->vcodec, QUICKTIME_H264)) return BC_YUV420P;
510                         if(match4(asset->vcodec, QUICKTIME_HV64)) return BC_YUV420P;
511                         if(match4(asset->vcodec, QUICKTIME_DIV3) ||
512                                 match4(asset->vcodec, QUICKTIME_SVQ3)) return BC_YUV420P;
513                         break;
514                 case PLAYBACK_X11_GL:
515                         if(match4(asset->vcodec, QUICKTIME_YUV420) ||
516                                 match4(asset->vcodec, QUICKTIME_YUV422) ||
517                                 match4(asset->vcodec, QUICKTIME_2VUY) ||
518                                 match4(asset->vcodec, QUICKTIME_JPEG) ||
519                                 match4(asset->vcodec, QUICKTIME_MJPA) ||
520                                 match4(asset->vcodec, QUICKTIME_MJPG) ||
521                                 match4(asset->vcodec, QUICKTIME_DV) ||
522                                 match4(asset->vcodec, QUICKTIME_DVCP) ||
523                                 match4(asset->vcodec, QUICKTIME_DVSD) ||
524                                 match4(asset->vcodec, QUICKTIME_HV60) ||
525                                 match4(asset->vcodec, QUICKTIME_DIVX) ||
526                                 match4(asset->vcodec, QUICKTIME_DVSD) ||
527                                 match4(asset->vcodec, QUICKTIME_MP4V) ||
528                                 match4(asset->vcodec, QUICKTIME_H263) ||
529                                 match4(asset->vcodec, QUICKTIME_H264) ||
530                                 match4(asset->vcodec, QUICKTIME_HV64) ||
531                                 match4(asset->vcodec, QUICKTIME_DIV3) ||
532                                 match4(asset->vcodec, QUICKTIME_DVSD)) return BC_YUV888;
533                         break;
534                 case PLAYBACK_DV1394:
535                 case PLAYBACK_FIREWIRE:
536                         if(match4(asset->vcodec, QUICKTIME_DV) ||
537                                 match4(asset->vcodec, QUICKTIME_DVSD) ||
538                                 match4(asset->vcodec, QUICKTIME_DVCP)) return BC_COMPRESSED;
539                         return BC_YUV422P;
540                         break;
541                 case PLAYBACK_LML:
542                 case PLAYBACK_BUZ:
543                         if(match4(asset->vcodec, QUICKTIME_MJPA))
544                                 return BC_COMPRESSED;
545                         else
546                                 return BC_YUV422P;
547                         break;
548                 case VIDEO4LINUX:
549                 case VIDEO4LINUX2:
550                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV420, 4)) return BC_YUV422;
551                         else
552                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV422, 4)) return BC_YUV422;
553                         else
554                         if(!strncasecmp(asset->vcodec, QUICKTIME_YUV411, 4)) return BC_YUV411P;
555                         else
556                         if(!strncasecmp(asset->vcodec, QUICKTIME_JPEG, 4)) return BC_YUV420P;
557                         else
558                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4)) return BC_YUV422P;
559                         else
560                         if(!strncasecmp(asset->vcodec, QUICKTIME_HV60, 4)) return BC_YUV420P;
561                         else
562                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIVX, 4)) return BC_YUV420P;
563                         else
564                         if(!strncasecmp(asset->vcodec, QUICKTIME_H263, 4)) return BC_YUV420P;
565                         else
566                         if(!strncasecmp(asset->vcodec, QUICKTIME_DIV3, 4)) return BC_YUV420P;
567                         else
568                         if(!strncasecmp(asset->vcodec, QUICKTIME_MP4V, 4)) return BC_YUV422P;
569                         break;
570
571                 case CAPTURE_BUZ:
572                 case CAPTURE_LML:
573                 case VIDEO4LINUX2JPEG:
574                         if(!strncasecmp(asset->vcodec, QUICKTIME_MJPA, 4))
575                                 return BC_COMPRESSED;
576                         else
577                                 return BC_YUV422;
578                         break;
579
580                 case CAPTURE_JPEG_WEBCAM:
581                         return BC_COMPRESSED;
582                         break;
583
584                 case CAPTURE_YUYV_WEBCAM:
585                         return BC_YUV422;
586                         break;
587
588                 case CAPTURE_FIREWIRE:
589                 case CAPTURE_IEC61883:
590                         if(!strncasecmp(asset->vcodec, QUICKTIME_DV, 4) ||
591                                 !strncasecmp(asset->vcodec, QUICKTIME_DVSD, 4) ||
592                                 !strncasecmp(asset->vcodec, QUICKTIME_DVCP, 4))
593                                 return BC_COMPRESSED;
594                         else
595                                 return BC_YUV422;
596                         break;
597                 case CAPTURE_DVB:
598                 case VIDEO4LINUX2MPEG:
599                         return BC_YUV422P;
600                         break;
601         }
602         return BC_RGB888;
603 }
604
605 int FileMOV::can_copy_from(Edit *edit, int64_t position)
606 {
607         if(!fd) return 0;
608         Indexable *source = edit->get_source();
609         if( !source->is_asset ) return 0;
610         Asset *asset = (Asset *)source;
611
612 //printf("FileMOV::can_copy_from 1 %d %s %s\n", asset->format, asset->vcodec, this->asset->vcodec);
613         if(asset->format == FILE_JPEG_LIST &&
614                 match4(this->asset->vcodec, QUICKTIME_JPEG))
615                 return 1;
616         else
617         if((asset->format == FILE_MOV ||
618                 asset->format == FILE_AVI))
619         {
620 //printf("FileMOV::can_copy_from %s %s\n", asset->vcodec, this->asset->vcodec);
621                 if(match4(asset->vcodec, this->asset->vcodec))
622                         return 1;
623 // there are combinations where the same codec has multiple fourcc codes
624 // check for DV...
625                 int is_edit_dv = 0;
626                 int is_this_dv = 0;
627                 if (match4(asset->vcodec, QUICKTIME_DV) ||
628                         match4(asset->vcodec, QUICKTIME_DVSD) ||
629                         match4(asset->vcodec, QUICKTIME_DVCP))
630                         is_edit_dv = 1;
631                 if (match4(this->asset->vcodec, QUICKTIME_DV) ||
632                         match4(this->asset->vcodec, QUICKTIME_DVSD) ||
633                         match4(this->asset->vcodec, QUICKTIME_DVCP))
634                         is_this_dv = 1;
635                 if (is_this_dv && is_edit_dv)
636                         return 1;
637         }
638         else
639         if(edit->asset->format == FILE_RAWDV)
640         {
641                 if(match4(this->asset->vcodec, QUICKTIME_DV) ||
642                         match4(this->asset->vcodec, QUICKTIME_DVSD) ||
643                         match4(this->asset->vcodec, QUICKTIME_DVCP))
644                         return 1;
645         }
646
647         return 0;
648 }
649
650
651 int64_t FileMOV::get_audio_length()
652 {
653         if(!fd) return 0;
654         int64_t result = quicktime_audio_length(fd, 0) + samples_correction;
655
656         return result;
657 }
658
659 int FileMOV::set_audio_position(int64_t x)
660 {
661         if(!fd) return 1;
662 // quicktime sets positions for each track seperately so store position in audio_position
663         if(x >= 0 && x < asset->audio_length)
664                 return quicktime_set_audio_position(fd, x, 0);
665         else
666                 return 1;
667 }
668
669 int FileMOV::set_video_position(int64_t x)
670 {
671         if(!fd) return 1;
672         if(x >= 0 && x < asset->video_length)
673         {
674                 int result = quicktime_set_video_position(fd, x, file->current_layer);
675                 return result;
676         }else
677                 return 1;
678 }
679
680
681 void FileMOV::new_audio_temp(int64_t len)
682 {
683         if(temp_allocated && temp_allocated < len)
684         {
685                 for(int i = 0; i < asset->channels; i++)
686                         delete [] temp_float[i];
687                 delete [] temp_float;
688                 temp_allocated = 0;
689         }
690
691         if(!temp_allocated)
692         {
693                 temp_allocated = len;
694                 temp_float = new float*[asset->channels];
695                 for(int i = 0; i < asset->channels; i++)
696                         temp_float[i] = new float[len];
697         }
698 }
699
700
701
702 int FileMOV::write_samples(double **buffer, int64_t len)
703 {
704         int i, j;
705         int result = 0;
706         int chunk_size;
707
708         if(!fd) return 0;
709
710         if(quicktime_supported_audio(fd, 0))
711         {
712 // Use Quicktime's compressor. (Always used)
713 // Allocate temp buffer
714                 new_audio_temp(len);
715
716 // Copy to float buffer
717                 for(i = 0; i < asset->channels; i++)
718                 {
719                         for(j = 0; j < len; j++)
720                         {
721                                 temp_float[i][j] = buffer[i][j];
722                         }
723                 }
724
725 // Because of the way Quicktime's compressors work we want to limit the chunk
726 // size to speed up decompression.
727                 float **channel_ptr;
728                 channel_ptr = new float*[asset->channels];
729
730                 for(j = 0; j < len && !result; )
731                 {
732                         chunk_size = asset->sample_rate;
733                         if(j + chunk_size > len) chunk_size = len - j;
734
735                         for(i = 0; i < asset->channels; i++)
736                         {
737                                 channel_ptr[i] = &temp_float[i][j];
738                         }
739
740                         result = quicktime_encode_audio(fd, 0, channel_ptr, chunk_size);
741                         j += asset->sample_rate;
742                 }
743
744                 delete [] channel_ptr;
745         }
746         return result;
747 }
748
749 int FileMOV::write_frames(VFrame ***frames, int len)
750 {
751         int i, j, result = 0;
752         int default_compressor = 1;
753         const int debug = 0;
754 if(debug) printf("FileMOV::write_frames %d\n", __LINE__);
755         if(!fd) return 0;
756 if(debug) printf("FileMOV::write_frames %d layers=%d\n", __LINE__, asset->layers);
757
758         for(i = 0; i < asset->layers && !result; i++)
759         {
760
761
762 if(debug) printf("FileMOV::write_frames %d colormodel=%d size=" _LD "\n",
763   __LINE__, frames[i][0]->get_color_model(), frames[i][0]->get_compressed_size());
764
765
766
767 // Fix direct copy cases for format conversions.
768                 if(frames[i][0]->get_color_model() == BC_COMPRESSED)
769                 {
770 if(debug) printf("FileMOV::write_frames %d len=%d\n", __LINE__, len);
771                         default_compressor = 0;
772                         for(j = 0; j < len && !result; j++)
773                         {
774                                 VFrame *frame = frames[i][j];
775
776
777 if(debug) printf("FileMOV::write_frames %d %d colormodel=%d size=%d %02x %02x %02x %02x %02x %02x %02x %02x\n",
778 __LINE__,
779 frame->get_shmid(),
780 (int)frame->get_color_model(),
781 (int)frame->get_compressed_size(),
782 frames[i][j]->get_data()[0],
783 frames[i][j]->get_data()[1],
784 frames[i][j]->get_data()[2],
785 frames[i][j]->get_data()[3],
786 frames[i][j]->get_data()[4],
787 frames[i][j]->get_data()[5],
788 frames[i][j]->get_data()[6],
789 frames[i][j]->get_data()[7]);
790
791 // Special handling for DIVX
792 // Determine keyframe status.
793 // Write VOL header in the first frame if none exists
794                                 if(!strcmp(asset->vcodec, QUICKTIME_DIVX) ||
795                                         !strcmp(asset->vcodec, QUICKTIME_H263) ||
796                                         !strcmp(asset->vcodec, QUICKTIME_HV60))
797                                 {
798                                         if(quicktime_mpeg4_is_key(frame->get_data(),
799                                                 frame->get_compressed_size(),
800                                                 asset->vcodec))
801                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
802
803
804 // Write header
805                                         if(!(file->current_frame + j) &&
806                                                 !quicktime_mpeg4_has_vol(frame->get_data()))
807                                         {
808                                                 VFrame *temp_frame = new VFrame;
809
810                                                 temp_frame->allocate_compressed_data(frame->get_compressed_size() +
811                                                         0xff);
812                                                 int bytes = quicktime_mpeg4_write_vol(temp_frame->get_data(),
813                                                         asset->width,
814                                                         asset->height,
815                                                         60000,
816                                                         asset->frame_rate);
817                                                 memcpy(temp_frame->get_data() + bytes,
818                                                         frame->get_data(),
819                                                         frame->get_compressed_size());
820                                                 temp_frame->set_compressed_size(frame->get_compressed_size() + bytes);
821
822                                                 result = quicktime_write_frame(fd,
823                                                         temp_frame->get_data(),
824                                                         temp_frame->get_compressed_size(),
825                                                         i);
826
827                                                 delete temp_frame;
828
829
830                                         }
831                                         else
832                                         {
833                                                 result = quicktime_write_frame(fd,
834                                                         frame->get_data(),
835                                                         frame->get_compressed_size(),
836                                                         i);
837                                         }
838                                 }
839                                 else
840 // Determine keyframe status
841                                 if(!strcmp(asset->vcodec, QUICKTIME_H264) ||
842                                         !strcmp(asset->vcodec, QUICKTIME_HV64) ||
843                                         !strcmp(asset->vcodec, QUICKTIME_MP4V))
844                                 {
845                                         if(frame->get_keyframe() || file->current_frame + j == 0)
846                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
847
848 // Write frame
849 if(debug) printf("FileMOV::write_frames %d result=%d data=%p size=%ld\n",
850 __LINE__,
851 result,
852 frame->get_data(),
853 frame->get_compressed_size());
854                                                 result = quicktime_write_frame(fd,
855                                                         frame->get_data(),
856                                                         frame->get_compressed_size(),
857                                                         i);
858
859 if(debug) printf("FileMOV::write_frames %d result=%d\n", __LINE__, result);
860                                 }
861                                 else
862                                 if(!strcmp(asset->vcodec, QUICKTIME_DIV3))
863                                 {
864                                         if(quicktime_mpeg4_is_key(frame->get_data(),
865                                                 frame->get_compressed_size(),
866                                                 asset->vcodec))
867                                                 quicktime_insert_keyframe(fd, file->current_frame + j, i);
868                                         result = quicktime_write_frame(fd,
869                                                 frame->get_data(),
870                                                 frame->get_compressed_size(),
871                                                 i);
872                                 }
873                                 else
874                                 if(!strcmp(asset->vcodec, QUICKTIME_MJPA))
875                                 {
876                                         long field2_offset;
877
878 // Create extra space for markers
879                                         if(frame->get_compressed_allocated() - frame->get_compressed_size() < 0x100)
880                                                 frame->allocate_compressed_data(frame->get_compressed_size() + 0x100);
881
882                                         unsigned char *data = frame->get_data();
883                                         long data_size = frame->get_compressed_size();
884                                         long data_allocated = frame->get_compressed_allocated();
885
886 // Sometimes get 0 length frames
887                                         if(data_size)
888                                         {
889                                                 if(asset->format == FILE_MOV)
890                                                 {
891                                                         mjpeg_insert_quicktime_markers(&data,
892                                                                 &data_size,
893                                                                 &data_allocated,
894                                                                 2,
895                                                                 &field2_offset);
896                                                 }
897                                                 else
898                                                 {
899                                                         mjpeg_insert_avi_markers(&data,
900                                                                 &data_size,
901                                                                 &data_allocated,
902                                                                 2,
903                                                                 &field2_offset);
904                                                 }
905                                                 frame->set_compressed_size(data_size);
906                                                 result = quicktime_write_frame(fd,
907                                                         frame->get_data(),
908                                                         frame->get_compressed_size(),
909                                                         i);
910                                         }
911                                         else
912                                                 printf("FileMOV::write_frames data_size=%ld\n", data_size);
913                                 }
914                                 else
915                                         result = quicktime_write_frame(fd,
916                                                 frame->get_data(),
917                                                 frame->get_compressed_size(),
918                                                 i);
919                         }
920 if(debug) printf("FileMOV::write_frames %d result=%d\n", __LINE__, result);
921                 }
922                 else
923                 if(match4(asset->vcodec, QUICKTIME_YUV420) ||
924                         match4(asset->vcodec, QUICKTIME_2VUY) ||
925                         match4(asset->vcodec, QUICKTIME_YUV422) ||
926                         match4(asset->vcodec, QUICKTIME_RAW))
927                 {
928 // Direct copy planes where possible
929                         default_compressor = 0;
930                         for(j = 0; j < len && !result; j++)
931                         {
932                                 VFrame *frame = frames[i][j];
933 //printf("FileMOV::write_frames 1 %d\n", frame->get_color_model());
934                                 quicktime_set_cmodel(fd, frame->get_color_model());
935                                 if(cmodel_is_planar(frame->get_color_model()))
936                                 {
937                                         unsigned char *planes[3];
938                                         planes[0] = frame->get_y();
939                                         planes[1] = frame->get_u();
940                                         planes[2] = frame->get_v();
941                                         result = quicktime_encode_video(fd, planes, i);
942                                 }
943                                 else
944                                 {
945                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
946 //printf("FileMOV::write_frames 2 %d\n", result);
947                                 }
948 //printf("FileMOV::write_frames 2\n");
949                         }
950                 }
951                 else
952                 if(file->cpus > 1 &&
953                         (match4(asset->vcodec, QUICKTIME_JPEG) ||
954                         match4(asset->vcodec, QUICKTIME_MJPA)))
955                 {
956                         default_compressor = 0;
957 // Compress symmetrically on an SMP system.
958                         ThreadStruct *threadframe;
959                         int fields = match4(asset->vcodec, QUICKTIME_MJPA) ? 2 : 1;
960
961 // Set up threads for symmetric compression.
962                         if(!threads)
963                         {
964                                 threads = new FileMOVThread*[file->cpus];
965                                 for(j = 0; j < file->cpus; j++)
966                                 {
967                                         threads[j] = new FileMOVThread(this, fields);
968                                         threads[j]->start_encoding();
969                                 }
970                         }
971
972 // Set up the frame structures for asynchronous compression.
973 // The mjpeg object must exist in each threadframe because it is where the output
974 // is stored.
975                         while(threadframes.total < len)
976                         {
977                                 threadframes.append(threadframe = new ThreadStruct);
978                         }
979
980 // Load thread frame structures with new frames.
981                         for(j = 0; j < len; j++)
982                         {
983                                 VFrame *frame = frames[i][j];
984                                 threadframes.values[j]->input = frame;
985                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
986                         }
987                         total_threadframes = len;
988                         current_threadframe = 0;
989
990 // Start the threads compressing
991                         for(j = 0; j < file->cpus; j++)
992                         {
993                                 threads[j]->encode_buffer();
994                         }
995
996
997 // Write the frames as they're finished
998                         for(j = 0; j < len; j++)
999                         {
1000                                 threadframes.values[j]->completion_lock->lock("FileMOV::write_frames 1");
1001                                 threadframes.values[j]->completion_lock->unlock();
1002                                 if(!result)
1003                                 {
1004                                         result = quicktime_write_frame(fd,
1005                                                 threadframes.values[j]->output,
1006                                                 threadframes.values[j]->output_size,
1007                                                 i);
1008                                 }
1009                         }
1010                 }
1011
1012                 if(default_compressor)
1013                 {
1014 //printf("FileMOV::write_frames 3\n");
1015 // Use the library's built in compressor.
1016                         for(j = 0; j < len && !result; j++)
1017                         {
1018 //printf("FileMOV::write_frames 4\n");
1019                                 VFrame *frame = frames[i][j];
1020                                 quicktime_set_cmodel(fd, frame->get_color_model());
1021 //printf("FileMOV::write_frames 5\n");
1022                                 if(cmodel_is_planar(frame->get_color_model()))
1023                                 {
1024                                         unsigned char *planes[3];
1025                                         planes[0] = frame->get_y();
1026                                         planes[1] = frame->get_u();
1027                                         planes[2] = frame->get_v();
1028                                         result = quicktime_encode_video(fd, planes, i);
1029                                 }
1030                                 else
1031                                 {
1032 if(debug) printf("FileMOV::write_frames 1\n");
1033                                         result = quicktime_encode_video(fd, frame->get_rows(), i);
1034 if(debug) printf("FileMOV::write_frames 10\n");
1035                                 }
1036                         }
1037                 }
1038 //printf("FileMOV::write_frames 4\n");
1039         }
1040
1041
1042         return result;
1043 }
1044
1045
1046
1047 int FileMOV::read_frame(VFrame *frame)
1048 {
1049         if(!fd) return 1;
1050         int result = 0;
1051         const int debug = 0;
1052
1053 if(debug) printf("FileMOV::read_frame %d frame=" _LD " color_model=%d\n",
1054   __LINE__, file->current_frame, frame->get_color_model());
1055         switch(frame->get_color_model())
1056         {
1057                 case BC_COMPRESSED:
1058                         frame->allocate_compressed_data(quicktime_frame_size(fd, file->current_frame, file->current_layer));
1059                         frame->set_compressed_size(quicktime_frame_size(fd, file->current_frame, file->current_layer));
1060                         frame->set_keyframe((quicktime_get_keyframe_before(fd,
1061                                 file->current_frame,
1062                                 file->current_layer) == file->current_frame));
1063 // printf("FileMOV::read_frame 1 " _LD " %d %p %d\n",
1064 // file->current_frame,
1065 // frame->get_keyframe(),
1066 // frame->get_data(),
1067 // frame->get_compressed_size());
1068                         result = quicktime_read_frame(fd,
1069                                 frame->get_data(),
1070                                 file->current_layer);
1071                         break;
1072
1073 // Progressive
1074                 case BC_YUV420P:
1075                 case BC_YUV422P:
1076                 {
1077                         unsigned char *row_pointers[3];
1078                         row_pointers[0] = frame->get_y();
1079                         row_pointers[1] = frame->get_u();
1080                         row_pointers[2] = frame->get_v();
1081
1082                         quicktime_set_cmodel(fd, frame->get_color_model());
1083                         result = quicktime_decode_video(fd,
1084                                 row_pointers,
1085                                 file->current_layer);
1086                 }
1087                 break;
1088
1089 // Packed
1090                 default:
1091                         quicktime_set_cmodel(fd, frame->get_color_model());
1092                         result = quicktime_decode_video(fd,
1093                                 frame->get_rows(),
1094                                 file->current_layer);
1095                         break;
1096         }
1097
1098
1099 if(debug) printf("FileMOV::read_frame %d\n", __LINE__);
1100         if (result)
1101                 printf("quicktime_read_frame/quicktime_decode_video failed, result:\n");
1102
1103         return result;
1104 }
1105
1106
1107
1108 int64_t FileMOV::compressed_frame_size()
1109 {
1110         if(!fd) return 0;
1111         return quicktime_frame_size(fd, file->current_frame, file->current_layer);
1112 }
1113
1114 int FileMOV::read_compressed_frame(VFrame *buffer)
1115 {
1116         int64_t result;
1117         if(!fd) return 0;
1118
1119         result = quicktime_read_frame(fd, buffer->get_data(), file->current_layer);
1120         buffer->set_compressed_size(result);
1121         buffer->set_keyframe((quicktime_get_keyframe_before(fd,
1122                 file->current_frame,
1123                 file->current_layer) == file->current_frame));
1124         result = !result;
1125         return result;
1126 }
1127
1128 int FileMOV::write_compressed_frame(VFrame *buffer)
1129 {
1130         int result = 0;
1131         if(!fd) return 0;
1132
1133         result = quicktime_write_frame(fd,
1134                 buffer->get_data(),
1135                 buffer->get_compressed_size(),
1136                 file->current_layer);
1137         return result;
1138 }
1139
1140
1141
1142 int FileMOV::read_raw(VFrame *frame,
1143                 float in_x1, float in_y1, float in_x2, float in_y2,
1144                 float out_x1, float out_y1, float out_x2, float out_y2,
1145                 int use_float, int interpolate)
1146 {
1147         int64_t result = 1;
1148         if(!fd) return 1;
1149
1150         quicktime_set_video_position(fd, file->current_frame, file->current_layer);
1151 // Develop importing strategy
1152         switch(frame->get_color_model())
1153         {
1154                 case BC_RGB888:
1155                         result = quicktime_decode_video(fd, frame->get_rows(), file->current_layer);
1156                         break;
1157                 case BC_RGBA8888:
1158                 case BC_RGB161616:
1159                 case BC_RGBA16161616:
1160                 case BC_YUV888:
1161                 case BC_YUVA8888:
1162                 case BC_YUV161616:
1163                 case BC_YUVA16161616:
1164                 case BC_YUV420P:
1165                         eprintf("FileMOV::read_raw: unknown colormodel\n");
1166                         break;
1167         }
1168         return result;
1169 }
1170
1171 // Overlay samples
1172 int FileMOV::read_samples(double *buffer, int64_t len)
1173 {
1174         if(!fd) return 1;
1175
1176         if(quicktime_track_channels(fd, 0) > file->current_channel &&
1177                 quicktime_supported_audio(fd, 0))
1178         {
1179
1180 //printf("FileMOV::read_samples 2 " _LD " " _LD "\n", file->current_sample, quicktime_audio_position(fd, 0));
1181                 new_audio_temp(len);
1182
1183 //printf("FileMOV::read_samples 3 " _LD " " _LD "\n", file->current_sample, quicktime_audio_position(fd, 0));
1184                 if(quicktime_decode_audio(fd, 0, temp_float[0], len, file->current_channel))
1185                 {
1186                         printf("quicktime_decode_audio failed\n");
1187                         return 1;
1188                 }
1189                 else
1190                 {
1191                         for(int i = 0; i < len; i++) buffer[i] = temp_float[0][i];
1192                 }
1193
1194 // if(file->current_channel == 0)
1195 // for(int i = 0; i < len; i++)
1196 // {
1197 //      int16_t value;
1198 //      value = (int16_t)(temp_float[0][i] * 32767);
1199 //      fwrite(&value, 2, 1, stdout);
1200 // }
1201 //printf("FileMOV::read_samples 4 " _LD " " _LD "\n", file->current_sample, quicktime_audio_position(fd, 0));
1202         }
1203
1204         return 0;
1205 }
1206
1207
1208 const char* FileMOV::strtocompression(const char *string)
1209 {
1210         if(!strcasecmp(string, _(DIVX_NAME))) return QUICKTIME_DIVX;
1211         if(!strcasecmp(string, _(H264_NAME))) return QUICKTIME_H264;
1212         if(!strcasecmp(string, _(HV64_NAME))) return QUICKTIME_HV64;
1213         if(!strcasecmp(string, _(MP4V_NAME))) return QUICKTIME_MP4V;
1214         if(!strcasecmp(string, _(H263_NAME))) return QUICKTIME_H263;
1215         if(!strcasecmp(string, _(HV60_NAME))) return QUICKTIME_HV60;
1216         if(!strcasecmp(string, _(DIV3_NAME))) return QUICKTIME_DIV3;
1217 // Students say QUICKTIME_DV is required for compression even though
1218 // QUICKTIME_DVSD is produced by other software
1219 //      if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DVSD;
1220         if(!strcasecmp(string, _(DV_NAME))) return QUICKTIME_DV;
1221         if(!strcasecmp(string, _(PNG_NAME))) return QUICKTIME_PNG;
1222         if(!strcasecmp(string, _(PNGA_NAME))) return MOV_PNGA;
1223         if(!strcasecmp(string, _(RGB_NAME))) return QUICKTIME_RAW;
1224         if(!strcasecmp(string, _(RGBA_NAME))) return MOV_RGBA;
1225         if(!strcasecmp(string, _(QTJPEG_NAME))) return QUICKTIME_JPEG;
1226         if(!strcasecmp(string, _(QTMJPEGP_NAME))) return QUICKTIME_MJPG;
1227         if(!strcasecmp(string, _(MJPA_NAME))) return QUICKTIME_MJPA;
1228         if(!strcasecmp(string, _(YUV420_NAME))) return QUICKTIME_YUV420;
1229         if(!strcasecmp(string, _(YUV411_NAME))) return QUICKTIME_YUV411;
1230         if(!strcasecmp(string, _(YUV422_NAME))) return QUICKTIME_YUV422;
1231         if(!strcasecmp(string, _(TWOVUY_NAME))) return QUICKTIME_2VUY;
1232         if(!strcasecmp(string, _(YUV444_NAME))) return QUICKTIME_YUV444;
1233         if(!strcasecmp(string, _(YUVA4444_NAME))) return QUICKTIME_YUVA4444;
1234         if(!strcasecmp(string, _(YUV444_10BIT_NAME))) return QUICKTIME_YUV444_10bit;
1235
1236         if(!strcasecmp(string, _(TWOS_NAME))) return QUICKTIME_TWOS;
1237         if(!strcasecmp(string, _(RAW_NAME))) return QUICKTIME_RAW;
1238         if(!strcasecmp(string, _(IMA4_NAME))) return QUICKTIME_IMA4;
1239         if(!strcasecmp(string, _(ULAW_NAME))) return QUICKTIME_ULAW;
1240         if(!strcasecmp(string, _(MP3_NAME))) return QUICKTIME_MP3;
1241         if(!strcasecmp(string, _(MP4A_NAME))) return QUICKTIME_MP4A;
1242         if(!strcasecmp(string, _(VORBIS_NAME))) return QUICKTIME_VORBIS;
1243
1244
1245
1246         return QUICKTIME_RAW;
1247 }
1248
1249 const char* FileMOV::compressiontostr(const char *string)
1250 {
1251         if(match4(string, QUICKTIME_H263)) return _(H263_NAME);
1252         if(match4(string, QUICKTIME_H264)) return _(H264_NAME);
1253         if(match4(string, QUICKTIME_HV64)) return _(HV64_NAME);
1254         if(match4(string, QUICKTIME_DIVX)) return _(DIVX_NAME);
1255         if(match4(string, QUICKTIME_MP4V)) return _(MP4V_NAME);
1256         if(match4(string, QUICKTIME_HV60)) return _(HV60_NAME);
1257         if(match4(string, QUICKTIME_DIV3)) return _(DIV3_NAME);
1258         if(match4(string, QUICKTIME_DV)) return _(DV_NAME);
1259         if(match4(string, QUICKTIME_DVCP)) return _(DV_NAME);
1260         if(match4(string, QUICKTIME_DVSD)) return _(DV_NAME);
1261         if(match4(string, MOV_PNGA)) return _(PNGA_NAME);
1262         if(match4(string, QUICKTIME_RAW)) return _(RGB_NAME);
1263         if(match4(string, MOV_RGBA)) return _(RGBA_NAME);
1264         if(match4(string, QUICKTIME_JPEG)) return _(QTJPEG_NAME);
1265         if(match4(string, QUICKTIME_MJPG)) return _(QTMJPEGP_NAME);
1266         if(match4(string, QUICKTIME_MJPA)) return _(MJPA_NAME);
1267         if(match4(string, QUICKTIME_YUV420)) return _(YUV420_NAME);
1268         if(match4(string, QUICKTIME_YUV411)) return _(YUV411_NAME);
1269         if(match4(string, QUICKTIME_YUV422)) return _(YUV422_NAME);
1270         if(match4(string, QUICKTIME_2VUY)) return _(TWOVUY_NAME);
1271         if(match4(string, QUICKTIME_YUV444)) return _(YUV444_NAME);
1272         if(match4(string, QUICKTIME_YUVA4444)) return _(YUVA4444_NAME);
1273         if(match4(string, QUICKTIME_YUV444_10bit)) return _(YUV444_10BIT_NAME);
1274
1275
1276
1277
1278
1279         if(match4(string, QUICKTIME_TWOS)) return _(TWOS_NAME);
1280         if(match4(string, QUICKTIME_RAW)) return _(RAW_NAME);
1281         if(match4(string, QUICKTIME_IMA4)) return _(IMA4_NAME);
1282         if(match4(string, QUICKTIME_ULAW)) return _(ULAW_NAME);
1283         if(match4(string, QUICKTIME_MP3)) return _(MP3_NAME);
1284         if(match4(string, QUICKTIME_MP4A)) return _(MP4A_NAME);
1285         if(match4(string, QUICKTIME_VORBIS)) return _(VORBIS_NAME);
1286
1287
1288
1289         return _("Unknown");
1290 }
1291
1292
1293
1294
1295
1296 ThreadStruct::ThreadStruct()
1297 {
1298         input = 0;
1299         output = 0;
1300         output_allocated = 0;
1301         output_size = 0;
1302         completion_lock = new Condition(1, "ThreadStruct::completion_lock");
1303 }
1304
1305 ThreadStruct::~ThreadStruct()
1306 {
1307         if(output) delete [] output;
1308         delete completion_lock;
1309 }
1310
1311 void ThreadStruct::load_output(mjpeg_t *mjpeg)
1312 {
1313         if(output_allocated < mjpeg_output_size(mjpeg))
1314         {
1315                 delete [] output;
1316                 output = 0;
1317         }
1318         if(!output)
1319         {
1320                 output_allocated = mjpeg_output_size(mjpeg);
1321                 output = new unsigned char[output_allocated];
1322         }
1323
1324         output_size = mjpeg_output_size(mjpeg);
1325         memcpy(output, mjpeg_output_buffer(mjpeg), output_size);
1326 }
1327
1328
1329 FileMOVThread::FileMOVThread(FileMOV *filemov, int fields)
1330  : Thread(1, 0, 0)
1331 {
1332         this->filemov = filemov;
1333         this->fields = fields;
1334         mjpeg = 0;
1335         input_lock = new Condition(1, "FileMOVThread::input_lock");
1336 }
1337
1338 FileMOVThread::~FileMOVThread()
1339 {
1340         delete input_lock;
1341 }
1342
1343 int FileMOVThread::start_encoding()
1344 {
1345         mjpeg = mjpeg_new(filemov->asset->width,
1346                 filemov->asset->height,
1347                 fields);
1348         mjpeg_set_quality(mjpeg, filemov->asset->jpeg_quality);
1349         mjpeg_set_float(mjpeg, 0);
1350         done = 0;
1351         set_synchronous(1);
1352         input_lock->lock("FileMOVThread::start_encoding");
1353         start();
1354         return 0;
1355 }
1356
1357 int FileMOVThread::stop_encoding()
1358 {
1359         done = 1;
1360         input_lock->unlock();
1361         join();
1362         if(mjpeg) mjpeg_delete(mjpeg);
1363         return 0;
1364 }
1365
1366 int FileMOVThread::encode_buffer()
1367 {
1368         input_lock->unlock();
1369         return 0;
1370 }
1371
1372 void FileMOVThread::run()
1373 {
1374         while(!done)
1375         {
1376                 input_lock->lock("FileMOVThread::run");
1377
1378                 if(!done)
1379                 {
1380 // Get a frame to compress.
1381                         filemov->threadframe_lock->lock("FileMOVThread::stop_encoding");
1382                         if(filemov->current_threadframe < filemov->total_threadframes)
1383                         {
1384 // Frame is available to process.
1385                                 input_lock->unlock();
1386                                 threadframe = filemov->threadframes.values[filemov->current_threadframe];
1387                                 VFrame *frame = threadframe->input;
1388
1389                                 filemov->current_threadframe++;
1390                                 filemov->threadframe_lock->unlock();
1391
1392                                 mjpeg_compress(mjpeg,
1393                                         frame->get_rows(),
1394                                         frame->get_y(),
1395                                         frame->get_u(),
1396                                         frame->get_v(),
1397                                         frame->get_color_model(),
1398                                         1);
1399
1400                                 if(fields > 1)
1401                                 {
1402                                         unsigned char *data = mjpeg_output_buffer(mjpeg);
1403                                         long data_size = mjpeg_output_size(mjpeg);
1404                                         long data_allocated = mjpeg_output_allocated(mjpeg);
1405                                         long field2_offset;
1406
1407                                         if(filemov->asset->format == FILE_MOV)
1408                                         {
1409                                                 mjpeg_insert_quicktime_markers(&data,
1410                                                         &data_size,
1411                                                         &data_allocated,
1412                                                         2,
1413                                                         &field2_offset);
1414                                         }
1415                                         else
1416                                         {
1417                                                 mjpeg_insert_avi_markers(&data,
1418                                                         &data_size,
1419                                                         &data_allocated,
1420                                                         2,
1421                                                         &field2_offset);
1422                                         }
1423                                         mjpeg_set_output_size(mjpeg, data_size);
1424                                 }
1425                                 threadframe->load_output(mjpeg);
1426                                 threadframe->completion_lock->unlock();
1427                         }
1428                         else
1429                                 filemov->threadframe_lock->unlock();
1430                 }
1431         }
1432 }
1433
1434
1435
1436
1437
1438
1439 MOVConfigAudio::MOVConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1440  : BC_Window(PROGRAM_NAME ": Audio Compression",
1441         parent_window->get_abs_cursor_x(1),
1442         parent_window->get_abs_cursor_y(1),
1443         350,
1444         250)
1445 {
1446         this->parent_window = parent_window;
1447         this->asset = asset;
1448         compression_popup = 0;
1449         reset();
1450 }
1451
1452 MOVConfigAudio::~MOVConfigAudio()
1453 {
1454         lock_window("MOVConfigAudio::~MOVConfigAudio");
1455         if(compression_popup) delete compression_popup;
1456         if(bits_popup) delete bits_popup;
1457         compression_items.remove_all_objects();
1458         unlock_window();
1459 }
1460
1461
1462 void MOVConfigAudio::reset()
1463 {
1464         bits_popup = 0;
1465         bits_title = 0;
1466         dither = 0;
1467         vorbis_min_bitrate = 0;
1468         vorbis_bitrate = 0;
1469         vorbis_max_bitrate = 0;
1470         vorbis_vbr = 0;
1471         mp3_bitrate = 0;
1472         mp4a_bitrate = 0;
1473         mp4a_quantqual = 0;
1474 }
1475
1476 void MOVConfigAudio::create_objects()
1477 {
1478         int x = 10, y = 10;
1479         lock_window("MOVConfigAudio::create_objects");
1480
1481         if(asset->format == FILE_MOV)
1482         {
1483                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1484                 compression_items.append(new BC_ListBoxItem(_(RAW_NAME)));
1485                 compression_items.append(new BC_ListBoxItem(_(IMA4_NAME)));
1486                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1487                 compression_items.append(new BC_ListBoxItem(_(ULAW_NAME)));
1488                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1489                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1490         }
1491         else
1492         {
1493                 compression_items.append(new BC_ListBoxItem(_(TWOS_NAME)));
1494                 compression_items.append(new BC_ListBoxItem(_(MP3_NAME)));
1495                 compression_items.append(new BC_ListBoxItem(_(VORBIS_NAME)));
1496                 compression_items.append(new BC_ListBoxItem(_(MP4A_NAME)));
1497         }
1498
1499         add_tool(new BC_Title(x, y, _("Compression:")));
1500         y += 25;
1501         compression_popup = new MOVConfigAudioPopup(this, x, y);
1502         compression_popup->create_objects();
1503
1504         update_parameters();
1505
1506         add_subwindow(new BC_OKButton(this));
1507         show_window(1);
1508         unlock_window();
1509 }
1510
1511 void MOVConfigAudio::update_parameters()
1512 {
1513         int x = 10, y = 70;
1514         if(bits_title) delete bits_title;
1515         if(bits_popup) delete bits_popup;
1516         if(dither) delete dither;
1517         if(vorbis_min_bitrate) delete vorbis_min_bitrate;
1518         if(vorbis_bitrate) delete vorbis_bitrate;
1519         if(vorbis_max_bitrate) delete vorbis_max_bitrate;
1520         if(vorbis_vbr) delete vorbis_vbr;
1521         if(mp3_bitrate) delete mp3_bitrate;
1522         delete mp4a_bitrate;
1523         delete mp4a_quantqual;
1524
1525         reset();
1526
1527
1528
1529         if(!strcasecmp(asset->acodec, QUICKTIME_TWOS) ||
1530                 !strcasecmp(asset->acodec, QUICKTIME_RAW))
1531         {
1532                 add_subwindow(bits_title = new BC_Title(x, y, _("Bits per channel:")));
1533                 bits_popup = new BitsPopup(this,
1534                         x + 150,
1535                         y,
1536                         &asset->bits,
1537                         0,
1538                         0,
1539                         0,
1540                         0,
1541                         0);
1542                 bits_popup->create_objects();
1543                 y += 40;
1544                 add_subwindow(dither = new BC_CheckBox(x, y, &asset->dither, _("Dither")));
1545         }
1546         else
1547         if(!strcasecmp(asset->acodec, QUICKTIME_IMA4))
1548         {
1549         }
1550         else
1551         if(!strcasecmp(asset->acodec, QUICKTIME_MP3))
1552         {
1553                 mp3_bitrate = new MOVConfigAudioNum(this,
1554                         _("Bitrate:"),
1555                         x,
1556                         y,
1557                         &asset->mp3_bitrate);
1558                 mp3_bitrate->set_increment(64000);
1559                 mp3_bitrate->create_objects();
1560         }
1561         else
1562         if(!strcasecmp(asset->acodec, QUICKTIME_ULAW))
1563         {
1564         }
1565         else
1566         if(!strcasecmp(asset->acodec, QUICKTIME_VORBIS))
1567         {
1568                 add_subwindow(vorbis_vbr = new MOVConfigAudioToggle(this,
1569                         _("Variable bitrate"),
1570                         x,
1571                         y,
1572                         &asset->vorbis_vbr));
1573                 y += 35;
1574                 vorbis_min_bitrate = new MOVConfigAudioNum(this,
1575                         _("Min bitrate:"),
1576                         x,
1577                         y,
1578                         &asset->vorbis_min_bitrate);
1579                 vorbis_min_bitrate->set_increment(1000);
1580                 y += 30;
1581                 vorbis_bitrate = new MOVConfigAudioNum(this,
1582                         _("Avg bitrate:"),
1583                         x,
1584                         y,
1585                         &asset->vorbis_bitrate);
1586                 vorbis_bitrate->set_increment(1000);
1587                 y += 30;
1588                 vorbis_max_bitrate = new MOVConfigAudioNum(this,
1589                         _("Max bitrate:"),
1590                         x,
1591                         y,
1592                         &asset->vorbis_max_bitrate);
1593                 vorbis_max_bitrate->set_increment(1000);
1594
1595
1596
1597                 vorbis_min_bitrate->create_objects();
1598                 vorbis_bitrate->create_objects();
1599                 vorbis_max_bitrate->create_objects();
1600         }
1601         else
1602         if(!strcasecmp(asset->acodec, QUICKTIME_MP4A))
1603         {
1604                 mp4a_bitrate = new MOVConfigAudioNum(this,
1605                         _("Bitrate:"),
1606                         x,
1607                         y,
1608                         &asset->mp4a_bitrate);
1609                 mp4a_bitrate->set_increment(64000);
1610                 mp4a_bitrate->create_objects();
1611
1612                 y += 30;
1613                 mp4a_quantqual = new MOVConfigAudioNum(this,
1614                         _("Quantization Quality (%):"),
1615                         x,
1616                         y,
1617                         &asset->mp4a_quantqual);
1618                 mp4a_quantqual->set_increment(1);
1619                 mp4a_quantqual->create_objects();
1620         }
1621         show_window(1);
1622 }
1623
1624 int MOVConfigAudio::close_event()
1625 {
1626         set_done(0);
1627         return 1;
1628 }
1629
1630
1631
1632
1633
1634 MOVConfigAudioToggle::MOVConfigAudioToggle(MOVConfigAudio *popup,
1635         char *title_text,
1636         int x,
1637         int y,
1638         int *output)
1639  : BC_CheckBox(x, y, *output, title_text)
1640 {
1641         this->popup = popup;
1642         this->output = output;
1643 }
1644 int MOVConfigAudioToggle::handle_event()
1645 {
1646         *output = get_value();
1647         return 1;
1648 }
1649
1650
1651
1652
1653
1654 MOVConfigAudioNum::MOVConfigAudioNum(MOVConfigAudio *popup, char *title_text, int x, int y, int *output)
1655  : BC_TumbleTextBox(popup,
1656                 (int64_t)*output,
1657                 (int64_t)-1,
1658                 (int64_t)25000000,
1659                 popup->get_w() - 150,
1660                 y,
1661                 100)
1662 {
1663         this->popup = popup;
1664         this->title_text = title_text;
1665         this->output = output;
1666         this->x = x;
1667         this->y = y;
1668 }
1669
1670 MOVConfigAudioNum::~MOVConfigAudioNum()
1671 {
1672         if(!popup->get_deleting()) delete title;
1673 }
1674
1675 void MOVConfigAudioNum::create_objects()
1676 {
1677         popup->add_subwindow(title = new BC_Title(x, y, title_text));
1678         BC_TumbleTextBox::create_objects();
1679 }
1680
1681 int MOVConfigAudioNum::handle_event()
1682 {
1683         *output = atol(get_text());
1684         return 1;
1685 }
1686
1687
1688
1689
1690
1691
1692
1693
1694 MOVConfigAudioPopup::MOVConfigAudioPopup(MOVConfigAudio *popup, int x, int y)
1695  : BC_PopupTextBox(popup,
1696                 &popup->compression_items,
1697                 FileMOV::compressiontostr(popup->asset->acodec),
1698                 x,
1699                 y,
1700                 300,
1701                 300)
1702 {
1703         this->popup = popup;
1704 }
1705
1706 int MOVConfigAudioPopup::handle_event()
1707 {
1708         strcpy(popup->asset->acodec, FileMOV::strtocompression(get_text()));
1709         popup->update_parameters();
1710         return 1;
1711 }
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729 MOVConfigVideo::MOVConfigVideo(BC_WindowBase *parent_window,
1730         Asset *asset,
1731         const char *locked_compressor)
1732  : BC_Window(PROGRAM_NAME ": Video Compression",
1733         parent_window->get_abs_cursor_x(1),
1734         parent_window->get_abs_cursor_y(1),
1735         420,
1736         420)
1737 {
1738         this->parent_window = parent_window;
1739         this->asset = asset;
1740         this->locked_compressor = locked_compressor;
1741         compression_popup = 0;
1742
1743         reset();
1744 }
1745
1746 MOVConfigVideo::~MOVConfigVideo()
1747 {
1748         lock_window("MOVConfigVideo::~MOVConfigVideo");
1749         if(compression_popup) delete compression_popup;
1750         compression_items.remove_all_objects();
1751         unlock_window();
1752 }
1753
1754 void MOVConfigVideo::create_objects()
1755 {
1756         int x = 10, y = 10;
1757         lock_window("MOVConfigVideo::create_objects");
1758
1759         if(asset->format == FILE_MOV)
1760         {
1761                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1762                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1763 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1764                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1765                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1766                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1767                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1768                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1769                 compression_items.append(new BC_ListBoxItem(_(QTMJPEGP_NAME)));
1770                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1771                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1772                 compression_items.append(new BC_ListBoxItem(_(PNGA_NAME)));
1773                 compression_items.append(new BC_ListBoxItem(_(RGB_NAME)));
1774                 compression_items.append(new BC_ListBoxItem(_(RGBA_NAME)));
1775                 compression_items.append(new BC_ListBoxItem(_(YUV420_NAME)));
1776                 compression_items.append(new BC_ListBoxItem(_(YUV422_NAME)));
1777                 compression_items.append(new BC_ListBoxItem(_(TWOVUY_NAME)));
1778                 compression_items.append(new BC_ListBoxItem(_(YUV444_NAME)));
1779                 compression_items.append(new BC_ListBoxItem(_(YUVA4444_NAME)));
1780                 compression_items.append(new BC_ListBoxItem(_(YUV444_10BIT_NAME)));
1781         }
1782         else
1783         {
1784                 compression_items.append(new BC_ListBoxItem(_(H264_NAME)));
1785                 compression_items.append(new BC_ListBoxItem(_(HV64_NAME)));
1786 //              compression_items.append(new BC_ListBoxItem(_(DIVX_NAME)));
1787                 compression_items.append(new BC_ListBoxItem(_(MP4V_NAME)));
1788                 compression_items.append(new BC_ListBoxItem(_(HV60_NAME)));
1789                 compression_items.append(new BC_ListBoxItem(_(DIV3_NAME)));
1790                 compression_items.append(new BC_ListBoxItem(_(DV_NAME)));
1791                 compression_items.append(new BC_ListBoxItem(_(QTJPEG_NAME)));
1792                 compression_items.append(new BC_ListBoxItem(_(MJPA_NAME)));
1793                 compression_items.append(new BC_ListBoxItem(_(PNG_NAME)));
1794         }
1795
1796         add_subwindow(new BC_Title(x, y, _("Compression:")));
1797         y += 25;
1798
1799         if(!locked_compressor)
1800         {
1801                 compression_popup = new MOVConfigVideoPopup(this, x, y);
1802                 compression_popup->create_objects();
1803         }
1804         else
1805         {
1806                 add_subwindow(new BC_Title(x,
1807                         y,
1808                         FileMOV::compressiontostr(locked_compressor),
1809                         MEDIUMFONT,
1810                         RED,
1811                         0));
1812         }
1813         y += 40;
1814
1815         param_x = x;
1816         param_y = y;
1817         update_parameters();
1818
1819         add_subwindow(new BC_OKButton(this));
1820         show_window(1);
1821         unlock_window();
1822 }
1823
1824 int MOVConfigVideo::close_event()
1825 {
1826         set_done(0);
1827         return 1;
1828 }
1829
1830
1831 void MOVConfigVideo::reset()
1832 {
1833         jpeg_quality = 0;
1834         jpeg_quality_title = 0;
1835
1836         divx_bitrate = 0;
1837         divx_rc_period = 0;
1838         divx_rc_reaction_ratio = 0;
1839         divx_rc_reaction_period = 0;
1840         divx_max_key_interval = 0;
1841         divx_max_quantizer = 0;
1842         divx_min_quantizer = 0;
1843         divx_quantizer = 0;
1844         divx_quality = 0;
1845         divx_fix_bitrate = 0;
1846         divx_fix_quant = 0;
1847
1848         h264_bitrate = 0;
1849         h264_quantizer = 0;
1850         h264_fix_bitrate = 0;
1851         h264_fix_quant = 0;
1852
1853         ms_bitrate = 0;
1854         ms_bitrate_tolerance = 0;
1855         ms_quantization = 0;
1856         ms_interlaced = 0;
1857         ms_gop_size = 0;
1858         ms_fix_bitrate = 0;
1859         ms_fix_quant = 0;
1860 }
1861
1862 void MOVConfigVideo::update_parameters()
1863 {
1864         if(jpeg_quality)
1865         {
1866                 delete jpeg_quality_title;
1867                 delete jpeg_quality;
1868         }
1869
1870         if(divx_bitrate) delete divx_bitrate;
1871         if(divx_rc_period) delete divx_rc_period;
1872         if(divx_rc_reaction_ratio) delete divx_rc_reaction_ratio;
1873         if(divx_rc_reaction_period) delete divx_rc_reaction_period;
1874         if(divx_max_key_interval) delete divx_max_key_interval;
1875         if(divx_max_quantizer) delete divx_max_quantizer;
1876         if(divx_min_quantizer) delete divx_min_quantizer;
1877         if(divx_quantizer) delete divx_quantizer;
1878         if(divx_quality) delete divx_quality;
1879         if(divx_fix_quant) delete divx_fix_quant;
1880         if(divx_fix_bitrate) delete divx_fix_bitrate;
1881
1882         if(ms_bitrate) delete ms_bitrate;
1883         if(ms_bitrate_tolerance) delete ms_bitrate_tolerance;
1884         if(ms_interlaced) delete ms_interlaced;
1885         if(ms_quantization) delete ms_quantization;
1886         if(ms_gop_size) delete ms_gop_size;
1887         if(ms_fix_bitrate) delete ms_fix_bitrate;
1888         if(ms_fix_quant) delete ms_fix_quant;
1889
1890         delete h264_bitrate;
1891         delete h264_quantizer;
1892         delete h264_fix_bitrate;
1893         delete h264_fix_quant;
1894
1895         reset();
1896
1897
1898         const char *vcodec = asset->vcodec;
1899         if(locked_compressor) vcodec = locked_compressor;
1900
1901
1902 // H264 parameters
1903         if(!strcmp(vcodec, QUICKTIME_H264) ||
1904                 !strcmp(vcodec, QUICKTIME_HV64))
1905         {
1906                 int x = param_x, y = param_y;
1907                 h264_bitrate = new MOVConfigVideoNum(this,
1908                         _("Bitrate:"),
1909                         x,
1910                         y,
1911                         &asset->h264_bitrate);
1912                 h264_bitrate->set_increment(1000000);
1913                 h264_bitrate->create_objects();
1914                 add_subwindow(h264_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260,
1915                                 y,
1916                                 &asset->h264_fix_bitrate,
1917                                 1));
1918                 y += 30;
1919                 h264_quantizer = new MOVConfigVideoNum(this,
1920                         _("Quantization:"),
1921                         x,
1922                         y,
1923                         0,
1924                         51,
1925                         &asset->h264_quantizer);
1926                 h264_quantizer->create_objects();
1927                 add_subwindow(h264_fix_quant = new MOVConfigVideoFixQuant(x + 260,
1928                                 y,
1929                                 &asset->h264_fix_bitrate,
1930                                 0));
1931                 h264_fix_bitrate->opposite = h264_fix_quant;
1932                 h264_fix_quant->opposite = h264_fix_bitrate;
1933         }
1934         else
1935 // ffmpeg parameters
1936         if(!strcmp(vcodec, QUICKTIME_MP4V) ||
1937                 !strcmp(vcodec, QUICKTIME_DIV3))
1938         {
1939                 int x = param_x, y = param_y;
1940                 ms_bitrate = new MOVConfigVideoNum(this,
1941                         _("Bitrate:"),
1942                         x,
1943                         y,
1944                         &asset->ms_bitrate);
1945                 ms_bitrate->set_increment(1000000);
1946                 ms_bitrate->create_objects();
1947                 add_subwindow(ms_fix_bitrate = new MOVConfigVideoFixBitrate(x + 260,
1948                                 y,
1949                                 &asset->ms_fix_bitrate,
1950                                 1));
1951                 y += 30;
1952
1953                 ms_bitrate_tolerance = new MOVConfigVideoNum(this,
1954                         _("Bitrate tolerance:"),
1955                         x,
1956                         y,
1957                         &asset->ms_bitrate_tolerance);
1958                 ms_bitrate_tolerance->create_objects();
1959                 y += 30;
1960
1961
1962
1963                 ms_quantization = new MOVConfigVideoNum(this,
1964                         _("Quantization:"),
1965                         x,
1966                         y,
1967                         &asset->ms_quantization);
1968                 ms_quantization->create_objects();
1969                 add_subwindow(ms_fix_quant = new MOVConfigVideoFixQuant(x + 260,
1970                                 y,
1971                                 &asset->ms_fix_bitrate,
1972                                 0));
1973                 ms_fix_bitrate->opposite = ms_fix_quant;
1974                 ms_fix_quant->opposite = ms_fix_bitrate;
1975
1976
1977                 y += 30;
1978                 add_subwindow(ms_interlaced = new MOVConfigVideoCheckBox(_("Interlaced"),
1979                         x,
1980                         y,
1981                         &asset->ms_interlaced));
1982                 y += 30;
1983                 ms_gop_size = new MOVConfigVideoNum(this,
1984                         _("Keyframe interval:"),
1985                         x,
1986                         y,
1987                         &asset->ms_gop_size);
1988                 ms_gop_size->create_objects();
1989         }
1990         else
1991 // OpenDivx parameters
1992         if(!strcmp(vcodec, QUICKTIME_DIVX) ||
1993                 !strcmp(vcodec, QUICKTIME_H263) ||
1994                 !strcmp(vcodec, QUICKTIME_HV60))
1995         {
1996                 int x = param_x, y = param_y;
1997                 divx_bitrate = new MOVConfigVideoNum(this,
1998                         _("Bitrate:"),
1999                         x,
2000                         y,
2001                         &asset->divx_bitrate);
2002                 divx_bitrate->set_increment(1000000);
2003                 divx_bitrate->create_objects();
2004                 add_subwindow(divx_fix_bitrate =
2005                         new MOVConfigVideoFixBitrate(x + 260,
2006                                 y,
2007                                 &asset->divx_fix_bitrate,
2008                                 1));
2009                 y += 30;
2010                 divx_quantizer = new MOVConfigVideoNum(this,
2011                         _("Quantizer:"),
2012                         x,
2013                         y,
2014                         &asset->divx_quantizer);
2015                 divx_quantizer->create_objects();
2016                 add_subwindow(divx_fix_quant =
2017                         new MOVConfigVideoFixQuant(x + 260,
2018                                 y,
2019                                 &asset->divx_fix_bitrate,
2020                                 0));
2021                 divx_fix_quant->opposite = divx_fix_bitrate;
2022                 divx_fix_bitrate->opposite = divx_fix_quant;
2023                 y += 30;
2024                 divx_rc_period = new MOVConfigVideoNum(this,
2025                         _("RC Period:"),
2026                         x,
2027                         y,
2028                         &asset->divx_rc_period);
2029                 divx_rc_period->create_objects();
2030                 y += 30;
2031                 divx_rc_reaction_ratio = new MOVConfigVideoNum(this,
2032                         _("Reaction Ratio:"),
2033                         x,
2034                         y,
2035                         &asset->divx_rc_reaction_ratio);
2036                 divx_rc_reaction_ratio->create_objects();
2037                 y += 30;
2038                 divx_rc_reaction_period = new MOVConfigVideoNum(this,
2039                         _("Reaction Period:"),
2040                         x,
2041                         y,
2042                         &asset->divx_rc_reaction_period);
2043                 divx_rc_reaction_period->create_objects();
2044                 y += 30;
2045                 divx_max_key_interval = new MOVConfigVideoNum(this,
2046                         _("Max Key Interval:"),
2047                         x,
2048                         y,
2049                         &asset->divx_max_key_interval);
2050                 divx_max_key_interval->create_objects();
2051                 y += 30;
2052                 divx_max_quantizer = new MOVConfigVideoNum(this,
2053                         _("Max Quantizer:"),
2054                         x,
2055                         y,
2056                         &asset->divx_max_quantizer);
2057                 divx_max_quantizer->create_objects();
2058                 y += 30;
2059                 divx_min_quantizer = new MOVConfigVideoNum(this,
2060                         _("Min Quantizer:"),
2061                         x,
2062                         y,
2063                         &asset->divx_min_quantizer);
2064                 divx_min_quantizer->create_objects();
2065                 y += 30;
2066                 divx_quality = new MOVConfigVideoNum(this,
2067                         _("Quality:"),
2068                         x,
2069                         y,
2070                         &asset->divx_quality);
2071                 divx_quality->create_objects();
2072         }
2073         else
2074         if(!strcmp(vcodec, QUICKTIME_JPEG) ||
2075                 !strcmp(vcodec, QUICKTIME_MJPA))
2076         {
2077                 add_subwindow(jpeg_quality_title = new BC_Title(param_x, param_y, _("Quality:")));
2078                 add_subwindow(jpeg_quality = new BC_ISlider(param_x + 80,
2079                         param_y,
2080                         0,
2081                         200,
2082                         200,
2083                         0,
2084                         100,
2085                         asset->jpeg_quality,
2086                         0,
2087                         0,
2088                         &asset->jpeg_quality));
2089         }
2090         show_window(1);
2091 }
2092
2093
2094
2095
2096
2097 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup, char *title_text, int x, int y, int *output)
2098  : BC_TumbleTextBox(popup,
2099                 (int64_t)*output,
2100                 (int64_t)1,
2101                 (int64_t)25000000,
2102                 x + 130,
2103                 y,
2104                 100)
2105 {
2106         this->popup = popup;
2107         this->title_text = title_text;
2108         this->output = output;
2109         this->x = x;
2110         this->y = y;
2111 }
2112
2113 MOVConfigVideoNum::MOVConfigVideoNum(MOVConfigVideo *popup,
2114         char *title_text,
2115         int x,
2116         int y,
2117         int min,
2118         int max,
2119         int *output)
2120  : BC_TumbleTextBox(popup,
2121                 (int64_t)*output,
2122                 (int64_t)min,
2123                 (int64_t)max,
2124                 x + 130,
2125                 y,
2126                 100)
2127 {
2128         this->popup = popup;
2129         this->title_text = title_text;
2130         this->output = output;
2131         this->x = x;
2132         this->y = y;
2133 }
2134
2135 MOVConfigVideoNum::~MOVConfigVideoNum()
2136 {
2137         if(!popup->get_deleting()) delete title;
2138 }
2139
2140 void MOVConfigVideoNum::create_objects()
2141 {
2142         popup->add_subwindow(title = new BC_Title(x, y, title_text));
2143         BC_TumbleTextBox::create_objects();
2144 }
2145
2146 int MOVConfigVideoNum::handle_event()
2147 {
2148         *output = atol(get_text());
2149         return 1;
2150 }
2151
2152
2153
2154
2155
2156
2157
2158 MOVConfigVideoCheckBox::MOVConfigVideoCheckBox(char *title_text, int x, int y, int *output)
2159  : BC_CheckBox(x, y, *output, title_text)
2160 {
2161         this->output = output;
2162 }
2163
2164 int MOVConfigVideoCheckBox::handle_event()
2165 {
2166         *output = get_value();
2167         return 1;
2168 }
2169
2170
2171
2172
2173
2174
2175 MOVConfigVideoFixBitrate::MOVConfigVideoFixBitrate(int x,
2176         int y,
2177         int *output,
2178         int value)
2179  : BC_Radial(x,
2180         y,
2181         *output == value,
2182         _("Fix bitrate"))
2183 {
2184         this->output = output;
2185         this->value = value;
2186 }
2187
2188 int MOVConfigVideoFixBitrate::handle_event()
2189 {
2190         *output = value;
2191         opposite->update(0);
2192         return 1;
2193 }
2194
2195
2196
2197
2198
2199
2200 MOVConfigVideoFixQuant::MOVConfigVideoFixQuant(int x,
2201         int y,
2202         int *output,
2203         int value)
2204  : BC_Radial(x,
2205         y,
2206         *output == value,
2207         _("Fix quantization"))
2208 {
2209         this->output = output;
2210         this->value = value;
2211 }
2212
2213 int MOVConfigVideoFixQuant::handle_event()
2214 {
2215         *output = value;
2216         opposite->update(0);
2217         return 1;
2218 }
2219
2220
2221
2222
2223
2224 MOVConfigVideoPopup::MOVConfigVideoPopup(MOVConfigVideo *popup, int x, int y)
2225  : BC_PopupTextBox(popup,
2226                 &popup->compression_items,
2227                 FileMOV::compressiontostr(popup->asset->vcodec),
2228                 x,
2229                 y,
2230                 300,
2231                 300)
2232 {
2233         this->popup = popup;
2234 }
2235
2236 int MOVConfigVideoPopup::handle_event()
2237 {
2238         strcpy(popup->asset->vcodec, FileMOV::strtocompression(get_text()));
2239         popup->update_parameters();
2240         return 1;
2241 }
2242
2243
2244
2245
2246
2247
2248
2249
2250