X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fdvdcreate.C;h=157f17ee23db4f99c115a432b97d03e08ffa12f1;hp=1014baf5e2368312a739e01b0d5bac51aedcbc76;hb=4a6b59824b2db18e6cc49b43a971923d5e5903ae;hpb=7fd85fb66168f6b518c5f2d73e04036e87faa0e1 diff --git a/cinelerra-5.1/cinelerra/dvdcreate.C b/cinelerra-5.1/cinelerra/dvdcreate.C index 1014baf5..157f17ee 100644 --- a/cinelerra-5.1/cinelerra/dvdcreate.C +++ b/cinelerra-5.1/cinelerra/dvdcreate.C @@ -96,6 +96,165 @@ int CreateDVD_MenuItem::handle_event() } +DVD_BatchRenderJob::DVD_BatchRenderJob(Preferences *preferences, + int labeled, int farmed, int standard, int muxed) + : BatchRenderJob("DVD_JOB", preferences, labeled, farmed) +{ + this->standard = standard; + this->muxed = muxed; + + chapter = -1; + edl = 0; + fp =0; +} + +void DVD_BatchRenderJob::copy_from(DVD_BatchRenderJob *src) +{ + standard = src->standard; + muxed = src->muxed; + BatchRenderJob::copy_from(src); +} + +DVD_BatchRenderJob *DVD_BatchRenderJob::copy() +{ + DVD_BatchRenderJob *t = new DVD_BatchRenderJob(preferences, + labeled, farmed, standard, muxed); + t->copy_from(this); + return t; +} + +void DVD_BatchRenderJob::load(FileXML *file) +{ + standard = file->tag.get_property("STANDARD", standard); + muxed = file->tag.get_property("MUXED", muxed); + BatchRenderJob::load(file); +} + +void DVD_BatchRenderJob::save(FileXML *file) +{ + file->tag.set_property("STANDARD", standard); + file->tag.set_property("MUXED", muxed); + BatchRenderJob::save(file); +} + +void DVD_BatchRenderJob::create_chapter(double pos) +{ + fprintf(fp,"%s", !chapter++? "\" chapters=\"" : ","); + int secs = pos, mins = secs/60; + int frms = (pos-secs) * edl->session->frame_rate; + fprintf(fp,"%d:%02d:%02d.%d", mins/60, mins%60, secs%60, frms); +} + +char *DVD_BatchRenderJob::create_script(EDL *edl, ArrayList *idxbls) +{ + char script[BCTEXTLEN]; + strcpy(script, edl_path); + this->edl = edl; + this->fp = 0; + char *bp = strrchr(script,'/'); + int fd = -1; + if( bp ) { + strcpy(bp, "/dvd.sh"); + fd = open(script, O_WRONLY+O_CREAT+O_TRUNC, 0755); + } + if( fd >= 0 ) + fp = fdopen(fd, "w"); + if( !fp ) { + char err[BCTEXTLEN], msg[BCTEXTLEN]; + strerror_r(errno, err, sizeof(err)); + sprintf(msg, _("Unable to save: %s\n-- %s"), script, err); + MainError::show_error(msg); + return 0; + } + + fprintf(fp,"#!/bin/bash\n"); + fprintf(fp,"sdir=`dirname $0`\n"); + fprintf(fp,"dir=`cd \"$sdir\"; pwd`\n"); + fprintf(fp,"echo \"running %s\"\n", script); + fprintf(fp,"\n"); + const char *exec_path = File::get_cinlib_path(); + fprintf(fp,"PATH=$PATH:%s\n",exec_path); + int file_seq = farmed || labeled ? 1 : 0; + if( !muxed ) { + if( file_seq ) { + fprintf(fp, "cat > $dir/dvd.m2v $dir/dvd.m2v0*\n"); + fprintf(fp, "mplex -M -f 8 -o $dir/dvd.mpg $dir/dvd.m2v $dir/dvd.ac3\n"); + file_seq = 0; + } + else + fprintf(fp, "mplex -f 8 -o $dir/dvd.mpg $dir/dvd.m2v $dir/dvd.ac3\n"); + } + fprintf(fp,"rm -rf $dir/iso\n"); + fprintf(fp,"mkdir -p $dir/iso\n"); + fprintf(fp,"\n"); +// dvdauthor ver 0.7.0 requires this to work + int norm = dvd_formats[standard].norm; + const char *name = dvd_norms[norm].name; + fprintf(fp,"export VIDEO_FORMAT=%s\n", name); + fprintf(fp,"dvdauthor -x - <\n"); + fprintf(fp," \n"); + fprintf(fp," jump title 1; \n"); + fprintf(fp," \n"); + fprintf(fp," \n"); + fprintf(fp," \n"); + char std[BCSTRLEN], *cp = std; + for( const char *np=name; *np!=0; ++cp,++np) *cp = *np + 'a'-'A'; + *cp = 0; + EDLSession *session = edl->session; + fprintf(fp," \n"); + fprintf(fp," \n"); + fprintf(fp,"\n"); + fprintf(fp,"eof\n"); + fprintf(fp,"\n"); + fprintf(fp,"echo To burn dvd, load blank media and run:\n"); + fprintf(fp,"echo growisofs -dvd-compat -Z /dev/dvd -dvd-video $dir/iso\n"); + fprintf(fp,"kill $$\n"); + fprintf(fp,"\n"); + fclose(fp); + return cstrdup(script); +} + + CreateDVD_Thread::CreateDVD_Thread(MWindow *mwindow) : BC_DialogThread() { @@ -108,7 +267,8 @@ CreateDVD_Thread::CreateDVD_Thread(MWindow *mwindow) this->use_wide_audio = 0; this->use_ffmpeg = 0; this->use_resize_tracks = 0; - this->use_label_chapters = 0; + this->use_labeled = 0; + this->use_farmed = 0; this->dvd_size = DVD_SIZE; this->dvd_width = DVD_WIDTH; @@ -137,7 +297,6 @@ int CreateDVD_Thread::create_dvd_jobs(ArrayList *jobs, const ch return 1; } EDLSession *session = edl->session; - double total_length = edl->tracks->total_length(); if( total_length <= 0 ) { char msg[BCTEXTLEN]; @@ -168,88 +327,6 @@ int CreateDVD_Thread::create_dvd_jobs(ArrayList *jobs, const ch session->audio_channels = session->audio_tracks = use_wide_audio ? DVD_WIDE_CHANNELS : DVD_CHANNELS; - char script_filename[BCTEXTLEN]; - sprintf(script_filename, "%s/dvd.sh", asset_dir); - int fd = open(script_filename, O_WRONLY+O_CREAT+O_TRUNC, 0755); - FILE *fp = fdopen(fd, "w"); - if( !fp ) { - char err[BCTEXTLEN], msg[BCTEXTLEN]; - strerror_r(errno, err, sizeof(err)); - sprintf(msg, _("Unable to save: %s\n-- %s"), script_filename, err); - MainError::show_error(msg); - return 1; - } - fprintf(fp,"#!/bin/bash\n"); - fprintf(fp,"echo \"running %s\" $# $*\n", script_filename); - fprintf(fp,"\n"); - const char *exec_path = File::get_cinlib_path(); - fprintf(fp,"PATH=$PATH:%s\n",exec_path); - if( mwindow->preferences->use_renderfarm || - (use_label_chapters && edl->labels ) ) { - if( !use_ffmpeg ) { - fprintf(fp, "cat > $1/dvd.m2v $1/dvd.m2v0*\n"); - fprintf(fp, "mplex -M -f 8 -o $1/dvd.mpg $1/dvd.m2v $1/dvd.ac3\n"); - } - else - fprintf(fp, "ffmpeg -f concat -safe 0 -i <(for f in \"$1/dvd.mpg0\"*; do " - "echo \"file '$f'\"; done) -c copy -y $1/dvd.mpg\n"); - } - else - fprintf(fp, "mplex -f 8 -o $1/dvd.mpg $1/dvd.m2v $1/dvd.ac3\n"); - fprintf(fp,"rm -rf $1/iso\n"); - fprintf(fp,"mkdir -p $1/iso\n"); - fprintf(fp,"\n"); -// dvdauthor ver 0.7.0 requires this to work - int norm = dvd_formats[use_standard].norm; - const char *name = dvd_norms[norm].name; - fprintf(fp,"export VIDEO_FORMAT=%s\n", name); - fprintf(fp,"dvdauthor -x - <\n"); - fprintf(fp," \n"); - fprintf(fp," jump title 1; \n"); - fprintf(fp," \n"); - fprintf(fp," \n"); - fprintf(fp," \n"); - char std[BCSTRLEN], *cp = std; - for( const char *np=name; *np!=0; ++cp,++np) *cp = *np + 'a'-'A'; - *cp = 0; - fprintf(fp," \n"); - fprintf(fp," \n"); - fprintf(fp,"\n"); - fprintf(fp,"eof\n"); - fprintf(fp,"\n"); - fprintf(fp,"echo To burn dvd, load blank media and run:\n"); - fprintf(fp,"echo growisofs -dvd-compat -Z /dev/dvd -dvd-video $1/iso\n"); - fprintf(fp,"kill $$\n"); - fprintf(fp,"\n"); - fclose(fp); - session->audio_channels = session->audio_tracks = !use_wide_audio ? DVD_CHANNELS : DVD_WIDE_CHANNELS; for( int i=0; i *jobs, const ch return 1; } - BatchRenderJob *job = new BatchRenderJob(mwindow->preferences, use_label_chapters); + BatchRenderJob *job = new DVD_BatchRenderJob(mwindow->preferences, + use_labeled, use_farmed, use_standard, 0);// use_ffmpeg); jobs->append(job); strcpy(&job->edl_path[0], xml_filename); Asset *asset = job->asset; @@ -300,8 +378,15 @@ int CreateDVD_Thread::create_dvd_jobs(ArrayList *jobs, const ch sprintf(&asset->path[0],"%s/dvd.mpg", asset_dir); asset->format = FILE_FFMPEG; strcpy(asset->fformat, "dvd"); - +// if there are many renderfarm jobs, then there are small audio fragments of +// silence that are used at the end of a render to fill the last audio "block". +// this extra data gradually skews the audio/video sync. Therefore, the audio +// is not rendered muxed for ffmpeg, and is remuxed as with mjpeg rendering. +// since this audio is in one file, the only fragment is at the end and is ok. +#if 0 asset->audio_data = 1; + asset->channels = session->audio_channels; + asset->sample_rate = session->sample_rate; strcpy(asset->acodec, "dvd.dvd"); FFMPEG::set_option_path(option_path, "audio/%s", asset->acodec); FFMPEG::load_options(option_path, asset->ff_audio_options, @@ -315,6 +400,29 @@ int CreateDVD_Thread::create_dvd_jobs(ArrayList *jobs, const ch sizeof(asset->ff_video_options)); asset->ff_video_bitrate = vid_bitrate; asset->ff_video_quality = -1; + use_farmed = job->farmed; +#else + asset->video_data = 1; + strcpy(asset->vcodec, "raw.dvd"); + sprintf(&asset->path[0],"%s/dvd.m2v", asset_dir); + FFMPEG::set_option_path(option_path, "video/%s", asset->vcodec); + FFMPEG::load_options(option_path, asset->ff_video_options, + sizeof(asset->ff_video_options)); + asset->ff_video_bitrate = vid_bitrate; + asset->ff_video_quality = -1; + use_farmed = job->farmed; + + job = new BatchRenderJob(mwindow->preferences, 0, 0); + jobs->append(job); + strcpy(&job->edl_path[0], xml_filename); + asset = job->asset; + sprintf(&asset->path[0],"%s/dvd.ac3", asset_dir); + asset->format = FILE_AC3; + asset->audio_data = 1; + asset->channels = session->audio_channels; + asset->sample_rate = session->sample_rate; + asset->ac3_bitrate = dvd_kaudio_rate; +#endif } else { sprintf(&asset->path[0],"%s/dvd.m2v", asset_dir); @@ -332,6 +440,7 @@ int CreateDVD_Thread::create_dvd_jobs(ArrayList *jobs, const ch asset->vmpeg_preset = 8; asset->vmpeg_field_order = 0; asset->vmpeg_pframe_distance = 0; + use_farmed = job->farmed; job = new BatchRenderJob(mwindow->preferences, 0, 0); jobs->append(job); strcpy(&job->edl_path[0], xml_filename); @@ -350,12 +459,6 @@ int CreateDVD_Thread::create_dvd_jobs(ArrayList *jobs, const ch asset->ac3_bitrate = dvd_kaudio_rate; } - job = new BatchRenderJob(mwindow->preferences, 0, 0); - jobs->append(job); - job->edl_path[0] = '@'; - strcpy(&job->edl_path[1], script_filename); - strcpy(&job->asset->path[0], asset_dir); - return 0; } @@ -444,7 +547,7 @@ void CreateDVD_Thread::handle_close_event(int result) mwindow->resync_guis(); if( ret ) return; mwindow->batch_render->save_jobs(); - mwindow->batch_render->start(); + mwindow->batch_render->start(-use_farmed, -use_labeled); } BC_Window* CreateDVD_Thread::new_gui() @@ -464,7 +567,8 @@ BC_Window* CreateDVD_Thread::new_gui() use_wide_audio = 0; use_ffmpeg = 0; use_resize_tracks = 0; - use_label_chapters = 0; + use_labeled = 0; + use_farmed = 0; use_standard = DVD_NTSC_4x3; dvd_size = DVD_SIZE; @@ -705,7 +809,7 @@ CreateDVD_Histogram::~CreateDVD_Histogram() } CreateDVD_LabelChapters::CreateDVD_LabelChapters(CreateDVD_GUI *gui, int x, int y) - : BC_CheckBox(x, y, &gui->thread->use_label_chapters, _("Chapters at Labels")) + : BC_CheckBox(x, y, &gui->thread->use_labeled, _("Chapters at Labels")) { this->gui = gui; } @@ -714,6 +818,16 @@ CreateDVD_LabelChapters::~CreateDVD_LabelChapters() { } +CreateDVD_UseRenderFarm::CreateDVD_UseRenderFarm(CreateDVD_GUI *gui, int x, int y) + : BC_CheckBox(x, y, &gui->thread->use_farmed, _("Use render farm")) +{ + this->gui = gui; +} + +CreateDVD_UseRenderFarm::~CreateDVD_UseRenderFarm() +{ +} + CreateDVD_WideAudio::CreateDVD_WideAudio(CreateDVD_GUI *gui, int x, int y) : BC_CheckBox(x, y, &gui->thread->use_wide_audio, _("Audio 5.1")) { @@ -755,7 +869,8 @@ CreateDVD_GUI::CreateDVD_GUI(CreateDVD_Thread *thread, int x, int y, int w, int need_resize_tracks = 0; need_histogram = 0; need_wide_audio = 0; - need_label_chapters = 0; + need_labeled = 0; + need_farmed = 0; ok = 0; cancel = 0; } @@ -813,24 +928,30 @@ void CreateDVD_GUI::create_objects() add_subwindow(scale); scale->create_objects(); y += standard->get_h() + pady/2; - need_deinterlace = new CreateDVD_Deinterlace(this, x, y); + x1 = x; int y1 = y; + need_deinterlace = new CreateDVD_Deinterlace(this, x1, y); add_subwindow(need_deinterlace); - x1 = x + 170; - int x2 = x1 + 170; - need_inverse_telecine = new CreateDVD_InverseTelecine(this, x1, y); - add_subwindow(need_inverse_telecine); - need_use_ffmpeg = new CreateDVD_UseFFMpeg(this, x2, y); - add_subwindow(need_use_ffmpeg); y += need_deinterlace->get_h() + pady/2; need_histogram = new CreateDVD_Histogram(this, x, y); add_subwindow(need_histogram); + y = y1; x1 += 170; + need_inverse_telecine = new CreateDVD_InverseTelecine(this, x1, y); + add_subwindow(need_inverse_telecine); + y += need_inverse_telecine->get_h() + pady/2; need_wide_audio = new CreateDVD_WideAudio(this, x1, y); add_subwindow(need_wide_audio); - need_resize_tracks = new CreateDVD_ResizeTracks(this, x2, y); + y += need_wide_audio->get_h() + pady/2; + need_use_ffmpeg = new CreateDVD_UseFFMpeg(this, x1, y); + add_subwindow(need_use_ffmpeg); + y += need_use_ffmpeg->get_h() + pady/2; + need_resize_tracks = new CreateDVD_ResizeTracks(this, x1, y); add_subwindow(need_resize_tracks); - y += need_histogram->get_h() + pady/2; - need_label_chapters = new CreateDVD_LabelChapters(this, x1, y); - add_subwindow(need_label_chapters); + y = y1; x1 += 170; + need_labeled = new CreateDVD_LabelChapters(this, x1, y); + add_subwindow(need_labeled); + y += need_labeled->get_h() + pady/2; + need_farmed = new CreateDVD_UseRenderFarm(this, x1, y); + add_subwindow(need_farmed); ok_w = BC_OKButton::calculate_w(); ok_h = BC_OKButton::calculate_h(); ok_x = 10; @@ -880,7 +1001,8 @@ void CreateDVD_GUI::update() need_resize_tracks->set_value(thread->use_resize_tracks); need_histogram->set_value(thread->use_histogram); need_wide_audio->set_value(thread->use_wide_audio); - need_label_chapters->set_value(thread->use_label_chapters); + need_labeled->set_value(thread->use_labeled); + need_farmed->set_value(thread->use_farmed); } int CreateDVD_Thread:: @@ -928,7 +1050,8 @@ option_presets() use_scale = Rescale::none; use_resize_tracks = 0; use_wide_audio = 0; - use_label_chapters = 0; + use_labeled = 0; + use_farmed = 0; if( !mwindow->edl ) return 1; @@ -994,11 +1117,12 @@ option_presets() } if( !has_deinterlace && max_h > 2*dvd_height ) use_deinterlace = 1; Labels *labels = mwindow->edl->labels; - use_label_chapters = labels && labels->first ? 1 : 0; + use_labeled = labels && labels->first ? 1 : 0; if( tracks->recordable_audio_tracks() == DVD_WIDE_CHANNELS ) use_wide_audio = 1; + use_farmed = mwindow->preferences->use_renderfarm; return 0; }