2 #include "bcprogressbox.h"
3 #include "bcwidgetgrid.h"
12 #include "filesystem.h"
14 #include "indexfile.h"
15 #include "interlacemodes.h"
17 #include "mainerror.h"
18 #include "mwindow.inc"
19 #include "preferences.h"
21 #include "videodevice.inc"
31 #define MJPEG_EXE PLUGIN_DIR "/mpeg2enc.plugin"
39 // M JPEG dependancies
40 static double frame_rate_codes[] =
53 static double aspect_ratio_codes[] =
69 FileMPEG::FileMPEG(Asset_GC asset, File *file)
70 : FileBase(asset, file)
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");
83 delete next_frame_lock;
84 delete next_frame_done;
87 void FileMPEG::get_parameters(BC_WindowBase *parent_window,
89 BC_WindowBase* &format_window,
93 if(audio_options && asset->format == FILE_AMPEG)
95 MPEGConfigAudio *window = new MPEGConfigAudio(parent_window, asset);
96 format_window = window;
97 window->create_objects();
102 if(video_options && asset->format == FILE_VMPEG)
104 MPEGConfigVideo *window = new MPEGConfigVideo(parent_window, asset);
105 format_window = window;
106 window->create_objects();
107 window->run_window();
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)
122 if((fd = mpeg3_open(asset->path, &error)))
124 *bytes = mpeg3_get_bytes(fd);
125 *stracks = mpeg3_subtitle_tracks(fd);
131 int FileMPEG::reset_parameters_derived()
148 toolame_allocation = 0;
155 lame_output_allocation = 0;
161 // Just create the Quicktime objects since this routine is also called
163 int FileMPEG::open_file(int rd, int wr)
173 if(!(fd = mpeg3_open(asset->path, &error)))
175 char string[BCTEXTLEN];
176 if(error == MPEG3_INVALID_TOC_VERSION)
178 eprintf("Couldn't open %s because it has an invalid table of contents version.\n"
179 "Rebuild the table of contents with mpeg3toc.",
183 if(error == MPEG3_TOC_DATE_MISMATCH)
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.",
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))
197 if(create_index()) return 1;
200 mpeg3_set_cpus(fd, file->cpus);
202 asset->audio_data = mpeg3_has_audio(fd);
203 if(asset->audio_data)
206 for(int i = 0; i < mpeg3_total_astreams(fd); i++)
208 asset->channels += mpeg3_audio_channels(fd, i);
210 if(!asset->sample_rate)
211 asset->sample_rate = mpeg3_sample_rate(fd, 0);
212 asset->audio_length = mpeg3_audio_samples(fd, 0);
215 asset->video_data = mpeg3_has_video(fd);
216 if(asset->video_data)
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);
230 //printf("FileMPEG::open %d\n", file->playback_subtitle);
231 if(file->playback_subtitle >= 0)
232 mpeg3_show_subtitle(fd, file->playback_subtitle);
239 if(wr && asset->format == FILE_VMPEG)
241 // Heroine Virtual encoder
242 if(asset->vmpeg_cmodel == MPEG_YUV422)
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
255 append_vcommand_line("mpeg2enc");
258 if(asset->aspect_ratio > 0)
260 append_vcommand_line("-a");
261 if(EQUIV(asset->aspect_ratio, 1))
262 append_vcommand_line("1");
264 if(EQUIV(asset->aspect_ratio, 1.333))
265 append_vcommand_line("2");
267 if(EQUIV(asset->aspect_ratio, 1.777))
268 append_vcommand_line("3");
270 if(EQUIV(asset->aspect_ratio, 2.11))
271 append_vcommand_line("4");
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)
278 append_vcommand_line("--cbr -b");
279 append_vcommand_line(bitrate_string);
283 append_vcommand_line("-q");
284 append_vcommand_line(quant_string);
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);
300 // mjpegtools encoder
302 char string[BCTEXTLEN];
303 sprintf(mjpeg_command, MJPEG_EXE);
305 // Must disable interlacing if MPEG-1
306 switch (asset->vmpeg_preset)
308 case 0: asset->vmpeg_progressive = 1; break;
309 case 1: asset->vmpeg_progressive = 1; break;
310 case 2: asset->vmpeg_progressive = 1; break;
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)
319 sprintf(string, " -b %d -q 1", asset->vmpeg_bitrate / 1000);
323 sprintf(string, " -b 0 -q %d", asset->vmpeg_quantization);
325 strcat(mjpeg_command, string);
333 int aspect_ratio_code = -1;
334 if(asset->aspect_ratio > 0)
336 for(int i = 0; i < sizeof(aspect_ratio_codes) / sizeof(double); i++)
338 if(EQUIV(aspect_ratio_codes[i], asset->aspect_ratio))
340 aspect_ratio_code = i;
345 if(aspect_ratio_code < 0)
347 eprintf("Unsupported aspect ratio %f\n", asset->aspect_ratio);
348 aspect_ratio_code = 2;
350 sprintf(string, " -a %d", aspect_ratio_code);
351 strcat(mjpeg_command, string);
359 int frame_rate_code = -1;
360 for(int i = 1; sizeof(frame_rate_codes) / sizeof(double); ++i)
362 if(EQUIV(asset->frame_rate, frame_rate_codes[i]))
368 if(frame_rate_code < 0)
371 eprintf("Unsupported frame rate %f\n", asset->frame_rate);
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");
385 sprintf(string, " -M %d", file->cpus);
386 strcat(mjpeg_command, string);
389 if(!asset->vmpeg_progressive)
391 strcat(mjpeg_command, asset->vmpeg_field_order ? " -z b" : " -z t");
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")))
417 eprintf("Error while opening \"%s\" for writing. \n%m\n", mjpeg_command);
420 video_out = new FileMPEGVideo(this);
425 if(wr && asset->format == FILE_AMPEG)
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)
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);
453 if(asset->ampeg_derivative == 3)
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,
460 lame_set_num_channels(lame_global,
462 if((result = lame_init_params(lame_global)) < 0)
464 eprintf(_("encode: lame_init_params returned %d\n"), result);
465 lame_close(lame_global);
469 if(!(lame_fd = fopen(asset->path, "w")))
471 eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
472 lame_close(lame_global);
479 eprintf("ampeg_derivative=%d\n", asset->ampeg_derivative);
484 // Transport stream for DVB capture
487 if(!(dvb_out = fopen(asset->path, "w")))
489 eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
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,
517 char *ptr = strrchr(index_filename, '.');
522 // File is a table of contents.
523 if(fd && mpeg3_has_toc(fd)) return 0;
525 sprintf(ptr, ".toc");
530 // Test existing copy of TOC
531 mpeg3_close(fd); // Always free old fd
532 if((fd_toc = mpeg3_open(index_filename, &error)))
534 // Just exchange old fd
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);
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,
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)
566 gettimeofday(¤t_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);
576 progress->update_title(string, 1);
577 // fprintf(stderr, "ETA: %dm%ds \r",
578 // bytes_processed * 100 / total_bytes,
582 prev_time = new_time;
584 if(bytes_processed >= total_bytes) break;
585 if(progress->is_cancelled())
592 mpeg3_stop_toc(index_file);
594 progress->stop_progress();
600 remove(index_filename);
604 // Reopen file from index path instead of asset path.
605 if(!(fd = mpeg3_open(index_filename, &error)))
617 void FileMPEG::append_vcommand_line(const char *string)
621 char *argv = strdup(string);
622 vcommand_line.append(argv);
626 void FileMPEG::append_acommand_line(const char *string)
630 char *argv = strdup(string);
631 acommand_line.append(argv);
636 int FileMPEG::close_file()
639 next_frame_lock->unlock();
648 // End of sequence signal
649 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
651 mpeg2enc_set_input_buffers(1, 0, 0, 0);
657 vcommand_line.remove_all_objects();
658 acommand_line.remove_all_objects();
662 toolame_send_buffer(0, 0);
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);
686 FileBase::close_file();
690 int FileMPEG::get_best_colormodel(Asset_GC asset, int driver)
692 //printf("FileMPEG::get_best_colormodel 1\n");
697 if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
698 if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
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;
705 case PLAYBACK_X11_GL:
712 case PLAYBACK_DV1394:
713 case PLAYBACK_FIREWIRE:
718 if(asset->vmpeg_cmodel == MPEG_YUV420) return BC_YUV420P;
719 if(asset->vmpeg_cmodel == MPEG_YUV422) return BC_YUV422P;
725 case CAPTURE_FIREWIRE:
726 case CAPTURE_IEC61883:
730 //printf("FileMPEG::get_best_colormodel 100\n");
733 int FileMPEG::colormodel_supported(int colormodel)
738 int FileMPEG::get_index(char *index_path)
743 // Convert the index tables from tracks to channels.
744 if(mpeg3_index_tracks(fd))
746 // Calculate size of buffer needed for all channels
748 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
750 buffer_size += mpeg3_index_size(fd, i) *
751 mpeg3_index_channels(fd, i) *
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++)
766 for(int j = 0; j < mpeg3_index_channels(fd, i); j++)
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;
780 asset->index_bytes = fs.get_size(asset->path);
782 asset->write_index(index_path, buffer_size * sizeof(float));
783 delete [] asset->index_buffer;
792 int FileMPEG::can_copy_from(Edit *edit, int64_t position)
798 int FileMPEG::set_audio_position(int64_t sample)
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)
810 if(sample >= 0 && sample < asset->audio_length)
812 //printf("FileMPEG::set_audio_position seeking stream %d\n", sample);
813 return mpeg3_set_sample(fd, sample, stream);
822 int FileMPEG::set_video_position(int64_t x)
825 if(x >= 0 && x < asset->video_length)
827 //printf("FileMPEG::set_video_position 1 %lld\n", x);
828 mpeg3_set_frame(fd, x, file->current_layer);
834 int64_t FileMPEG::get_memory_usage()
838 int64_t result = mpeg3_memory_usage(fd);
845 int FileMPEG::write_samples(double **buffer, int64_t len)
849 //printf("FileMPEG::write_samples 1\n");
850 if(asset->ampeg_derivative == 2)
853 int channels = MIN(asset->channels, 2);
854 int64_t audio_size = len * channels * 2;
855 if(toolame_allocation < audio_size)
857 if(toolame_temp) delete [] toolame_temp;
858 toolame_temp = new unsigned char[audio_size];
859 toolame_allocation = audio_size;
862 for(int i = 0; i < channels; i++)
864 int16_t *output = ((int16_t*)toolame_temp) + i;
865 double *input = buffer[i];
866 for(int j = 0; j < len; j++)
868 int sample = (int)(*input * 0x7fff);
869 *output = (int16_t)(CLIP(sample, -0x8000, 0x7fff));
874 result = toolame_send_buffer((char*)toolame_temp, audio_size);
877 if(asset->ampeg_derivative == 3)
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)
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;
892 if(lame_output_allocation < audio_size * 4)
894 if(lame_output) delete [] lame_output;
895 lame_output_allocation = audio_size * 4;
896 lame_output = new char[lame_output_allocation];
899 for(int i = 0; i < channels; i++)
901 float *output = lame_temp[i];
902 double *input = buffer[i];
903 for(int j = 0; j < len; j++)
905 *output++ = *input++ * (float)32768;
909 result = lame_encode_buffer_float(lame_global,
911 (channels > 1) ? lame_temp[1] : lame_temp[0],
913 (unsigned char*)lame_output,
914 lame_output_allocation);
917 char *real_output = lame_output;
921 for(int i = 0; i < bytes; i++)
924 real_output = &lame_output[i];
930 if(bytes > 0 && lame_started)
932 result = !fwrite(real_output, 1, bytes, lame_fd);
934 eprintf("Error while writing samples");
946 int FileMPEG::write_frames(VFrame ***frames, int len)
952 int temp_w = (int)((asset->width + 15) / 16) * 16;
957 (asset->vmpeg_cmodel == MPEG_YUV420) ? BC_YUV420P : BC_YUV422P;
960 // Height depends on progressiveness
961 if(asset->vmpeg_progressive || asset->vmpeg_derivative == 1)
962 temp_h = (int)((asset->height + 15) / 16) * 16;
964 temp_h = (int)((asset->height + 31) / 32) * 32;
966 //printf("FileMPEG::write_frames 1\n");
968 // Only 1 layer is supported in MPEG output
969 for(int i = 0; i < 1; i++)
971 for(int j = 0; j < len && !result; j++)
973 VFrame *frame = frames[i][j];
977 if(asset->vmpeg_cmodel == MPEG_YUV422)
979 if(frame->get_w() == temp_w &&
980 frame->get_h() == temp_h &&
981 frame->get_color_model() == output_cmodel)
983 mpeg2enc_set_input_buffers(0,
984 (char*)frame->get_y(),
985 (char*)frame->get_u(),
986 (char*)frame->get_v());
991 (temp_frame->get_w() != temp_w ||
992 temp_frame->get_h() != temp_h ||
993 temp_frame->get_color_model() || output_cmodel))
1002 temp_frame = new VFrame(0,
1008 cmodel_transfer(temp_frame->get_rows(),
1010 temp_frame->get_y(),
1011 temp_frame->get_u(),
1012 temp_frame->get_v(),
1024 frame->get_color_model(),
1025 temp_frame->get_color_model(),
1030 mpeg2enc_set_input_buffers(0,
1031 (char*)temp_frame->get_y(),
1032 (char*)temp_frame->get_u(),
1033 (char*)temp_frame->get_v());
1038 // MJPEG uses the same dimensions as the input
1039 if(frame->get_color_model() == output_cmodel)
1041 mjpeg_y = frame->get_y();
1042 mjpeg_u = frame->get_u();
1043 mjpeg_v = frame->get_v();
1049 temp_frame = new VFrame(0,
1055 cmodel_transfer(temp_frame->get_rows(),
1057 temp_frame->get_y(),
1058 temp_frame->get_u(),
1059 temp_frame->get_v(),
1071 frame->get_color_model(),
1072 temp_frame->get_color_model(),
1077 mjpeg_y = temp_frame->get_y();
1078 mjpeg_u = temp_frame->get_u();
1079 mjpeg_v = temp_frame->get_v();
1085 next_frame_lock->unlock();
1086 next_frame_done->lock("FileMPEG::write_frames");
1087 if(mjpeg_error) result = 1;
1103 int FileMPEG::read_frame(VFrame *frame)
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;
1116 if(mpeg3_colormodel(fd, 0) == MPEG3_YUV422P)
1117 src_cmodel = BC_YUV422P;
1119 switch(frame->get_color_model())
1123 case MPEG3_BGRA8888:
1125 case MPEG3_RGBA8888:
1126 case MPEG3_RGBA16161616:
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 */
1134 asset->width, /* Dimensions of output_rows */
1136 frame->get_color_model(), /* One of the color model #defines */
1137 file->current_layer);
1143 // Read these directly
1144 if(frame->get_color_model() == src_cmodel)
1147 mpeg3_read_yuvframe(fd,
1148 (char*)frame->get_y(),
1149 (char*)frame->get_u(),
1150 (char*)frame->get_v(),
1155 file->current_layer);
1159 // Process through temp frame
1163 mpeg3_read_yuvframe_ptr(fd,
1167 file->current_layer);
1171 cmodel_transfer(frame->get_rows(),
1188 frame->get_color_model(),
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++)
1211 int FileMPEG::read_samples(double *buffer, int64_t len)
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);
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,
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;
1244 int FileMPEG::prefer_samples_float()
1249 int FileMPEG::read_samples_float(float *buffer, int64_t len)
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);
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,
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");
1279 char* FileMPEG::strtocompression(char *string)
1284 char* FileMPEG::compressiontostr(char *string)
1295 FileMPEGVideo::FileMPEGVideo(FileMPEG *file)
1301 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
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);
1310 FileMPEGVideo::~FileMPEGVideo()
1315 void FileMPEGVideo::run()
1317 if(file->asset->vmpeg_cmodel == MPEG_YUV422)
1319 printf("FileMPEGVideo::run ");
1320 for(int i = 0; i < file->vcommand_line.total; i++)
1321 printf("%s ", file->vcommand_line.values[i]);
1323 mpeg2enc(file->vcommand_line.total, file->vcommand_line.values);
1329 file->next_frame_lock->lock("FileMPEGVideo::run");
1332 file->next_frame_done->unlock();
1338 // YUV4 sequence header
1339 if(!file->wrote_header)
1341 file->wrote_header = 1;
1343 char string[BCTEXTLEN];
1344 char interlace_string[BCTEXTLEN];
1345 if(!file->asset->vmpeg_progressive)
1347 sprintf(interlace_string, file->asset->vmpeg_field_order ? "b" : "t");
1351 sprintf(interlace_string, "p");
1354 fprintf(file->mjpeg_out, "YUV4MPEG2 W%d H%d F%d:%d I%s A%d:%d C%s\n",
1356 file->asset->height,
1357 (int)(file->asset->frame_rate * 1001),
1360 (int)(file->asset->aspect_ratio * 1000),
1365 // YUV4 frame header
1366 fprintf(file->mjpeg_out, "FRAME\n");
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();
1379 pclose(file->mjpeg_out);
1380 file->mjpeg_out = 0;
1403 FileMPEGAudio::FileMPEGAudio(FileMPEG *file)
1407 toolame_init_buffers();
1410 FileMPEGAudio::~FileMPEGAudio()
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),
1439 this->parent_window = parent_window;
1440 this->asset = asset;
1443 MPEGConfigAudio::~MPEGConfigAudio()
1447 int MPEGConfigAudio::create_objects()
1454 BC_RelocatableWidget *rw;
1455 wg = add_widgetgrid(new BC_WidgetGrid(10, 10, 10, 10, 3, 3));
1458 if(asset->format == FILE_MPEG)
1460 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
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);
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);
1482 add_subwindow(new BC_OKButton(this));
1485 resize_window(wg->get_w_wm(), wg->get_h_wm() + rw->get_h());
1492 int MPEGConfigAudio::close_event()
1504 MPEGLayer::MPEGLayer(int x, int y, MPEGConfigAudio *gui)
1505 : BC_PopupMenu(x, y, 100, layer_to_string(gui->asset->ampeg_derivative))
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);
1523 int MPEGLayer::string_to_layer(char *string)
1525 if(!strcasecmp(layer_to_string(2), string))
1527 if(!strcasecmp(layer_to_string(3), string))
1533 char* MPEGLayer::layer_to_string(int layer)
1557 MPEGABitrate::MPEGABitrate(int x, int y, MPEGConfigAudio *gui)
1561 bitrate_to_string(gui->string, gui->asset->ampeg_bitrate))
1566 void MPEGABitrate::create_objects()
1568 set_layer(gui->asset->ampeg_derivative);
1571 void MPEGABitrate::set_layer(int layer)
1573 while(total_items())
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"));
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"));
1610 int MPEGABitrate::handle_event()
1612 gui->asset->ampeg_bitrate = string_to_bitrate(get_text());
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);
1636 MPEGConfigVideo::MPEGConfigVideo(BC_WindowBase *parent_window,
1638 : BC_Window(PROGRAM_NAME ": Video Compression",
1639 parent_window->get_abs_cursor_x(1),
1640 parent_window->get_abs_cursor_y(1),
1649 this->parent_window = parent_window;
1650 this->asset = asset;
1655 MPEGConfigVideo::~MPEGConfigVideo()
1659 int MPEGConfigVideo::create_objects()
1665 if(asset->format == FILE_MPEG)
1667 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
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();
1676 BC_OKButton *okbutton;
1677 add_subwindow(okbutton = new BC_OKButton(this));
1678 ok_height = okbutton->get_h();
1680 update_cmodel_objs();
1687 int MPEGConfigVideo::close_event()
1694 void MPEGConfigVideo::delete_cmodel_objs()
1699 delete fixed_bitrate;
1702 delete iframe_distance;
1703 delete pframe_distance;
1704 delete top_field_first;
1708 titles.remove_all_objects();
1712 void MPEGConfigVideo::reset_cmodel()
1720 iframe_distance = 0;
1721 pframe_distance = 0;
1722 top_field_first = 0;
1728 void MPEGConfigVideo::update_cmodel_objs()
1736 BC_RelocatableWidget *rw;
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)
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();
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);
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);
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);
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);
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);
1795 if(asset->vmpeg_cmodel == MPEG_YUV420)
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);
1806 add_subwindow(top_field_first = new BC_CheckBox(x, y, &asset->vmpeg_field_order, _("Bottom field first")));
1808 wg_set->add(top_field_first, wg_row, 0);
1809 wg_set->set_crspan(wg_row++, 0, 3, 1);
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);
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);
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))
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());
1859 int MPEGDerivative::string_to_derivative(char *string)
1861 if(!strcasecmp(derivative_to_string(1), string))
1863 if(!strcasecmp(derivative_to_string(2), string))
1869 char* MPEGDerivative::derivative_to_string(int derivative)
1897 MPEGPreset::MPEGPreset(int x, int y, MPEGConfigVideo *gui)
1898 : BC_PopupMenu(x, y, 200, value_to_string(gui->asset->vmpeg_preset))
1903 void MPEGPreset::create_objects()
1905 for(int i = 0; i < 10; i++)
1907 add_item(new BC_MenuItem(value_to_string(i)));
1911 int MPEGPreset::handle_event()
1913 gui->asset->vmpeg_preset = string_to_value(get_text());
1917 int MPEGPreset::string_to_value(char *string)
1919 for(int i = 0; i < 10; i++)
1921 if(!strcasecmp(value_to_string(i), string))
1927 char* MPEGPreset::value_to_string(int derivative)
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;
1955 MPEGBitrate::MPEGBitrate(int x, int y, MPEGConfigVideo *gui)
1956 : BC_TextBox(x, y, 100, 1, gui->asset->vmpeg_bitrate)
1962 int MPEGBitrate::handle_event()
1964 gui->asset->vmpeg_bitrate = atol(get_text());
1972 MPEGQuant::MPEGQuant(int x, int y, MPEGConfigVideo *gui)
1973 : BC_TumbleTextBox(gui,
1974 (int64_t)gui->asset->vmpeg_quantization,
1984 int MPEGQuant::handle_event()
1986 gui->asset->vmpeg_quantization = atol(get_text());
1990 MPEGFixedBitrate::MPEGFixedBitrate(int x, int y, MPEGConfigVideo *gui)
1991 : BC_Radial(x, y, gui->asset->vmpeg_fix_bitrate, _("Fixed bitrate"))
1996 int MPEGFixedBitrate::handle_event()
1999 gui->asset->vmpeg_fix_bitrate = 1;
2000 gui->fixed_quant->update(0);
2004 MPEGFixedQuant::MPEGFixedQuant(int x, int y, MPEGConfigVideo *gui)
2005 : BC_Radial(x, y, !gui->asset->vmpeg_fix_bitrate, _("Fixed quantization"))
2010 int MPEGFixedQuant::handle_event()
2013 gui->asset->vmpeg_fix_bitrate = 0;
2014 gui->fixed_bitrate->update(0);
2026 MPEGIFrameDistance::MPEGIFrameDistance(int x, int y, MPEGConfigVideo *gui)
2027 : BC_TumbleTextBox(gui,
2028 (int64_t)gui->asset->vmpeg_iframe_distance,
2038 int MPEGIFrameDistance::handle_event()
2040 gui->asset->vmpeg_iframe_distance = atoi(get_text());
2050 MPEGPFrameDistance::MPEGPFrameDistance(int x, int y, MPEGConfigVideo *gui)
2051 : BC_TumbleTextBox(gui,
2052 (int64_t)gui->asset->vmpeg_pframe_distance,
2062 int MPEGPFrameDistance::handle_event()
2064 gui->asset->vmpeg_pframe_distance = atoi(get_text());
2075 MPEGColorModel::MPEGColorModel(int x, int y, MPEGConfigVideo *gui)
2076 : BC_PopupMenu(x, y, 150, cmodel_to_string(gui->asset->vmpeg_cmodel))
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();
2094 int MPEGColorModel::string_to_cmodel(char *string)
2096 if(!strcasecmp(cmodel_to_string(0), string))
2098 if(!strcasecmp(cmodel_to_string(1), string))
2103 char* MPEGColorModel::cmodel_to_string(int cmodel)
2108 return _("YUV 4:2:0");
2112 return _("YUV 4:2:2");
2116 return _("YUV 4:2:0");
2129 // c-file-style: "linux"