From: Carl Hetherington Date: Sun, 27 Apr 2014 22:41:26 +0000 (+0100) Subject: Merge master. X-Git-Tag: v2.0.48~853 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=7f2e74604a51b984e4c8cbb5d5f4bb642677ec00;hp=-c Merge master. --- 7f2e74604a51b984e4c8cbb5d5f4bb642677ec00 diff --combined ChangeLog index 04eb830f5,c30de54f8..1bbaed6e5 --- a/ChangeLog +++ b/ChangeLog @@@ -1,7 -1,46 +1,50 @@@ +2014-03-07 Carl Hetherington + + * Add subtitle view. + + 2014-04-27 Carl Hetherington + + * Version 1.66.16 released. + + 2014-04-27 Carl Hetherington + + * Add .dpx to the list of acceptable image files. + + * Slightly better handling of uncaught exceptions. + + * Use our own directory picker on 14.04 (as well as 13.04 and 13.10) as + it appears that the same bug remains. + + 2014-04-25 Carl Hetherington + + * Version 1.66.15 released. + + 2014-04-25 Carl Hetherington + + * Fix subtitle display when the next subtitle is decoded before the previous + one has finished. + + 2014-04-24 Carl Hetherington + + * Version 1.66.14 released. + + 2014-04-23 Carl Hetherington + + * Version 1.66.13 released. + + 2014-04-21 Carl Hetherington + + * Update to es_ES translation from Manuel AC. + + * Update to fr_FR translation from Thierry Journet. + + 2014-04-17 Carl Hetherington + + * Fix update of the gain control when using the gain calculator + dialog. + + * Version 1.66.12 released. + 2014-04-07 Carl Hetherington * Version 1.66.11 released. @@@ -66,7 -105,6 +109,7 @@@ * Another attempt to fix colour conversion dialog strange behaviour on OS X. +>>>>>>> master 2014-03-18 Carl Hetherington diff --combined cscript index c07c43031,142f1c287..890c937e6 --- a/cscript +++ b/cscript @@@ -71,6 -71,20 +71,20 @@@ deb_depends['13.10'] = {'libc6': '2.17- 'libcurl3': '7.29.0-1ubuntu3', 'libzip2': '0.10.1-1.1'} + deb_depends['14.04'] = {'libc6': '2.19-0ubuntu6', + 'libssh-4': '0.6.1-0ubuntu3', + 'libboost-filesystem1.54.0': '1.54.0-4ubuntu3', + 'libboost-thread1.54.0': '1.54.0-4ubuntu3', + 'libsndfile1': '1.0.25-7ubuntu2', + 'libmagick++5': '8:6.7.7.10-6ubuntu3', + 'libxml++2.6-2': '2.36.0-2ubuntu1', + 'libgtk2.0-0': '2.24.23-0ubuntu1', + 'libxmlsec1': '1.2.18-2ubuntu1', + 'libxmlsec1-openssl': '1.2.18-2ubuntu1', + 'libboost-date-time1.54.0': '1.54.0-4ubuntu3', + 'libcurl3': '7.35.0-1ubuntu2', + 'libzip2': '0.10.1-1.2'} + deb_depends['7'] = {'libc6': '2.13', 'libssh-4': '0.5.4', 'libboost-filesystem1.49.0': '1.49.0', @@@ -130,7 -144,7 +144,7 @@@ def make_control(debian_version, bits, def dependencies(target): return (('ffmpeg-cdist', 'a0db025'), - ('libdcp', '8af7b48')) + ('libdcp', '1.0')) def build(target, options): cmd = './waf configure --prefix=%s' % target.work_dir_cscript() diff --combined src/lib/image_content.cc index d7b37a835,3b87fcf00..56c83d3f7 --- a/src/lib/image_content.cc +++ b/src/lib/image_content.cc @@@ -44,7 -44,11 +44,11 @@@ ImageContent::ImageContent (shared_ptr< _paths.push_back (i->path ()); } } - + + if (_paths.empty()) { + throw FileError (_("No valid image files were found in the folder."), p); + } + sort (_paths.begin(), _paths.end()); } } @@@ -110,7 -114,7 +114,7 @@@ ImageContent::examine (shared_ptr } void -ImageContent::set_video_length (VideoContent::Frame len) +ImageContent::set_video_length (ContentTime len) { { boost::mutex::scoped_lock lm (_mutex); @@@ -120,12 -124,14 +124,12 @@@ signal_changed (ContentProperty::LENGTH); } -Time +DCPTime ImageContent::full_length () const { shared_ptr film = _film.lock (); assert (film); - - FrameRateConversion frc (video_frame_rate(), film->video_frame_rate ()); - return video_length_after_3d_combine() * frc.factor() * TIME_HZ / video_frame_rate(); + return DCPTime (video_length_after_3d_combine(), FrameRateChange (video_frame_rate(), film->video_frame_rate())); } string @@@ -133,7 -139,7 +137,7 @@@ ImageContent::identifier () cons { stringstream s; s << VideoContent::identifier (); - s << "_" << video_length(); + s << "_" << video_length().get(); return s.str (); } diff --combined src/lib/job.cc index 3639e5283,96aedac65..c6a6b90a8 --- a/src/lib/job.cc +++ b/src/lib/job.cc @@@ -1,5 -1,5 +1,5 @@@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2012-2014 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@@ -23,14 -23,12 +23,14 @@@ #include #include -#include +#include #include "job.h" #include "util.h" #include "cross.h" #include "ui_signaller.h" #include "exceptions.h" +#include "film.h" +#include "log.h" #include "i18n.h" @@@ -68,8 -66,8 +68,8 @@@ Job::run_wrapper ( run (); - } catch (libdcp::FileError& e) { - + } catch (dcp::FileError& e) { + string m = String::compose (_("An error occurred whilst handling the file %1."), boost::filesystem::path (e.filename()).leaf()); try { @@@ -110,7 -108,7 +110,7 @@@ set_error ( e.what (), - _("It is not known what caused this error. The best idea is to report the problem to the DCP-o-matic mailing list (carl@dcpomatic.com)") + _("It is not known what caused this error. Please report the problem to the DCP-o-matic author (carl@dcpomatic.com).") ); set_progress (1); @@@ -120,7 -118,7 +120,7 @@@ set_error ( _("Unknown error"), - _("It is not known what caused this error. The best idea is to report the problem to the DCP-o-matic mailing list (carl@dcpomatic.com)") + _("It is not known what caused this error. Please report the problem to the DCP-o-matic author (carl@dcpomatic.com).") ); set_progress (1); @@@ -206,7 -204,7 +206,7 @@@ Job::set_state (State s } } -/** @return Time (in seconds) that this sub-job has been running */ +/** @return DCPTime (in seconds) that this sub-job has been running */ int Job::elapsed_time () const { @@@ -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)); boost::mutex::scoped_lock lm (_state_mutex); _error_summary = s; _error_details = d; diff --combined src/lib/piece.h index 000000000,76df909ff..976409381 mode 000000,100644..100644 --- a/src/lib/piece.h +++ b/src/lib/piece.h @@@ -1,0 -1,65 +1,43 @@@ + /* + Copyright (C) 2013-2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + + #ifndef DCPOMATIC_PIECE_H + #define DCPOMATIC_PIECE_H + + #include "types.h" + #include "video_content.h" + + class Content; + class Decoder; -class Piece; -class Image; -class Player; - -struct IncomingVideo -{ -public: - boost::weak_ptr weak_piece; - boost::shared_ptr image; - Eyes eyes; - bool same; - VideoContent::Frame frame; - Time extra; -}; + + class Piece + { + public: - Piece (boost::shared_ptr c); - Piece (boost::shared_ptr c, boost::shared_ptr d); - void set_repeat (IncomingVideo video, int num); - void reset_repeat (); - bool repeating () const; - void repeat (Player* player); - ++ Piece (boost::shared_ptr c, boost::shared_ptr d, FrameRateChange f) ++ : content (c) ++ , decoder (d) ++ , frc (f) ++ {} ++ + boost::shared_ptr content; + boost::shared_ptr decoder; - /** Time of the last video we emitted relative to the start of the DCP */ - Time video_position; - /** Time of the last audio we emitted relative to the start of the DCP */ - Time audio_position; - - IncomingVideo repeat_video; - int repeat_to_do; - int repeat_done; ++ FrameRateChange frc; + }; + + #endif diff --combined src/lib/player.h index d83045ab1,4d911a83b..62ba89e6c --- a/src/lib/player.h +++ b/src/lib/player.h @@@ -27,10 -27,10 +27,11 @@@ #include "content.h" #include "film.h" #include "rect.h" -#include "audio_merger.h" #include "audio_content.h" +#include "dcpomatic_time.h" +#include "content_subtitle.h" +#include "position_image.h" + #include "piece.h" -#include "subtitle.h" class Job; class Film; @@@ -38,74 -38,64 +39,82 @@@ class Playlist class AudioContent; class Piece; class Image; -class Resampler; +class DCPVideo; +class Decoder; + +class PlayerStatistics +{ +public: + struct Video { + Video () + : black (0) + , repeat (0) + , good (0) + , skip (0) + {} + + int black; + int repeat; + int good; + int skip; + } video; + + struct Audio { + Audio () + : silence (0) + , good (0) + , skip (0) + {} + + DCPTime silence; + int64_t good; + int64_t skip; + } audio; + + void dump (boost::shared_ptr) const; +}; - class Piece + /** A wrapper for an Image which contains some pending operations; these may + * not be necessary if the receiver of the PlayerImage throws it away. + */ + class PlayerImage { public: - Piece (boost::shared_ptr c, boost::shared_ptr d, FrameRateChange f) - : content (c) - , decoder (d) - , frc (f) - {} - - boost::shared_ptr content; - boost::shared_ptr decoder; - FrameRateChange frc; - PlayerImage (boost::shared_ptr, Crop, libdcp::Size, libdcp::Size, Scaler const *); ++ PlayerImage (boost::shared_ptr, Crop, dcp::Size, dcp::Size, Scaler const *); + + void set_subtitle (boost::shared_ptr, Position); + + boost::shared_ptr image (); - ++ + private: + boost::shared_ptr _in; + Crop _crop; - libdcp::Size _inter_size; - libdcp::Size _out_size; ++ dcp::Size _inter_size; ++ dcp::Size _out_size; + Scaler const * _scaler; + boost::shared_ptr _subtitle_image; + Position _subtitle_position; }; - + /** @class Player - * @brief A class which can `play' a Playlist; emitting its audio and video. + * @brief A class which can `play' a Playlist. */ class Player : public boost::enable_shared_from_this, public boost::noncopyable { public: Player (boost::shared_ptr, boost::shared_ptr); - void disable_video (); - void disable_audio (); - - bool pass (); - void seek (Time, bool); + boost::shared_ptr get_video (DCPTime time, bool accurate); + boost::shared_ptr get_audio (DCPTime time, DCPTime length, bool accurate); - Time video_position () const { - return _video_position; + void set_video_container_size (dcp::Size); + void set_approximate_size (); + void set_burn_subtitles (bool burn) { + _burn_subtitles = burn; } - void set_video_container_size (libdcp::Size); - - bool repeat_last_video (); - - /** Emitted when a video frame is ready. - * First parameter is the video image. - * Second parameter is the eye(s) that should see this image. - * Third parameter is the colour conversion that should be used for this image. - * Fourth parameter is true if the image is the same as the last one that was emitted. - * Fifth parameter is the time. - */ - boost::signals2::signal, Eyes, ColourConversion, bool, Time)> Video; + PlayerStatistics const & statistics () const; - /** Emitted when some audio data is ready */ - boost::signals2::signal, Time)> Audio; - /** Emitted when something has changed such that if we went back and emitted * the last frame again it would look different. This is not emitted after * a seek. @@@ -118,49 -108,50 +127,49 @@@ private friend class PlayerWrapper; friend class Piece; - void process_video (boost::weak_ptr, boost::shared_ptr, Eyes, bool, VideoContent::Frame, Time); - void process_audio (boost::weak_ptr, boost::shared_ptr, AudioContent::Frame); - void process_subtitle (boost::weak_ptr, boost::shared_ptr, dcpomatic::Rect, Time, Time); void setup_pieces (); void playlist_changed (); void content_changed (boost::weak_ptr, int, bool); - void do_seek (Time, bool); void flush (); - void emit_black (); - void emit_silence (OutputAudioFrame); - boost::shared_ptr resampler (boost::shared_ptr, bool); void film_changed (Film::Property); - void update_subtitle (); - + std::list process_content_image_subtitles ( + boost::shared_ptr, std::list > + ); + std::list process_content_text_subtitles (std::list >); + void update_subtitle_from_text (); + VideoFrame dcp_to_content_video (boost::shared_ptr piece, DCPTime t) const; + AudioFrame dcp_to_content_audio (boost::shared_ptr piece, DCPTime t) const; + ContentTime dcp_to_content_subtitle (boost::shared_ptr piece, DCPTime t) const; + boost::shared_ptr black_dcp_video (DCPTime) const; + + template + std::list > + overlaps (DCPTime t) + { + std::list > overlaps; + for (typename std::list >::const_iterator i = _pieces.begin(); i != _pieces.end(); ++i) { + if (boost::dynamic_pointer_cast ((*i)->content) && (*i)->content->position() <= t && t < (*i)->content->end()) { + overlaps.push_back (*i); + } + } + + return overlaps; + } + boost::shared_ptr _film; boost::shared_ptr _playlist; - - bool _video; - bool _audio; /** Our pieces are ready to go; if this is false the pieces must be (re-)created before they are used */ bool _have_valid_pieces; std::list > _pieces; - /** The time after the last video that we emitted */ - Time _video_position; - /** The time after the last audio that we emitted */ - Time _audio_position; - - AudioMerger _audio_merger; - - libdcp::Size _video_container_size; - boost::shared_ptr _black_frame; - std::map, boost::shared_ptr > _resamplers; - - std::list _subtitles; - -#ifdef DCPOMATIC_DEBUG - boost::shared_ptr _last_video; -#endif + dcp::Size _video_container_size; + boost::shared_ptr _black_image; - bool _last_emit_was_black; + bool _approximate_size; + bool _burn_subtitles; - IncomingVideo _last_incoming_video; + PlayerStatistics _statistics; boost::signals2::scoped_connection _playlist_changed_connection; boost::signals2::scoped_connection _playlist_content_changed_connection; diff --combined src/lib/util.cc index 40e9d9c2e,f15d2283c..c23deb59e --- a/src/lib/util.cc +++ b/src/lib/util.cc @@@ -1,5 -1,5 +1,5 @@@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2012-2014 Carl Hetherington Copyright (C) 2000-2007 Paul Davis This program is free software; you can redistribute it and/or modify @@@ -46,13 -46,12 +46,13 @@@ #include #include #include +#include #include #include -#include -#include -#include -#include +#include +#include +#include +#include extern "C" { #include #include @@@ -71,7 -70,6 +71,7 @@@ #include "job.h" #include "cross.h" #include "video_content.h" +#include "rect.h" #ifdef DCPOMATIC_WINDOWS #include "stack.hpp" #endif @@@ -103,7 -101,7 +103,7 @@@ using boost::shared_ptr using boost::thread; using boost::lexical_cast; using boost::optional; -using libdcp::Size; +using dcp::Size; static boost::thread::id ui_thread; static boost::filesystem::path backtrace_file; @@@ -239,6 -237,24 +239,6 @@@ ffmpeg_version_to_string (int v return s.str (); } -/** Return a user-readable string summarising the versions of our dependencies */ -string -dependency_version_summary () -{ - stringstream s; - s << N_("libopenjpeg ") << opj_version () << N_(", ") - << N_("libavcodec ") << ffmpeg_version_to_string (avcodec_version()) << N_(", ") - << N_("libavfilter ") << ffmpeg_version_to_string (avfilter_version()) << N_(", ") - << N_("libavformat ") << ffmpeg_version_to_string (avformat_version()) << N_(", ") - << N_("libavutil ") << ffmpeg_version_to_string (avutil_version()) << N_(", ") - << N_("libswscale ") << ffmpeg_version_to_string (swscale_version()) << N_(", ") - << MagickVersion << N_(", ") - << N_("libssh ") << ssh_version (0) << N_(", ") - << N_("libdcp ") << libdcp::version << N_(" git ") << libdcp::git_commit; - - return s.str (); -} - double seconds (struct timeval t) { @@@ -325,8 -341,7 +325,8 @@@ dcpomatic_setup ( set_terminate (terminate); - libdcp::init (); + Pango::init (); + dcp::init (); Ratio::setup_ratios (); VideoContentScale::setup_scales (); @@@ -475,6 -490,33 +475,6 @@@ md5_digest (vector 2) { - description = String::compose (_("Each content frame will be repeated %1 more times in the DCP.\n"), repeat - 1); - } - - if (change_speed) { - float const pc = dcp * 100 / (source * factor()); - description += String::compose (_("DCP will run at %1%% of the content speed.\n"), pc); - } - } -} - LocaleGuard::LocaleGuard () : _old (0) { @@@ -785,7 -876,7 +785,7 @@@ valid_image_file (boost::filesystem::pa { string ext = f.extension().string(); transform (ext.begin(), ext.end(), ext.begin(), ::tolower); - return (ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".bmp" || ext == ".tga"); + return (ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".bmp" || ext == ".tga" || ext == ".dpx"); } string @@@ -803,7 -894,7 +803,7 @@@ tidy_for_filename (string f return t; } -shared_ptr +shared_ptr make_signer () { boost::filesystem::path const sd = Config::instance()->signer_chain_directory (); @@@ -823,37 -914,37 +823,37 @@@ if (!boost::filesystem::exists (p)) { boost::filesystem::remove_all (sd); boost::filesystem::create_directories (sd); - libdcp::make_signer_chain (sd, openssl_path ()); + dcp::make_signer_chain (sd, openssl_path ()); break; } ++i; } - libdcp::CertificateChain chain; + dcp::CertificateChain chain; { boost::filesystem::path p (sd); p /= "ca.self-signed.pem"; - chain.add (shared_ptr (new libdcp::Certificate (p))); + chain.add (shared_ptr (new dcp::Certificate (p))); } { boost::filesystem::path p (sd); p /= "intermediate.signed.pem"; - chain.add (shared_ptr (new libdcp::Certificate (p))); + chain.add (shared_ptr (new dcp::Certificate (p))); } { boost::filesystem::path p (sd); p /= "leaf.signed.pem"; - chain.add (shared_ptr (new libdcp::Certificate (p))); + chain.add (shared_ptr (new dcp::Certificate (p))); } boost::filesystem::path signer_key (sd); signer_key /= "leaf.key"; - return shared_ptr (new libdcp::Signer (chain, signer_key)); + return shared_ptr (new dcp::Signer (chain, signer_key)); } map @@@ -902,14 -993,14 +902,14 @@@ split_get_request (string url return r; } -libdcp::Size -fit_ratio_within (float ratio, libdcp::Size full_frame) +dcp::Size +fit_ratio_within (float ratio, dcp::Size full_frame) { if (ratio < full_frame.ratio ()) { - return libdcp::Size (rint (full_frame.height * ratio), full_frame.height); + return dcp::Size (rint (full_frame.height * ratio), full_frame.height); } - return libdcp::Size (full_frame.width, rint (full_frame.width / ratio)); + return dcp::Size (full_frame.width, rint (full_frame.width / ratio)); } void * @@@ -940,24 -1031,6 +940,24 @@@ divide_with_round (int64_t a, int64_t b } } +/** Return a user-readable string summarising the versions of our dependencies */ +string +dependency_version_summary () +{ + stringstream s; + s << N_("libopenjpeg ") << opj_version () << N_(", ") + << N_("libavcodec ") << ffmpeg_version_to_string (avcodec_version()) << N_(", ") + << N_("libavfilter ") << ffmpeg_version_to_string (avfilter_version()) << N_(", ") + << N_("libavformat ") << ffmpeg_version_to_string (avformat_version()) << N_(", ") + << N_("libavutil ") << ffmpeg_version_to_string (avutil_version()) << N_(", ") + << N_("libswscale ") << ffmpeg_version_to_string (swscale_version()) << N_(", ") + << MagickVersion << N_(", ") + << N_("libssh ") << ssh_version (0) << N_(", ") + << N_("libdcp ") << dcp::version << N_(" git ") << dcp::git_commit; + + return s.str (); +} + ScopedTemporary::ScopedTemporary () : _open (0) { diff --combined src/wx/film_editor.cc index 7fa34c516,1131675bc..2cf6a0b6c --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@@ -803,11 -803,16 +803,16 @@@ FilmEditor::content_add_folder_clicked return; } - _film->examine_and_add_content ( - shared_ptr ( - new ImageContent (_film, boost::filesystem::path (wx_to_std (d->GetPath ()))) - ) - ); + shared_ptr ic; + + try { + ic.reset (new ImageContent (_film, boost::filesystem::path (wx_to_std (d->GetPath ())))); + } catch (FileError& e) { + error_dialog (this, std_to_wx (e.what ())); + return; + } + + _film->examine_and_add_content (ic); } void @@@ -849,7 -854,7 +854,7 @@@ FilmEditor::setup_content_sensitivity ( _video_panel->Enable (video_selection.size() > 0 && _generally_sensitive); _audio_panel->Enable (audio_selection.size() > 0 && _generally_sensitive); - _subtitle_panel->Enable (selection.size() == 1 && dynamic_pointer_cast (selection.front()) && _generally_sensitive); + _subtitle_panel->Enable (selection.size() == 1 && dynamic_pointer_cast (selection.front()) && _generally_sensitive); _timing_panel->Enable (selection.size() == 1 && _generally_sensitive); }