From 8bef34f672815c3c9b4236d06fdee8dfd0bffbc2 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 24 Nov 2013 01:52:23 +0000 Subject: [PATCH] Various joining fixes. --- src/lib/content.cc | 9 +++- src/lib/content_factory.cc | 8 ++-- src/lib/content_factory.h | 2 +- src/lib/ffmpeg.cc | 21 ++++----- src/lib/ffmpeg.h | 7 +-- src/lib/ffmpeg_content.cc | 88 ++++++++++++++++++++++++++++++++------ src/lib/ffmpeg_content.h | 54 ++++++++++++++++------- src/lib/ffmpeg_decoder.cc | 14 +++--- src/lib/ffmpeg_examiner.cc | 12 +++--- src/lib/film.cc | 6 ++- src/lib/image_content.cc | 2 +- src/lib/image_content.h | 2 +- src/lib/playlist.cc | 4 +- src/lib/playlist.h | 2 +- src/lib/sndfile_content.cc | 2 +- src/lib/sndfile_content.h | 2 +- src/lib/util.cc | 21 ++++++--- src/lib/video_content.cc | 5 ++- src/tools/dcpomatic.cc | 1 + src/wx/film_editor.cc | 4 +- src/wx/hints_dialog.cc | 2 +- test/stream_test.cc | 3 +- 22 files changed, 190 insertions(+), 81 deletions(-) diff --git a/src/lib/content.cc b/src/lib/content.cc index eaa55790b..f09012765 100644 --- a/src/lib/content.cc +++ b/src/lib/content.cc @@ -25,6 +25,7 @@ #include "content_factory.h" #include "ui_signaller.h" #include "exceptions.h" +#include "film.h" #include "i18n.h" @@ -102,6 +103,10 @@ Content::Content (shared_ptr f, vector > c) if (i < (c.size() - 1) && c[i]->trim_end ()) { throw JoinError (_("Only the last piece of content to be joined can have an end trim.")); } + + for (size_t j = 0; j < c[i]->number_of_paths(); ++j) { + _paths.push_back (c[i]->path (j)); + } } } @@ -186,7 +191,7 @@ Content::clone () const xmlpp::Document doc; xmlpp::Node* node = doc.create_root_node ("Content"); as_xml (node); - return content_factory (film, cxml::NodePtr(new cxml::Node (node))); + return content_factory (film, cxml::NodePtr (new cxml::Node (node)), Film::state_version); } string @@ -251,6 +256,8 @@ Content::path_summary () const { /* XXX: should handle multiple paths more gracefully */ + assert (number_of_paths ()); + string s = path(0).filename().string (); if (number_of_paths() > 1) { s += " ..."; diff --git a/src/lib/content_factory.cc b/src/lib/content_factory.cc index e800628c1..bab22b8eb 100644 --- a/src/lib/content_factory.cc +++ b/src/lib/content_factory.cc @@ -27,18 +27,18 @@ using std::string; using boost::shared_ptr; shared_ptr -content_factory (shared_ptr film, cxml::NodePtr node) +content_factory (shared_ptr film, cxml::NodePtr node, int version) { string const type = node->string_child ("Type"); boost::shared_ptr content; if (type == "FFmpeg") { - content.reset (new FFmpegContent (film, node)); + content.reset (new FFmpegContent (film, node, version)); } else if (type == "Image") { - content.reset (new ImageContent (film, node)); + content.reset (new ImageContent (film, node, version)); } else if (type == "Sndfile") { - content.reset (new SndfileContent (film, node)); + content.reset (new SndfileContent (film, node, version)); } return content; diff --git a/src/lib/content_factory.h b/src/lib/content_factory.h index d2f75051a..071d925e0 100644 --- a/src/lib/content_factory.h +++ b/src/lib/content_factory.h @@ -19,5 +19,5 @@ class Film; -extern boost::shared_ptr content_factory (boost::shared_ptr, cxml::NodePtr); +extern boost::shared_ptr content_factory (boost::shared_ptr, cxml::NodePtr, int); extern boost::shared_ptr content_factory (boost::shared_ptr, boost::filesystem::path); diff --git a/src/lib/ffmpeg.cc b/src/lib/ffmpeg.cc index 3b894a6ff..e85a2c44e 100644 --- a/src/lib/ffmpeg.cc +++ b/src/lib/ffmpeg.cc @@ -37,8 +37,7 @@ using boost::lexical_cast; boost::mutex FFmpeg::_mutex; -/** @param long_probe true to do a long probe of the file looking for streams */ -FFmpeg::FFmpeg (boost::shared_ptr c, bool long_probe) +FFmpeg::FFmpeg (boost::shared_ptr c) : _ffmpeg_content (c) , _avio_buffer (0) , _avio_buffer_size (4096) @@ -47,7 +46,7 @@ FFmpeg::FFmpeg (boost::shared_ptr c, bool long_probe) , _frame (0) , _video_stream (-1) { - setup_general (long_probe); + setup_general (); setup_video (); setup_audio (); } @@ -81,7 +80,7 @@ avio_seek_wrapper (void* data, int64_t offset, int whence) } void -FFmpeg::setup_general (bool long_probe) +FFmpeg::setup_general () { av_register_all (); @@ -92,13 +91,11 @@ FFmpeg::setup_general (bool long_probe) _format_context->pb = _avio_context; AVDictionary* options = 0; - if (long_probe) { - /* These durations are in microseconds, and represent how far into the content file - we will look for streams. - */ - av_dict_set (&options, "analyzeduration", lexical_cast (5 * 60 * 1e6).c_str(), 0); - av_dict_set (&options, "probesize", lexical_cast (5 * 60 * 1e6).c_str(), 0); - } + /* These durations are in microseconds, and represent how far into the content file + we will look for streams. + */ + av_dict_set (&options, "analyzeduration", lexical_cast (5 * 60 * 1e6).c_str(), 0); + av_dict_set (&options, "probesize", lexical_cast (5 * 60 * 1e6).c_str(), 0); if (avformat_open_input (&_format_context, 0, 0, &options) < 0) { throw OpenFileError (_ffmpeg_content->path(0).string ()); @@ -176,7 +173,7 @@ FFmpeg::video_codec_context () const AVCodecContext * FFmpeg::audio_codec_context () const { - return _format_context->streams[_ffmpeg_content->audio_stream()->id]->codec; + return _ffmpeg_content->audio_stream()->stream(_format_context)->codec; } int diff --git a/src/lib/ffmpeg.h b/src/lib/ffmpeg.h index 182ee634b..760918437 100644 --- a/src/lib/ffmpeg.h +++ b/src/lib/ffmpeg.h @@ -43,7 +43,7 @@ class FFmpegContent; class FFmpeg { public: - FFmpeg (boost::shared_ptr, bool); + FFmpeg (boost::shared_ptr); virtual ~FFmpeg (); boost::shared_ptr ffmpeg_content () const { @@ -67,7 +67,8 @@ protected: AVFormatContext* _format_context; AVPacket _packet; AVFrame* _frame; - + + /** Index of video stream within AVFormatContext */ int _video_stream; /* It would appear (though not completely verified) that one must have @@ -77,7 +78,7 @@ protected: static boost::mutex _mutex; private: - void setup_general (bool); + void setup_general (); void setup_video (); void setup_audio (); }; diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index e843e1e16..9533315a5 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -17,6 +17,9 @@ */ +extern "C" { +#include +} #include #include "ffmpeg_content.h" #include "ffmpeg_examiner.h" @@ -55,7 +58,7 @@ FFmpegContent::FFmpegContent (shared_ptr f, boost::filesystem::path } -FFmpegContent::FFmpegContent (shared_ptr f, shared_ptr node) +FFmpegContent::FFmpegContent (shared_ptr f, shared_ptr node, int version) : Content (f, node) , VideoContent (f, node) , AudioContent (f, node) @@ -63,7 +66,7 @@ FFmpegContent::FFmpegContent (shared_ptr f, shared_ptr c = node->node_children ("SubtitleStream"); for (list::const_iterator i = c.begin(); i != c.end(); ++i) { - _subtitle_streams.push_back (shared_ptr (new FFmpegSubtitleStream (*i))); + _subtitle_streams.push_back (shared_ptr (new FFmpegSubtitleStream (*i, version))); if ((*i)->optional_number_child ("Selected")) { _subtitle_stream = _subtitle_streams.back (); } @@ -71,7 +74,7 @@ FFmpegContent::FFmpegContent (shared_ptr f, shared_ptrnode_children ("AudioStream"); for (list::const_iterator i = c.begin(); i != c.end(); ++i) { - _audio_streams.push_back (shared_ptr (new FFmpegAudioStream (*i))); + _audio_streams.push_back (shared_ptr (new FFmpegAudioStream (*i, version))); if ((*i)->optional_number_child ("Selected")) { _audio_stream = _audio_streams.back (); } @@ -93,10 +96,10 @@ FFmpegContent::FFmpegContent (shared_ptr f, vector ref = dynamic_pointer_cast (c[0]); assert (ref); - + for (size_t i = 0; i < c.size(); ++i) { shared_ptr fc = dynamic_pointer_cast (c[i]); - if (*(fc->_subtitle_stream.get()) != *(ref->_subtitle_stream.get())) { + if (f->with_subtitles() && *(fc->_subtitle_stream.get()) != *(ref->_subtitle_stream.get())) { throw JoinError (_("Content to be joined must use the same subtitle stream.")); } @@ -346,11 +349,33 @@ operator!= (FFmpegAudioStream const & a, FFmpegAudioStream const & b) return a.id != b.id; } -FFmpegAudioStream::FFmpegAudioStream (shared_ptr node) - : mapping (node->node_child ("Mapping")) +FFmpegStream::FFmpegStream (shared_ptr node, int version) + : _legacy_id (false) { name = node->string_child ("Name"); id = node->number_child ("Id"); + if (version == 4 || node->optional_bool_child ("LegacyId")) { + _legacy_id = true; + } +} + +void +FFmpegStream::as_xml (xmlpp::Node* root) const +{ + root->add_child("Name")->add_child_text (name); + root->add_child("Id")->add_child_text (lexical_cast (id)); + if (_legacy_id) { + /* Write this so that version > 4 files are read in correctly + if the Id came originally from a version <= 4 file. + */ + root->add_child("LegacyId")->add_child_text ("1"); + } +} + +FFmpegAudioStream::FFmpegAudioStream (shared_ptr node, int version) + : FFmpegStream (node, version) + , mapping (node->node_child ("Mapping")) +{ frame_rate = node->number_child ("FrameRate"); channels = node->number_child ("Channels"); first_audio = node->optional_number_child ("FirstAudio"); @@ -359,8 +384,7 @@ FFmpegAudioStream::FFmpegAudioStream (shared_ptr node) void FFmpegAudioStream::as_xml (xmlpp::Node* root) const { - root->add_child("Name")->add_child_text (name); - root->add_child("Id")->add_child_text (lexical_cast (id)); + FFmpegStream::as_xml (root); root->add_child("FrameRate")->add_child_text (lexical_cast (frame_rate)); root->add_child("Channels")->add_child_text (lexical_cast (channels)); if (first_audio) { @@ -369,21 +393,57 @@ FFmpegAudioStream::as_xml (xmlpp::Node* root) const mapping.as_xml (root->add_child("Mapping")); } +int +FFmpegStream::index (AVFormatContext const * fc) const +{ + if (_legacy_id) { + return id; + } + + size_t i = 0; + while (i < fc->nb_streams) { + if (fc->streams[i]->id == id) { + return i; + } + ++i; + } + + assert (false); +} + +AVStream * +FFmpegStream::stream (AVFormatContext const * fc) const +{ + if (_legacy_id) { + return fc->streams[id]; + } + + size_t i = 0; + while (i < fc->nb_streams) { + if (fc->streams[i]->id == id) { + return fc->streams[i]; + } + ++i; + } + + assert (false); + return 0; +} + /** Construct a SubtitleStream from a value returned from to_string(). * @param t String returned from to_string(). * @param v State file version. */ -FFmpegSubtitleStream::FFmpegSubtitleStream (shared_ptr node) +FFmpegSubtitleStream::FFmpegSubtitleStream (shared_ptr node, int version) + : FFmpegStream (node, version) { - name = node->string_child ("Name"); - id = node->number_child ("Id"); + } void FFmpegSubtitleStream::as_xml (xmlpp::Node* root) const { - root->add_child("Name")->add_child_text (name); - root->add_child("Id")->add_child_text (lexical_cast (id)); + FFmpegStream::as_xml (root); } Time diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h index 4576aaf45..7ff159b85 100644 --- a/src/lib/ffmpeg_content.h +++ b/src/lib/ffmpeg_content.h @@ -26,15 +26,44 @@ #include "subtitle_content.h" #include "audio_mapping.h" +struct AVFormatContext; +struct AVStream; + class Filter; class ffmpeg_pts_offset_test; -class FFmpegAudioStream +class FFmpegStream { public: - FFmpegAudioStream (std::string n, int i, int f, int c) + FFmpegStream (std::string n, int i) : name (n) , id (i) + , _legacy_id (false) + {} + + FFmpegStream (boost::shared_ptr, int); + + void as_xml (xmlpp::Node *) const; + + /** @param c An AVFormatContext. + * @return Stream index within the AVFormatContext. + */ + int index (AVFormatContext const * c) const; + AVStream* stream (AVFormatContext const * c) const; + + std::string name; + int id; + +private: + /** If this is true, id is in fact the index */ + bool _legacy_id; +}; + +class FFmpegAudioStream : public FFmpegStream +{ +public: + FFmpegAudioStream (std::string n, int i, int f, int c) + : FFmpegStream (n, i) , frame_rate (f) , channels (c) , mapping (c) @@ -42,12 +71,10 @@ public: mapping.make_default (); } - FFmpegAudioStream (boost::shared_ptr); + FFmpegAudioStream (boost::shared_ptr, int); void as_xml (xmlpp::Node *) const; - - std::string name; - int id; + int frame_rate; int channels; AudioMapping mapping; @@ -58,27 +85,24 @@ private: /* Constructor for tests */ FFmpegAudioStream () - : mapping (1) + : FFmpegStream ("", 0) + , mapping (1) {} }; extern bool operator== (FFmpegAudioStream const & a, FFmpegAudioStream const & b); extern bool operator!= (FFmpegAudioStream const & a, FFmpegAudioStream const & b); -class FFmpegSubtitleStream +class FFmpegSubtitleStream : public FFmpegStream { public: FFmpegSubtitleStream (std::string n, int i) - : name (n) - , id (i) + : FFmpegStream (n, i) {} - FFmpegSubtitleStream (boost::shared_ptr); + FFmpegSubtitleStream (boost::shared_ptr, int); void as_xml (xmlpp::Node *) const; - - std::string name; - int id; }; extern bool operator== (FFmpegSubtitleStream const & a, FFmpegSubtitleStream const & b); @@ -98,7 +122,7 @@ class FFmpegContent : public VideoContent, public AudioContent, public SubtitleC { public: FFmpegContent (boost::shared_ptr, boost::filesystem::path); - FFmpegContent (boost::shared_ptr, boost::shared_ptr); + FFmpegContent (boost::shared_ptr, boost::shared_ptr, int version); FFmpegContent (boost::shared_ptr, std::vector >); boost::shared_ptr shared_from_this () { diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index be3247537..5a1b78762 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -63,7 +63,7 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr f, shared_ptr film = _film.lock (); assert (film); + + int const si = _packet.stream_index; - if (_packet.stream_index == _video_stream && _decode_video) { + if (si == _video_stream && _decode_video) { decode_video_packet (); - } else if (_ffmpeg_content->audio_stream() && _packet.stream_index == _ffmpeg_content->audio_stream()->id && _decode_audio) { + } else if (_ffmpeg_content->audio_stream() && si == _ffmpeg_content->audio_stream()->index (_format_context) && _decode_audio) { decode_audio_packet (); - } else if (_ffmpeg_content->subtitle_stream() && _packet.stream_index == _ffmpeg_content->subtitle_stream()->id && film->with_subtitles ()) { + } else if (_ffmpeg_content->subtitle_stream() && si == _ffmpeg_content->subtitle_stream()->index (_format_context) && film->with_subtitles ()) { decode_subtitle_packet (); } @@ -511,11 +513,11 @@ FFmpegDecoder::setup_subtitle () { boost::mutex::scoped_lock lm (_mutex); - if (!_ffmpeg_content->subtitle_stream() || _ffmpeg_content->subtitle_stream()->id >= int (_format_context->nb_streams)) { + if (!_ffmpeg_content->subtitle_stream() || _ffmpeg_content->subtitle_stream()->index (_format_context) >= int (_format_context->nb_streams)) { return; } - _subtitle_codec_context = _format_context->streams[_ffmpeg_content->subtitle_stream()->id]->codec; + _subtitle_codec_context = _ffmpeg_content->subtitle_stream()->stream(_format_context)->codec; _subtitle_codec = avcodec_find_decoder (_subtitle_codec_context->codec_id); if (_subtitle_codec == 0) { diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index 8e4f24720..78b6e3121 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -24,6 +24,8 @@ extern "C" { #include "ffmpeg_examiner.h" #include "ffmpeg_content.h" +#include "i18n.h" + using std::string; using std::cout; using std::max; @@ -32,7 +34,7 @@ using boost::shared_ptr; using boost::optional; FFmpegExaminer::FFmpegExaminer (shared_ptr c) - : FFmpeg (c, true) + : FFmpeg (c) { /* Find audio and subtitle streams */ @@ -50,12 +52,12 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c) _audio_streams.push_back ( shared_ptr ( - new FFmpegAudioStream (audio_stream_name (s), i, s->codec->sample_rate, s->codec->channels) + new FFmpegAudioStream (audio_stream_name (s), s->id, s->codec->sample_rate, s->codec->channels) ) ); } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { - _subtitle_streams.push_back (shared_ptr (new FFmpegSubtitleStream (subtitle_stream_name (s), i))); + _subtitle_streams.push_back (shared_ptr (new FFmpegSubtitleStream (subtitle_stream_name (s), s->id))); } } @@ -78,9 +80,9 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr c) } } else { for (size_t i = 0; i < _audio_streams.size(); ++i) { - if (_packet.stream_index == _audio_streams[i]->id && !_audio_streams[i]->first_audio) { + if (_packet.stream_index == _audio_streams[i]->index (_format_context) && !_audio_streams[i]->first_audio) { if (avcodec_decode_audio4 (context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) { - _audio_streams[i]->first_audio = frame_time (_audio_streams[i]->id); + _audio_streams[i]->first_audio = frame_time (_audio_streams[i]->index (_format_context)); } } } diff --git a/src/lib/film.cc b/src/lib/film.cc index eab91c7d2..d53d61a63 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -83,7 +83,7 @@ using boost::optional; using libdcp::Size; using libdcp::Signer; -int const Film::state_version = 4; +int const Film::state_version = 5; /** Construct a Film object in a given directory. * @@ -374,6 +374,8 @@ Film::read_metadata () cxml::Document f ("Metadata"); f.read_file (file ("metadata.xml")); + + int const version = f.number_child ("Version"); _name = f.string_child ("Name"); _use_dci_name = f.bool_child ("UseDCIName"); @@ -405,7 +407,7 @@ Film::read_metadata () _three_d = f.bool_child ("ThreeD"); _interop = f.bool_child ("Interop"); _key = libdcp::Key (f.string_child ("Key")); - _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist")); + _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), version); _dirty = false; } diff --git a/src/lib/image_content.cc b/src/lib/image_content.cc index 14a7c97d5..b05fa6b8d 100644 --- a/src/lib/image_content.cc +++ b/src/lib/image_content.cc @@ -50,7 +50,7 @@ ImageContent::ImageContent (shared_ptr f, boost::filesystem::path p) } -ImageContent::ImageContent (shared_ptr f, shared_ptr node) +ImageContent::ImageContent (shared_ptr f, shared_ptr node, int) : Content (f, node) , VideoContent (f, node) { diff --git a/src/lib/image_content.h b/src/lib/image_content.h index 3da782725..47c5a20e3 100644 --- a/src/lib/image_content.h +++ b/src/lib/image_content.h @@ -31,7 +31,7 @@ class ImageContent : public VideoContent { public: ImageContent (boost::shared_ptr, boost::filesystem::path); - ImageContent (boost::shared_ptr, boost::shared_ptr); + ImageContent (boost::shared_ptr, boost::shared_ptr, int); boost::shared_ptr shared_from_this () { return boost::dynamic_pointer_cast (Content::shared_from_this ()); diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index e2a3c3486..37b290218 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -113,11 +113,11 @@ Playlist::video_identifier () const /** @param node node */ void -Playlist::set_from_xml (shared_ptr film, shared_ptr node) +Playlist::set_from_xml (shared_ptr film, shared_ptr node, int version) { list c = node->node_children ("Content"); for (list::iterator i = c.begin(); i != c.end(); ++i) { - _content.push_back (content_factory (film, *i)); + _content.push_back (content_factory (film, *i, version)); } sort (_content.begin(), _content.end(), ContentSorter ()); diff --git a/src/lib/playlist.h b/src/lib/playlist.h index a1ae9b151..f87b3397b 100644 --- a/src/lib/playlist.h +++ b/src/lib/playlist.h @@ -56,7 +56,7 @@ public: ~Playlist (); void as_xml (xmlpp::Node *); - void set_from_xml (boost::shared_ptr, boost::shared_ptr); + void set_from_xml (boost::shared_ptr, boost::shared_ptr, int); void add (boost::shared_ptr); void remove (boost::shared_ptr); diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc index 706949964..c7879202f 100644 --- a/src/lib/sndfile_content.cc +++ b/src/lib/sndfile_content.cc @@ -43,7 +43,7 @@ SndfileContent::SndfileContent (shared_ptr f, boost::filesystem::pat } -SndfileContent::SndfileContent (shared_ptr f, shared_ptr node) +SndfileContent::SndfileContent (shared_ptr f, shared_ptr node, int) : Content (f, node) , AudioContent (f, node) , _audio_mapping (node->node_child ("AudioMapping")) diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h index 191d62527..701ff16b2 100644 --- a/src/lib/sndfile_content.h +++ b/src/lib/sndfile_content.h @@ -33,7 +33,7 @@ class SndfileContent : public AudioContent { public: SndfileContent (boost::shared_ptr, boost::filesystem::path); - SndfileContent (boost::shared_ptr, boost::shared_ptr); + SndfileContent (boost::shared_ptr, boost::shared_ptr, int); boost::shared_ptr shared_from_this () { return boost::dynamic_pointer_cast (Content::shared_from_this ()); diff --git a/src/lib/util.cc b/src/lib/util.cc index 7ae4f8b16..98dec58d7 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -91,6 +91,7 @@ using std::numeric_limits; using std::pair; using std::ofstream; using std::cout; +using std::streampos; using boost::shared_ptr; using boost::thread; using boost::lexical_cast; @@ -396,6 +397,11 @@ md5_digest (vector files, shared_ptr job) MD5_CTX md5_context; MD5_Init (&md5_context); + vector sizes; + for (size_t i = 0; i < files.size(); ++i) { + sizes.push_back (boost::filesystem::file_size (files[i])); + } + for (size_t i = 0; i < files.size(); ++i) { ifstream f (files[i].string().c_str(), std::ios::binary); if (!f.good ()) { @@ -403,18 +409,19 @@ md5_digest (vector files, shared_ptr job) } f.seekg (0, std::ios::end); - int bytes = f.tellg (); + streampos const bytes = f.tellg (); f.seekg (0, std::ios::beg); - while (bytes > 0) { - int const t = min (bytes, buffer_size); + streampos remaining = bytes; + while (remaining > 0) { + int const t = min (remaining, streampos (buffer_size)); f.read (buffer, t); MD5_Update (&md5_context, buffer, t); - bytes -= t; - } + remaining -= t; - if (job) { - job->set_progress (float (i) / files.size ()); + if (job) { + job->set_progress ((float (i) + 1 - float(remaining) / bytes) / files.size ()); + } } } diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc index ca4ed8a9f..0a19ffd69 100644 --- a/src/lib/video_content.cc +++ b/src/lib/video_content.cc @@ -101,10 +101,11 @@ VideoContent::VideoContent (shared_ptr f, shared_ptr f, vector > c) : Content (f, c) + , _video_length (0) { shared_ptr ref = dynamic_pointer_cast (c[0]); assert (ref); - + for (size_t i = 0; i < c.size(); ++i) { shared_ptr vc = dynamic_pointer_cast (c[i]); @@ -131,6 +132,8 @@ VideoContent::VideoContent (shared_ptr f, vector if (vc->colour_conversion() != ref->colour_conversion()) { throw JoinError (_("Content to be joined must have the same colour conversion.")); } + + _video_length += vc->video_length (); } _video_size = ref->video_size (); diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 1d01e4da8..a4239bd21 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -246,6 +246,7 @@ public: Frame (wxString const & title) : wxFrame (NULL, -1, title) , _servers_list_dialog (0) + , _hints_dialog (0) { wxMenuBar* bar = new wxMenuBar; setup_menu (bar); diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index b3d28db5f..99d607731 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -820,7 +820,9 @@ FilmEditor::selected_content () break; } - sel.push_back (_film->content()[s]); + if (s < int (_film->content().size ())) { + sel.push_back (_film->content()[s]); + } } return sel; diff --git a/src/wx/hints_dialog.cc b/src/wx/hints_dialog.cc index 18b1f5451..668d71321 100644 --- a/src/wx/hints_dialog.cc +++ b/src/wx/hints_dialog.cc @@ -87,7 +87,7 @@ HintsDialog::film_changed () if (vob > 1) { hint = true; - _text->WriteText (wxString::Format (_("You have %d files that look like they are VOB files from DVD. You should coalesce them to ensure smooth joins between the files."), vob)); + _text->WriteText (wxString::Format (_("You have %d files that look like they are VOB files from DVD. You should join them to ensure smooth joins between the files."), vob)); _text->Newline (); } diff --git a/test/stream_test.cc b/test/stream_test.cc index b56f133c7..86bcc5a69 100644 --- a/test/stream_test.cc +++ b/test/stream_test.cc @@ -21,6 +21,7 @@ #include #include #include "lib/ffmpeg_content.h" +#include "lib/film.h" using std::pair; using std::list; @@ -61,7 +62,7 @@ BOOST_AUTO_TEST_CASE (stream_test) map->add_child("DCP")->add_child_text ("2"); } - FFmpegAudioStream a (shared_ptr (new cxml::Node (root))); + FFmpegAudioStream a (shared_ptr (new cxml::Node (root)), Film::state_version); BOOST_CHECK_EQUAL (a.id, 4); BOOST_CHECK_EQUAL (a.frame_rate, 44100); -- 2.30.2