X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fbdcreate.C;h=27f728ad6dc80c1a21d20723d5eec697edf30a34;hp=e559a24e0a4afa93e6937e9fed1a8f2e47678791;hb=HEAD;hpb=21c2e6b36d6a96c2f662a89459d607b5a387f4eb diff --git a/cinelerra-5.1/cinelerra/bdcreate.C b/cinelerra-5.1/cinelerra/bdcreate.C index e559a24e..27f728ad 100644 --- a/cinelerra-5.1/cinelerra/bdcreate.C +++ b/cinelerra-5.1/cinelerra/bdcreate.C @@ -1,4 +1,5 @@ #include "asset.h" +#include "bchash.h" #include "bdcreate.h" #include "clip.h" #include "edl.h" @@ -7,6 +8,7 @@ #include "edlsession.h" #include "file.h" #include "filexml.h" +#include "interlacemodes.h" #include "keyframe.h" #include "labels.h" #include "mainerror.h" @@ -15,6 +17,7 @@ #include "mwindowgui.h" #include "plugin.h" #include "pluginset.h" +#include "preferences.h" #include "rescale.h" #include "track.h" #include "tracks.h" @@ -27,33 +30,34 @@ // BD Creation +// selected by timezone #define BD_1920x1080_2997i 0 -#define BD_1920x1080_2500i 1 -#define BD_1920x1080_2400p 2 -#define BD_1920x1080_23976p 3 -#define BD_1280x720_5994p 4 -#define BD_1280x720_5000p 5 -#define BD_1280x720_23976p 6 -#define BD_1280x720_2400p 7 -#define BD_720x576_2500i 8 -#define BD_720x480_2997i 9 +#define BD_1920x1080_25i 3 static struct bd_format { const char *name; int w, h; double framerate; - int interlaced, wide; + int wide, interlaced; } bd_formats[] = { - { "1920x1080 29.97i", 1920,1080, 29.97, 1, 1 }, - { "1920x1080 25i", 1920,1080, 25., 1, 1 }, - { "1920x1080 24p", 1920,1080, 24., 0, 1 }, - { "1920x1080 23.976p", 1920,1080, 23.976, 0, 1 }, - { "1280x720 59.94p", 1280,720, 59.94, 0, 1 }, - { "1280x720 50p", 1280,720, 50., 0, 1 }, - { "1280x720 23.976p", 1280,720, 23.976, 0, 1 }, - { "1280x720 24p", 1280,720, 24., 0, 1 }, - { "720x576 25i", 720,576, 25., 1, 0 }, - { "720x480 29.97i", 720,480, 29.97, 1, 0 }, +// framerates are frames, not fields, per second, *=not standard + { "1920x1080 29.97i", 1920,1080, 29.97, 1, ILACE_MODE_TOP_FIRST }, + { "1920x1080 29.97p*", 1920,1080, 29.97, 1, ILACE_MODE_NOTINTERLACED }, + { "1920x1080 24p", 1920,1080, 24., 1, ILACE_MODE_NOTINTERLACED }, + { "1920x1080 25i", 1920,1080, 25., 1, ILACE_MODE_TOP_FIRST }, + { "1920x1080 23.976p", 1920,1080, 23.976, 1, ILACE_MODE_NOTINTERLACED }, + { "1440x1080 29.97i", 1440,1080, 29.97, -1, ILACE_MODE_TOP_FIRST }, + { "1440x1080 25i", 1440,1080, 25., -1, ILACE_MODE_TOP_FIRST }, + { "1440x1080 24p", 1440,1080, 24., -1, ILACE_MODE_NOTINTERLACED }, + { "1440x1080 23.976p", 1440,1080, 23.976,-1, ILACE_MODE_NOTINTERLACED }, + { "1280x720 59.94p", 1280,720, 59.94, 1, ILACE_MODE_NOTINTERLACED }, + { "1280x720 50p", 1280,720, 50., 1, ILACE_MODE_NOTINTERLACED }, + { "1280x720 24p", 1280,720, 24., 1, ILACE_MODE_NOTINTERLACED }, + { "1280x720 23.976p", 1280,720, 23.976, 1, ILACE_MODE_NOTINTERLACED }, + { "720x576 25i", 720,576, 25., 0, ILACE_MODE_BOTTOM_FIRST }, + { "720x576 25p*", 720,576, 25., 0, ILACE_MODE_NOTINTERLACED }, + { "720x480 29.97i", 720,480, 29.97, 0, ILACE_MODE_BOTTOM_FIRST }, + { "720x480 29.97p*", 720,480, 29.97, 0, ILACE_MODE_NOTINTERLACED }, }; const int64_t CreateBD_Thread::BD_SIZE = 25000000000; @@ -66,11 +70,12 @@ const double CreateBD_Thread::BD_ASPECT_WIDTH = 4.; const double CreateBD_Thread::BD_ASPECT_HEIGHT = 3.; const double CreateBD_Thread::BD_FRAMERATE = 24000. / 1001.; //const int CreateBD_Thread::BD_MAX_BITRATE = 40000000; -const int CreateBD_Thread::BD_MAX_BITRATE = 8000000; +const int CreateBD_Thread::BD_MAX_BITRATE = 10000000; const int CreateBD_Thread::BD_CHANNELS = 2; const int CreateBD_Thread::BD_WIDE_CHANNELS = 6; const double CreateBD_Thread::BD_SAMPLERATE = 48000; -const double CreateBD_Thread::BD_KAUDIO_RATE = 224; +const double CreateBD_Thread::BD_KAUDIO_RATE = 192; +const int CreateBD_Thread::BD_INTERLACE_MODE = ILACE_MODE_NOTINTERLACED; CreateBD_MenuItem::CreateBD_MenuItem(MWindow *mwindow) : BC_MenuItem(_("BD Render..."), _("Ctrl-d"), 'd') @@ -116,8 +121,53 @@ CreateBD_Thread::~CreateBD_Thread() close_window(); } -int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, - const char *tmp_path, const char *asset_title) +int CreateBD_Thread::get_udfs_mount(char *udfs, char *mopts, char *mntpt) +{ + int ret = 0; +// default: mount -t udf -o loop $1/bd.udfs $1/udfs + strcpy(udfs,"$1/bd.udfs"); + strcpy(mopts,"-t udf -o loop $1/bd.udfs "); + strcpy(mntpt,"$1/udfs"); + const char *home = getenv("HOME"); + if( !home ) return ret; + FILE *fp = fopen("/etc/fstab","r"); + if( !fp ) return ret; + int len = strlen(home); + char line[BCTEXTLEN], typ[BCTEXTLEN], file[BCTEXTLEN]; + char mpnt[BCTEXTLEN], opts[BCTEXTLEN]; + while( fgets(line,sizeof(line),fp) ) { +// search "/etc/fstab" for: $HOME/img_file $HOME/bluray udf noauto,loop,rw,user + if( line[0] == '#' || line[0] == ';' ) continue; + if( sscanf(line,"%s %s %s %s ", &file[0], &mpnt[0], &typ[0], &opts[0]) != 4 ) + continue; + if( strcmp("udf", typ) ) continue; + if( strncmp(home, file, len) || file[len] != '/' ) continue; + if( strncmp(home, mpnt, len) ) continue; + if( strcmp(&mpnt[len], "/bluray") ) continue; + int loop = 0, user = 0, rw = 0, noauto = 0; + char *op = opts, *ep = op + sizeof(opts)-1; + while( op < ep && *op ) { + char opt[BCTEXTLEN], *cp = opt; + while( op < ep && *op && (*cp=*op++)!=',' ) ++cp; + *cp = 0; + if( !strcmp("loop", opt) ) loop = 1; + else if( !strcmp("user", opt) ) user = 1; + else if( !strcmp("noauto", opt) ) noauto = 1; + else if( !strcmp("rw", opt) ) rw = 1; + } + if( loop && user && rw && noauto ) { + strcpy(udfs, file); + strcpy(mopts, ""); + strcpy(mntpt, mpnt); + ret = 1; + break; + } + } + fclose(fp); + return ret; +} + +int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, const char *asset_dir) { EDL *edl = mwindow->edl; if( !edl || !edl->session ) { @@ -136,9 +186,6 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, return 1; } - char asset_dir[BCTEXTLEN]; - sprintf(asset_dir, "%s/%s", tmp_path, asset_title); - if( mkdir(asset_dir, 0777) ) { char err[BCTEXTLEN], msg[BCTEXTLEN]; strerror_r(errno, err, sizeof(err)); @@ -160,6 +207,7 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, session->sample_rate = bd_samplerate; session->audio_channels = session->audio_tracks = use_wide_audio ? BD_WIDE_CHANNELS : BD_CHANNELS; + session->interlace_mode = bd_interlace_mode; char script_filename[BCTEXTLEN]; sprintf(script_filename, "%s/bd.sh", asset_dir); @@ -172,43 +220,39 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, MainError::show_error(msg); return 1; } + char udfs[BCTEXTLEN], mopts[BCTEXTLEN], mntpt[BCTEXTLEN]; + int is_usr_mnt = get_udfs_mount(udfs, mopts, mntpt); const char *exec_path = File::get_cinlib_path(); fprintf(fp,"#!/bin/bash -ex\n"); fprintf(fp,"PATH=$PATH:%s\n",exec_path); fprintf(fp,"mkdir -p $1/udfs\n"); - fprintf(fp,"sz=`du -sb $1/bd.m2ts | sed -e 's/[ \t].*//'`\n"); + fprintf(fp,"sz=`du -cb $1/bd.m2ts* | tail -1 | sed -e 's/[ \t].*//'`\n"); fprintf(fp,"blks=$((sz/2048 + 4096))\n"); - fprintf(fp,"mkudffs $1/bd.udfs $blks\n"); - fprintf(fp,"mount -o loop $1/bd.udfs $1/udfs\n"); - fprintf(fp,"bdwrite $1/udfs $1/bd.m2ts\n"); - fprintf(fp,"umount $1/udfs\n"); + fprintf(fp,"rm -f %s\n", udfs); + fprintf(fp,"mkudffs -b 2048 %s $blks\n", udfs); + fprintf(fp,"mount %s%s\n", mopts, mntpt); + fprintf(fp,"bdwrite %s $1/bd.m2ts*\n",mntpt); + fprintf(fp,"umount %s\n",mntpt); + if( is_usr_mnt ) + fprintf(fp,"mv -f %s $1/bd.udfs\n", udfs); fprintf(fp,"echo To burn bluray, load writable media and run:\n"); fprintf(fp,"echo for WORM: growisofs -dvd-compat -Z /dev/bd=$1/bd.udfs\n"); fprintf(fp,"echo for RW: dd if=$1/bd.udfs of=/dev/bd bs=2048000\n"); + fprintf(fp,"kill $$\n"); fprintf(fp,"\n"); fclose(fp); - if( use_wide_audio ) { - session->audio_channels = session->audio_tracks = BD_WIDE_CHANNELS; - session->achannel_positions[0] = 90; - session->achannel_positions[1] = 150; - session->achannel_positions[2] = 30; - session->achannel_positions[3] = 210; - session->achannel_positions[4] = 330; - session->achannel_positions[5] = 270; - if( edl->tracks->recordable_audio_tracks() == BD_WIDE_CHANNELS ) - mwindow->remap_audio(MWindow::AUDIO_1_TO_1); - } - else { - session->audio_channels = session->audio_tracks = BD_CHANNELS; - session->achannel_positions[0] = 180; - session->achannel_positions[1] = 0; - if( edl->tracks->recordable_audio_tracks() == BD_WIDE_CHANNELS ) - mwindow->remap_audio(MWindow::AUDIO_5_1_TO_2); - } + session->audio_channels = session->audio_tracks = + !use_wide_audio ? BD_CHANNELS : BD_WIDE_CHANNELS; + for( int i=0; iachannel_positions[i] = default_audio_channel_position(i, session->audio_channels); + int audio_mapping = edl->tracks->recordable_audio_tracks() == BD_WIDE_CHANNELS && + !use_wide_audio ? MWindow::AUDIO_5_1_TO_2 : MWindow::AUDIO_1_TO_1; + mwindow->remap_audio(audio_mapping); double new_samplerate = session->sample_rate; double new_framerate = session->frame_rate; + edl->retrack(); edl->rechannel(); edl->resample(old_samplerate, new_samplerate, TRACK_AUDIO); edl->resample(old_framerate, new_framerate, TRACK_VIDEO); @@ -222,7 +266,7 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, char xml_filename[BCTEXTLEN]; sprintf(xml_filename, "%s/bd.xml", asset_dir); FileXML xml_file; - edl->save_xml(&xml_file, xml_filename, 0, 0); + edl->save_xml(&xml_file, xml_filename); xml_file.terminate_string(); if( xml_file.write_to_file(xml_filename) ) { char msg[BCTEXTLEN]; @@ -231,7 +275,7 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, return 1; } - BatchRenderJob *job = new BatchRenderJob(mwindow->preferences); + BatchRenderJob *job = new BatchRenderJob(mwindow->preferences, use_label_chapters); jobs->append(job); strcpy(&job->edl_path[0], xml_filename); Asset *asset = job->asset; @@ -241,6 +285,7 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, asset->width = session->output_w; asset->height = session->output_h; asset->aspect_ratio = session->aspect_w / session->aspect_h; + asset->interlace_mode = session->interlace_mode; char option_path[BCTEXTLEN]; sprintf(&asset->path[0],"%s/bd.m2ts", asset_dir); @@ -249,6 +294,7 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, asset->audio_data = 1; strcpy(asset->acodec, "bluray.m2ts"); + //mwindow->defaults->get("DEFAULT_BLURAY_ACODEC", asset->acodec); FFMPEG::set_option_path(option_path, "audio/%s", asset->acodec); FFMPEG::load_options(option_path, asset->ff_audio_options, sizeof(asset->ff_audio_options)); @@ -256,13 +302,24 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, asset->video_data = 1; strcpy(asset->vcodec, "bluray.m2ts"); + //mwindow->defaults->get("DEFAULT_BLURAY_VCODEC", asset->vcodec); FFMPEG::set_option_path(option_path, "video/%s", asset->vcodec); FFMPEG::load_options(option_path, asset->ff_video_options, sizeof(asset->ff_video_options)); + const char *opts = 0; + switch( asset->interlace_mode ) { + case ILACE_MODE_TOP_FIRST: opts = ":tff\n"; break; + case ILACE_MODE_BOTTOM_FIRST: opts = ":bff\n"; break; + } + if( opts ) { + int len = strlen(asset->ff_video_options); + char *cp = asset->ff_video_options + len-1; + strncpy(cp, opts, sizeof(asset->ff_video_options)-len); + } asset->ff_video_bitrate = vid_bitrate; - asset->ff_video_quality = 0; + asset->ff_video_quality = -1; - job = new BatchRenderJob(mwindow->preferences); + job = new BatchRenderJob(mwindow->preferences, 0, 0); jobs->append(job); job->edl_path[0] = '@'; strcpy(&job->edl_path[1], script_filename); @@ -274,6 +331,7 @@ int CreateBD_Thread::create_bd_jobs(ArrayList *jobs, void CreateBD_Thread::handle_close_event(int result) { if( result ) return; + mwindow->defaults->update("WORK_DIRECTORY", tmp_path); mwindow->batch_render->load_defaults(mwindow->defaults); mwindow->undo->update_undo_before(); KeyFrame keyframe; char data[BCTEXTLEN]; @@ -318,6 +376,7 @@ void CreateBD_Thread::handle_close_event(int result) edit->startproject, edit->length, PLUGIN_STANDALONE, 0, &keyframe, 0); } + vtrk->optimize(); } } if( use_resize_tracks ) @@ -344,19 +403,23 @@ void CreateBD_Thread::handle_close_event(int result) keyframe.set_data(data); insert_video_plugin("Histogram", &keyframe); } - mwindow->batch_render->reset(1); - create_bd_jobs(&mwindow->batch_render->jobs, tmp_path, asset_title); - mwindow->save_backup(); + + char asset_dir[BCTEXTLEN], jobs_path[BCTEXTLEN]; + snprintf(asset_dir, sizeof(asset_dir), "%s/%s", tmp_path, asset_title); + snprintf(jobs_path, sizeof(jobs_path), "%s/bd.jobs", asset_dir); + mwindow->batch_render->reset(jobs_path); + int ret = create_bd_jobs(&mwindow->batch_render->jobs, asset_dir); mwindow->undo->update_undo_after(_("create bd"), LOAD_ALL); mwindow->resync_guis(); - mwindow->batch_render->handle_close_event(0); + if( ret ) return; + mwindow->batch_render->save_jobs(); mwindow->batch_render->start(); } BC_Window* CreateBD_Thread::new_gui() { - memset(tmp_path,0,sizeof(tmp_path)); - strcpy(tmp_path,"/tmp"); + strcpy(tmp_path, "/tmp"); + mwindow->defaults->get("WORK_DIRECTORY", tmp_path); memset(asset_title,0,sizeof(asset_title)); time_t dt; time(&dt); struct tm dtm; localtime_r(&dt, &dtm); @@ -370,8 +433,8 @@ BC_Window* CreateBD_Thread::new_gui() use_wide_audio = 0; use_resize_tracks = 0; use_label_chapters = 0; - use_standard = BD_1920x1080_2997i; - + use_standard = !strcmp(mwindow->default_std(),"NTSC") ? + BD_1920x1080_2997i : BD_1920x1080_25i; bd_size = BD_SIZE; bd_width = BD_WIDTH; bd_height = BD_HEIGHT; @@ -381,6 +444,7 @@ BC_Window* CreateBD_Thread::new_gui() bd_samplerate = BD_SAMPLERATE; bd_max_bitrate = BD_MAX_BITRATE; bd_kaudio_rate = BD_KAUDIO_RATE; + bd_interlace_mode = BD_INTERLACE_MODE; max_w = 0; max_h = 0; int has_standard = -1; @@ -406,6 +470,12 @@ BC_Window* CreateBD_Thread::new_gui() gui = new CreateBD_GUI(this, x, y, w, h); gui->create_objects(); + + if( getuid() != 0 ) { + mwindow->show_warning( + &mwindow->preferences->bd_warn_root, + _("Must be root to mount UDFS images\n")); + } return gui; } @@ -468,7 +538,7 @@ CreateBD_DiskSpace::~CreateBD_DiskSpace() int64_t CreateBD_DiskSpace::tmp_path_space() { - const char *path = gui->tmp_path->get_text(); + const char *path = gui->thread->tmp_path; if( access(path,R_OK+W_OK) ) return 0; struct statfs sfs; if( statfs(path, &sfs) ) return 0; @@ -509,13 +579,15 @@ CreateBD_TmpPath::~CreateBD_TmpPath() int CreateBD_TmpPath::handle_event() { + get_text(); gui->disk_space->update(); return 1; } CreateBD_AssetTitle::CreateBD_AssetTitle(CreateBD_GUI *gui, int x, int y, int w) - : BC_TextBox(x, y, w, 1, 0, gui->thread->asset_title, 1, MEDIUMFONT) + : BC_TextBox(x, y, w, 1, -(int)sizeof(gui->thread->asset_title), + gui->thread->asset_title, 1, MEDIUMFONT) { this->gui = gui; } @@ -524,6 +596,11 @@ CreateBD_AssetTitle::~CreateBD_AssetTitle() { } +int CreateBD_AssetTitle::handle_event() +{ + get_text(); + return 1; +} CreateBD_Deinterlace::CreateBD_Deinterlace(CreateBD_GUI *gui, int x, int y) : BC_CheckBox(x, y, &gui->thread->use_deinterlace, _("Deinterlace")) @@ -624,6 +701,7 @@ CreateBD_GUI::CreateBD_GUI(CreateBD_Thread *thread, int x, int y, int w, int h) need_inverse_telecine = 0; need_resize_tracks = 0; need_histogram = 0; + non_standard = 0; need_wide_audio = 0; need_label_chapters = 0; ok = 0; @@ -675,6 +753,7 @@ void CreateBD_GUI::create_objects() standard = new CreateBD_Format(this, title->get_w() + padx, y); add_subwindow(standard); standard->create_objects(); + standard->set_text(bd_formats[thread->use_standard].name); x0 -= 30; title = new BC_Title(x0, y, _("Scale:"), MEDIUMFONT, YELLOW); add_subwindow(title); @@ -694,6 +773,8 @@ void CreateBD_GUI::create_objects() need_wide_audio = new CreateBD_WideAudio(this, x1, y); add_subwindow(need_wide_audio); y += need_histogram->get_h() + pady/2; + non_standard = new BC_Title(x, y+5, "", MEDIUMFONT, RED); + add_subwindow(non_standard); need_resize_tracks = new CreateBD_ResizeTracks(this, x1, y); add_subwindow(need_resize_tracks); // need_label_chapters = new CreateBD_LabelChapters(this, x2, y); @@ -765,6 +846,7 @@ insert_video_plugin(const char *title, KeyFrame *default_keyframe) edit->startproject, edit->length, PLUGIN_STANDALONE, 0, default_keyframe, 0); } + vtrk->optimize(); } return 0; } @@ -800,10 +882,12 @@ option_presets() bd_width = bd_formats[use_standard].w; bd_height = bd_formats[use_standard].h; bd_framerate = bd_formats[use_standard].framerate; - bd_aspect_width = bd_formats[use_standard].wide ? - BD_WIDE_ASPECT_WIDTH : BD_ASPECT_WIDTH; - bd_aspect_height = bd_formats[use_standard].wide ? - BD_WIDE_ASPECT_HEIGHT : BD_ASPECT_HEIGHT; + int wide = bd_formats[use_standard].wide; + bd_aspect_width = wide < 0 ? 1. : + wide > 0 ? BD_WIDE_ASPECT_WIDTH : BD_ASPECT_WIDTH; + bd_aspect_height = wide < 0 ? 1. : + wide > 0 ? BD_WIDE_ASPECT_HEIGHT : BD_ASPECT_HEIGHT; + bd_interlace_mode = bd_formats[use_standard].interlaced; double bd_aspect = bd_aspect_width / bd_aspect_height; Tracks *tracks = mwindow->edl->tracks; @@ -826,17 +910,17 @@ option_presets() float aw, ah; MWindow::create_aspect_ratio(aw, ah, w, h); double aspect = ah > 0 ? aw / ah : 1; - if( !EQUIV(aspect, bd_aspect) ) use_scale = Rescale::scaled; + if( wide >= 0 && !EQUIV(aspect, bd_aspect) ) + use_scale = Rescale::scaled; } for( int i=0; iplugin_set.size(); ++i ) { - for(Plugin *plugin = (Plugin*)trk->plugin_set[i]->first; - plugin; - plugin = (Plugin*)plugin->next) { - if( !strcmp(plugin->title, _("Deinterlace")) ) + for( Plugin *plugin = (Plugin*)trk->plugin_set[i]->first; + plugin; plugin=(Plugin*)plugin->next ) { + if( !strcmp(plugin->title, "Deinterlace") ) has_deinterlace = 1; - if( !strcmp(plugin->title, _("Auto Scale")) || - !strcmp(plugin->title, _("Scale Ratio")) || - !strcmp(plugin->title, _("Scale")) ) + if( !strcmp(plugin->title, "Auto Scale") || + !strcmp(plugin->title, "Scale Ratio") || + !strcmp(plugin->title, "Scale") ) has_scale = 1; } } @@ -883,8 +967,20 @@ CreateBD_FormatItem::~CreateBD_FormatItem() int CreateBD_FormatItem::handle_event() { - popup->set_text(get_text()); + const char *text = get_text(); + int standard = this->standard; + if( standard < 0 ) { + BC_SubMenu *submenu = get_submenu(); + CreateBD_FormatItem *sub_item0 = + (CreateBD_FormatItem *)submenu->get_item(0); + standard = sub_item0->standard; + text = sub_item0->get_text(); + } popup->gui->thread->use_standard = standard; + popup->set_text(text); + int n = strlen(text)-1; + int not_standard = n >= 0 && text[n] == '*' ? 1 : 0; + popup->gui->non_standard->update(not_standard ? _("* non-standard format") : "", 0); return popup->handle_event(); } @@ -901,10 +997,19 @@ CreateBD_Format::~CreateBD_Format() void CreateBD_Format::create_objects() { + BC_SubMenu *submenu = 0; + CreateBD_FormatItem *item = 0; + int ww = 0, hh = 0; for( int i=0; i<(int)(sizeof(bd_formats)/sizeof(bd_formats[0])); ++i ) { - add_item(new CreateBD_FormatItem(this, i, bd_formats[i].name)); + if( ww != bd_formats[i].w || hh != bd_formats[i].h ) { + ww = bd_formats[i].w; hh = bd_formats[i].h; + char string[BCSTRLEN]; + sprintf(string, "%dx%d", ww,hh); + add_item(item = new CreateBD_FormatItem(this, -1, string)); + item->add_submenu(submenu = new BC_SubMenu()); + } + submenu->add_submenuitem(new CreateBD_FormatItem(this, i, bd_formats[i].name)); } - set_value(gui->thread->use_standard); } int CreateBD_Format::handle_event()