summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-11-24 01:52:23 +0000
committerCarl Hetherington <cth@carlh.net>2013-11-24 01:52:23 +0000
commit8bef34f672815c3c9b4236d06fdee8dfd0bffbc2 (patch)
treed37c47bf3ccb308f7a2959be0c2ef9c0e7ec9575 /src
parentc3da7c64f01420447dbab7f5c2ea42ff1b911cc5 (diff)
Various joining fixes.
Diffstat (limited to 'src')
-rw-r--r--src/lib/content.cc9
-rw-r--r--src/lib/content_factory.cc8
-rw-r--r--src/lib/content_factory.h2
-rw-r--r--src/lib/ffmpeg.cc21
-rw-r--r--src/lib/ffmpeg.h7
-rw-r--r--src/lib/ffmpeg_content.cc88
-rw-r--r--src/lib/ffmpeg_content.h54
-rw-r--r--src/lib/ffmpeg_decoder.cc14
-rw-r--r--src/lib/ffmpeg_examiner.cc12
-rw-r--r--src/lib/film.cc6
-rw-r--r--src/lib/image_content.cc2
-rw-r--r--src/lib/image_content.h2
-rw-r--r--src/lib/playlist.cc4
-rw-r--r--src/lib/playlist.h2
-rw-r--r--src/lib/sndfile_content.cc2
-rw-r--r--src/lib/sndfile_content.h2
-rw-r--r--src/lib/util.cc21
-rw-r--r--src/lib/video_content.cc5
-rw-r--r--src/tools/dcpomatic.cc1
-rw-r--r--src/wx/film_editor.cc4
-rw-r--r--src/wx/hints_dialog.cc2
21 files changed, 188 insertions, 80 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<const Film> f, vector<shared_ptr<Content> > 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>
-content_factory (shared_ptr<const Film> film, cxml::NodePtr node)
+content_factory (shared_ptr<const Film> film, cxml::NodePtr node, int version)
{
string const type = node->string_child ("Type");
boost::shared_ptr<Content> 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> content_factory (boost::shared_ptr<const Film>, cxml::NodePtr);
+extern boost::shared_ptr<Content> content_factory (boost::shared_ptr<const Film>, cxml::NodePtr, int);
extern boost::shared_ptr<Content> content_factory (boost::shared_ptr<const Film>, 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<const FFmpegContent> c, bool long_probe)
+FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
: _ffmpeg_content (c)
, _avio_buffer (0)
, _avio_buffer_size (4096)
@@ -47,7 +46,7 @@ FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> 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<string> (5 * 60 * 1e6).c_str(), 0);
- av_dict_set (&options, "probesize", lexical_cast<string> (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<string> (5 * 60 * 1e6).c_str(), 0);
+ av_dict_set (&options, "probesize", lexical_cast<string> (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<const FFmpegContent>, bool);
+ FFmpeg (boost::shared_ptr<const FFmpegContent>);
virtual ~FFmpeg ();
boost::shared_ptr<const FFmpegContent> 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 <libavformat/avformat.h>
+}
#include <libcxml/cxml.h>
#include "ffmpeg_content.h"
#include "ffmpeg_examiner.h"
@@ -55,7 +58,7 @@ FFmpegContent::FFmpegContent (shared_ptr<const Film> f, boost::filesystem::path
}
-FFmpegContent::FFmpegContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
+FFmpegContent::FFmpegContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node, int version)
: Content (f, node)
, VideoContent (f, node)
, AudioContent (f, node)
@@ -63,7 +66,7 @@ FFmpegContent::FFmpegContent (shared_ptr<const Film> f, shared_ptr<const cxml::N
{
list<cxml::NodePtr> c = node->node_children ("SubtitleStream");
for (list<cxml::NodePtr>::const_iterator i = c.begin(); i != c.end(); ++i) {
- _subtitle_streams.push_back (shared_ptr<FFmpegSubtitleStream> (new FFmpegSubtitleStream (*i)));
+ _subtitle_streams.push_back (shared_ptr<FFmpegSubtitleStream> (new FFmpegSubtitleStream (*i, version)));
if ((*i)->optional_number_child<int> ("Selected")) {
_subtitle_stream = _subtitle_streams.back ();
}
@@ -71,7 +74,7 @@ FFmpegContent::FFmpegContent (shared_ptr<const Film> f, shared_ptr<const cxml::N
c = node->node_children ("AudioStream");
for (list<cxml::NodePtr>::const_iterator i = c.begin(); i != c.end(); ++i) {
- _audio_streams.push_back (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream (*i)));
+ _audio_streams.push_back (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream (*i, version)));
if ((*i)->optional_number_child<int> ("Selected")) {
_audio_stream = _audio_streams.back ();
}
@@ -93,10 +96,10 @@ FFmpegContent::FFmpegContent (shared_ptr<const Film> f, vector<boost::shared_ptr
{
shared_ptr<FFmpegContent> ref = dynamic_pointer_cast<FFmpegContent> (c[0]);
assert (ref);
-
+
for (size_t i = 0; i < c.size(); ++i) {
shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (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<const cxml::Node> node)
- : mapping (node->node_child ("Mapping"))
+FFmpegStream::FFmpegStream (shared_ptr<const cxml::Node> node, int version)
+ : _legacy_id (false)
{
name = node->string_child ("Name");
id = node->number_child<int> ("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<string> (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<const cxml::Node> node, int version)
+ : FFmpegStream (node, version)
+ , mapping (node->node_child ("Mapping"))
+{
frame_rate = node->number_child<int> ("FrameRate");
channels = node->number_child<int64_t> ("Channels");
first_audio = node->optional_number_child<double> ("FirstAudio");
@@ -359,8 +384,7 @@ FFmpegAudioStream::FFmpegAudioStream (shared_ptr<const cxml::Node> 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<string> (id));
+ FFmpegStream::as_xml (root);
root->add_child("FrameRate")->add_child_text (lexical_cast<string> (frame_rate));
root->add_child("Channels")->add_child_text (lexical_cast<string> (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<const cxml::Node> node)
+FFmpegSubtitleStream::FFmpegSubtitleStream (shared_ptr<const cxml::Node> node, int version)
+ : FFmpegStream (node, version)
{
- name = node->string_child ("Name");
- id = node->number_child<int> ("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<string> (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<const cxml::Node>, 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<const cxml::Node>);
+ FFmpegAudioStream (boost::shared_ptr<const cxml::Node>, 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<const cxml::Node>);
+ FFmpegSubtitleStream (boost::shared_ptr<const cxml::Node>, 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<const Film>, boost::filesystem::path);
- FFmpegContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
+ FFmpegContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>, int version);
FFmpegContent (boost::shared_ptr<const Film>, std::vector<boost::shared_ptr<Content> >);
boost::shared_ptr<FFmpegContent> 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<const Film> f, shared_ptr<const FFmpegC
, VideoDecoder (f, c)
, AudioDecoder (f, c)
, SubtitleDecoder (f)
- , FFmpeg (c, false)
+ , FFmpeg (c)
, _subtitle_codec_context (0)
, _subtitle_codec (0)
, _decode_video (video)
@@ -171,12 +171,14 @@ FFmpegDecoder::pass ()
shared_ptr<const Film> 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<const FFmpegContent> c)
- : FFmpeg (c, true)
+ : FFmpeg (c)
{
/* Find audio and subtitle streams */
@@ -50,12 +52,12 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c)
_audio_streams.push_back (
shared_ptr<FFmpegAudioStream> (
- 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<FFmpegSubtitleStream> (new FFmpegSubtitleStream (subtitle_stream_name (s), i)));
+ _subtitle_streams.push_back (shared_ptr<FFmpegSubtitleStream> (new FFmpegSubtitleStream (subtitle_stream_name (s), s->id)));
}
}
@@ -78,9 +80,9 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> 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<int> ("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<const Film> f, boost::filesystem::path p)
}
-ImageContent::ImageContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
+ImageContent::ImageContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> 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<const Film>, boost::filesystem::path);
- ImageContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
+ ImageContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>, int);
boost::shared_ptr<ImageContent> shared_from_this () {
return boost::dynamic_pointer_cast<ImageContent> (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 <Playlist> node */
void
-Playlist::set_from_xml (shared_ptr<const Film> film, shared_ptr<const cxml::Node> node)
+Playlist::set_from_xml (shared_ptr<const Film> film, shared_ptr<const cxml::Node> node, int version)
{
list<cxml::NodePtr> c = node->node_children ("Content");
for (list<cxml::NodePtr>::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<const Film>, boost::shared_ptr<const cxml::Node>);
+ void set_from_xml (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>, int);
void add (boost::shared_ptr<Content>);
void remove (boost::shared_ptr<Content>);
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<const Film> f, boost::filesystem::pat
}
-SndfileContent::SndfileContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
+SndfileContent::SndfileContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> 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<const Film>, boost::filesystem::path);
- SndfileContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
+ SndfileContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>, int);
boost::shared_ptr<SndfileContent> shared_from_this () {
return boost::dynamic_pointer_cast<SndfileContent> (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<boost::filesystem::path> files, shared_ptr<Job> job)
MD5_CTX md5_context;
MD5_Init (&md5_context);
+ vector<int64_t> 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<boost::filesystem::path> files, shared_ptr<Job> 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<const Film> f, shared_ptr<const cxml::Nod
VideoContent::VideoContent (shared_ptr<const Film> f, vector<shared_ptr<Content> > c)
: Content (f, c)
+ , _video_length (0)
{
shared_ptr<VideoContent> ref = dynamic_pointer_cast<VideoContent> (c[0]);
assert (ref);
-
+
for (size_t i = 0; i < c.size(); ++i) {
shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (c[i]);
@@ -131,6 +132,8 @@ VideoContent::VideoContent (shared_ptr<const Film> f, vector<shared_ptr<Content>
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 ();
}