r854: Merge 2.1:
[cinelerra_cv/ct.git] / cinelerra / filempeg.C
blob2af7c724ddaae213d411cc3ee700b9e49baf6bff
1 #include "asset.h"
2 #include "bcprogressbox.h"
3 #include "bcsignals.h"
4 #include "bitspopup.h"
5 #include "byteorder.h"
6 #include "clip.h"
7 #include "condition.h"
8 #include "edit.h"
9 #include "file.h"
10 #include "filempeg.h"
11 #include "filesystem.h"
12 #include "guicast.h"
13 #include "indexfile.h"
14 #include "interlacemodes.h"
15 #include "language.h"
16 #include "mainerror.h"
17 #include "mwindow.inc"
18 #include "preferences.h"
19 #include "vframe.h"
20 #include "videodevice.inc"
22 #include <stdio.h>
23 #include <string.h>
24 #include <unistd.h>
26 #define MPEG_YUV420 0
27 #define MPEG_YUV422 1
30 #define MJPEG_EXE PLUGIN_DIR "/mpeg2enc.plugin"
38 // M JPEG dependancies
39 static double frame_rate_codes[] = 
41         0,
42         24000.0/1001.0,
43         24.0,
44         25.0,
45         30000.0/1001.0,
46         30.0,
47         50.0,
48         60000.0/1001.0,
49         60.0
52 static double aspect_ratio_codes[] =
54         0,
55         1.0,
56         1.333,
57         1.777,
58         2.11
68 FileMPEG::FileMPEG(Asset *asset, File *file)
69  : FileBase(asset, file)
71         reset_parameters();
72 // May also be VMPEG or AMPEG if write status.
73         if(asset->format == FILE_UNKNOWN) asset->format = FILE_MPEG;
74         asset->byte_order = 0;
75         next_frame_lock = new Condition(0, "FileMPEG::next_frame_lock");
76         next_frame_done = new Condition(0, "FileMPEG::next_frame_done");
79 FileMPEG::~FileMPEG()
81         close_file();
82         delete next_frame_lock;
83         delete next_frame_done;
86 void FileMPEG::get_parameters(BC_WindowBase *parent_window, 
87         Asset *asset, 
88         BC_WindowBase* &format_window,
89         int audio_options,
90         int video_options)
92         if(audio_options && asset->format == FILE_AMPEG)
93         {
94                 MPEGConfigAudio *window = new MPEGConfigAudio(parent_window, asset);
95                 format_window = window;
96                 window->create_objects();
97                 window->run_window();
98                 delete window;
99         }
100         else
101         if(video_options && asset->format == FILE_VMPEG)
102         {
103                 MPEGConfigVideo *window = new MPEGConfigVideo(parent_window, asset);
104                 format_window = window;
105                 window->create_objects();
106                 window->run_window();
107                 delete window;
108         }
111 int FileMPEG::check_sig(Asset *asset)
113         return mpeg3_check_sig(asset->path);
116 int FileMPEG::reset_parameters_derived()
118         wrote_header = 0;
119         mjpeg_out = 0;
120         mjpeg_eof = 0;
121         mjpeg_error = 0;
125         fd = 0;
126         video_out = 0;
127         audio_out = 0;
128         prev_track = 0;
129         temp_frame = 0;
130         toolame_temp = 0;
131         toolame_allocation = 0;
132         toolame_result = 0;
133         lame_temp[0] = 0;
134         lame_temp[1] = 0;
135         lame_allocation = 0;
136         lame_global = 0;
137         lame_output = 0;
138         lame_output_allocation = 0;
139         lame_fd = 0;
140         lame_started = 0;
144 // Just create the Quicktime objects since this routine is also called
145 // for reopening.
146 int FileMPEG::open_file(int rd, int wr)
148 SET_TRACE
149         int result = 0;
150         this->rd = rd;
151         this->wr = wr;
153         if(rd)
154         {
155                 int error = 0;
156                 if(!(fd = mpeg3_open(asset->path, &error)))
157                 {
158                         char string[BCTEXTLEN];
159                         if(error == MPEG3_INVALID_TOC_VERSION)
160                         {
161                                 sprintf(string, 
162                                         "Couldn't open %s because it has an invalid table of contents version.\n"
163                                         "Rebuild the table of contents with mpeg3toc.",
164                                         asset->path);
165                                 MainError::show_error(string);
166                         }
167                         else
168                         if(error == MPEG3_TOC_DATE_MISMATCH)
169                         {
170                                 sprintf(string, 
171                                         "Couldn't open %s because the table of contents date differs from the source date.\n"
172                                         "Rebuild the table of contents with mpeg3toc.",
173                                         asset->path);
174                                 MainError::show_error(string);
175                         }
176                         result = 1;
177                 }
178                 else
179                 {
180 // Determine if the file needs a table of contents and create one if needed.
181 // If it has video it must be scanned since video has keyframes.
182                                 if(mpeg3_total_vstreams(fd))
183                                 {
184                                         if(create_index()) return 1;
185                                 }
187                         mpeg3_set_cpus(fd, file->cpus);
189                         asset->audio_data = mpeg3_has_audio(fd);
190                         if(asset->audio_data)
191                         {
192                                 asset->channels = 0;
193                                 for(int i = 0; i < mpeg3_total_astreams(fd); i++)
194                                 {
195                                         asset->channels += mpeg3_audio_channels(fd, i);
196                                 }
197                                 if(!asset->sample_rate)
198                                         asset->sample_rate = mpeg3_sample_rate(fd, 0);
199                                 asset->audio_length = mpeg3_audio_samples(fd, 0); 
200                         }
202                         asset->video_data = mpeg3_has_video(fd);
203                         if(asset->video_data)
204                         {
205                                 asset->layers = mpeg3_total_vstreams(fd);
206                                 asset->width = mpeg3_video_width(fd, 0);
207                                 asset->height = mpeg3_video_height(fd, 0);
208                                 asset->interlace_mode = BC_ILACE_MODE_UNDETECTED; // TODO: (to do this, start at hvirtualcvs/libmpeg3/headers.c 
209                                                                                   //        and find out how to decode info from the header)
210                                 asset->video_length = mpeg3_video_frames(fd, 0);
211                                 asset->vmpeg_cmodel = 
212                                         (mpeg3_colormodel(fd, 0) == MPEG3_YUV422P) ? MPEG_YUV422 : MPEG_YUV420;
213                                 if(!asset->frame_rate)
214                                         asset->frame_rate = mpeg3_frame_rate(fd, 0);
215                         }
216                 }
217         }
218         
219         
220         
221         if(wr && asset->format == FILE_VMPEG)
222         {
223 // Heroine Virtual encoder
224                 if(asset->vmpeg_cmodel == MPEG_YUV422)
225                 {
226                         char bitrate_string[BCTEXTLEN];
227                         char quant_string[BCTEXTLEN];
228                         char iframe_string[BCTEXTLEN];
230                         sprintf(bitrate_string, "%d", asset->vmpeg_bitrate);
231                         sprintf(quant_string, "%d", asset->vmpeg_quantization);
232                         sprintf(iframe_string, "%d", asset->vmpeg_iframe_distance);
234 // Construct command line
235                         if(!result)
236                         {
237                                 append_vcommand_line("mpeg2enc");
240                                 if(asset->aspect_ratio > 0)
241                                 {
242                                         append_vcommand_line("-a");
243                                         if(EQUIV(asset->aspect_ratio, 1))
244                                                 append_vcommand_line("1");
245                                         else
246                                         if(EQUIV(asset->aspect_ratio, 1.333))
247                                                 append_vcommand_line("2");
248                                         else
249                                         if(EQUIV(asset->aspect_ratio, 1.777))
250                                                 append_vcommand_line("3");
251                                         else
252                                         if(EQUIV(asset->aspect_ratio, 2.11))
253                                                 append_vcommand_line("4");
254                                 }
256                                 append_vcommand_line(asset->vmpeg_derivative == 1 ? "-1" : "");
257                                 append_vcommand_line(asset->vmpeg_cmodel == MPEG_YUV422 ? "-422" : "");
258                                 if(asset->vmpeg_fix_bitrate)
259                                 {
260                                         append_vcommand_line("--cbr -b");
261                                         append_vcommand_line(bitrate_string);
262                                 }
263                                 else
264                                 {
265                                         append_vcommand_line("-q");
266                                         append_vcommand_line(quant_string);
267                                 }
268                                 append_vcommand_line(!asset->vmpeg_fix_bitrate ? quant_string : "");
269                                 append_vcommand_line("-n");
270                                 append_vcommand_line(iframe_string);
271                                 append_vcommand_line(asset->vmpeg_progressive ? "-p" : "");
272                                 append_vcommand_line(asset->vmpeg_denoise ? "-d" : "");
273                                 append_vcommand_line(file->cpus <= 1 ? "-u" : "");
274                                 append_vcommand_line(asset->vmpeg_seq_codes ? "-g" : "");
275                                 append_vcommand_line(asset->path);
277                                 video_out = new FileMPEGVideo(this);
278                                 video_out->start();
279                         }
280                 }
281                 else
282 // mjpegtools encoder
283                 {
284                         char string[BCTEXTLEN];
285                         sprintf(mjpeg_command, MJPEG_EXE);
287                         if(asset->vmpeg_fix_bitrate)
288                         {
289                                 sprintf(string, " --cbr -b %d", asset->vmpeg_bitrate);
290                         }
291                         else
292                         {
293                                 sprintf(string, " -q %d", asset->vmpeg_quantization);
294                         }
295                         strcat(mjpeg_command, string);
302 // Aspect ratio
303                         int aspect_ratio_code = -1;
304                         if(asset->aspect_ratio > 0)
305                         {
306                                 for(int i = 0; i < sizeof(aspect_ratio_codes) / sizeof(double); i++)
307                                 {
308                                         if(EQUIV(aspect_ratio_codes[i], asset->aspect_ratio))
309                                         {
310                                                 aspect_ratio_code = i;
311                                                 break;
312                                         }
313                                 }
314                         }
315                         if(aspect_ratio_code < 0)
316                         {
317                                 printf("FileMPEG::open_file: Unsupported aspect ratio %f\n", asset->aspect_ratio);
318                                 aspect_ratio_code = 2;
319                         }
320                         sprintf(string, " -a %d", aspect_ratio_code);
321                         strcat(mjpeg_command, string);
328 // Frame rate
329                         int frame_rate_code = -1;
330                 for(int i = 1; sizeof(frame_rate_codes) / sizeof(double); ++i)
331                         {
332                                 if(EQUIV(asset->frame_rate, frame_rate_codes[i]))
333                                 {
334                                         frame_rate_code = i;
335                                         break;
336                                 }
337                         }
338                         if(frame_rate_code < 0)
339                         {
340                                 frame_rate_code = 4;
341                                 printf("FileMPEG::open_file: Unsupported frame rate %f\n", asset->frame_rate);
342                         }
343                         sprintf(string, " -F %d", frame_rate_code);
344                         strcat(mjpeg_command, string);
350                         strcat(mjpeg_command, 
351                                 asset->vmpeg_progressive ? " -I 0" : " -I 1");
352                         
355                         sprintf(string, " -M %d", file->cpus);
356                         strcat(mjpeg_command, string);
359                         if(!asset->vmpeg_progressive)
360                         {
361                                 strcat(mjpeg_command, asset->vmpeg_field_order ? " -z b" : " -z t");
362                         }
365                         sprintf(string, " -f %d", asset->vmpeg_preset);
366                         strcat(mjpeg_command, string);
369                         sprintf(string, " -g %d -G %d", asset->vmpeg_iframe_distance, asset->vmpeg_iframe_distance);
370                         strcat(mjpeg_command, string);
373                         if(asset->vmpeg_seq_codes) strcat(mjpeg_command, " -s");
376                         sprintf(string, " -R %d", CLAMP(asset->vmpeg_pframe_distance, 0, 2));
377                         strcat(mjpeg_command, string);
379                         sprintf(string, " -o '%s'", asset->path);
380                         strcat(mjpeg_command, string);
384                         printf("FileMPEG::open_file: Running %s\n", mjpeg_command);
385                         if(!(mjpeg_out = popen(mjpeg_command, "w")))
386                         {
387                                 perror("FileMPEG::open_file");
388                         }
390                         video_out = new FileMPEGVideo(this);
391                         video_out->start();
392                 }
393         }
395         if(wr && asset->format == FILE_AMPEG)
396         {
397                 char command_line[BCTEXTLEN];
398                 char encoder_string[BCTEXTLEN];
399                 char argument_string[BCTEXTLEN];
401 //printf("FileMPEG::open_file 1 %d\n", asset->ampeg_derivative);
402                 encoder_string[0] = 0;
404                 if(asset->ampeg_derivative == 2)
405                 {
406                         char string[BCTEXTLEN];
407                         append_acommand_line("toolame");
408                         append_acommand_line("-m");
409                         append_acommand_line((asset->channels >= 2) ? "j" : "m");
410                         sprintf(string, "%f", (float)asset->sample_rate / 1000);
411                         append_acommand_line("-s");
412                         append_acommand_line(string);
413                         sprintf(string, "%d", asset->ampeg_bitrate);
414                         append_acommand_line("-b");
415                         append_acommand_line(string);
416                         append_acommand_line("-");
417                         append_acommand_line(asset->path);
419                         audio_out = new FileMPEGAudio(this);
420                         audio_out->start();
421                 }
422                 else
423                 if(asset->ampeg_derivative == 3)
424                 {
425                         lame_global = lame_init();
426                         lame_set_brate(lame_global, asset->ampeg_bitrate / 1000);
427                         lame_set_quality(lame_global, 0);
428                         lame_set_in_samplerate(lame_global, 
429                                 asset->sample_rate);
430                         if((result = lame_init_params(lame_global)) < 0)
431                         {
432                                 printf(_("encode: lame_init_params returned %d\n"), result);
433                                 lame_close(lame_global);
434                                 lame_global = 0;
435                         }
436                         else
437                         if(!(lame_fd = fopen(asset->path, "w")))
438                         {
439                                 perror("FileMPEG::open_file");
440                                 lame_close(lame_global);
441                                 lame_global = 0;
442                         }
443                 }
444                 else
445                 {
446                         printf("FileMPEG::open_file: ampeg_derivative=%d\n", asset->ampeg_derivative);
447                         result = 1;
448                 }
449         }
451 //asset->dump();
452 SET_TRACE
453         return result;
463 int FileMPEG::create_index()
465 // Calculate TOC path
466         char index_filename[BCTEXTLEN];
467         char source_filename[BCTEXTLEN];
468         IndexFile::get_index_filename(source_filename, 
469                 file->preferences->index_directory, 
470                 index_filename, 
471                 asset->path);
472         char *ptr = strrchr(index_filename, '.');
473         int error = 0;
475         if(!ptr) return 1;
477         sprintf(ptr, ".toc");
479 // Test existence of TOC
480         FILE *test = fopen(index_filename, "r");
481         if(test)
482         {
483 // Reopen with table of contents
484                 fclose(test);
485         }
486         else
487         {
488 // Create progress window.
489 // This gets around the fact that MWindowGUI is locked.
490                 char progress_title[BCTEXTLEN];
491                 char string[BCTEXTLEN];
492                 sprintf(progress_title, "Creating %s\n", index_filename);
493                 int64_t total_bytes;
494                 mpeg3_t *index_file = mpeg3_start_toc(asset->path, index_filename, &total_bytes);
495                 struct timeval new_time;
496                 struct timeval prev_time;
497                 struct timeval start_time;
498                 struct timeval current_time;
499                 gettimeofday(&prev_time, 0);
500                 gettimeofday(&start_time, 0);
502                 BC_ProgressBox *progress = new BC_ProgressBox(-1, 
503                         -1, 
504                         progress_title, 
505                         total_bytes);
506                 progress->start();
507                 int result = 0;
508                 while(1)
509                 {
510                         int64_t bytes_processed;
511                         mpeg3_do_toc(index_file, &bytes_processed);
512                         gettimeofday(&new_time, 0);
514                         if(new_time.tv_sec - prev_time.tv_sec >= 1)
515                         {
516                                 gettimeofday(&current_time, 0);
517                                 int64_t elapsed_seconds = current_time.tv_sec - start_time.tv_sec;
518                                 int64_t total_seconds = elapsed_seconds * total_bytes / bytes_processed;
519                                 int64_t eta = total_seconds - elapsed_seconds;
520                                 progress->update(bytes_processed, 1);
521                                 sprintf(string, 
522                                         "%sETA: %lldm%llds",
523                                         progress_title,
524                                         eta / 60,
525                                         eta % 60);
526                                 progress->update_title(string, 1);
527 //                              fprintf(stderr, "ETA: %dm%ds        \r", 
528 //                                      bytes_processed * 100 / total_bytes,
529 //                                      eta / 60,
530 //                                      eta % 60);
531 //                              fflush(stdout);
532                                 prev_time = new_time;
533                         }
534                         if(bytes_processed >= total_bytes) break;
535                         if(progress->is_cancelled()) 
536                         {
537                                 result = 1;
538                                 break;
539                         }
540                 }
542                 mpeg3_stop_toc(index_file);
544                 progress->stop_progress();
545                 delete progress;
547 // Remove if error
548                 if(result)
549                 {
550                         remove(index_filename);
551                         return 1;
552                 }
553                 else
554 // Fix date to date of source if success
555                 {
556                 }
558         }
562 // Reopen file from index path instead of asset path.
563         if(fd) mpeg3_close(fd);
564         if(!(fd = mpeg3_open(index_filename, &error)))
565         {
566                 return 1;
567         }
568         else
569                 return 0;
577 void FileMPEG::append_vcommand_line(const char *string)
579         if(string[0])
580         {
581                 char *argv = strdup(string);
582                 vcommand_line.append(argv);
583         }
586 void FileMPEG::append_acommand_line(const char *string)
588         if(string[0])
589         {
590                 char *argv = strdup(string);
591                 acommand_line.append(argv);
592         }
596 int FileMPEG::close_file()
598         mjpeg_eof = 1;
599         next_frame_lock->unlock();
601         if(fd)
602         {
603                 mpeg3_close(fd);
604         }
606         if(video_out)
607         {
608 // End of sequence signal
609                 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
610                 {
611                         mpeg2enc_set_input_buffers(1, 0, 0, 0);
612                 }
613                 delete video_out;
614                 video_out = 0;
615         }
617         vcommand_line.remove_all_objects();
618         acommand_line.remove_all_objects();
620         if(audio_out)
621         {
622                 toolame_send_buffer(0, 0);
623                 delete audio_out;
624                 audio_out = 0;
625         }
627         if(lame_global)
628                 lame_close(lame_global);
630         if(temp_frame) delete temp_frame;
631         if(toolame_temp) delete [] toolame_temp;
633         if(lame_temp[0]) delete [] lame_temp[0];
634         if(lame_temp[1]) delete [] lame_temp[1];
635         if(lame_output) delete [] lame_output;
636         if(lame_fd) fclose(lame_fd);
638         if(mjpeg_out) fclose(mjpeg_out);
639         reset_parameters();
641         FileBase::close_file();
642         return 0;
645 int FileMPEG::get_best_colormodel(Asset *asset, int driver)
647 //printf("FileMPEG::get_best_colormodel 1\n");
648         switch(driver)
649         {
650                 case PLAYBACK_X11:
651                         return BC_RGB888;
652                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
653                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
654                         break;
655                 case PLAYBACK_X11_XV:
656                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
657                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
658                         break;
659                 case PLAYBACK_X11_GL:
660                         return BC_YUV888;
661                         break;
662                 case PLAYBACK_LML:
663                 case PLAYBACK_BUZ:
664                         return BC_YUV422P;
665                         break;
666                 case PLAYBACK_DV1394:
667                 case PLAYBACK_FIREWIRE:
668                         return BC_YUV422P;
669                         break;
670                 case VIDEO4LINUX:
671                 case VIDEO4LINUX2:
672                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
673                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
674                         break;
675                 case CAPTURE_BUZ:
676                 case CAPTURE_LML:
677                         return BC_YUV422;
678                         break;
679                 case CAPTURE_FIREWIRE:
680                 case CAPTURE_IEC61883:
681                         return BC_YUV422P;
682                         break;
683         }
684 //printf("FileMPEG::get_best_colormodel 100\n");
687 int FileMPEG::colormodel_supported(int colormodel)
689         return colormodel;
692 int FileMPEG::get_index(char *index_path)
694         if(!fd) return 1;
697 // Convert the index tables from tracks to channels.
698         if(mpeg3_index_tracks(fd))
699         {
700 // Calculate size of buffer needed for all channels
701                 int buffer_size = 0;
702                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
703                 {
704                         buffer_size += mpeg3_index_size(fd, i) *
705                                 mpeg3_index_channels(fd, i) *
706                                 2;
707                 }
709                 asset->index_buffer = new float[buffer_size];
711 // Size of index buffer in floats
712                 int current_offset = 0;
713 // Current asset channel
714                 int current_channel = 0;
715                 asset->index_zoom = mpeg3_index_zoom(fd);
716                 asset->index_offsets = new int64_t[asset->channels];
717                 asset->index_sizes = new int64_t[asset->channels];
718                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
719                 {
720                         for(int j = 0; j < mpeg3_index_channels(fd, i); j++)
721                         {
722                                 asset->index_offsets[current_channel] = current_offset;
723                                 asset->index_sizes[current_channel] = mpeg3_index_size(fd, i) * 2;
724                                 memcpy(asset->index_buffer + current_offset,
725                                         mpeg3_index_data(fd, i, j),
726                                         mpeg3_index_size(fd, i) * sizeof(float) * 2);
728                                 current_offset += mpeg3_index_size(fd, i) * 2;
729                                 current_channel++;
730                         }
731                 }
733                 FileSystem fs;
734                 asset->index_bytes = fs.get_size(asset->path);
736                 asset->write_index(index_path, buffer_size * sizeof(float));
737                 delete [] asset->index_buffer;
739                 return 0;
740         }
742         return 1;
746 int FileMPEG::can_copy_from(Edit *edit, int64_t position)
748         if(!fd) return 0;
749         return 0;
752 int FileMPEG::set_audio_position(int64_t sample)
754 #if 0
755         if(!fd) return 1;
756         
757         int channel, stream;
758         to_streamchannel(file->current_channel, stream, channel);
760 //printf("FileMPEG::set_audio_position %d %d %d\n", sample, mpeg3_get_sample(fd, stream), last_sample);
761         if(sample != mpeg3_get_sample(fd, stream) &&
762                 sample != last_sample)
763         {
764                 if(sample >= 0 && sample < asset->audio_length)
765                 {
766 //printf("FileMPEG::set_audio_position seeking stream %d\n", sample);
767                         return mpeg3_set_sample(fd, sample, stream);
768                 }
769                 else
770                         return 1;
771         }
772 #endif
773         return 0;
776 int FileMPEG::set_video_position(int64_t x)
778         if(!fd) return 1;
779         if(x >= 0 && x < asset->video_length)
780         {
781 //printf("FileMPEG::set_video_position 1 %lld\n", x);
782                 mpeg3_set_frame(fd, x, file->current_layer);
783         }
784         else
785                 return 1;
788 int64_t FileMPEG::get_memory_usage()
790         if(rd && fd)
791         {
792                 int64_t result = mpeg3_memory_usage(fd);
793                 return result;
794         }
795         return 0;
799 int FileMPEG::write_samples(double **buffer, int64_t len)
801         int result = 0;
803 //printf("FileMPEG::write_samples 1\n");
804         if(asset->ampeg_derivative == 2)
805         {
806 // Convert to int16
807                 int channels = MIN(asset->channels, 2);
808                 int64_t audio_size = len * channels * 2;
809                 if(toolame_allocation < audio_size)
810                 {
811                         if(toolame_temp) delete [] toolame_temp;
812                         toolame_temp = new unsigned char[audio_size];
813                         toolame_allocation = audio_size;
814                 }
816                 for(int i = 0; i < channels; i++)
817                 {
818                         int16_t *output = ((int16_t*)toolame_temp) + i;
819                         double *input = buffer[i];
820                         for(int j = 0; j < len; j++)
821                         {
822                                 int sample = (int)(*input * 0x7fff);
823                                 *output = (int16_t)(CLIP(sample, -0x8000, 0x7fff));
824                                 output += channels;
825                                 input++;
826                         }
827                 }
828                 result = toolame_send_buffer((char*)toolame_temp, audio_size);
829         }
830         else
831         if(asset->ampeg_derivative == 3)
832         {
833                 int channels = MIN(asset->channels, 2);
834                 int64_t audio_size = len * channels;
835                 if(!lame_global) return 1;
836                 if(!lame_fd) return 1;
837                 if(lame_allocation < audio_size)
838                 {
839                         if(lame_temp[0]) delete [] lame_temp[0];
840                         if(lame_temp[1]) delete [] lame_temp[1];
841                         lame_temp[0] = new float[audio_size];
842                         lame_temp[1] = new float[audio_size];
843                         lame_allocation = audio_size;
844                 }
846                 if(lame_output_allocation < audio_size * 4)
847                 {
848                         if(lame_output) delete [] lame_output;
849                         lame_output_allocation = audio_size * 4;
850                         lame_output = new char[lame_output_allocation];
851                 }
853                 for(int i = 0; i < channels; i++)
854                 {
855                         float *output = lame_temp[i];
856                         double *input = buffer[i];
857                         for(int j = 0; j < len; j++)
858                         {
859                                 *output++ = *input++ * (float)32768;
860                         }
861                 }
863                 result = lame_encode_buffer_float(lame_global,
864                         lame_temp[0],
865                         (channels > 1) ? lame_temp[1] : lame_temp[0],
866                         len,
867                         (unsigned char*)lame_output,
868                         lame_output_allocation);
869                 if(result > 0)
870                 {
871                         char *real_output = lame_output;
872                         int bytes = result;
873                         if(!lame_started)
874                         {
875                                 for(int i = 0; i < bytes; i++)
876                                         if(lame_output[i])
877                                         {
878                                                 real_output = &lame_output[i];
879                                                 lame_started = 1;
880                                                 bytes -= i;
881                                                 break;
882                                         }
883                         }
884                         if(bytes > 0 && lame_started)
885                         {
886                                 result = !fwrite(real_output, 1, bytes, lame_fd);
887                                 if(result)
888                                         perror("FileMPEG::write_samples");
889                         }
890                         else
891                                 result = 0;
892                 }
893                 else
894                         result = 1;
895         }
897         return result;
900 int FileMPEG::write_frames(VFrame ***frames, int len)
902         int result = 0;
904         if(video_out)
905         {
906                 int temp_w = (int)((asset->width + 15) / 16) * 16;
907                 int temp_h;
910                 int output_cmodel = 
911                         (asset->vmpeg_cmodel == MPEG_YUV420) ? BC_YUV420P : BC_YUV422P;
912                 
913                 
914 // Height depends on progressiveness
915                 if(asset->vmpeg_progressive || asset->vmpeg_derivative == 1)
916                         temp_h = (int)((asset->height + 15) / 16) * 16;
917                 else
918                         temp_h = (int)((asset->height + 31) / 32) * 32;
920 //printf("FileMPEG::write_frames 1\n");
921                 
922 // Only 1 layer is supported in MPEG output
923                 for(int i = 0; i < 1; i++)
924                 {
925                         for(int j = 0; j < len && !result; j++)
926                         {
927                                 VFrame *frame = frames[i][j];
928                                 
929                                 
930                                 
931                                 if(asset->vmpeg_cmodel == MPEG_YUV422)
932                                 {
933                                         if(frame->get_w() == temp_w &&
934                                                 frame->get_h() == temp_h &&
935                                                 frame->get_color_model() == output_cmodel)
936                                         {
937                                                 mpeg2enc_set_input_buffers(0, 
938                                                         (char*)frame->get_y(),
939                                                         (char*)frame->get_u(),
940                                                         (char*)frame->get_v());
941                                         }
942                                         else
943                                         {
944                                                 if(temp_frame &&
945                                                         (temp_frame->get_w() != temp_w ||
946                                                         temp_frame->get_h() != temp_h ||
947                                                         temp_frame->get_color_model() || output_cmodel))
948                                                 {
949                                                         delete temp_frame;
950                                                         temp_frame = 0;
951                                                 }
954                                                 if(!temp_frame)
955                                                 {
956                                                         temp_frame = new VFrame(0, 
957                                                                 temp_w, 
958                                                                 temp_h, 
959                                                                 output_cmodel);
960                                                 }
962                                                 cmodel_transfer(temp_frame->get_rows(), 
963                                                         frame->get_rows(),
964                                                         temp_frame->get_y(),
965                                                         temp_frame->get_u(),
966                                                         temp_frame->get_v(),
967                                                         frame->get_y(),
968                                                         frame->get_u(),
969                                                         frame->get_v(),
970                                                         0,
971                                                         0,
972                                                         asset->width,
973                                                         asset->height,
974                                                         0,
975                                                         0,
976                                                         asset->width,
977                                                         asset->height,
978                                                         frame->get_color_model(), 
979                                                         temp_frame->get_color_model(),
980                                                         0, 
981                                                         frame->get_w(),
982                                                         temp_w);
984                                                 mpeg2enc_set_input_buffers(0, 
985                                                         (char*)temp_frame->get_y(),
986                                                         (char*)temp_frame->get_u(),
987                                                         (char*)temp_frame->get_v());
988                                         }
989                                 }
990                                 else
991                                 {
992 // MJPEG uses the same dimensions as the input
993                                         if(frame->get_color_model() == output_cmodel)
994                                         {
995                                                 mjpeg_y = frame->get_y();
996                                                 mjpeg_u = frame->get_u();
997                                                 mjpeg_v = frame->get_v();
998                                         }
999                                         else
1000                                         {
1001                                                 if(!temp_frame)
1002                                                 {
1003                                                         temp_frame = new VFrame(0, 
1004                                                                 asset->width, 
1005                                                                 asset->height, 
1006                                                                 output_cmodel);
1007                                                 }
1009                                                 cmodel_transfer(temp_frame->get_rows(), 
1010                                                         frame->get_rows(),
1011                                                         temp_frame->get_y(),
1012                                                         temp_frame->get_u(),
1013                                                         temp_frame->get_v(),
1014                                                         frame->get_y(),
1015                                                         frame->get_u(),
1016                                                         frame->get_v(),
1017                                                         0,
1018                                                         0,
1019                                                         asset->width,
1020                                                         asset->height,
1021                                                         0,
1022                                                         0,
1023                                                         asset->width,
1024                                                         asset->height,
1025                                                         frame->get_color_model(), 
1026                                                         temp_frame->get_color_model(),
1027                                                         0, 
1028                                                         frame->get_w(),
1029                                                         temp_w);
1031                                                 mjpeg_y = temp_frame->get_y();
1032                                                 mjpeg_u = temp_frame->get_u();
1033                                                 mjpeg_v = temp_frame->get_v();
1034                                         }
1039                                         next_frame_lock->unlock();
1040                                         next_frame_done->lock("FileMPEG::write_frames");
1041                                         if(mjpeg_error) result = 1;
1042                                 }
1048                         }
1049                 }
1050         }
1054         return result;
1057 int FileMPEG::read_frame(VFrame *frame)
1059         if(!fd) return 1;
1060         int result = 0;
1061         int src_cmodel;
1063 // printf("FileMPEG::read_frame\n");
1064 // frame->dump_stacks();
1065 // frame->dump_params();
1067         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV420P)
1068                 src_cmodel = BC_YUV420P;
1069         else
1070         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV422P)
1071                 src_cmodel = BC_YUV422P;
1073         switch(frame->get_color_model())
1074         {
1075                 case MPEG3_RGB565:
1076                 case MPEG3_BGR888:
1077                 case MPEG3_BGRA8888:
1078                 case MPEG3_RGB888:
1079                 case MPEG3_RGBA8888:
1080                 case MPEG3_RGBA16161616:
1081 SET_TRACE
1082                         mpeg3_read_frame(fd, 
1083                                         frame->get_rows(), /* Array of pointers to the start of each output row */
1084                                         0,                    /* Location in input frame to take picture */
1085                                         0, 
1086                                         asset->width, 
1087                                         asset->height, 
1088                                         asset->width,                   /* Dimensions of output_rows */
1089                                         asset->height, 
1090                                         frame->get_color_model(),             /* One of the color model #defines */
1091                                         file->current_layer);
1092 SET_TRACE
1093                         break;
1095 // Use Temp
1096                 default:
1097 // Read these directly
1098                         if(frame->get_color_model() == src_cmodel)
1099                         {
1100 SET_TRACE
1101                                 mpeg3_read_yuvframe(fd,
1102                                         (char*)frame->get_y(),
1103                                         (char*)frame->get_u(),
1104                                         (char*)frame->get_v(),
1105                                         0,
1106                                         0,
1107                                         asset->width,
1108                                         asset->height,
1109                                         file->current_layer);
1110 SET_TRACE
1111                         }
1112                         else
1113 // Process through temp frame
1114                         {
1115                                 char *y, *u, *v;
1116 SET_TRACE
1117                                 mpeg3_read_yuvframe_ptr(fd,
1118                                         &y,
1119                                         &u,
1120                                         &v,
1121                                         file->current_layer);
1122 SET_TRACE
1123                                 if(y && u && v)
1124                                 {
1125                                         cmodel_transfer(frame->get_rows(), 
1126                                                 0,
1127                                                 frame->get_y(),
1128                                                 frame->get_u(),
1129                                                 frame->get_v(),
1130                                                 (unsigned char*)y,
1131                                                 (unsigned char*)u,
1132                                                 (unsigned char*)v,
1133                                                 0,
1134                                                 0,
1135                                                 asset->width,
1136                                                 asset->height,
1137                                                 0,
1138                                                 0,
1139                                                 asset->width,
1140                                                 asset->height,
1141                                                 src_cmodel, 
1142                                                 frame->get_color_model(),
1143                                                 0, 
1144                                                 asset->width,
1145                                                 frame->get_w());
1146                                 }
1147                         }
1148                         break;
1149         }
1151 SET_TRACE
1152         return result;
1156 void FileMPEG::to_streamchannel(int channel, int &stream_out, int &channel_out)
1158         for(stream_out = 0, channel_out = file->current_channel; 
1159                 stream_out < mpeg3_total_astreams(fd) && 
1160                         channel_out >= mpeg3_audio_channels(fd, stream_out);
1161                 channel_out -= mpeg3_audio_channels(fd, stream_out), stream_out++)
1162         ;
1165 int FileMPEG::read_samples(double *buffer, int64_t len)
1167         if(!fd) return 0;
1168         if(len < 0) return 0;
1170 // This is directed to a FileMPEGBuffer
1171         float *temp_float = new float[len];
1172 // Translate pure channel to a stream and a channel in the mpeg stream
1173         int stream, channel;
1174         to_streamchannel(file->current_channel, stream, channel);
1175         
1176         
1177         
1178 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1180         mpeg3_set_sample(fd, 
1181                 file->current_sample,
1182                 stream);
1183         mpeg3_read_audio(fd, 
1184                 temp_float,      /* Pointer to pre-allocated buffer of floats */
1185                 0,      /* Pointer to pre-allocated buffer of int16's */
1186                 channel,          /* Channel to decode */
1187                 len,         /* Number of samples to decode */
1188                 stream);          /* Stream containing the channel */
1191 //      last_sample = file->current_sample;
1192         for(int i = 0; i < len; i++) buffer[i] = temp_float[i];
1194         delete [] temp_float;
1195         return 0;
1198 int FileMPEG::prefer_samples_float()
1200         return 1;
1203 int FileMPEG::read_samples_float(float *buffer, int64_t len)
1205         if(!fd) return 0;
1207 // Translate pure channel to a stream and a channel in the mpeg stream
1208         int stream, channel;
1209         to_streamchannel(file->current_channel, stream, channel);
1210         
1211         
1212 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1214         mpeg3_set_sample(fd, 
1215                 file->current_sample,
1216                 stream);
1217         mpeg3_read_audio(fd, 
1218                 buffer,         /* Pointer to pre-allocated buffer of floats */
1219                 0,              /* Pointer to pre-allocated buffer of int16's */
1220                 channel,          /* Channel to decode */
1221                 len,         /* Number of samples to decode */
1222                 stream);          /* Stream containing the channel */
1225 //      last_sample = file->current_sample;
1227 //printf("FileMPEG::read_samples 100\n");
1228         return 0;
1233 char* FileMPEG::strtocompression(char *string)
1235         return "";
1238 char* FileMPEG::compressiontostr(char *string)
1240         return "";
1249 FileMPEGVideo::FileMPEGVideo(FileMPEG *file)
1250  : Thread(1, 0, 0)
1252         this->file = file;
1253         
1254         
1255         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1256         {
1257                 mpeg2enc_init_buffers();
1258                 mpeg2enc_set_w(file->asset->width);
1259                 mpeg2enc_set_h(file->asset->height);
1260                 mpeg2enc_set_rate(file->asset->frame_rate);
1261         }
1264 FileMPEGVideo::~FileMPEGVideo()
1266         Thread::join();
1269 void FileMPEGVideo::run()
1271         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1272         {
1273                 printf("FileMPEGVideo::run ");
1274                 for(int i = 0; i < file->vcommand_line.total; i++)
1275                 printf("%s ", file->vcommand_line.values[i]);
1276                 printf("\n");
1277                 mpeg2enc(file->vcommand_line.total, file->vcommand_line.values);
1278         }
1279         else
1280         {
1281                 while(1)
1282                 {
1283                         file->next_frame_lock->lock("FileMPEGVideo::run");
1284                         if(file->mjpeg_eof) 
1285                         {
1286                                 file->next_frame_done->unlock();
1287                                 break;
1288                         }
1292 // YUV4 sequence header
1293                         if(!file->wrote_header)
1294                         {
1295                                 file->wrote_header = 1;
1297                                 char string[BCTEXTLEN];
1298                                 char interlace_string[BCTEXTLEN];
1299                                 if(!file->asset->vmpeg_progressive)
1300                                 {
1301                                         sprintf(interlace_string, file->asset->vmpeg_field_order ? "b" : "t");
1302                                 }
1303                                 else
1304                                 {
1305                                         sprintf(interlace_string, "p");
1306                                 }
1308                                 fprintf(file->mjpeg_out, "YUV4MPEG2 W%d H%d F%d:%d I%s A%d:%d C%s\n",
1309                                         file->asset->width,
1310                                         file->asset->height,
1311                                         (int)(file->asset->frame_rate * 1001),
1312                                         1001,
1313                                         interlace_string,
1314                                         (int)(file->asset->aspect_ratio * 1000),
1315                                         1000,
1316                                         "420mpeg2");
1317                         }
1319 // YUV4 frame header
1320                         fprintf(file->mjpeg_out, "FRAME\n");
1322 // YUV data
1323                         if(!fwrite(file->mjpeg_y, file->asset->width * file->asset->height, 1, file->mjpeg_out))
1324                                 file->mjpeg_error = 1;
1325                         if(!fwrite(file->mjpeg_u, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1326                                 file->mjpeg_error = 1;
1327                         if(!fwrite(file->mjpeg_v, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1328                                 file->mjpeg_error = 1;
1329                         fflush(file->mjpeg_out);
1331                         file->next_frame_done->unlock();
1332                 }
1333                 pclose(file->mjpeg_out);
1334                 file->mjpeg_out = 0;
1335         }
1357 FileMPEGAudio::FileMPEGAudio(FileMPEG *file)
1358  : Thread(1, 0, 0)
1360         this->file = file;
1361         toolame_init_buffers();
1364 FileMPEGAudio::~FileMPEGAudio()
1366         Thread::join();
1369 void FileMPEGAudio::run()
1371         file->toolame_result = toolame(file->acommand_line.total, file->acommand_line.values);
1381 MPEGConfigAudio::MPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1382  : BC_Window(PROGRAM_NAME ": Audio Compression",
1383         parent_window->get_abs_cursor_x(1),
1384         parent_window->get_abs_cursor_y(1),
1385         310,
1386         120,
1387         -1,
1388         -1,
1389         0,
1390         0,
1391         1)
1393         this->parent_window = parent_window;
1394         this->asset = asset;
1397 MPEGConfigAudio::~MPEGConfigAudio()
1401 int MPEGConfigAudio::create_objects()
1403         int x = 10, y = 10;
1404         int x1 = 150;
1405         MPEGLayer *layer;
1407         add_tool(new BC_Title(x, y, _("Layer:")));
1408         add_tool(layer = new MPEGLayer(x1, y, this));
1409         layer->create_objects();
1411         y += 30;
1412         add_tool(new BC_Title(x, y, _("Kbits per second:")));
1413         add_tool(bitrate = new MPEGABitrate(x1, y, this));
1414         bitrate->create_objects();
1415         
1416         
1417         add_subwindow(new BC_OKButton(this));
1418         show_window();
1419         flush();
1420         return 0;
1423 int MPEGConfigAudio::close_event()
1425         set_done(0);
1426         return 1;
1435 MPEGLayer::MPEGLayer(int x, int y, MPEGConfigAudio *gui)
1436  : BC_PopupMenu(x, y, 100, layer_to_string(gui->asset->ampeg_derivative))
1438         this->gui = gui;
1441 void MPEGLayer::create_objects()
1443         add_item(new BC_MenuItem(layer_to_string(2)));
1444         add_item(new BC_MenuItem(layer_to_string(3)));
1447 int MPEGLayer::handle_event()
1449         gui->asset->ampeg_derivative = string_to_layer(get_text());
1450         gui->bitrate->set_layer(gui->asset->ampeg_derivative);
1451         return 1;
1454 int MPEGLayer::string_to_layer(char *string)
1456         if(!strcasecmp(layer_to_string(2), string))
1457                 return 2;
1458         if(!strcasecmp(layer_to_string(3), string))
1459                 return 3;
1461         return 2;
1464 char* MPEGLayer::layer_to_string(int layer)
1466         switch(layer)
1467         {
1468                 case 2:
1469                         return _("II");
1470                         break;
1471                 
1472                 case 3:
1473                         return _("III");
1474                         break;
1475                         
1476                 default:
1477                         return _("II");
1478                         break;
1479         }
1488 MPEGABitrate::MPEGABitrate(int x, int y, MPEGConfigAudio *gui)
1489  : BC_PopupMenu(x, 
1490         y, 
1491         100, 
1492         bitrate_to_string(gui->string, gui->asset->ampeg_bitrate))
1494         this->gui = gui;
1497 void MPEGABitrate::create_objects()
1499         set_layer(gui->asset->ampeg_derivative);
1502 void MPEGABitrate::set_layer(int layer)
1504         while(total_items())
1505         {
1506                 remove_item(0);
1507         }
1509         if(layer == 2)
1510         {
1511                 add_item(new BC_MenuItem("160"));
1512                 add_item(new BC_MenuItem("192"));
1513                 add_item(new BC_MenuItem("224"));
1514                 add_item(new BC_MenuItem("256"));
1515                 add_item(new BC_MenuItem("320"));
1516                 add_item(new BC_MenuItem("384"));
1517         }
1518         else
1519         {
1520                 add_item(new BC_MenuItem("8"));
1521                 add_item(new BC_MenuItem("16"));
1522                 add_item(new BC_MenuItem("24"));
1523                 add_item(new BC_MenuItem("32"));
1524                 add_item(new BC_MenuItem("40"));
1525                 add_item(new BC_MenuItem("48"));
1526                 add_item(new BC_MenuItem("56"));
1527                 add_item(new BC_MenuItem("64"));
1528                 add_item(new BC_MenuItem("80"));
1529                 add_item(new BC_MenuItem("96"));
1530                 add_item(new BC_MenuItem("112"));
1531                 add_item(new BC_MenuItem("128"));
1532                 add_item(new BC_MenuItem("144"));
1533                 add_item(new BC_MenuItem("160"));
1534                 add_item(new BC_MenuItem("192"));
1535                 add_item(new BC_MenuItem("224"));
1536                 add_item(new BC_MenuItem("256"));
1537                 add_item(new BC_MenuItem("320"));
1538         }
1541 int MPEGABitrate::handle_event()
1543         gui->asset->ampeg_bitrate = string_to_bitrate(get_text());
1544         return 1;
1547 int MPEGABitrate::string_to_bitrate(char *string)
1549         return atol(string);
1553 char* MPEGABitrate::bitrate_to_string(char *string, int bitrate)
1555         sprintf(string, "%d", bitrate);
1556         return string;
1567 MPEGConfigVideo::MPEGConfigVideo(BC_WindowBase *parent_window, 
1568         Asset *asset)
1569  : BC_Window(PROGRAM_NAME ": Video Compression",
1570         parent_window->get_abs_cursor_x(1),
1571         parent_window->get_abs_cursor_y(1),
1572         500,
1573         400,
1574         -1,
1575         -1,
1576         0,
1577         0,
1578         1)
1580         this->parent_window = parent_window;
1581         this->asset = asset;
1582         reset_cmodel();
1585 MPEGConfigVideo::~MPEGConfigVideo()
1589 int MPEGConfigVideo::create_objects()
1591         int x = 10, y = 10;
1592         int x1 = x + 150;
1593         int x2 = x + 300;
1596         add_subwindow(new BC_Title(x, y, _("Color model:")));
1597         add_subwindow(cmodel = new MPEGColorModel(x1, y, this));
1598         cmodel->create_objects();
1599         y += 30;
1601         update_cmodel_objs();
1603         add_subwindow(new BC_OKButton(this));
1604         show_window();
1605         flush();
1606         return 0;
1609 int MPEGConfigVideo::close_event()
1611         set_done(0);
1612         return 1;
1616 void MPEGConfigVideo::delete_cmodel_objs()
1618         delete preset;
1619         delete derivative;
1620         delete bitrate;
1621         delete fixed_bitrate;
1622         delete quant;
1623         delete fixed_quant;
1624         delete iframe_distance;
1625         delete pframe_distance;
1626         delete top_field_first;
1627         delete progressive;
1628         delete denoise;
1629         delete seq_codes;
1630         titles.remove_all_objects();
1631         reset_cmodel();
1634 void MPEGConfigVideo::reset_cmodel()
1636         preset = 0;
1637         derivative = 0;
1638         bitrate = 0;
1639         fixed_bitrate = 0;
1640         quant = 0;
1641         fixed_quant = 0;
1642         iframe_distance = 0;
1643         pframe_distance = 0;
1644         top_field_first = 0;
1645         progressive = 0;
1646         denoise = 0;
1647         seq_codes = 0;
1650 void MPEGConfigVideo::update_cmodel_objs()
1652         BC_Title *title;
1653         int x = 10;
1654         int y = 40;
1655         int x1 = x + 150;
1656         int x2 = x + 280;
1658         delete_cmodel_objs();
1660         if(asset->vmpeg_cmodel == MPEG_YUV420)
1661         {
1662                 add_subwindow(title = new BC_Title(x, y + 5, _("Format Preset:")));
1663                 titles.append(title);
1664                 add_subwindow(preset = new MPEGPreset(x1, y, this));
1665                 preset->create_objects();
1666                 y += 30;
1667         }
1669         add_subwindow(title = new BC_Title(x, y + 5, _("Derivative:")));
1670         titles.append(title);
1671         add_subwindow(derivative = new MPEGDerivative(x1, y, this));
1672         derivative->create_objects();
1673         y += 30;
1675         add_subwindow(title = new BC_Title(x, y + 5, _("Bitrate:")));
1676         titles.append(title);
1677         add_subwindow(bitrate = new MPEGBitrate(x1, y, this));
1678         add_subwindow(fixed_bitrate = new MPEGFixedBitrate(x2, y, this));
1679         y += 30;
1681         add_subwindow(title = new BC_Title(x, y, _("Quantization:")));
1682         titles.append(title);
1683         quant = new MPEGQuant(x1, y, this);
1684         quant->create_objects();
1685         add_subwindow(fixed_quant = new MPEGFixedQuant(x2, y, this));
1686         y += 30;
1688         add_subwindow(title = new BC_Title(x, y, _("I frame distance:")));
1689         titles.append(title);
1690         iframe_distance = new MPEGIFrameDistance(x1, y, this);
1691         iframe_distance->create_objects();
1692         y += 30;
1694         if(asset->vmpeg_cmodel == MPEG_YUV420)
1695         {
1696                 add_subwindow(title = new BC_Title(x, y, _("P frame distance:")));
1697                 titles.append(title);
1698                 pframe_distance = new MPEGPFrameDistance(x1, y, this);
1699                 pframe_distance->create_objects();
1700                 y += 30;
1702                 add_subwindow(top_field_first = new BC_CheckBox(x, y, &asset->vmpeg_field_order, _("Bottom field first")));
1703                 y += 30;
1704         }
1706         add_subwindow(progressive = new BC_CheckBox(x, y, &asset->vmpeg_progressive, _("Progressive frames")));
1707         y += 30;
1708         add_subwindow(denoise = new BC_CheckBox(x, y, &asset->vmpeg_denoise, _("Denoise")));
1709         y += 30;
1710         add_subwindow(seq_codes = new BC_CheckBox(x, y, &asset->vmpeg_seq_codes, _("Sequence start codes in every GOP")));
1726 MPEGDerivative::MPEGDerivative(int x, int y, MPEGConfigVideo *gui)
1727  : BC_PopupMenu(x, y, 150, derivative_to_string(gui->asset->vmpeg_derivative))
1729         this->gui = gui;
1732 void MPEGDerivative::create_objects()
1734         add_item(new BC_MenuItem(derivative_to_string(1)));
1735         add_item(new BC_MenuItem(derivative_to_string(2)));
1738 int MPEGDerivative::handle_event()
1740         gui->asset->vmpeg_derivative = string_to_derivative(get_text());
1741         return 1;
1744 int MPEGDerivative::string_to_derivative(char *string)
1746         if(!strcasecmp(derivative_to_string(1), string))
1747                 return 1;
1748         if(!strcasecmp(derivative_to_string(2), string))
1749                 return 2;
1751         return 1;
1754 char* MPEGDerivative::derivative_to_string(int derivative)
1756         switch(derivative)
1757         {
1758                 case 1:
1759                         return _("MPEG-1");
1760                         break;
1761                 
1762                 case 2:
1763                         return _("MPEG-2");
1764                         break;
1765                         
1766                 default:
1767                         return _("MPEG-1");
1768                         break;
1769         }
1782 MPEGPreset::MPEGPreset(int x, int y, MPEGConfigVideo *gui)
1783  : BC_PopupMenu(x, y, 200, value_to_string(gui->asset->vmpeg_preset))
1785         this->gui = gui;
1788 void MPEGPreset::create_objects()
1790         for(int i = 0; i < 10; i++)
1791         {
1792                 add_item(new BC_MenuItem(value_to_string(i)));
1793         }
1796 int MPEGPreset::handle_event()
1798         gui->asset->vmpeg_preset = string_to_value(get_text());
1799         return 1;
1802 int MPEGPreset::string_to_value(char *string)
1804         for(int i = 0; i < 10; i++)
1805         {
1806                 if(!strcasecmp(value_to_string(i), string))
1807                         return i;
1808         }
1809         return 0;
1812 char* MPEGPreset::value_to_string(int derivative)
1814         switch(derivative)
1815         {
1816                 case 0: return _("Generic MPEG-1"); break;
1817                 case 1: return _("standard VCD"); break;
1818                 case 2: return _("user VCD"); break;
1819                 case 3: return _("Generic MPEG-2"); break;
1820                 case 4: return _("standard SVCD"); break;
1821                 case 5: return _("user SVCD"); break;
1822                 case 6: return _("VCD Still sequence"); break;
1823                 case 7: return _("SVCD Still sequence"); break;
1824                 case 8: return _("DVD NAV"); break;
1825                 case 9: return _("DVD"); break;
1826                 default: return _("Generic MPEG-1"); break;
1827         }
1840 MPEGBitrate::MPEGBitrate(int x, int y, MPEGConfigVideo *gui)
1841  : BC_TextBox(x, y, 100, 1, gui->asset->vmpeg_bitrate)
1843         this->gui = gui;
1847 int MPEGBitrate::handle_event()
1849         gui->asset->vmpeg_bitrate = atol(get_text());
1850         return 1;
1857 MPEGQuant::MPEGQuant(int x, int y, MPEGConfigVideo *gui)
1858  : BC_TumbleTextBox(gui, 
1859         (int64_t)gui->asset->vmpeg_quantization, 
1860         (int64_t)1,
1861         (int64_t)100,
1862         x, 
1863         y,
1864         100)
1866         this->gui = gui;
1869 int MPEGQuant::handle_event()
1871         gui->asset->vmpeg_quantization = atol(get_text());
1872         return 1;
1875 MPEGFixedBitrate::MPEGFixedBitrate(int x, int y, MPEGConfigVideo *gui)
1876  : BC_Radial(x, y, gui->asset->vmpeg_fix_bitrate, _("Fixed bitrate"))
1878         this->gui = gui;
1881 int MPEGFixedBitrate::handle_event()
1883         update(1);
1884         gui->asset->vmpeg_fix_bitrate = 1;
1885         gui->fixed_quant->update(0);
1886         return 1;
1889 MPEGFixedQuant::MPEGFixedQuant(int x, int y, MPEGConfigVideo *gui)
1890  : BC_Radial(x, y, !gui->asset->vmpeg_fix_bitrate, _("Fixed quantization"))
1892         this->gui = gui;
1895 int MPEGFixedQuant::handle_event()
1897         update(1);
1898         gui->asset->vmpeg_fix_bitrate = 0;
1899         gui->fixed_bitrate->update(0);
1900         return 1;
1911 MPEGIFrameDistance::MPEGIFrameDistance(int x, int y, MPEGConfigVideo *gui)
1912  : BC_TumbleTextBox(gui, 
1913         (int64_t)gui->asset->vmpeg_iframe_distance, 
1914         (int64_t)1,
1915         (int64_t)100,
1916         x, 
1917         y,
1918         50)
1920         this->gui = gui;
1923 int MPEGIFrameDistance::handle_event()
1925         gui->asset->vmpeg_iframe_distance = atoi(get_text());
1926         return 1;
1935 MPEGPFrameDistance::MPEGPFrameDistance(int x, int y, MPEGConfigVideo *gui)
1936  : BC_TumbleTextBox(gui, 
1937         (int64_t)gui->asset->vmpeg_pframe_distance, 
1938         (int64_t)0,
1939         (int64_t)2,
1940         x, 
1941         y,
1942         50)
1944         this->gui = gui;
1947 int MPEGPFrameDistance::handle_event()
1949         gui->asset->vmpeg_pframe_distance = atoi(get_text());
1950         return 1;
1960 MPEGColorModel::MPEGColorModel(int x, int y, MPEGConfigVideo *gui)
1961  : BC_PopupMenu(x, y, 150, cmodel_to_string(gui->asset->vmpeg_cmodel))
1963         this->gui = gui;
1966 void MPEGColorModel::create_objects()
1968         add_item(new BC_MenuItem(cmodel_to_string(0)));
1969         add_item(new BC_MenuItem(cmodel_to_string(1)));
1972 int MPEGColorModel::handle_event()
1974         gui->asset->vmpeg_cmodel = string_to_cmodel(get_text());
1975         gui->update_cmodel_objs();
1976         return 1;
1979 int MPEGColorModel::string_to_cmodel(char *string)
1981         if(!strcasecmp(cmodel_to_string(0), string))
1982                 return 0;
1983         if(!strcasecmp(cmodel_to_string(1), string))
1984                 return 1;
1985         return 1;
1988 char* MPEGColorModel::cmodel_to_string(int cmodel)
1990         switch(cmodel)
1991         {
1992                 case MPEG_YUV420:
1993                         return _("YUV 4:2:0");
1994                         break;
1995                 
1996                 case MPEG_YUV422:
1997                         return _("YUV 4:2:2");
1998                         break;
1999                         
2000                 default:
2001                         return _("YUV 4:2:0");
2002                         break;
2003         }