r863: Merge 2.1:
[cinelerra_cv/ct.git] / cinelerra / filempeg.C
blob6fb38accd585bb3b4705024ee71b7d47e708fb7c
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                                 sprintf(string, 
178                                         "Couldn't open %s because it has an invalid table of contents version.\n"
179                                         "Rebuild the table of contents with mpeg3toc.",
180                                         asset->path);
181                                 MainError::show_error(string);
182                         }
183                         else
184                         if(error == MPEG3_TOC_DATE_MISMATCH)
185                         {
186                                 sprintf(string, 
187                                         "Couldn't open %s because the table of contents date differs from the source date.\n"
188                                         "Rebuild the table of contents with mpeg3toc.",
189                                         asset->path);
190                                 MainError::show_error(string);
191                         }
192                         result = 1;
193                 }
194                 else
195                 {
196 // Determine if the file needs a table of contents and create one if needed.
197 // If it has video it must be scanned since video has keyframes.
198                         if(mpeg3_total_vstreams(fd))
199                         {
200                                 if(create_index()) return 1;
201                         }
203                         mpeg3_set_cpus(fd, file->cpus);
205                         asset->audio_data = mpeg3_has_audio(fd);
206                         if(asset->audio_data)
207                         {
208                                 asset->channels = 0;
209                                 for(int i = 0; i < mpeg3_total_astreams(fd); i++)
210                                 {
211                                         asset->channels += mpeg3_audio_channels(fd, i);
212                                 }
213                                 if(!asset->sample_rate)
214                                         asset->sample_rate = mpeg3_sample_rate(fd, 0);
215                                 asset->audio_length = mpeg3_audio_samples(fd, 0); 
216                         }
218                         asset->video_data = mpeg3_has_video(fd);
219                         if(asset->video_data)
220                         {
221                                 asset->layers = mpeg3_total_vstreams(fd);
222                                 asset->width = mpeg3_video_width(fd, 0);
223                                 asset->height = mpeg3_video_height(fd, 0);
224                                 asset->interlace_mode = BC_ILACE_MODE_UNDETECTED; // TODO: (to do this, start at hvirtualcvs/libmpeg3/headers.c 
225                                                                                   //        and find out how to decode info from the header)
226                                 asset->video_length = mpeg3_video_frames(fd, 0);
227                                 asset->vmpeg_cmodel = 
228                                         (mpeg3_colormodel(fd, 0) == MPEG3_YUV422P) ? MPEG_YUV422 : MPEG_YUV420;
229                                 if(!asset->frame_rate)
230                                         asset->frame_rate = mpeg3_frame_rate(fd, 0);
232 // Enable subtitles
233 //printf("FileMPEG::open %d\n", file->playback_subtitle);
234                                 if(file->playback_subtitle >= 0)
235                                         mpeg3_show_subtitle(fd, file->playback_subtitle);
236                         }
237                 }
238         }
241         
242         if(wr && asset->format == FILE_VMPEG)
243         {
244 // Heroine Virtual encoder
245                 if(asset->vmpeg_cmodel == MPEG_YUV422)
246                 {
247                         char bitrate_string[BCTEXTLEN];
248                         char quant_string[BCTEXTLEN];
249                         char iframe_string[BCTEXTLEN];
251                         sprintf(bitrate_string, "%d", asset->vmpeg_bitrate);
252                         sprintf(quant_string, "%d", asset->vmpeg_quantization);
253                         sprintf(iframe_string, "%d", asset->vmpeg_iframe_distance);
255 // Construct command line
256                         if(!result)
257                         {
258                                 append_vcommand_line("mpeg2enc");
261                                 if(asset->aspect_ratio > 0)
262                                 {
263                                         append_vcommand_line("-a");
264                                         if(EQUIV(asset->aspect_ratio, 1))
265                                                 append_vcommand_line("1");
266                                         else
267                                         if(EQUIV(asset->aspect_ratio, 1.333))
268                                                 append_vcommand_line("2");
269                                         else
270                                         if(EQUIV(asset->aspect_ratio, 1.777))
271                                                 append_vcommand_line("3");
272                                         else
273                                         if(EQUIV(asset->aspect_ratio, 2.11))
274                                                 append_vcommand_line("4");
275                                 }
277                                 append_vcommand_line(asset->vmpeg_derivative == 1 ? "-1" : "");
278                                 append_vcommand_line(asset->vmpeg_cmodel == MPEG_YUV422 ? "-422" : "");
279                                 if(asset->vmpeg_fix_bitrate)
280                                 {
281                                         append_vcommand_line("--cbr -b");
282                                         append_vcommand_line(bitrate_string);
283                                 }
284                                 else
285                                 {
286                                         append_vcommand_line("-q");
287                                         append_vcommand_line(quant_string);
288                                 }
289                                 append_vcommand_line(!asset->vmpeg_fix_bitrate ? quant_string : "");
290                                 append_vcommand_line("-n");
291                                 append_vcommand_line(iframe_string);
292                                 append_vcommand_line(asset->vmpeg_progressive ? "-p" : "");
293                                 append_vcommand_line(asset->vmpeg_denoise ? "-d" : "");
294                                 append_vcommand_line(file->cpus <= 1 ? "-u" : "");
295                                 append_vcommand_line(asset->vmpeg_seq_codes ? "-g" : "");
296                                 append_vcommand_line(asset->path);
298                                 video_out = new FileMPEGVideo(this);
299                                 video_out->start();
300                         }
301                 }
302                 else
303 // mjpegtools encoder
304                 {
305                         char string[BCTEXTLEN];
306                         sprintf(mjpeg_command, MJPEG_EXE);
308 // Must disable interlacing if MPEG-1
309                         switch (asset->vmpeg_preset)
310                         {
311                                 case 0: asset->vmpeg_progressive = 1; break;
312                                 case 1: asset->vmpeg_progressive = 1; break;
313                                 case 2: asset->vmpeg_progressive = 1; break;
314                         }
318 // The current usage of mpeg2enc requires bitrate of 0 when quantization is fixed and
319 // quantization of 1 when bitrate is fixed.  Perfectly intuitive.
320                         if(asset->vmpeg_fix_bitrate)
321                         {
322                                 sprintf(string, " -b %d -q 1", asset->vmpeg_bitrate / 1000);
323                         }
324                         else
325                         {
326                                 sprintf(string, " -b 0 -q %d", asset->vmpeg_quantization);
327                         }
328                         strcat(mjpeg_command, string);
335 // Aspect ratio
336                         int aspect_ratio_code = -1;
337                         if(asset->aspect_ratio > 0)
338                         {
339                                 for(int i = 0; i < sizeof(aspect_ratio_codes) / sizeof(double); i++)
340                                 {
341                                         if(EQUIV(aspect_ratio_codes[i], asset->aspect_ratio))
342                                         {
343                                                 aspect_ratio_code = i;
344                                                 break;
345                                         }
346                                 }
347                         }
348                         if(aspect_ratio_code < 0)
349                         {
350                                 printf("FileMPEG::open_file: Unsupported aspect ratio %f\n", asset->aspect_ratio);
351                                 aspect_ratio_code = 2;
352                         }
353                         sprintf(string, " -a %d", aspect_ratio_code);
354                         strcat(mjpeg_command, string);
361 // Frame rate
362                         int frame_rate_code = -1;
363                 for(int i = 1; sizeof(frame_rate_codes) / sizeof(double); ++i)
364                         {
365                                 if(EQUIV(asset->frame_rate, frame_rate_codes[i]))
366                                 {
367                                         frame_rate_code = i;
368                                         break;
369                                 }
370                         }
371                         if(frame_rate_code < 0)
372                         {
373                                 frame_rate_code = 4;
374                                 printf("FileMPEG::open_file: Unsupported frame rate %f\n", asset->frame_rate);
375                         }
376                         sprintf(string, " -F %d", frame_rate_code);
377                         strcat(mjpeg_command, string);
383                         strcat(mjpeg_command, 
384                                 asset->vmpeg_progressive ? " -I 0" : " -I 1");
385                         
388                         sprintf(string, " -M %d", file->cpus);
389                         strcat(mjpeg_command, string);
392                         if(!asset->vmpeg_progressive)
393                         {
394                                 strcat(mjpeg_command, asset->vmpeg_field_order ? " -z b" : " -z t");
395                         }
398                         sprintf(string, " -f %d", asset->vmpeg_preset);
399                         strcat(mjpeg_command, string);
402                         sprintf(string, " -g %d -G %d", asset->vmpeg_iframe_distance, asset->vmpeg_iframe_distance);
403                         strcat(mjpeg_command, string);
406                         if(asset->vmpeg_seq_codes) strcat(mjpeg_command, " -s");
409                         sprintf(string, " -R %d", CLAMP(asset->vmpeg_pframe_distance, 0, 2));
410                         strcat(mjpeg_command, string);
412                         sprintf(string, " -o '%s'", asset->path);
413                         strcat(mjpeg_command, string);
417                         printf("FileMPEG::open_file: Running %s\n", mjpeg_command);
418                         if(!(mjpeg_out = popen(mjpeg_command, "w")))
419                         {
420                                 perror("FileMPEG::open_file");
421                         }
423                         video_out = new FileMPEGVideo(this);
424                         video_out->start();
425                 }
426         }
427         else
428         if(wr && asset->format == FILE_AMPEG)
429         {
430                 char command_line[BCTEXTLEN];
431                 char encoder_string[BCTEXTLEN];
432                 char argument_string[BCTEXTLEN];
434 //printf("FileMPEG::open_file 1 %d\n", asset->ampeg_derivative);
435                 encoder_string[0] = 0;
437                 if(asset->ampeg_derivative == 2)
438                 {
439                         char string[BCTEXTLEN];
440                         append_acommand_line("toolame");
441                         append_acommand_line("-m");
442                         append_acommand_line((asset->channels >= 2) ? "j" : "m");
443                         sprintf(string, "%f", (float)asset->sample_rate / 1000);
444                         append_acommand_line("-s");
445                         append_acommand_line(string);
446                         sprintf(string, "%d", asset->ampeg_bitrate);
447                         append_acommand_line("-b");
448                         append_acommand_line(string);
449                         append_acommand_line("-");
450                         append_acommand_line(asset->path);
452                         audio_out = new FileMPEGAudio(this);
453                         audio_out->start();
454                 }
455                 else
456                 if(asset->ampeg_derivative == 3)
457                 {
458                         lame_global = lame_init();
459                         lame_set_brate(lame_global, asset->ampeg_bitrate / 1000);
460                         lame_set_quality(lame_global, 0);
461                         lame_set_in_samplerate(lame_global, 
462                                 asset->sample_rate);
463                         lame_set_num_channels(lame_global,
464                                 asset->channels);
465                         if((result = lame_init_params(lame_global)) < 0)
466                         {
467                                 printf(_("encode: lame_init_params returned %d\n"), result);
468                                 lame_close(lame_global);
469                                 lame_global = 0;
470                         }
471                         else
472                         if(!(lame_fd = fopen(asset->path, "w")))
473                         {
474                                 perror("FileMPEG::open_file");
475                                 lame_close(lame_global);
476                                 lame_global = 0;
477                                 result = 1;
478                         }
479                 }
480                 else
481                 {
482                         printf("FileMPEG::open_file: ampeg_derivative=%d\n", asset->ampeg_derivative);
483                         result = 1;
484                 }
485         }
486         else
487 // Transport stream for DVB capture
488         if(wr)
489         {
490                 if(!(dvb_out = fopen(asset->path, "w")))
491                 {
492                         perror("FileMPEG::open_file");
493                         result = 1;
494                 }
495                 
496         }
499 //asset->dump();
500 SET_TRACE
501         return result;
511 int FileMPEG::create_index()
513 // Calculate TOC path
514         char index_filename[BCTEXTLEN];
515         char source_filename[BCTEXTLEN];
516         IndexFile::get_index_filename(source_filename, 
517                 file->preferences->index_directory, 
518                 index_filename, 
519                 asset->path);
520         char *ptr = strrchr(index_filename, '.');
521         int error = 0;
523         if(!ptr) return 1;
525 // File is a table of contents.
526         if(fd && mpeg3_has_toc(fd)) return 0;
528         sprintf(ptr, ".toc");
530         int need_toc = 1;
532 // Test existing copy of TOC
533         if((fd = mpeg3_open(index_filename, &error)))
534                 need_toc = 0;
536         if(need_toc)
537         {
538 // Create progress window.
539 // This gets around the fact that MWindowGUI is locked.
540                 char progress_title[BCTEXTLEN];
541                 char string[BCTEXTLEN];
542                 sprintf(progress_title, "Creating %s\n", index_filename);
543                 int64_t total_bytes;
544                 mpeg3_t *index_file = mpeg3_start_toc(asset->path, index_filename, &total_bytes);
545                 struct timeval new_time;
546                 struct timeval prev_time;
547                 struct timeval start_time;
548                 struct timeval current_time;
549                 gettimeofday(&prev_time, 0);
550                 gettimeofday(&start_time, 0);
552                 BC_ProgressBox *progress = new BC_ProgressBox(-1, 
553                         -1, 
554                         progress_title, 
555                         total_bytes);
556                 progress->start();
557                 int result = 0;
558                 while(1)
559                 {
560                         int64_t bytes_processed;
561                         mpeg3_do_toc(index_file, &bytes_processed);
562                         gettimeofday(&new_time, 0);
564                         if(new_time.tv_sec - prev_time.tv_sec >= 1)
565                         {
566                                 gettimeofday(&current_time, 0);
567                                 int64_t elapsed_seconds = current_time.tv_sec - start_time.tv_sec;
568                                 int64_t total_seconds = elapsed_seconds * total_bytes / bytes_processed;
569                                 int64_t eta = total_seconds - elapsed_seconds;
570                                 progress->update(bytes_processed, 1);
571                                 sprintf(string, 
572                                         "%sETA: %lldm%llds",
573                                         progress_title,
574                                         eta / 60,
575                                         eta % 60);
576                                 progress->update_title(string, 1);
577 //                              fprintf(stderr, "ETA: %dm%ds        \r", 
578 //                                      bytes_processed * 100 / total_bytes,
579 //                                      eta / 60,
580 //                                      eta % 60);
581 //                              fflush(stdout);
582                                 prev_time = new_time;
583                         }
584                         if(bytes_processed >= total_bytes) break;
585                         if(progress->is_cancelled()) 
586                         {
587                                 result = 1;
588                                 break;
589                         }
590                 }
592                 mpeg3_stop_toc(index_file);
594                 progress->stop_progress();
595                 delete progress;
597 // Remove if error
598                 if(result)
599                 {
600                         remove(index_filename);
601                         return 1;
602                 }
603                 else
604 // Fix date to date of source if success
605                 {
606                 }
608                 if(fd) mpeg3_close(fd);
609                 fd = 0;
610         }
614 // Reopen file from index path instead of asset path.
615         if(!fd)
616         {
617                 if(!(fd = mpeg3_open(index_filename, &error)))
618                 {
619                         return 1;
620                 }
621                 else
622                         return 0;
623         }
625         return 0;
633 void FileMPEG::append_vcommand_line(const char *string)
635         if(string[0])
636         {
637                 char *argv = strdup(string);
638                 vcommand_line.append(argv);
639         }
642 void FileMPEG::append_acommand_line(const char *string)
644         if(string[0])
645         {
646                 char *argv = strdup(string);
647                 acommand_line.append(argv);
648         }
652 int FileMPEG::close_file()
654         mjpeg_eof = 1;
655         next_frame_lock->unlock();
657         if(fd)
658         {
659                 mpeg3_close(fd);
660         }
662         if(video_out)
663         {
664 // End of sequence signal
665                 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
666                 {
667                         mpeg2enc_set_input_buffers(1, 0, 0, 0);
668                 }
669                 delete video_out;
670                 video_out = 0;
671         }
673         vcommand_line.remove_all_objects();
674         acommand_line.remove_all_objects();
676         if(audio_out)
677         {
678                 toolame_send_buffer(0, 0);
679                 delete audio_out;
680                 audio_out = 0;
681         }
683         if(lame_global)
684                 lame_close(lame_global);
686         if(temp_frame) delete temp_frame;
687         if(toolame_temp) delete [] toolame_temp;
689         if(lame_temp[0]) delete [] lame_temp[0];
690         if(lame_temp[1]) delete [] lame_temp[1];
691         if(lame_output) delete [] lame_output;
692         if(lame_fd) fclose(lame_fd);
694         if(mjpeg_out) fclose(mjpeg_out);
697         if(dvb_out)
698                 fclose(dvb_out);
700         reset_parameters();
702         FileBase::close_file();
703         return 0;
706 int FileMPEG::get_best_colormodel(Asset *asset, int driver)
708 //printf("FileMPEG::get_best_colormodel 1\n");
709         switch(driver)
710         {
711                 case PLAYBACK_X11:
712                         return BC_RGB888;
713                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
714                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
715                         break;
716                 case PLAYBACK_X11_XV:
717                 case PLAYBACK_ASYNCHRONOUS:
718                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
719                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
720                         break;
721                 case PLAYBACK_X11_GL:
722                         return BC_YUV888;
723                         break;
724                 case PLAYBACK_LML:
725                 case PLAYBACK_BUZ:
726                         return BC_YUV422P;
727                         break;
728                 case PLAYBACK_DV1394:
729                 case PLAYBACK_FIREWIRE:
730                         return BC_YUV422P;
731                         break;
732                 case VIDEO4LINUX:
733                 case VIDEO4LINUX2:
734                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
735                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
736                         break;
737                 case CAPTURE_BUZ:
738                 case CAPTURE_LML:
739                         return BC_YUV422;
740                         break;
741                 case CAPTURE_FIREWIRE:
742                 case CAPTURE_IEC61883:
743                         return BC_YUV422P;
744                         break;
745         }
746 //printf("FileMPEG::get_best_colormodel 100\n");
749 int FileMPEG::colormodel_supported(int colormodel)
751         return colormodel;
754 int FileMPEG::get_index(char *index_path)
756         if(!fd) return 1;
759 // Convert the index tables from tracks to channels.
760         if(mpeg3_index_tracks(fd))
761         {
762 // Calculate size of buffer needed for all channels
763                 int buffer_size = 0;
764                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
765                 {
766                         buffer_size += mpeg3_index_size(fd, i) *
767                                 mpeg3_index_channels(fd, i) *
768                                 2;
769                 }
771                 asset->index_buffer = new float[buffer_size];
773 // Size of index buffer in floats
774                 int current_offset = 0;
775 // Current asset channel
776                 int current_channel = 0;
777                 asset->index_zoom = mpeg3_index_zoom(fd);
778                 asset->index_offsets = new int64_t[asset->channels];
779                 asset->index_sizes = new int64_t[asset->channels];
780                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
781                 {
782                         for(int j = 0; j < mpeg3_index_channels(fd, i); j++)
783                         {
784                                 asset->index_offsets[current_channel] = current_offset;
785                                 asset->index_sizes[current_channel] = mpeg3_index_size(fd, i) * 2;
786                                 memcpy(asset->index_buffer + current_offset,
787                                         mpeg3_index_data(fd, i, j),
788                                         mpeg3_index_size(fd, i) * sizeof(float) * 2);
790                                 current_offset += mpeg3_index_size(fd, i) * 2;
791                                 current_channel++;
792                         }
793                 }
795                 FileSystem fs;
796                 asset->index_bytes = fs.get_size(asset->path);
798                 asset->write_index(index_path, buffer_size * sizeof(float));
799                 delete [] asset->index_buffer;
801                 return 0;
802         }
804         return 1;
808 int FileMPEG::can_copy_from(Edit *edit, int64_t position)
810         if(!fd) return 0;
811         return 0;
814 int FileMPEG::set_audio_position(int64_t sample)
816 #if 0
817         if(!fd) return 1;
818         
819         int channel, stream;
820         to_streamchannel(file->current_channel, stream, channel);
822 //printf("FileMPEG::set_audio_position %d %d %d\n", sample, mpeg3_get_sample(fd, stream), last_sample);
823         if(sample != mpeg3_get_sample(fd, stream) &&
824                 sample != last_sample)
825         {
826                 if(sample >= 0 && sample < asset->audio_length)
827                 {
828 //printf("FileMPEG::set_audio_position seeking stream %d\n", sample);
829                         return mpeg3_set_sample(fd, sample, stream);
830                 }
831                 else
832                         return 1;
833         }
834 #endif
835         return 0;
838 int FileMPEG::set_video_position(int64_t x)
840         if(!fd) return 1;
841         if(x >= 0 && x < asset->video_length)
842         {
843 //printf("FileMPEG::set_video_position 1 %lld\n", x);
844                 mpeg3_set_frame(fd, x, file->current_layer);
845         }
846         else
847                 return 1;
850 int64_t FileMPEG::get_memory_usage()
852         if(rd && fd)
853         {
854                 int64_t result = mpeg3_memory_usage(fd);
855                 return result;
856         }
857         return 0;
861 int FileMPEG::write_samples(double **buffer, int64_t len)
863         int result = 0;
865 //printf("FileMPEG::write_samples 1\n");
866         if(asset->ampeg_derivative == 2)
867         {
868 // Convert to int16
869                 int channels = MIN(asset->channels, 2);
870                 int64_t audio_size = len * channels * 2;
871                 if(toolame_allocation < audio_size)
872                 {
873                         if(toolame_temp) delete [] toolame_temp;
874                         toolame_temp = new unsigned char[audio_size];
875                         toolame_allocation = audio_size;
876                 }
878                 for(int i = 0; i < channels; i++)
879                 {
880                         int16_t *output = ((int16_t*)toolame_temp) + i;
881                         double *input = buffer[i];
882                         for(int j = 0; j < len; j++)
883                         {
884                                 int sample = (int)(*input * 0x7fff);
885                                 *output = (int16_t)(CLIP(sample, -0x8000, 0x7fff));
886                                 output += channels;
887                                 input++;
888                         }
889                 }
890                 result = toolame_send_buffer((char*)toolame_temp, audio_size);
891         }
892         else
893         if(asset->ampeg_derivative == 3)
894         {
895                 int channels = MIN(asset->channels, 2);
896                 int64_t audio_size = len * channels;
897                 if(!lame_global) return 1;
898                 if(!lame_fd) return 1;
899                 if(lame_allocation < audio_size)
900                 {
901                         if(lame_temp[0]) delete [] lame_temp[0];
902                         if(lame_temp[1]) delete [] lame_temp[1];
903                         lame_temp[0] = new float[audio_size];
904                         lame_temp[1] = new float[audio_size];
905                         lame_allocation = audio_size;
906                 }
908                 if(lame_output_allocation < audio_size * 4)
909                 {
910                         if(lame_output) delete [] lame_output;
911                         lame_output_allocation = audio_size * 4;
912                         lame_output = new char[lame_output_allocation];
913                 }
915                 for(int i = 0; i < channels; i++)
916                 {
917                         float *output = lame_temp[i];
918                         double *input = buffer[i];
919                         for(int j = 0; j < len; j++)
920                         {
921                                 *output++ = *input++ * (float)32768;
922                         }
923                 }
925                 result = lame_encode_buffer_float(lame_global,
926                         lame_temp[0],
927                         (channels > 1) ? lame_temp[1] : lame_temp[0],
928                         len,
929                         (unsigned char*)lame_output,
930                         lame_output_allocation);
931                 if(result > 0)
932                 {
933                         char *real_output = lame_output;
934                         int bytes = result;
935                         if(!lame_started)
936                         {
937                                 for(int i = 0; i < bytes; i++)
938                                         if(lame_output[i])
939                                         {
940                                                 real_output = &lame_output[i];
941                                                 lame_started = 1;
942                                                 bytes -= i;
943                                                 break;
944                                         }
945                         }
946                         if(bytes > 0 && lame_started)
947                         {
948                                 result = !fwrite(real_output, 1, bytes, lame_fd);
949                                 if(result)
950                                         perror("FileMPEG::write_samples");
951                         }
952                         else
953                                 result = 0;
954                 }
955                 else
956                         result = 1;
957         }
959         return result;
962 int FileMPEG::write_frames(VFrame ***frames, int len)
964         int result = 0;
966         if(video_out)
967         {
968                 int temp_w = (int)((asset->width + 15) / 16) * 16;
969                 int temp_h;
972                 int output_cmodel = 
973                         (asset->vmpeg_cmodel == MPEG_YUV420) ? BC_YUV420P : BC_YUV422P;
974                 
975                 
976 // Height depends on progressiveness
977                 if(asset->vmpeg_progressive || asset->vmpeg_derivative == 1)
978                         temp_h = (int)((asset->height + 15) / 16) * 16;
979                 else
980                         temp_h = (int)((asset->height + 31) / 32) * 32;
982 //printf("FileMPEG::write_frames 1\n");
983                 
984 // Only 1 layer is supported in MPEG output
985                 for(int i = 0; i < 1; i++)
986                 {
987                         for(int j = 0; j < len && !result; j++)
988                         {
989                                 VFrame *frame = frames[i][j];
990                                 
991                                 
992                                 
993                                 if(asset->vmpeg_cmodel == MPEG_YUV422)
994                                 {
995                                         if(frame->get_w() == temp_w &&
996                                                 frame->get_h() == temp_h &&
997                                                 frame->get_color_model() == output_cmodel)
998                                         {
999                                                 mpeg2enc_set_input_buffers(0, 
1000                                                         (char*)frame->get_y(),
1001                                                         (char*)frame->get_u(),
1002                                                         (char*)frame->get_v());
1003                                         }
1004                                         else
1005                                         {
1006                                                 if(temp_frame &&
1007                                                         (temp_frame->get_w() != temp_w ||
1008                                                         temp_frame->get_h() != temp_h ||
1009                                                         temp_frame->get_color_model() || output_cmodel))
1010                                                 {
1011                                                         delete temp_frame;
1012                                                         temp_frame = 0;
1013                                                 }
1016                                                 if(!temp_frame)
1017                                                 {
1018                                                         temp_frame = new VFrame(0, 
1019                                                                 temp_w, 
1020                                                                 temp_h, 
1021                                                                 output_cmodel);
1022                                                 }
1024                                                 cmodel_transfer(temp_frame->get_rows(), 
1025                                                         frame->get_rows(),
1026                                                         temp_frame->get_y(),
1027                                                         temp_frame->get_u(),
1028                                                         temp_frame->get_v(),
1029                                                         frame->get_y(),
1030                                                         frame->get_u(),
1031                                                         frame->get_v(),
1032                                                         0,
1033                                                         0,
1034                                                         asset->width,
1035                                                         asset->height,
1036                                                         0,
1037                                                         0,
1038                                                         asset->width,
1039                                                         asset->height,
1040                                                         frame->get_color_model(), 
1041                                                         temp_frame->get_color_model(),
1042                                                         0, 
1043                                                         frame->get_w(),
1044                                                         temp_w);
1046                                                 mpeg2enc_set_input_buffers(0, 
1047                                                         (char*)temp_frame->get_y(),
1048                                                         (char*)temp_frame->get_u(),
1049                                                         (char*)temp_frame->get_v());
1050                                         }
1051                                 }
1052                                 else
1053                                 {
1054 // MJPEG uses the same dimensions as the input
1055                                         if(frame->get_color_model() == output_cmodel)
1056                                         {
1057                                                 mjpeg_y = frame->get_y();
1058                                                 mjpeg_u = frame->get_u();
1059                                                 mjpeg_v = frame->get_v();
1060                                         }
1061                                         else
1062                                         {
1063                                                 if(!temp_frame)
1064                                                 {
1065                                                         temp_frame = new VFrame(0, 
1066                                                                 asset->width, 
1067                                                                 asset->height, 
1068                                                                 output_cmodel);
1069                                                 }
1071                                                 cmodel_transfer(temp_frame->get_rows(), 
1072                                                         frame->get_rows(),
1073                                                         temp_frame->get_y(),
1074                                                         temp_frame->get_u(),
1075                                                         temp_frame->get_v(),
1076                                                         frame->get_y(),
1077                                                         frame->get_u(),
1078                                                         frame->get_v(),
1079                                                         0,
1080                                                         0,
1081                                                         asset->width,
1082                                                         asset->height,
1083                                                         0,
1084                                                         0,
1085                                                         asset->width,
1086                                                         asset->height,
1087                                                         frame->get_color_model(), 
1088                                                         temp_frame->get_color_model(),
1089                                                         0, 
1090                                                         frame->get_w(),
1091                                                         temp_w);
1093                                                 mjpeg_y = temp_frame->get_y();
1094                                                 mjpeg_u = temp_frame->get_u();
1095                                                 mjpeg_v = temp_frame->get_v();
1096                                         }
1101                                         next_frame_lock->unlock();
1102                                         next_frame_done->lock("FileMPEG::write_frames");
1103                                         if(mjpeg_error) result = 1;
1104                                 }
1110                         }
1111                 }
1112         }
1116         return result;
1119 int FileMPEG::read_frame(VFrame *frame)
1121         if(!fd) return 1;
1122         int result = 0;
1123         int src_cmodel;
1125 // printf("FileMPEG::read_frame\n");
1126 // frame->dump_stacks();
1127 // frame->dump_params();
1129         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV420P)
1130                 src_cmodel = BC_YUV420P;
1131         else
1132         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV422P)
1133                 src_cmodel = BC_YUV422P;
1135         switch(frame->get_color_model())
1136         {
1137                 case MPEG3_RGB565:
1138                 case MPEG3_BGR888:
1139                 case MPEG3_BGRA8888:
1140                 case MPEG3_RGB888:
1141                 case MPEG3_RGBA8888:
1142                 case MPEG3_RGBA16161616:
1143 SET_TRACE
1144                         mpeg3_read_frame(fd, 
1145                                         frame->get_rows(), /* Array of pointers to the start of each output row */
1146                                         0,                    /* Location in input frame to take picture */
1147                                         0, 
1148                                         asset->width, 
1149                                         asset->height, 
1150                                         asset->width,                   /* Dimensions of output_rows */
1151                                         asset->height, 
1152                                         frame->get_color_model(),             /* One of the color model #defines */
1153                                         file->current_layer);
1154 SET_TRACE
1155                         break;
1157 // Use Temp
1158                 default:
1159 // Read these directly
1160                         if(frame->get_color_model() == src_cmodel)
1161                         {
1162 SET_TRACE
1163                                 mpeg3_read_yuvframe(fd,
1164                                         (char*)frame->get_y(),
1165                                         (char*)frame->get_u(),
1166                                         (char*)frame->get_v(),
1167                                         0,
1168                                         0,
1169                                         asset->width,
1170                                         asset->height,
1171                                         file->current_layer);
1172 SET_TRACE
1173                         }
1174                         else
1175 // Process through temp frame
1176                         {
1177                                 char *y, *u, *v;
1178 SET_TRACE
1179                                 mpeg3_read_yuvframe_ptr(fd,
1180                                         &y,
1181                                         &u,
1182                                         &v,
1183                                         file->current_layer);
1184 SET_TRACE
1185                                 if(y && u && v)
1186                                 {
1187                                         cmodel_transfer(frame->get_rows(), 
1188                                                 0,
1189                                                 frame->get_y(),
1190                                                 frame->get_u(),
1191                                                 frame->get_v(),
1192                                                 (unsigned char*)y,
1193                                                 (unsigned char*)u,
1194                                                 (unsigned char*)v,
1195                                                 0,
1196                                                 0,
1197                                                 asset->width,
1198                                                 asset->height,
1199                                                 0,
1200                                                 0,
1201                                                 asset->width,
1202                                                 asset->height,
1203                                                 src_cmodel, 
1204                                                 frame->get_color_model(),
1205                                                 0, 
1206                                                 asset->width,
1207                                                 frame->get_w());
1208                                 }
1209                         }
1210                         break;
1211         }
1213 SET_TRACE
1214         return result;
1218 void FileMPEG::to_streamchannel(int channel, int &stream_out, int &channel_out)
1220         for(stream_out = 0, channel_out = file->current_channel; 
1221                 stream_out < mpeg3_total_astreams(fd) && 
1222                         channel_out >= mpeg3_audio_channels(fd, stream_out);
1223                 channel_out -= mpeg3_audio_channels(fd, stream_out), stream_out++)
1224         ;
1227 int FileMPEG::read_samples(double *buffer, int64_t len)
1229         if(!fd) return 0;
1230         if(len < 0) return 0;
1232 // This is directed to a FileMPEGBuffer
1233         float *temp_float = new float[len];
1234 // Translate pure channel to a stream and a channel in the mpeg stream
1235         int stream, channel;
1236         to_streamchannel(file->current_channel, stream, channel);
1237         
1238         
1239         
1240 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1242         mpeg3_set_sample(fd, 
1243                 file->current_sample,
1244                 stream);
1245         mpeg3_read_audio(fd, 
1246                 temp_float,      /* Pointer to pre-allocated buffer of floats */
1247                 0,      /* Pointer to pre-allocated buffer of int16's */
1248                 channel,          /* Channel to decode */
1249                 len,         /* Number of samples to decode */
1250                 stream);          /* Stream containing the channel */
1253 //      last_sample = file->current_sample;
1254         for(int i = 0; i < len; i++) buffer[i] = temp_float[i];
1256         delete [] temp_float;
1257         return 0;
1260 int FileMPEG::prefer_samples_float()
1262         return 1;
1265 int FileMPEG::read_samples_float(float *buffer, int64_t len)
1267         if(!fd) return 0;
1269 // Translate pure channel to a stream and a channel in the mpeg stream
1270         int stream, channel;
1271         to_streamchannel(file->current_channel, stream, channel);
1272         
1273         
1274 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1276         mpeg3_set_sample(fd, 
1277                 file->current_sample,
1278                 stream);
1279         mpeg3_read_audio(fd, 
1280                 buffer,         /* Pointer to pre-allocated buffer of floats */
1281                 0,              /* Pointer to pre-allocated buffer of int16's */
1282                 channel,          /* Channel to decode */
1283                 len,         /* Number of samples to decode */
1284                 stream);          /* Stream containing the channel */
1287 //      last_sample = file->current_sample;
1289 //printf("FileMPEG::read_samples 100\n");
1290         return 0;
1295 char* FileMPEG::strtocompression(char *string)
1297         return "";
1300 char* FileMPEG::compressiontostr(char *string)
1302         return "";
1311 FileMPEGVideo::FileMPEGVideo(FileMPEG *file)
1312  : Thread(1, 0, 0)
1314         this->file = file;
1315         
1316         
1317         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1318         {
1319                 mpeg2enc_init_buffers();
1320                 mpeg2enc_set_w(file->asset->width);
1321                 mpeg2enc_set_h(file->asset->height);
1322                 mpeg2enc_set_rate(file->asset->frame_rate);
1323         }
1326 FileMPEGVideo::~FileMPEGVideo()
1328         Thread::join();
1331 void FileMPEGVideo::run()
1333         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1334         {
1335                 printf("FileMPEGVideo::run ");
1336                 for(int i = 0; i < file->vcommand_line.total; i++)
1337                 printf("%s ", file->vcommand_line.values[i]);
1338                 printf("\n");
1339                 mpeg2enc(file->vcommand_line.total, file->vcommand_line.values);
1340         }
1341         else
1342         {
1343                 while(1)
1344                 {
1345                         file->next_frame_lock->lock("FileMPEGVideo::run");
1346                         if(file->mjpeg_eof) 
1347                         {
1348                                 file->next_frame_done->unlock();
1349                                 break;
1350                         }
1354 // YUV4 sequence header
1355                         if(!file->wrote_header)
1356                         {
1357                                 file->wrote_header = 1;
1359                                 char string[BCTEXTLEN];
1360                                 char interlace_string[BCTEXTLEN];
1361                                 if(!file->asset->vmpeg_progressive)
1362                                 {
1363                                         sprintf(interlace_string, file->asset->vmpeg_field_order ? "b" : "t");
1364                                 }
1365                                 else
1366                                 {
1367                                         sprintf(interlace_string, "p");
1368                                 }
1370                                 fprintf(file->mjpeg_out, "YUV4MPEG2 W%d H%d F%d:%d I%s A%d:%d C%s\n",
1371                                         file->asset->width,
1372                                         file->asset->height,
1373                                         (int)(file->asset->frame_rate * 1001),
1374                                         1001,
1375                                         interlace_string,
1376                                         (int)(file->asset->aspect_ratio * 1000),
1377                                         1000,
1378                                         "420mpeg2");
1379                         }
1381 // YUV4 frame header
1382                         fprintf(file->mjpeg_out, "FRAME\n");
1384 // YUV data
1385                         if(!fwrite(file->mjpeg_y, file->asset->width * file->asset->height, 1, file->mjpeg_out))
1386                                 file->mjpeg_error = 1;
1387                         if(!fwrite(file->mjpeg_u, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1388                                 file->mjpeg_error = 1;
1389                         if(!fwrite(file->mjpeg_v, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1390                                 file->mjpeg_error = 1;
1391                         fflush(file->mjpeg_out);
1393                         file->next_frame_done->unlock();
1394                 }
1395                 pclose(file->mjpeg_out);
1396                 file->mjpeg_out = 0;
1397         }
1419 FileMPEGAudio::FileMPEGAudio(FileMPEG *file)
1420  : Thread(1, 0, 0)
1422         this->file = file;
1423         toolame_init_buffers();
1426 FileMPEGAudio::~FileMPEGAudio()
1428         Thread::join();
1431 void FileMPEGAudio::run()
1433         file->toolame_result = toolame(file->acommand_line.total, file->acommand_line.values);
1443 MPEGConfigAudio::MPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1444  : BC_Window(PROGRAM_NAME ": Audio Compression",
1445         parent_window->get_abs_cursor_x(1),
1446         parent_window->get_abs_cursor_y(1),
1447         310,
1448         120,
1449         -1,
1450         -1,
1451         0,
1452         0,
1453         1)
1455         this->parent_window = parent_window;
1456         this->asset = asset;
1459 MPEGConfigAudio::~MPEGConfigAudio()
1463 int MPEGConfigAudio::create_objects()
1465         int x = 10, y = 10;
1466         int x1 = 150;
1467         MPEGLayer *layer;
1470         if(asset->format == FILE_MPEG)
1471         {
1472                 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1473                 return 0;
1474         }
1477         add_tool(new BC_Title(x, y, _("Layer:")));
1478         add_tool(layer = new MPEGLayer(x1, y, this));
1479         layer->create_objects();
1481         y += 30;
1482         add_tool(new BC_Title(x, y, _("Kbits per second:")));
1483         add_tool(bitrate = new MPEGABitrate(x1, y, this));
1484         bitrate->create_objects();
1485         
1486         
1487         add_subwindow(new BC_OKButton(this));
1488         show_window();
1489         flush();
1490         return 0;
1493 int MPEGConfigAudio::close_event()
1495         set_done(0);
1496         return 1;
1505 MPEGLayer::MPEGLayer(int x, int y, MPEGConfigAudio *gui)
1506  : BC_PopupMenu(x, y, 100, layer_to_string(gui->asset->ampeg_derivative))
1508         this->gui = gui;
1511 void MPEGLayer::create_objects()
1513         add_item(new BC_MenuItem(layer_to_string(2)));
1514         add_item(new BC_MenuItem(layer_to_string(3)));
1517 int MPEGLayer::handle_event()
1519         gui->asset->ampeg_derivative = string_to_layer(get_text());
1520         gui->bitrate->set_layer(gui->asset->ampeg_derivative);
1521         return 1;
1524 int MPEGLayer::string_to_layer(char *string)
1526         if(!strcasecmp(layer_to_string(2), string))
1527                 return 2;
1528         if(!strcasecmp(layer_to_string(3), string))
1529                 return 3;
1531         return 2;
1534 char* MPEGLayer::layer_to_string(int layer)
1536         switch(layer)
1537         {
1538                 case 2:
1539                         return _("II");
1540                         break;
1541                 
1542                 case 3:
1543                         return _("III");
1544                         break;
1545                         
1546                 default:
1547                         return _("II");
1548                         break;
1549         }
1558 MPEGABitrate::MPEGABitrate(int x, int y, MPEGConfigAudio *gui)
1559  : BC_PopupMenu(x, 
1560         y, 
1561         100, 
1562         bitrate_to_string(gui->string, gui->asset->ampeg_bitrate))
1564         this->gui = gui;
1567 void MPEGABitrate::create_objects()
1569         set_layer(gui->asset->ampeg_derivative);
1572 void MPEGABitrate::set_layer(int layer)
1574         while(total_items())
1575         {
1576                 remove_item(0);
1577         }
1579         if(layer == 2)
1580         {
1581                 add_item(new BC_MenuItem("160"));
1582                 add_item(new BC_MenuItem("192"));
1583                 add_item(new BC_MenuItem("224"));
1584                 add_item(new BC_MenuItem("256"));
1585                 add_item(new BC_MenuItem("320"));
1586                 add_item(new BC_MenuItem("384"));
1587         }
1588         else
1589         {
1590                 add_item(new BC_MenuItem("8"));
1591                 add_item(new BC_MenuItem("16"));
1592                 add_item(new BC_MenuItem("24"));
1593                 add_item(new BC_MenuItem("32"));
1594                 add_item(new BC_MenuItem("40"));
1595                 add_item(new BC_MenuItem("48"));
1596                 add_item(new BC_MenuItem("56"));
1597                 add_item(new BC_MenuItem("64"));
1598                 add_item(new BC_MenuItem("80"));
1599                 add_item(new BC_MenuItem("96"));
1600                 add_item(new BC_MenuItem("112"));
1601                 add_item(new BC_MenuItem("128"));
1602                 add_item(new BC_MenuItem("144"));
1603                 add_item(new BC_MenuItem("160"));
1604                 add_item(new BC_MenuItem("192"));
1605                 add_item(new BC_MenuItem("224"));
1606                 add_item(new BC_MenuItem("256"));
1607                 add_item(new BC_MenuItem("320"));
1608         }
1611 int MPEGABitrate::handle_event()
1613         gui->asset->ampeg_bitrate = string_to_bitrate(get_text());
1614         return 1;
1617 int MPEGABitrate::string_to_bitrate(char *string)
1619         return atol(string);
1623 char* MPEGABitrate::bitrate_to_string(char *string, int bitrate)
1625         sprintf(string, "%d", bitrate);
1626         return string;
1637 MPEGConfigVideo::MPEGConfigVideo(BC_WindowBase *parent_window, 
1638         Asset *asset)
1639  : BC_Window(PROGRAM_NAME ": Video Compression",
1640         parent_window->get_abs_cursor_x(1),
1641         parent_window->get_abs_cursor_y(1),
1642         500,
1643         400,
1644         -1,
1645         -1,
1646         0,
1647         0,
1648         1)
1650         this->parent_window = parent_window;
1651         this->asset = asset;
1652         reset_cmodel();
1655 MPEGConfigVideo::~MPEGConfigVideo()
1659 int MPEGConfigVideo::create_objects()
1661         int x = 10, y = 10;
1662         int x1 = x + 150;
1663         int x2 = x + 300;
1665         if(asset->format == FILE_MPEG)
1666         {
1667                 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1668                 return 0;
1669         }
1671         add_subwindow(new BC_Title(x, y, _("Color model:")));
1672         add_subwindow(cmodel = new MPEGColorModel(x1, y, this));
1673         cmodel->create_objects();
1674         y += 30;
1676         update_cmodel_objs();
1678         add_subwindow(new BC_OKButton(this));
1679         show_window();
1680         flush();
1681         return 0;
1684 int MPEGConfigVideo::close_event()
1686         set_done(0);
1687         return 1;
1691 void MPEGConfigVideo::delete_cmodel_objs()
1693         delete preset;
1694         delete derivative;
1695         delete bitrate;
1696         delete fixed_bitrate;
1697         delete quant;
1698         delete fixed_quant;
1699         delete iframe_distance;
1700         delete pframe_distance;
1701         delete top_field_first;
1702         delete progressive;
1703         delete denoise;
1704         delete seq_codes;
1705         titles.remove_all_objects();
1706         reset_cmodel();
1709 void MPEGConfigVideo::reset_cmodel()
1711         preset = 0;
1712         derivative = 0;
1713         bitrate = 0;
1714         fixed_bitrate = 0;
1715         quant = 0;
1716         fixed_quant = 0;
1717         iframe_distance = 0;
1718         pframe_distance = 0;
1719         top_field_first = 0;
1720         progressive = 0;
1721         denoise = 0;
1722         seq_codes = 0;
1725 void MPEGConfigVideo::update_cmodel_objs()
1727         BC_Title *title;
1728         int x = 10;
1729         int y = 40;
1730         int x1 = x + 150;
1731         int x2 = x + 280;
1733         delete_cmodel_objs();
1735         if(asset->vmpeg_cmodel == MPEG_YUV420)
1736         {
1737                 add_subwindow(title = new BC_Title(x, y + 5, _("Format Preset:")));
1738                 titles.append(title);
1739                 add_subwindow(preset = new MPEGPreset(x1, y, this));
1740                 preset->create_objects();
1741                 y += 30;
1742         }
1744         add_subwindow(title = new BC_Title(x, y + 5, _("Derivative:")));
1745         titles.append(title);
1746         add_subwindow(derivative = new MPEGDerivative(x1, y, this));
1747         derivative->create_objects();
1748         y += 30;
1750         add_subwindow(title = new BC_Title(x, y + 5, _("Bitrate:")));
1751         titles.append(title);
1752         add_subwindow(bitrate = new MPEGBitrate(x1, y, this));
1753         add_subwindow(fixed_bitrate = new MPEGFixedBitrate(x2, y, this));
1754         y += 30;
1756         add_subwindow(title = new BC_Title(x, y, _("Quantization:")));
1757         titles.append(title);
1758         quant = new MPEGQuant(x1, y, this);
1759         quant->create_objects();
1760         add_subwindow(fixed_quant = new MPEGFixedQuant(x2, y, this));
1761         y += 30;
1763         add_subwindow(title = new BC_Title(x, y, _("I frame distance:")));
1764         titles.append(title);
1765         iframe_distance = new MPEGIFrameDistance(x1, y, this);
1766         iframe_distance->create_objects();
1767         y += 30;
1769         if(asset->vmpeg_cmodel == MPEG_YUV420)
1770         {
1771                 add_subwindow(title = new BC_Title(x, y, _("P frame distance:")));
1772                 titles.append(title);
1773                 pframe_distance = new MPEGPFrameDistance(x1, y, this);
1774                 pframe_distance->create_objects();
1775                 y += 30;
1777                 add_subwindow(top_field_first = new BC_CheckBox(x, y, &asset->vmpeg_field_order, _("Bottom field first")));
1778                 y += 30;
1779         }
1781         add_subwindow(progressive = new BC_CheckBox(x, y, &asset->vmpeg_progressive, _("Progressive frames")));
1782         y += 30;
1783         add_subwindow(denoise = new BC_CheckBox(x, y, &asset->vmpeg_denoise, _("Denoise")));
1784         y += 30;
1785         add_subwindow(seq_codes = new BC_CheckBox(x, y, &asset->vmpeg_seq_codes, _("Sequence start codes in every GOP")));
1801 MPEGDerivative::MPEGDerivative(int x, int y, MPEGConfigVideo *gui)
1802  : BC_PopupMenu(x, y, 150, derivative_to_string(gui->asset->vmpeg_derivative))
1804         this->gui = gui;
1807 void MPEGDerivative::create_objects()
1809         add_item(new BC_MenuItem(derivative_to_string(1)));
1810         add_item(new BC_MenuItem(derivative_to_string(2)));
1813 int MPEGDerivative::handle_event()
1815         gui->asset->vmpeg_derivative = string_to_derivative(get_text());
1816         return 1;
1819 int MPEGDerivative::string_to_derivative(char *string)
1821         if(!strcasecmp(derivative_to_string(1), string))
1822                 return 1;
1823         if(!strcasecmp(derivative_to_string(2), string))
1824                 return 2;
1826         return 1;
1829 char* MPEGDerivative::derivative_to_string(int derivative)
1831         switch(derivative)
1832         {
1833                 case 1:
1834                         return _("MPEG-1");
1835                         break;
1836                 
1837                 case 2:
1838                         return _("MPEG-2");
1839                         break;
1840                         
1841                 default:
1842                         return _("MPEG-1");
1843                         break;
1844         }
1857 MPEGPreset::MPEGPreset(int x, int y, MPEGConfigVideo *gui)
1858  : BC_PopupMenu(x, y, 200, value_to_string(gui->asset->vmpeg_preset))
1860         this->gui = gui;
1863 void MPEGPreset::create_objects()
1865         for(int i = 0; i < 10; i++)
1866         {
1867                 add_item(new BC_MenuItem(value_to_string(i)));
1868         }
1871 int MPEGPreset::handle_event()
1873         gui->asset->vmpeg_preset = string_to_value(get_text());
1874         return 1;
1877 int MPEGPreset::string_to_value(char *string)
1879         for(int i = 0; i < 10; i++)
1880         {
1881                 if(!strcasecmp(value_to_string(i), string))
1882                         return i;
1883         }
1884         return 0;
1887 char* MPEGPreset::value_to_string(int derivative)
1889         switch(derivative)
1890         {
1891                 case 0: return _("Generic MPEG-1"); break;
1892                 case 1: return _("standard VCD"); break;
1893                 case 2: return _("user VCD"); break;
1894                 case 3: return _("Generic MPEG-2"); break;
1895                 case 4: return _("standard SVCD"); break;
1896                 case 5: return _("user SVCD"); break;
1897                 case 6: return _("VCD Still sequence"); break;
1898                 case 7: return _("SVCD Still sequence"); break;
1899                 case 8: return _("DVD NAV"); break;
1900                 case 9: return _("DVD"); break;
1901                 default: return _("Generic MPEG-1"); break;
1902         }
1915 MPEGBitrate::MPEGBitrate(int x, int y, MPEGConfigVideo *gui)
1916  : BC_TextBox(x, y, 100, 1, gui->asset->vmpeg_bitrate)
1918         this->gui = gui;
1922 int MPEGBitrate::handle_event()
1924         gui->asset->vmpeg_bitrate = atol(get_text());
1925         return 1;
1932 MPEGQuant::MPEGQuant(int x, int y, MPEGConfigVideo *gui)
1933  : BC_TumbleTextBox(gui, 
1934         (int64_t)gui->asset->vmpeg_quantization, 
1935         (int64_t)1,
1936         (int64_t)100,
1937         x, 
1938         y,
1939         100)
1941         this->gui = gui;
1944 int MPEGQuant::handle_event()
1946         gui->asset->vmpeg_quantization = atol(get_text());
1947         return 1;
1950 MPEGFixedBitrate::MPEGFixedBitrate(int x, int y, MPEGConfigVideo *gui)
1951  : BC_Radial(x, y, gui->asset->vmpeg_fix_bitrate, _("Fixed bitrate"))
1953         this->gui = gui;
1956 int MPEGFixedBitrate::handle_event()
1958         update(1);
1959         gui->asset->vmpeg_fix_bitrate = 1;
1960         gui->fixed_quant->update(0);
1961         return 1;
1964 MPEGFixedQuant::MPEGFixedQuant(int x, int y, MPEGConfigVideo *gui)
1965  : BC_Radial(x, y, !gui->asset->vmpeg_fix_bitrate, _("Fixed quantization"))
1967         this->gui = gui;
1970 int MPEGFixedQuant::handle_event()
1972         update(1);
1973         gui->asset->vmpeg_fix_bitrate = 0;
1974         gui->fixed_bitrate->update(0);
1975         return 1;
1986 MPEGIFrameDistance::MPEGIFrameDistance(int x, int y, MPEGConfigVideo *gui)
1987  : BC_TumbleTextBox(gui, 
1988         (int64_t)gui->asset->vmpeg_iframe_distance, 
1989         (int64_t)1,
1990         (int64_t)100,
1991         x, 
1992         y,
1993         50)
1995         this->gui = gui;
1998 int MPEGIFrameDistance::handle_event()
2000         gui->asset->vmpeg_iframe_distance = atoi(get_text());
2001         return 1;
2010 MPEGPFrameDistance::MPEGPFrameDistance(int x, int y, MPEGConfigVideo *gui)
2011  : BC_TumbleTextBox(gui, 
2012         (int64_t)gui->asset->vmpeg_pframe_distance, 
2013         (int64_t)0,
2014         (int64_t)2,
2015         x, 
2016         y,
2017         50)
2019         this->gui = gui;
2022 int MPEGPFrameDistance::handle_event()
2024         gui->asset->vmpeg_pframe_distance = atoi(get_text());
2025         return 1;
2035 MPEGColorModel::MPEGColorModel(int x, int y, MPEGConfigVideo *gui)
2036  : BC_PopupMenu(x, y, 150, cmodel_to_string(gui->asset->vmpeg_cmodel))
2038         this->gui = gui;
2041 void MPEGColorModel::create_objects()
2043         add_item(new BC_MenuItem(cmodel_to_string(0)));
2044         add_item(new BC_MenuItem(cmodel_to_string(1)));
2047 int MPEGColorModel::handle_event()
2049         gui->asset->vmpeg_cmodel = string_to_cmodel(get_text());
2050         gui->update_cmodel_objs();
2051         return 1;
2054 int MPEGColorModel::string_to_cmodel(char *string)
2056         if(!strcasecmp(cmodel_to_string(0), string))
2057                 return 0;
2058         if(!strcasecmp(cmodel_to_string(1), string))
2059                 return 1;
2060         return 1;
2063 char* MPEGColorModel::cmodel_to_string(int cmodel)
2065         switch(cmodel)
2066         {
2067                 case MPEG_YUV420:
2068                         return _("YUV 4:2:0");
2069                         break;
2070                 
2071                 case MPEG_YUV422:
2072                         return _("YUV 4:2:2");
2073                         break;
2074                         
2075                 default:
2076                         return _("YUV 4:2:0");
2077                         break;
2078         }