int const AudioContentProperty::AUDIO_DELAY = 204;
int const AudioContentProperty::AUDIO_MAPPING = 205;
+AudioContent::AudioContent (shared_ptr<const Film> f)
+ : Content (f)
+ , _audio_gain (0)
+ , _audio_delay (Config::instance()->default_audio_delay ())
+{
+
+}
+
AudioContent::AudioContent (shared_ptr<const Film> f, DCPTime s)
: Content (f, s)
, _audio_gain (0)
public:
typedef int64_t Frame;
+ AudioContent (boost::shared_ptr<const Film>);
AudioContent (boost::shared_ptr<const Film>, DCPTime);
AudioContent (boost::shared_ptr<const Film>, boost::filesystem::path);
AudioContent (boost::shared_ptr<const Film>, cxml::ConstNodePtr);
--- /dev/null
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ 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.
+
+*/
+
+class AudioExaminer
+{
+public:
+ virtual ~AudioExaminer () {}
+
+ virtual int audio_channels () const = 0;
+ virtual ContentTime audio_length () const = 0;
+ virtual int audio_frame_rate () const = 0;
+};
--- /dev/null
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ 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.
+
+*/
+
+#include <dcp/dcp.h>
+#include "dcp_content.h"
+#include "dcp_examiner.h"
+#include "job.h"
+#include "film.h"
+#include "compose.hpp"
+
+#include "i18n.h"
+
+using std::string;
+using boost::shared_ptr;
+
+DCPContent::DCPContent (shared_ptr<const Film> f, boost::filesystem::path p)
+ : Content (f)
+ , VideoContent (f)
+ , SingleStreamAudioContent (f)
+ , SubtitleContent (f)
+ , _directory (p)
+{
+ read_directory (p);
+}
+
+void
+DCPContent::read_directory (boost::filesystem::path p)
+{
+ for (boost::filesystem::directory_iterator i(p); i != boost::filesystem::directory_iterator(); ++i) {
+ if (boost::filesystem::is_regular_file (i->path ())) {
+ _paths.push_back (i->path ());
+ } else if (boost::filesystem::is_directory (i->path ())) {
+ read_directory (i->path ());
+ }
+ }
+}
+
+void
+DCPContent::examine (shared_ptr<Job> job)
+{
+ job->set_progress_unknown ();
+ Content::examine (job);
+ shared_ptr<VideoExaminer> examiner (new DCPExaminer (shared_from_this ()));
+ take_from_video_examiner (examiner);
+}
+
+string
+DCPContent::summary () const
+{
+ return String::compose (_("%1 [DCP]"), path_summary ());
+}
+
+string
+DCPContent::technical_summary () const
+{
+ return Content::technical_summary() + " - "
+ + VideoContent::technical_summary() + " - "
+ + AudioContent::technical_summary() + " - ";
+}
+
+void
+DCPContent::as_xml (xmlpp::Node* node) const
+{
+ node->add_child("Type")->add_child_text ("DCP");
+ Content::as_xml (node);
+ VideoContent::as_xml (node);
+ SingleStreamAudioContent::as_xml (node);
+}
+
+DCPTime
+DCPContent::full_length () const
+{
+ shared_ptr<const Film> film = _film.lock ();
+ assert (film);
+ return DCPTime (video_length (), FrameRateChange (video_frame_rate (), film->video_frame_rate ()));
+}
--- /dev/null
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ 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.
+
+*/
+
+#include "video_content.h"
+#include "single_stream_audio_content.h"
+#include "subtitle_content.h"
+
+class DCPContent : public VideoContent, public SingleStreamAudioContent, public SubtitleContent
+{
+public:
+ DCPContent (boost::shared_ptr<const Film> f, boost::filesystem::path p);
+
+ boost::shared_ptr<DCPContent> shared_from_this () {
+ return boost::dynamic_pointer_cast<DCPContent> (Content::shared_from_this ());
+ }
+
+ DCPTime full_length () const;
+
+ void examine (boost::shared_ptr<Job>);
+ std::string summary () const;
+ std::string technical_summary () const;
+ void as_xml (xmlpp::Node *) const;
+
+ boost::filesystem::path directory () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _directory;
+ }
+
+private:
+ void read_directory (boost::filesystem::path);
+
+ boost::filesystem::path _directory;
+};
--- /dev/null
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ 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.
+
+*/
+
+#include <dcp/dcp.h>
+#include <dcp/cpl.h>
+#include <dcp/reel.h>
+#include <dcp/mono_picture_mxf.h>
+#include <dcp/stereo_picture_mxf.h>
+#include <dcp/reel_picture_asset.h>
+#include <dcp/mono_picture_frame.h>
+#include <dcp/stereo_picture_frame.h>
+#include "dcp_decoder.h"
+#include "dcp_content.h"
+#include "image_proxy.h"
+#include "image.h"
+
+using std::list;
+using std::cout;
+using boost::shared_ptr;
+using boost::dynamic_pointer_cast;
+
+DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c, shared_ptr<Log> log)
+ : VideoDecoder (c)
+ , AudioDecoder (c)
+ , SubtitleDecoder (c)
+ , _log (log)
+ , _dcp_content (c)
+{
+ dcp::DCP dcp (c->directory ());
+ dcp.read ();
+ assert (dcp.cpls().size() == 1);
+ _reels = dcp.cpls().front()->reels ();
+ _reel = _reels.begin ();
+}
+
+bool
+DCPDecoder::pass ()
+{
+ if (_reel == _reels.end ()) {
+ return true;
+ }
+
+ float const vfr = _dcp_content->video_frame_rate ();
+
+ if ((*_reel)->main_picture ()) {
+ shared_ptr<dcp::PictureMXF> mxf = (*_reel)->main_picture()->mxf ();
+ shared_ptr<dcp::MonoPictureMXF> mono = dynamic_pointer_cast<dcp::MonoPictureMXF> (mxf);
+ shared_ptr<dcp::StereoPictureMXF> stereo = dynamic_pointer_cast<dcp::StereoPictureMXF> (mxf);
+ if (mono) {
+ shared_ptr<Image> image (new Image (PIX_FMT_RGB24, mxf->size(), false));
+ mono->get_frame (_next.frames (vfr))->rgb_frame (image->data()[0]);
+ shared_ptr<Image> aligned (new Image (image, true));
+ video (shared_ptr<ImageProxy> (new RawImageProxy (aligned, _log)), _next.frames (vfr));
+ } else {
+
+ shared_ptr<Image> left (new Image (PIX_FMT_RGB24, mxf->size(), false));
+ stereo->get_frame (_next.frames (vfr))->rgb_frame (dcp::EYE_LEFT, left->data()[0]);
+ shared_ptr<Image> aligned_left (new Image (left, true));
+ video (shared_ptr<ImageProxy> (new RawImageProxy (aligned_left, _log)), _next.frames (vfr));
+
+ shared_ptr<Image> right (new Image (PIX_FMT_RGB24, mxf->size(), false));
+ stereo->get_frame (_next.frames (vfr))->rgb_frame (dcp::EYE_RIGHT, right->data()[0]);
+ shared_ptr<Image> aligned_right (new Image (right, true));
+ video (shared_ptr<ImageProxy> (new RawImageProxy (aligned_right, _log)), _next.frames (vfr));
+ }
+ }
+
+ /* XXX: sound */
+ /* XXX: subtitle */
+
+ _next += ContentTime::from_frames (1, vfr);
+
+ if ((*_reel)->main_picture ()) {
+ if ((*_reel)->main_picture()->duration() >= _next.frames (vfr)) {
+ ++_reel;
+ }
+ }
+
+ return false;
+}
+
+void
+DCPDecoder::seek (ContentTime t, bool accurate)
+{
+ VideoDecoder::seek (t, accurate);
+ AudioDecoder::seek (t, accurate);
+ SubtitleDecoder::seek (t, accurate);
+
+ _reel = _reels.begin ();
+ while (_reel != _reels.end() && t >= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->video_frame_rate ())) {
+ t -= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->video_frame_rate ());
+ ++_reel;
+ }
+
+ _next = t;
+}
+
+
+list<ContentTimePeriod>
+DCPDecoder::subtitles_during (ContentTimePeriod, bool starting) const
+{
+ return list<ContentTimePeriod> ();
+}
--- /dev/null
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ 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.
+
+*/
+
+#include "video_decoder.h"
+#include "audio_decoder.h"
+#include "subtitle_decoder.h"
+
+namespace dcp {
+ class Reel;
+}
+
+class DCPContent;
+class Log;
+
+class DCPDecoder : public VideoDecoder, public AudioDecoder, public SubtitleDecoder
+{
+public:
+ DCPDecoder (boost::shared_ptr<const DCPContent>, boost::shared_ptr<Log>);
+
+private:
+ void seek (ContentTime t, bool accurate);
+ bool pass ();
+ std::list<ContentTimePeriod> subtitles_during (ContentTimePeriod, bool starting) const;
+
+ ContentTime _next;
+ std::list<boost::shared_ptr<dcp::Reel> > _reels;
+ std::list<boost::shared_ptr<dcp::Reel> >::iterator _reel;
+ boost::shared_ptr<Log> _log;
+ boost::shared_ptr<const DCPContent> _dcp_content;
+};
--- /dev/null
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ 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.
+
+*/
+
+#include <dcp/dcp.h>
+#include <dcp/cpl.h>
+#include <dcp/reel.h>
+#include <dcp/reel_picture_asset.h>
+#include <dcp/reel_sound_asset.h>
+#include <dcp/sound_mxf.h>
+#include "dcp_examiner.h"
+#include "dcp_content.h"
+#include "exceptions.h"
+
+#include "i18n.h"
+
+using std::list;
+using boost::shared_ptr;
+
+DCPExaminer::DCPExaminer (shared_ptr<const DCPContent> content)
+{
+ dcp::DCP dcp (content->directory ());
+ dcp.read ();
+
+ if (dcp.cpls().size() == 0) {
+ throw DCPError ("No CPLs found in DCP");
+ } else if (dcp.cpls().size() > 1) {
+ throw DCPError ("Multiple CPLs found in DCP");
+ }
+
+ list<shared_ptr<dcp::Reel> > reels = dcp.cpls().front()->reels ();
+ for (list<shared_ptr<dcp::Reel> >::const_iterator i = reels.begin(); i != reels.end(); ++i) {
+
+ if ((*i)->main_picture ()) {
+ dcp::Fraction const frac = (*i)->main_picture()->frame_rate ();
+ float const fr = float(frac.numerator) / frac.denominator;
+ if (!_video_frame_rate) {
+ _video_frame_rate = fr;
+ } else if (_video_frame_rate.get() != fr) {
+ throw DCPError (_("Mismatched frame rates in DCP"));
+ }
+
+ shared_ptr<dcp::PictureMXF> mxf = (*i)->main_picture()->mxf ();
+ if (!_video_size) {
+ _video_size = mxf->size ();
+ } else if (_video_size.get() != mxf->size ()) {
+ throw DCPError (_("Mismatched video sizes in DCP"));
+ }
+
+ _video_length += ContentTime::from_frames ((*i)->main_picture()->duration(), _video_frame_rate.get ());
+ }
+
+ if ((*i)->main_sound ()) {
+ shared_ptr<dcp::SoundMXF> mxf = (*i)->main_sound()->mxf ();
+
+ if (!_audio_channels) {
+ _audio_channels = mxf->channels ();
+ } else if (_audio_channels.get() != mxf->channels ()) {
+ throw DCPError (_("Mismatched audio channel counts in DCP"));
+ }
+
+ if (!_audio_frame_rate) {
+ _audio_frame_rate = mxf->sampling_rate ();
+ } else if (_audio_frame_rate.get() != mxf->sampling_rate ()) {
+ throw DCPError (_("Mismatched audio frame rates in DCP"));
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ 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.
+
+*/
+
+#include "video_examiner.h"
+
+class DCPContent;
+
+class DCPExaminer : public VideoExaminer
+{
+public:
+ DCPExaminer (boost::shared_ptr<const DCPContent>);
+
+ float video_frame_rate () const {
+ return _video_frame_rate.get_value_or (24);
+ }
+
+ dcp::Size video_size () const {
+ return _video_size.get_value_or (dcp::Size (1998, 1080));
+ }
+
+ ContentTime video_length () const {
+ return _video_length;
+ }
+
+private:
+ boost::optional<float> _video_frame_rate;
+ boost::optional<dcp::Size> _video_size;
+ ContentTime _video_length;
+ boost::optional<int> _audio_channels;
+ boost::optional<int> _audio_frame_rate;
+};
SubRipError (std::string, std::string, boost::filesystem::path);
};
+class DCPError : public StringError
+{
+public:
+ DCPError (std::string s)
+ : StringError (s)
+ {}
+};
+
/** @class ExceptionStore
* @brief A parent class for classes which have a need to catch and
* re-throw exceptions.
-
+ *
* This is intended for classes which run their own thread; they should do
* something like
*
shared_ptr<const Film> film = _film.lock ();
assert (film);
- LOG_GENERAL ("Video length obtained from header as %1 frames", video_length.frames (video_frame_rate ()));
{
boost::mutex::scoped_lock lm (_mutex);
#include "content_video.h"
#include "player_video.h"
#include "frame_rate_change.h"
+#include "dcp_content.h"
+#include "dcp_decoder.h"
#define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
frc = FrameRateChange (fc->video_frame_rate(), _film->video_frame_rate());
}
+ shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (*i);
+ if (dc) {
+ decoder.reset (new DCPDecoder (dc, _film->log ()));
+ frc = FrameRateChange (dc->video_frame_rate(), _film->video_frame_rate());
+ }
+
/* ImageContent */
shared_ptr<const ImageContent> ic = dynamic_pointer_cast<const ImageContent> (*i);
if (ic) {
--- /dev/null
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ 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.
+
+*/
+
+#include <dcp/raw_convert.h>
+#include "single_stream_audio_content.h"
+#include "audio_examiner.h"
+#include "film.h"
+
+using std::string;
+using boost::shared_ptr;
+using dcp::raw_convert;
+
+SingleStreamAudioContent::SingleStreamAudioContent (shared_ptr<const Film> f)
+ : Content (f)
+ , AudioContent (f)
+ , _audio_channels (0)
+ , _audio_length (0)
+ , _audio_frame_rate (0)
+{
+
+}
+
+SingleStreamAudioContent::SingleStreamAudioContent (shared_ptr<const Film> f, boost::filesystem::path p)
+ : Content (f, p)
+ , AudioContent (f, p)
+ , _audio_channels (0)
+ , _audio_length (0)
+ , _audio_frame_rate (0)
+{
+
+}
+
+SingleStreamAudioContent::SingleStreamAudioContent (shared_ptr<const Film> f, cxml::ConstNodePtr node, int version)
+ : Content (f, node)
+ , AudioContent (f, node)
+ , _audio_mapping (node->node_child ("AudioMapping"), version)
+{
+ _audio_channels = node->number_child<int> ("AudioChannels");
+ _audio_length = ContentTime (node->number_child<ContentTime::Type> ("AudioLength"));
+ _audio_frame_rate = node->number_child<int> ("AudioFrameRate");
+}
+
+void
+SingleStreamAudioContent::set_audio_mapping (AudioMapping m)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ _audio_mapping = m;
+ }
+
+ AudioContent::set_audio_mapping (m);
+}
+
+
+void
+SingleStreamAudioContent::as_xml (xmlpp::Node* node) const
+{
+ AudioContent::as_xml (node);
+ node->add_child("AudioChannels")->add_child_text (raw_convert<string> (audio_channels ()));
+ node->add_child("AudioLength")->add_child_text (raw_convert<string> (audio_length().get ()));
+ node->add_child("AudioFrameRate")->add_child_text (raw_convert<string> (audio_frame_rate ()));
+ _audio_mapping.as_xml (node->add_child("AudioMapping"));
+}
+
+void
+SingleStreamAudioContent::take_from_audio_examiner (shared_ptr<AudioExaminer> examiner)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ _audio_channels = examiner->audio_channels ();
+ _audio_length = examiner->audio_length ();
+ _audio_frame_rate = examiner->audio_frame_rate ();
+ }
+
+ signal_changed (AudioContentProperty::AUDIO_CHANNELS);
+ signal_changed (AudioContentProperty::AUDIO_LENGTH);
+ signal_changed (AudioContentProperty::AUDIO_FRAME_RATE);
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ /* XXX: do this in signal_changed...? */
+ _audio_mapping = AudioMapping (_audio_channels);
+ _audio_mapping.make_default ();
+ }
+
+ signal_changed (AudioContentProperty::AUDIO_MAPPING);
+}
--- /dev/null
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ 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_SINGLE_STREAM_AUDIO_CONTENT_H
+#define DCPOMATIC_SINGLE_STREAM_AUDIO_CONTENT_H
+
+#include "audio_content.h"
+
+class AudioExaminer;
+
+class SingleStreamAudioContent : public AudioContent
+{
+public:
+ SingleStreamAudioContent (boost::shared_ptr<const Film>);
+ SingleStreamAudioContent (boost::shared_ptr<const Film>, boost::filesystem::path);
+ SingleStreamAudioContent (boost::shared_ptr<const Film> f, cxml::ConstNodePtr node, int version);
+
+ void as_xml (xmlpp::Node* node) const;
+
+ /* AudioContent */
+ int audio_channels () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _audio_channels;
+ }
+
+ ContentTime audio_length () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _audio_length;
+ }
+
+ int audio_frame_rate () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _audio_frame_rate;
+ }
+
+ AudioMapping audio_mapping () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _audio_mapping;
+ }
+
+ void set_audio_mapping (AudioMapping);
+
+ void take_from_audio_examiner (boost::shared_ptr<AudioExaminer>);
+
+protected:
+ int _audio_channels;
+ ContentTime _audio_length;
+ int _audio_frame_rate;
+ AudioMapping _audio_mapping;
+};
+
+#endif
SndfileContent::SndfileContent (shared_ptr<const Film> f, boost::filesystem::path p)
: Content (f, p)
- , AudioContent (f, p)
- , _audio_channels (0)
- , _audio_length (0)
- , _audio_frame_rate (0)
+ , SingleStreamAudioContent (f, p)
{
}
SndfileContent::SndfileContent (shared_ptr<const Film> f, cxml::ConstNodePtr node, int version)
: Content (f, node)
- , AudioContent (f, node)
- , _audio_mapping (node->node_child ("AudioMapping"), version)
+ , SingleStreamAudioContent (f, node, version)
{
- _audio_channels = node->number_child<int> ("AudioChannels");
- _audio_length = ContentTime (node->number_child<ContentTime::Type> ("AudioLength"));
- _audio_frame_rate = node->number_child<int> ("AudioFrameRate");
+
+}
+
+void
+SndfileContent::as_xml (xmlpp::Node* node) const
+{
+ node->add_child("Type")->add_child_text ("Sndfile");
+ Content::as_xml (node);
+ SingleStreamAudioContent::as_xml (node);
}
+
string
SndfileContent::summary () const
{
{
job->set_progress_unknown ();
Content::examine (job);
-
- SndfileDecoder dec (shared_from_this());
-
- {
- boost::mutex::scoped_lock lm (_mutex);
- _audio_channels = dec.audio_channels ();
- _audio_length = dec.audio_length ();
- _audio_frame_rate = dec.audio_frame_rate ();
- }
-
- signal_changed (AudioContentProperty::AUDIO_CHANNELS);
- signal_changed (AudioContentProperty::AUDIO_LENGTH);
- signal_changed (AudioContentProperty::AUDIO_FRAME_RATE);
-
- {
- boost::mutex::scoped_lock lm (_mutex);
- /* XXX: do this in signal_changed...? */
- _audio_mapping = AudioMapping (_audio_channels);
- _audio_mapping.make_default ();
- }
-
- signal_changed (AudioContentProperty::AUDIO_MAPPING);
-}
-
-void
-SndfileContent::as_xml (xmlpp::Node* node) const
-{
- node->add_child("Type")->add_child_text ("Sndfile");
- Content::as_xml (node);
- AudioContent::as_xml (node);
-
- node->add_child("AudioChannels")->add_child_text (raw_convert<string> (audio_channels ()));
- node->add_child("AudioLength")->add_child_text (raw_convert<string> (audio_length().get ()));
- node->add_child("AudioFrameRate")->add_child_text (raw_convert<string> (audio_frame_rate ()));
- _audio_mapping.as_xml (node->add_child("AudioMapping"));
+ shared_ptr<AudioExaminer> dec (new SndfileDecoder (shared_from_this()));
+ take_from_audio_examiner (dec);
}
DCPTime
return DCPTime (audio_length(), film->active_frame_rate_change (position ()));
}
-void
-SndfileContent::set_audio_mapping (AudioMapping m)
-{
- {
- boost::mutex::scoped_lock lm (_mutex);
- _audio_mapping = m;
- }
-
- AudioContent::set_audio_mapping (m);
-}
extern "C" {
#include <libavutil/audioconvert.h>
}
-#include "audio_content.h"
+#include "single_stream_audio_content.h"
namespace cxml {
class Node;
}
-class SndfileContent : public AudioContent
+class SndfileContent : public SingleStreamAudioContent
{
public:
SndfileContent (boost::shared_ptr<const Film>, boost::filesystem::path);
return boost::dynamic_pointer_cast<SndfileContent> (Content::shared_from_this ());
}
+ DCPTime full_length () const;
+
void examine (boost::shared_ptr<Job>);
std::string summary () const;
std::string technical_summary () const;
std::string information () const;
void as_xml (xmlpp::Node *) const;
- DCPTime full_length () const;
-
- /* AudioContent */
- int audio_channels () const {
- boost::mutex::scoped_lock lm (_mutex);
- return _audio_channels;
- }
-
- ContentTime audio_length () const {
- boost::mutex::scoped_lock lm (_mutex);
- return _audio_length;
- }
-
- int audio_frame_rate () const {
- boost::mutex::scoped_lock lm (_mutex);
- return _audio_frame_rate;
- }
-
- AudioMapping audio_mapping () const {
- boost::mutex::scoped_lock lm (_mutex);
- return _audio_mapping;
- }
-
- void set_audio_mapping (AudioMapping);
static bool valid_file (boost::filesystem::path);
-
-private:
- int _audio_channels;
- ContentTime _audio_length;
- int _audio_frame_rate;
- AudioMapping _audio_mapping;
};
#endif
#include <sndfile.h>
#include "decoder.h"
#include "audio_decoder.h"
+#include "audio_examiner.h"
class SndfileContent;
-class SndfileDecoder : public AudioDecoder
+class SndfileDecoder : public AudioDecoder, public AudioExaminer
{
public:
SndfileDecoder (boost::shared_ptr<const SndfileContent> c);
int const SubtitleContentProperty::SUBTITLE_SCALE = 502;
int const SubtitleContentProperty::SUBTITLE_USE = 503;
+SubtitleContent::SubtitleContent (shared_ptr<const Film> f)
+ : Content (f)
+ , _subtitle_use (false)
+ , _subtitle_x_offset (0)
+ , _subtitle_y_offset (0)
+ , _subtitle_scale (1)
+{
+
+}
+
SubtitleContent::SubtitleContent (shared_ptr<const Film> f, boost::filesystem::path p)
: Content (f, p)
, _subtitle_use (false)
class SubtitleContent : public virtual Content
{
public:
+ SubtitleContent (boost::shared_ptr<const Film>);
SubtitleContent (boost::shared_ptr<const Film>, boost::filesystem::path);
SubtitleContent (boost::shared_ptr<const Film>, cxml::ConstNodePtr, int version);
SubtitleContent (boost::shared_ptr<const Film>, std::vector<boost::shared_ptr<Content> >);
#include "film.h"
#include "exceptions.h"
#include "frame_rate_change.h"
+#include "log.h"
#include "i18n.h"
+#define LOG_GENERAL(...) film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
+
int const VideoContentProperty::VIDEO_SIZE = 0;
int const VideoContentProperty::VIDEO_FRAME_RATE = 1;
int const VideoContentProperty::VIDEO_FRAME_TYPE = 2;
_video_frame_rate = vfr;
_video_length = vl;
}
+
+ shared_ptr<const Film> film = _film.lock ();
+ assert (film);
+ LOG_GENERAL ("Video length obtained from header as %1 frames", _video_length.frames (_video_frame_rate));
signal_changed (VideoContentProperty::VIDEO_SIZE);
signal_changed (VideoContentProperty::VIDEO_FRAME_RATE);
#else
: _video_content (c)
#endif
+ , _same (false)
{
}
void
VideoDecoder::video (shared_ptr<const ImageProxy> image, VideoFrame frame)
{
- /* We should not receive the same thing twice */
- assert (_decoded_video.empty() || frame != _decoded_video.back().frame);
+ /* We may receive the same frame index twice for 3D, and we need to know
+ when that happens.
+ */
+ _same = (!_decoded_video.empty() && frame == _decoded_video.back().frame);
/* Fill in gaps */
/* XXX: 3D */
_decoded_video.push_back (ContentVideo (image, EYES_BOTH, PART_WHOLE, frame));
break;
case VIDEO_FRAME_TYPE_3D_ALTERNATE:
- _decoded_video.push_back (ContentVideo (image, (frame % 2) ? EYES_RIGHT : EYES_LEFT, PART_WHOLE, frame));
+ _decoded_video.push_back (ContentVideo (image, _same ? EYES_RIGHT : EYES_LEFT, PART_WHOLE, frame));
break;
case VIDEO_FRAME_TYPE_3D_LEFT_RIGHT:
_decoded_video.push_back (ContentVideo (image, EYES_LEFT, PART_LEFT_HALF, frame));
boost::shared_ptr<const VideoContent> _video_content;
std::list<ContentVideo> _decoded_video;
+ bool _same;
};
#endif
content_factory.cc
content_subtitle.cc
cross.cc
+ dcp_content.cc
dcp_content_type.cc
+ dcp_decoder.cc
+ dcp_examiner.cc
dcp_video.cc
dcpomatic_time.cc
dolby_cp750.cc
send_kdm_email_job.cc
server.cc
server_finder.cc
+ single_stream_audio_content.cc
sndfile_content.cc
sndfile_decoder.cc
sound_processor.cc
#include "lib/playlist.h"
#include "lib/content.h"
#include "lib/content_factory.h"
+#include "lib/dcp_content.h"
#include "timecode.h"
#include "wx_util.h"
#include "film_editor.h"
return;
}
- shared_ptr<ImageContent> ic;
+ shared_ptr<Content> content;
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;
+ content.reset (new ImageContent (_film, boost::filesystem::path (wx_to_std (d->GetPath ()))));
+ } catch (...) {
+ try {
+ content.reset (new DCPContent (_film, boost::filesystem::path (wx_to_std (d->GetPath ()))));
+ } catch (...) {
+ error_dialog (this, _("Could not find any images nor a DCP in that folder"));
+ return;
+ }
}
- _film->examine_and_add_content (ic);
+ if (content) {
+ _film->examine_and_add_content (content);
+ }
}
void