*/
+
/** @file src/lib/content.cc
* @brief Content class.
*/
+
#include "content.h"
#include "change_signaller.h"
#include "util.h"
#include "i18n.h"
-using std::string;
-using std::list;
+
using std::cout;
-using std::vector;
+using std::list;
+using std::make_shared;
using std::max;
using std::pair;
using std::shared_ptr;
+using std::string;
+using std::vector;
using boost::optional;
-using dcp::raw_convert;
using dcp::locale_convert;
+using dcp::raw_convert;
using namespace dcpomatic;
+
int const ContentProperty::PATH = 400;
int const ContentProperty::POSITION = 401;
int const ContentProperty::LENGTH = 402;
int const ContentProperty::TRIM_END = 404;
int const ContentProperty::VIDEO_FRAME_RATE = 405;
+
Content::Content ()
- : _position (0)
- , _trim_start (0)
- , _trim_end (0)
- , _change_signals_frequent (false)
+ : _change_signals_frequent (false)
{
}
+
Content::Content (DCPTime p)
: _position (p)
- , _trim_start (0)
- , _trim_end (0)
, _change_signals_frequent (false)
{
}
+
Content::Content (boost::filesystem::path p)
- : _position (0)
- , _trim_start (0)
- , _trim_end (0)
- , _change_signals_frequent (false)
+ : _change_signals_frequent (false)
{
add_path (p);
}
+
Content::Content (cxml::ConstNodePtr node)
: _change_signals_frequent (false)
{
_video_frame_rate = node->optional_number_child<double> ("VideoFrameRate");
}
-Content::Content (vector<shared_ptr<Content> > c)
- : _position (c.front()->position ())
- , _trim_start (c.front()->trim_start ())
- , _trim_end (c.back()->trim_end ())
+
+Content::Content (vector<shared_ptr<Content>> c)
+ : _position (c.front()->position())
+ , _trim_start (c.front()->trim_start())
+ , _trim_end (c.back()->trim_end())
, _video_frame_rate (c.front()->video_frame_rate())
, _change_signals_frequent (false)
{
}
}
+
void
Content::as_xml (xmlpp::Node* node, bool with_paths) const
{
if (with_paths) {
for (size_t i = 0; i < _paths.size(); ++i) {
- xmlpp::Element* p = node->add_child("Path");
+ auto p = node->add_child("Path");
p->add_child_text (_paths[i].string());
p->set_attribute ("mtime", raw_convert<string>(_last_write_times[i]));
}
}
- node->add_child("Digest")->add_child_text (_digest);
- node->add_child("Position")->add_child_text (raw_convert<string> (_position.get ()));
- node->add_child("TrimStart")->add_child_text (raw_convert<string> (_trim_start.get ()));
- node->add_child("TrimEnd")->add_child_text (raw_convert<string> (_trim_end.get ()));
+ node->add_child("Digest")->add_child_text(_digest);
+ node->add_child("Position")->add_child_text(raw_convert<string>(_position.get()));
+ node->add_child("TrimStart")->add_child_text(raw_convert<string>(_trim_start.get()));
+ node->add_child("TrimEnd")->add_child_text(raw_convert<string>(_trim_end.get()));
if (_video_frame_rate) {
- node->add_child("VideoFrameRate")->add_child_text (raw_convert<string> (_video_frame_rate.get()));
+ node->add_child("VideoFrameRate")->add_child_text(raw_convert<string>(_video_frame_rate.get()));
}
}
+
string
Content::calculate_digest () const
{
return digest_head_tail(p, 1000000) + raw_convert<string>(boost::filesystem::file_size(p.front()));
}
+
void
Content::examine (shared_ptr<const Film>, shared_ptr<Job> job)
{
}
}
+
void
Content::signal_change (ChangeType c, int p)
{
}
}
+
void
Content::set_position (shared_ptr<const Film> film, DCPTime p, bool force_emit)
{
}
}
+
void
Content::set_trim_start (ContentTime t)
{
}
}
+
void
Content::set_trim_end (ContentTime t)
{
/* notes is unused here (we assume) */
list<string> notes;
- return content_factory (cxml::NodePtr(new cxml::Node(node)), Film::current_state_version, notes);
+ return content_factory (make_shared<cxml::Node>(node), Film::current_state_version, notes);
}
+
string
Content::technical_summary () const
{
return s;
}
+
DCPTime
Content::length_after_trim (shared_ptr<const Film> film) const
{
return length;
}
+
/** @return string which changes when something about this content changes which affects
* the appearance of its video.
*/
return buffer;
}
+
bool
Content::paths_valid () const
{
return true;
}
+
void
Content::set_paths (vector<boost::filesystem::path> paths)
{
}
}
+
string
Content::path_summary () const
{
return s;
}
+
/** @return a list of properties that might be interesting to the user */
list<UserProperty>
Content::user_properties (shared_ptr<const Film> film) const
return p;
}
+
/** @return DCP times of points within this content where a reel split could occur */
list<DCPTime>
Content::reel_split_points (shared_ptr<const Film>) const
return t;
}
+
void
Content::set_video_frame_rate (double r)
{
}
}
+
void
Content::unset_video_frame_rate ()
{
}
}
+
double
Content::active_video_frame_rate (shared_ptr<const Film> film) const
{
return film->active_frame_rate_change(position()).source;
}
+
void
Content::add_properties (shared_ptr<const Film>, list<UserProperty>& p) const
{
}
}
+
/** Take settings from the given content if it is of the correct type */
void
Content::take_settings_from (shared_ptr<const Content> c)
}
}
+
shared_ptr<TextContent>
Content::only_text () const
{
DCPOMATIC_ASSERT (text.size() < 2);
- if (text.empty ()) {
- return shared_ptr<TextContent> ();
+ if (text.empty()) {
+ return {};
}
return text.front ();
}
+
shared_ptr<TextContent>
Content::text_of_original_type (TextType type) const
{
}
}
- return shared_ptr<TextContent> ();
+ return {};
}
+
void
Content::add_path (boost::filesystem::path p)
{
/*
- Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
/** @file src/lib/content.h
* @brief Content class.
*/
+
#ifndef DCPOMATIC_CONTENT_H
#define DCPOMATIC_CONTENT_H
static int const VIDEO_FRAME_RATE;
};
+
/** @class Content
* @brief A piece of content represented by one or more files on disk.
*/
-class Content : public std::enable_shared_from_this<Content>, public Signaller, public boost::noncopyable
+class Content : public std::enable_shared_from_this<Content>, public Signaller
{
public:
explicit Content ();
Content (dcpomatic::DCPTime);
Content (boost::filesystem::path);
Content (cxml::ConstNodePtr);
- Content (std::vector<std::shared_ptr<Content> >);
+ Content (std::vector<std::shared_ptr<Content>>);
virtual ~Content () {}
+ Content (Content const&) = delete;
+ Content& operator= (Content const&) = delete;
+
/** Examine the content to establish digest, frame rates and any other
* useful metadata.
* @param job Job to use to report progress, or 0.
/*
- Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2017-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
#include "ffmpeg_encoder.h"
#include "film.h"
#include "job.h"
#include "i18n.h"
-using std::string;
-using std::runtime_error;
+
using std::cout;
+using std::make_shared;
using std::pair;
+using std::runtime_error;
using std::shared_ptr;
-using boost::bind;
+using std::string;
using std::weak_ptr;
+using boost::bind;
using boost::optional;
using namespace dcpomatic;
#if BOOST_VERSION >= 106100
using namespace boost::placeholders;
#endif
+
int FFmpegFileEncoder::_video_stream_index = 0;
int FFmpegFileEncoder::_audio_stream_index_base = 1;
-class ExportAudioStream : public boost::noncopyable
+class ExportAudioStream
{
public:
ExportAudioStream (string codec_name, int channels, int frame_rate, AVSampleFormat sample_format, AVFormatContext* format_context, int stream_index)
avcodec_close (_codec_context);
}
+ ExportAudioStream (ExportAudioStream const&) = delete;
+ ExportAudioStream& operator= (ExportAudioStream const&) = delete;
+
int frame_size () const {
return _codec_context->frame_size;
}
{
DCPOMATIC_ASSERT (size);
- AVFrame* frame = av_frame_alloc ();
+ auto frame = av_frame_alloc ();
DCPOMATIC_ASSERT (frame);
int const buffer_size = av_samples_get_buffer_size (0, channels, size, _codec_context->sample_fmt, 0);
DCPOMATIC_ASSERT (buffer_size >= 0);
- void* samples = av_malloc (buffer_size);
+ auto samples = av_malloc (buffer_size);
DCPOMATIC_ASSERT (samples);
frame->nb_samples = size;
boost::filesystem::path output
)
: _audio_stream_per_channel (audio_stream_per_channel)
- , _video_options (0)
, _audio_channels (channels)
, _output (output)
, _video_frame_size (video_frame_size)
, _video_frame_rate (video_frame_rate)
, _audio_frame_rate (audio_frame_rate)
- , _audio_frames (0)
{
_pixel_format = pixel_format (format);
throw runtime_error (String::compose("could not open FFmpeg output file %1 (%2)", _output.string(), r));
}
- AVDictionary* options = 0;
+ AVDictionary* options = nullptr;
if (avformat_write_header (_format_context, &options) < 0) {
throw runtime_error ("could not write header to FFmpeg output file");
return AV_PIX_FMT_YUV422P10;
}
+
void
FFmpegFileEncoder::setup_video ()
{
for (int i = 0; i < streams; ++i) {
_audio_streams.push_back(
- shared_ptr<ExportAudioStream>(
- new ExportAudioStream(_audio_codec_name, channels_per_stream, _audio_frame_rate, _sample_format, _format_context, _audio_stream_index_base + i)
+ make_shared<ExportAudioStream>(
+ _audio_codec_name, channels_per_stream, _audio_frame_rate, _sample_format, _format_context, _audio_stream_index_base + i
)
);
}
av_write_trailer (_format_context);
}
+
void
FFmpegFileEncoder::video (shared_ptr<PlayerVideo> video, DCPTime time)
{
}
+
/** Called when the player gives us some audio */
void
FFmpegFileEncoder::audio (shared_ptr<AudioBuffers> audio)
}
}
+
void
FFmpegFileEncoder::audio_frame (int size)
{
_audio_frames += size;
}
+
void
FFmpegFileEncoder::subtitle (PlayerText, DCPTimePeriod)
{
}
+
void
FFmpegFileEncoder::buffer_free (void* opaque, uint8_t* data)
{
reinterpret_cast<FFmpegFileEncoder*>(opaque)->buffer_free2(data);
}
+
void
FFmpegFileEncoder::buffer_free2 (uint8_t* data)
{
*/
+
#ifndef DCPOMATIC_FFMPEG_FILE_ENCODER_H
#define DCPOMATIC_FFMPEG_FILE_ENCODER_H
+
#include "encoder.h"
#include "event_history.h"
#include "audio_mapping.h"
static void buffer_free(void* opaque, uint8_t* data);
void buffer_free2(uint8_t* data);
- AVCodec* _video_codec;
- AVCodecContext* _video_codec_context;
- std::vector<std::shared_ptr<ExportAudioStream> > _audio_streams;
+ AVCodec* _video_codec = nullptr;
+ AVCodecContext* _video_codec_context = nullptr;
+ std::vector<std::shared_ptr<ExportAudioStream>> _audio_streams;
bool _audio_stream_per_channel;
- AVFormatContext* _format_context;
- AVStream* _video_stream;
+ AVFormatContext* _format_context = nullptr;
+ AVStream* _video_stream = nullptr;
AVPixelFormat _pixel_format;
AVSampleFormat _sample_format;
- AVDictionary* _video_options;
+ AVDictionary* _video_options = nullptr;
std::string _video_codec_name;
std::string _audio_codec_name;
int _audio_channels;
int _video_frame_rate;
int _audio_frame_rate;
- int64_t _audio_frames;
+ int64_t _audio_frames = 0;
std::shared_ptr<AudioBuffers> _pending_audio;
/** Store of shared_ptr<Image> to keep them alive whilst raw pointers into
their data have been passed to FFmpeg.
*/
- std::map<uint8_t*, std::shared_ptr<const Image> > _pending_images;
+ std::map<uint8_t*, std::shared_ptr<const Image>> _pending_images;
boost::mutex _pending_images_mutex;
static int _video_stream_index;
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
/** @file src/log.cc
* @brief A very simple logging class.
*/
+
#include "log.h"
#include "cross.h"
#include "config.h"
Log::Log ()
- : _types (0)
{
}
+
void
Log::log (shared_ptr<const LogEntry> e)
{
do_log (e);
}
+
/** @param n String to log */
void
Log::log (string message, int type)
do_log (e);
}
+
void
Log::dcp_log (dcp::NoteType type, string m)
{
}
}
+
void
Log::set_types (int t)
{
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
#ifndef DCPOMATIC_LOG_H
#define DCPOMATIC_LOG_H
+
/** @file src/log.h
* @brief A very simple logging class.
*/
+
#include "log_entry.h"
#include <dcp/types.h>
#include <boost/thread/mutex.hpp>
#include <boost/signals2.hpp>
#include <string>
+
/** @class Log
* @brief A very simple logging class.
*/
-class Log : public boost::noncopyable
+class Log
{
public:
Log ();
virtual ~Log () {}
+ Log (Log const&) = delete;
+ Log& operator= (Log const&) = delete;
+
void log (std::shared_ptr<const LogEntry> entry);
void log (std::string message, int type);
void dcp_log (dcp::NoteType type, std::string message);
virtual void do_log (std::shared_ptr<const LogEntry> entry) = 0;
/** bit-field of log types which should be put into the log (others are ignored) */
- int _types;
+ int _types = 0;
};
+
#endif
/*
- Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
#include "nanomsg.h"
#include "dcpomatic_log.h"
#include "exceptions.h"
#include <stdexcept>
#include <cerrno>
+
using std::string;
using std::runtime_error;
using boost::optional;
+
#define NANOMSG_URL "ipc:///tmp/dcpomatic.ipc"
+
Nanomsg::Nanomsg (bool server)
{
_socket = nn_socket (AF_SP, NN_PAIR);
}
}
+
bool
Nanomsg::send (string s, int timeout)
{
return true;
}
+
optional<string>
Nanomsg::get_from_pending ()
{
if (_pending.empty()) {
- return optional<string>();
+ return {};
}
- string const l = _pending.back();
+ auto const l = _pending.back();
_pending.pop_back();
return l;
}
+
void
Nanomsg::recv_and_parse (int flags)
{
nn_freemsg (buf);
}
+
optional<string>
Nanomsg::receive (int timeout)
{
nn_setsockopt (_socket, NN_SOL_SOCKET, NN_RCVTIMEO, &timeout, sizeof(int));
}
- optional<string> l = get_from_pending ();
+ auto l = get_from_pending ();
if (l) {
return *l;
}
/*
- Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
#include <string>
#include <list>
#include <boost/optional.hpp>
-#include <boost/noncopyable.hpp>
-class Nanomsg : public boost::noncopyable
+
+class Nanomsg
{
public:
explicit Nanomsg (bool server);
+ NanoMsg (Nanomsg const&) = delete;
+ NanoMsg& operator= (Nanomsg const&) = delete;
+
/** Try to send a message, waiting for some timeout before giving up.
* @param timeout Timeout in milliseconds, or -1 for infinite timeout.
* @return true if the send happened, false if there was a timeout.
*/
bool send (std::string s, int timeout);
-
+
/** Try to receive a message, waiting for some timeout before giving up.
* @param timeout Timeout in milliseconds, or -1 for infinite timeout.
* @return Empty if the timeout was reached, otherwise the received string.
/*
- Copyright (C) 2018-2020 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
#include "state.h"
#include "cross.h"
#include <glib.h>
+
using std::string;
+
boost::optional<boost::filesystem::path> State::override_path;
+
/** @param file State filename
- * @return Full path to write @file to */
+ * @return Full path to write @file to.
+ */
boost::filesystem::path
State::path (string file, bool create_directories)
{
/*
- Copyright (C) 2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
#ifndef DCPOMATIC_STATE_H
#define DCPOMATIC_STATE_H
-#include <boost/noncopyable.hpp>
+
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
-class State : public boost::noncopyable
+
+class State
{
public:
+ State () {}
virtual ~State () {}
virtual void read () = 0;
virtual void write () const = 0;
+ State (State const&) = delete;
+ State& operator= (State const&) = delete;
+
/** If set, this overrides the standard path (in home, Library, AppData or wherever) for config.xml, cinemas.xml etc. */
static boost::optional<boost::filesystem::path> override_path;
static boost::filesystem::path path (std::string file, bool create_directories = true);
};
+
#endif
/*
- Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
#include "update_checker.h"
#include "version.h"
#include "util.h"
#include <string>
#include <iostream>
+
#define BUFFER_SIZE 1024
+
using std::cout;
using std::min;
using std::string;
using boost::ends_with;
using dcp::raw_convert;
+
/** Singleton instance */
-UpdateChecker* UpdateChecker::_instance = 0;
+UpdateChecker* UpdateChecker::_instance = nullptr;
+
static size_t
write_callback_wrapper (void* data, size_t size, size_t nmemb, void* user)
return reinterpret_cast<UpdateChecker*>(user)->write_callback (data, size, nmemb);
}
+
/** Construct an UpdateChecker. This sets things up and starts a thread to
* do the work.
*/
UpdateChecker::UpdateChecker ()
: _buffer (new char[BUFFER_SIZE])
- , _offset (0)
- , _curl (0)
- , _state (NOT_RUN)
- , _emits (0)
- , _to_do (0)
- , _terminate (false)
+ , _state (State::NOT_RUN)
{
_curl = curl_easy_init ();
curl_easy_setopt (_curl, CURLOPT_USERAGENT, agent.c_str ());
}
+
void
UpdateChecker::start ()
{
#endif
}
+
UpdateChecker::~UpdateChecker ()
{
boost::this_thread::disable_interruption dis;
delete[] _buffer;
}
+
/** Start running the update check */
void
UpdateChecker::run ()
_condition.notify_one ();
}
+
void
UpdateChecker::thread ()
{
int r = curl_easy_perform (_curl);
if (r != CURLE_OK) {
- set_state (FAILED);
+ set_state (State::FAILED);
return;
}
}
if (_stable || _test) {
- set_state (YES);
+ set_state (State::YES);
} else {
- set_state (NO);
+ set_state (State::NO);
}
} catch (...) {
- set_state (FAILED);
+ set_state (State::FAILED);
}
}
}
+
size_t
UpdateChecker::write_callback (void* data, size_t size, size_t nmemb)
{
return t;
}
+
void
UpdateChecker::set_state (State s)
{
_emits++;
}
- emit (boost::bind (boost::ref (StateChanged)));
+ emit (boost::bind(boost::ref(StateChanged)));
}
+
UpdateChecker *
UpdateChecker::instance ()
{
return _instance;
}
+
bool
UpdateChecker::version_less_than (string const & a, string const & b)
{
DCPOMATIC_ASSERT (ap.size() == 3 && bp.size() == 3);
if (ap[0] != bp[0]) {
- return raw_convert<int> (ap[0]) < raw_convert<int> (bp[0]);
+ return raw_convert<int>(ap[0]) < raw_convert<int>(bp[0]);
}
if (ap[1] != bp[1]) {
- return raw_convert<int> (ap[1]) < raw_convert<int> (bp[1]);
+ return raw_convert<int>(ap[1]) < raw_convert<int>(bp[1]);
}
float am;
if (ends_with (ap[2], "devel")) {
- am = raw_convert<int> (ap[2].substr (0, ap[2].length() - 5)) + 0.5;
+ am = raw_convert<int>(ap[2].substr(0, ap[2].length() - 5)) + 0.5;
} else {
- am = raw_convert<int> (ap[2]);
+ am = raw_convert<int>(ap[2]);
}
float bm;
if (ends_with (bp[2], "devel")) {
- bm = raw_convert<int> (bp[2].substr (0, bp[2].length() - 5)) + 0.5;
+ bm = raw_convert<int>(bp[2].substr(0, bp[2].length() - 5)) + 0.5;
} else {
- bm = raw_convert<int> (bp[2]);
+ bm = raw_convert<int>(bp[2]);
}
return am < bm;
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
-/** @file src/lib/update.h
+
+/** @file src/lib/update_checker.h
* @brief UpdateChecker class.
*/
+
#include "signaller.h"
#include <curl/curl.h>
#include <boost/signals2.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread.hpp>
+
struct update_checker_test;
+
/** Class to check for the existance of an update for DCP-o-matic on a remote server */
-class UpdateChecker : public Signaller, public boost::noncopyable
+class UpdateChecker : public Signaller
{
public:
~UpdateChecker ();
+ UpdateChecker (UpdateChecker const &);
+ UpdateChecker& operator= (UpdateChecker const &);
+
void run ();
- enum State {
+ enum class State {
YES, ///< there is an update
FAILED, ///< the check failed, so we don't know
NO, ///< there is no update
void thread ();
char* _buffer;
- int _offset;
- CURL* _curl;
+ int _offset = 0;
+ CURL* _curl = nullptr;
/** mutex to protect _state, _stable, _test and _emits */
mutable boost::mutex _data_mutex;
State _state;
boost::optional<std::string> _stable;
boost::optional<std::string> _test;
- int _emits;
+ int _emits = 0;
boost::thread _thread;
boost::mutex _process_mutex;
boost::condition _condition;
- int _to_do;
- bool _terminate;
+ int _to_do = 0;
+ bool _terminate = false;
};
/*
- Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
#include "writer.h"
#include "compose.hpp"
#include "film.h"
#include "i18n.h"
+
/* OS X strikes again */
#undef set_key
-using std::make_pair;
-using std::pair;
-using std::string;
-using std::list;
+
using std::cout;
+using std::dynamic_pointer_cast;
+using std::list;
+using std::make_pair;
+using std::make_shared;
using std::map;
-using std::min;
using std::max;
-using std::vector;
+using std::min;
+using std::pair;
using std::shared_ptr;
+using std::string;
+using std::vector;
using std::weak_ptr;
-using std::dynamic_pointer_cast;
using boost::optional;
#if BOOST_VERSION >= 106100
using namespace boost::placeholders;
Writer::Writer (weak_ptr<const Film> weak_film, weak_ptr<Job> j, bool text_only)
: WeakConstFilm (weak_film)
, _job (j)
- , _finish (false)
- , _queued_full_in_memory (0)
/* These will be reset to sensible values when J2KEncoder is created */
, _maximum_frames_in_memory (8)
, _maximum_queue_size (8)
- , _full_written (0)
- , _fake_written (0)
- , _repeat_written (0)
- , _pushed_to_disk (0)
, _text_only (text_only)
- , _have_subtitles (false)
{
- shared_ptr<Job> job = _job.lock ();
+ auto job = _job.lock ();
int reel_index = 0;
auto const reels = film()->reels();
}
}
+
void
Writer::start ()
{
}
}
+
Writer::~Writer ()
{
if (!_text_only) {
}
}
+
/** Pass a video frame to the writer for writing to disk at some point.
* This method can be called with frames out of order.
* @param encoded JPEG2000-encoded data.
}
QueueItem qi;
- qi.type = QueueItem::FULL;
+ qi.type = QueueItem::Type::FULL;
qi.encoded = encoded;
qi.reel = video_reel (frame);
qi.frame = frame - _reels[qi.reel].start ();
_empty_condition.notify_all ();
}
+
bool
Writer::can_repeat (Frame frame) const
{
return frame > _reels[video_reel(frame)].start();
}
+
/** Repeat the last frame that was written to a reel as a new frame.
* @param frame Frame index within the DCP of the new (repeated) frame.
* @param eyes Eyes that this repeated frame image is for.
}
QueueItem qi;
- qi.type = QueueItem::REPEAT;
+ qi.type = QueueItem::Type::REPEAT;
qi.reel = video_reel (frame);
qi.frame = frame - _reels[qi.reel].start ();
if (film()->three_d() && eyes == Eyes::BOTH) {
_empty_condition.notify_all ();
}
+
void
Writer::fake_write (Frame frame, Eyes eyes)
{
Frame const frame_in_reel = frame - _reels[reel].start ();
QueueItem qi;
- qi.type = QueueItem::FAKE;
+ qi.type = QueueItem::Type::FAKE;
{
shared_ptr<InfoFileHandle> info_file = film()->info_file_handle(_reels[reel].period(), true);
_empty_condition.notify_all ();
}
+
/** Write some audio frames to the DCP.
* @param audio Audio data.
* @param time Time of this data within the DCP.
}
_queue.sort ();
- QueueItem const & f = _queue.front();
+ auto const & f = _queue.front();
return _last_written[f.reel].next(f);
}
if (!_queue.empty() && !have_sequenced_image_at_queue_head()) {
LOG_WARNING (N_("Finishing writer with a left-over queue of %1:"), _queue.size());
for (auto const& i: _queue) {
- if (i.type == QueueItem::FULL) {
+ if (i.type == QueueItem::Type::FULL) {
LOG_WARNING (N_("- type FULL, frame %1, eyes %2"), i.frame, (int) i.eyes);
} else {
LOG_WARNING (N_("- type FAKE, size %1, frame %2, eyes %3"), i.size, i.frame, (int) i.eyes);
/* Write any frames that we can write; i.e. those that are in sequence. */
while (have_sequenced_image_at_queue_head ()) {
- QueueItem qi = _queue.front ();
+ auto qi = _queue.front ();
_last_written[qi.reel].update (qi);
_queue.pop_front ();
- if (qi.type == QueueItem::FULL && qi.encoded) {
+ if (qi.type == QueueItem::Type::FULL && qi.encoded) {
--_queued_full_in_memory;
}
lock.unlock ();
- ReelWriter& reel = _reels[qi.reel];
+ auto& reel = _reels[qi.reel];
switch (qi.type) {
- case QueueItem::FULL:
+ case QueueItem::Type::FULL:
LOG_DEBUG_ENCODE (N_("Writer FULL-writes %1 (%2)"), qi.frame, (int) qi.eyes);
if (!qi.encoded) {
qi.encoded.reset (new ArrayData(film()->j2c_path(qi.reel, qi.frame, qi.eyes, false)));
reel.write (qi.encoded, qi.frame, qi.eyes);
++_full_written;
break;
- case QueueItem::FAKE:
+ case QueueItem::Type::FAKE:
LOG_DEBUG_ENCODE (N_("Writer FAKE-writes %1"), qi.frame);
reel.fake_write (qi.size);
++_fake_written;
break;
- case QueueItem::REPEAT:
+ case QueueItem::Type::REPEAT:
LOG_DEBUG_ENCODE (N_("Writer REPEAT-writes %1"), qi.frame);
reel.repeat_write (qi.frame, qi.eyes);
++_repeat_written;
/* Find one from the back of the queue */
_queue.sort ();
- list<QueueItem>::reverse_iterator i = _queue.rbegin ();
- while (i != _queue.rend() && (i->type != QueueItem::FULL || !i->encoded)) {
+ auto i = _queue.rbegin ();
+ while (i != _queue.rend() && (i->type != QueueItem::Type::FULL || !i->encoded)) {
++i;
}
store_current ();
}
+
void
Writer::terminate_thread (bool can_throw)
{
dcp::DCP dcp (output_dcp);
- shared_ptr<dcp::CPL> cpl (
- new dcp::CPL (
- film()->dcp_name(),
- film()->dcp_content_type()->libdcp_kind ()
- )
+ auto cpl = make_shared<dcp::CPL>(
+ film()->dcp_name(),
+ film()->dcp_content_type()->libdcp_kind()
);
dcp.add (cpl);
/* Calculate digests for each reel in parallel */
- shared_ptr<Job> job = _job.lock ();
+ auto job = _job.lock ();
if (job) {
job->sub (_("Computing digests"));
}
boost::asio::io_service service;
boost::thread_group pool;
- shared_ptr<boost::asio::io_service::work> work (new boost::asio::io_service::work (service));
+ auto work = make_shared<boost::asio::io_service::work>(service);
int const threads = max (1, Config::instance()->master_encoding_threads ());
/* Add metadata */
- string creator = Config::instance()->dcp_creator();
+ auto creator = Config::instance()->dcp_creator();
if (creator.empty()) {
creator = String::compose("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
}
- string issuer = Config::instance()->dcp_issuer();
+ auto issuer = Config::instance()->dcp_issuer();
if (issuer.empty()) {
issuer = String::compose("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
}
cpl->set_additional_subtitle_languages(std::vector<dcp::LanguageTag>(sl.begin() + 1, sl.end()));
}
- shared_ptr<const dcp::CertificateChain> signer;
- signer = Config::instance()->signer_chain ();
+ auto signer = Config::instance()->signer_chain();
/* We did check earlier, but check again here to be on the safe side */
string reason;
if (!signer->valid (&reason)) {
write_cover_sheet (output_dcp);
}
+
void
Writer::write_cover_sheet (boost::filesystem::path output_dcp)
{
- boost::filesystem::path const cover = film()->file("COVER_SHEET.txt");
- FILE* f = fopen_boost (cover, "w");
+ auto const cover = film()->file("COVER_SHEET.txt");
+ auto f = fopen_boost (cover, "w");
if (!f) {
throw OpenFileError (cover, errno, OpenFileError::WRITE);
}
- string text = Config::instance()->cover_sheet ();
+ auto text = Config::instance()->cover_sheet ();
boost::algorithm::replace_all (text, "$CPL_NAME", film()->name());
boost::algorithm::replace_all (text, "$TYPE", film()->dcp_content_type()->pretty_name());
boost::algorithm::replace_all (text, "$CONTAINER", film()->container()->container_nickname());
boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", film()->isdcf_metadata().audio_language);
- vector<dcp::LanguageTag> subtitle_languages = film()->subtitle_languages();
+ auto subtitle_languages = film()->subtitle_languages();
if (subtitle_languages.empty()) {
boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", "None");
} else {
boost::uintmax_t size = 0;
for (
- boost::filesystem::recursive_directory_iterator i = boost::filesystem::recursive_directory_iterator(output_dcp);
+ auto i = boost::filesystem::recursive_directory_iterator(output_dcp);
i != boost::filesystem::recursive_directory_iterator();
++i) {
- if (boost::filesystem::is_regular_file (i->path ())) {
- size += boost::filesystem::file_size (i->path ());
+ if (boost::filesystem::is_regular_file (i->path())) {
+ size += boost::filesystem::file_size (i->path());
}
}
if (size > (1000000000L)) {
- boost::algorithm::replace_all (text, "$SIZE", String::compose ("%1GB", dcp::locale_convert<string> (size / 1000000000.0, 1, true)));
+ boost::algorithm::replace_all (text, "$SIZE", String::compose("%1GB", dcp::locale_convert<string>(size / 1000000000.0, 1, true)));
} else {
- boost::algorithm::replace_all (text, "$SIZE", String::compose ("%1MB", dcp::locale_convert<string> (size / 1000000.0, 1, true)));
+ boost::algorithm::replace_all (text, "$SIZE", String::compose("%1MB", dcp::locale_convert<string>(size / 1000000.0, 1, true)));
}
- pair<int, int> ch = audio_channel_types (film()->mapped_audio_channels(), film()->audio_channels());
- string description = String::compose("%1.%2", ch.first, ch.second);
+ auto ch = audio_channel_types (film()->mapped_audio_channels(), film()->audio_channels());
+ auto description = String::compose("%1.%2", ch.first, ch.second);
if (description == "0.0") {
description = _("None");
fclose (f);
}
+
/** @param frame Frame index within the whole DCP.
* @return true if we can fake-write this frame.
*/
parameters in the asset writer.
*/
- ReelWriter const & reel = _reels[video_reel(frame)];
+ auto const & reel = _reels[video_reel(frame)];
/* Make frame relative to the start of the reel */
frame -= reel.start ();
return (frame != 0 && frame < reel.first_nonexistant_frame());
}
+
/** @param track Closed caption track if type == TextType::CLOSED_CAPTION */
void
Writer::write (PlayerText text, TextType type, optional<DCPTextTrack> track, DCPTimePeriod period)
(*reel)->write (text, type, track, period);
}
+
void
Writer::write (vector<FontData> fonts)
{
}
}
+
bool
operator< (QueueItem const & a, QueueItem const & b)
{
return static_cast<int> (a.eyes) < static_cast<int> (b.eyes);
}
+
bool
operator== (QueueItem const & a, QueueItem const & b)
{
return a.reel == b.reel && a.frame == b.frame && a.eyes == b.eyes;
}
+
void
Writer::set_encoder_threads (int threads)
{
_maximum_queue_size = threads * 16;
}
+
void
Writer::write (ReferencedReelAsset asset)
{
_reel_assets.push_back (asset);
}
+
size_t
Writer::video_reel (int frame) const
{
return i;
}
+
void
Writer::set_digest_progress (Job* job, float progress)
{
*/
+
/** @file src/lib/writer.h
* @brief Writer class.
*/
+
#include "atmos_metadata.h"
#include "types.h"
#include "player_text.h"
#include <boost/thread/condition.hpp>
#include <list>
+
namespace dcp {
class Data;
}
class ReferencedReelAsset;
class ReelWriter;
+
struct QueueItem
{
public:
- QueueItem ()
- : size (0)
- , reel (0)
- , frame (0)
- , eyes (Eyes::BOTH)
- {}
-
- enum Type {
+ QueueItem () {}
+
+ enum class Type {
/** a normal frame with some JPEG200 data */
FULL,
/** a frame whose data already exists in the MXF,
/** encoded data for FULL */
std::shared_ptr<const dcp::Data> encoded;
/** size of data for FAKE */
- int size;
+ int size = 0;
/** reel index */
- size_t reel;
+ size_t reel = 0;
/** frame index within the reel */
- int frame;
+ int frame = 0;
/** eyes for FULL, FAKE and REPEAT */
- Eyes eyes;
+ Eyes eyes = Eyes::BOTH;
};
+
bool operator< (QueueItem const & a, QueueItem const & b);
bool operator== (QueueItem const & a, QueueItem const & b);
+
/** @class Writer
* @brief Class to manage writing JPEG2000 and audio data to assets on disk.
*
* will sort it out. write() for AudioBuffers must be called in order.
*/
-class Writer : public ExceptionStore, public boost::noncopyable, public WeakConstFilm
+class Writer : public ExceptionStore, public WeakConstFilm
{
public:
Writer (std::weak_ptr<const Film>, std::weak_ptr<Job>, bool text_only = false);
~Writer ();
+ Writer (Writer const &) = delete;
+ Writer& operator= (Writer const &) = delete;
+
void start ();
bool can_fake_write (Frame) const;
/** our thread */
boost::thread _thread;
/** true if our thread should finish */
- bool _finish;
+ bool _finish = false;
/** queue of things to write to disk */
std::list<QueueItem> _queue;
/** number of FULL frames whose JPEG200 data is currently held in RAM */
- int _queued_full_in_memory;
+ int _queued_full_in_memory = 0;
/** mutex for thread state */
mutable boost::mutex _state_mutex;
/** condition to manage thread wakeups when we have nothing to do */
std::vector<LastWritten> _last_written;
/** number of FULL written frames */
- int _full_written;
+ int _full_written = 0;
/** number of FAKE written frames */
- int _fake_written;
- int _repeat_written;
+ int _fake_written = 0;
+ int _repeat_written = 0;
/** number of frames pushed to disk and then recovered
due to the limit of frames to be held in memory.
*/
- int _pushed_to_disk;
+ int _pushed_to_disk = 0;
bool _text_only;
std::vector<dcpomatic::FontData> _fonts;
/** true if any reel has any subtitles */
- bool _have_subtitles;
+ bool _have_subtitles = false;
/** all closed caption tracks that we have on any reel */
std::set<DCPTextTrack> _have_closed_captions;
};
return;
}
- if (uc->state() == UpdateChecker::YES) {
+ if (uc->state() == UpdateChecker::State::YES) {
auto dialog = new UpdateDialog (this, uc->stable(), uc->test());
dialog->ShowModal ();
dialog->Destroy ();
- } else if (uc->state() == UpdateChecker::FAILED) {
+ } else if (uc->state() == UpdateChecker::State::FAILED) {
error_dialog (this, _("The DCP-o-matic download server could not be contacted."));
} else {
error_dialog (this, _("There are no new versions of DCP-o-matic available."));
return;
}
- if (uc->state() == UpdateChecker::YES) {
+ if (uc->state() == UpdateChecker::State::YES) {
auto dialog = new UpdateDialog (this, uc->stable (), uc->test ());
dialog->ShowModal ();
dialog->Destroy ();
- } else if (uc->state() == UpdateChecker::FAILED) {
+ } else if (uc->state() == UpdateChecker::State::FAILED) {
error_dialog (this, _("The DCP-o-matic download server could not be contacted."));
} else {
error_dialog (this, _("There are no new versions of DCP-o-matic available."));