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"
37 #include "indexfile.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.plugin"
54 #define MJPEG_EXE "/mpeg2enc.plugin"
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,
109 BC_WindowBase* &format_window,
113 if(audio_options && asset->format == FILE_AMPEG)
115 MPEGConfigAudio *window = new MPEGConfigAudio(parent_window, asset);
116 format_window = window;
117 window->create_objects();
118 window->run_window();
122 if(video_options && asset->format == FILE_VMPEG)
124 MPEGConfigVideo *window = new MPEGConfigVideo(parent_window, asset);
125 format_window = window;
126 window->create_objects();
127 window->run_window();
132 int FileMPEG::check_sig(Asset *asset)
134 return mpeg3_check_sig(asset->path);
137 void FileMPEG::get_info(char *title_path, char *path, char *text)
143 int zio_access = ZIO_UNBUFFERED+ZIO_SINGLE_ACCESS;
144 if( !(fd=mpeg3_zopen(title_path, path, &result,zio_access)) ) result = 1;
145 if( !result ) result = mpeg3_create_title(fd, 0);
149 if( mpeg3_has_toc(fd) ) {
150 cp += sprintf(cp, _("toc path:%s\n"), path);
151 cp += sprintf(cp, _("title path:\n"));
152 for( int i=0; i<100; ++i ) {
153 char *title_path = mpeg3_title_path(fd,i);
154 if( !title_path ) break;
155 cp += sprintf(cp, " %2d. %s\n", i+1, title_path);
159 cp += sprintf(cp, _("file path:%s\n"), path);
160 int64_t bytes = mpeg3_get_bytes(fd);
161 char string[BCTEXTLEN];
162 sprintf(string,"%ld",bytes);
163 Units::punctuate(string);
164 cp += sprintf(cp, _("size: %s"), string);
166 if( mpeg3_is_program_stream(fd) )
167 cp += sprintf(cp, _(" program stream\n"));
168 else if( mpeg3_is_transport_stream(fd) )
169 cp += sprintf(cp, _(" transport stream\n"));
170 else if( mpeg3_is_video_stream(fd) )
171 cp += sprintf(cp, _(" video stream\n"));
172 else if( mpeg3_is_audio_stream(fd) )
173 cp += sprintf(cp, _(" audio stream\n"));
175 int64_t sdate = mpeg3_get_source_date(fd);
178 memset(&ostat,0,sizeof(struct stat64));
179 sdate = stat64(path, &ostat) < 0 ? 0 : ostat.st_mtime;
181 time_t tm = (time_t)sdate;
182 cp += sprintf(cp, _("date: %s\n"), ctime(&tm));
184 int vtrks = mpeg3_total_vstreams(fd);
185 cp += sprintf(cp, _("%d video tracks\n"), vtrks);
186 for( int vtrk=0; vtrk<vtrks; ++vtrk ) {
187 int cmdl = mpeg3_colormodel(fd, vtrk);
188 int color_model = bc_colormodel(cmdl);
189 char *cmodel = MPEGColorModel::cmodel_to_string(color_model);
190 int width = mpeg3_video_width(fd, vtrk);
191 int height = mpeg3_video_height(fd, vtrk);
192 cp += sprintf(cp, _(" v%d %s %dx%d"), vtrk, cmodel, width, height);
193 double frame_rate = mpeg3_frame_rate(fd, vtrk);
194 int64_t frames = mpeg3_video_frames(fd, vtrk);
195 cp += sprintf(cp, _(" (%5.2f), %ld frames"), frame_rate, frames);
196 if( frame_rate > 0 ) {
197 double secs = (double)frames / frame_rate;
198 cp += sprintf(cp, _(" (%0.3f secs)"),secs);
202 int atrks = mpeg3_total_astreams(fd);
203 cp += sprintf(cp, _("%d audio tracks\n"), atrks);
204 for( int atrk=0; atrk<atrks; ++atrk) {
205 const char *format = mpeg3_audio_format(fd, atrk);
206 cp += sprintf(cp, _(" a%d %s"), atrk, format);
207 int channels = mpeg3_audio_channels(fd, atrk);
208 int sample_rate = mpeg3_sample_rate(fd, atrk);
209 cp += sprintf(cp, _(" ch%d (%d)"), channels, sample_rate);
210 int64_t samples = mpeg3_audio_samples(fd, atrk);
211 cp += sprintf(cp, " %ld",samples);
212 int64_t nudge = mpeg3_get_audio_nudge(fd, atrk);
213 *cp++ = nudge >= 0 ? '+' : (nudge=-nudge, '-');
214 cp += sprintf(cp, _("%ld samples"),nudge);
215 if( sample_rate > 0 ) {
216 double secs = (double)(samples+nudge) / sample_rate;
217 cp += sprintf(cp, _(" (%0.3f secs)"),secs);
221 int stracks = mpeg3_subtitle_tracks(fd);
223 cp += sprintf(cp, _("%d subtitles\n"), stracks);
225 int vts_titles = mpeg3_get_total_vts_titles(fd);
227 cp += sprintf(cp, _("%d title sets, "), vts_titles);
228 int interleaves = mpeg3_get_total_interleaves(fd);
229 if( interleaves > 0 )
230 cp += sprintf(cp, _("%d interleaves\n"), interleaves);
231 int vts_title = mpeg3_set_vts_title(fd, -1);
232 int angle = mpeg3_set_angle(fd, -1);
233 int interleave = mpeg3_set_interleave(fd, -1);
234 int program = mpeg3_set_program(fd, -1);
235 cp += sprintf(cp, _("current program %d = title %d, angle %d, interleave %d\n\n"),
236 program, vts_title, angle, interleave);
238 ArrayList<double> cell_times;
239 int cell_no = 0; double cell_time;
240 while( !mpeg3_get_cell_time(fd, cell_no++, &cell_time) ) {
241 cell_times.append(cell_time);
243 if( cell_times.size() > 1 ) {
244 cp += sprintf(cp, _("cell times:"));
245 for( int i=0; i<cell_times.size(); ++i ) {
246 if( (i%4) == 0 ) *cp++ = '\n';
247 cp += sprintf(cp,_(" %3d. %8.3f"),i,cell_times.get(i));
249 cp += sprintf(cp, "\n");
252 int elements = mpeg3_dvb_channel_count(fd);
253 if( elements <= 0 ) return;
254 if( !mpeg3_dvb_get_system_time(fd, &sdate) ) {
256 cp += sprintf(cp, _("\nsystem time: %s"), ctime_r(&tm,string));
258 cp += sprintf(cp, _("elements %d\n"), elements);
260 for( int n=0; n<elements; ++n ) {
261 char name[16], enc[8]; int vstream, astream;
262 int major, minor, total_astreams, total_vstreams;
263 if( mpeg3_dvb_get_channel(fd,n, &major, &minor) ||
264 mpeg3_dvb_get_station_id(fd,n,&name[0]) ||
265 mpeg3_dvb_total_vstreams(fd,n,&total_vstreams) ||
266 mpeg3_dvb_total_astreams(fd,n,&total_astreams) ) continue;
267 cp += sprintf(cp, " %3d.%-3d %s", major, minor, &name[0]);
268 for( int vidx=0; vidx<total_vstreams; ++vidx ) {
269 if( mpeg3_dvb_vstream_number(fd,n,vidx,&vstream) ) continue;
270 if( vstream < 0 ) continue;
271 cp += sprintf(cp, " v%d", vstream);
273 for( int aidx=0; aidx<total_astreams; ++aidx ) {
274 if( mpeg3_dvb_astream_number(fd,n,aidx,&astream,&enc[0]) ) continue;
275 if( astream < 0 ) continue;
276 cp += sprintf(cp, " a%d %s", astream, &enc[0]);
278 for(int i=0; i<astream; ++i )
279 atrack += mpeg3_audio_channels(fd, i);
280 int channels = mpeg3_audio_channels(fd, astream);
281 cp += sprintf(cp, " trk %d-%d", atrack+1, atrack+channels);
282 if( enc[0] ) cp += sprintf(cp," (%s)",enc);
284 cp += sprintf(cp, "\n");
287 for( int n=0; n<elements; ++n ) {
289 if( mpeg3_dvb_get_channel(fd,n, &major, &minor) ) continue;
290 cp += sprintf(cp, "\n**chan %3d.%-3d\n", major, minor);
291 int len = mpeg3_dvb_get_chan_info(fd, n, -1, 0, cp, 1023);
292 if( len < 0 ) len = sprintf(cp,_("no info"));
293 cp += len; *cp++ = '*'; *cp++ = '*'; *cp++ = '\n';
294 for( int ord=0; ord<0x80; ++ord ) {
295 for( int i=0; (len=mpeg3_dvb_get_chan_info(fd,n,ord,i,cp,1023)) >= 0; ++i ) {
296 char *bp = cp; cp += len;
297 for( int k=2; --k>=0; ) { // skip 2 lines
298 while( bp<cp && *bp++!='\n' );
300 for( char *lp=bp; bp<cp; ++bp ) { // add new lines
301 if( *bp == '\n' || ((bp-lp)>=60 && *bp==' ') )
304 *cp++ = '\n'; *cp = 0; // trailing new line
313 int FileMPEG::get_audio_for_video(int vstream, int astream, int64_t &channel_mask)
317 int elements = mpeg3_dvb_channel_count(fd);
318 if( elements <= 0 ) return -1;
321 int total_astreams = 0, total_vstreams = 0;
322 for( int n=0; pidx<0 && n<elements; ++n ) {
323 total_astreams = total_vstreams = 0;
324 if( mpeg3_dvb_total_vstreams(fd,n,&total_vstreams) ||
325 mpeg3_dvb_total_astreams(fd,n,&total_astreams) ) continue;
326 if( !total_vstreams || !total_astreams ) continue;
327 for( int i=0; pidx<0 && i<total_vstreams; ++i ) {
329 if( mpeg3_dvb_vstream_number(fd,n,i,&vstrm) ) continue;
330 if( vstrm == vstream ) pidx = n;
333 if( pidx < 0 ) return -1;
335 int64_t channels = 0;
336 for( int i=0; i<total_astreams; ++i ) {
338 if( mpeg3_dvb_astream_number(fd,pidx,i,&astrm,0) ) continue;
339 if( astrm < 0 ) continue;
340 if( ret < 0 ) ret = astrm;
341 if( astream > 0 ) { --astream; continue; }
343 for(int i=0; i<astrm; ++i )
344 atrack += mpeg3_audio_channels(fd, i);
345 int64_t mask = (1 << mpeg3_audio_channels(fd, astrm)) - 1;
346 channels |= mask << atrack;
347 if( !astream ) break;
349 channel_mask = channels;
353 int FileMPEG::reset_parameters_derived()
366 twolame_allocation = 0;
375 lame_output_allocation = 0;
382 int FileMPEG::open_file(int rd, int wr)
387 char toc_name[BCTEXTLEN];
388 result = file->preferences->get_asset_file_path(asset, toc_name);
390 fd = mpeg3_open_title(asset->path, toc_name, &error);
393 if(error == zmpeg3_t::ERR_INVALID_TOC_VERSION) {
394 eprintf(_("Couldn't open %s: invalid table of contents version.\n"
395 "Rebuilding the table of contents."), asset->path);
397 else if(error == zmpeg3_t::ERR_TOC_DATE_MISMATCH) {
398 eprintf(_("Couldn't open %s: table of contents out of date.\n"
399 "Rebuilding the table of contents."), asset->path);
402 eprintf(_("Couldn't open %s: table of contents corrupt.\n"
403 "Rebuilding the table of contents."), asset->path);
405 char filename[BCTEXTLEN];
406 strcpy(filename, toc_name);
407 char *sfx = strrchr(filename,'.');
408 if( sfx && !strcmp(sfx+1,"toc") ) {
412 strcpy(toc_name, asset->path);
413 fd = mpeg3_open_title(asset->path, toc_name, &error);
417 eprintf(_("Couldn't open %s: rebuild failed.\n"), asset->path);
420 // Determine if the file needs a table of contents and create one if needed.
421 // If it has video it must be scanned since video has keyframes.
422 if(mpeg3_total_vstreams(fd) || mpeg3_total_astreams(fd)) {
423 if(create_index()) return 1;
426 // more than 4 doesnt help much
427 mpeg3_set_cpus(fd, file->cpus < 4 ? file->cpus : 4);
428 file->current_program = mpeg3_set_program(fd, -1);
429 if( asset->program < 0 )
430 asset->program = file->current_program;
432 asset->audio_data = mpeg3_has_audio(fd);
433 if(asset->audio_data) {
435 for(int i = 0; i < mpeg3_total_astreams(fd); i++) {
436 asset->channels += mpeg3_audio_channels(fd, i);
438 if(!asset->sample_rate)
439 asset->sample_rate = mpeg3_sample_rate(fd, 0);
440 asset->audio_length = mpeg3_audio_samples(fd, 0);
441 if(!asset->channels ||
446 asset->video_data = mpeg3_has_video(fd);
447 if(asset->video_data) {
448 if( !asset->layers ) {
449 asset->layers = mpeg3_total_vstreams(fd);
451 asset->actual_width = mpeg3_video_width(fd, 0);
453 asset->width = asset->actual_width;
454 asset->actual_height = mpeg3_video_height(fd, 0);
456 asset->height = asset->actual_height;
457 if( !asset->video_length )
458 asset->video_length = mpeg3_video_frames(fd, 0);
459 if( !asset->vmpeg_cmodel )
460 asset->vmpeg_cmodel = bc_colormodel(mpeg3_colormodel(fd, 0));
461 if( !asset->frame_rate )
462 asset->frame_rate = mpeg3_frame_rate(fd, 0);
469 if(!result && wr && asset->format == FILE_VMPEG)
471 // Heroine Virtual encoder
472 // this one is cinelerra-x.x.x/mpeg2enc
473 if(asset->vmpeg_cmodel == BC_YUV422P)
475 char bitrate_string[BCTEXTLEN];
476 char quant_string[BCTEXTLEN];
477 char iframe_string[BCTEXTLEN];
479 sprintf(bitrate_string, "%d", asset->vmpeg_bitrate);
480 sprintf(quant_string, "%d", asset->vmpeg_quantization);
481 sprintf(iframe_string, "%d", asset->vmpeg_iframe_distance);
483 // Construct command line
486 char string[BCTEXTLEN]; string[0] = 0;
487 sprintf(mjpeg_command, "%s%s",
488 file->preferences->plugin_dir, HVPEG_EXE);
489 append_vcommand_line(string);
491 if(asset->aspect_ratio > 0)
493 append_vcommand_line("-a");
495 if(EQUIV((double)asset->width / asset->height,
496 asset->aspect_ratio))
497 append_vcommand_line("1");
499 if(EQUIV(asset->aspect_ratio, 1.333))
500 append_vcommand_line("2");
502 if(EQUIV(asset->aspect_ratio, 1.777))
503 append_vcommand_line("3");
505 if(EQUIV(asset->aspect_ratio, 2.11))
506 append_vcommand_line("4");
509 append_vcommand_line(asset->vmpeg_derivative == 1 ? "-1" : "");
510 append_vcommand_line(asset->vmpeg_cmodel == BC_YUV422P ? "-422" : "");
511 if(asset->vmpeg_fix_bitrate)
513 append_vcommand_line("-b");
514 append_vcommand_line(bitrate_string);
518 append_vcommand_line("-q");
519 append_vcommand_line(quant_string);
521 append_vcommand_line("-n");
522 append_vcommand_line(iframe_string);
523 append_vcommand_line(asset->vmpeg_progressive ? "-p" : "");
524 append_vcommand_line(asset->vmpeg_denoise ? "-d" : "");
525 append_vcommand_line(file->cpus <= 1 ? "-u" : "");
526 append_vcommand_line(asset->vmpeg_seq_codes ? "-g" : "");
527 append_vcommand_line(asset->path);
529 video_out = new FileMPEGVideo(this);
534 // mjpegtools encoder
535 // this one is cinelerra-x.x.x/thirdparty/mjpegtools/mpeg2enc
537 sprintf(mjpeg_command, "%s%s -v 0 ",
538 file->preferences->plugin_dir, MJPEG_EXE);
540 // Must disable interlacing if MPEG-1
541 switch (asset->vmpeg_preset)
543 case 0: asset->vmpeg_progressive = 1; break;
544 case 1: asset->vmpeg_progressive = 1; break;
545 case 2: asset->vmpeg_progressive = 1; break;
550 // The current usage of mpeg2enc requires bitrate of 0 when quantization is fixed and
551 // quantization of 1 when bitrate is fixed. Perfectly intuitive.
552 char string[BCTEXTLEN];
553 if(asset->vmpeg_fix_bitrate)
555 sprintf(string, " -b %d -q 1", asset->vmpeg_bitrate / 1000);
559 sprintf(string, " -b 0 -q %d", asset->vmpeg_quantization);
561 strcat(mjpeg_command, string);
569 int aspect_ratio_code = -1;
570 if(asset->aspect_ratio > 0)
572 int ncodes = sizeof(aspect_ratio_codes) / sizeof(double);
573 for(int i = 1; i < ncodes; i++)
575 if(EQUIV(aspect_ratio_codes[i], asset->aspect_ratio))
577 aspect_ratio_code = i;
585 if(EQUIV((double)asset->width / asset->height, asset->aspect_ratio))
586 aspect_ratio_code = 1;
588 if(aspect_ratio_code < 0)
590 eprintf(_("Unsupported aspect ratio %f\n"), asset->aspect_ratio);
591 aspect_ratio_code = 2;
593 sprintf(string, " -a %d", aspect_ratio_code);
594 strcat(mjpeg_command, string);
602 int frame_rate_code = -1;
603 int ncodes = sizeof(frame_rate_codes) / sizeof(double);
604 for(int i = 1; i < ncodes; ++i)
606 if(EQUIV(asset->frame_rate, frame_rate_codes[i]))
612 if(frame_rate_code < 0)
615 eprintf(_("Unsupported frame rate %f\n"), asset->frame_rate);
617 sprintf(string, " -F %d", frame_rate_code);
618 strcat(mjpeg_command, string);
624 strcat(mjpeg_command,
625 asset->vmpeg_progressive ? " -I 0" : " -I 1");
629 sprintf(string, " -M %d", file->cpus);
630 strcat(mjpeg_command, string);
633 if(!asset->vmpeg_progressive)
635 strcat(mjpeg_command, asset->vmpeg_field_order ? " -z b" : " -z t");
639 sprintf(string, " -f %d", asset->vmpeg_preset);
640 strcat(mjpeg_command, string);
643 sprintf(string, " -g %d -G %d", asset->vmpeg_iframe_distance, asset->vmpeg_iframe_distance);
644 strcat(mjpeg_command, string);
647 if(asset->vmpeg_seq_codes) strcat(mjpeg_command, " -s");
650 sprintf(string, " -R %d", CLAMP(asset->vmpeg_pframe_distance, 0, 2));
651 strcat(mjpeg_command, string);
653 sprintf(string, " -o '%s'", asset->path);
654 strcat(mjpeg_command, string);
658 printf("FileMPEG::open_file: Running %s\n", mjpeg_command);
659 if(!(mjpeg_out = popen(mjpeg_command, "w")))
661 perror("FileMPEG::open_file");
662 eprintf(_("Error while opening \"%s\" for writing\n%m\n"), mjpeg_command);
666 video_out = new FileMPEGVideo(this);
671 if(wr && asset->format == FILE_AMPEG)
673 //char encoder_string[BCTEXTLEN]; encoder_string[0] = 0;
674 //printf("FileMPEG::open_file 1 %d\n", asset->ampeg_derivative);
676 if(asset->ampeg_derivative == 2)
678 twofp = fopen(asset->path, "w" );
679 if( !twofp ) return 1;
680 twopts = twolame_init();
681 int channels = asset->channels >= 2 ? 2 : 1;
682 twolame_set_num_channels(twopts, channels);
683 twolame_set_in_samplerate(twopts, asset->sample_rate);
684 twolame_set_mode(twopts, channels >= 2 ?
685 TWOLAME_JOINT_STEREO : TWOLAME_MONO);
686 twolame_set_bitrate(twopts, asset->ampeg_bitrate);
687 twolame_init_params(twopts);
690 if(asset->ampeg_derivative == 3)
692 lame_global = lame_init();
693 // lame_set_brate(lame_global, asset->ampeg_bitrate / 1000);
694 lame_set_brate(lame_global, asset->ampeg_bitrate);
695 lame_set_quality(lame_global, 0);
696 lame_set_in_samplerate(lame_global,
698 lame_set_num_channels(lame_global,
700 if((result = lame_init_params(lame_global)) < 0)
702 eprintf(_("encode: lame_init_params returned %d\n"), result);
703 lame_close(lame_global);
707 if(!(lame_fd = fopen(asset->path, "w")))
709 perror("FileMPEG::open_file");
710 eprintf(_("Error while opening \"%s\" for writing\n%m\n"), asset->path);
711 lame_close(lame_global);
718 eprintf(_("ampeg_derivative=%d\n"), asset->ampeg_derivative);
723 // Transport stream for DVB capture
724 if(!result && !rd && !wr && asset->format == FILE_MPEG)
726 if( (recd_fd = open(asset->path, O_CREAT+O_TRUNC+O_WRONLY,
727 S_IRUSR+S_IWUSR + S_IRGRP+S_IWGRP)) < 0 )
729 perror("FileMPEG::open_file");
730 eprintf(_("Error while opening \"%s\" for writing\n%m\n"), asset->path);
744 int FileMPEG::set_skimming(int track, int skim, skim_fn fn, void *vp)
746 return !fn ? mpeg3_set_thumbnail_callback(fd, track, 0, 0, 0, 0) :
747 mpeg3_set_thumbnail_callback(fd, track, skim, 1, fn, vp);
750 int FileMPEG::skimming(void *vp, int track)
752 File *file = (File *)vp;
753 FileMPEG *mpeg = (FileMPEG *)file->file;
754 return mpeg->skim_result = mpeg->skim_callback(mpeg->skim_data, track);
757 int FileMPEG::skim_video(int track, void *vp, skim_fn fn)
759 skim_callback = fn; skim_data = vp;
760 mpeg3_set_thumbnail_callback(fd, track, 1, 1, skimming, (void*)file);
762 while( skim_result < 0 && !mpeg3_end_of_video(fd, track) )
763 mpeg3_drop_frames(fd, 1, track);
764 mpeg3_set_thumbnail_callback(fd, track, 0, 0, 0, 0);
770 int FileMPEG::toc_nail(void *vp, int track)
772 File *file = (File *)vp;
773 FileMPEG *mpeg = (FileMPEG *)file->file;
774 int64_t framenum; uint8_t *tdat; int mw, mh;
775 if( mpeg->get_thumbnail(track, framenum, tdat, mw, mh) ) return 1;
776 int pid, width, height; double framerate;
777 if( mpeg->get_video_info(track, pid, framerate, width, height) ) return 1;
778 if( pid < 0 || framerate <= 0 ) return 1;
779 double position = framenum / framerate;
780 //printf("t%d/%03x f"_LD", %dx%d %dx%d\n",track,pid,framenum,mw,mh,width,height);
781 MWindow::commercials->get_frame(file, pid, position, tdat, mw, mh, width, height);
786 int FileMPEG::create_index()
788 // Calculate TOC path
789 char index_filename[BCTEXTLEN];
790 char source_filename[BCTEXTLEN];
792 IndexFile::get_index_filename(source_filename,
793 file->preferences->index_directory,
796 char *ptr = strrchr(index_filename, '.');
801 // File is a table of contents.
802 if(fd && mpeg3_has_toc(fd)) return 0;
804 sprintf(ptr, ".toc");
808 if(fd) mpeg3_close(fd);
811 // Test existing copy of TOC
812 if((fd = mpeg3_open_title(asset->path, index_filename, &error)))
818 // Create progress window.
819 // This gets around the fact that MWindowGUI is locked.
820 int64_t total_bytes = 0, last_bytes = -1;
821 fd = mpeg3_start_toc( asset->path, index_filename,
822 file->current_program, &total_bytes);
824 eprintf(_("cant init toc index\n"));
828 struct timeval new_time, prev_time, start_time, current_time;
829 gettimeofday(&prev_time, 0); gettimeofday(&start_time, 0);
831 if( !result && file->preferences->scan_commercials ) {
832 set_skimming(-1, 1, toc_nail, file);
833 if( (result=MWindow::commercials->resetDb() ) != 0 )
834 eprintf(_("cant access commercials database"));
837 char progress_title[BCTEXTLEN]; progress_title[0] = 0;
838 BC_ProgressBox *progress = 0;
840 sprintf(progress_title, _("Creating %s\n"), index_filename);
841 progress = new BC_ProgressBox(-1, -1,
842 progress_title, total_bytes);
847 int64_t bytes_processed = 0;
848 if( mpeg3_do_toc(fd, &bytes_processed) ) break;
849 gettimeofday(&new_time, 0);
851 if(new_time.tv_sec - prev_time.tv_sec >= 1)
853 gettimeofday(¤t_time, 0);
854 int64_t elapsed_seconds = current_time.tv_sec - start_time.tv_sec;
855 int64_t total_seconds = !bytes_processed ? 0 :
856 elapsed_seconds * total_bytes / bytes_processed;
857 int64_t eta = total_seconds - elapsed_seconds;
858 progress->update(bytes_processed, 1);
859 char string[BCTEXTLEN];
860 sprintf(string, "%sETA: " _LD "m" _LD "s",
861 progress_title, eta / 60, eta % 60);
862 progress->update_title(string, 1);
863 // fprintf(stderr, "ETA: %dm%ds \r",
864 // bytes_processed * 100 / total_bytes,
865 // eta / 60, eta % 60);
867 prev_time = new_time;
869 if(bytes_processed >= total_bytes) break;
870 if(progress->is_cancelled()) result = 1;
871 if( bytes_processed == last_bytes ) {
872 eprintf(_("toc scan stopped before eof"));
875 last_bytes = bytes_processed;
878 // record scan results
879 if( file->preferences->scan_commercials ) {
880 if( !result ) MWindow::commercials->write_ads(asset->path);
881 MWindow::commercials->closeDb();
884 if( fd ) { mpeg3_stop_toc(fd); fd = 0; }
885 if( progress ) { progress->stop_progress(); delete progress; }
886 if( result ) { remove_file(index_filename); return 1; }
891 // Reopen file from index path instead of asset path.
894 if(!(fd = mpeg3_open(index_filename, &error)))
908 void FileMPEG::append_vcommand_line(const char *string)
912 char *argv = cstrdup(string);
913 vcommand_line.append(argv);
917 int FileMPEG::close_file()
920 next_frame_lock->unlock();
929 // End of sequence signal
930 if(file->asset->vmpeg_cmodel == BC_YUV422P)
932 mpeg2enc_set_input_buffers(1, 0, 0, 0);
938 vcommand_line.remove_all_objects();
941 unsigned char opkt[1152*2];
942 int ret = twolame_encode_flush(twopts, opkt, sizeof(opkt));
944 fwrite(opkt, 1, ret, twofp);
946 fprintf(stderr, _("twolame error encoding audio: %d\n"), ret);
947 fclose(twofp); twofp = 0;
949 if( twopts ) { twolame_close(&twopts); twopts = 0; }
952 lame_close(lame_global);
954 if(temp_frame) delete temp_frame;
955 if(twolame_temp) delete [] twolame_temp;
957 if(lame_temp[0]) delete [] lame_temp[0];
958 if(lame_temp[1]) delete [] lame_temp[1];
959 if(lame_output) delete [] lame_output;
960 if(lame_fd) fclose(lame_fd);
962 if(mjpeg_out) pclose(mjpeg_out);
971 FileBase::close_file();
975 int FileMPEG::get_best_colormodel(Asset *asset, int driver)
977 //printf("FileMPEG::get_best_colormodel 1\n");
982 case PLAYBACK_X11_XV:
983 case PLAYBACK_ASYNCHRONOUS:
984 return zmpeg3_cmdl(asset->vmpeg_cmodel) > 0 ?
985 asset->vmpeg_cmodel : BC_RGB888;
986 case PLAYBACK_X11_GL:
991 case PLAYBACK_DV1394:
992 case PLAYBACK_FIREWIRE:
996 return zmpeg3_cmdl(asset->vmpeg_cmodel) > 0 ?
997 asset->vmpeg_cmodel : BC_RGB888;
998 case VIDEO4LINUX2JPEG:
999 return BC_COMPRESSED;
1001 case VIDEO4LINUX2MPEG:
1003 case CAPTURE_JPEG_WEBCAM:
1004 return BC_COMPRESSED;
1005 case CAPTURE_YUYV_WEBCAM:
1010 case CAPTURE_FIREWIRE:
1011 case CAPTURE_IEC61883:
1014 eprintf(_("unknown driver %d\n"),driver);
1018 int FileMPEG::colormodel_supported(int colormodel)
1023 int FileMPEG::get_index(char *index_path)
1028 // Convert the index tables from tracks to channels.
1029 if(mpeg3_index_tracks(fd))
1031 // Calculate size of buffer needed for all channels
1032 int buffer_size = 0;
1033 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
1035 buffer_size += mpeg3_index_size(fd, i) *
1036 mpeg3_index_channels(fd, i) *
1040 IndexState *index_state = asset->index_state;
1041 index_state->index_buffer = new float[buffer_size];
1043 int index_channels = 0;
1044 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
1045 index_channels += mpeg3_index_channels(fd, i);
1046 // Size of index buffer in floats
1047 int current_offset = 0;
1048 // Current asset channel
1049 int current_channel = 0;
1050 index_state->channels = index_channels;
1051 index_state->index_zoom = mpeg3_index_zoom(fd);
1052 index_state->index_offsets = new int64_t[index_channels];
1053 index_state->index_sizes = new int64_t[index_channels];
1054 for(int i = 0; i < mpeg3_index_tracks(fd); i++)
1056 for(int j = 0; j < mpeg3_index_channels(fd, i); j++)
1058 index_state->index_offsets[current_channel] = current_offset;
1059 index_state->index_sizes[current_channel] = mpeg3_index_size(fd, i) * 2;
1060 memcpy(index_state->index_buffer + current_offset,
1061 mpeg3_index_data(fd, i, j),
1062 mpeg3_index_size(fd, i) * sizeof(float) * 2);
1064 current_offset += mpeg3_index_size(fd, i) * 2;
1070 index_state->index_bytes = fs.get_size(asset->path);
1072 index_state->write_index(index_path,
1073 buffer_size * sizeof(float),
1075 asset->audio_length);
1076 delete [] index_state->index_buffer;
1085 int FileMPEG::can_copy_from(Asset *asset, int64_t position)
1091 int FileMPEG::set_audio_position(int64_t sample)
1096 int channel, stream;
1097 to_streamchannel(file->current_channel, stream, channel);
1099 //printf("FileMPEG::set_audio_position %d %d %d\n", sample, mpeg3_get_sample(fd, stream), last_sample);
1100 if(sample != mpeg3_get_sample(fd, stream) &&
1101 sample != last_sample)
1103 if(sample >= 0 && sample < asset->audio_length)
1105 //printf("FileMPEG::set_audio_position seeking stream %d\n", sample);
1106 return mpeg3_set_sample(fd, sample, stream);
1115 int FileMPEG::set_video_position(int64_t pos)
1117 if( !fd || pos < 0 || pos >= asset->video_length )
1119 //printf("FileMPEG::set_video_position 1 " _LD "\n", x);
1120 mpeg3_set_frame(fd, pos, file->current_layer);
1124 int64_t FileMPEG::get_memory_usage()
1126 int64_t result = file->rd && fd ? mpeg3_memory_usage(fd) : 0;
1127 //printf("FileMPEG::get_memory_usage %d " _LD "\n", __LINE__, result);
1131 int FileMPEG::set_program(int no)
1133 return fd ? mpeg3_set_program(fd, no) : -1;
1136 int FileMPEG::get_cell_time(int no, double &time)
1138 return fd ? mpeg3_get_cell_time(fd, no, &time) : -1;
1141 int FileMPEG::get_system_time(int64_t &tm)
1143 return fd ? mpeg3_dvb_get_system_time(fd, &tm) : -1;
1146 int FileMPEG::get_video_pid(int track)
1148 return fd ? mpeg3_video_pid(fd, track) : -1;
1151 int FileMPEG::get_video_info(int track, int &pid,
1152 double &framerate, int &width, int &height, char *title)
1154 if( !fd ) return -1;
1155 pid = mpeg3_video_pid(fd, track);
1156 framerate = mpeg3_frame_rate(fd, track);
1157 width = mpeg3_video_width(fd, track);
1158 height = mpeg3_video_height(fd, track);
1159 if( !title ) return 0;
1162 int elements = mpeg3_dvb_channel_count(fd);
1163 for( int n=0; n<elements; ++n ) {
1164 int major, minor, total_vstreams, vstream, vidx;
1165 if( mpeg3_dvb_get_channel(fd,n, &major, &minor) ||
1166 mpeg3_dvb_total_vstreams(fd,n,&total_vstreams) ) continue;
1167 for( vidx=0; vidx<total_vstreams; ++vidx ) {
1168 if( mpeg3_dvb_vstream_number(fd,n,vidx,&vstream) ) continue;
1169 if( vstream < 0 ) continue;
1170 if( vstream == track ) {
1171 sprintf(title, "%3d.%-3d", major, minor);
1179 int FileMPEG::select_video_stream(Asset *asset, int vstream)
1181 if( !fd ) return -1;
1182 asset->width = mpeg3_video_width(fd, vstream);
1183 asset->height = mpeg3_video_height(fd, vstream);
1184 asset->video_length = mpeg3_video_frames(fd, vstream);
1185 asset->frame_rate = mpeg3_frame_rate(fd, vstream);
1189 int FileMPEG::select_audio_stream(Asset *asset, int astream)
1191 if( !fd ) return -1;
1192 asset->channels = mpeg3_audio_channels(fd, astream);
1193 asset->sample_rate = mpeg3_sample_rate(fd, astream);
1194 asset->audio_length = mpeg3_audio_samples(fd, astream);
1198 int FileMPEG::get_thumbnail(int stream,
1199 int64_t &position, unsigned char *&thumbnail, int &ww, int &hh)
1202 mpeg3_get_thumbnail(fd, stream, &position, &thumbnail, &ww, &hh);
1205 int FileMPEG::write_samples(double **buffer, int64_t len)
1209 //printf("FileMPEG::write_samples 1\n");
1210 if(asset->ampeg_derivative == 2) {
1212 int channels = MIN(asset->channels, 2);
1213 int64_t audio_size = len * channels * 2;
1214 if(twolame_allocation < audio_size) {
1215 if(twolame_temp) delete [] twolame_temp;
1216 twolame_temp = new unsigned char[audio_size];
1217 twolame_allocation = audio_size;
1218 if(twolame_out) delete [] twolame_out;
1219 twolame_out = new unsigned char[audio_size + 1152];
1222 for(int i = 0; i < channels; i++) {
1223 int16_t *output = ((int16_t*)twolame_temp) + i;
1224 double *input = buffer[i];
1225 for(int j = 0; j < len; j++) {
1226 int sample = (int)(*input * 0x7fff);
1227 *output = (int16_t)(CLIP(sample, -0x8000, 0x7fff));
1232 int ret = twolame_encode_buffer_interleaved(twopts,
1233 (int16_t*)twolame_temp, len,
1234 twolame_out, twolame_allocation+1152);
1236 fwrite(twolame_out, 1, ret, twofp);
1238 fprintf(stderr, _("twolame error encoding audio: %d\n"), ret);
1241 if(asset->ampeg_derivative == 3)
1243 int channels = MIN(asset->channels, 2);
1244 int64_t audio_size = len * channels;
1245 if(!lame_global) return 1;
1246 if(!lame_fd) return 1;
1247 if(lame_allocation < audio_size)
1249 if(lame_temp[0]) delete [] lame_temp[0];
1250 if(lame_temp[1]) delete [] lame_temp[1];
1251 lame_temp[0] = new float[audio_size];
1252 lame_temp[1] = new float[audio_size];
1253 lame_allocation = audio_size;
1256 if(lame_output_allocation < audio_size * 4)
1258 if(lame_output) delete [] lame_output;
1259 lame_output_allocation = audio_size * 4;
1260 lame_output = new char[lame_output_allocation];
1263 for(int i = 0; i < channels; i++)
1265 float *output = lame_temp[i];
1266 double *input = buffer[i];
1267 for(int j = 0; j < len; j++)
1269 *output++ = *input++ * (float)32768;
1273 result = lame_encode_buffer_float(lame_global,
1275 (channels > 1) ? lame_temp[1] : lame_temp[0],
1277 (unsigned char*)lame_output,
1278 lame_output_allocation);
1281 char *real_output = lame_output;
1285 for(int i = 0; i < bytes; i++)
1288 real_output = &lame_output[i];
1294 if(bytes > 0 && lame_started)
1296 result = !fwrite(real_output, 1, bytes, lame_fd);
1298 perror("FileMPEG::write_samples");
1299 eprintf(_("write failed: %m"));
1312 int FileMPEG::write_frames(VFrame ***frames, int len)
1318 int temp_w = (int)((asset->width + 15) / 16) * 16;
1321 int output_cmodel = asset->vmpeg_cmodel;
1322 // verify colormodel supported in MPEG output
1323 switch( output_cmodel ) {
1331 // Height depends on progressiveness
1332 if(asset->vmpeg_progressive || asset->vmpeg_derivative == 1)
1333 temp_h = (int)((asset->height + 15) / 16) * 16;
1335 temp_h = (int)((asset->height + 31) / 32) * 32;
1337 //printf("FileMPEG::write_frames 1\n");
1339 // Only 1 layer is supported in MPEG output
1340 for(int i = 0; i < 1; i++)
1342 for(int j = 0; j < len && !result; j++)
1344 VFrame *frame = frames[i][j];
1348 if(asset->vmpeg_cmodel == BC_YUV422P)
1350 if(frame->get_w() == temp_w &&
1351 frame->get_h() == temp_h &&
1352 frame->get_color_model() == output_cmodel)
1354 mpeg2enc_set_input_buffers(0,
1355 (char*)frame->get_y(),
1356 (char*)frame->get_u(),
1357 (char*)frame->get_v());
1362 (temp_frame->get_w() != temp_w ||
1363 temp_frame->get_h() != temp_h ||
1364 temp_frame->get_color_model() || output_cmodel))
1373 temp_frame = new VFrame(0,
1381 BC_CModels::transfer(temp_frame->get_rows(),
1383 temp_frame->get_y(),
1384 temp_frame->get_u(),
1385 temp_frame->get_v(),
1395 temp_frame->get_w(),
1396 temp_frame->get_h(),
1397 frame->get_color_model(),
1398 temp_frame->get_color_model(),
1401 temp_frame->get_w());
1403 mpeg2enc_set_input_buffers(0,
1404 (char*)temp_frame->get_y(),
1405 (char*)temp_frame->get_u(),
1406 (char*)temp_frame->get_v());
1411 // MJPEG uses the same dimensions as the input
1412 //printf("FileMPEG::write_frames %d\n", __LINE__);sleep(1);
1413 if(frame->get_color_model() == output_cmodel)
1415 mjpeg_y = frame->get_y();
1416 mjpeg_u = frame->get_u();
1417 mjpeg_v = frame->get_v();
1421 //printf("FileMPEG::write_frames %d\n", __LINE__);sleep(1);
1424 temp_frame = new VFrame(0,
1432 // printf("FileMPEG::write_frames %d temp_frame=%p %p %p %p frame=%p %p %p %p color_model=%p %p\n",
1435 // temp_frame->get_w(),
1436 // temp_frame->get_h(),
1440 // temp_frame->get_color_model(),
1441 // frame->get_color_model()); sleep(1);
1442 BC_CModels::transfer(temp_frame->get_rows(),
1444 temp_frame->get_y(),
1445 temp_frame->get_u(),
1446 temp_frame->get_v(),
1456 temp_frame->get_w(),
1457 temp_frame->get_h(),
1458 frame->get_color_model(),
1459 temp_frame->get_color_model(),
1462 temp_frame->get_w());
1463 //printf("FileMPEG::write_frames %d\n", __LINE__);sleep(1);
1465 mjpeg_y = temp_frame->get_y();
1466 mjpeg_u = temp_frame->get_u();
1467 mjpeg_v = temp_frame->get_v();
1473 next_frame_lock->unlock();
1474 next_frame_done->lock("FileMPEG::write_frames");
1475 if(mjpeg_error) result = 1;
1491 int FileMPEG::zmpeg3_cmdl(int colormodel)
1493 switch( colormodel ) {
1494 case BC_BGR888: return zmpeg3_t::cmdl_BGR888;
1495 case BC_BGR8888: return zmpeg3_t::cmdl_BGRA8888;
1496 case BC_RGB565: return zmpeg3_t::cmdl_RGB565;
1497 case BC_RGB888: return zmpeg3_t::cmdl_RGB888;
1498 case BC_RGBA8888: return zmpeg3_t::cmdl_RGBA8888;
1499 case BC_RGBA16161616: return zmpeg3_t::cmdl_RGBA16161616;
1500 case BC_YUV420P: return zmpeg3_t::cmdl_YUV420P;
1501 case BC_YUV422P: return zmpeg3_t::cmdl_YUV422P;
1502 case BC_YUV422: return zmpeg3_t::cmdl_YUYV;
1503 case BC_YUV888: return zmpeg3_t::cmdl_YUV888;
1504 case BC_YUVA8888: return zmpeg3_t::cmdl_YUVA8888;
1509 int FileMPEG::bc_colormodel(int cmdl)
1512 case zmpeg3_t::cmdl_BGR888: return BC_BGR888;
1513 case zmpeg3_t::cmdl_BGRA8888: return BC_BGR8888;
1514 case zmpeg3_t::cmdl_RGB565: return BC_RGB565;
1515 case zmpeg3_t::cmdl_RGB888: return BC_RGB888;
1516 case zmpeg3_t::cmdl_RGBA8888: return BC_RGBA8888;
1517 case zmpeg3_t::cmdl_RGBA16161616: return BC_RGBA16161616;
1518 case zmpeg3_t::cmdl_YUV420P: return BC_YUV420P;
1519 case zmpeg3_t::cmdl_YUV422P: return BC_YUV422P;
1520 case zmpeg3_t::cmdl_YUYV: return BC_YUV422;
1521 case zmpeg3_t::cmdl_YUV888: return BC_YUV888;
1522 case zmpeg3_t::cmdl_YUVA8888: return BC_YUVA8888;
1527 const char *FileMPEG::zmpeg3_cmdl_name(int cmdl)
1529 # define CMDL(nm) #nm
1530 static const char *cmdl_name[] = {
1556 return cmdl>=0 && cmdl<lengthof(cmdl_name) ? cmdl_name[cmdl] : cmdl_name[6];
1560 int FileMPEG::read_frame(VFrame *frame)
1564 int width = mpeg3_video_width(fd,file->current_layer);
1565 int height = mpeg3_video_height(fd,file->current_layer);
1566 int stream_cmdl = mpeg3_colormodel(fd,file->current_layer);
1567 int stream_color_model = bc_colormodel(stream_cmdl);
1568 int frame_color_model = frame->get_color_model();
1569 int frame_cmdl = zmpeg3_cmdl(frame_color_model);
1570 mpeg3_show_subtitle(fd, file->current_layer, file->playback_subtitle);
1573 switch( frame_color_model ) { // check for direct copy
1576 if( stream_color_model == frame_color_model &&
1577 width == frame->get_w() && height == frame->get_h() ) {
1578 mpeg3_read_yuvframe(fd,
1579 (char*)frame->get_y(),
1580 (char*)frame->get_u(),
1581 (char*)frame->get_v(),
1582 0, 0, width, height,
1583 file->current_layer);
1588 if( frame_cmdl >= 0 ) { // supported by read_frame
1589 // cant rely on frame->get_rows(), format may not support it
1591 switch( frame_color_model ) {
1592 case BC_YUV420P: uvs = 2; break;
1593 case BC_YUV422P: uvs = 1; break;
1595 //int w = frame->get_w();
1596 int h = frame->get_h();
1597 int bpl = frame->get_bytes_per_line();
1598 int uvw = !uvs ? 0 : bpl / 2;
1599 int uvh = !uvs ? 0 : h / uvs;
1600 uint8_t *rows[h + 2*uvh], *rp;
1602 if( (rp=frame->get_y()) ) {
1603 for( int i=0; i<h; ++i, rp+=bpl ) rows[n++] = rp;
1604 rp = frame->get_u();
1605 for( int i=0; i<uvh; ++i, rp+=uvw ) rows[n++] = rp;
1606 rp = frame->get_v();
1607 for( int i=0; i<uvh; ++i, rp+=uvw ) rows[n++] = rp;
1610 rp = frame->get_data(); uvh *= 2;
1611 for( int i=0; i<h; ++i, rp+=bpl ) rows[n++] = rp;
1612 for( int i=0; i<uvh; ++i, rp+=uvw ) rows[n++] = rp;
1615 mpeg3_read_frame(fd,
1616 rows, /* start of each output row */
1617 0, 0, width, height, /* input box */
1618 frame->get_w(), /* Dimensions of output_rows */
1621 file->current_layer);
1626 mpeg3_read_yuvframe_ptr(fd, &y, &u, &v, file->current_layer);
1628 BC_CModels::transfer(frame->get_rows(), 0,
1635 0, 0, width, height,
1636 0, 0, frame->get_w(), frame->get_h(),
1648 void FileMPEG::to_streamchannel(int channel, int &stream_out, int &channel_out)
1650 int total_astreams = mpeg3_total_astreams(fd);
1651 for(stream_out = 0; stream_out < total_astreams; ++stream_out )
1653 int stream_channels = mpeg3_audio_channels(fd, stream_out);
1654 if( channel < stream_channels ) break;
1655 channel -= stream_channels;
1657 channel_out = channel;
1660 int FileMPEG::read_samples(double *buffer, int64_t len)
1663 if(len < 0) return 0;
1665 // Translate pure channel to a stream and a channel in the mpeg stream
1666 int stream, channel;
1667 to_streamchannel(file->current_channel, stream, channel);
1669 //printf("FileMPEG::read_samples 1 current_sample=" _LD " len=" _LD " channel=%d\n", file->current_sample, len, channel);
1671 mpeg3_set_sample(fd,
1672 file->current_sample,
1674 mpeg3_read_audio_d(fd,
1675 buffer, /* Pointer to pre-allocated buffer of doubles */
1676 channel, /* Channel to decode */
1677 len, /* Number of samples to decode */
1678 stream); /* Stream containing the channel */
1680 // last_sample = file->current_sample;
1684 const char* FileMPEG::strtocompression(char *string)
1689 const char* FileMPEG::compressiontostr(char *string)
1700 FileMPEGVideo::FileMPEGVideo(FileMPEG *file)
1706 if(file->asset->vmpeg_cmodel == BC_YUV422P)
1708 mpeg2enc_init_buffers();
1709 mpeg2enc_set_w(file->asset->width);
1710 mpeg2enc_set_h(file->asset->height);
1711 mpeg2enc_set_rate(file->asset->frame_rate);
1715 FileMPEGVideo::~FileMPEGVideo()
1720 void FileMPEGVideo::run()
1722 if(file->asset->vmpeg_cmodel == BC_YUV422P)
1724 printf("FileMPEGVideo::run ");
1725 for(int i = 0; i < file->vcommand_line.total; i++)
1726 printf("%s ", file->vcommand_line.values[i]);
1728 mpeg2enc(file->vcommand_line.total, file->vcommand_line.values);
1734 //printf("FileMPEGVideo::run %d\n", __LINE__);
1735 file->next_frame_lock->lock("FileMPEGVideo::run");
1736 //printf("FileMPEGVideo::run %d\n", __LINE__);
1739 file->next_frame_done->unlock();
1745 //printf("FileMPEGVideo::run %d\n", __LINE__);
1746 // YUV4 sequence header
1747 if(!file->wrote_header)
1749 file->wrote_header = 1;
1751 char interlace_string[BCTEXTLEN];
1752 if(!file->asset->vmpeg_progressive)
1754 sprintf(interlace_string, file->asset->vmpeg_field_order ? "b" : "t");
1758 sprintf(interlace_string, "p");
1760 double aspect_ratio = file->asset->aspect_ratio >= 0 ?
1761 file->asset->aspect_ratio : 1.0;
1762 //printf("FileMPEGVideo::run %d\n", __LINE__);
1763 fprintf(file->mjpeg_out, "YUV4MPEG2 W%d H%d F%d:%d I%s A%d:%d C%s\n",
1764 file->asset->width, file->asset->height,
1765 (int)(file->asset->frame_rate * 1001),
1766 1001, interlace_string,
1767 (int)(aspect_ratio * 1000), 1000,
1769 //printf("FileMPEGVideo::run %d\n", __LINE__);
1772 // YUV4 frame header
1773 //printf("FileMPEGVideo::run %d\n", __LINE__);
1774 fprintf(file->mjpeg_out, "FRAME\n");
1777 //printf("FileMPEGVideo::run %d\n", __LINE__);
1778 if(!fwrite(file->mjpeg_y, file->asset->width * file->asset->height, 1, file->mjpeg_out))
1779 file->mjpeg_error = 1;
1780 //printf("FileMPEGVideo::run %d\n", __LINE__);
1781 if(!fwrite(file->mjpeg_u, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1782 file->mjpeg_error = 1;
1783 //printf("FileMPEGVideo::run %d\n", __LINE__);
1784 if(!fwrite(file->mjpeg_v, file->asset->width * file->asset->height / 4, 1, file->mjpeg_out))
1785 file->mjpeg_error = 1;
1786 //printf("FileMPEGVideo::run %d\n", __LINE__);
1787 fflush(file->mjpeg_out);
1789 //printf("FileMPEGVideo::run %d\n", __LINE__);
1790 file->next_frame_done->unlock();
1791 //printf("FileMPEGVideo::run %d\n", __LINE__);
1793 pclose(file->mjpeg_out);
1794 file->mjpeg_out = 0;
1809 MPEGConfigAudio::MPEGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
1810 : BC_Window(_(PROGRAM_NAME ": Audio Compression"),
1811 parent_window->get_abs_cursor_x(1),
1812 parent_window->get_abs_cursor_y(1),
1821 this->parent_window = parent_window;
1822 this->asset = asset;
1825 MPEGConfigAudio::~MPEGConfigAudio()
1829 void MPEGConfigAudio::create_objects()
1835 lock_window("MPEGConfigAudio::create_objects");
1836 if(asset->format == FILE_MPEG)
1838 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
1844 add_tool(new BC_Title(x, y, _("Layer:")));
1845 add_tool(layer = new MPEGLayer(x1, y, this));
1846 layer->create_objects();
1849 add_tool(new BC_Title(x, y, _("Kbits per second:")));
1850 add_tool(bitrate = new MPEGABitrate(x1, y, this));
1851 bitrate->create_objects();
1854 add_subwindow(new BC_OKButton(this));
1859 int MPEGConfigAudio::close_event()
1871 MPEGLayer::MPEGLayer(int x, int y, MPEGConfigAudio *gui)
1872 : BC_PopupMenu(x, y, 100, layer_to_string(gui->asset->ampeg_derivative))
1877 void MPEGLayer::create_objects()
1879 add_item(new BC_MenuItem(layer_to_string(2)));
1880 add_item(new BC_MenuItem(layer_to_string(3)));
1883 int MPEGLayer::handle_event()
1885 gui->asset->ampeg_derivative = string_to_layer(get_text());
1886 gui->bitrate->set_layer(gui->asset->ampeg_derivative);
1890 int MPEGLayer::string_to_layer(char *string)
1892 if(!strcasecmp(layer_to_string(2), string))
1894 if(!strcasecmp(layer_to_string(3), string))
1900 char* MPEGLayer::layer_to_string(int layer)
1924 MPEGABitrate::MPEGABitrate(int x, int y, MPEGConfigAudio *gui)
1928 bitrate_to_string(gui->string, gui->asset->ampeg_bitrate))
1933 void MPEGABitrate::create_objects()
1935 set_layer(gui->asset->ampeg_derivative);
1938 void MPEGABitrate::set_layer(int layer)
1940 while(total_items())
1947 add_item(new BC_MenuItem("160"));
1948 add_item(new BC_MenuItem("192"));
1949 add_item(new BC_MenuItem("224"));
1950 add_item(new BC_MenuItem("256"));
1951 add_item(new BC_MenuItem("320"));
1952 add_item(new BC_MenuItem("384"));
1956 add_item(new BC_MenuItem("8"));
1957 add_item(new BC_MenuItem("16"));
1958 add_item(new BC_MenuItem("24"));
1959 add_item(new BC_MenuItem("32"));
1960 add_item(new BC_MenuItem("40"));
1961 add_item(new BC_MenuItem("48"));
1962 add_item(new BC_MenuItem("56"));
1963 add_item(new BC_MenuItem("64"));
1964 add_item(new BC_MenuItem("80"));
1965 add_item(new BC_MenuItem("96"));
1966 add_item(new BC_MenuItem("112"));
1967 add_item(new BC_MenuItem("128"));
1968 add_item(new BC_MenuItem("144"));
1969 add_item(new BC_MenuItem("160"));
1970 add_item(new BC_MenuItem("192"));
1971 add_item(new BC_MenuItem("224"));
1972 add_item(new BC_MenuItem("256"));
1973 add_item(new BC_MenuItem("320"));
1977 int MPEGABitrate::handle_event()
1979 gui->asset->ampeg_bitrate = string_to_bitrate(get_text());
1983 int MPEGABitrate::string_to_bitrate(char *string)
1985 return atol(string);
1989 char* MPEGABitrate::bitrate_to_string(char *string, int bitrate)
1991 sprintf(string, "%d", bitrate);
2003 MPEGConfigVideo::MPEGConfigVideo(BC_WindowBase *parent_window,
2005 : BC_Window(_(PROGRAM_NAME ": Video Compression"),
2006 parent_window->get_abs_cursor_x(1),
2007 parent_window->get_abs_cursor_y(1),
2016 this->parent_window = parent_window;
2017 this->asset = asset;
2021 MPEGConfigVideo::~MPEGConfigVideo()
2025 void MPEGConfigVideo::create_objects()
2031 lock_window("MPEGConfigVideo::create_objects");
2032 if(asset->format == FILE_MPEG)
2034 add_subwindow(new BC_Title(x, y, _("No options for MPEG transport stream.")));
2039 add_subwindow(new BC_Title(x, y, _("Color model:")));
2040 add_subwindow(cmodel = new MPEGColorModel(x1, y, this));
2041 cmodel->create_objects();
2044 update_cmodel_objs();
2046 add_subwindow(new BC_OKButton(this));
2051 int MPEGConfigVideo::close_event()
2058 void MPEGConfigVideo::delete_cmodel_objs()
2063 delete fixed_bitrate;
2066 delete iframe_distance;
2067 delete pframe_distance;
2068 delete top_field_first;
2072 titles.remove_all_objects();
2076 void MPEGConfigVideo::reset_cmodel()
2084 iframe_distance = 0;
2085 pframe_distance = 0;
2086 top_field_first = 0;
2092 void MPEGConfigVideo::update_cmodel_objs()
2100 delete_cmodel_objs();
2102 if(asset->vmpeg_cmodel == BC_YUV420P)
2104 add_subwindow(title = new BC_Title(x, y + 5, _("Format Preset:")));
2105 titles.append(title);
2106 add_subwindow(preset = new MPEGPreset(x1, y, this));
2107 preset->create_objects();
2111 add_subwindow(title = new BC_Title(x, y + 5, _("Derivative:")));
2112 titles.append(title);
2113 add_subwindow(derivative = new MPEGDerivative(x1, y, this));
2114 derivative->create_objects();
2117 add_subwindow(title = new BC_Title(x, y + 5, _("Bitrate:")));
2118 titles.append(title);
2119 add_subwindow(bitrate = new MPEGBitrate(x1, y, this));
2120 add_subwindow(fixed_bitrate = new MPEGFixedBitrate(x2, y, this));
2123 add_subwindow(title = new BC_Title(x, y, _("Quantization:")));
2124 titles.append(title);
2125 quant = new MPEGQuant(x1, y, this);
2126 quant->create_objects();
2127 add_subwindow(fixed_quant = new MPEGFixedQuant(x2, y, this));
2130 add_subwindow(title = new BC_Title(x, y, _("I frame distance:")));
2131 titles.append(title);
2132 iframe_distance = new MPEGIFrameDistance(x1, y, this);
2133 iframe_distance->create_objects();
2136 if(asset->vmpeg_cmodel == BC_YUV420P)
2138 add_subwindow(title = new BC_Title(x, y, _("P frame distance:")));
2139 titles.append(title);
2140 pframe_distance = new MPEGPFrameDistance(x1, y, this);
2141 pframe_distance->create_objects();
2144 add_subwindow(top_field_first = new BC_CheckBox(x, y, &asset->vmpeg_field_order, _("Bottom field first")));
2148 add_subwindow(progressive = new BC_CheckBox(x, y, &asset->vmpeg_progressive, _("Progressive frames")));
2150 add_subwindow(denoise = new BC_CheckBox(x, y, &asset->vmpeg_denoise, _("Denoise")));
2152 add_subwindow(seq_codes = new BC_CheckBox(x, y, &asset->vmpeg_seq_codes, _("Sequence start codes in every GOP")));
2168 MPEGDerivative::MPEGDerivative(int x, int y, MPEGConfigVideo *gui)
2169 : BC_PopupMenu(x, y, 150, derivative_to_string(gui->asset->vmpeg_derivative))
2174 void MPEGDerivative::create_objects()
2176 add_item(new BC_MenuItem(derivative_to_string(1)));
2177 add_item(new BC_MenuItem(derivative_to_string(2)));
2180 int MPEGDerivative::handle_event()
2182 gui->asset->vmpeg_derivative = string_to_derivative(get_text());
2186 int MPEGDerivative::string_to_derivative(char *string)
2188 if(!strcasecmp(derivative_to_string(1), string))
2190 if(!strcasecmp(derivative_to_string(2), string))
2196 char* MPEGDerivative::derivative_to_string(int derivative)
2224 MPEGPreset::MPEGPreset(int x, int y, MPEGConfigVideo *gui)
2225 : BC_PopupMenu(x, y, 200, value_to_string(gui->asset->vmpeg_preset))
2230 void MPEGPreset::create_objects()
2232 for(int i = 0; i < 10; i++)
2234 add_item(new BC_MenuItem(value_to_string(i)));
2238 int MPEGPreset::handle_event()
2240 gui->asset->vmpeg_preset = string_to_value(get_text());
2244 int MPEGPreset::string_to_value(char *string)
2246 for(int i = 0; i < 10; i++)
2248 if(!strcasecmp(value_to_string(i), string))
2254 char* MPEGPreset::value_to_string(int derivative)
2258 case 0: return _("Generic MPEG-1"); break;
2259 case 1: return _("standard VCD"); break;
2260 case 2: return _("user VCD"); break;
2261 case 3: return _("Generic MPEG-2"); break;
2262 case 4: return _("standard SVCD"); break;
2263 case 5: return _("user SVCD"); break;
2264 case 6: return _("VCD Still sequence"); break;
2265 case 7: return _("SVCD Still sequence"); break;
2266 case 8: return _("DVD NAV"); break;
2267 case 9: return _("DVD"); break;
2268 default: return _("Generic MPEG-1"); break;
2282 MPEGBitrate::MPEGBitrate(int x, int y, MPEGConfigVideo *gui)
2283 : BC_TextBox(x, y, 100, 1, gui->asset->vmpeg_bitrate)
2289 int MPEGBitrate::handle_event()
2291 gui->asset->vmpeg_bitrate = atol(get_text());
2299 MPEGQuant::MPEGQuant(int x, int y, MPEGConfigVideo *gui)
2300 : BC_TumbleTextBox(gui,
2301 (int64_t)gui->asset->vmpeg_quantization,
2311 int MPEGQuant::handle_event()
2313 gui->asset->vmpeg_quantization = atol(get_text());
2317 MPEGFixedBitrate::MPEGFixedBitrate(int x, int y, MPEGConfigVideo *gui)
2318 : BC_Radial(x, y, gui->asset->vmpeg_fix_bitrate, _("Fixed bitrate"))
2323 int MPEGFixedBitrate::handle_event()
2326 gui->asset->vmpeg_fix_bitrate = 1;
2327 gui->fixed_quant->update(0);
2331 MPEGFixedQuant::MPEGFixedQuant(int x, int y, MPEGConfigVideo *gui)
2332 : BC_Radial(x, y, !gui->asset->vmpeg_fix_bitrate, _("Fixed quantization"))
2337 int MPEGFixedQuant::handle_event()
2340 gui->asset->vmpeg_fix_bitrate = 0;
2341 gui->fixed_bitrate->update(0);
2353 MPEGIFrameDistance::MPEGIFrameDistance(int x, int y, MPEGConfigVideo *gui)
2354 : BC_TumbleTextBox(gui,
2355 (int64_t)gui->asset->vmpeg_iframe_distance,
2365 int MPEGIFrameDistance::handle_event()
2367 gui->asset->vmpeg_iframe_distance = atoi(get_text());
2377 MPEGPFrameDistance::MPEGPFrameDistance(int x, int y, MPEGConfigVideo *gui)
2378 : BC_TumbleTextBox(gui,
2379 (int64_t)gui->asset->vmpeg_pframe_distance,
2389 int MPEGPFrameDistance::handle_event()
2391 gui->asset->vmpeg_pframe_distance = atoi(get_text());
2402 MPEGColorModel::MPEGColorModel(int x, int y, MPEGConfigVideo *gui)
2403 : BC_PopupMenu(x, y, 150, cmodel_to_string(gui->asset->vmpeg_cmodel))
2408 void MPEGColorModel::create_objects()
2410 add_item(new BC_MenuItem(cmodel_to_string(BC_YUV420P)));
2411 add_item(new BC_MenuItem(cmodel_to_string(BC_YUV422P)));
2414 int MPEGColorModel::handle_event()
2416 gui->asset->vmpeg_cmodel = string_to_cmodel(get_text());
2417 gui->update_cmodel_objs();
2418 gui->show_window(1);
2422 int MPEGColorModel::string_to_cmodel(char *string)
2424 if(!strcasecmp(cmodel_to_string(BC_YUV420P), string))
2426 if(!strcasecmp(cmodel_to_string(BC_YUV422P), string))
2431 char* MPEGColorModel::cmodel_to_string(int cmodel)
2435 case BC_YUV420P: return _("YUV 4:2:0");
2436 case BC_YUV422P: return _("YUV 4:2:2");
2437 default: return _("YUV 4:2:0");