From: Carl Hetherington Date: Mon, 2 Jun 2014 11:06:20 +0000 (+0100) Subject: Merge master. X-Git-Tag: v2.0.48~805 X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=3574212ee42b2bd924eb95d5c0f4f69ec9e0a2f0 Merge master. --- 3574212ee42b2bd924eb95d5c0f4f69ec9e0a2f0 diff --cc ChangeLog index 6f31dd5d2,bd7ec7c62..e31fc719e --- a/ChangeLog +++ b/ChangeLog @@@ -1,7 -1,60 +1,64 @@@ +2014-03-07 Carl Hetherington + + * Add subtitle view. + + 2014-05-29 Carl Hetherington + + * Version 1.69.18 released. + + 2014-05-28 Carl Hetherington + + * Version 1.69.17 released. + + 2014-05-28 Carl Hetherington + + * Version 1.69.16 released. + + 2014-05-28 Carl Hetherington + + * Rework KDM generation to be about CPLs rather than DCPs, + and allow specification of any CPL to generate KDMs for. + + Requested-by: Richard Turner + + 2014-05-27 Carl Hetherington + + * Version 1.69.15 released. + + 2014-05-26 Carl Hetherington + + * Version 1.69.14 released. + + 2014-05-26 Carl Hetherington + + * Fix problems with non-zero FFmpeg content start times. + + 2014-05-24 Carl Hetherington + + * Version 1.69.13 released. + + 2014-05-24 Carl Hetherington + + * Fix problems with log setup from config. + + 2014-05-23 Carl Hetherington + + * Version 1.69.12 released. + + 2014-05-22 Carl Hetherington + + * Version 1.69.11 released. + + 2014-05-21 Carl Hetherington + + * Version 1.69.10 released. + + 2014-05-21 Carl Hetherington + + * Tidy up logging a bit and make it configurable from the GUI + (moving a few things into an Advanced preferences tab at + the same time). + 2014-05-19 Carl Hetherington * Version 1.69.9 released. diff --cc src/lib/content.h index 1d3764c20,596a0a905..6bbf33b35 --- a/src/lib/content.h +++ b/src/lib/content.h @@@ -138,6 -129,8 +138,10 @@@ public _change_signals_frequent = f; } - bool trimmed (Time) const; ++ boost::shared_ptr film () const { ++ return _film.lock (); ++ } + boost::signals2::signal, int, bool)> Changed; protected: diff --cc src/lib/decoder.h index 0ec73ba91,d67592ed8..18f612e53 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@@ -27,11 -27,8 +27,10 @@@ #include #include #include +#include "types.h" +#include "dcpomatic_time.h" -class Film; +class Decoded; - class Film; /** @class Decoder. * @brief Parent class for decoders of content. diff --cc src/lib/encoder.cc index 2364b67a7,e83ac70f5..5dc9e47c7 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@@ -209,15 -214,16 +212,15 @@@ Encoder::process_video (shared_ptr ( new DCPVideoFrame ( - pvf, _video_frames_out, _film->video_frame_rate(), - _film->j2k_bandwidth(), _film->resolution(), _film->log() + pvf, + _video_frames_out, + _film->video_frame_rate(), + _film->j2k_bandwidth(), + _film->resolution(), + _film->log() ) )); diff --cc src/lib/ffmpeg_content.cc index 2b507ab37,41a3724a2..9889d511c --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@@ -166,14 -166,14 +168,14 @@@ FFmpegContent::examine (shared_ptr film = _film.lock (); - assert (film); - shared_ptr examiner (new FFmpegExaminer (shared_from_this ())); + take_from_video_examiner (examiner); + + ContentTime video_length = examiner->video_length (); - VideoContent::Frame video_length = 0; - video_length = examiner->video_length (); - LOG_GENERAL ("Video length obtained from header as %1 frames", video_length); + shared_ptr film = _film.lock (); + assert (film); - film->log()->log (String::compose ("Video length obtained from header as %1 frames", video_length.frames (video_frame_rate ()))); ++ LOG_GENERAL ("Video length obtained from header as %1 frames", video_length.frames (video_frame_rate ())); { boost::mutex::scoped_lock lm (_mutex); diff --cc src/lib/ffmpeg_decoder.cc index d668deb6f,5fe34ce14..0dae2a4ed --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@@ -44,9 -43,13 +44,14 @@@ extern "C" #include "audio_buffers.h" #include "ffmpeg_content.h" #include "image_proxy.h" ++#include "film.h" #include "i18n.h" -#define LOG_GENERAL(...) film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL); -#define LOG_ERROR(...) film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_ERROR); -#define LOG_WARNING(...) film->log()->log (__VA_ARGS__, Log::TYPE_WARNING); ++#define LOG_GENERAL(...) _video_content->film()->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL); ++#define LOG_ERROR(...) _video_content->film()->log()->log (String::compose (__VA_ARGS__), Log::TYPE_ERROR); ++#define LOG_WARNING(...) _video_content->film()->log()->log (__VA_ARGS__, Log::TYPE_WARNING); + using std::cout; using std::string; using std::vector; @@@ -138,7 -160,9 +143,7 @@@ FFmpegDecoder::pass ( /* Maybe we should fail here, but for now we'll just finish off instead */ char buf[256]; av_strerror (r, buf, sizeof(buf)); - _log->log (String::compose (N_("error on av_read_frame (%1) (%2)"), buf, r)); - shared_ptr film = _film.lock (); - assert (film); + LOG_ERROR (N_("error on av_read_frame (%1) (%2)"), buf, r); } flush (); @@@ -429,9 -401,10 +434,9 @@@ FFmpegDecoder::decode_audio_packet ( int frame_finished; int const decode_result = avcodec_decode_audio4 (audio_codec_context(), _frame, &frame_finished, ©_packet); + if (decode_result < 0) { - _log->log (String::compose ("avcodec_decode_audio4 failed (%1)", decode_result)); - shared_ptr film = _film.lock (); - assert (film); + LOG_ERROR ("avcodec_decode_audio4 failed (%1)", decode_result); return; } @@@ -471,9 -459,13 +476,9 @@@ FFmpegDecoder::decode_video_packet ( } if (i == _filter_graphs.end ()) { - shared_ptr film = _film.lock (); - assert (film); - - graph.reset (new FilterGraph (_ffmpeg_content, libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)); + graph.reset (new FilterGraph (_ffmpeg_content, dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)); _filter_graphs.push_back (graph); - _log->log (String::compose (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format)); - + LOG_GENERAL (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format); } else { graph = *i; } @@@ -485,10 -480,50 +490,13 @@@ shared_ptr image = i->first; if (i->second != AV_NOPTS_VALUE) { - - double const pts = i->second * av_q2d (_format_context->streams[_video_stream]->time_base) + _pts_offset; - - if (_just_sought) { - /* We just did a seek, so disable any attempts to correct for where we - are / should be. - */ - _video_position = rint (pts * _ffmpeg_content->video_frame_rate ()); - _just_sought = false; - } - - double const next = _video_position / _ffmpeg_content->video_frame_rate(); - double const one_frame = 1 / _ffmpeg_content->video_frame_rate (); - double delta = pts - next; - - while (delta > one_frame) { - /* This PTS is more than one frame forward in time of where we think we should be; emit - a black frame. - */ - - /* XXX: I think this should be a copy of the last frame... */ - boost::shared_ptr black ( - new Image ( - static_cast (_frame->format), - libdcp::Size (video_codec_context()->width, video_codec_context()->height), - true - ) - ); - - shared_ptr film = _film.lock (); - assert (film); - - black->make_black (); - video (shared_ptr (new RawImageProxy (image, film->log())), false, _video_position); - delta -= one_frame; - } - - if (delta > -one_frame) { - /* This PTS is within a frame of being right; emit this (otherwise it will be dropped) */ - video (shared_ptr (new RawImageProxy (image, film->log())), false, _video_position); - } - + double const pts = i->second * av_q2d (_format_context->streams[_video_stream]->time_base) + _pts_offset.seconds (); - video (shared_ptr (new RawImageProxy (image)), rint (pts * _ffmpeg_content->video_frame_rate ())); ++ video ( ++ shared_ptr (new RawImageProxy (image, _video_content->film()->log())), ++ rint (pts * _ffmpeg_content->video_frame_rate ()) ++ ); } else { - _log->log ("Dropping frame without PTS"); + LOG_WARNING ("Dropping frame without PTS"); } } diff --cc src/lib/ffmpeg_examiner.cc index df12830f8,d73063083..d9bcedfc5 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@@ -159,25 -118,27 +159,25 @@@ FFmpegExaminer::frame_time (AVStream* s float FFmpegExaminer::video_frame_rate () const { - AVStream* s = _format_context->streams[_video_stream]; - - if (s->avg_frame_rate.num && s->avg_frame_rate.den) { - return av_q2d (s->avg_frame_rate); - } - - return av_q2d (s->r_frame_rate); + /* This use of r_frame_rate is debateable; there's a few different + * frame rates in the format context, but this one seems to be the most + * reliable. + */ + return av_q2d (av_stream_get_r_frame_rate (_format_context->streams[_video_stream])); } -libdcp::Size +dcp::Size FFmpegExaminer::video_size () const { - return libdcp::Size (video_codec_context()->width, video_codec_context()->height); + return dcp::Size (video_codec_context()->width, video_codec_context()->height); } -/** @return Length (in video frames) according to our content's header */ -VideoContent::Frame +/** @return Length according to our content's header */ +ContentTime FFmpegExaminer::video_length () const { - ContentTime const length = ContentTime::from_seconds (double (_format_context->duration) / AV_TIME_BASE); - VideoContent::Frame const length = (double (_format_context->duration - _format_context->start_time) / AV_TIME_BASE) * video_frame_rate(); - return max (1, length); ++ ContentTime const length = ContentTime::from_seconds (double (_format_context->duration - _format_context->start_time) / AV_TIME_BASE); + return ContentTime (max (int64_t (1), length.get ())); } string diff --cc src/lib/film.cc index 50b1b4fad,1b5b2b366..25730ae1c --- a/src/lib/film.cc +++ b/src/lib/film.cc @@@ -77,10 -77,13 +77,13 @@@ using boost::to_upper_copy using boost::ends_with; using boost::starts_with; using boost::optional; -using libdcp::Size; -using libdcp::Signer; -using libdcp::raw_convert; +using dcp::Size; +using dcp::Signer; +using dcp::raw_convert; + #define LOG_GENERAL(...) log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL); + #define LOG_GENERAL_NC(...) log()->log (__VA_ARGS__, Log::TYPE_GENERAL); + /* 5 -> 6 * AudioMapping XML changed. * 6 -> 7 @@@ -780,9 -780,13 +783,16 @@@ Film::cpls () cons ) { try { - libdcp::DCP dcp (*i); + dcp::DCP dcp (*i); dcp.read (); - out.push_back (i->path().leaf ()); + out.push_back ( + CPLSummary ( - i->path().leaf().string(), dcp.cpls().front()->id(), dcp.cpls().front()->name(), dcp.cpls().front()->filename() ++ i->path().leaf().string(), ++ dcp.cpls().front()->id(), ++ dcp.cpls().front()->annotation_text(), ++ dcp.cpls().front()->file() + ) + ); } catch (...) { } @@@ -958,32 -980,27 +968,21 @@@ Film::frame_size () cons return fit_ratio_within (container()->ratio(), full_frame ()); } -/** @param from KDM from time in local time. - * @param to KDM to time in local time. - */ -libdcp::KDM +dcp::EncryptedKDM Film::make_kdm ( - shared_ptr target, + shared_ptr target, - boost::filesystem::path dcp_dir, + boost::filesystem::path cpl_file, - boost::posix_time::ptime from, - boost::posix_time::ptime until + dcp::LocalTime from, + dcp::LocalTime until ) const { -- shared_ptr signer = make_signer (); -- - dcp::DCP dcp (dir (dcp_dir.string ())); - - try { - dcp.read (); - } catch (...) { - throw KDMError (_("Could not read DCP to make KDM for")); - } - - dcp.cpls().front()->set_mxf_keys (key ()); - time_t now = time (0); - struct tm* tm = localtime (&now); - string const issue_date = libdcp::tm_to_string (tm); -- - return libdcp::KDM (cpl_file, signer, target, key (), from, until, "DCP-o-matic", issue_date); ++ shared_ptr cpl (new dcp::CPL (cpl_file)); + return dcp::DecryptedKDM ( - dcp.cpls().front(), from, until, "DCP-o-matic", dcp.cpls().front()->content_title_text(), dcp::LocalTime().as_string() - ).encrypt (signer, target); ++ cpl, from, until, "DCP-o-matic", cpl->content_title_text(), dcp::LocalTime().as_string() ++ ).encrypt (make_signer(), target); } -list +list Film::make_kdms ( list > screens, boost::filesystem::path dcp, diff --cc src/lib/film.h index ee8756b3d,06c770efa..d9d7e82fd --- a/src/lib/film.h +++ b/src/lib/film.h @@@ -96,10 -95,10 +96,10 @@@ public return _dirty; } - libdcp::Size full_frame () const; - libdcp::Size frame_size () const; + dcp::Size full_frame () const; + dcp::Size frame_size () const; - std::list dcps () const; + std::vector cpls () const; boost::shared_ptr make_player () const; boost::shared_ptr playlist () const; @@@ -112,27 -116,26 +112,27 @@@ /* Proxies for some Playlist methods */ ContentList content () const; - Time length () const; + DCPTime length () const; bool has_subtitles () const; - OutputVideoFrame best_video_frame_rate () const; + int best_video_frame_rate () const; + FrameRateChange active_frame_rate_change (DCPTime) const; - libdcp::KDM + dcp::EncryptedKDM make_kdm ( - boost::shared_ptr target, + boost::shared_ptr target, - boost::filesystem::path dcp, + boost::filesystem::path cpl_file, - boost::posix_time::ptime from, - boost::posix_time::ptime until + dcp::LocalTime from, + dcp::LocalTime until ) const; - std::list make_kdms ( + std::list make_kdms ( std::list >, - boost::filesystem::path dcp, + boost::filesystem::path cpl_file, - boost::posix_time::ptime from, - boost::posix_time::ptime until + dcp::LocalTime from, + dcp::LocalTime until ) const; - libdcp::Key key () const { + dcp::Key key () const { return _key; } diff --cc src/lib/image_decoder.cc index 9f83d1d89,7a9acd9e4..d3cdbd6f1 --- a/src/lib/image_decoder.cc +++ b/src/lib/image_decoder.cc @@@ -40,21 -41,23 +40,21 @@@ ImageDecoder::ImageDecoder (shared_ptr< } -void +bool ImageDecoder::pass () { - if (_video_position >= _image_content->video_length ()) { - return; + if (_video_position >= _image_content->video_length().frames (_image_content->video_frame_rate ())) { + return true; } - if (_image && _image_content->still ()) { - video (_image, true, _video_position); - return; + if (!_image_content->still() || !_image) { + /* Either we need an image or we are using moving images, so load one */ - _image.reset (new MagickImageProxy (_image_content->path (_image_content->still() ? 0 : _video_position))); ++ _image.reset (new MagickImageProxy (_image_content->path (_image_content->still() ? 0 : _video_position), _image_content->film()->log ())); } - - shared_ptr film = _film.lock (); - assert (film); - - _image.reset (new MagickImageProxy (_image_content->path (_image_content->still() ? 0 : _video_position), film->log ())); - video (_image, false, _video_position); + + video (_image, _video_position); + ++_video_position; + return false; } void diff --cc src/lib/image_proxy.cc index c74e846c9,230bfacad..16bd92f6e --- a/src/lib/image_proxy.cc +++ b/src/lib/image_proxy.cc @@@ -38,9 -41,17 +41,17 @@@ ImageProxy::ImageProxy (shared_ptr xml, shared_ptr socket) + RawImageProxy::RawImageProxy (shared_ptr image, shared_ptr log) + : ImageProxy (log) + , _image (image) + { + + } + + RawImageProxy::RawImageProxy (shared_ptr xml, shared_ptr socket, shared_ptr log) + : ImageProxy (log) { - libdcp::Size size ( + dcp::Size size ( xml->number_child ("Width"), xml->number_child ("Height") ); @@@ -112,8 -127,10 +127,9 @@@ MagickImageProxy::image () cons throw DecodeError (_("Could not decode image file")); } + dcp::Size size (magick_image->columns(), magick_image->rows()); + LOG_TIMING ("[%1] MagickImageProxy decode finished", boost::this_thread::get_id ()); - libdcp::Size size (magick_image->columns(), magick_image->rows()); - _image.reset (new Image (PIX_FMT_RGB24, size, true)); using namespace MagickCore; diff --cc src/lib/job.cc index c6a6b90a8,96aedac65..594c0da34 --- a/src/lib/job.cc +++ b/src/lib/job.cc @@@ -281,7 -279,6 +281,7 @@@ Job::error_summary () cons void Job::set_error (string s, string d) { - _film->log()->log (String::compose ("Error in job: %1 (%2)", s, d)); ++ _film->log()->log (String::compose ("Error in job: %1 (%2)", s, d), Log::TYPE_ERROR); boost::mutex::scoped_lock lm (_state_mutex); _error_summary = s; _error_details = d; diff --cc src/lib/kdm.cc index 902f0d333,d5d5ec0a0..c08750961 --- a/src/lib/kdm.cc +++ b/src/lib/kdm.cc @@@ -102,12 -102,12 +102,12 @@@ static list film, list > screens, - boost::filesystem::path dcp, + boost::filesystem::path cpl, - boost::posix_time::ptime from, - boost::posix_time::ptime to + dcp::LocalTime from, + dcp::LocalTime to ) { - list kdms = film->make_kdms (screens, dcp, from, to); - list kdms = film->make_kdms (screens, cpl, from, to); ++ list kdms = film->make_kdms (screens, cpl, from, to); list screen_kdms; @@@ -126,12 -126,12 +126,12 @@@ static list film, list > screens, - boost::filesystem::path dcp, + boost::filesystem::path cpl, - boost::posix_time::ptime from, - boost::posix_time::ptime to + dcp::LocalTime from, + dcp::LocalTime to ) { - list screen_kdms = make_screen_kdms (film, screens, dcp, from, to); + list screen_kdms = make_screen_kdms (film, screens, cpl, from, to); list cinema_kdms; while (!screen_kdms.empty ()) { @@@ -171,9 -171,9 +171,9 @@@ voi write_kdm_files ( shared_ptr film, list > screens, - boost::filesystem::path dcp, + boost::filesystem::path cpl, - boost::posix_time::ptime from, - boost::posix_time::ptime to, + dcp::LocalTime from, + dcp::LocalTime to, boost::filesystem::path directory ) { @@@ -191,9 -191,9 +191,9 @@@ voi write_kdm_zip_files ( shared_ptr film, list > screens, - boost::filesystem::path dcp, + boost::filesystem::path cpl, - boost::posix_time::ptime from, - boost::posix_time::ptime to, + dcp::LocalTime from, + dcp::LocalTime to, boost::filesystem::path directory ) { @@@ -210,12 -210,12 +210,12 @@@ voi email_kdms ( shared_ptr film, list > screens, - boost::filesystem::path dcp, + boost::filesystem::path cpl, - boost::posix_time::ptime from, - boost::posix_time::ptime to + dcp::LocalTime from, + dcp::LocalTime to ) { - list cinema_kdms = make_cinema_kdms (film, screens, dcp, from, to); + list cinema_kdms = make_cinema_kdms (film, screens, cpl, from, to); for (list::const_iterator i = cinema_kdms.begin(); i != cinema_kdms.end(); ++i) { diff --cc src/lib/kdm.h index 5df161b2a,8aacd7b72..023107a82 --- a/src/lib/kdm.h +++ b/src/lib/kdm.h @@@ -26,26 -26,26 +26,26 @@@ class Film extern void write_kdm_files ( boost::shared_ptr film, std::list > screens, - boost::filesystem::path dcp, + boost::filesystem::path cpl, - boost::posix_time::ptime from, - boost::posix_time::ptime to, + dcp::LocalTime from, + dcp::LocalTime to, boost::filesystem::path directory ); extern void write_kdm_zip_files ( boost::shared_ptr film, std::list > screens, - boost::filesystem::path dcp, + boost::filesystem::path cpl, - boost::posix_time::ptime from, - boost::posix_time::ptime to, + dcp::LocalTime from, + dcp::LocalTime to, boost::filesystem::path directory ); extern void email_kdms ( boost::shared_ptr film, std::list > screens, - boost::filesystem::path dcp, + boost::filesystem::path cpl, - boost::posix_time::ptime from, - boost::posix_time::ptime to + dcp::LocalTime from, + dcp::LocalTime to ); diff --cc src/lib/player.cc index b60dd8467,b112760ef..77def1e60 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@@ -36,13 -32,13 +36,15 @@@ #include "image.h" #include "image_proxy.h" #include "ratio.h" -#include "resampler.h" #include "log.h" #include "scaler.h" +#include "render_subtitles.h" +#include "config.h" +#include "content_video.h" #include "player_video_frame.h" + #define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL); + using std::list; using std::cout; using std::min; @@@ -283,89 -342,30 +285,89 @@@ Player::process_content_text_subtitles } void -Player::flush () +Player::set_approximate_size () { - TimedAudioBuffers