r932: When playing update clocks only, not all zoombar widgets
[cinelerra_cv/mob.git] / cinelerra / filempeg.C
blobd11b58c3f2fac2cb419823bf8ff1f83f109217e3
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 / 1000);
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         int need_toc = 1;
528 // Test existing copy of TOC
529         if((fd = mpeg3_open(index_filename, &error)))
530                 need_toc = 0;
532         if(need_toc)
533         {
534 // Create progress window.
535 // This gets around the fact that MWindowGUI is locked.
536                 char progress_title[BCTEXTLEN];
537                 char string[BCTEXTLEN];
538                 sprintf(progress_title, "Creating %s\n", index_filename);
539                 int64_t total_bytes;
540                 mpeg3_t *index_file = mpeg3_start_toc(asset->path, index_filename, &total_bytes);
541                 struct timeval new_time;
542                 struct timeval prev_time;
543                 struct timeval start_time;
544                 struct timeval current_time;
545                 gettimeofday(&prev_time, 0);
546                 gettimeofday(&start_time, 0);
548                 BC_ProgressBox *progress = new BC_ProgressBox(-1, 
549                         -1, 
550                         progress_title, 
551                         total_bytes);
552                 progress->start();
553                 int result = 0;
554                 while(1)
555                 {
556                         int64_t bytes_processed;
557                         mpeg3_do_toc(index_file, &bytes_processed);
558                         gettimeofday(&new_time, 0);
560                         if(new_time.tv_sec - prev_time.tv_sec >= 1)
561                         {
562                                 gettimeofday(&current_time, 0);
563                                 int64_t elapsed_seconds = current_time.tv_sec - start_time.tv_sec;
564                                 int64_t total_seconds = elapsed_seconds * total_bytes / bytes_processed;
565                                 int64_t eta = total_seconds - elapsed_seconds;
566                                 progress->update(bytes_processed, 1);
567                                 sprintf(string, 
568                                         "%sETA: %lldm%llds",
569                                         progress_title,
570                                         eta / 60,
571                                         eta % 60);
572                                 progress->update_title(string, 1);
573 //                              fprintf(stderr, "ETA: %dm%ds        \r", 
574 //                                      bytes_processed * 100 / total_bytes,
575 //                                      eta / 60,
576 //                                      eta % 60);
577 //                              fflush(stdout);
578                                 prev_time = new_time;
579                         }
580                         if(bytes_processed >= total_bytes) break;
581                         if(progress->is_cancelled()) 
582                         {
583                                 result = 1;
584                                 break;
585                         }
586                 }
588                 mpeg3_stop_toc(index_file);
590                 progress->stop_progress();
591                 delete progress;
593 // Remove if error
594                 if(result)
595                 {
596                         remove(index_filename);
597                         return 1;
598                 }
599                 else
600 // Fix date to date of source if success
601                 {
602                 }
604                 if(fd) mpeg3_close(fd);
605                 fd = 0;
606         }
610 // Reopen file from index path instead of asset path.
611         if(!fd)
612         {
613                 if(!(fd = mpeg3_open(index_filename, &error)))
614                 {
615                         return 1;
616                 }
617                 else
618                         return 0;
619         }
621         return 0;
629 void FileMPEG::append_vcommand_line(const char *string)
631         if(string[0])
632         {
633                 char *argv = strdup(string);
634                 vcommand_line.append(argv);
635         }
638 void FileMPEG::append_acommand_line(const char *string)
640         if(string[0])
641         {
642                 char *argv = strdup(string);
643                 acommand_line.append(argv);
644         }
648 int FileMPEG::close_file()
650         mjpeg_eof = 1;
651         next_frame_lock->unlock();
653         if(fd)
654         {
655                 mpeg3_close(fd);
656         }
658         if(video_out)
659         {
660 // End of sequence signal
661                 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
662                 {
663                         mpeg2enc_set_input_buffers(1, 0, 0, 0);
664                 }
665                 delete video_out;
666                 video_out = 0;
667         }
669         vcommand_line.remove_all_objects();
670         acommand_line.remove_all_objects();
672         if(audio_out)
673         {
674                 toolame_send_buffer(0, 0);
675                 delete audio_out;
676                 audio_out = 0;
677         }
679         if(lame_global)
680                 lame_close(lame_global);
682         if(temp_frame) delete temp_frame;
683         if(toolame_temp) delete [] toolame_temp;
685         if(lame_temp[0]) delete [] lame_temp[0];
686         if(lame_temp[1]) delete [] lame_temp[1];
687         if(lame_output) delete [] lame_output;
688         if(lame_fd) fclose(lame_fd);
690         if(mjpeg_out) fclose(mjpeg_out);
693         if(dvb_out)
694                 fclose(dvb_out);
696         reset_parameters();
698         FileBase::close_file();
699         return 0;
702 int FileMPEG::get_best_colormodel(Asset *asset, int driver)
704 //printf("FileMPEG::get_best_colormodel 1\n");
705         switch(driver)
706         {
707                 case PLAYBACK_X11:
708                         return BC_RGB888;
709                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
710                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
711                         break;
712                 case PLAYBACK_X11_XV:
713                 case PLAYBACK_ASYNCHRONOUS:
714                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
715                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
716                         break;
717                 case PLAYBACK_X11_GL:
718                         return BC_YUV888;
719                         break;
720                 case PLAYBACK_LML:
721                 case PLAYBACK_BUZ:
722                         return BC_YUV422P;
723                         break;
724                 case PLAYBACK_DV1394:
725                 case PLAYBACK_FIREWIRE:
726                         return BC_YUV422P;
727                         break;
728                 case VIDEO4LINUX:
729                 case VIDEO4LINUX2:
730                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
731                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
732                         break;
733                 case CAPTURE_BUZ:
734                 case CAPTURE_LML:
735                         return BC_YUV422;
736                         break;
737                 case CAPTURE_FIREWIRE:
738                 case CAPTURE_IEC61883:
739                         return BC_YUV422P;
740                         break;
741         }
742 //printf("FileMPEG::get_best_colormodel 100\n");
745 int FileMPEG::colormodel_supported(int colormodel)
747         return colormodel;
750 int FileMPEG::get_index(char *index_path)
752         if(!fd) return 1;
755 // Convert the index tables from tracks to channels.
756         if(mpeg3_index_tracks(fd))
757         {
758 // Calculate size of buffer needed for all channels
759                 int buffer_size = 0;
760                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
761                 {
762                         buffer_size += mpeg3_index_size(fd, i) *
763                                 mpeg3_index_channels(fd, i) *
764                                 2;
765                 }
767                 asset->index_buffer = new float[buffer_size];
769 // Size of index buffer in floats
770                 int current_offset = 0;
771 // Current asset channel
772                 int current_channel = 0;
773                 asset->index_zoom = mpeg3_index_zoom(fd);
774                 asset->index_offsets = new int64_t[asset->channels];
775                 asset->index_sizes = new int64_t[asset->channels];
776                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
777                 {
778                         for(int j = 0; j < mpeg3_index_channels(fd, i); j++)
779                         {
780                                 asset->index_offsets[current_channel] = current_offset;
781                                 asset->index_sizes[current_channel] = mpeg3_index_size(fd, i) * 2;
782                                 memcpy(asset->index_buffer + current_offset,
783                                         mpeg3_index_data(fd, i, j),
784                                         mpeg3_index_size(fd, i) * sizeof(float) * 2);
786                                 current_offset += mpeg3_index_size(fd, i) * 2;
787                                 current_channel++;
788                         }
789                 }
791                 FileSystem fs;
792                 asset->index_bytes = fs.get_size(asset->path);
794                 asset->write_index(index_path, buffer_size * sizeof(float));
795                 delete [] asset->index_buffer;
797                 return 0;
798         }
800         return 1;
804 int FileMPEG::can_copy_from(Edit *edit, int64_t position)
806         if(!fd) return 0;
807         return 0;
810 int FileMPEG::set_audio_position(int64_t sample)
812 #if 0
813         if(!fd) return 1;
814         
815         int channel, stream;
816         to_streamchannel(file->current_channel, stream, channel);
818 //printf("FileMPEG::set_audio_position %d %d %d\n", sample, mpeg3_get_sample(fd, stream), last_sample);
819         if(sample != mpeg3_get_sample(fd, stream) &&
820                 sample != last_sample)
821         {
822                 if(sample >= 0 && sample < asset->audio_length)
823                 {
824 //printf("FileMPEG::set_audio_position seeking stream %d\n", sample);
825                         return mpeg3_set_sample(fd, sample, stream);
826                 }
827                 else
828                         return 1;
829         }
830 #endif
831         return 0;
834 int FileMPEG::set_video_position(int64_t x)
836         if(!fd) return 1;
837         if(x >= 0 && x < asset->video_length)
838         {
839 //printf("FileMPEG::set_video_position 1 %lld\n", x);
840                 mpeg3_set_frame(fd, x, file->current_layer);
841         }
842         else
843                 return 1;
846 int64_t FileMPEG::get_memory_usage()
848         if(rd && fd)
849         {
850                 int64_t result = mpeg3_memory_usage(fd);
851                 return result;
852         }
853         return 0;
857 int FileMPEG::write_samples(double **buffer, int64_t len)
859         int result = 0;
861 //printf("FileMPEG::write_samples 1\n");
862         if(asset->ampeg_derivative == 2)
863         {
864 // Convert to int16
865                 int channels = MIN(asset->channels, 2);
866                 int64_t audio_size = len * channels * 2;
867                 if(toolame_allocation < audio_size)
868                 {
869                         if(toolame_temp) delete [] toolame_temp;
870                         toolame_temp = new unsigned char[audio_size];
871                         toolame_allocation = audio_size;
872                 }
874                 for(int i = 0; i < channels; i++)
875                 {
876                         int16_t *output = ((int16_t*)toolame_temp) + i;
877                         double *input = buffer[i];
878                         for(int j = 0; j < len; j++)
879                         {
880                                 int sample = (int)(*input * 0x7fff);
881                                 *output = (int16_t)(CLIP(sample, -0x8000, 0x7fff));
882                                 output += channels;
883                                 input++;
884                         }
885                 }
886                 result = toolame_send_buffer((char*)toolame_temp, audio_size);
887         }
888         else
889         if(asset->ampeg_derivative == 3)
890         {
891                 int channels = MIN(asset->channels, 2);
892                 int64_t audio_size = len * channels;
893                 if(!lame_global) return 1;
894                 if(!lame_fd) return 1;
895                 if(lame_allocation < audio_size)
896                 {
897                         if(lame_temp[0]) delete [] lame_temp[0];
898                         if(lame_temp[1]) delete [] lame_temp[1];
899                         lame_temp[0] = new float[audio_size];
900                         lame_temp[1] = new float[audio_size];
901                         lame_allocation = audio_size;
902                 }
904                 if(lame_output_allocation < audio_size * 4)
905                 {
906                         if(lame_output) delete [] lame_output;
907                         lame_output_allocation = audio_size * 4;
908                         lame_output = new char[lame_output_allocation];
909                 }
911                 for(int i = 0; i < channels; i++)
912                 {
913                         float *output = lame_temp[i];
914                         double *input = buffer[i];
915                         for(int j = 0; j < len; j++)
916                         {
917                                 *output++ = *input++ * (float)32768;
918                         }
919                 }
921                 result = lame_encode_buffer_float(lame_global,
922                         lame_temp[0],
923                         (channels > 1) ? lame_temp[1] : lame_temp[0],
924                         len,
925                         (unsigned char*)lame_output,
926                         lame_output_allocation);
927                 if(result > 0)
928                 {
929                         char *real_output = lame_output;
930                         int bytes = result;
931                         if(!lame_started)
932                         {
933                                 for(int i = 0; i < bytes; i++)
934                                         if(lame_output[i])
935                                         {
936                                                 real_output = &lame_output[i];
937                                                 lame_started = 1;
938                                                 bytes -= i;
939                                                 break;
940                                         }
941                         }
942                         if(bytes > 0 && lame_started)
943                         {
944                                 result = !fwrite(real_output, 1, bytes, lame_fd);
945                                 if(result)
946                                         eprintf("Error while writing samples");
947                         }
948                         else
949                                 result = 0;
950                 }
951                 else
952                         result = 1;
953         }
955         return result;
958 int FileMPEG::write_frames(VFrame ***frames, int len)
960         int result = 0;
962         if(video_out)
963         {
964                 int temp_w = (int)((asset->width + 15) / 16) * 16;
965                 int temp_h;
968                 int output_cmodel = 
969                         (asset->vmpeg_cmodel == MPEG_YUV420) ? BC_YUV420P : BC_YUV422P;
970                 
971                 
972 // Height depends on progressiveness
973                 if(asset->vmpeg_progressive || asset->vmpeg_derivative == 1)
974                         temp_h = (int)((asset->height + 15) / 16) * 16;
975                 else
976                         temp_h = (int)((asset->height + 31) / 32) * 32;
978 //printf("FileMPEG::write_frames 1\n");
979                 
980 // Only 1 layer is supported in MPEG output
981                 for(int i = 0; i < 1; i++)
982                 {
983                         for(int j = 0; j < len && !result; j++)
984                         {
985                                 VFrame *frame = frames[i][j];
986                                 
987                                 
988                                 
989                                 if(asset->vmpeg_cmodel == MPEG_YUV422)
990                                 {
991                                         if(frame->get_w() == temp_w &&
992                                                 frame->get_h() == temp_h &&
993                                                 frame->get_color_model() == output_cmodel)
994                                         {
995                                                 mpeg2enc_set_input_buffers(0, 
996                                                         (char*)frame->get_y(),
997                                                         (char*)frame->get_u(),
998                                                         (char*)frame->get_v());
999                                         }
1000                                         else
1001                                         {
1002                                                 if(temp_frame &&
1003                                                         (temp_frame->get_w() != temp_w ||
1004                                                         temp_frame->get_h() != temp_h ||
1005                                                         temp_frame->get_color_model() || output_cmodel))
1006                                                 {
1007                                                         delete temp_frame;
1008                                                         temp_frame = 0;
1009                                                 }
1012                                                 if(!temp_frame)
1013                                                 {
1014                                                         temp_frame = new VFrame(0, 
1015                                                                 temp_w, 
1016                                                                 temp_h, 
1017                                                                 output_cmodel);
1018                                                 }
1020                                                 cmodel_transfer(temp_frame->get_rows(), 
1021                                                         frame->get_rows(),
1022                                                         temp_frame->get_y(),
1023                                                         temp_frame->get_u(),
1024                                                         temp_frame->get_v(),
1025                                                         frame->get_y(),
1026                                                         frame->get_u(),
1027                                                         frame->get_v(),
1028                                                         0,
1029                                                         0,
1030                                                         asset->width,
1031                                                         asset->height,
1032                                                         0,
1033                                                         0,
1034                                                         asset->width,
1035                                                         asset->height,
1036                                                         frame->get_color_model(), 
1037                                                         temp_frame->get_color_model(),
1038                                                         0, 
1039                                                         frame->get_w(),
1040                                                         temp_w);
1042                                                 mpeg2enc_set_input_buffers(0, 
1043                                                         (char*)temp_frame->get_y(),
1044                                                         (char*)temp_frame->get_u(),
1045                                                         (char*)temp_frame->get_v());
1046                                         }
1047                                 }
1048                                 else
1049                                 {
1050 // MJPEG uses the same dimensions as the input
1051                                         if(frame->get_color_model() == output_cmodel)
1052                                         {
1053                                                 mjpeg_y = frame->get_y();
1054                                                 mjpeg_u = frame->get_u();
1055                                                 mjpeg_v = frame->get_v();
1056                                         }
1057                                         else
1058                                         {
1059                                                 if(!temp_frame)
1060                                                 {
1061                                                         temp_frame = new VFrame(0, 
1062                                                                 asset->width, 
1063                                                                 asset->height, 
1064                                                                 output_cmodel);
1065                                                 }
1067                                                 cmodel_transfer(temp_frame->get_rows(), 
1068                                                         frame->get_rows(),
1069                                                         temp_frame->get_y(),
1070                                                         temp_frame->get_u(),
1071                                                         temp_frame->get_v(),
1072                                                         frame->get_y(),
1073                                                         frame->get_u(),
1074                                                         frame->get_v(),
1075                                                         0,
1076                                                         0,
1077                                                         asset->width,
1078                                                         asset->height,
1079                                                         0,
1080                                                         0,
1081                                                         asset->width,
1082                                                         asset->height,
1083                                                         frame->get_color_model(), 
1084                                                         temp_frame->get_color_model(),
1085                                                         0, 
1086                                                         frame->get_w(),
1087                                                         temp_w);
1089                                                 mjpeg_y = temp_frame->get_y();
1090                                                 mjpeg_u = temp_frame->get_u();
1091                                                 mjpeg_v = temp_frame->get_v();
1092                                         }
1097                                         next_frame_lock->unlock();
1098                                         next_frame_done->lock("FileMPEG::write_frames");
1099                                         if(mjpeg_error) result = 1;
1100                                 }
1106                         }
1107                 }
1108         }
1112         return result;
1115 int FileMPEG::read_frame(VFrame *frame)
1117         if(!fd) return 1;
1118         int result = 0;
1119         int src_cmodel;
1121 // printf("FileMPEG::read_frame\n");
1122 // frame->dump_stacks();
1123 // frame->dump_params();
1125         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV420P)
1126                 src_cmodel = BC_YUV420P;
1127         else
1128         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV422P)
1129                 src_cmodel = BC_YUV422P;
1131         switch(frame->get_color_model())
1132         {
1133                 case MPEG3_RGB565:
1134                 case MPEG3_BGR888:
1135                 case MPEG3_BGRA8888:
1136                 case MPEG3_RGB888:
1137                 case MPEG3_RGBA8888:
1138                 case MPEG3_RGBA16161616:
1139 SET_TRACE
1140                         mpeg3_read_frame(fd, 
1141                                         frame->get_rows(), /* Array of pointers to the start of each output row */
1142                                         0,                    /* Location in input frame to take picture */
1143                                         0, 
1144                                         asset->width, 
1145                                         asset->height, 
1146                                         asset->width,                   /* Dimensions of output_rows */
1147                                         asset->height, 
1148                                         frame->get_color_model(),             /* One of the color model #defines */
1149                                         file->current_layer);
1150 SET_TRACE
1151                         break;
1153 // Use Temp
1154                 default:
1155 // Read these directly
1156                         if(frame->get_color_model() == src_cmodel)
1157                         {
1158 SET_TRACE
1159                                 mpeg3_read_yuvframe(fd,
1160                                         (char*)frame->get_y(),
1161                                         (char*)frame->get_u(),
1162                                         (char*)frame->get_v(),
1163                                         0,
1164                                         0,
1165                                         asset->width,
1166                                         asset->height,
1167                                         file->current_layer);
1168 SET_TRACE
1169                         }
1170                         else
1171 // Process through temp frame
1172                         {
1173                                 char *y, *u, *v;
1174 SET_TRACE
1175                                 mpeg3_read_yuvframe_ptr(fd,
1176                                         &y,
1177                                         &u,
1178                                         &v,
1179                                         file->current_layer);
1180 SET_TRACE
1181                                 if(y && u && v)
1182                                 {
1183                                         cmodel_transfer(frame->get_rows(), 
1184                                                 0,
1185                                                 frame->get_y(),
1186                                                 frame->get_u(),
1187                                                 frame->get_v(),
1188                                                 (unsigned char*)y,
1189                                                 (unsigned char*)u,
1190                                                 (unsigned char*)v,
1191                                                 0,
1192                                                 0,
1193                                                 asset->width,
1194                                                 asset->height,
1195                                                 0,
1196                                                 0,
1197                                                 asset->width,
1198                                                 asset->height,
1199                                                 src_cmodel, 
1200                                                 frame->get_color_model(),
1201                                                 0, 
1202                                                 asset->width,
1203                                                 frame->get_w());
1204                                 }
1205                         }
1206                         break;
1207         }
1209 SET_TRACE
1210         return result;
1214 void FileMPEG::to_streamchannel(int channel, int &stream_out, int &channel_out)
1216         for(stream_out = 0, channel_out = file->current_channel; 
1217                 stream_out < mpeg3_total_astreams(fd) && 
1218                         channel_out >= mpeg3_audio_channels(fd, stream_out);
1219                 channel_out -= mpeg3_audio_channels(fd, stream_out), stream_out++)
1220         ;
1223 int FileMPEG::read_samples(double *buffer, int64_t len)
1225         if(!fd) return 0;
1226         if(len < 0) return 0;
1228 // This is directed to a FileMPEGBuffer
1229         float *temp_float = new float[len];
1230 // Translate pure channel to a stream and a channel in the mpeg stream
1231         int stream, channel;
1232         to_streamchannel(file->current_channel, stream, channel);
1233         
1234         
1235         
1236 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1238         mpeg3_set_sample(fd, 
1239                 file->current_sample,
1240                 stream);
1241         mpeg3_read_audio(fd, 
1242                 temp_float,      /* Pointer to pre-allocated buffer of floats */
1243                 0,      /* Pointer to pre-allocated buffer of int16's */
1244                 channel,          /* Channel to decode */
1245                 len,         /* Number of samples to decode */
1246                 stream);          /* Stream containing the channel */
1249 //      last_sample = file->current_sample;
1250         for(int i = 0; i < len; i++) buffer[i] = temp_float[i];
1252         delete [] temp_float;
1253         return 0;
1256 int FileMPEG::prefer_samples_float()
1258         return 1;
1261 int FileMPEG::read_samples_float(float *buffer, int64_t len)
1263         if(!fd) return 0;
1265 // Translate pure channel to a stream and a channel in the mpeg stream
1266         int stream, channel;
1267         to_streamchannel(file->current_channel, stream, channel);
1268         
1269         
1270 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1272         mpeg3_set_sample(fd, 
1273                 file->current_sample,
1274                 stream);
1275         mpeg3_read_audio(fd, 
1276                 buffer,         /* Pointer to pre-allocated buffer of floats */
1277                 0,              /* Pointer to pre-allocated buffer of int16's */
1278                 channel,          /* Channel to decode */
1279                 len,         /* Number of samples to decode */
1280                 stream);          /* Stream containing the channel */
1283 //      last_sample = file->current_sample;
1285 //printf("FileMPEG::read_samples 100\n");
1286         return 0;
1291 char* FileMPEG::strtocompression(char *string)
1293         return "";
1296 char* FileMPEG::compressiontostr(char *string)
1298         return "";
1307 FileMPEGVideo::FileMPEGVideo(FileMPEG *file)
1308  : Thread(1, 0, 0)
1310         this->file = file;
1311         
1312         
1313         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1314         {
1315                 mpeg2enc_init_buffers();
1316                 mpeg2enc_set_w(file->asset->width);
1317                 mpeg2enc_set_h(file->asset->height);
1318                 mpeg2enc_set_rate(file->asset->frame_rate);
1319         }
1322 FileMPEGVideo::~FileMPEGVideo()
1324         Thread::join();
1327 void FileMPEGVideo::run()
1329         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1330         {
1331                 printf("FileMPEGVideo::run ");
1332                 for(int i = 0; i < file->vcommand_line.total; i++)
1333                 printf("%s ", file->vcommand_line.values[i]);
1334                 printf("\n");
1335                 mpeg2enc(file->vcommand_line.total, file->vcommand_line.values);
1336         }
1337         else
1338         {
1339                 while(1)
1340                 {
1341                         file->next_frame_lock->lock("FileMPEGVideo::run");
1342                         if(file->mjpeg_eof) 
1343                         {
1344                                 file->next_frame_done->unlock();
1345                                 break;
1346                         }
1350 // YUV4 sequence header
1351                         if(!file->wrote_header)
1352                         {
1353                                 file->wrote_header = 1;
1355                                 char string[BCTEXTLEN];
1356                                 char interlace_string[BCTEXTLEN];
1357                                 if(!file->asset->vmpeg_progressive)
1358                                 {
1359                                         sprintf(interlace_string, file->asset->vmpeg_field_order ? "b" : "t");
1360                                 }
1361                                 else
1362                                 {
1363                                         sprintf(interlace_string, "p");
1364                                 }
1366                                 fprintf(file->mjpeg_out, "YUV4MPEG2 W%d H%d F%d:%d I%s A%d:%d C%s\n",
1367                                         file->asset->width,
1368                                         file->asset->height,
1369                                         (int)(file->asset->frame_rate * 1001),
1370                                         1001,
1371                                         interlace_string,
1372                                         (int)(file->asset->aspect_ratio * 1000),
1373                                         1000,
1374                                         "420mpeg2");
1375                         }
1377 // YUV4 frame header
1378                         fprintf(file->mjpeg_out, "FRAME\n");
1380 // YUV data
1381                         if(!fwrite(file->mjpeg_y, file->asset->width * file->asset->height, 1, file->mjpeg_out))
1382                                 file->mjpeg_error = 1;
1383                         if(!fwrite(file->mjpeg_u, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1384                                 file->mjpeg_error = 1;
1385                         if(!fwrite(file->mjpeg_v, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1386                                 file->mjpeg_error = 1;
1387                         fflush(file->mjpeg_out);
1389                         file->next_frame_done->unlock();
1390                 }
1391                 pclose(file->mjpeg_out);
1392                 file->mjpeg_out = 0;
1393         }
1415 FileMPEGAudio::FileMPEGAudio(FileMPEG *file)
1416  : Thread(1, 0, 0)
1418         this->file = file;
1419         toolame_init_buffers();
1422 FileMPEGAudio::~FileMPEGAudio()
1424         Thread::join();
1427 void FileMPEGAudio::run()
1429         file->toolame_result = toolame(file->acommand_line.total, file->acommand_line.values);
1439 MPEGConfigAudio::MPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1440  : BC_Window(PROGRAM_NAME ": Audio Compression",
1441         parent_window->get_abs_cursor_x(1),
1442         parent_window->get_abs_cursor_y(1),
1443         310,
1444         120,
1445         -1,
1446         -1,
1447         0,
1448         0,
1449         1)
1451         this->parent_window = parent_window;
1452         this->asset = asset;
1455 MPEGConfigAudio::~MPEGConfigAudio()
1459 int MPEGConfigAudio::create_objects()
1461         int x = 10, y = 10;
1462         int x1 = 150;
1463         MPEGLayer *layer;
1466         if(asset->format == FILE_MPEG)
1467         {
1468                 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1469                 return 0;
1470         }
1473         add_tool(new BC_Title(x, y, _("Layer:")));
1474         add_tool(layer = new MPEGLayer(x1, y, this));
1475         layer->create_objects();
1477         y += 30;
1478         add_tool(new BC_Title(x, y, _("Kbits per second:")));
1479         add_tool(bitrate = new MPEGABitrate(x1, y, this));
1480         bitrate->create_objects();
1481         
1482         
1483         add_subwindow(new BC_OKButton(this));
1484         show_window();
1485         flush();
1486         return 0;
1489 int MPEGConfigAudio::close_event()
1491         set_done(0);
1492         return 1;
1501 MPEGLayer::MPEGLayer(int x, int y, MPEGConfigAudio *gui)
1502  : BC_PopupMenu(x, y, 100, layer_to_string(gui->asset->ampeg_derivative))
1504         this->gui = gui;
1507 void MPEGLayer::create_objects()
1509         add_item(new BC_MenuItem(layer_to_string(2)));
1510         add_item(new BC_MenuItem(layer_to_string(3)));
1513 int MPEGLayer::handle_event()
1515         gui->asset->ampeg_derivative = string_to_layer(get_text());
1516         gui->bitrate->set_layer(gui->asset->ampeg_derivative);
1517         return 1;
1520 int MPEGLayer::string_to_layer(char *string)
1522         if(!strcasecmp(layer_to_string(2), string))
1523                 return 2;
1524         if(!strcasecmp(layer_to_string(3), string))
1525                 return 3;
1527         return 2;
1530 char* MPEGLayer::layer_to_string(int layer)
1532         switch(layer)
1533         {
1534                 case 2:
1535                         return _("II");
1536                         break;
1537                 
1538                 case 3:
1539                         return _("III");
1540                         break;
1541                         
1542                 default:
1543                         return _("II");
1544                         break;
1545         }
1554 MPEGABitrate::MPEGABitrate(int x, int y, MPEGConfigAudio *gui)
1555  : BC_PopupMenu(x, 
1556         y, 
1557         100, 
1558         bitrate_to_string(gui->string, gui->asset->ampeg_bitrate))
1560         this->gui = gui;
1563 void MPEGABitrate::create_objects()
1565         set_layer(gui->asset->ampeg_derivative);
1568 void MPEGABitrate::set_layer(int layer)
1570         while(total_items())
1571         {
1572                 remove_item(0);
1573         }
1575         if(layer == 2)
1576         {
1577                 add_item(new BC_MenuItem("160"));
1578                 add_item(new BC_MenuItem("192"));
1579                 add_item(new BC_MenuItem("224"));
1580                 add_item(new BC_MenuItem("256"));
1581                 add_item(new BC_MenuItem("320"));
1582                 add_item(new BC_MenuItem("384"));
1583         }
1584         else
1585         {
1586                 add_item(new BC_MenuItem("8"));
1587                 add_item(new BC_MenuItem("16"));
1588                 add_item(new BC_MenuItem("24"));
1589                 add_item(new BC_MenuItem("32"));
1590                 add_item(new BC_MenuItem("40"));
1591                 add_item(new BC_MenuItem("48"));
1592                 add_item(new BC_MenuItem("56"));
1593                 add_item(new BC_MenuItem("64"));
1594                 add_item(new BC_MenuItem("80"));
1595                 add_item(new BC_MenuItem("96"));
1596                 add_item(new BC_MenuItem("112"));
1597                 add_item(new BC_MenuItem("128"));
1598                 add_item(new BC_MenuItem("144"));
1599                 add_item(new BC_MenuItem("160"));
1600                 add_item(new BC_MenuItem("192"));
1601                 add_item(new BC_MenuItem("224"));
1602                 add_item(new BC_MenuItem("256"));
1603                 add_item(new BC_MenuItem("320"));
1604         }
1607 int MPEGABitrate::handle_event()
1609         gui->asset->ampeg_bitrate = string_to_bitrate(get_text());
1610         return 1;
1613 int MPEGABitrate::string_to_bitrate(char *string)
1615         return atol(string);
1619 char* MPEGABitrate::bitrate_to_string(char *string, int bitrate)
1621         sprintf(string, "%d", bitrate);
1622         return string;
1633 MPEGConfigVideo::MPEGConfigVideo(BC_WindowBase *parent_window, 
1634         Asset *asset)
1635  : BC_Window(PROGRAM_NAME ": Video Compression",
1636         parent_window->get_abs_cursor_x(1),
1637         parent_window->get_abs_cursor_y(1),
1638         500,
1639         400,
1640         -1,
1641         -1,
1642         0,
1643         0,
1644         1)
1646         this->parent_window = parent_window;
1647         this->asset = asset;
1648         reset_cmodel();
1651 MPEGConfigVideo::~MPEGConfigVideo()
1655 int MPEGConfigVideo::create_objects()
1657         int x = 10, y = 10;
1658         int x1 = x + 150;
1659         int x2 = x + 300;
1661         if(asset->format == FILE_MPEG)
1662         {
1663                 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1664                 return 0;
1665         }
1667         add_subwindow(new BC_Title(x, y, _("Color model:")));
1668         add_subwindow(cmodel = new MPEGColorModel(x1, y, this));
1669         cmodel->create_objects();
1670         y += 30;
1672         update_cmodel_objs();
1674         add_subwindow(new BC_OKButton(this));
1675         show_window();
1676         flush();
1677         return 0;
1680 int MPEGConfigVideo::close_event()
1682         set_done(0);
1683         return 1;
1687 void MPEGConfigVideo::delete_cmodel_objs()
1689         delete preset;
1690         delete derivative;
1691         delete bitrate;
1692         delete fixed_bitrate;
1693         delete quant;
1694         delete fixed_quant;
1695         delete iframe_distance;
1696         delete pframe_distance;
1697         delete top_field_first;
1698         delete progressive;
1699         delete denoise;
1700         delete seq_codes;
1701         titles.remove_all_objects();
1702         reset_cmodel();
1705 void MPEGConfigVideo::reset_cmodel()
1707         preset = 0;
1708         derivative = 0;
1709         bitrate = 0;
1710         fixed_bitrate = 0;
1711         quant = 0;
1712         fixed_quant = 0;
1713         iframe_distance = 0;
1714         pframe_distance = 0;
1715         top_field_first = 0;
1716         progressive = 0;
1717         denoise = 0;
1718         seq_codes = 0;
1721 void MPEGConfigVideo::update_cmodel_objs()
1723         BC_Title *title;
1724         int x = 10;
1725         int y = 40;
1726         int x1 = x + 150;
1727         int x2 = x + 280;
1729         delete_cmodel_objs();
1731         if(asset->vmpeg_cmodel == MPEG_YUV420)
1732         {
1733                 add_subwindow(title = new BC_Title(x, y + 5, _("Format Preset:")));
1734                 titles.append(title);
1735                 add_subwindow(preset = new MPEGPreset(x1, y, this));
1736                 preset->create_objects();
1737                 y += 30;
1738         }
1740         add_subwindow(title = new BC_Title(x, y + 5, _("Derivative:")));
1741         titles.append(title);
1742         add_subwindow(derivative = new MPEGDerivative(x1, y, this));
1743         derivative->create_objects();
1744         y += 30;
1746         add_subwindow(title = new BC_Title(x, y + 5, _("Bitrate:")));
1747         titles.append(title);
1748         add_subwindow(bitrate = new MPEGBitrate(x1, y, this));
1749         add_subwindow(fixed_bitrate = new MPEGFixedBitrate(x2, y, this));
1750         y += 30;
1752         add_subwindow(title = new BC_Title(x, y, _("Quantization:")));
1753         titles.append(title);
1754         quant = new MPEGQuant(x1, y, this);
1755         quant->create_objects();
1756         add_subwindow(fixed_quant = new MPEGFixedQuant(x2, y, this));
1757         y += 30;
1759         add_subwindow(title = new BC_Title(x, y, _("I frame distance:")));
1760         titles.append(title);
1761         iframe_distance = new MPEGIFrameDistance(x1, y, this);
1762         iframe_distance->create_objects();
1763         y += 30;
1765         if(asset->vmpeg_cmodel == MPEG_YUV420)
1766         {
1767                 add_subwindow(title = new BC_Title(x, y, _("P frame distance:")));
1768                 titles.append(title);
1769                 pframe_distance = new MPEGPFrameDistance(x1, y, this);
1770                 pframe_distance->create_objects();
1771                 y += 30;
1773                 add_subwindow(top_field_first = new BC_CheckBox(x, y, &asset->vmpeg_field_order, _("Bottom field first")));
1774                 y += 30;
1775         }
1777         add_subwindow(progressive = new BC_CheckBox(x, y, &asset->vmpeg_progressive, _("Progressive frames")));
1778         y += 30;
1779         add_subwindow(denoise = new BC_CheckBox(x, y, &asset->vmpeg_denoise, _("Denoise")));
1780         y += 30;
1781         add_subwindow(seq_codes = new BC_CheckBox(x, y, &asset->vmpeg_seq_codes, _("Sequence start codes in every GOP")));
1797 MPEGDerivative::MPEGDerivative(int x, int y, MPEGConfigVideo *gui)
1798  : BC_PopupMenu(x, y, 150, derivative_to_string(gui->asset->vmpeg_derivative))
1800         this->gui = gui;
1803 void MPEGDerivative::create_objects()
1805         add_item(new BC_MenuItem(derivative_to_string(1)));
1806         add_item(new BC_MenuItem(derivative_to_string(2)));
1809 int MPEGDerivative::handle_event()
1811         gui->asset->vmpeg_derivative = string_to_derivative(get_text());
1812         return 1;
1815 int MPEGDerivative::string_to_derivative(char *string)
1817         if(!strcasecmp(derivative_to_string(1), string))
1818                 return 1;
1819         if(!strcasecmp(derivative_to_string(2), string))
1820                 return 2;
1822         return 1;
1825 char* MPEGDerivative::derivative_to_string(int derivative)
1827         switch(derivative)
1828         {
1829                 case 1:
1830                         return _("MPEG-1");
1831                         break;
1832                 
1833                 case 2:
1834                         return _("MPEG-2");
1835                         break;
1836                         
1837                 default:
1838                         return _("MPEG-1");
1839                         break;
1840         }
1853 MPEGPreset::MPEGPreset(int x, int y, MPEGConfigVideo *gui)
1854  : BC_PopupMenu(x, y, 200, value_to_string(gui->asset->vmpeg_preset))
1856         this->gui = gui;
1859 void MPEGPreset::create_objects()
1861         for(int i = 0; i < 10; i++)
1862         {
1863                 add_item(new BC_MenuItem(value_to_string(i)));
1864         }
1867 int MPEGPreset::handle_event()
1869         gui->asset->vmpeg_preset = string_to_value(get_text());
1870         return 1;
1873 int MPEGPreset::string_to_value(char *string)
1875         for(int i = 0; i < 10; i++)
1876         {
1877                 if(!strcasecmp(value_to_string(i), string))
1878                         return i;
1879         }
1880         return 0;
1883 char* MPEGPreset::value_to_string(int derivative)
1885         switch(derivative)
1886         {
1887                 case 0: return _("Generic MPEG-1"); break;
1888                 case 1: return _("standard VCD"); break;
1889                 case 2: return _("user VCD"); break;
1890                 case 3: return _("Generic MPEG-2"); break;
1891                 case 4: return _("standard SVCD"); break;
1892                 case 5: return _("user SVCD"); break;
1893                 case 6: return _("VCD Still sequence"); break;
1894                 case 7: return _("SVCD Still sequence"); break;
1895                 case 8: return _("DVD NAV"); break;
1896                 case 9: return _("DVD"); break;
1897                 default: return _("Generic MPEG-1"); break;
1898         }
1911 MPEGBitrate::MPEGBitrate(int x, int y, MPEGConfigVideo *gui)
1912  : BC_TextBox(x, y, 100, 1, gui->asset->vmpeg_bitrate)
1914         this->gui = gui;
1918 int MPEGBitrate::handle_event()
1920         gui->asset->vmpeg_bitrate = atol(get_text());
1921         return 1;
1928 MPEGQuant::MPEGQuant(int x, int y, MPEGConfigVideo *gui)
1929  : BC_TumbleTextBox(gui, 
1930         (int64_t)gui->asset->vmpeg_quantization, 
1931         (int64_t)1,
1932         (int64_t)100,
1933         x, 
1934         y,
1935         100)
1937         this->gui = gui;
1940 int MPEGQuant::handle_event()
1942         gui->asset->vmpeg_quantization = atol(get_text());
1943         return 1;
1946 MPEGFixedBitrate::MPEGFixedBitrate(int x, int y, MPEGConfigVideo *gui)
1947  : BC_Radial(x, y, gui->asset->vmpeg_fix_bitrate, _("Fixed bitrate"))
1949         this->gui = gui;
1952 int MPEGFixedBitrate::handle_event()
1954         update(1);
1955         gui->asset->vmpeg_fix_bitrate = 1;
1956         gui->fixed_quant->update(0);
1957         return 1;
1960 MPEGFixedQuant::MPEGFixedQuant(int x, int y, MPEGConfigVideo *gui)
1961  : BC_Radial(x, y, !gui->asset->vmpeg_fix_bitrate, _("Fixed quantization"))
1963         this->gui = gui;
1966 int MPEGFixedQuant::handle_event()
1968         update(1);
1969         gui->asset->vmpeg_fix_bitrate = 0;
1970         gui->fixed_bitrate->update(0);
1971         return 1;
1982 MPEGIFrameDistance::MPEGIFrameDistance(int x, int y, MPEGConfigVideo *gui)
1983  : BC_TumbleTextBox(gui, 
1984         (int64_t)gui->asset->vmpeg_iframe_distance, 
1985         (int64_t)1,
1986         (int64_t)100,
1987         x, 
1988         y,
1989         50)
1991         this->gui = gui;
1994 int MPEGIFrameDistance::handle_event()
1996         gui->asset->vmpeg_iframe_distance = atoi(get_text());
1997         return 1;
2006 MPEGPFrameDistance::MPEGPFrameDistance(int x, int y, MPEGConfigVideo *gui)
2007  : BC_TumbleTextBox(gui, 
2008         (int64_t)gui->asset->vmpeg_pframe_distance, 
2009         (int64_t)0,
2010         (int64_t)2,
2011         x, 
2012         y,
2013         50)
2015         this->gui = gui;
2018 int MPEGPFrameDistance::handle_event()
2020         gui->asset->vmpeg_pframe_distance = atoi(get_text());
2021         return 1;
2031 MPEGColorModel::MPEGColorModel(int x, int y, MPEGConfigVideo *gui)
2032  : BC_PopupMenu(x, y, 150, cmodel_to_string(gui->asset->vmpeg_cmodel))
2034         this->gui = gui;
2037 void MPEGColorModel::create_objects()
2039         add_item(new BC_MenuItem(cmodel_to_string(0)));
2040         add_item(new BC_MenuItem(cmodel_to_string(1)));
2043 int MPEGColorModel::handle_event()
2045         gui->asset->vmpeg_cmodel = string_to_cmodel(get_text());
2046         gui->update_cmodel_objs();
2047         return 1;
2050 int MPEGColorModel::string_to_cmodel(char *string)
2052         if(!strcasecmp(cmodel_to_string(0), string))
2053                 return 0;
2054         if(!strcasecmp(cmodel_to_string(1), string))
2055                 return 1;
2056         return 1;
2059 char* MPEGColorModel::cmodel_to_string(int cmodel)
2061         switch(cmodel)
2062         {
2063                 case MPEG_YUV420:
2064                         return _("YUV 4:2:0");
2065                         break;
2066                 
2067                 case MPEG_YUV422:
2068                         return _("YUV 4:2:2");
2069                         break;
2070                         
2071                 default:
2072                         return _("YUV 4:2:0");
2073                         break;
2074         }