Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / cinelerra / filempeg.C
blob0c8a3df27e8a5fba8c31bcb02be2abe0e30d0db5
1 #include "asset.h"
2 #include "bcprogressbox.h"
3 #include "bcwidgetgrid.h"
4 #include "bcsignals.h"
5 #include "bitspopup.h"
6 #include "byteorder.h"
7 #include "clip.h"
8 #include "condition.h"
9 #include "edit.h"
10 #include "file.h"
11 #include "filempeg.h"
12 #include "filesystem.h"
13 #include "guicast.h"
14 #include "indexfile.h"
15 #include "interlacemodes.h"
16 #include "language.h"
17 #include "mainerror.h"
18 #include "mwindow.inc"
19 #include "preferences.h"
20 #include "vframe.h"
21 #include "videodevice.inc"
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
27 #define MPEG_YUV420 0
28 #define MPEG_YUV422 1
31 #define MJPEG_EXE PLUGIN_DIR "/mpeg2enc.plugin"
39 // M JPEG dependancies
40 static double frame_rate_codes[] = 
42         0,
43         24000.0/1001.0,
44         24.0,
45         25.0,
46         30000.0/1001.0,
47         30.0,
48         50.0,
49         60000.0/1001.0,
50         60.0
53 static double aspect_ratio_codes[] =
55         0,
56         1.0,
57         1.333,
58         1.777,
59         2.11
69 FileMPEG::FileMPEG(Asset_GC asset, File *file)
70  : FileBase(asset, file)
72         reset_parameters();
73 // May also be VMPEG or AMPEG if write status.
74         if(asset->format == FILE_UNKNOWN) asset->format = FILE_MPEG;
75         asset->byte_order = 0;
76         next_frame_lock = new Condition(0, "FileMPEG::next_frame_lock");
77         next_frame_done = new Condition(0, "FileMPEG::next_frame_done");
80 FileMPEG::~FileMPEG()
82         close_file();
83         delete next_frame_lock;
84         delete next_frame_done;
87 void FileMPEG::get_parameters(BC_WindowBase *parent_window, 
88         Asset_GC asset, 
89         BC_WindowBase* &format_window,
90         int audio_options,
91         int video_options)
93         if(audio_options && asset->format == FILE_AMPEG)
94         {
95                 MPEGConfigAudio *window = new MPEGConfigAudio(parent_window, asset);
96                 format_window = window;
97                 window->create_objects();
98                 window->run_window();
99                 delete window;
100         }
101         else
102         if(video_options && asset->format == FILE_VMPEG)
103         {
104                 MPEGConfigVideo *window = new MPEGConfigVideo(parent_window, asset);
105                 format_window = window;
106                 window->create_objects();
107                 window->run_window();
108                 delete window;
109         }
112 int FileMPEG::check_sig(Asset_GC asset)
114         return mpeg3_check_sig(asset->path);
117 void FileMPEG::get_info(Asset_GC asset, int64_t *bytes, int *stracks)
119         mpeg3_t *fd;
121         int error = 0;
122         if((fd = mpeg3_open(asset->path, &error)))
123         {
124                 *bytes = mpeg3_get_bytes(fd);
125                 *stracks = mpeg3_subtitle_tracks(fd);
126                 mpeg3_close(fd);
127         }
128         return;
131 int FileMPEG::reset_parameters_derived()
133         wrote_header = 0;
134         mjpeg_out = 0;
135         mjpeg_eof = 0;
136         mjpeg_error = 0;
139         dvb_out = 0;
142         fd = 0;
143         video_out = 0;
144         audio_out = 0;
145         prev_track = 0;
146         temp_frame = 0;
147         toolame_temp = 0;
148         toolame_allocation = 0;
149         toolame_result = 0;
150         lame_temp[0] = 0;
151         lame_temp[1] = 0;
152         lame_allocation = 0;
153         lame_global = 0;
154         lame_output = 0;
155         lame_output_allocation = 0;
156         lame_fd = 0;
157         lame_started = 0;
161 // Just create the Quicktime objects since this routine is also called
162 // for reopening.
163 int FileMPEG::open_file(int rd, int wr)
165 SET_TRACE
166         int result = 0;
167         this->rd = rd;
168         this->wr = wr;
170         if(rd)
171         {
172                 int error = 0;
173                 if(!(fd = mpeg3_open(asset->path, &error)))
174                 {
175                         char string[BCTEXTLEN];
176                         if(error == MPEG3_INVALID_TOC_VERSION)
177                         {
178                                 eprintf("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                         }
182                         else
183                         if(error == MPEG3_TOC_DATE_MISMATCH)
184                         {
185                                 eprintf("Couldn't open %s because the table of contents date differs from the source date.\n"
186                                         "Rebuild the table of contents with mpeg3toc.",
187                                         asset->path);
188                         }
189                         result = 1;
190                 }
191                 else
192                 {
193 // Determine if the file needs a table of contents and create one if needed.
194 // If it has video it must be scanned since video has keyframes.
195                         if(mpeg3_total_vstreams(fd))
196                         {
197                                 if(create_index()) return 1;
198                         }
200                         mpeg3_set_cpus(fd, file->cpus);
202                         asset->audio_data = mpeg3_has_audio(fd);
203                         if(asset->audio_data)
204                         {
205                                 asset->channels = 0;
206                                 for(int i = 0; i < mpeg3_total_astreams(fd); i++)
207                                 {
208                                         asset->channels += mpeg3_audio_channels(fd, i);
209                                 }
210                                 if(!asset->sample_rate)
211                                         asset->sample_rate = mpeg3_sample_rate(fd, 0);
212                                 asset->audio_length = mpeg3_audio_samples(fd, 0); 
213                         }
215                         asset->video_data = mpeg3_has_video(fd);
216                         if(asset->video_data)
217                         {
218                                 asset->layers = mpeg3_total_vstreams(fd);
219                                 asset->width = mpeg3_video_width(fd, 0);
220                                 asset->height = mpeg3_video_height(fd, 0);
221                                 asset->interlace_mode = BC_ILACE_MODE_UNDETECTED; // TODO: (to do this, start at hvirtualcvs/libmpeg3/headers.c 
222                                                                                   //        and find out how to decode info from the header)
223                                 asset->video_length = mpeg3_video_frames(fd, 0);
224                                 asset->vmpeg_cmodel = 
225                                         (mpeg3_colormodel(fd, 0) == MPEG3_YUV422P) ? MPEG_YUV422 : MPEG_YUV420;
226                                 if(!asset->frame_rate)
227                                         asset->frame_rate = mpeg3_frame_rate(fd, 0);
229 // Enable subtitles
230 //printf("FileMPEG::open %d\n", file->playback_subtitle);
231                                 if(file->playback_subtitle >= 0)
232                                         mpeg3_show_subtitle(fd, file->playback_subtitle);
233                         }
234                 }
235         }
238         
239         if(wr && asset->format == FILE_VMPEG)
240         {
241 // Heroine Virtual encoder
242                 if(asset->vmpeg_cmodel == MPEG_YUV422)
243                 {
244                         char bitrate_string[BCTEXTLEN];
245                         char quant_string[BCTEXTLEN];
246                         char iframe_string[BCTEXTLEN];
248                         sprintf(bitrate_string, "%d", asset->vmpeg_bitrate);
249                         sprintf(quant_string, "%d", asset->vmpeg_quantization);
250                         sprintf(iframe_string, "%d", asset->vmpeg_iframe_distance);
252 // Construct command line
253                         if(!result)
254                         {
255                                 append_vcommand_line("mpeg2enc");
258                                 if(asset->aspect_ratio > 0)
259                                 {
260                                         append_vcommand_line("-a");
261                                         if(EQUIV(asset->aspect_ratio, 1))
262                                                 append_vcommand_line("1");
263                                         else
264                                         if(EQUIV(asset->aspect_ratio, 1.333))
265                                                 append_vcommand_line("2");
266                                         else
267                                         if(EQUIV(asset->aspect_ratio, 1.777))
268                                                 append_vcommand_line("3");
269                                         else
270                                         if(EQUIV(asset->aspect_ratio, 2.11))
271                                                 append_vcommand_line("4");
272                                 }
274                                 append_vcommand_line(asset->vmpeg_derivative == 1 ? "-1" : "");
275                                 append_vcommand_line(asset->vmpeg_cmodel == MPEG_YUV422 ? "-422" : "");
276                                 if(asset->vmpeg_fix_bitrate)
277                                 {
278                                         append_vcommand_line("--cbr -b");
279                                         append_vcommand_line(bitrate_string);
280                                 }
281                                 else
282                                 {
283                                         append_vcommand_line("-q");
284                                         append_vcommand_line(quant_string);
285                                 }
286                                 append_vcommand_line(!asset->vmpeg_fix_bitrate ? quant_string : "");
287                                 append_vcommand_line("-n");
288                                 append_vcommand_line(iframe_string);
289                                 append_vcommand_line(asset->vmpeg_progressive ? "-p" : "");
290                                 append_vcommand_line(asset->vmpeg_denoise ? "-d" : "");
291                                 append_vcommand_line(file->cpus <= 1 ? "-u" : "");
292                                 append_vcommand_line(asset->vmpeg_seq_codes ? "-g" : "");
293                                 append_vcommand_line(asset->path);
295                                 video_out = new FileMPEGVideo(this);
296                                 video_out->start();
297                         }
298                 }
299                 else
300 // mjpegtools encoder
301                 {
302                         char string[BCTEXTLEN];
303                         sprintf(mjpeg_command, MJPEG_EXE);
305 // Must disable interlacing if MPEG-1
306                         switch (asset->vmpeg_preset)
307                         {
308                                 case 0: asset->vmpeg_progressive = 1; break;
309                                 case 1: asset->vmpeg_progressive = 1; break;
310                                 case 2: asset->vmpeg_progressive = 1; break;
311                         }
315 // The current usage of mpeg2enc requires bitrate of 0 when quantization is fixed and
316 // quantization of 1 when bitrate is fixed.  Perfectly intuitive.
317                         if(asset->vmpeg_fix_bitrate)
318                         {
319                                 sprintf(string, " -b %d -q 1", asset->vmpeg_bitrate / 1000);
320                         }
321                         else
322                         {
323                                 sprintf(string, " -b 0 -q %d", asset->vmpeg_quantization);
324                         }
325                         strcat(mjpeg_command, string);
332 // Aspect ratio
333                         int aspect_ratio_code = -1;
334                         if(asset->aspect_ratio > 0)
335                         {
336                                 for(int i = 0; i < sizeof(aspect_ratio_codes) / sizeof(double); i++)
337                                 {
338                                         if(EQUIV(aspect_ratio_codes[i], asset->aspect_ratio))
339                                         {
340                                                 aspect_ratio_code = i;
341                                                 break;
342                                         }
343                                 }
344                         }
345                         if(aspect_ratio_code < 0)
346                         {
347                                 eprintf("Unsupported aspect ratio %f\n", asset->aspect_ratio);
348                                 aspect_ratio_code = 2;
349                         }
350                         sprintf(string, " -a %d", aspect_ratio_code);
351                         strcat(mjpeg_command, string);
358 // Frame rate
359                         int frame_rate_code = -1;
360                 for(int i = 1; sizeof(frame_rate_codes) / sizeof(double); ++i)
361                         {
362                                 if(EQUIV(asset->frame_rate, frame_rate_codes[i]))
363                                 {
364                                         frame_rate_code = i;
365                                         break;
366                                 }
367                         }
368                         if(frame_rate_code < 0)
369                         {
370                                 frame_rate_code = 4;
371                                 eprintf("Unsupported frame rate %f\n", asset->frame_rate);
372                         }
373                         sprintf(string, " -F %d", frame_rate_code);
374                         strcat(mjpeg_command, string);
380                         strcat(mjpeg_command, 
381                                 asset->vmpeg_progressive ? " -I 0" : " -I 1");
382                         
385                         sprintf(string, " -M %d", file->cpus);
386                         strcat(mjpeg_command, string);
389                         if(!asset->vmpeg_progressive)
390                         {
391                                 strcat(mjpeg_command, asset->vmpeg_field_order ? " -z b" : " -z t");
392                         }
395                         sprintf(string, " -f %d", asset->vmpeg_preset);
396                         strcat(mjpeg_command, string);
399                         sprintf(string, " -g %d -G %d", asset->vmpeg_iframe_distance, asset->vmpeg_iframe_distance);
400                         strcat(mjpeg_command, string);
403                         if(asset->vmpeg_seq_codes) strcat(mjpeg_command, " -s");
406                         sprintf(string, " -R %d", CLAMP(asset->vmpeg_pframe_distance, 0, 2));
407                         strcat(mjpeg_command, string);
409                         sprintf(string, " -o '%s'", asset->path);
410                         strcat(mjpeg_command, string);
414                         eprintf("Running %s\n", mjpeg_command);
415                         if(!(mjpeg_out = popen(mjpeg_command, "w")))
416                         {
417                                 eprintf("Error while opening \"%s\" for writing. \n%m\n", mjpeg_command);
418                         }
420                         video_out = new FileMPEGVideo(this);
421                         video_out->start();
422                 }
423         }
424         else
425         if(wr && asset->format == FILE_AMPEG)
426         {
427                 char command_line[BCTEXTLEN];
428                 char encoder_string[BCTEXTLEN];
429                 char argument_string[BCTEXTLEN];
431 //printf("FileMPEG::open_file 1 %d\n", asset->ampeg_derivative);
432                 encoder_string[0] = 0;
434                 if(asset->ampeg_derivative == 2)
435                 {
436                         char string[BCTEXTLEN];
437                         append_acommand_line("toolame");
438                         append_acommand_line("-m");
439                         append_acommand_line((asset->channels >= 2) ? "j" : "m");
440                         sprintf(string, "%f", (float)asset->sample_rate / 1000);
441                         append_acommand_line("-s");
442                         append_acommand_line(string);
443                         sprintf(string, "%d", asset->ampeg_bitrate);
444                         append_acommand_line("-b");
445                         append_acommand_line(string);
446                         append_acommand_line("-");
447                         append_acommand_line(asset->path);
449                         audio_out = new FileMPEGAudio(this);
450                         audio_out->start();
451                 }
452                 else
453                 if(asset->ampeg_derivative == 3)
454                 {
455                         lame_global = lame_init();
456                         lame_set_brate(lame_global, asset->ampeg_bitrate);
457                         lame_set_quality(lame_global, 0);
458                         lame_set_in_samplerate(lame_global, 
459                                 asset->sample_rate);
460                         lame_set_num_channels(lame_global,
461                                 asset->channels);
462                         if((result = lame_init_params(lame_global)) < 0)
463                         {
464                                 eprintf(_("encode: lame_init_params returned %d\n"), result);
465                                 lame_close(lame_global);
466                                 lame_global = 0;
467                         }
468                         else
469                         if(!(lame_fd = fopen(asset->path, "w")))
470                         {
471                                 eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
472                                 lame_close(lame_global);
473                                 lame_global = 0;
474                                 result = 1;
475                         }
476                 }
477                 else
478                 {
479                         eprintf("ampeg_derivative=%d\n", asset->ampeg_derivative);
480                         result = 1;
481                 }
482         }
483         else
484 // Transport stream for DVB capture
485         if(wr)
486         {
487                 if(!(dvb_out = fopen(asset->path, "w")))
488                 {
489                         eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
490                         result = 1;
491                 }
492                 
493         }
496 //asset->dump();
497 SET_TRACE
498         return result;
508 int FileMPEG::create_index()
510 // Calculate TOC path
511         char index_filename[BCTEXTLEN];
512         char source_filename[BCTEXTLEN];
513         IndexFile::get_index_filename(source_filename, 
514                 file->preferences->index_directory, 
515                 index_filename, 
516                 asset->path);
517         char *ptr = strrchr(index_filename, '.');
518         int error = 0;
520         if(!ptr) return 1;
522 // File is a table of contents.
523         if(fd && mpeg3_has_toc(fd)) return 0;
525         sprintf(ptr, ".toc");
527         mpeg3_t *fd_toc;
530 // Test existing copy of TOC
531         mpeg3_close(fd);     // Always free old fd
532         if((fd_toc = mpeg3_open(index_filename, &error)))
533         {
534 // Just exchange old fd 
535                 fd = fd_toc;
536         } else
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                 }
604 // Reopen file from index path instead of asset path.
605                 if(!(fd = mpeg3_open(index_filename, &error)))
606                         return 1;
607         }
609         return 0;
617 void FileMPEG::append_vcommand_line(const char *string)
619         if(string[0])
620         {
621                 char *argv = strdup(string);
622                 vcommand_line.append(argv);
623         }
626 void FileMPEG::append_acommand_line(const char *string)
628         if(string[0])
629         {
630                 char *argv = strdup(string);
631                 acommand_line.append(argv);
632         }
636 int FileMPEG::close_file()
638         mjpeg_eof = 1;
639         next_frame_lock->unlock();
641         if(fd)
642         {
643                 mpeg3_close(fd);
644         }
646         if(video_out)
647         {
648 // End of sequence signal
649                 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
650                 {
651                         mpeg2enc_set_input_buffers(1, 0, 0, 0);
652                 }
653                 delete video_out;
654                 video_out = 0;
655         }
657         vcommand_line.remove_all_objects();
658         acommand_line.remove_all_objects();
660         if(audio_out)
661         {
662                 toolame_send_buffer(0, 0);
663                 delete audio_out;
664                 audio_out = 0;
665         }
667         if(lame_global)
668                 lame_close(lame_global);
670         if(temp_frame) delete temp_frame;
671         if(toolame_temp) delete [] toolame_temp;
673         if(lame_temp[0]) delete [] lame_temp[0];
674         if(lame_temp[1]) delete [] lame_temp[1];
675         if(lame_output) delete [] lame_output;
676         if(lame_fd) fclose(lame_fd);
678         if(mjpeg_out) fclose(mjpeg_out);
681         if(dvb_out)
682                 fclose(dvb_out);
684         reset_parameters();
686         FileBase::close_file();
687         return 0;
690 int FileMPEG::get_best_colormodel(Asset_GC asset, int driver)
692 //printf("FileMPEG::get_best_colormodel 1\n");
693         switch(driver)
694         {
695                 case PLAYBACK_X11:
696                         return BC_RGB888;
697                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
698                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
699                         break;
700                 case PLAYBACK_X11_XV:
701                 case PLAYBACK_ASYNCHRONOUS:
702                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
703                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
704                         break;
705                 case PLAYBACK_X11_GL:
706                         return BC_YUV888;
707                         break;
708                 case PLAYBACK_LML:
709                 case PLAYBACK_BUZ:
710                         return BC_YUV422P;
711                         break;
712                 case PLAYBACK_DV1394:
713                 case PLAYBACK_FIREWIRE:
714                         return BC_YUV422P;
715                         break;
716                 case VIDEO4LINUX:
717                 case VIDEO4LINUX2:
718                         if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
719                         if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
720                         break;
721                 case CAPTURE_BUZ:
722                 case CAPTURE_LML:
723                         return BC_YUV422;
724                         break;
725                 case CAPTURE_FIREWIRE:
726                 case CAPTURE_IEC61883:
727                         return BC_YUV422P;
728                         break;
729         }
730 //printf("FileMPEG::get_best_colormodel 100\n");
733 int FileMPEG::colormodel_supported(int colormodel)
735         return colormodel;
738 int FileMPEG::get_index(char *index_path)
740         if(!fd) return 1;
743 // Convert the index tables from tracks to channels.
744         if(mpeg3_index_tracks(fd))
745         {
746 // Calculate size of buffer needed for all channels
747                 int buffer_size = 0;
748                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
749                 {
750                         buffer_size += mpeg3_index_size(fd, i) *
751                                 mpeg3_index_channels(fd, i) *
752                                 2;
753                 }
755                 asset->index_buffer = new float[buffer_size];
757 // Size of index buffer in floats
758                 int current_offset = 0;
759 // Current asset channel
760                 int current_channel = 0;
761                 asset->index_zoom = mpeg3_index_zoom(fd);
762                 asset->index_offsets = new int64_t[asset->channels];
763                 asset->index_sizes = new int64_t[asset->channels];
764                 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
765                 {
766                         for(int j = 0; j < mpeg3_index_channels(fd, i); j++)
767                         {
768                                 asset->index_offsets[current_channel] = current_offset;
769                                 asset->index_sizes[current_channel] = mpeg3_index_size(fd, i) * 2;
770                                 memcpy(asset->index_buffer + current_offset,
771                                         mpeg3_index_data(fd, i, j),
772                                         mpeg3_index_size(fd, i) * sizeof(float) * 2);
774                                 current_offset += mpeg3_index_size(fd, i) * 2;
775                                 current_channel++;
776                         }
777                 }
779                 FileSystem fs;
780                 asset->index_bytes = fs.get_size(asset->path);
782                 asset->write_index(index_path, buffer_size * sizeof(float));
783                 delete [] asset->index_buffer;
785                 return 0;
786         }
788         return 1;
792 int FileMPEG::can_copy_from(Edit *edit, int64_t position)
794         if(!fd) return 0;
795         return 0;
798 int FileMPEG::set_audio_position(int64_t sample)
800 #if 0
801         if(!fd) return 1;
802         
803         int channel, stream;
804         to_streamchannel(file->current_channel, stream, channel);
806 //printf("FileMPEG::set_audio_position %d %d %d\n", sample, mpeg3_get_sample(fd, stream), last_sample);
807         if(sample != mpeg3_get_sample(fd, stream) &&
808                 sample != last_sample)
809         {
810                 if(sample >= 0 && sample < asset->audio_length)
811                 {
812 //printf("FileMPEG::set_audio_position seeking stream %d\n", sample);
813                         return mpeg3_set_sample(fd, sample, stream);
814                 }
815                 else
816                         return 1;
817         }
818 #endif
819         return 0;
822 int FileMPEG::set_video_position(int64_t x)
824         if(!fd) return 1;
825         if(x >= 0 && x < asset->video_length)
826         {
827 //printf("FileMPEG::set_video_position 1 %lld\n", x);
828                 mpeg3_set_frame(fd, x, file->current_layer);
829         }
830         else
831                 return 1;
834 int64_t FileMPEG::get_memory_usage()
836         if(rd && fd)
837         {
838                 int64_t result = mpeg3_memory_usage(fd);
839                 return result;
840         }
841         return 0;
845 int FileMPEG::write_samples(double **buffer, int64_t len)
847         int result = 0;
849 //printf("FileMPEG::write_samples 1\n");
850         if(asset->ampeg_derivative == 2)
851         {
852 // Convert to int16
853                 int channels = MIN(asset->channels, 2);
854                 int64_t audio_size = len * channels * 2;
855                 if(toolame_allocation < audio_size)
856                 {
857                         if(toolame_temp) delete [] toolame_temp;
858                         toolame_temp = new unsigned char[audio_size];
859                         toolame_allocation = audio_size;
860                 }
862                 for(int i = 0; i < channels; i++)
863                 {
864                         int16_t *output = ((int16_t*)toolame_temp) + i;
865                         double *input = buffer[i];
866                         for(int j = 0; j < len; j++)
867                         {
868                                 int sample = (int)(*input * 0x7fff);
869                                 *output = (int16_t)(CLIP(sample, -0x8000, 0x7fff));
870                                 output += channels;
871                                 input++;
872                         }
873                 }
874                 result = toolame_send_buffer((char*)toolame_temp, audio_size);
875         }
876         else
877         if(asset->ampeg_derivative == 3)
878         {
879                 int channels = MIN(asset->channels, 2);
880                 int64_t audio_size = len * channels;
881                 if(!lame_global) return 1;
882                 if(!lame_fd) return 1;
883                 if(lame_allocation < audio_size)
884                 {
885                         if(lame_temp[0]) delete [] lame_temp[0];
886                         if(lame_temp[1]) delete [] lame_temp[1];
887                         lame_temp[0] = new float[audio_size];
888                         lame_temp[1] = new float[audio_size];
889                         lame_allocation = audio_size;
890                 }
892                 if(lame_output_allocation < audio_size * 4)
893                 {
894                         if(lame_output) delete [] lame_output;
895                         lame_output_allocation = audio_size * 4;
896                         lame_output = new char[lame_output_allocation];
897                 }
899                 for(int i = 0; i < channels; i++)
900                 {
901                         float *output = lame_temp[i];
902                         double *input = buffer[i];
903                         for(int j = 0; j < len; j++)
904                         {
905                                 *output++ = *input++ * (float)32768;
906                         }
907                 }
909                 result = lame_encode_buffer_float(lame_global,
910                         lame_temp[0],
911                         (channels > 1) ? lame_temp[1] : lame_temp[0],
912                         len,
913                         (unsigned char*)lame_output,
914                         lame_output_allocation);
915                 if(result > 0)
916                 {
917                         char *real_output = lame_output;
918                         int bytes = result;
919                         if(!lame_started)
920                         {
921                                 for(int i = 0; i < bytes; i++)
922                                         if(lame_output[i])
923                                         {
924                                                 real_output = &lame_output[i];
925                                                 lame_started = 1;
926                                                 bytes -= i;
927                                                 break;
928                                         }
929                         }
930                         if(bytes > 0 && lame_started)
931                         {
932                                 result = !fwrite(real_output, 1, bytes, lame_fd);
933                                 if(result)
934                                         eprintf("Error while writing samples");
935                         }
936                         else
937                                 result = 0;
938                 }
939                 else
940                         result = 1;
941         }
943         return result;
946 int FileMPEG::write_frames(VFrame ***frames, int len)
948         int result = 0;
950         if(video_out)
951         {
952                 int temp_w = (int)((asset->width + 15) / 16) * 16;
953                 int temp_h;
956                 int output_cmodel = 
957                         (asset->vmpeg_cmodel == MPEG_YUV420) ? BC_YUV420P : BC_YUV422P;
958                 
959                 
960 // Height depends on progressiveness
961                 if(asset->vmpeg_progressive || asset->vmpeg_derivative == 1)
962                         temp_h = (int)((asset->height + 15) / 16) * 16;
963                 else
964                         temp_h = (int)((asset->height + 31) / 32) * 32;
966 //printf("FileMPEG::write_frames 1\n");
967                 
968 // Only 1 layer is supported in MPEG output
969                 for(int i = 0; i < 1; i++)
970                 {
971                         for(int j = 0; j < len && !result; j++)
972                         {
973                                 VFrame *frame = frames[i][j];
974                                 
975                                 
976                                 
977                                 if(asset->vmpeg_cmodel == MPEG_YUV422)
978                                 {
979                                         if(frame->get_w() == temp_w &&
980                                                 frame->get_h() == temp_h &&
981                                                 frame->get_color_model() == output_cmodel)
982                                         {
983                                                 mpeg2enc_set_input_buffers(0, 
984                                                         (char*)frame->get_y(),
985                                                         (char*)frame->get_u(),
986                                                         (char*)frame->get_v());
987                                         }
988                                         else
989                                         {
990                                                 if(temp_frame &&
991                                                         (temp_frame->get_w() != temp_w ||
992                                                         temp_frame->get_h() != temp_h ||
993                                                         temp_frame->get_color_model() || output_cmodel))
994                                                 {
995                                                         delete temp_frame;
996                                                         temp_frame = 0;
997                                                 }
1000                                                 if(!temp_frame)
1001                                                 {
1002                                                         temp_frame = new VFrame(0, 
1003                                                                 temp_w, 
1004                                                                 temp_h, 
1005                                                                 output_cmodel);
1006                                                 }
1008                                                 cmodel_transfer(temp_frame->get_rows(), 
1009                                                         frame->get_rows(),
1010                                                         temp_frame->get_y(),
1011                                                         temp_frame->get_u(),
1012                                                         temp_frame->get_v(),
1013                                                         frame->get_y(),
1014                                                         frame->get_u(),
1015                                                         frame->get_v(),
1016                                                         0,
1017                                                         0,
1018                                                         asset->width,
1019                                                         asset->height,
1020                                                         0,
1021                                                         0,
1022                                                         asset->width,
1023                                                         asset->height,
1024                                                         frame->get_color_model(), 
1025                                                         temp_frame->get_color_model(),
1026                                                         0, 
1027                                                         frame->get_w(),
1028                                                         temp_w);
1030                                                 mpeg2enc_set_input_buffers(0, 
1031                                                         (char*)temp_frame->get_y(),
1032                                                         (char*)temp_frame->get_u(),
1033                                                         (char*)temp_frame->get_v());
1034                                         }
1035                                 }
1036                                 else
1037                                 {
1038 // MJPEG uses the same dimensions as the input
1039                                         if(frame->get_color_model() == output_cmodel)
1040                                         {
1041                                                 mjpeg_y = frame->get_y();
1042                                                 mjpeg_u = frame->get_u();
1043                                                 mjpeg_v = frame->get_v();
1044                                         }
1045                                         else
1046                                         {
1047                                                 if(!temp_frame)
1048                                                 {
1049                                                         temp_frame = new VFrame(0, 
1050                                                                 asset->width, 
1051                                                                 asset->height, 
1052                                                                 output_cmodel);
1053                                                 }
1055                                                 cmodel_transfer(temp_frame->get_rows(), 
1056                                                         frame->get_rows(),
1057                                                         temp_frame->get_y(),
1058                                                         temp_frame->get_u(),
1059                                                         temp_frame->get_v(),
1060                                                         frame->get_y(),
1061                                                         frame->get_u(),
1062                                                         frame->get_v(),
1063                                                         0,
1064                                                         0,
1065                                                         asset->width,
1066                                                         asset->height,
1067                                                         0,
1068                                                         0,
1069                                                         asset->width,
1070                                                         asset->height,
1071                                                         frame->get_color_model(), 
1072                                                         temp_frame->get_color_model(),
1073                                                         0, 
1074                                                         frame->get_w(),
1075                                                         temp_w);
1077                                                 mjpeg_y = temp_frame->get_y();
1078                                                 mjpeg_u = temp_frame->get_u();
1079                                                 mjpeg_v = temp_frame->get_v();
1080                                         }
1085                                         next_frame_lock->unlock();
1086                                         next_frame_done->lock("FileMPEG::write_frames");
1087                                         if(mjpeg_error) result = 1;
1088                                 }
1094                         }
1095                 }
1096         }
1100         return result;
1103 int FileMPEG::read_frame(VFrame *frame)
1105         if(!fd) return 1;
1106         int result = 0;
1107         int src_cmodel;
1109 // printf("FileMPEG::read_frame\n");
1110 // frame->dump_stacks();
1111 // frame->dump_params();
1113         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV420P)
1114                 src_cmodel = BC_YUV420P;
1115         else
1116         if(mpeg3_colormodel(fd, 0) == MPEG3_YUV422P)
1117                 src_cmodel = BC_YUV422P;
1119         switch(frame->get_color_model())
1120         {
1121                 case MPEG3_RGB565:
1122                 case MPEG3_BGR888:
1123                 case MPEG3_BGRA8888:
1124                 case MPEG3_RGB888:
1125                 case MPEG3_RGBA8888:
1126                 case MPEG3_RGBA16161616:
1127 SET_TRACE
1128                         mpeg3_read_frame(fd, 
1129                                         frame->get_rows(), /* Array of pointers to the start of each output row */
1130                                         0,                    /* Location in input frame to take picture */
1131                                         0, 
1132                                         asset->width, 
1133                                         asset->height, 
1134                                         asset->width,                   /* Dimensions of output_rows */
1135                                         asset->height, 
1136                                         frame->get_color_model(),             /* One of the color model #defines */
1137                                         file->current_layer);
1138 SET_TRACE
1139                         break;
1141 // Use Temp
1142                 default:
1143 // Read these directly
1144                         if(frame->get_color_model() == src_cmodel)
1145                         {
1146 SET_TRACE
1147                                 mpeg3_read_yuvframe(fd,
1148                                         (char*)frame->get_y(),
1149                                         (char*)frame->get_u(),
1150                                         (char*)frame->get_v(),
1151                                         0,
1152                                         0,
1153                                         asset->width,
1154                                         asset->height,
1155                                         file->current_layer);
1156 SET_TRACE
1157                         }
1158                         else
1159 // Process through temp frame
1160                         {
1161                                 char *y, *u, *v;
1162 SET_TRACE
1163                                 mpeg3_read_yuvframe_ptr(fd,
1164                                         &y,
1165                                         &u,
1166                                         &v,
1167                                         file->current_layer);
1168 SET_TRACE
1169                                 if(y && u && v)
1170                                 {
1171                                         cmodel_transfer(frame->get_rows(), 
1172                                                 0,
1173                                                 frame->get_y(),
1174                                                 frame->get_u(),
1175                                                 frame->get_v(),
1176                                                 (unsigned char*)y,
1177                                                 (unsigned char*)u,
1178                                                 (unsigned char*)v,
1179                                                 0,
1180                                                 0,
1181                                                 asset->width,
1182                                                 asset->height,
1183                                                 0,
1184                                                 0,
1185                                                 asset->width,
1186                                                 asset->height,
1187                                                 src_cmodel, 
1188                                                 frame->get_color_model(),
1189                                                 0, 
1190                                                 asset->width,
1191                                                 frame->get_w());
1192                                 }
1193                         }
1194                         break;
1195         }
1197 SET_TRACE
1198         return result;
1202 void FileMPEG::to_streamchannel(int channel, int &stream_out, int &channel_out)
1204         for(stream_out = 0, channel_out = file->current_channel; 
1205                 stream_out < mpeg3_total_astreams(fd) && 
1206                         channel_out >= mpeg3_audio_channels(fd, stream_out);
1207                 channel_out -= mpeg3_audio_channels(fd, stream_out), stream_out++)
1208         ;
1211 int FileMPEG::read_samples(double *buffer, int64_t len)
1213         if(!fd) return 0;
1214         if(len < 0) return 0;
1216 // This is directed to a FileMPEGBuffer
1217         float *temp_float = new float[len];
1218 // Translate pure channel to a stream and a channel in the mpeg stream
1219         int stream, channel;
1220         to_streamchannel(file->current_channel, stream, channel);
1221         
1222         
1223         
1224 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1226         mpeg3_set_sample(fd, 
1227                 file->current_sample,
1228                 stream);
1229         mpeg3_read_audio(fd, 
1230                 temp_float,      /* Pointer to pre-allocated buffer of floats */
1231                 0,      /* Pointer to pre-allocated buffer of int16's */
1232                 channel,          /* Channel to decode */
1233                 len,         /* Number of samples to decode */
1234                 stream);          /* Stream containing the channel */
1237 //      last_sample = file->current_sample;
1238         for(int i = 0; i < len; i++) buffer[i] = temp_float[i];
1240         delete [] temp_float;
1241         return 0;
1244 int FileMPEG::prefer_samples_float()
1246         return 1;
1249 int FileMPEG::read_samples_float(float *buffer, int64_t len)
1251         if(!fd) return 0;
1253 // Translate pure channel to a stream and a channel in the mpeg stream
1254         int stream, channel;
1255         to_streamchannel(file->current_channel, stream, channel);
1256         
1257         
1258 //printf("FileMPEG::read_samples 1 current_sample=%ld len=%ld channel=%d\n", file->current_sample, len, channel);
1260         mpeg3_set_sample(fd, 
1261                 file->current_sample,
1262                 stream);
1263         mpeg3_read_audio(fd, 
1264                 buffer,         /* Pointer to pre-allocated buffer of floats */
1265                 0,              /* Pointer to pre-allocated buffer of int16's */
1266                 channel,          /* Channel to decode */
1267                 len,         /* Number of samples to decode */
1268                 stream);          /* Stream containing the channel */
1271 //      last_sample = file->current_sample;
1273 //printf("FileMPEG::read_samples 100\n");
1274         return 0;
1279 char* FileMPEG::strtocompression(char *string)
1281         return "";
1284 char* FileMPEG::compressiontostr(char *string)
1286         return "";
1295 FileMPEGVideo::FileMPEGVideo(FileMPEG *file)
1296  : Thread(1, 0, 0)
1298         this->file = file;
1299         
1300         
1301         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1302         {
1303                 mpeg2enc_init_buffers();
1304                 mpeg2enc_set_w(file->asset->width);
1305                 mpeg2enc_set_h(file->asset->height);
1306                 mpeg2enc_set_rate(file->asset->frame_rate);
1307         }
1310 FileMPEGVideo::~FileMPEGVideo()
1312         Thread::join();
1315 void FileMPEGVideo::run()
1317         if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1318         {
1319                 printf("FileMPEGVideo::run ");
1320                 for(int i = 0; i < file->vcommand_line.total; i++)
1321                 printf("%s ", file->vcommand_line.values[i]);
1322                 printf("\n");
1323                 mpeg2enc(file->vcommand_line.total, file->vcommand_line.values);
1324         }
1325         else
1326         {
1327                 while(1)
1328                 {
1329                         file->next_frame_lock->lock("FileMPEGVideo::run");
1330                         if(file->mjpeg_eof) 
1331                         {
1332                                 file->next_frame_done->unlock();
1333                                 break;
1334                         }
1338 // YUV4 sequence header
1339                         if(!file->wrote_header)
1340                         {
1341                                 file->wrote_header = 1;
1343                                 char string[BCTEXTLEN];
1344                                 char interlace_string[BCTEXTLEN];
1345                                 if(!file->asset->vmpeg_progressive)
1346                                 {
1347                                         sprintf(interlace_string, file->asset->vmpeg_field_order ? "b" : "t");
1348                                 }
1349                                 else
1350                                 {
1351                                         sprintf(interlace_string, "p");
1352                                 }
1354                                 fprintf(file->mjpeg_out, "YUV4MPEG2 W%d H%d F%d:%d I%s A%d:%d C%s\n",
1355                                         file->asset->width,
1356                                         file->asset->height,
1357                                         (int)(file->asset->frame_rate * 1001),
1358                                         1001,
1359                                         interlace_string,
1360                                         (int)(file->asset->aspect_ratio * 1000),
1361                                         1000,
1362                                         "420mpeg2");
1363                         }
1365 // YUV4 frame header
1366                         fprintf(file->mjpeg_out, "FRAME\n");
1368 // YUV data
1369                         if(!fwrite(file->mjpeg_y, file->asset->width * file->asset->height, 1, file->mjpeg_out))
1370                                 file->mjpeg_error = 1;
1371                         if(!fwrite(file->mjpeg_u, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1372                                 file->mjpeg_error = 1;
1373                         if(!fwrite(file->mjpeg_v, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1374                                 file->mjpeg_error = 1;
1375                         fflush(file->mjpeg_out);
1377                         file->next_frame_done->unlock();
1378                 }
1379                 pclose(file->mjpeg_out);
1380                 file->mjpeg_out = 0;
1381         }
1403 FileMPEGAudio::FileMPEGAudio(FileMPEG *file)
1404  : Thread(1, 0, 0)
1406         this->file = file;
1407         toolame_init_buffers();
1410 FileMPEGAudio::~FileMPEGAudio()
1412         Thread::join();
1415 void FileMPEGAudio::run()
1417         file->toolame_result = toolame(file->acommand_line.total, file->acommand_line.values);
1427 MPEGConfigAudio::MPEGConfigAudio(BC_WindowBase *parent_window, Asset_GC asset)
1428  : BC_Window(PROGRAM_NAME ": Audio Compression",
1429         parent_window->get_abs_cursor_x(1),
1430         parent_window->get_abs_cursor_y(1),
1431         310,
1432         120,
1433         -1,
1434         -1,
1435         0,
1436         0,
1437         1)
1439         this->parent_window = parent_window;
1440         this->asset = asset;
1443 MPEGConfigAudio::~MPEGConfigAudio()
1447 int MPEGConfigAudio::create_objects()
1449         int x = 10, y = 10;
1450         int x1 = 150;
1451         MPEGLayer *layer;
1453         BC_WidgetGrid *wg;
1454         BC_RelocatableWidget *rw;
1455         wg = add_widgetgrid(new BC_WidgetGrid(10, 10, 10, 10, 3, 3));
1456         int wg_row = 0;
1458         if(asset->format == FILE_MPEG)
1459         {
1460                 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1461                 return 0;
1462         }
1465         rw =
1466         add_tool(new BC_Title(x, y, _("Layer:")));
1467         add_tool(layer = new MPEGLayer(x1, y, this));
1468         layer->create_objects();
1469         wg->add(rw, wg_row, 0);
1470         wg->add(layer, wg_row++, 1);
1472         y += 30;
1473         rw =
1474         add_tool(new BC_Title(x, y, _("Kbits per second:")));
1475         add_tool(bitrate = new MPEGABitrate(x1, y, this));
1476         bitrate->create_objects();
1477         wg->add(rw, wg_row, 0);
1478         wg->add(bitrate, wg_row++, 1);
1479         
1480         
1481         rw =
1482         add_subwindow(new BC_OKButton(this));
1484         wg->move_widgets();
1485         resize_window(wg->get_w_wm(), wg->get_h_wm() + rw->get_h());
1487         show_window();
1488         flush();
1489         return 0;
1492 int MPEGConfigAudio::close_event()
1494         set_done(0);
1495         return 1;
1504 MPEGLayer::MPEGLayer(int x, int y, MPEGConfigAudio *gui)
1505  : BC_PopupMenu(x, y, 100, layer_to_string(gui->asset->ampeg_derivative))
1507         this->gui = gui;
1510 void MPEGLayer::create_objects()
1512         add_item(new BC_MenuItem(layer_to_string(2)));
1513         add_item(new BC_MenuItem(layer_to_string(3)));
1516 int MPEGLayer::handle_event()
1518         gui->asset->ampeg_derivative = string_to_layer(get_text());
1519         gui->bitrate->set_layer(gui->asset->ampeg_derivative);
1520         return 1;
1523 int MPEGLayer::string_to_layer(char *string)
1525         if(!strcasecmp(layer_to_string(2), string))
1526                 return 2;
1527         if(!strcasecmp(layer_to_string(3), string))
1528                 return 3;
1530         return 2;
1533 char* MPEGLayer::layer_to_string(int layer)
1535         switch(layer)
1536         {
1537                 case 2:
1538                         return _("II");
1539                         break;
1540                 
1541                 case 3:
1542                         return _("III");
1543                         break;
1544                         
1545                 default:
1546                         return _("II");
1547                         break;
1548         }
1557 MPEGABitrate::MPEGABitrate(int x, int y, MPEGConfigAudio *gui)
1558  : BC_PopupMenu(x, 
1559         y, 
1560         100, 
1561         bitrate_to_string(gui->string, gui->asset->ampeg_bitrate))
1563         this->gui = gui;
1566 void MPEGABitrate::create_objects()
1568         set_layer(gui->asset->ampeg_derivative);
1571 void MPEGABitrate::set_layer(int layer)
1573         while(total_items())
1574         {
1575                 remove_item(0);
1576         }
1578         if(layer == 2)
1579         {
1580                 add_item(new BC_MenuItem("160"));
1581                 add_item(new BC_MenuItem("192"));
1582                 add_item(new BC_MenuItem("224"));
1583                 add_item(new BC_MenuItem("256"));
1584                 add_item(new BC_MenuItem("320"));
1585                 add_item(new BC_MenuItem("384"));
1586         }
1587         else
1588         {
1589                 add_item(new BC_MenuItem("8"));
1590                 add_item(new BC_MenuItem("16"));
1591                 add_item(new BC_MenuItem("24"));
1592                 add_item(new BC_MenuItem("32"));
1593                 add_item(new BC_MenuItem("40"));
1594                 add_item(new BC_MenuItem("48"));
1595                 add_item(new BC_MenuItem("56"));
1596                 add_item(new BC_MenuItem("64"));
1597                 add_item(new BC_MenuItem("80"));
1598                 add_item(new BC_MenuItem("96"));
1599                 add_item(new BC_MenuItem("112"));
1600                 add_item(new BC_MenuItem("128"));
1601                 add_item(new BC_MenuItem("144"));
1602                 add_item(new BC_MenuItem("160"));
1603                 add_item(new BC_MenuItem("192"));
1604                 add_item(new BC_MenuItem("224"));
1605                 add_item(new BC_MenuItem("256"));
1606                 add_item(new BC_MenuItem("320"));
1607         }
1610 int MPEGABitrate::handle_event()
1612         gui->asset->ampeg_bitrate = string_to_bitrate(get_text());
1613         return 1;
1616 int MPEGABitrate::string_to_bitrate(char *string)
1618         return atol(string);
1622 char* MPEGABitrate::bitrate_to_string(char *string, int bitrate)
1624         sprintf(string, "%d", bitrate);
1625         return string;
1636 MPEGConfigVideo::MPEGConfigVideo(BC_WindowBase *parent_window, 
1637         Asset_GC asset)
1638  : BC_Window(PROGRAM_NAME ": Video Compression",
1639         parent_window->get_abs_cursor_x(1),
1640         parent_window->get_abs_cursor_y(1),
1641         500,
1642         400,
1643         500,
1644         400,
1645         0,
1646         1,
1647         1)
1649         this->parent_window = parent_window;
1650         this->asset = asset;
1651         reset_cmodel();
1652         wg_set = 0;
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(cmodel_title = new BC_Title(x, y, _("Color model:")));
1672         add_subwindow(cmodel = new MPEGColorModel(x1, y, this));
1673         cmodel->create_objects();
1674         y += 30;
1676         BC_OKButton *okbutton;
1677         add_subwindow(okbutton = new BC_OKButton(this));
1678         ok_height = okbutton->get_h();
1680         update_cmodel_objs();
1682         show_window();
1683         flush();
1684         return 0;
1687 int MPEGConfigVideo::close_event()
1689         set_done(0);
1690         return 1;
1694 void MPEGConfigVideo::delete_cmodel_objs()
1696         delete preset;
1697         delete derivative;
1698         delete bitrate;
1699         delete fixed_bitrate;
1700         delete quant;
1701         delete fixed_quant;
1702         delete iframe_distance;
1703         delete pframe_distance;
1704         delete top_field_first;
1705         delete progressive;
1706         delete denoise;
1707         delete seq_codes;
1708         titles.remove_all_objects();
1709         reset_cmodel();
1712 void MPEGConfigVideo::reset_cmodel()
1714         preset = 0;
1715         derivative = 0;
1716         bitrate = 0;
1717         fixed_bitrate = 0;
1718         quant = 0;
1719         fixed_quant = 0;
1720         iframe_distance = 0;
1721         pframe_distance = 0;
1722         top_field_first = 0;
1723         progressive = 0;
1724         denoise = 0;
1725         seq_codes = 0;
1728 void MPEGConfigVideo::update_cmodel_objs()
1730         BC_Title *title;
1731         int x = 10;
1732         int y = 40;
1733         int x1 = x + 150;
1734         int x2 = x + 280;
1736         BC_RelocatableWidget *rw;
1737         int wg_row = 0;
1738         delete_cmodel_objs();
1740         // deletion of the old wg_set isn't required as the BC_WindowBase clean all created wg_sets
1741         wg_set = add_widgetgrid(new BC_WidgetGrid(10, 10, 10, 10, 10, 7));
1742         wg_set->add(cmodel_title, wg_row, 0);
1743         wg_set->add(cmodel, wg_row, 1);
1744         wg_set->set_crspan(wg_row++, 1, 2, 1);
1746         if(asset->vmpeg_cmodel == MPEG_YUV420)
1747         {
1748                 add_subwindow(title = new BC_Title(x, y + 5, _("Format Preset:")));
1749                 titles.append(title);
1750                 add_subwindow(preset = new MPEGPreset(x1, y, this));
1751                 preset->create_objects();
1752                 y += 30;
1753                 wg_set->add(title, wg_row, 0);
1754                 wg_set->add(preset, wg_row, 1);
1755                 wg_set->set_crspan(wg_row++, 1, 2, 1);
1756         }
1758         add_subwindow(title = new BC_Title(x, y + 5, _("Derivative:")));
1759         titles.append(title);
1760         add_subwindow(derivative = new MPEGDerivative(x1, y, this));
1761         derivative->create_objects();
1762         wg_set->add(title, wg_row, 0);
1763         wg_set->add(derivative, wg_row, 1);
1764         wg_set->set_crspan(wg_row++, 1, 2, 1);
1765         y += 30;
1767         add_subwindow(title = new BC_Title(x, y + 5, _("Bitrate:")));
1768         titles.append(title);
1769         add_subwindow(bitrate = new MPEGBitrate(x1, y, this));
1770         add_subwindow(fixed_bitrate = new MPEGFixedBitrate(x2, y, this));
1771         wg_set->add(title, wg_row, 0);
1772         wg_set->add(bitrate, wg_row, 1);
1773         wg_set->add(fixed_bitrate, wg_row++, 2);
1774         y += 30;
1776         add_subwindow(title = new BC_Title(x, y, _("Quantization:")));
1777         titles.append(title);
1778         quant = new MPEGQuant(x1, y, this);
1779         quant->create_objects();
1780         add_subwindow(fixed_quant = new MPEGFixedQuant(x2, y, this));
1781         wg_set->add(title, wg_row, 0);
1782         wg_set->add(quant, wg_row, 1);
1783         wg_set->add(fixed_quant, wg_row++, 2);
1784         y += 30;
1786         add_subwindow(title = new BC_Title(x, y, _("I frame distance:")));
1787         titles.append(title);
1788         iframe_distance = new MPEGIFrameDistance(x1, y, this);
1789         iframe_distance->create_objects();
1790         wg_set->add(title, wg_row, 0);
1791         wg_set->add(iframe_distance, wg_row, 1);
1792         wg_set->set_crspan(wg_row++, 1, 2, 1);
1793         y += 30;
1795         if(asset->vmpeg_cmodel == MPEG_YUV420)
1796         {
1797                 add_subwindow(title = new BC_Title(x, y, _("P frame distance:")));
1798                 titles.append(title);
1799                 pframe_distance = new MPEGPFrameDistance(x1, y, this);
1800                 pframe_distance->create_objects();
1801                 wg_set->add(title, wg_row, 0);
1802                 wg_set->add(pframe_distance, wg_row, 1);
1803                 wg_set->set_crspan(wg_row++, 1, 2, 1);
1804                 y += 30;
1806                 add_subwindow(top_field_first = new BC_CheckBox(x, y, &asset->vmpeg_field_order, _("Bottom field first")));
1807                 y += 30;
1808                 wg_set->add(top_field_first, wg_row, 0);
1809                 wg_set->set_crspan(wg_row++, 0, 3, 1);
1810         }
1812         add_subwindow(progressive = new BC_CheckBox(x, y, &asset->vmpeg_progressive, _("Progressive frames")));
1813         wg_set->add(progressive, wg_row, 0);
1814         wg_set->set_crspan(wg_row++, 0, 3, 1);
1815         y += 30;
1816         add_subwindow(denoise = new BC_CheckBox(x, y, &asset->vmpeg_denoise, _("Denoise")));
1817         wg_set->add(denoise, wg_row, 0);
1818         wg_set->set_crspan(wg_row++, 0, 3, 1);
1819         y += 30;
1820         add_subwindow(seq_codes = new BC_CheckBox(x, y, &asset->vmpeg_seq_codes, _("Sequence start codes in every GOP")));
1821         wg_set->add(seq_codes, wg_row, 0);
1822         wg_set->set_crspan(wg_row++, 0, 3, 1);
1824         wg_set->move_widgets();
1825         resize_window(wg_set->get_w_wm(), wg_set->get_h_wm() + ok_height);
1841 MPEGDerivative::MPEGDerivative(int x, int y, MPEGConfigVideo *gui)
1842  : BC_PopupMenu(x, y, 150, derivative_to_string(gui->asset->vmpeg_derivative))
1844         this->gui = gui;
1847 void MPEGDerivative::create_objects()
1849         add_item(new BC_MenuItem(derivative_to_string(1)));
1850         add_item(new BC_MenuItem(derivative_to_string(2)));
1853 int MPEGDerivative::handle_event()
1855         gui->asset->vmpeg_derivative = string_to_derivative(get_text());
1856         return 1;
1859 int MPEGDerivative::string_to_derivative(char *string)
1861         if(!strcasecmp(derivative_to_string(1), string))
1862                 return 1;
1863         if(!strcasecmp(derivative_to_string(2), string))
1864                 return 2;
1866         return 1;
1869 char* MPEGDerivative::derivative_to_string(int derivative)
1871         switch(derivative)
1872         {
1873                 case 1:
1874                         return _("MPEG-1");
1875                         break;
1876                 
1877                 case 2:
1878                         return _("MPEG-2");
1879                         break;
1880                         
1881                 default:
1882                         return _("MPEG-1");
1883                         break;
1884         }
1897 MPEGPreset::MPEGPreset(int x, int y, MPEGConfigVideo *gui)
1898  : BC_PopupMenu(x, y, 200, value_to_string(gui->asset->vmpeg_preset))
1900         this->gui = gui;
1903 void MPEGPreset::create_objects()
1905         for(int i = 0; i < 10; i++)
1906         {
1907                 add_item(new BC_MenuItem(value_to_string(i)));
1908         }
1911 int MPEGPreset::handle_event()
1913         gui->asset->vmpeg_preset = string_to_value(get_text());
1914         return 1;
1917 int MPEGPreset::string_to_value(char *string)
1919         for(int i = 0; i < 10; i++)
1920         {
1921                 if(!strcasecmp(value_to_string(i), string))
1922                         return i;
1923         }
1924         return 0;
1927 char* MPEGPreset::value_to_string(int derivative)
1929         switch(derivative)
1930         {
1931                 case 0: return _("Generic MPEG-1"); break;
1932                 case 1: return _("standard VCD"); break;
1933                 case 2: return _("user VCD"); break;
1934                 case 3: return _("Generic MPEG-2"); break;
1935                 case 4: return _("standard SVCD"); break;
1936                 case 5: return _("user SVCD"); break;
1937                 case 6: return _("VCD Still sequence"); break;
1938                 case 7: return _("SVCD Still sequence"); break;
1939                 case 8: return _("DVD NAV"); break;
1940                 case 9: return _("DVD"); break;
1941                 default: return _("Generic MPEG-1"); break;
1942         }
1955 MPEGBitrate::MPEGBitrate(int x, int y, MPEGConfigVideo *gui)
1956  : BC_TextBox(x, y, 100, 1, gui->asset->vmpeg_bitrate)
1958         this->gui = gui;
1962 int MPEGBitrate::handle_event()
1964         gui->asset->vmpeg_bitrate = atol(get_text());
1965         return 1;
1972 MPEGQuant::MPEGQuant(int x, int y, MPEGConfigVideo *gui)
1973  : BC_TumbleTextBox(gui, 
1974         (int64_t)gui->asset->vmpeg_quantization, 
1975         (int64_t)1,
1976         (int64_t)100,
1977         x, 
1978         y,
1979         100)
1981         this->gui = gui;
1984 int MPEGQuant::handle_event()
1986         gui->asset->vmpeg_quantization = atol(get_text());
1987         return 1;
1990 MPEGFixedBitrate::MPEGFixedBitrate(int x, int y, MPEGConfigVideo *gui)
1991  : BC_Radial(x, y, gui->asset->vmpeg_fix_bitrate, _("Fixed bitrate"))
1993         this->gui = gui;
1996 int MPEGFixedBitrate::handle_event()
1998         update(1);
1999         gui->asset->vmpeg_fix_bitrate = 1;
2000         gui->fixed_quant->update(0);
2001         return 1;
2004 MPEGFixedQuant::MPEGFixedQuant(int x, int y, MPEGConfigVideo *gui)
2005  : BC_Radial(x, y, !gui->asset->vmpeg_fix_bitrate, _("Fixed quantization"))
2007         this->gui = gui;
2010 int MPEGFixedQuant::handle_event()
2012         update(1);
2013         gui->asset->vmpeg_fix_bitrate = 0;
2014         gui->fixed_bitrate->update(0);
2015         return 1;
2026 MPEGIFrameDistance::MPEGIFrameDistance(int x, int y, MPEGConfigVideo *gui)
2027  : BC_TumbleTextBox(gui, 
2028         (int64_t)gui->asset->vmpeg_iframe_distance, 
2029         (int64_t)1,
2030         (int64_t)100,
2031         x, 
2032         y,
2033         50)
2035         this->gui = gui;
2038 int MPEGIFrameDistance::handle_event()
2040         gui->asset->vmpeg_iframe_distance = atoi(get_text());
2041         return 1;
2050 MPEGPFrameDistance::MPEGPFrameDistance(int x, int y, MPEGConfigVideo *gui)
2051  : BC_TumbleTextBox(gui, 
2052         (int64_t)gui->asset->vmpeg_pframe_distance, 
2053         (int64_t)0,
2054         (int64_t)2,
2055         x, 
2056         y,
2057         50)
2059         this->gui = gui;
2062 int MPEGPFrameDistance::handle_event()
2064         gui->asset->vmpeg_pframe_distance = atoi(get_text());
2065         return 1;
2075 MPEGColorModel::MPEGColorModel(int x, int y, MPEGConfigVideo *gui)
2076  : BC_PopupMenu(x, y, 150, cmodel_to_string(gui->asset->vmpeg_cmodel))
2078         this->gui = gui;
2081 void MPEGColorModel::create_objects()
2083         add_item(new BC_MenuItem(cmodel_to_string(0)));
2084         add_item(new BC_MenuItem(cmodel_to_string(1)));
2087 int MPEGColorModel::handle_event()
2089         gui->asset->vmpeg_cmodel = string_to_cmodel(get_text());
2090         gui->update_cmodel_objs();
2091         return 1;
2094 int MPEGColorModel::string_to_cmodel(char *string)
2096         if(!strcasecmp(cmodel_to_string(0), string))
2097                 return 0;
2098         if(!strcasecmp(cmodel_to_string(1), string))
2099                 return 1;
2100         return 1;
2103 char* MPEGColorModel::cmodel_to_string(int cmodel)
2105         switch(cmodel)
2106         {
2107                 case MPEG_YUV420:
2108                         return _("YUV 4:2:0");
2109                         break;
2110                 
2111                 case MPEG_YUV422:
2112                         return _("YUV 4:2:2");
2113                         break;
2114                         
2115                 default:
2116                         return _("YUV 4:2:0");
2117                         break;
2118         }
2127 //      Local Variables:
2128 //      mode: C++
2129 //      c-file-style: "linux"
2130 //      End: