-// Copyright 2005-6 Ben Hutchings <ben@decadent.org.uk>.
+// Copyright 2005-8 Ben Hutchings <ben@decadent.org.uk>.
// See the file "COPYING" for licence details.
#include <cerrno>
#include <sstream>
#include <stdexcept>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
#include <gdkmm/pixbuf.h>
#include <glibmm/miscutils.h>
#include <glibmm/spawn.h>
}
}
}
+ // Pad vertically to even y coordinates since dvdauthor claims
+ // odd values may result in incorrect display.
+ // XXX This may cause overlappping where it wasn't previously
+ // a problem.
spumux_file << " <button"
" x0='" << this_entry.area.left << "'"
- " y0='" << this_entry.area.top << "'"
+ " y0='" << (this_entry.area.top & ~1) << "'"
" x1='" << this_entry.area.right << "'"
- " y1='" << this_entry.area.bottom << "'"
+ " y1='" << ((this_entry.area.bottom + 1) & ~1) << "'"
" left='" << (i == 0 ? button_count : i) << "'"
" right='" << 1 + (i + 1) % button_count << "'"
" up='" << 1 + up_button << "'"
if (!spumux_file)
throw std::runtime_error("Failed to write control file for spumux");
+ std::string output_name(
+ temp_file_name(temp_dir_, "menu-%3d.mpeg", 1 + index));
+
std::ostringstream command_stream;
- unsigned frame_count(menu_duration_frames(frame_params_));
if (encoder_ == mpeg_encoder_ffmpeg)
{
- for (unsigned i = 0; i != frame_count; ++i)
- {
- std::string frame_name(background_name);
- frame_name.push_back('-');
- frame_name.push_back('0' + i / 10);
- frame_name.push_back('0' + i % 10);
- if (symlink(background_name.c_str(), frame_name.c_str()) != 0)
- throw std::runtime_error(
- std::string("symlink: ").append(std::strerror(errno)));
- }
command_stream <<
"ffmpeg -f image2 -vcodec png"
" -r " << frame_params_.rate_numer <<
"/" << frame_params_.rate_denom <<
- " -i " << background_name << "-%02d"
+ " -i " << background_name <<
+ " -loop_input -t " << menu_duration_seconds(frame_params_) <<
" -target " << frame_params_.common_name << "-dvd"
" -vcodec mpeg2video -aspect 4:3 -an -y /dev/stdout";
}
else
{
- assert(encoder_ == mpeg_encoder_mjpegtools_old
- || encoder_ == mpeg_encoder_mjpegtools_new);
+ assert(encoder_ == mpeg_encoder_mjpegtools);
command_stream
<< "pngtopnm " << background_name
- << " | ppmtoy4m -v0 -n" << frame_count << " -F"
- << frame_params_.rate_numer << ":" << frame_params_.rate_denom
+ << " | ppmtoy4m -v0 -n" << menu_duration_frames(frame_params_)
+ << " -F" << frame_params_.rate_numer << ":" << frame_params_.rate_denom
<< " -A" << frame_params_.pixel_ratio_width
<< ":" << frame_params_.pixel_ratio_height
- << " -Ip ";
- // The chroma subsampling keywords changed between
- // versions 1.6.2 and 1.8 of mjpegtools. There is no
- // keyword that works with both.
- if (encoder_ == mpeg_encoder_mjpegtools_old)
- command_stream << "-S420_mpeg2";
- else
- command_stream << "-S420mpeg2";
- command_stream <<
+ << " -Ip -S420mpeg2"
" | mpeg2enc -v0 -f8 -a2 -o/dev/stdout"
" | mplex -v0 -f8 -o/dev/stdout /dev/stdin";
}
command_stream
- << " | spumux -v0 -mdvd " << spumux_name
- << " > " << temp_file_name(temp_dir_, "menu-%3d.mpeg", 1 + index);
+ << " | spumux -v0 -mdvd " << spumux_name << " > " << output_name;
std::string command(command_stream.str());
const char * argv[] = {
"/bin/sh", "-c", command.c_str(), 0
sigc::slot<void>(),
0, 0,
&command_result);
- if (command_result != 0)
+ struct stat stat_buf;
+ if (command_result != 0 || stat(output_name.c_str(), &stat_buf) != 0
+ || stat_buf.st_size == 0)
throw std::runtime_error("spumux pipeline failed");
}
const unsigned menu_begin = titleset_num * dvdauthor_anonymous_menus_max;
const unsigned menu_end =
have_real_menus
- ? std::min((titleset_num + 1) * dvdauthor_anonymous_menus_max,
- menus_.size())
+ ? std::min<unsigned>(
+ (titleset_num + 1) * dvdauthor_anonymous_menus_max,
+ menus_.size())
: menu_begin + 1;
for (unsigned menu_index = menu_begin;