r1014: Enable horizontal scrolling with the mouse wheel by pressing Ctrl.
[cinelerra_cv/ct.git] / cinelerra / filempeg.C
blobc7658f0ba61693a12ff02b7553c23fe7b1fa5ba1
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 void FileMPEG::get_info(Asset *asset, int64_t *bytes, int *stracks)
118         mpeg3_t *fd;
120         int error = 0;
121         if((fd = mpeg3_open(asset->path, &error)))
122         {
123                 *bytes = mpeg3_get_bytes(fd);
124                 *stracks = mpeg3_subtitle_tracks(fd);
125                 mpeg3_close(fd);
126         }
127         return;
130 int FileMPEG::reset_parameters_derived()
132         wrote_header = 0;
133         mjpeg_out = 0;
134         mjpeg_eof = 0;
135         mjpeg_error = 0;
138         dvb_out = 0;
141         fd = 0;
142         video_out = 0;
143         audio_out = 0;
144         prev_track = 0;
145         temp_frame = 0;
146         toolame_temp = 0;
147         toolame_allocation = 0;
148         toolame_result = 0;
149         lame_temp[0] = 0;
150         lame_temp[1] = 0;
151         lame_allocation = 0;
152         lame_global = 0;
153         lame_output = 0;
154         lame_output_allocation = 0;
155         lame_fd = 0;
156         lame_started = 0;
160 // Just create the Quicktime objects since this routine is also called
161 // for reopening.
162 int FileMPEG::open_file(int rd, int wr)
164 SET_TRACE
165         int result = 0;
166         this->rd = rd;
167         this->wr = wr;
169         if(rd)
170         {
171                 int error = 0;
172                 if(!(fd = mpeg3_open(asset->path, &error)))
173                 {
174                         char string[BCTEXTLEN];
175                         if(error == MPEG3_INVALID_TOC_VERSION)
176                         {
177                                 eprintf("Couldn't open %s because it has an invalid table of contents version.\n"
178                                         "Rebuild the table of contents with mpeg3toc.",
179                                         asset->path);
180                         }
181                         else
182                         if(error == MPEG3_TOC_DATE_MISMATCH)
183                         {
184                                 eprintf("Couldn't open %s because the table of contents date differs from the source date.\n"
185                                         "Rebuild the table of contents with mpeg3toc.",
186                                         asset->path);
187                         }
188                         result = 1;
189                 }
190                 else
191                 {
192 // Determine if the file needs a table of contents and create one if needed.
193 // If it has video it must be scanned since video has keyframes.
194                         if(mpeg3_total_vstreams(fd))
195                         {
196                                 if(create_index()) return 1;
197                         }
199                         mpeg3_set_cpus(fd, file->cpus);
201                         asset->audio_data = mpeg3_has_audio(fd);
202                         if(asset->audio_data)
203                         {
204                                 asset->channels = 0;
205                                 for(int i = 0; i < mpeg3_total_astreams(fd); i++)
206                                 {
207                                         asset->channels += mpeg3_audio_channels(fd, i);
208                                 }
209                                 if(!asset->sample_rate)
210                                         asset->sample_rate = mpeg3_sample_rate(fd, 0);
211                                 asset->audio_length = mpeg3_audio_samples(fd, 0); 
212                         }
214                         asset->video_data = mpeg3_has_video(fd);
215                         if(asset->video_data)
216                         {
217                                 asset->layers = mpeg3_total_vstreams(fd);
218                                 asset->width = mpeg3_video_width(fd, 0);
219                                 asset->height = mpeg3_video_height(fd, 0);
220                                 asset->interlace_mode = BC_ILACE_MODE_UNDETECTED; // TODO: (to do this, start at hvirtualcvs/libmpeg3/headers.c 
221                                                                                   //        and find out how to decode info from the header)
222                                 asset->video_length = mpeg3_video_frames(fd, 0);
223                                 asset->vmpeg_cmodel = 
224                                         (mpeg3_colormodel(fd, 0) == MPEG3_YUV422P) ? MPEG_YUV422 : MPEG_YUV420;
225                                 if(!asset->frame_rate)
226                                         asset->frame_rate = mpeg3_frame_rate(fd, 0);
228 // Enable subtitles
229 //printf("FileMPEG::open %d\n", file->playback_subtitle);
230                                 if(file->playback_subtitle >= 0)
231                                         mpeg3_show_subtitle(fd, file->playback_subtitle);
232                         }
233                 }
234         }
237         
238         if(wr && asset->format == FILE_VMPEG)
239         {
240 // Heroine Virtual encoder
241                 if(asset->vmpeg_cmodel == MPEG_YUV422)
242                 {
243                         char bitrate_string[BCTEXTLEN];
244                         char quant_string[BCTEXTLEN];
245                         char iframe_string[BCTEXTLEN];
247                         sprintf(bitrate_string, "%d", asset->vmpeg_bitrate);
248                         sprintf(quant_string, "%d", asset->vmpeg_quantization);
249                         sprintf(iframe_string, "%d", asset->vmpeg_iframe_distance);
251 // Construct command line
252                         if(!result)
253                         {
254                                 append_vcommand_line("mpeg2enc");
257                                 if(asset->aspect_ratio > 0)
258                                 {
259                                         append_vcommand_line("-a");
260                                         if(EQUIV(asset->aspect_ratio, 1))
261                                                 append_vcommand_line("1");
262                                         else
263                                         if(EQUIV(asset->aspect_ratio, 1.333))
264                                                 append_vcommand_line("2");
265                                         else
266                                         if(EQUIV(asset->aspect_ratio, 1.777))
267                                                 append_vcommand_line("3");
268                                         else
269                                         if(EQUIV(asset->aspect_ratio, 2.11))
270                                                 append_vcommand_line("4");
271                                 }
273                                 append_vcommand_line(asset->vmpeg_derivative == 1 ? "-1" : "");
274                                 append_vcommand_line(asset->vmpeg_cmodel == MPEG_YUV422 ? "-422" : "");
275                                 if(asset->vmpeg_fix_bitrate)
276                                 {
277                                         append_vcommand_line("--cbr -b");
278                                         append_vcommand_line(bitrate_string);
279                                 }
280                                 else
281                                 {
282                                         append_vcommand_line("-q");
283                                         append_vcommand_line(quant_string);
284                                 }
285                                 append_vcommand_line(!asset->vmpeg_fix_bitrate ? quant_string : "");
286                                 append_vcommand_line("-n");
287                                 append_vcommand_line(iframe_string);
288                                 append_vcommand_line(asset->vmpeg_progressive ? "-p" : "");
289                                 append_vcommand_line(asset->vmpeg_denoise ? "-d" : "");
290                                 append_vcommand_line(file->cpus <= 1 ? "-u" : "");
291                                 append_vcommand_line(asset->vmpeg_seq_codes ? "-g" : "");
292                                 append_vcommand_line(asset->path);
294                                 video_out = new FileMPEGVideo(this);
295                                 video_out->start();
296                         }
297                 }
298                 else
299 // mjpegtools encoder
300                 {
301                         char string[BCTEXTLEN];
302                         sprintf(mjpeg_command, MJPEG_EXE);
304 // Must disable interlacing if MPEG-1
305                         switch (asset->vmpeg_preset)
306                         {
307                                 case 0: asset->vmpeg_progressive = 1; break;
308                                 case 1: asset->vmpeg_progressive = 1; break;
309                                 case 2: asset->vmpeg_progressive = 1; break;
310                         }
314 // The current usage of mpeg2enc requires bitrate of 0 when quantization is fixed and
315 // quantization of 1 when bitrate is fixed.  Perfectly intuitive.
316                         if(asset->vmpeg_fix_bitrate)
317                         {
318                                 sprintf(string, " -b %d -q 1", asset->vmpeg_bitrate / 1000);
319                         }
320                         else
321                         {
322                                 sprintf(string, " -b 0 -q %d", asset->vmpeg_quantization);
323                         }
324                         strcat(mjpeg_command, string);
331 // Aspect ratio
332                         int aspect_ratio_code = -1;
333                         if(asset->aspect_ratio > 0)
334                         {
335                                 for(int i = 0; i < sizeof(aspect_ratio_codes) / sizeof(double); i++)
336                                 {
337                                         if(EQUIV(aspect_ratio_codes[i], asset->aspect_ratio))
338                                         {
339                                                 aspect_ratio_code = i;
340                                                 break;
341                                         }
342                                 }
343                         }
344                         if(aspect_ratio_code < 0)
345                         {
346                                 eprintf("Unsupported aspect ratio %f\n", asset->aspect_ratio);
347                                 aspect_ratio_code = 2;
348                         }
349                         sprintf(string, " -a %d", aspect_ratio_code);
350                         strcat(mjpeg_command, string);
357 // Frame rate
358                         int frame_rate_code = -1;
359                 for(int i = 1; sizeof(frame_rate_codes) / sizeof(double); ++i)
360                         {
361                                 if(EQUIV(asset->frame_rate, frame_rate_codes[i]))
362                                 {
363                                         frame_rate_code = i;
364                                         break;
365                                 }
366                         }
367                         if(frame_rate_code < 0)
368                         {
369                                 frame_rate_code = 4;
370                                 eprintf("Unsupported frame rate %f\n", asset->frame_rate);
371                         }
372                         sprintf(string, " -F %d", frame_rate_code);
373                         strcat(mjpeg_command, string);
379                         strcat(mjpeg_command, 
380                                 asset->vmpeg_progressive ? " -I 0" : " -I 1");
381                         
384                         sprintf(string, " -M %d", file->cpus);
385                         strcat(mjpeg_command, string);
388                         if(!asset->vmpeg_progressive)
389                         {
390                                 strcat(mjpeg_command, asset->vmpeg_field_order ? " -z b" : " -z t");
391                         }
394                         sprintf(string, " -f %d", asset->vmpeg_preset);
395                         strcat(mjpeg_command, string);
398                         sprintf(string, " -g %d -G %d", asset->vmpeg_iframe_distance, asset->vmpeg_iframe_distance);
399                         strcat(mjpeg_command, string);
402                         if(asset->vmpeg_seq_codes) strcat(mjpeg_command, " -s");
405                         sprintf(string, " -R %d", CLAMP(asset->vmpeg_pframe_distance, 0, 2));
406                         strcat(mjpeg_command, string);
408                         sprintf(string, " -o '%s'", asset->path);
409                         strcat(mjpeg_command, string);
413                         eprintf("Running %s\n", mjpeg_command);
414                         if(!(mjpeg_out = popen(mjpeg_command, "w")))
415                         {
416                                 eprintf("Error while opening \"%s\" for writing. \n%m\n", mjpeg_command);
417                         }
419                         video_out = new FileMPEGVideo(this);
420                         video_out->start();
421                 }
422         }
423         else
424         if(wr && asset->format == FILE_AMPEG)
425         {
426                 char command_line[BCTEXTLEN];
427                 char encoder_string[BCTEXTLEN];
428                 char argument_string[BCTEXTLEN];
430 //printf("FileMPEG::open_file 1 %d\n", asset->ampeg_derivative);
431                 encoder_string[0] = 0;
433                 if(asset->ampeg_derivative == 2)
434                 {
435                         char string[BCTEXTLEN];
436                         append_acommand_line("toolame");
437                         append_acommand_line("-m");
438                         append_acommand_line((asset->channels >= 2) ? "j" : "m");
439                         sprintf(string, "%f", (float)asset->sample_rate / 1000);
440                         append_acommand_line("-s");
441                         append_acommand_line(string);
442                         sprintf(string, "%d", asset->ampeg_bitrate);
443                         append_acommand_line("-b");
444                         append_acommand_line(string);
445                         append_acommand_line("-");
446                         append_acommand_line(asset->path);
448                         audio_out = new FileMPEGAudio(this);
449                         audio_out->start();
450                 }
451                 else
452                 if(asset->ampeg_derivative == 3)
453                 {
454                         lame_global = lame_init();
455                         lame_set_brate(lame_global, asset->ampeg_bitrate);
456                         lame_set_quality(lame_global, 0);
457                         lame_set_in_samplerate(lame_global, 
458                                 asset->sample_rate);
459                         lame_set_num_channels(lame_global,
460                                 asset->channels);
461                         if((result = lame_init_params(lame_global)) < 0)
462                         {
463                                 eprintf(_("encode: lame_init_params returned %d\n"), result);
464                                 lame_close(lame_global);
465                                 lame_global = 0;
466                         }
467                         else
468                         if(!(lame_fd = fopen(asset->path, "w")))
469                         {
470                                 eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
471                                 lame_close(lame_global);
472                                 lame_global = 0;
473                                 result = 1;
474                         }
475                 }
476                 else
477                 {
478                         eprintf("ampeg_derivative=%d\n", asset->ampeg_derivative);
479                         result = 1;
480                 }
481         }
482         else
483 // Transport stream for DVB capture
484         if(wr)
485         {
486                 if(!(dvb_out = fopen(asset->path, "w")))
487                 {
488                         eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
489                         result = 1;
490                 }
491                 
492         }
495 //asset->dump();
496 SET_TRACE
497         return result;
507 int FileMPEG::create_index()
509 // Calculate TOC path
510         char index_filename[BCTEXTLEN];
511         char source_filename[BCTEXTLEN];
512         IndexFile::get_index_filename(source_filename, 
513                 file->preferences->index_directory, 
514                 index_filename, 
515                 asset->path);
516         char *ptr = strrchr(index_filename, '.');
517         int error = 0;
519         if(!ptr) return 1;
521 // File is a table of contents.
522         if(fd && mpeg3_has_toc(fd)) return 0;
524         sprintf(ptr, ".toc");
526         mpeg3_t *fd_toc;
529 // Test existing copy of TOC
530         mpeg3_close(fd);     // Always free old fd
531         if((fd_toc = mpeg3_open(index_filename, &error)))
532         {
533 // Just exchange old fd 
534                 fd = fd_toc;
535         } else
536         {
537 // Create progress window.
538 // This gets around the fact that MWindowGUI is locked.
539                 char progress_title[BCTEXTLEN];
540                 char string[BCTEXTLEN];
541                 sprintf(progress_title, "Creating %s\n", index_filename);
542                 int64_t total_bytes;
543                 mpeg3_t *index_file = mpeg3_start_toc(asset->path, index_filename, &total_bytes);
544                 struct timeval new_time;
545                 struct timeval prev_time;
546                 struct timeval start_time;
547                 struct timeval current_time;
548                 gettimeofday(&prev_time, 0);
549                 gettimeofday(&start_time, 0);
551                 BC_ProgressBox *progress = new BC_ProgressBox(-1, 
552                         -1, 
553                         progress_title, 
554                         total_bytes);
555                 progress->start();
556                 int result = 0;
557                 while(1)
558                 {
559                         int64_t bytes_processed;
560                         mpeg3_do_toc(index_file, &bytes_processed);
561                         gettimeofday(&new_time, 0);
563                         if(new_time.tv_sec - prev_time.tv_sec >= 1)
564                         {
565                                 gettimeofday(&current_time, 0);
566                                 int64_t elapsed_seconds = current_time.tv_sec - start_time.tv_sec;
567                                 int64_t total_seconds = elapsed_seconds * total_bytes / bytes_processed;
568                                 int64_t eta = total_seconds - elapsed_seconds;
569                                 progress->update(bytes_processed, 1);
570                                 sprintf(string, 
571                                         "%sETA: %lldm%llds",
572                                         progress_title,
573                                         eta / 60,
574                                         eta % 60);
575                                 progress->update_title(string, 1);
576 //                              fprintf(stderr, "ETA: %dm%ds        \r", 
577 //                                      bytes_processed * 100 / total_bytes,
578 //                                      eta / 60,
579 //                                      eta % 60);
580 //                              fflush(stdout);
581                                 prev_time = new_time;
582                         }
583                         if(bytes_processed >= total_bytes) break;
584                         if(progress->is_cancelled()) 
585                         {
586                                 result = 1;
587                                 break;
588                         }
589                 }
591                 mpeg3_stop_toc(index_file);
593                 progress->stop_progress();
594                 delete progress;
596 // Remove if error
597                 if(result)
598                 {
599                         remove(index_filename);
600                         return 1;
601                 }
603 // Reopen file from index path instead of asset path.
604                 if(!(fd = mpeg3_open(index_filename, &error)))
605                         return 1;
606         }
608         return 0;
616 void FileMPEG::append_vcommand_line(const char *string)
618         if(string[0])
619         {
620                 char *argv = strdup(string);
621                 vcommand_line.append(argv);
622         }
625 void FileMPEG::append_acommand_line(const char *string)
627         if(string[0])
628         {
629                 char *argv = strdup(string);
630                 acommand_line.append(argv);
631         }
635 int FileMPEG::close_file()
637         mjpeg_eof = 1;
638         next_frame_lock->unlock();
640         if(fd)
641         {
642                 mpeg3_close(fd);
643         }
645         if(video_out)
646         {
647 // End of sequence signal
648                 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
649                 {
650                         mpeg2enc_set_input_buffers(1, 0, 0, 0);
651                 }
652                 delete video_out;
653                 video_out = 0;
654         }
656         vcommand_line.remove_all_objects();
657         acommand_line.remove_all_objects();
659         if(audio_out)
660         {
661                 toolame_send_buffer(0, 0);
662                 delete audio_out;
663                 audio_out = 0;
664         }
666         if(lame_global)
667                 lame_close(lame_global);
669         if(temp_frame) delete temp_frame;
670         if(toolame_temp) delete [] toolame_temp;
672         if(lame_temp[0]) delete [] lame_temp[0];
673         if(lame_temp[1]) delete [] lame_temp[1];
674         if(lame_output) delete [] lame_output;
675         if(lame_fd) fclose(lame_fd);
677         if(mjpeg_out) fclose(mjpeg_out);
680         if(dvb_out)
681                 fclose(dvb_out);
683         reset_parameters();
685         FileBase::close_file();
686         return 0;
689 int FileMPEG::get_best_colormodel(Asset *asset, int driver)
691 //printf("FileMPEG::get_best_colormodel 1\n");
692         switch(driver)
693         {
694                 case PLAYBACK_X11:
695                         return BC_RGB888;
696                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
697                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
698                         break;
699                 case PLAYBACK_X11_XV:
700                 case PLAYBACK_ASYNCHRONOUS:
701                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
702                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
703                         break;
704                 case PLAYBACK_X11_GL:
705                         return BC_YUV888;
706                         break;
707                 case PLAYBACK_LML:
708                 case PLAYBACK_BUZ:
709                         return BC_YUV422P;
710                         break;
711                 case PLAYBACK_DV1394:
712                 case PLAYBACK_FIREWIRE:
713                         return BC_YUV422P;
714                         break;
715                 case VIDEO4LINUX:
716                 case VIDEO4LINUX2:
717                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
718                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
719                         break;
720                 case CAPTURE_BUZ:
721                 case CAPTURE_LML:
722                         return BC_YUV422;
723                         break;
724                 case CAPTURE_FIREWIRE:
725                 case CAPTURE_IEC61883:
726                         return BC_YUV422P;
727                         break;
728         }
729 //printf("FileMPEG::get_best_colormodel 100\n");
732 int FileMPEG::colormodel_supported(int colormodel)
734         return colormodel;
737 int FileMPEG::get_index(char *index_path)
739         if(!fd) return 1;
742 // Convert the index tables from tracks to channels.
743         if(mpeg3_index_tracks(fd))
744         {
745 // Calculate size of buffer needed for all channels
746                 int buffer_size = 0;
747                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
748                 {
749                         buffer_size += mpeg3_index_size(fd, i) *
750                                 mpeg3_index_channels(fd, i) *
751                                 2;
752                 }
754                 asset->index_buffer = new float[buffer_size];
756 // Size of index buffer in floats
757                 int current_offset = 0;
758 // Current asset channel
759                 int current_channel = 0;
760                 asset->index_zoom = mpeg3_index_zoom(fd);
761                 asset->index_offsets = new int64_t[asset->channels];
762                 asset->index_sizes = new int64_t[asset->channels];
763                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
764                 {
765                         for(int j = 0; j < mpeg3_index_channels(fd, i); j++)
766                         {
767                                 asset->index_offsets[current_channel] = current_offset;
768                                 asset->index_sizes[current_channel] = mpeg3_index_size(fd, i) * 2;
769                                 memcpy(asset->index_buffer + current_offset,
770                                         mpeg3_index_data(fd, i, j),
771                                         mpeg3_index_size(fd, i) * sizeof(float) * 2);
773                                 current_offset += mpeg3_index_size(fd, i) * 2;
774                                 current_channel++;
775                         }
776                 }
778                 FileSystem fs;
779                 asset->index_bytes = fs.get_size(asset->path);
781                 asset->write_index(index_path, buffer_size * sizeof(float));
782                 delete [] asset->index_buffer;
784                 return 0;
785         }
787         return 1;
791 int FileMPEG::can_copy_from(Edit *edit, int64_t position)
793         if(!fd) return 0;
794         return 0;
797 int FileMPEG::set_audio_position(int64_t sample)
799 #if 0
800         if(!fd) return 1;
801         
802         int channel, stream;
803         to_streamchannel(file->current_channel, stream, channel);
805 //printf("FileMPEG::set_audio_position %d %d %d\n", sample, mpeg3_get_sample(fd, stream), last_sample);
806         if(sample != mpeg3_get_sample(fd, stream) &&
807                 sample != last_sample)
808         {
809                 if(sample >= 0 && sample < asset->audio_length)
810                 {
811 //printf("FileMPEG::set_audio_position seeking stream %d\n", sample);
812                         return mpeg3_set_sample(fd, sample, stream);
813                 }
814                 else
815                         return 1;
816         }
817 #endif
818         return 0;
821 int FileMPEG::set_video_position(int64_t x)
823         if(!fd) return 1;
824         if(x >= 0 && x < asset->video_length)
825         {
826 //printf("FileMPEG::set_video_position 1 %lld\n", x);
827                 mpeg3_set_frame(fd, x, file->current_layer);
828         }
829         else
830                 return 1;
833 int64_t FileMPEG::get_memory_usage()
835         if(rd && fd)
836         {
837                 int64_t result = mpeg3_memory_usage(fd);
838                 return result;
839         }
840         return 0;
844 int FileMPEG::write_samples(double **buffer, int64_t len)
846         int result = 0;
848 //printf("FileMPEG::write_samples 1\n");
849         if(asset->ampeg_derivative == 2)
850         {
851 // Convert to int16
852                 int channels = MIN(asset->channels, 2);
853                 int64_t audio_size = len * channels * 2;
854                 if(toolame_allocation < audio_size)
855                 {
856                         if(toolame_temp) delete [] toolame_temp;
857                         toolame_temp = new unsigned char[audio_size];
858                         toolame_allocation = audio_size;
859                 }
861                 for(int i = 0; i < channels; i++)
862                 {
863                         int16_t *output = ((int16_t*)toolame_temp) + i;
864                         double *input = buffer[i];
865                         for(int j = 0; j < len; j++)
866                         {
867                                 int sample = (int)(*input * 0x7fff);
868                                 *output = (int16_t)(CLIP(sample, -0x8000, 0x7fff));
869                                 output += channels;
870                                 input++;
871                         }
872                 }
873                 result = toolame_send_buffer((char*)toolame_temp, audio_size);
874         }
875         else
876         if(asset->ampeg_derivative == 3)
877         {
878                 int channels = MIN(asset->channels, 2);
879                 int64_t audio_size = len * channels;
880                 if(!lame_global) return 1;
881                 if(!lame_fd) return 1;
882                 if(lame_allocation < audio_size)
883                 {
884                         if(lame_temp[0]) delete [] lame_temp[0];
885                         if(lame_temp[1]) delete [] lame_temp[1];
886                         lame_temp[0] = new float[audio_size];
887                         lame_temp[1] = new float[audio_size];
888                         lame_allocation = audio_size;
889                 }
891                 if(lame_output_allocation < audio_size * 4)
892                 {
893                         if(lame_output) delete [] lame_output;
894                         lame_output_allocation = audio_size * 4;
895                         lame_output = new char[lame_output_allocation];
896                 }
898                 for(int i = 0; i < channels; i++)
899                 {
900                         float *output = lame_temp[i];
901                         double *input = buffer[i];
902                         for(int j = 0; j < len; j++)
903                         {
904                                 *output++ = *input++ * (float)32768;
905                         }
906                 }
908                 result = lame_encode_buffer_float(lame_global,
909                         lame_temp[0],
910                         (channels > 1) ? lame_temp[1] : lame_temp[0],
911                         len,
912                         (unsigned char*)lame_output,
913                         lame_output_allocation);
914                 if(result > 0)
915                 {
916                         char *real_output = lame_output;
917                         int bytes = result;
918                         if(!lame_started)
919                         {
920                                 for(int i = 0; i < bytes; i++)
921                                         if(lame_output[i])
922                                         {
923                                                 real_output = &lame_output[i];
924                                                 lame_started = 1;
925                                                 bytes -= i;
926                                                 break;
927                                         }
928                         }
929                         if(bytes > 0 && lame_started)
930                         {
931                                 result = !fwrite(real_output, 1, bytes, lame_fd);
932                                 if(result)
933                                         eprintf("Error while writing samples");
934                         }
935                         else
936                                 result = 0;
937                 }
938                 else
939                         result = 1;
940         }
942         return result;
945 int FileMPEG::write_frames(VFrame ***frames, int len)
947         int result = 0;
949         if(video_out)
950         {
951                 int temp_w = (int)((asset->width + 15) / 16) * 16;
952                 int temp_h;
955                 int output_cmodel = 
956                         (asset->vmpeg_cmodel == MPEG_YUV420) ? BC_YUV420P : BC_YUV422P;
957                 
958                 
959 // Height depends on progressiveness
960                 if(asset->vmpeg_progressive || asset->vmpeg_derivative == 1)
961                         temp_h = (int)((asset->height + 15) / 16) * 16;
962                 else
963                         temp_h = (int)((asset->height + 31) / 32) * 32;
965 //printf("FileMPEG::write_frames 1\n");
966                 
967 // Only 1 layer is supported in MPEG output
968                 for(int i = 0; i < 1; i++)
969                 {
970                         for(int j = 0; j < len && !result; j++)
971                         {
972                                 VFrame *frame = frames[i][j];
973                                 
974                                 
975                                 
976                                 if(asset->vmpeg_cmodel == MPEG_YUV422)
977                                 {
978                                         if(frame->get_w() == temp_w &&
979                                                 frame->get_h() == temp_h &&
980                                                 frame->get_color_model() == output_cmodel)
981                                         {
982                                                 mpeg2enc_set_input_buffers(0, 
983                                                         (char*)frame->get_y(),
984                                                         (char*)frame->get_u(),
985                                                         (char*)frame->get_v());
986                                         }
987                                         else
988                                         {
989                                                 if(temp_frame &&
990                                                         (temp_frame->get_w() != temp_w ||
991                                                         temp_frame->get_h() != temp_h ||
992                                                         temp_frame->get_color_model() || output_cmodel))
993                                                 {
994                                                         delete temp_frame;
995                                                         temp_frame = 0;
996                                                 }
999                                                 if(!temp_frame)
1000                                                 {
1001                                                         temp_frame = new VFrame(0, 
1002                                                                 temp_w, 
1003                                                                 temp_h, 
1004                                                                 output_cmodel);
1005                                                 }
1007                                                 cmodel_transfer(temp_frame->get_rows(), 
1008                                                         frame->get_rows(),
1009                                                         temp_frame->get_y(),
1010                                                         temp_frame->get_u(),
1011                                                         temp_frame->get_v(),
1012                                                         frame->get_y(),
1013                                                         frame->get_u(),
1014                                                         frame->get_v(),
1015                                                         0,
1016                                                         0,
1017                                                         asset->width,
1018                                                         asset->height,
1019                                                         0,
1020                                                         0,
1021                                                         asset->width,
1022                                                         asset->height,
1023                                                         frame->get_color_model(), 
1024                                                         temp_frame->get_color_model(),
1025                                                         0, 
1026                                                         frame->get_w(),
1027                                                         temp_w);
1029                                                 mpeg2enc_set_input_buffers(0, 
1030                                                         (char*)temp_frame->get_y(),
1031                                                         (char*)temp_frame->get_u(),
1032                                                         (char*)temp_frame->get_v());
1033                                         }
1034                                 }
1035                                 else
1036                                 {
1037 // MJPEG uses the same dimensions as the input
1038                                         if(frame->get_color_model() == output_cmodel)
1039                                         {
1040                                                 mjpeg_y = frame->get_y();
1041                                                 mjpeg_u = frame->get_u();
1042                                                 mjpeg_v = frame->get_v();
1043                                         }
1044                                         else
1045                                         {
1046                                                 if(!temp_frame)
1047                                                 {
1048                                                         temp_frame = new VFrame(0, 
1049                                                                 asset->width, 
1050                                                                 asset->height, 
1051                                                                 output_cmodel);
1052                                                 }
1054                                                 cmodel_transfer(temp_frame->get_rows(), 
1055                                                         frame->get_rows(),
1056                                                         temp_frame->get_y(),
1057                                                         temp_frame->get_u(),
1058                                                         temp_frame->get_v(),
1059                                                         frame->get_y(),
1060                                                         frame->get_u(),
1061                                                         frame->get_v(),
1062                                                         0,
1063                                                         0,
1064                                                         asset->width,
1065                                                         asset->height,
1066                                                         0,
1067                                                         0,
1068                                                         asset->width,
1069                                                         asset->height,
1070                                                         frame->get_color_model(), 
1071                                                         temp_frame->get_color_model(),
1072                                                         0, 
1073                                                         frame->get_w(),
1074                                                         temp_w);
1076                                                 mjpeg_y = temp_frame->get_y();
1077                                                 mjpeg_u = temp_frame->get_u();
1078                                                 mjpeg_v = temp_frame->get_v();
1079                                         }
1084                                         next_frame_lock->unlock();
1085                                         next_frame_done->lock("FileMPEG::write_frames");
1086                                         if(mjpeg_error) result = 1;
1087                                 }
1093                         }
1094                 }
1095         }
1099         return result;
1102 int FileMPEG::read_frame(VFrame *frame)
1104         if(!fd) return 1;
1105         int result = 0;
1106         int src_cmodel;
1108 // printf("FileMPEG::read_frame\n");
1109 // frame->dump_stacks();
1110 // frame->dump_params();
1112         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV420P)
1113                 src_cmodel = BC_YUV420P;
1114         else
1115         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV422P)
1116                 src_cmodel = BC_YUV422P;
1118         switch(frame->get_color_model())
1119         {
1120                 case MPEG3_RGB565:
1121                 case MPEG3_BGR888:
1122                 case MPEG3_BGRA8888:
1123                 case MPEG3_RGB888:
1124                 case MPEG3_RGBA8888:
1125                 case MPEG3_RGBA16161616:
1126 SET_TRACE
1127                         mpeg3_read_frame(fd, 
1128                                         frame->get_rows(), /* Array of pointers to the start of each output row */
1129                                         0,                    /* Location in input frame to take picture */
1130                                         0, 
1131                                         asset->width, 
1132                                         asset->height, 
1133                                         asset->width,                   /* Dimensions of output_rows */
1134                                         asset->height, 
1135                                         frame->get_color_model(),             /* One of the color model #defines */
1136                                         file->current_layer);
1137 SET_TRACE
1138                         break;
1140 // Use Temp
1141                 default:
1142 // Read these directly
1143                         if(frame->get_color_model() == src_cmodel)
1144                         {
1145 SET_TRACE
1146                                 mpeg3_read_yuvframe(fd,
1147                                         (char*)frame->get_y(),
1148                                         (char*)frame->get_u(),
1149                                         (char*)frame->get_v(),
1150                                         0,
1151                                         0,
1152                                         asset->width,
1153                                         asset->height,
1154                                         file->current_layer);
1155 SET_TRACE
1156                         }
1157                         else
1158 // Process through temp frame
1159                         {
1160                                 char *y, *u, *v;
1161 SET_TRACE
1162                                 mpeg3_read_yuvframe_ptr(fd,
1163                                         &y,
1164                                         &u,
1165                                         &v,
1166                                         file->current_layer);
1167 SET_TRACE
1168                                 if(y && u && v)
1169                                 {
1170                                         cmodel_transfer(frame->get_rows(), 
1171                                                 0,
1172                                                 frame->get_y(),
1173                                                 frame->get_u(),
1174                                                 frame->get_v(),
1175                                                 (unsigned char*)y,
1176                                                 (unsigned char*)u,
1177                                                 (unsigned char*)v,
1178                                                 0,
1179                                                 0,
1180                                                 asset->width,
1181                                                 asset->height,
1182                                                 0,
1183                                                 0,
1184                                                 asset->width,
1185                                                 asset->height,
1186                                                 src_cmodel, 
1187                                                 frame->get_color_model(),
1188                                                 0, 
1189                                                 asset->width,
1190                                                 frame->get_w());
1191                                 }
1192                         }
1193                         break;
1194         }
1196 SET_TRACE
1197         return result;
1201 void FileMPEG::to_streamchannel(int channel, int &stream_out, int &channel_out)
1203         for(stream_out = 0, channel_out = file->current_channel; 
1204                 stream_out < mpeg3_total_astreams(fd) && 
1205                         channel_out >= mpeg3_audio_channels(fd, stream_out);
1206                 channel_out -= mpeg3_audio_channels(fd, stream_out), stream_out++)
1207         ;
1210 int FileMPEG::read_samples(double *buffer, int64_t len)
1212         if(!fd) return 0;
1213         if(len < 0) return 0;
1215 // This is directed to a FileMPEGBuffer
1216         float *temp_float = new float[len];
1217 // Translate pure channel to a stream and a channel in the mpeg stream
1218         int stream, channel;
1219         to_streamchannel(file->current_channel, stream, channel);
1220         
1221         
1222         
1223 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1225         mpeg3_set_sample(fd, 
1226                 file->current_sample,
1227                 stream);
1228         mpeg3_read_audio(fd, 
1229                 temp_float,      /* Pointer to pre-allocated buffer of floats */
1230                 0,      /* Pointer to pre-allocated buffer of int16's */
1231                 channel,          /* Channel to decode */
1232                 len,         /* Number of samples to decode */
1233                 stream);          /* Stream containing the channel */
1236 //      last_sample = file->current_sample;
1237         for(int i = 0; i < len; i++) buffer[i] = temp_float[i];
1239         delete [] temp_float;
1240         return 0;
1243 int FileMPEG::prefer_samples_float()
1245         return 1;
1248 int FileMPEG::read_samples_float(float *buffer, int64_t len)
1250         if(!fd) return 0;
1252 // Translate pure channel to a stream and a channel in the mpeg stream
1253         int stream, channel;
1254         to_streamchannel(file->current_channel, stream, channel);
1255         
1256         
1257 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1259         mpeg3_set_sample(fd, 
1260                 file->current_sample,
1261                 stream);
1262         mpeg3_read_audio(fd, 
1263                 buffer,         /* Pointer to pre-allocated buffer of floats */
1264                 0,              /* Pointer to pre-allocated buffer of int16's */
1265                 channel,          /* Channel to decode */
1266                 len,         /* Number of samples to decode */
1267                 stream);          /* Stream containing the channel */
1270 //      last_sample = file->current_sample;
1272 //printf("FileMPEG::read_samples 100\n");
1273         return 0;
1278 char* FileMPEG::strtocompression(char *string)
1280         return "";
1283 char* FileMPEG::compressiontostr(char *string)
1285         return "";
1294 FileMPEGVideo::FileMPEGVideo(FileMPEG *file)
1295  : Thread(1, 0, 0)
1297         this->file = file;
1298         
1299         
1300         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1301         {
1302                 mpeg2enc_init_buffers();
1303                 mpeg2enc_set_w(file->asset->width);
1304                 mpeg2enc_set_h(file->asset->height);
1305                 mpeg2enc_set_rate(file->asset->frame_rate);
1306         }
1309 FileMPEGVideo::~FileMPEGVideo()
1311         Thread::join();
1314 void FileMPEGVideo::run()
1316         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1317         {
1318                 printf("FileMPEGVideo::run ");
1319                 for(int i = 0; i < file->vcommand_line.total; i++)
1320                 printf("%s ", file->vcommand_line.values[i]);
1321                 printf("\n");
1322                 mpeg2enc(file->vcommand_line.total, file->vcommand_line.values);
1323         }
1324         else
1325         {
1326                 while(1)
1327                 {
1328                         file->next_frame_lock->lock("FileMPEGVideo::run");
1329                         if(file->mjpeg_eof) 
1330                         {
1331                                 file->next_frame_done->unlock();
1332                                 break;
1333                         }
1337 // YUV4 sequence header
1338                         if(!file->wrote_header)
1339                         {
1340                                 file->wrote_header = 1;
1342                                 char string[BCTEXTLEN];
1343                                 char interlace_string[BCTEXTLEN];
1344                                 if(!file->asset->vmpeg_progressive)
1345                                 {
1346                                         sprintf(interlace_string, file->asset->vmpeg_field_order ? "b" : "t");
1347                                 }
1348                                 else
1349                                 {
1350                                         sprintf(interlace_string, "p");
1351                                 }
1353                                 fprintf(file->mjpeg_out, "YUV4MPEG2 W%d H%d F%d:%d I%s A%d:%d C%s\n",
1354                                         file->asset->width,
1355                                         file->asset->height,
1356                                         (int)(file->asset->frame_rate * 1001),
1357                                         1001,
1358                                         interlace_string,
1359                                         (int)(file->asset->aspect_ratio * 1000),
1360                                         1000,
1361                                         "420mpeg2");
1362                         }
1364 // YUV4 frame header
1365                         fprintf(file->mjpeg_out, "FRAME\n");
1367 // YUV data
1368                         if(!fwrite(file->mjpeg_y, file->asset->width * file->asset->height, 1, file->mjpeg_out))
1369                                 file->mjpeg_error = 1;
1370                         if(!fwrite(file->mjpeg_u, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1371                                 file->mjpeg_error = 1;
1372                         if(!fwrite(file->mjpeg_v, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1373                                 file->mjpeg_error = 1;
1374                         fflush(file->mjpeg_out);
1376                         file->next_frame_done->unlock();
1377                 }
1378                 pclose(file->mjpeg_out);
1379                 file->mjpeg_out = 0;
1380         }
1402 FileMPEGAudio::FileMPEGAudio(FileMPEG *file)
1403  : Thread(1, 0, 0)
1405         this->file = file;
1406         toolame_init_buffers();
1409 FileMPEGAudio::~FileMPEGAudio()
1411         Thread::join();
1414 void FileMPEGAudio::run()
1416         file->toolame_result = toolame(file->acommand_line.total, file->acommand_line.values);
1426 MPEGConfigAudio::MPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1427  : BC_Window(PROGRAM_NAME ": Audio Compression",
1428         parent_window->get_abs_cursor_x(1),
1429         parent_window->get_abs_cursor_y(1),
1430         310,
1431         120,
1432         -1,
1433         -1,
1434         0,
1435         0,
1436         1)
1438         this->parent_window = parent_window;
1439         this->asset = asset;
1442 MPEGConfigAudio::~MPEGConfigAudio()
1446 int MPEGConfigAudio::create_objects()
1448         int x = 10, y = 10;
1449         int x1 = 150;
1450         MPEGLayer *layer;
1453         if(asset->format == FILE_MPEG)
1454         {
1455                 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1456                 return 0;
1457         }
1460         add_tool(new BC_Title(x, y, _("Layer:")));
1461         add_tool(layer = new MPEGLayer(x1, y, this));
1462         layer->create_objects();
1464         y += 30;
1465         add_tool(new BC_Title(x, y, _("Kbits per second:")));
1466         add_tool(bitrate = new MPEGABitrate(x1, y, this));
1467         bitrate->create_objects();
1468         
1469         
1470         add_subwindow(new BC_OKButton(this));
1471         show_window();
1472         flush();
1473         return 0;
1476 int MPEGConfigAudio::close_event()
1478         set_done(0);
1479         return 1;
1488 MPEGLayer::MPEGLayer(int x, int y, MPEGConfigAudio *gui)
1489  : BC_PopupMenu(x, y, 100, layer_to_string(gui->asset->ampeg_derivative))
1491         this->gui = gui;
1494 void MPEGLayer::create_objects()
1496         add_item(new BC_MenuItem(layer_to_string(2)));
1497         add_item(new BC_MenuItem(layer_to_string(3)));
1500 int MPEGLayer::handle_event()
1502         gui->asset->ampeg_derivative = string_to_layer(get_text());
1503         gui->bitrate->set_layer(gui->asset->ampeg_derivative);
1504         return 1;
1507 int MPEGLayer::string_to_layer(char *string)
1509         if(!strcasecmp(layer_to_string(2), string))
1510                 return 2;
1511         if(!strcasecmp(layer_to_string(3), string))
1512                 return 3;
1514         return 2;
1517 char* MPEGLayer::layer_to_string(int layer)
1519         switch(layer)
1520         {
1521                 case 2:
1522                         return _("II");
1523                         break;
1524                 
1525                 case 3:
1526                         return _("III");
1527                         break;
1528                         
1529                 default:
1530                         return _("II");
1531                         break;
1532         }
1541 MPEGABitrate::MPEGABitrate(int x, int y, MPEGConfigAudio *gui)
1542  : BC_PopupMenu(x, 
1543         y, 
1544         100, 
1545         bitrate_to_string(gui->string, gui->asset->ampeg_bitrate))
1547         this->gui = gui;
1550 void MPEGABitrate::create_objects()
1552         set_layer(gui->asset->ampeg_derivative);
1555 void MPEGABitrate::set_layer(int layer)
1557         while(total_items())
1558         {
1559                 remove_item(0);
1560         }
1562         if(layer == 2)
1563         {
1564                 add_item(new BC_MenuItem("160"));
1565                 add_item(new BC_MenuItem("192"));
1566                 add_item(new BC_MenuItem("224"));
1567                 add_item(new BC_MenuItem("256"));
1568                 add_item(new BC_MenuItem("320"));
1569                 add_item(new BC_MenuItem("384"));
1570         }
1571         else
1572         {
1573                 add_item(new BC_MenuItem("8"));
1574                 add_item(new BC_MenuItem("16"));
1575                 add_item(new BC_MenuItem("24"));
1576                 add_item(new BC_MenuItem("32"));
1577                 add_item(new BC_MenuItem("40"));
1578                 add_item(new BC_MenuItem("48"));
1579                 add_item(new BC_MenuItem("56"));
1580                 add_item(new BC_MenuItem("64"));
1581                 add_item(new BC_MenuItem("80"));
1582                 add_item(new BC_MenuItem("96"));
1583                 add_item(new BC_MenuItem("112"));
1584                 add_item(new BC_MenuItem("128"));
1585                 add_item(new BC_MenuItem("144"));
1586                 add_item(new BC_MenuItem("160"));
1587                 add_item(new BC_MenuItem("192"));
1588                 add_item(new BC_MenuItem("224"));
1589                 add_item(new BC_MenuItem("256"));
1590                 add_item(new BC_MenuItem("320"));
1591         }
1594 int MPEGABitrate::handle_event()
1596         gui->asset->ampeg_bitrate = string_to_bitrate(get_text());
1597         return 1;
1600 int MPEGABitrate::string_to_bitrate(char *string)
1602         return atol(string);
1606 char* MPEGABitrate::bitrate_to_string(char *string, int bitrate)
1608         sprintf(string, "%d", bitrate);
1609         return string;
1620 MPEGConfigVideo::MPEGConfigVideo(BC_WindowBase *parent_window, 
1621         Asset *asset)
1622  : BC_Window(PROGRAM_NAME ": Video Compression",
1623         parent_window->get_abs_cursor_x(1),
1624         parent_window->get_abs_cursor_y(1),
1625         500,
1626         400,
1627         -1,
1628         -1,
1629         0,
1630         0,
1631         1)
1633         this->parent_window = parent_window;
1634         this->asset = asset;
1635         reset_cmodel();
1638 MPEGConfigVideo::~MPEGConfigVideo()
1642 int MPEGConfigVideo::create_objects()
1644         int x = 10, y = 10;
1645         int x1 = x + 150;
1646         int x2 = x + 300;
1648         if(asset->format == FILE_MPEG)
1649         {
1650                 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1651                 return 0;
1652         }
1654         add_subwindow(new BC_Title(x, y, _("Color model:")));
1655         add_subwindow(cmodel = new MPEGColorModel(x1, y, this));
1656         cmodel->create_objects();
1657         y += 30;
1659         update_cmodel_objs();
1661         add_subwindow(new BC_OKButton(this));
1662         show_window();
1663         flush();
1664         return 0;
1667 int MPEGConfigVideo::close_event()
1669         set_done(0);
1670         return 1;
1674 void MPEGConfigVideo::delete_cmodel_objs()
1676         delete preset;
1677         delete derivative;
1678         delete bitrate;
1679         delete fixed_bitrate;
1680         delete quant;
1681         delete fixed_quant;
1682         delete iframe_distance;
1683         delete pframe_distance;
1684         delete top_field_first;
1685         delete progressive;
1686         delete denoise;
1687         delete seq_codes;
1688         titles.remove_all_objects();
1689         reset_cmodel();
1692 void MPEGConfigVideo::reset_cmodel()
1694         preset = 0;
1695         derivative = 0;
1696         bitrate = 0;
1697         fixed_bitrate = 0;
1698         quant = 0;
1699         fixed_quant = 0;
1700         iframe_distance = 0;
1701         pframe_distance = 0;
1702         top_field_first = 0;
1703         progressive = 0;
1704         denoise = 0;
1705         seq_codes = 0;
1708 void MPEGConfigVideo::update_cmodel_objs()
1710         BC_Title *title;
1711         int x = 10;
1712         int y = 40;
1713         int x1 = x + 150;
1714         int x2 = x + 280;
1716         delete_cmodel_objs();
1718         if(asset->vmpeg_cmodel == MPEG_YUV420)
1719         {
1720                 add_subwindow(title = new BC_Title(x, y + 5, _("Format Preset:")));
1721                 titles.append(title);
1722                 add_subwindow(preset = new MPEGPreset(x1, y, this));
1723                 preset->create_objects();
1724                 y += 30;
1725         }
1727         add_subwindow(title = new BC_Title(x, y + 5, _("Derivative:")));
1728         titles.append(title);
1729         add_subwindow(derivative = new MPEGDerivative(x1, y, this));
1730         derivative->create_objects();
1731         y += 30;
1733         add_subwindow(title = new BC_Title(x, y + 5, _("Bitrate:")));
1734         titles.append(title);
1735         add_subwindow(bitrate = new MPEGBitrate(x1, y, this));
1736         add_subwindow(fixed_bitrate = new MPEGFixedBitrate(x2, y, this));
1737         y += 30;
1739         add_subwindow(title = new BC_Title(x, y, _("Quantization:")));
1740         titles.append(title);
1741         quant = new MPEGQuant(x1, y, this);
1742         quant->create_objects();
1743         add_subwindow(fixed_quant = new MPEGFixedQuant(x2, y, this));
1744         y += 30;
1746         add_subwindow(title = new BC_Title(x, y, _("I frame distance:")));
1747         titles.append(title);
1748         iframe_distance = new MPEGIFrameDistance(x1, y, this);
1749         iframe_distance->create_objects();
1750         y += 30;
1752         if(asset->vmpeg_cmodel == MPEG_YUV420)
1753         {
1754                 add_subwindow(title = new BC_Title(x, y, _("P frame distance:")));
1755                 titles.append(title);
1756                 pframe_distance = new MPEGPFrameDistance(x1, y, this);
1757                 pframe_distance->create_objects();
1758                 y += 30;
1760                 add_subwindow(top_field_first = new BC_CheckBox(x, y, &asset->vmpeg_field_order, _("Bottom field first")));
1761                 y += 30;
1762         }
1764         add_subwindow(progressive = new BC_CheckBox(x, y, &asset->vmpeg_progressive, _("Progressive frames")));
1765         y += 30;
1766         add_subwindow(denoise = new BC_CheckBox(x, y, &asset->vmpeg_denoise, _("Denoise")));
1767         y += 30;
1768         add_subwindow(seq_codes = new BC_CheckBox(x, y, &asset->vmpeg_seq_codes, _("Sequence start codes in every GOP")));
1784 MPEGDerivative::MPEGDerivative(int x, int y, MPEGConfigVideo *gui)
1785  : BC_PopupMenu(x, y, 150, derivative_to_string(gui->asset->vmpeg_derivative))
1787         this->gui = gui;
1790 void MPEGDerivative::create_objects()
1792         add_item(new BC_MenuItem(derivative_to_string(1)));
1793         add_item(new BC_MenuItem(derivative_to_string(2)));
1796 int MPEGDerivative::handle_event()
1798         gui->asset->vmpeg_derivative = string_to_derivative(get_text());
1799         return 1;
1802 int MPEGDerivative::string_to_derivative(char *string)
1804         if(!strcasecmp(derivative_to_string(1), string))
1805                 return 1;
1806         if(!strcasecmp(derivative_to_string(2), string))
1807                 return 2;
1809         return 1;
1812 char* MPEGDerivative::derivative_to_string(int derivative)
1814         switch(derivative)
1815         {
1816                 case 1:
1817                         return _("MPEG-1");
1818                         break;
1819                 
1820                 case 2:
1821                         return _("MPEG-2");
1822                         break;
1823                         
1824                 default:
1825                         return _("MPEG-1");
1826                         break;
1827         }
1840 MPEGPreset::MPEGPreset(int x, int y, MPEGConfigVideo *gui)
1841  : BC_PopupMenu(x, y, 200, value_to_string(gui->asset->vmpeg_preset))
1843         this->gui = gui;
1846 void MPEGPreset::create_objects()
1848         for(int i = 0; i < 10; i++)
1849         {
1850                 add_item(new BC_MenuItem(value_to_string(i)));
1851         }
1854 int MPEGPreset::handle_event()
1856         gui->asset->vmpeg_preset = string_to_value(get_text());
1857         return 1;
1860 int MPEGPreset::string_to_value(char *string)
1862         for(int i = 0; i < 10; i++)
1863         {
1864                 if(!strcasecmp(value_to_string(i), string))
1865                         return i;
1866         }
1867         return 0;
1870 char* MPEGPreset::value_to_string(int derivative)
1872         switch(derivative)
1873         {
1874                 case 0: return _("Generic MPEG-1"); break;
1875                 case 1: return _("standard VCD"); break;
1876                 case 2: return _("user VCD"); break;
1877                 case 3: return _("Generic MPEG-2"); break;
1878                 case 4: return _("standard SVCD"); break;
1879                 case 5: return _("user SVCD"); break;
1880                 case 6: return _("VCD Still sequence"); break;
1881                 case 7: return _("SVCD Still sequence"); break;
1882                 case 8: return _("DVD NAV"); break;
1883                 case 9: return _("DVD"); break;
1884                 default: return _("Generic MPEG-1"); break;
1885         }
1898 MPEGBitrate::MPEGBitrate(int x, int y, MPEGConfigVideo *gui)
1899  : BC_TextBox(x, y, 100, 1, gui->asset->vmpeg_bitrate)
1901         this->gui = gui;
1905 int MPEGBitrate::handle_event()
1907         gui->asset->vmpeg_bitrate = atol(get_text());
1908         return 1;
1915 MPEGQuant::MPEGQuant(int x, int y, MPEGConfigVideo *gui)
1916  : BC_TumbleTextBox(gui, 
1917         (int64_t)gui->asset->vmpeg_quantization, 
1918         (int64_t)1,
1919         (int64_t)100,
1920         x, 
1921         y,
1922         100)
1924         this->gui = gui;
1927 int MPEGQuant::handle_event()
1929         gui->asset->vmpeg_quantization = atol(get_text());
1930         return 1;
1933 MPEGFixedBitrate::MPEGFixedBitrate(int x, int y, MPEGConfigVideo *gui)
1934  : BC_Radial(x, y, gui->asset->vmpeg_fix_bitrate, _("Fixed bitrate"))
1936         this->gui = gui;
1939 int MPEGFixedBitrate::handle_event()
1941         update(1);
1942         gui->asset->vmpeg_fix_bitrate = 1;
1943         gui->fixed_quant->update(0);
1944         return 1;
1947 MPEGFixedQuant::MPEGFixedQuant(int x, int y, MPEGConfigVideo *gui)
1948  : BC_Radial(x, y, !gui->asset->vmpeg_fix_bitrate, _("Fixed quantization"))
1950         this->gui = gui;
1953 int MPEGFixedQuant::handle_event()
1955         update(1);
1956         gui->asset->vmpeg_fix_bitrate = 0;
1957         gui->fixed_bitrate->update(0);
1958         return 1;
1969 MPEGIFrameDistance::MPEGIFrameDistance(int x, int y, MPEGConfigVideo *gui)
1970  : BC_TumbleTextBox(gui, 
1971         (int64_t)gui->asset->vmpeg_iframe_distance, 
1972         (int64_t)1,
1973         (int64_t)100,
1974         x, 
1975         y,
1976         50)
1978         this->gui = gui;
1981 int MPEGIFrameDistance::handle_event()
1983         gui->asset->vmpeg_iframe_distance = atoi(get_text());
1984         return 1;
1993 MPEGPFrameDistance::MPEGPFrameDistance(int x, int y, MPEGConfigVideo *gui)
1994  : BC_TumbleTextBox(gui, 
1995         (int64_t)gui->asset->vmpeg_pframe_distance, 
1996         (int64_t)0,
1997         (int64_t)2,
1998         x, 
1999         y,
2000         50)
2002         this->gui = gui;
2005 int MPEGPFrameDistance::handle_event()
2007         gui->asset->vmpeg_pframe_distance = atoi(get_text());
2008         return 1;
2018 MPEGColorModel::MPEGColorModel(int x, int y, MPEGConfigVideo *gui)
2019  : BC_PopupMenu(x, y, 150, cmodel_to_string(gui->asset->vmpeg_cmodel))
2021         this->gui = gui;
2024 void MPEGColorModel::create_objects()
2026         add_item(new BC_MenuItem(cmodel_to_string(0)));
2027         add_item(new BC_MenuItem(cmodel_to_string(1)));
2030 int MPEGColorModel::handle_event()
2032         gui->asset->vmpeg_cmodel = string_to_cmodel(get_text());
2033         gui->update_cmodel_objs();
2034         return 1;
2037 int MPEGColorModel::string_to_cmodel(char *string)
2039         if(!strcasecmp(cmodel_to_string(0), string))
2040                 return 0;
2041         if(!strcasecmp(cmodel_to_string(1), string))
2042                 return 1;
2043         return 1;
2046 char* MPEGColorModel::cmodel_to_string(int cmodel)
2048         switch(cmodel)
2049         {
2050                 case MPEG_YUV420:
2051                         return _("YUV 4:2:0");
2052                         break;
2053                 
2054                 case MPEG_YUV422:
2055                         return _("YUV 4:2:2");
2056                         break;
2057                         
2058                 default:
2059                         return _("YUV 4:2:0");
2060                         break;
2061         }