4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bcprogressbox.h"
24 #include "bcsignals.h"
25 #include "bitspopup.h"
26 #include "byteorder.h"
28 #include "commercials.h"
29 #include "condition.h"
34 #include "filesystem.h"
36 #include "indexfile.h"
37 #include "interlacemodes.h"
38 #include "indexstate.h"
40 #include "mainerror.h"
43 #include "preferences.h"
44 #include "removefile.h"
46 #include "videodevice.inc"
53 #define HVPEG_EXE "/hveg2enc"
54 #define MJPEG_EXE "/mpeg2enc"
57 // M JPEG dependancies
58 static double frame_rate_codes[] =
71 static double aspect_ratio_codes[] =
87 FileMPEG::FileMPEG(Asset *asset, File *file)
88 : FileBase(asset, file)
91 // May also be VMPEG or AMPEG if write status.
92 if(asset->format == FILE_UNKNOWN) asset->format = FILE_MPEG;
93 asset->byte_order = 0;
94 next_frame_lock = new Condition(0, "FileMPEG::next_frame_lock");
95 next_frame_done = new Condition(0, "FileMPEG::next_frame_done");
96 vcommand_line.set_array_delete();
102 delete next_frame_lock;
103 delete next_frame_done;
104 vcommand_line.remove_all_objects();
107 void FileMPEG::get_parameters(BC_WindowBase *parent_window,
108 Asset *asset, BC_WindowBase* &format_window,
109 int audio_options, int video_options, EDL *edl)
111 if(audio_options && asset->format == FILE_AMPEG)
113 MPEGConfigAudio *window = new MPEGConfigAudio(parent_window, asset);
114 format_window = window;
115 window->create_objects();
116 window->run_window();
120 if(video_options && asset->format == FILE_VMPEG)
122 MPEGConfigVideo *window = new MPEGConfigVideo(parent_window, asset);
123 format_window = window;
124 window->create_objects();
125 window->run_window();
130 int FileMPEG::check_sig(Asset *asset)
132 return mpeg3_check_sig(asset->path);
135 void FileMPEG::get_info(char *title_path, char *path, char *text, int len)
141 int zio_access = ZIO_UNBUFFERED+ZIO_SINGLE_ACCESS;
142 if( !(fd=mpeg3_zopen(title_path, path, &result,zio_access)) ) result = 1;
143 if( !result ) result = mpeg3_create_title(fd, 0);
146 char *cp = text, *ep = text + len-1;
147 if( mpeg3_has_toc(fd) ) {
148 cp += snprintf(cp,ep-cp, _("toc path:%s\n"), path);
149 cp += snprintf(cp,ep-cp, _("title path:\n"));
150 for( int i=0; i<100; ++i ) {
151 char *title_path = mpeg3_title_path(fd,i);
152 if( !title_path ) break;
153 cp += snprintf(cp,ep-cp, " %2d. %s\n", i+1, title_path);
157 cp += snprintf(cp,ep-cp, _("file path:%s\n"), path);
158 int64_t bytes = mpeg3_get_bytes(fd);
159 char string[BCTEXTLEN];
160 sprintf(string,"%jd",bytes);
161 Units::punctuate(string);
162 cp += snprintf(cp,ep-cp, _("size: %s"), string);
164 if( mpeg3_is_program_stream(fd) )
165 cp += snprintf(cp,ep-cp, _(" program stream\n"));
166 else if( mpeg3_is_transport_stream(fd) )
167 cp += snprintf(cp,ep-cp, _(" transport stream\n"));
168 else if( mpeg3_is_video_stream(fd) )
169 cp += snprintf(cp,ep-cp, _(" video stream\n"));
170 else if( mpeg3_is_audio_stream(fd) )
171 cp += snprintf(cp,ep-cp, _(" audio stream\n"));
173 int64_t sdate = mpeg3_get_source_date(fd);
176 memset(&ostat,0,sizeof(struct stat64));
177 sdate = stat64(path, &ostat) < 0 ? 0 : ostat.st_mtime;
179 time_t tm = (time_t)sdate;
180 cp += snprintf(cp,ep-cp, _("date: %s\n"), ctime(&tm));
182 int vtrks = mpeg3_total_vstreams(fd);
183 cp += snprintf(cp,ep-cp, _("%d video tracks\n"), vtrks);
184 for( int vtrk=0; vtrk<vtrks; ++vtrk ) {
185 int cmdl = mpeg3_colormodel(fd, vtrk);
186 int color_model = bc_colormodel(cmdl);
187 char *cmodel = MPEGColorModel::cmodel_to_string(color_model);
188 int width = mpeg3_video_width(fd, vtrk);
189 int height = mpeg3_video_height(fd, vtrk);
190 cp += snprintf(cp,ep-cp, _(" v%d %s %dx%d"), vtrk, cmodel, width, height);
191 double frame_rate = mpeg3_frame_rate(fd, vtrk);
192 int64_t frames = mpeg3_video_frames(fd, vtrk);
193 cp += snprintf(cp,ep-cp, _(" (%5.2f), %jd frames"), frame_rate, frames);
194 if( frame_rate > 0 ) {
195 double secs = (double)frames / frame_rate;
196 cp += snprintf(cp,ep-cp, _(" (%0.3f secs)"),secs);
200 int atrks = mpeg3_total_astreams(fd);
201 cp += snprintf(cp,ep-cp, _("%d audio tracks\n"), atrks);
202 for( int atrk=0; atrk<atrks; ++atrk) {
203 const char *format = mpeg3_audio_format(fd, atrk);
204 cp += snprintf(cp,ep-cp, _(" a%d %s"), atrk, format);
205 int channels = mpeg3_audio_channels(fd, atrk);
206 int sample_rate = mpeg3_sample_rate(fd, atrk);
207 cp += snprintf(cp,ep-cp, _(" ch%d (%d)"), channels, sample_rate);
208 int64_t samples = mpeg3_audio_samples(fd, atrk);
209 cp += snprintf(cp,ep-cp, " %jd",samples);
210 int64_t nudge = mpeg3_get_audio_nudge(fd, atrk);
211 *cp++ = nudge >= 0 ? '+' : (nudge=-nudge, '-');
212 cp += snprintf(cp,ep-cp, _("%jd samples"),nudge);
213 if( sample_rate > 0 ) {
214 double secs = (double)(samples+nudge) / sample_rate;
215 cp += snprintf(cp,ep-cp, _(" (%0.3f secs)"),secs);
219 int stracks = mpeg3_subtitle_tracks(fd);
221 cp += snprintf(cp,ep-cp, _("%d subtitles\n"), stracks);
223 int vts_titles = mpeg3_get_total_vts_titles(fd);
225 cp += snprintf(cp,ep-cp, _("%d title sets, "), vts_titles);
226 int interleaves = mpeg3_get_total_interleaves(fd);
227 if( interleaves > 0 )
228 cp += snprintf(cp,ep-cp, _("%d interleaves\n"), interleaves);
229 int vts_title = mpeg3_set_vts_title(fd, -1);
230 int angle = mpeg3_set_angle(fd, -1);
231 int interleave = mpeg3_set_interleave(fd, -1);
232 int program = mpeg3_set_program(fd, -1);
233 cp += snprintf(cp,ep-cp, _("current program %d = title %d, angle %d, interleave %d\n\n"),
234 program, vts_title, angle, interleave);
236 ArrayList<double> cell_times;
237 int cell_no = 0; double cell_time;
238 while( !mpeg3_get_cell_time(fd, cell_no++, &cell_time) ) {
239 cell_times.append(cell_time);
241 if( cell_times.size() > 1 ) {
242 cp += snprintf(cp,ep-cp, _("cell times:"));
243 for( int i=0; i<cell_times.size(); ++i ) {
244 if( (i%4) == 0 ) *cp++ = '\n';
245 cp += snprintf(cp,ep-cp," %3d. %8.3f",i,cell_times.get(i));
247 cp += snprintf(cp,ep-cp, "\n");
250 int elements = mpeg3_dvb_channel_count(fd);
251 if( elements <= 0 ) return;
252 if( !mpeg3_dvb_get_system_time(fd, &sdate) ) {
254 cp += snprintf(cp,ep-cp, _("\nsystem time: %s"), ctime_r(&tm,string));
256 cp += snprintf(cp,ep-cp, _("elements %d\n"), elements);
258 for( int n=0; n<elements; ++n ) {
259 char name[16], enc[8]; int vstream, astream;
260 int major, minor, total_astreams, total_vstreams;
261 if( mpeg3_dvb_get_channel(fd,n, &major, &minor) ||
262 mpeg3_dvb_get_station_id(fd,n,&name[0]) ||
263 mpeg3_dvb_total_vstreams(fd,n,&total_vstreams) ||
264 mpeg3_dvb_total_astreams(fd,n,&total_astreams) ) continue;
265 cp += snprintf(cp,ep-cp, " %3d.%-3d %s", major, minor, &name[0]);
266 for( int vidx=0; vidx<total_vstreams; ++vidx ) {
267 if( mpeg3_dvb_vstream_number(fd,n,vidx,&vstream) ) continue;
268 if( vstream < 0 ) continue;
269 cp += snprintf(cp,ep-cp, " v%d", vstream);
271 for( int aidx=0; aidx<total_astreams; ++aidx ) {
272 if( mpeg3_dvb_astream_number(fd,n,aidx,&astream,&enc[0]) ) continue;
273 if( astream < 0 ) continue;
274 cp += snprintf(cp,ep-cp, " a%d %s", astream, &enc[0]);
276 for(int i=0; i<astream; ++i )
277 atrack += mpeg3_audio_channels(fd, i);
278 int channels = mpeg3_audio_channels(fd, astream);
279 cp += snprintf(cp,ep-cp, " trk %d-%d", atrack+1, atrack+channels);
280 if( enc[0] ) cp += snprintf(cp,ep-cp," (%s)",enc);
282 cp += snprintf(cp,ep-cp, "\n");
285 for( int n=0; n<elements; ++n ) {
287 if( mpeg3_dvb_get_channel(fd,n, &major, &minor) ) continue;
288 cp += snprintf(cp,ep-cp, "\n**chan %3d.%-3d\n", major, minor);
289 int len = mpeg3_dvb_get_chan_info(fd, n, -1, 0, cp, 1023);
290 if( len < 0 ) len = snprintf(cp,ep-cp,_("no info"));
291 cp += len; *cp++ = '*'; *cp++ = '*'; *cp++ = '\n';
292 for( int ord=0; ord<0x80; ++ord ) {
293 for( int i=0; (len=mpeg3_dvb_get_chan_info(fd,n,ord,i,cp,1023)) >= 0; ++i ) {
294 char *bp = cp; cp += len;
295 for( int k=2; --k>=0; ) { // skip 2 lines
296 while( bp<cp && *bp++!='\n' );
298 for( char *lp=bp; bp<cp; ++bp ) { // add new lines
299 if( *bp == '\n' || ((bp-lp)>=60 && *bp==' ') )
302 *cp++ = '\n'; *cp = 0; // trailing new line
312 int FileMPEG::get_audio_for_video(int vstream, int astream, int64_t &channel_mask)
316 int elements = mpeg3_dvb_channel_count(fd);
317 if( elements <= 0 ) return -1;
320 int total_astreams = 0, total_vstreams = 0;
321 for( int n=0; pidx<0 && n<elements; ++n ) {
322 total_astreams = total_vstreams = 0;
323 if( mpeg3_dvb_total_vstreams(fd,n,&total_vstreams) ||
324 mpeg3_dvb_total_astreams(fd,n,&total_astreams) ) continue;
325 if( !total_vstreams || !total_astreams ) continue;
326 for( int i=0; pidx<0 && i<total_vstreams; ++i ) {
328 if( mpeg3_dvb_vstream_number(fd,n,i,&vstrm) ) continue;
329 if( vstrm == vstream ) pidx = n;
332 if( pidx < 0 ) return -1;
334 int64_t channels = 0;
335 for( int i=0; i<total_astreams; ++i ) {
337 if( mpeg3_dvb_astream_number(fd,pidx,i,&astrm,0) ) continue;
338 if( astrm < 0 ) continue;
339 if( ret < 0 ) ret = astrm;
340 if( astream > 0 ) { --astream; continue; }
342 for(int i=0; i<astrm; ++i )
343 atrack += mpeg3_audio_channels(fd, i);
344 int64_t mask = (1 << mpeg3_audio_channels(fd, astrm)) - 1;
345 channels |= mask << atrack;
346 if( !astream ) break;
348 channel_mask = channels;
352 int FileMPEG::reset_parameters_derived()
365 twolame_allocation = 0;
374 lame_output_allocation = 0;
381 int FileMPEG::open_file(int rd, int wr)
387 char toc_name[BCTEXTLEN];
388 result = file->preferences->get_asset_file_path(asset, toc_name);
391 // if toc exists, use it otherwise just probe file
392 char *path = !result ? toc_name : asset->path;
393 fd = mpeg3_open_title(asset->path, path, &error);
396 case zmpeg3_t::ERR_INVALID_TOC_VERSION:
397 eprintf(_("Couldn't open %s: invalid table of contents version.\n"),asset->path);
400 case zmpeg3_t::ERR_TOC_DATE_MISMATCH:
401 eprintf(_("Couldn't open %s: table of contents out of date.\n"),asset->path);
405 eprintf(_("Couldn't open %s: table of contents corrupt.\n"),asset->path);
410 eprintf(_("Rebuilding the table of contents\n"));
415 if( mpeg3_has_toc(fd) )
417 else if( mpeg3_total_vstreams(fd) || mpeg3_total_astreams(fd) )
420 eprintf(_("Couldn't open %s: no audio or video.\n"),asset->path);
427 if( fd ) { mpeg3_close(fd); fd = 0; }
428 result = create_toc(toc_name);
432 mpeg3_set_cpus(fd, file->cpus < 4 ? file->cpus : 4);
433 file->current_program = mpeg3_set_program(fd, -1);
434 if( asset->program < 0 )
435 asset->program = file->current_program;
437 asset->audio_data = mpeg3_has_audio(fd);
438 if(asset->audio_data) {
440 for(int i = 0; i < mpeg3_total_astreams(fd); i++) {
441 asset->channels += mpeg3_audio_channels(fd, i);
443 if(!asset->sample_rate)
444 asset->sample_rate = mpeg3_sample_rate(fd, 0);
445 asset->audio_length = mpeg3_audio_samples(fd, 0);
446 if( !asset->channels || !asset->sample_rate )
450 asset->video_data = mpeg3_has_video(fd);
451 if( !result && asset->video_data ) {
452 //TODO: this is not as easy as just looking at headers.
453 //most interlaced media is rendered as FRM, not TOP/BOT in coding ext hdrs.
454 //currently, just using the assetedit menu to set the required result as needed.
455 // if( asset->interlace_mode == ILACE_MODE_UNDETECTED )
456 // asset->interlace_mode = mpeg3_detect_interlace(fd, 0);
457 if( !asset->layers ) {
458 asset->layers = mpeg3_total_vstreams(fd);
460 asset->actual_width = mpeg3_video_width(fd, 0);
462 asset->width = asset->actual_width;
463 asset->actual_height = mpeg3_video_height(fd, 0);
465 asset->height = asset->actual_height;
466 if( !asset->video_length )
467 asset->video_length = mpeg3_video_frames(fd, 0);
468 if( !asset->vmpeg_cmodel )
469 asset->vmpeg_cmodel = bc_colormodel(mpeg3_colormodel(fd, 0));
470 if( !asset->frame_rate )
471 asset->frame_rate = mpeg3_frame_rate(fd, 0);
475 eprintf(_("Couldn't open %s: failed.\n"), asset->path);
479 if( !result && wr && asset->format == FILE_VMPEG ) {
480 // Heroine Virtual encoder
481 // this one is cinelerra-x.x.x/mpeg2enc
482 if(asset->vmpeg_cmodel == BC_YUV422P)
484 char bitrate_string[BCTEXTLEN];
485 char quant_string[BCTEXTLEN];
486 char iframe_string[BCTEXTLEN];
488 sprintf(bitrate_string, "%d", asset->vmpeg_bitrate);
489 sprintf(quant_string, "%d", asset->vmpeg_quantization);
490 sprintf(iframe_string, "%d", asset->vmpeg_iframe_distance);
492 // Construct command line
495 const char *exec_path = File::get_cinlib_path();
496 snprintf(mjpeg_command, sizeof(mjpeg_command),
497 "%s/%s", exec_path, HVPEG_EXE);
498 append_vcommand_line(mjpeg_command);
500 if(asset->aspect_ratio > 0)
502 append_vcommand_line("-a");
504 if(EQUIV(asset->aspect_ratio, 1.333))
505 append_vcommand_line("2");
507 if(EQUIV(asset->aspect_ratio, 1.777))
508 append_vcommand_line("3");
510 if(EQUIV(asset->aspect_ratio, 2.11))
511 append_vcommand_line("4");
513 if(EQUIV((double)asset->width / asset->height,
514 asset->aspect_ratio))
515 append_vcommand_line("1");
518 append_vcommand_line(asset->vmpeg_derivative == 1 ? "-1" : "");
519 append_vcommand_line(asset->vmpeg_cmodel == BC_YUV422P ? "-422" : "");
520 if(asset->vmpeg_fix_bitrate)
522 append_vcommand_line("-b");
523 append_vcommand_line(bitrate_string);
527 append_vcommand_line("-q");
528 append_vcommand_line(quant_string);
530 append_vcommand_line("-n");
531 append_vcommand_line(iframe_string);
532 append_vcommand_line(asset->vmpeg_progressive ? "-p" : "");
533 append_vcommand_line(asset->vmpeg_denoise ? "-d" : "");
534 append_vcommand_line(file->cpus <= 1 ? "-u" : "");
535 append_vcommand_line(asset->vmpeg_seq_codes ? "-g" : "");
536 append_vcommand_line(asset->path);
538 video_out = new FileMPEGVideo(this);
543 // mjpegtools encoder
544 // this one is cinelerra-x.x.x/thirdparty/mjpegtools/mpeg2enc
546 const char *exec_path = File::get_cinlib_path();
547 snprintf(mjpeg_command, sizeof(mjpeg_command),
548 "%s/%s -v 0 ", exec_path, MJPEG_EXE);
550 // Must disable interlacing if MPEG-1
551 switch (asset->vmpeg_preset)
553 case 0: asset->vmpeg_progressive = 1; break;
554 case 1: asset->vmpeg_progressive = 1; break;
555 case 2: asset->vmpeg_progressive = 1; break;
558 char string[BCTEXTLEN];
559 // The current usage of mpeg2enc requires bitrate of 0 when quantization is fixed and
560 // quantization of 1 when bitrate is fixed. Perfectly intuitive.
561 if(asset->vmpeg_fix_bitrate)
563 snprintf(string, sizeof(string),
564 " -b %d -q 1", asset->vmpeg_bitrate / 1000);
568 snprintf(string, sizeof(string),
569 " -b 0 -q %d", asset->vmpeg_quantization);
571 strncat(mjpeg_command, string, sizeof(mjpeg_command));
574 int aspect_ratio_code = -1;
575 if(asset->aspect_ratio > 0)
577 int ncodes = sizeof(aspect_ratio_codes) / sizeof(double);
578 for(int i = 1; i < ncodes; i++)
580 if(EQUIV(aspect_ratio_codes[i], asset->aspect_ratio))
582 aspect_ratio_code = i;
590 if(EQUIV((double)asset->width / asset->height, asset->aspect_ratio))
591 aspect_ratio_code = 1;
593 if(aspect_ratio_code < 0)
595 eprintf(_("Unsupported aspect ratio %f\n"), asset->aspect_ratio);
596 aspect_ratio_code = 2;
598 sprintf(string, " -a %d", aspect_ratio_code);
599 strncat(mjpeg_command, string, sizeof(mjpeg_command));
607 int frame_rate_code = -1;
608 int ncodes = sizeof(frame_rate_codes) / sizeof(double);
609 for(int i = 1; i < ncodes; ++i)
611 if(EQUIV(asset->frame_rate, frame_rate_codes[i]))
617 if(frame_rate_code < 0)
620 eprintf(_("Unsupported frame rate %f\n"), asset->frame_rate);
622 sprintf(string, " -F %d", frame_rate_code);
623 strncat(mjpeg_command, string, sizeof(mjpeg_command));
625 sprintf(string, " -H"); /* Maximize high-frequency resolution */
626 strncat(mjpeg_command, string, sizeof(mjpeg_command));
628 if(asset->vmpeg_preset == 3) /* no constrains for mpeg2 generic */
630 sprintf(string, " --no-constraints");
631 strncat(mjpeg_command, string, sizeof(mjpeg_command));
632 sprintf(string, " -V 500");
633 strncat(mjpeg_command, string, sizeof(mjpeg_command));
636 if(asset->vmpeg_preset == 13) /* set high profile for 1080 */
638 sprintf(string, " -l high");
639 strncat(mjpeg_command, string, sizeof(mjpeg_command));
642 if(asset->vmpeg_preset == 6) /* set -T for vcd */
644 sprintf(string, " -T 35");
645 strncat(mjpeg_command, string, sizeof(mjpeg_command));
648 if(asset->vmpeg_preset == 7) /* set -T for svcd */
650 sprintf(string, " -T 120");
651 strncat(mjpeg_command, string, sizeof(mjpeg_command));
654 sprintf(string, " -c"); /* set closed gop */
655 strncat(mjpeg_command, string, sizeof(mjpeg_command));
658 strncat(mjpeg_command,
659 asset->vmpeg_progressive ? " -I 0" : " -I 1",
660 sizeof(mjpeg_command));
664 sprintf(string, " -M %d", file->cpus);
665 strncat(mjpeg_command, string, sizeof(mjpeg_command));
668 if(!asset->vmpeg_progressive)
670 strncat(mjpeg_command,
671 asset->vmpeg_field_order ? " -z b" : " -z t",
672 sizeof(mjpeg_command));
676 snprintf(string, sizeof(string), " -f %d", asset->vmpeg_preset);
677 strncat(mjpeg_command, string, sizeof(mjpeg_command));
680 snprintf(string, sizeof(string),
681 " -g %d -G %d", asset->vmpeg_iframe_distance, asset->vmpeg_iframe_distance);
682 strncat(mjpeg_command, string, sizeof(mjpeg_command));
685 if(asset->vmpeg_seq_codes)
686 strncat(mjpeg_command, " -s", sizeof(mjpeg_command));
689 snprintf(string, sizeof(string),
690 " -R %d", CLAMP(asset->vmpeg_pframe_distance, 0, 2));
691 strncat(mjpeg_command, string, sizeof(mjpeg_command));
693 snprintf(string, sizeof(string), " -o '%s'", asset->path);
694 strncat(mjpeg_command, string, sizeof(mjpeg_command));
698 printf("FileMPEG::open_file: Running %s\n", mjpeg_command);
699 if(!(mjpeg_out = popen(mjpeg_command, "w")))
701 perror("FileMPEG::open_file");
702 eprintf(_("Error while opening \"%s\" for writing\n%m\n"), mjpeg_command);
706 video_out = new FileMPEGVideo(this);
710 else if( !result && wr && asset->format == FILE_AMPEG) {
711 //char encoder_string[BCTEXTLEN]; encoder_string[0] = 0;
712 //printf("FileMPEG::open_file 1 %d\n", asset->ampeg_derivative);
714 if(asset->ampeg_derivative == 2)
716 twofp = fopen(asset->path, "w" );
717 if( !twofp ) return 1;
718 twopts = twolame_init();
719 int channels = asset->channels >= 2 ? 2 : 1;
720 twolame_set_num_channels(twopts, channels);
721 twolame_set_in_samplerate(twopts, asset->sample_rate);
722 twolame_set_mode(twopts, channels >= 2 ?
723 TWOLAME_JOINT_STEREO : TWOLAME_MONO);
724 twolame_set_bitrate(twopts, asset->ampeg_bitrate);
725 twolame_init_params(twopts);
728 if(asset->ampeg_derivative == 3)
730 lame_global = lame_init();
731 // lame_set_brate(lame_global, asset->ampeg_bitrate / 1000);
732 lame_set_brate(lame_global, asset->ampeg_bitrate);
733 lame_set_quality(lame_global, 0);
734 lame_set_in_samplerate(lame_global,
736 lame_set_num_channels(lame_global,
738 if((result = lame_init_params(lame_global)) < 0)
740 eprintf(_("encode: lame_init_params returned %d\n"), result);
741 lame_close(lame_global);
745 if(!(lame_fd = fopen(asset->path, "w")))
747 perror("FileMPEG::open_file");
748 eprintf(_("Error while opening \"%s\" for writing\n%m\n"), asset->path);
749 lame_close(lame_global);
756 eprintf(_("ampeg_derivative=%d\n"), asset->ampeg_derivative);
761 // Transport stream for DVB capture
762 if( !result && !rd && !wr && asset->format == FILE_MPEG ) {
763 if( (recd_fd = open(asset->path, O_CREAT+O_TRUNC+O_WRONLY,
764 S_IRUSR+S_IWUSR + S_IRGRP+S_IWGRP)) < 0 ) {
765 perror("FileMPEG::open_file");
766 eprintf(_("Error while opening \"%s\" for writing\n%m\n"), asset->path);
780 int FileMPEG::set_skimming(int track, int skim, skim_fn fn, void *vp)
782 return !fn ? mpeg3_set_thumbnail_callback(fd, track, 0, 0, 0, 0) :
783 mpeg3_set_thumbnail_callback(fd, track, skim, 1, fn, vp);
786 int FileMPEG::skimming(void *vp, int track)
788 File *file = (File *)vp;
789 FileMPEG *mpeg = (FileMPEG *)file->file;
790 return mpeg->skim_result = mpeg->skim_callback(mpeg->skim_data, track);
793 int FileMPEG::skim_video(int track, void *vp, skim_fn fn)
795 skim_callback = fn; skim_data = vp;
796 mpeg3_set_thumbnail_callback(fd, track, 1, 1, skimming, (void*)file);
798 while( skim_result < 0 && !mpeg3_end_of_video(fd, track) )
799 mpeg3_drop_frames(fd, 1, track);
800 mpeg3_set_thumbnail_callback(fd, track, 0, 0, 0, 0);
806 #ifdef HAVE_COMMERCIAL
807 int FileMPEG::toc_nail(void *vp, int track)
809 File *file = (File *)vp;
810 FileMPEG *mpeg = (FileMPEG *)file->file;
811 int64_t framenum; uint8_t *tdat; int mw, mh;
812 if( mpeg->get_thumbnail(track, framenum, tdat, mw, mh) ) return 1;
813 int pid, width, height; double framerate;
814 if( mpeg->get_video_info(track, pid, framerate, width, height) ) return 1;
815 if( pid < 0 || framerate <= 0 ) return 1;
816 double position = framenum / framerate;
817 //printf("t%d/%03x f%jd, %dx%d %dx%d\n",track,pid,framenum,mw,mh,width,height);
818 MWindow::commercials->get_frame(file, pid, position, tdat, mw, mh, width, height);
823 int FileMPEG::create_toc(char *toc_path)
825 // delete any existing toc files
826 char toc_file[BCTEXTLEN];
827 strcpy(toc_file, toc_path);
828 if( strcmp(toc_file, asset->path) )
830 char *bp = strrchr(toc_file, '/');
831 if( !bp ) bp = toc_file;
832 char *sfx = strrchr(bp,'.');
838 int64_t total_bytes = 0, last_bytes = -1;
839 fd = mpeg3_start_toc(asset->path, toc_file,
840 file->current_program, &total_bytes);
842 eprintf(_("cant start toc/idx for file: %s\n"), asset->path);
846 // File needs a table of contents.
847 struct timeval new_time, prev_time, start_time, current_time;
848 gettimeofday(&prev_time, 0); gettimeofday(&start_time, 0);
849 #ifdef HAVE_COMMERCIAL
850 if( file->preferences->scan_commercials ) {
851 set_skimming(-1, 1, toc_nail, file);
852 if( MWindow::commercials->resetDb() != 0 )
853 eprintf(_("cant access commercials database"));
856 // This gets around the fact that MWindowGUI may be locked.
857 char progress_title[BCTEXTLEN];
858 sprintf(progress_title, _("Creating %s\n"), toc_file);
859 BC_ProgressBox progress(-1, -1, progress_title, total_bytes);
864 int64_t bytes_processed = 0;
865 if( mpeg3_do_toc(fd, &bytes_processed) ) break;
867 if( bytes_processed >= total_bytes ) break;
868 if( bytes_processed == last_bytes ) {
869 eprintf(_("toc scan stopped before eof"));
872 last_bytes = bytes_processed;
874 gettimeofday(&new_time, 0);
875 if( new_time.tv_sec - prev_time.tv_sec >= 1 ) {
876 gettimeofday(¤t_time, 0);
877 int64_t elapsed_seconds = current_time.tv_sec - start_time.tv_sec;
878 int64_t total_seconds = !bytes_processed ? 0 :
879 elapsed_seconds * total_bytes / bytes_processed;
880 int64_t eta = total_seconds - elapsed_seconds;
881 progress.update(bytes_processed, 1);
882 char string[BCTEXTLEN];
883 sprintf(string, "%sETA: %jdm%jds",
884 progress_title, eta / 60, eta % 60);
885 progress.update_title(string, 1);
886 // fprintf(stderr, "ETA: %dm%ds \r",
887 // bytes_processed * 100 / total_bytes,
888 // eta / 60, eta % 60);
890 prev_time = new_time;
893 if( progress.is_cancelled() ) {
899 #ifdef HAVE_COMMERCIAL
900 if( file->preferences->scan_commercials ) {
901 if( !result ) MWindow::commercials->write_ads(asset->path);
902 MWindow::commercials->closeDb();
909 progress.stop_progress();
912 remove_file(toc_file);
916 // Reopen file from toc path instead of asset path.
918 fd = mpeg3_open(toc_file, &error);
920 eprintf(_("mpeg3_open failed: %s"), toc_file);
926 int FileMPEG::get_index(IndexFile *index_file, MainProgressBar *progress_bar)
929 IndexState *index_state = index_file->get_state();
930 index_state->reset_index();
931 index_state->reset_markers();
933 // Convert the index tables from tracks to channels.
934 int ntracks = mpeg3_index_tracks(fd);
935 if( !ntracks ) return 1;
937 int index_zoom = mpeg3_index_zoom(fd);
939 for( int i = 0; i < ntracks; ++i ) {
940 int nch = mpeg3_index_channels(fd, i);
941 for( int j = 0; j < nch; ++j ) {
942 float *bfr = (float *)mpeg3_index_data(fd, i, j);
943 int64_t size = 2*mpeg3_index_size(fd, i);
944 index_state->add_index_entry(bfr, offset, size);
950 int64_t file_bytes = fs.get_size(asset->path);
951 char *index_path = index_file->index_filename;
952 return index_state->write_index(index_path, asset, index_zoom, file_bytes);
960 void FileMPEG::append_vcommand_line(const char *string)
964 char *argv = cstrdup(string);
965 vcommand_line.append(argv);
969 int FileMPEG::close_file()
972 next_frame_lock->unlock();
981 // End of sequence signal
982 if(file->asset->vmpeg_cmodel == BC_YUV422P)
984 mpeg2enc_set_input_buffers(1, 0, 0, 0);
990 vcommand_line.remove_all_objects();
993 unsigned char opkt[1152*2];
994 int ret = twolame_encode_flush(twopts, opkt, sizeof(opkt));
996 fwrite(opkt, 1, ret, twofp);
998 fprintf(stderr, _("twolame error encoding audio: %d\n"), ret);
999 fclose(twofp); twofp = 0;
1001 if( twopts ) { twolame_close(&twopts); twopts = 0; }
1004 lame_close(lame_global);
1006 if(temp_frame) delete temp_frame;
1007 if(twolame_temp) delete [] twolame_temp;
1009 if(lame_temp[0]) delete [] lame_temp[0];
1010 if(lame_temp[1]) delete [] lame_temp[1];
1011 if(lame_output) delete [] lame_output;
1012 if(lame_fd) fclose(lame_fd);
1014 if(mjpeg_out) pclose(mjpeg_out);
1016 if( recd_fd >= 0 ) {
1023 FileBase::close_file();
1027 int FileMPEG::get_best_colormodel(Asset *asset, int driver)
1029 //printf("FileMPEG::get_best_colormodel 1\n");
1033 // return BC_RGB888;
1034 // the direct X11 color model requires scaling in the codec
1036 case PLAYBACK_X11_XV:
1037 case PLAYBACK_ASYNCHRONOUS:
1038 return zmpeg3_cmdl(asset->vmpeg_cmodel) > 0 ?
1039 asset->vmpeg_cmodel : BC_RGB888;
1040 case PLAYBACK_X11_GL:
1042 case PLAYBACK_DV1394:
1043 case PLAYBACK_FIREWIRE:
1046 return zmpeg3_cmdl(asset->vmpeg_cmodel) > 0 ?
1047 asset->vmpeg_cmodel : BC_RGB888;
1048 case VIDEO4LINUX2JPEG:
1049 return BC_COMPRESSED;
1051 case VIDEO4LINUX2MPEG:
1053 case CAPTURE_JPEG_WEBCAM:
1054 return BC_COMPRESSED;
1055 case CAPTURE_YUYV_WEBCAM:
1057 case CAPTURE_FIREWIRE:
1058 case CAPTURE_IEC61883:
1061 eprintf(_("unknown driver %d\n"),driver);
1065 int FileMPEG::colormodel_supported(int colormodel)
1070 int FileMPEG::can_copy_from(Asset *asset, int64_t position)
1075 int FileMPEG::set_audio_position(int64_t sample)
1080 int channel, stream;
1081 to_streamchannel(file->current_channel, stream, channel);
1083 //printf("FileMPEG::set_audio_position %d %d %d\n", sample, mpeg3_get_sample(fd, stream), last_sample);
1084 if(sample != mpeg3_get_sample(fd, stream) &&
1085 sample != last_sample)
1087 if(sample >= 0 && sample < asset->audio_length)
1089 //printf("FileMPEG::set_audio_position seeking stream %d\n", sample);
1090 return mpeg3_set_sample(fd, sample, stream);
1099 int FileMPEG::set_video_position(int64_t pos)
1101 if( !fd || pos < 0 || pos >= asset->video_length )
1103 //printf("FileMPEG::set_video_position 1 %jd\n", x);
1104 mpeg3_set_frame(fd, pos, file->current_layer);
1108 int64_t FileMPEG::get_memory_usage()
1110 int64_t result = file->rd && fd ? mpeg3_memory_usage(fd) : 0;
1111 //printf("FileMPEG::get_memory_usage %d %jd\n", __LINE__, result);
1115 int FileMPEG::set_program(int no)
1117 return fd ? mpeg3_set_program(fd, no) : -1;
1120 int FileMPEG::get_cell_time(int no, double &time)
1122 return fd ? mpeg3_get_cell_time(fd, no, &time) : -1;
1125 int FileMPEG::get_system_time(int64_t &tm)
1127 return fd ? mpeg3_dvb_get_system_time(fd, &tm) : -1;
1130 int FileMPEG::get_video_pid(int track)
1132 return fd ? mpeg3_video_pid(fd, track) : -1;
1135 int FileMPEG::get_video_info(int track, int &pid,
1136 double &framerate, int &width, int &height, char *title)
1138 if( !fd ) return -1;
1139 pid = mpeg3_video_pid(fd, track);
1140 framerate = mpeg3_frame_rate(fd, track);
1141 width = mpeg3_video_width(fd, track);
1142 height = mpeg3_video_height(fd, track);
1143 if( !title ) return 0;
1146 int elements = mpeg3_dvb_channel_count(fd);
1147 for( int n=0; n<elements; ++n ) {
1148 int major, minor, total_vstreams, vstream, vidx;
1149 if( mpeg3_dvb_get_channel(fd,n, &major, &minor) ||
1150 mpeg3_dvb_total_vstreams(fd,n,&total_vstreams) ) continue;
1151 for( vidx=0; vidx<total_vstreams; ++vidx ) {
1152 if( mpeg3_dvb_vstream_number(fd,n,vidx,&vstream) ) continue;
1153 if( vstream < 0 ) continue;
1154 if( vstream == track ) {
1155 sprintf(title, "%3d.%-3d", major, minor);
1163 int FileMPEG::select_video_stream(Asset *asset, int vstream)
1165 if( !fd ) return -1;
1166 asset->width = mpeg3_video_width(fd, vstream);
1167 asset->height = mpeg3_video_height(fd, vstream);
1168 asset->video_length = mpeg3_video_frames(fd, vstream);
1169 asset->frame_rate = mpeg3_frame_rate(fd, vstream);
1173 int FileMPEG::select_audio_stream(Asset *asset, int astream)
1175 if( !fd ) return -1;
1176 asset->sample_rate = mpeg3_sample_rate(fd, astream);
1177 asset->audio_length = mpeg3_audio_samples(fd, astream);
1181 int FileMPEG::get_thumbnail(int stream,
1182 int64_t &position, unsigned char *&thumbnail, int &ww, int &hh)
1185 mpeg3_get_thumbnail(fd, stream, &position, &thumbnail, &ww, &hh);
1188 int FileMPEG::write_samples(double **buffer, int64_t len)
1192 //printf("FileMPEG::write_samples 1\n");
1193 if(asset->ampeg_derivative == 2) {
1195 int channels = MIN(asset->channels, 2);
1196 int64_t audio_size = len * channels * 2;
1197 if(twolame_allocation < audio_size) {
1198 if(twolame_temp) delete [] twolame_temp;
1199 twolame_temp = new unsigned char[audio_size];
1200 twolame_allocation = audio_size;
1201 if(twolame_out) delete [] twolame_out;
1202 twolame_out = new unsigned char[audio_size + 1152];
1205 for(int i = 0; i < channels; i++) {
1206 int16_t *output = ((int16_t*)twolame_temp) + i;
1207 double *input = buffer[i];
1208 for(int j = 0; j < len; j++) {
1209 int sample = (int)(*input * 0x7fff);
1210 *output = (int16_t)(CLIP(sample, -0x8000, 0x7fff));
1215 int ret = twolame_encode_buffer_interleaved(twopts,
1216 (int16_t*)twolame_temp, len,
1217 twolame_out, twolame_allocation+1152);
1219 fwrite(twolame_out, 1, ret, twofp);
1221 fprintf(stderr, _("twolame error encoding audio: %d\n"), ret);
1224 if(asset->ampeg_derivative == 3)
1226 int channels = MIN(asset->channels, 2);
1227 int64_t audio_size = len * channels;
1228 if(!lame_global) return 1;
1229 if(!lame_fd) return 1;
1230 if(lame_allocation < audio_size)
1232 if(lame_temp[0]) delete [] lame_temp[0];
1233 if(lame_temp[1]) delete [] lame_temp[1];
1234 lame_temp[0] = new float[audio_size];
1235 lame_temp[1] = new float[audio_size];
1236 lame_allocation = audio_size;
1239 if(lame_output_allocation < audio_size * 4)
1241 if(lame_output) delete [] lame_output;
1242 lame_output_allocation = audio_size * 4;
1243 lame_output = new char[lame_output_allocation];
1246 for(int i = 0; i < channels; i++)
1248 float *output = lame_temp[i];
1249 double *input = buffer[i];
1250 for(int j = 0; j < len; j++)
1252 *output++ = *input++ * (float)32768;
1256 result = lame_encode_buffer_float(lame_global,
1258 (channels > 1) ? lame_temp[1] : lame_temp[0],
1260 (unsigned char*)lame_output,
1261 lame_output_allocation);
1264 char *real_output = lame_output;
1268 for(int i = 0; i < bytes; i++)
1271 real_output = &lame_output[i];
1277 if(bytes > 0 && lame_started)
1279 result = !fwrite(real_output, 1, bytes, lame_fd);
1281 perror("FileMPEG::write_samples");
1282 eprintf(_("write failed: %m"));
1295 int FileMPEG::write_frames(VFrame ***frames, int len)
1301 int temp_w = (int)((asset->width + 15) / 16) * 16;
1304 int output_cmodel = asset->vmpeg_cmodel;
1305 // verify colormodel supported in MPEG output
1306 switch( output_cmodel ) {
1308 if( file->preferences->dvd_yuv420p_interlace &&
1309 ( asset->interlace_mode == ILACE_MODE_TOP_FIRST ||
1310 asset->interlace_mode == ILACE_MODE_BOTTOM_FIRST ) )
1311 output_cmodel = BC_YUV420PI;
1318 // Height depends on progressiveness
1319 if(asset->vmpeg_progressive || asset->vmpeg_derivative == 1)
1320 temp_h = (int)((asset->height + 15) / 16) * 16;
1322 temp_h = (int)((asset->height + 31) / 32) * 32;
1324 //printf("FileMPEG::write_frames 1\n");
1326 // Only 1 layer is supported in MPEG output
1327 for(int i = 0; i < 1; i++)
1329 for(int j = 0; j < len && !result; j++)
1331 VFrame *frame = frames[i][j];
1335 if(asset->vmpeg_cmodel == BC_YUV422P)
1337 if(frame->get_w() == temp_w &&
1338 frame->get_h() == temp_h &&
1339 frame->get_color_model() == output_cmodel)
1341 mpeg2enc_set_input_buffers(0,
1342 (char*)frame->get_y(),
1343 (char*)frame->get_u(),
1344 (char*)frame->get_v());
1349 (temp_frame->get_w() != temp_w ||
1350 temp_frame->get_h() != temp_h ||
1351 temp_frame->get_color_model() || output_cmodel))
1360 temp_frame = new VFrame(temp_w, temp_h,
1364 BC_CModels::transfer(temp_frame->get_rows(),
1366 temp_frame->get_y(),
1367 temp_frame->get_u(),
1368 temp_frame->get_v(),
1378 temp_frame->get_w(),
1379 temp_frame->get_h(),
1380 frame->get_color_model(),
1381 temp_frame->get_color_model(),
1384 temp_frame->get_w());
1386 mpeg2enc_set_input_buffers(0,
1387 (char*)temp_frame->get_y(),
1388 (char*)temp_frame->get_u(),
1389 (char*)temp_frame->get_v());
1394 // MJPEG uses the same dimensions as the input
1395 //printf("FileMPEG::write_frames %d\n", __LINE__);sleep(1);
1396 if(frame->get_color_model() == output_cmodel)
1398 mjpeg_y = frame->get_y();
1399 mjpeg_u = frame->get_u();
1400 mjpeg_v = frame->get_v();
1404 //printf("FileMPEG::write_frames %d\n", __LINE__);sleep(1);
1407 temp_frame = new VFrame(asset->width, asset->height,
1411 // printf("FileMPEG::write_frames %d temp_frame=%p %p %p %p frame=%p %p %p %p color_model=%p %p\n",
1414 // temp_frame->get_w(),
1415 // temp_frame->get_h(),
1419 // temp_frame->get_color_model(),
1420 // frame->get_color_model()); sleep(1);
1421 temp_frame->transfer_from(frame);
1422 //printf("FileMPEG::write_frames %d\n", __LINE__);sleep(1);
1424 mjpeg_y = temp_frame->get_y();
1425 mjpeg_u = temp_frame->get_u();
1426 mjpeg_v = temp_frame->get_v();
1432 next_frame_lock->unlock();
1433 next_frame_done->lock("FileMPEG::write_frames");
1434 if(mjpeg_error) result = 1;
1450 int FileMPEG::zmpeg3_cmdl(int colormodel)
1452 switch( colormodel ) {
1453 case BC_BGR888: return zmpeg3_t::cmdl_BGR888;
1454 case BC_BGR8888: return zmpeg3_t::cmdl_BGRA8888;
1455 case BC_RGB565: return zmpeg3_t::cmdl_RGB565;
1456 case BC_RGB888: return zmpeg3_t::cmdl_RGB888;
1457 case BC_RGBA8888: return zmpeg3_t::cmdl_RGBA8888;
1458 case BC_RGBA16161616: return zmpeg3_t::cmdl_RGBA16161616;
1459 case BC_YUV420P: return zmpeg3_t::cmdl_YUV420P;
1460 case BC_YUV422P: return zmpeg3_t::cmdl_YUV422P;
1461 case BC_YUV422: return zmpeg3_t::cmdl_YUYV;
1462 case BC_YUV888: return zmpeg3_t::cmdl_YUV888;
1463 case BC_YUVA8888: return zmpeg3_t::cmdl_YUVA8888;
1468 int FileMPEG::bc_colormodel(int cmdl)
1471 case zmpeg3_t::cmdl_BGR888: return BC_BGR888;
1472 case zmpeg3_t::cmdl_BGRA8888: return BC_BGR8888;
1473 case zmpeg3_t::cmdl_RGB565: return BC_RGB565;
1474 case zmpeg3_t::cmdl_RGB888: return BC_RGB888;
1475 case zmpeg3_t::cmdl_RGBA8888: return BC_RGBA8888;
1476 case zmpeg3_t::cmdl_RGBA16161616: return BC_RGBA16161616;
1477 case zmpeg3_t::cmdl_YUV420P: return BC_YUV420P;
1478 case zmpeg3_t::cmdl_YUV422P: return BC_YUV422P;
1479 case zmpeg3_t::cmdl_YUYV: return BC_YUV422;
1480 case zmpeg3_t::cmdl_YUV888: return BC_YUV888;
1481 case zmpeg3_t::cmdl_YUVA8888: return BC_YUVA8888;
1486 const char *FileMPEG::zmpeg3_cmdl_name(int cmdl)
1488 # define CMDL(nm) #nm
1489 static const char *cmdl_name[] = {
1515 return cmdl>=0 && cmdl<lengthof(cmdl_name) ? cmdl_name[cmdl] : cmdl_name[6];
1519 int FileMPEG::read_frame(VFrame *frame)
1523 int width = mpeg3_video_width(fd,file->current_layer);
1524 int height = mpeg3_video_height(fd,file->current_layer);
1525 int stream_cmdl = mpeg3_colormodel(fd,file->current_layer);
1526 int stream_color_model = bc_colormodel(stream_cmdl);
1527 int frame_color_model = frame->get_color_model();
1528 int frame_cmdl = asset->interlace_mode == ILACE_MODE_NOTINTERLACED ?
1529 zmpeg3_cmdl(frame_color_model) : -1;
1530 mpeg3_show_subtitle(fd, file->current_layer, file->playback_subtitle);
1532 switch( frame_color_model ) { // check for direct copy
1534 if( frame_cmdl < 0 ) break;
1536 if( stream_color_model == frame_color_model &&
1537 width == frame->get_w() && height == frame->get_h() ) {
1538 mpeg3_read_yuvframe(fd,
1539 (char*)frame->get_y(),
1540 (char*)frame->get_u(),
1541 (char*)frame->get_v(),
1542 0, 0, width, height,
1543 file->current_layer);
1548 if( frame_cmdl >= 0 ) { // supported by read_frame
1549 // cant rely on frame->get_rows(), format may not support it
1551 switch( frame_color_model ) {
1552 case BC_YUV420P: uvs = 2; break;
1553 case BC_YUV422P: uvs = 1; break;
1555 //int w = frame->get_w();
1556 int h = frame->get_h();
1557 int bpl = frame->get_bytes_per_line();
1558 int uvw = !uvs ? 0 : bpl / 2;
1559 int uvh = !uvs ? 0 : h / uvs;
1560 uint8_t *rows[h + 2*uvh], *rp;
1562 if( (rp=frame->get_y()) ) {
1563 for( int i=0; i<h; ++i, rp+=bpl ) rows[n++] = rp;
1564 rp = frame->get_u();
1565 for( int i=0; i<uvh; ++i, rp+=uvw ) rows[n++] = rp;
1566 rp = frame->get_v();
1567 for( int i=0; i<uvh; ++i, rp+=uvw ) rows[n++] = rp;
1570 rp = frame->get_data(); uvh *= 2;
1571 for( int i=0; i<h; ++i, rp+=bpl ) rows[n++] = rp;
1572 for( int i=0; i<uvh; ++i, rp+=uvw ) rows[n++] = rp;
1575 mpeg3_read_frame(fd,
1576 rows, /* start of each output row */
1577 0, 0, width, height, /* input box */
1578 frame->get_w(), /* Dimensions of output_rows */
1581 file->current_layer);
1586 mpeg3_read_yuvframe_ptr(fd, &y, &u, &v, file->current_layer);
1588 if( stream_color_model == BC_YUV420P &&
1589 file->preferences->dvd_yuv420p_interlace && (
1590 asset->interlace_mode == ILACE_MODE_TOP_FIRST ||
1591 asset->interlace_mode == ILACE_MODE_BOTTOM_FIRST ) )
1592 stream_color_model = BC_YUV420PI;
1593 BC_CModels::transfer(frame->get_rows(), 0,
1594 frame->get_y(), frame->get_u(), frame->get_v(),
1595 (unsigned char*)y, (unsigned char*)u, (unsigned char*)v,
1596 0,0, width,height, 0,0, frame->get_w(),frame->get_h(),
1597 stream_color_model, frame_color_model, 0, width, frame->get_w());
1604 void FileMPEG::to_streamchannel(int channel, int &stream_out, int &channel_out)
1606 int total_astreams = mpeg3_total_astreams(fd);
1607 for(stream_out = 0; stream_out < total_astreams; ++stream_out )
1609 int stream_channels = mpeg3_audio_channels(fd, stream_out);
1610 if( channel < stream_channels ) break;
1611 channel -= stream_channels;
1613 channel_out = channel;
1616 int FileMPEG::read_samples(double *buffer, int64_t len)
1619 if(len < 0) return 0;
1621 // Translate pure channel to a stream and a channel in the mpeg stream
1622 int stream, channel;
1623 to_streamchannel(file->current_channel, stream, channel);
1625 //printf("FileMPEG::read_samples 1 current_sample=%jd len=%jd channel=%d\n", file->current_sample, len, channel);
1627 mpeg3_set_sample(fd,
1628 file->current_sample,
1630 mpeg3_read_audio_d(fd,
1631 buffer, /* Pointer to pre-allocated buffer of doubles */
1632 channel, /* Channel to decode */
1633 len, /* Number of samples to decode */
1634 stream); /* Stream containing the channel */
1636 // last_sample = file->current_sample;
1645 FileMPEGVideo::FileMPEGVideo(FileMPEG *file)
1651 if(file->asset->vmpeg_cmodel == BC_YUV422P)
1653 mpeg2enc_init_buffers();
1654 mpeg2enc_set_w(file->asset->width);
1655 mpeg2enc_set_h(file->asset->height);
1656 mpeg2enc_set_rate(file->asset->frame_rate);
1660 FileMPEGVideo::~FileMPEGVideo()
1665 void FileMPEGVideo::run()
1667 if(file->asset->vmpeg_cmodel == BC_YUV422P)
1669 printf("FileMPEGVideo::run ");
1670 for(int i = 0; i < file->vcommand_line.total; i++)
1671 printf("%s ", file->vcommand_line.values[i]);
1673 mpeg2enc(file->vcommand_line.total, file->vcommand_line.values);
1679 //printf("FileMPEGVideo::run %d\n", __LINE__);
1680 file->next_frame_lock->lock("FileMPEGVideo::run");
1681 //printf("FileMPEGVideo::run %d\n", __LINE__);
1684 file->next_frame_done->unlock();
1690 //printf("FileMPEGVideo::run %d\n", __LINE__);
1691 // YUV4 sequence header
1692 if(!file->wrote_header)
1694 file->wrote_header = 1;
1696 char interlace_string[BCTEXTLEN];
1697 if(!file->asset->vmpeg_progressive)
1699 sprintf(interlace_string, file->asset->vmpeg_field_order ? "b" : "t");
1703 sprintf(interlace_string, "p");
1705 double aspect_ratio = file->asset->aspect_ratio >= 0 ?
1706 file->asset->aspect_ratio : 1.0;
1707 //printf("FileMPEGVideo::run %d\n", __LINE__);
1708 fprintf(file->mjpeg_out, "YUV4MPEG2 W%d H%d F%d:%d I%s A%d:%d C%s\n",
1709 file->asset->width, file->asset->height,
1710 (int)(file->asset->frame_rate * 1001),
1711 1001, interlace_string,
1712 (int)(aspect_ratio * 1000), 1000,
1714 //printf("FileMPEGVideo::run %d\n", __LINE__);
1717 // YUV4 frame header
1718 //printf("FileMPEGVideo::run %d\n", __LINE__);
1719 fprintf(file->mjpeg_out, "FRAME\n");
1722 //printf("FileMPEGVideo::run %d\n", __LINE__);
1723 if(!fwrite(file->mjpeg_y, file->asset->width * file->asset->height, 1, file->mjpeg_out))
1724 file->mjpeg_error = 1;
1725 //printf("FileMPEGVideo::run %d\n", __LINE__);
1726 if(!fwrite(file->mjpeg_u, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1727 file->mjpeg_error = 1;
1728 //printf("FileMPEGVideo::run %d\n", __LINE__);
1729 if(!fwrite(file->mjpeg_v, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1730 file->mjpeg_error = 1;
1731 //printf("FileMPEGVideo::run %d\n", __LINE__);
1732 fflush(file->mjpeg_out);
1734 //printf("FileMPEGVideo::run %d\n", __LINE__);
1735 file->next_frame_done->unlock();
1736 //printf("FileMPEGVideo::run %d\n", __LINE__);
1738 pclose(file->mjpeg_out);
1739 file->mjpeg_out = 0;
1745 MPEGConfigAudio::MPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1746 : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
1747 parent_window->get_abs_cursor_x(1), parent_window->get_abs_cursor_y(1),
1748 xS(310), yS(120), -1, -1, 0, 0, 1)
1750 this->parent_window = parent_window;
1751 this->asset = asset;
1752 // *** CONTEXT_HELP ***
1753 context_help_set_keyword("Single File Rendering");
1756 MPEGConfigAudio::~MPEGConfigAudio()
1760 void MPEGConfigAudio::create_objects()
1762 int x = xS(10), y = yS(10);
1766 lock_window("MPEGConfigAudio::create_objects");
1767 if(asset->format == FILE_MPEG)
1769 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1775 add_tool(new BC_Title(x, y, _("Layer:")));
1776 add_tool(layer = new MPEGLayer(x1, y, this));
1777 layer->create_objects();
1780 add_tool(new BC_Title(x, y, _("Kbits per second:")));
1781 add_tool(bitrate = new MPEGABitrate(x1, y, this));
1782 bitrate->create_objects();
1785 add_subwindow(new BC_OKButton(this));
1790 int MPEGConfigAudio::close_event()
1797 MPEGLayer::MPEGLayer(int x, int y, MPEGConfigAudio *gui)
1798 : BC_PopupMenu(x, y, xS(100), layer_to_string(gui->asset->ampeg_derivative))
1803 void MPEGLayer::create_objects()
1805 add_item(new BC_MenuItem(layer_to_string(2)));
1806 add_item(new BC_MenuItem(layer_to_string(3)));
1809 int MPEGLayer::handle_event()
1811 gui->asset->ampeg_derivative = string_to_layer(get_text());
1812 gui->bitrate->set_layer(gui->asset->ampeg_derivative);
1816 int MPEGLayer::string_to_layer(char *string)
1818 if(!strcasecmp(layer_to_string(2), string)) return 2;
1819 if(!strcasecmp(layer_to_string(3), string)) return 3;
1823 char* MPEGLayer::layer_to_string(int layer)
1826 case 2: return _("II");
1827 case 3: return _("III");
1833 MPEGABitrate::MPEGABitrate(int x, int y, MPEGConfigAudio *gui)
1834 : BC_PopupMenu(x, y, xS(100),
1835 bitrate_to_string(gui->string, gui->asset->ampeg_bitrate))
1840 void MPEGABitrate::create_objects()
1842 set_layer(gui->asset->ampeg_derivative);
1845 void MPEGABitrate::set_layer(int layer)
1847 while(total_items()) del_item(0);
1850 add_item(new BC_MenuItem("160"));
1851 add_item(new BC_MenuItem("192"));
1852 add_item(new BC_MenuItem("224"));
1853 add_item(new BC_MenuItem("256"));
1854 add_item(new BC_MenuItem("320"));
1855 add_item(new BC_MenuItem("384"));
1858 add_item(new BC_MenuItem("8"));
1859 add_item(new BC_MenuItem("16"));
1860 add_item(new BC_MenuItem("24"));
1861 add_item(new BC_MenuItem("32"));
1862 add_item(new BC_MenuItem("40"));
1863 add_item(new BC_MenuItem("48"));
1864 add_item(new BC_MenuItem("56"));
1865 add_item(new BC_MenuItem("64"));
1866 add_item(new BC_MenuItem("80"));
1867 add_item(new BC_MenuItem("96"));
1868 add_item(new BC_MenuItem("112"));
1869 add_item(new BC_MenuItem("128"));
1870 add_item(new BC_MenuItem("144"));
1871 add_item(new BC_MenuItem("160"));
1872 add_item(new BC_MenuItem("192"));
1873 add_item(new BC_MenuItem("224"));
1874 add_item(new BC_MenuItem("256"));
1875 add_item(new BC_MenuItem("320"));
1879 int MPEGABitrate::handle_event()
1881 gui->asset->ampeg_bitrate = string_to_bitrate(get_text());
1885 int MPEGABitrate::string_to_bitrate(char *string)
1887 return atol(string);
1891 char* MPEGABitrate::bitrate_to_string(char *string, int bitrate)
1893 sprintf(string, "%d", bitrate);
1899 MPEGConfigVideo::MPEGConfigVideo(BC_WindowBase *parent_window,
1901 : BC_Window(_(PROGRAM_NAME ": Video Compression"),
1902 parent_window->get_abs_cursor_x(1), parent_window->get_abs_cursor_y(1),
1903 xS(500), yS(400), -1, -1, 0, 0, 1)
1905 this->parent_window = parent_window;
1906 this->asset = asset;
1908 // *** CONTEXT_HELP ***
1909 context_help_set_keyword("Single File Rendering");
1912 MPEGConfigVideo::~MPEGConfigVideo()
1916 void MPEGConfigVideo::create_objects()
1918 int x = xS(10), y = yS(10);
1919 int x1 = x + xS(150);
1920 //int x2 = x + xS(300);
1922 lock_window("MPEGConfigVideo::create_objects");
1923 if(asset->format == FILE_MPEG)
1925 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1930 add_subwindow(new BC_Title(x, y, _("Color model:")));
1931 add_subwindow(cmodel = new MPEGColorModel(x1, y, this));
1932 cmodel->create_objects();
1934 add_subwindow(derivative = new MPEGDerivative(x1, y, this));
1935 derivative->create_objects();
1937 update_cmodel_objs();
1939 add_subwindow(new BC_OKButton(this));
1944 int MPEGConfigVideo::close_event()
1951 void MPEGConfigVideo::delete_cmodel_objs()
1955 delete fixed_bitrate;
1958 delete iframe_distance;
1959 delete pframe_distance;
1960 delete top_field_first;
1964 titles.remove_all_objects();
1968 void MPEGConfigVideo::reset_cmodel()
1975 iframe_distance = 0;
1976 pframe_distance = 0;
1977 top_field_first = 0;
1983 void MPEGConfigVideo::update_cmodel_objs()
1986 int ys5 = yS(5), ys30 = yS(30), ys40 = yS(40);
1988 int x = xs10, y = ys40;
1989 int x1 = x + xS(150);
1990 int x2 = x + xS(280);
1992 delete_cmodel_objs();
1994 if(asset->vmpeg_cmodel == BC_YUV420P)
1996 add_subwindow(title = new BC_Title(x, y + ys5, _("Format Preset:")));
1997 titles.append(title);
1998 add_subwindow(preset = new MPEGPreset(x1, y, this));
1999 preset->create_objects();
2003 add_subwindow(title = new BC_Title(x, y + ys5, _("Derivative:")));
2004 titles.append(title);
2005 derivative->reposition_window(x1, y);
2008 add_subwindow(title = new BC_Title(x, y + ys5, _("Bitrate:")));
2009 titles.append(title);
2010 add_subwindow(bitrate = new MPEGBitrate(x1, y, this));
2011 add_subwindow(fixed_bitrate = new MPEGFixedBitrate(x2, y, this));
2014 add_subwindow(title = new BC_Title(x, y, _("Quantization:")));
2015 titles.append(title);
2016 quant = new MPEGQuant(x1, y, this);
2017 quant->create_objects();
2018 add_subwindow(fixed_quant = new MPEGFixedQuant(x2, y, this));
2021 add_subwindow(title = new BC_Title(x, y, _("I frame distance:")));
2022 titles.append(title);
2023 iframe_distance = new MPEGIFrameDistance(x1, y, this);
2024 iframe_distance->create_objects();
2027 if(asset->vmpeg_cmodel == BC_YUV420P)
2029 add_subwindow(title = new BC_Title(x, y, _("P frame distance:")));
2030 titles.append(title);
2031 pframe_distance = new MPEGPFrameDistance(x1, y, this);
2032 pframe_distance->create_objects();
2035 add_subwindow(top_field_first = new BC_CheckBox(x, y, &asset->vmpeg_field_order, _("Bottom field first")));
2039 add_subwindow(progressive = new BC_CheckBox(x, y, &asset->vmpeg_progressive, _("Progressive frames")));
2041 add_subwindow(denoise = new BC_CheckBox(x, y, &asset->vmpeg_denoise, _("Denoise")));
2043 add_subwindow(seq_codes = new BC_CheckBox(x, y, &asset->vmpeg_seq_codes, _("Sequence start codes in every GOP")));
2048 MPEGDerivative::MPEGDerivative(int x, int y, MPEGConfigVideo *gui)
2049 : BC_PopupMenu(x, y, xS(150), derivative_to_string(gui->asset->vmpeg_derivative))
2054 void MPEGDerivative::create_objects()
2056 add_item(new BC_MenuItem(derivative_to_string(1)));
2057 add_item(new BC_MenuItem(derivative_to_string(2)));
2060 int MPEGDerivative::handle_event()
2062 gui->asset->vmpeg_derivative = string_to_derivative(get_text());
2063 if( gui->asset->vmpeg_derivative == 1 ) {
2064 gui->asset->vmpeg_cmodel = BC_YUV420P;
2065 char *text = MPEGColorModel::cmodel_to_string(gui->asset->vmpeg_cmodel);
2066 gui->cmodel->set_text(text);
2068 gui->cmodel->create_objects();
2069 gui->update_cmodel_objs();
2070 gui->show_window(1);
2074 int MPEGDerivative::string_to_derivative(char *string)
2076 if( !strcasecmp(derivative_to_string(1), string) ) return 1;
2077 if( !strcasecmp(derivative_to_string(2), string) ) return 2;
2081 char* MPEGDerivative::derivative_to_string(int derivative)
2083 switch(derivative) {
2084 case 1: return _("MPEG-1");
2085 case 2: return _("MPEG-2");
2091 MPEGPreset::MPEGPreset(int x, int y, MPEGConfigVideo *gui)
2092 : BC_PopupMenu(x, y, xS(200), value_to_string(gui->asset->vmpeg_preset))
2097 void MPEGPreset::create_objects()
2099 for(int i = 0; i < 14; i++) {
2100 add_item(new BC_MenuItem(value_to_string(i)));
2104 int MPEGPreset::handle_event()
2106 gui->asset->vmpeg_preset = string_to_value(get_text());
2110 int MPEGPreset::string_to_value(char *string)
2112 for(int i = 0; i < 14; i++) {
2113 if(!strcasecmp(value_to_string(i), string))
2119 char* MPEGPreset::value_to_string(int derivative)
2121 switch( derivative ) {
2122 case 0: return _("Generic MPEG-1"); break;
2123 case 1: return _("standard VCD"); break;
2124 case 2: return _("user VCD"); break;
2125 case 3: return _("Generic MPEG-2"); break;
2126 case 4: return _("standard SVCD"); break;
2127 case 5: return _("user SVCD"); break;
2128 case 6: return _("VCD Still sequence"); break;
2129 case 7: return _("SVCD Still sequence"); break;
2130 case 8: return _("DVD NAV"); break;
2131 case 9: return _("DVD"); break;
2132 case 10: return _("ATSC 480i"); break;
2133 case 11: return _("ATSC 480p"); break;
2134 case 12: return _("ATSC 720p"); break;
2135 case 13: return _("ATSC 1080i"); break;
2137 return _("Generic MPEG-1");
2141 MPEGBitrate::MPEGBitrate(int x, int y, MPEGConfigVideo *gui)
2142 : BC_TextBox(x, y, xS(100), 1, gui->asset->vmpeg_bitrate)
2148 int MPEGBitrate::handle_event()
2150 gui->asset->vmpeg_bitrate = atol(get_text());
2155 MPEGQuant::MPEGQuant(int x, int y, MPEGConfigVideo *gui)
2156 : BC_TumbleTextBox(gui,
2157 (int64_t)gui->asset->vmpeg_quantization,
2158 (int64_t)1, (int64_t)100,
2164 int MPEGQuant::handle_event()
2166 gui->asset->vmpeg_quantization = atol(get_text());
2170 MPEGFixedBitrate::MPEGFixedBitrate(int x, int y, MPEGConfigVideo *gui)
2171 : BC_Radial(x, y, gui->asset->vmpeg_fix_bitrate, _("Fixed bitrate"))
2176 int MPEGFixedBitrate::handle_event()
2179 gui->asset->vmpeg_fix_bitrate = 1;
2180 gui->fixed_quant->update(0);
2184 MPEGFixedQuant::MPEGFixedQuant(int x, int y, MPEGConfigVideo *gui)
2185 : BC_Radial(x, y, !gui->asset->vmpeg_fix_bitrate, _("Fixed quantization"))
2190 int MPEGFixedQuant::handle_event()
2193 gui->asset->vmpeg_fix_bitrate = 0;
2194 gui->fixed_bitrate->update(0);
2200 MPEGIFrameDistance::MPEGIFrameDistance(int x, int y, MPEGConfigVideo *gui)
2201 : BC_TumbleTextBox(gui,
2202 (int64_t)gui->asset->vmpeg_iframe_distance,
2203 (int64_t)1, (int64_t)100,
2209 int MPEGIFrameDistance::handle_event()
2211 gui->asset->vmpeg_iframe_distance = atoi(get_text());
2216 MPEGPFrameDistance::MPEGPFrameDistance(int x, int y, MPEGConfigVideo *gui)
2217 : BC_TumbleTextBox(gui,
2218 (int64_t)gui->asset->vmpeg_pframe_distance,
2219 (int64_t)0, (int64_t)2,
2225 int MPEGPFrameDistance::handle_event()
2227 gui->asset->vmpeg_pframe_distance = atoi(get_text());
2232 MPEGColorModel::MPEGColorModel(int x, int y, MPEGConfigVideo *gui)
2233 : BC_PopupMenu(x, y, xS(150), cmodel_to_string(gui->asset->vmpeg_cmodel))
2238 void MPEGColorModel::create_objects()
2240 while( total_items() > 0 ) del_item(0);
2241 add_item(new BC_MenuItem(cmodel_to_string(BC_YUV420P)));
2242 if( gui->asset->vmpeg_derivative == 2 )
2243 add_item(new BC_MenuItem(cmodel_to_string(BC_YUV422P)));
2246 int MPEGColorModel::handle_event()
2248 gui->asset->vmpeg_cmodel = string_to_cmodel(get_text());
2249 gui->update_cmodel_objs();
2250 gui->show_window(1);
2254 int MPEGColorModel::string_to_cmodel(char *string)
2256 if(!strcasecmp(cmodel_to_string(BC_YUV420P), string))
2258 if(!strcasecmp(cmodel_to_string(BC_YUV422P), string))
2263 char* MPEGColorModel::cmodel_to_string(int cmodel)
2267 case BC_YUV420P: return _("YUV 4:2:0");
2268 case BC_YUV422P: return _("YUV 4:2:2");
2269 default: return _("YUV 4:2:0");