X-Git-Url: https://git.decadent.org.uk/gitweb/?p=videolink.git;a=blobdiff_plain;f=generate_dvd.cpp;h=5d357e6d39c385fe6eb76a89551bd5c115340e64;hp=398fdd15e1662d6a095ccc0eafb9a74e0e1247b1;hb=3a7baf39d3211c0bda3de1ab2b657e024a35b8af;hpb=ef1488deebfb1a8f84ea4c0c498e50b90b75ff3d diff --git a/generate_dvd.cpp b/generate_dvd.cpp index 398fdd1..5d357e6 100644 --- a/generate_dvd.cpp +++ b/generate_dvd.cpp @@ -1,8 +1,12 @@ // Copyright 2005-6 Ben Hutchings . // See the file "COPYING" for licence details. +#include +#include #include +#include #include +#include #include #include @@ -76,12 +80,31 @@ namespace // We would like to use just a single frame for the menu but this // seems not to be legal or compatible. The minimum length of a // cell is 0.4 seconds but I've seen a static menu using 12 frames - // on a "PAL" disc so let's say 0.5 seconds rounded down. - const char menu_duration_string[] = "0.5"; + // on a commercial "PAL" disc so let's use 12 frames regardless. unsigned menu_duration_frames(const video::frame_params & params) { - return params.rate_numer / params.rate_denom / 2; + return 12; } + double menu_duration_seconds(const video::frame_params & params) + { + return double(menu_duration_frames(params)) + / double(params.rate_numer) + * double(params.rate_denom); + } + + void throw_length_error(const char * limit_type, std::size_t limit) + { + std::ostringstream oss; + oss << "exceeded DVD limit: " << limit_type << " > " << limit; + throw std::length_error(oss.str()); + } + + // dvdauthor uses some menu numbers to represent entry points - + // distinct from the actual numbers of the menus assigned as those + // entry points - resulting in a practical limit of 119 per + // domain. This seems to be an oddity of the parser that could be + // fixed, but for now we'll have to work with it. + const unsigned dvdauthor_anonymous_menus_max = dvd::domain_pgcs_max - 8; } dvd_generator::dvd_generator(const video::frame_params & frame_params, @@ -95,13 +118,8 @@ dvd_generator::pgc_ref dvd_generator::add_menu() { pgc_ref next_menu(menu_pgc, menus_.size()); - // Check against maximum number of menus. It appears that no more - // than 128 menus are reachable through LinkPGCN instructions, and - // dvdauthor uses some menu numbers for special purposes, resulting - // in a practical limit of 119 per domain. We can work around this - // later by spreading some menus across titlesets. - if (next_menu.index == 119) - throw std::runtime_error("No more than 119 menus can be used"); + if (next_menu.index == dvdauthor_anonymous_menus_max) + throw_length_error("number of menus", dvdauthor_anonymous_menus_max); menus_.resize(next_menu.index + 1); return next_menu; @@ -114,6 +132,10 @@ void dvd_generator::add_menu_entry(unsigned index, assert(index < menus_.size()); assert(target.type == menu_pgc && target.index < menus_.size() || target.type == title_pgc && target.index < titles_.size()); + + if (menus_[index].entries.size() == dvd::menu_buttons_max) + throw_length_error("number of buttons", dvd::menu_buttons_max); + menu_entry new_entry = { area, target }; menus_[index].entries.push_back(new_entry); } @@ -212,7 +234,10 @@ void dvd_generator::generate_menu_vob(unsigned index, std::string("symlink: ").append(std::strerror(errno))); } command_stream << - "ffmpeg -f image2 -vcodec png -i " << background_name << "-%02d" + "ffmpeg -f image2 -vcodec png" + " -r " << frame_params_.rate_numer << + "/" << frame_params_.rate_denom << + " -i " << background_name << "-%02d" " -target " << frame_params_.common_name << "-dvd" " -vcodec mpeg2video -aspect 4:3 -an -y /dev/stdout"; } @@ -264,8 +289,8 @@ dvd_generator::pgc_ref dvd_generator::add_title(vob_list & content) pgc_ref next_title(title_pgc, titles_.size()); // Check against maximum number of titles. - if (next_title.index == 99) - throw std::runtime_error("No more than 99 titles can be used"); + if (next_title.index == dvd::titles_max) + throw_length_error("number of titles", dvd::titles_max); titles_.resize(next_title.index + 1); titles_[next_title.index].swap(content); @@ -373,7 +398,9 @@ void dvd_generator::generate(const std::string & output_dir) const // Define a cell covering the whole menu and set a still // time at the end of that, since it seems all players // support that but some ignore a still time set on a PGC. - " \n" " \n";