/** @param f Film to compare.
* @param o Options.
*/
-ABTranscodeJob::ABTranscodeJob (shared_ptr<Film> f, shared_ptr<const DecodeOptions> od, shared_ptr<const EncodeOptions> oe, shared_ptr<Job> req)
+ABTranscodeJob::ABTranscodeJob (shared_ptr<Film> f, shared_ptr<const DecodeOptions> od, shared_ptr<Job> req)
: Job (f, req)
, _decode_opt (od)
- , _encode_opt (oe)
{
_film_b.reset (new Film (*_film));
_film_b->set_scaler (Config::instance()->reference_scaler ());
{
try {
/* _film_b is the one with reference filters */
- ABTranscoder w (_film_b, _film, _decode_opt, this, shared_ptr<Encoder> (new Encoder (_film, _encode_opt)));
+ ABTranscoder w (_film_b, _film, _decode_opt, this, shared_ptr<Encoder> (new Encoder (_film)));
w.go ();
set_progress (1);
set_state (FINISHED_OK);
class Film;
class DecodeOptions;
-class EncodeOptions;
/** @class ABTranscodeJob
* @brief Job to run a transcoder which produces output for A/B comparison of various settings.
ABTranscodeJob (
boost::shared_ptr<Film> f,
boost::shared_ptr<const DecodeOptions> od,
- boost::shared_ptr<const EncodeOptions> oe,
boost::shared_ptr<Job> req
);
private:
boost::shared_ptr<const DecodeOptions> _decode_opt;
- boost::shared_ptr<const EncodeOptions> _encode_opt;
/** Copy of our Film using the reference filters and scaler */
boost::shared_ptr<Film> _film_b;
using std::ifstream;
using boost::shared_ptr;
-CheckHashesJob::CheckHashesJob (shared_ptr<Film> f, shared_ptr<const DecodeOptions> od, shared_ptr<const EncodeOptions> oe, shared_ptr<Job> req)
+CheckHashesJob::CheckHashesJob (shared_ptr<Film> f, shared_ptr<const DecodeOptions> od, shared_ptr<Job> req)
: Job (f, req)
, _decode_opt (od)
- , _encode_opt (oe)
, _bad (0)
{
int const inc = dfr.skip ? 2 : 1;
for (SourceFrame i = _film->dcp_trim_start(); i < N; i += inc) {
- string const j2k_file = _encode_opt->frame_out_path (i, false);
- string const hash_file = _encode_opt->hash_out_path (i, false);
+ string const j2k_file = _film->frame_out_path (i, false);
+ string const hash_file = _film->hash_out_path (i, false);
if (!boost::filesystem::exists (j2k_file)) {
_film->log()->log (String::compose ("Frame %1 has a missing J2K file.", i));
shared_ptr<Job> tc;
if (_film->dcp_ab()) {
- tc.reset (new ABTranscodeJob (_film, _decode_opt, _encode_opt, shared_from_this()));
+ tc.reset (new ABTranscodeJob (_film, _decode_opt, shared_from_this()));
} else {
- tc.reset (new TranscodeJob (_film, _decode_opt, _encode_opt, shared_from_this()));
+ tc.reset (new TranscodeJob (_film, _decode_opt, shared_from_this()));
}
JobManager::instance()->add_after (shared_from_this(), tc);
- JobManager::instance()->add_after (tc, shared_ptr<Job> (new CheckHashesJob (_film, _decode_opt, _encode_opt, tc)));
+ JobManager::instance()->add_after (tc, shared_ptr<Job> (new CheckHashesJob (_film, _decode_opt, tc)));
}
set_progress (1);
#include "job.h"
class DecodeOptions;
-class EncodeOptions;
class CheckHashesJob : public Job
{
CheckHashesJob (
boost::shared_ptr<Film> f,
boost::shared_ptr<const DecodeOptions> od,
- boost::shared_ptr<const EncodeOptions> oe,
boost::shared_ptr<Job> req
);
private:
boost::shared_ptr<const DecodeOptions> _decode_opt;
- boost::shared_ptr<const EncodeOptions> _encode_opt;
int _bad;
};
* @param frame Frame index.
*/
void
-EncodedData::write (shared_ptr<const EncodeOptions> opt, SourceFrame frame)
+EncodedData::write (shared_ptr<const Film> film, SourceFrame frame)
{
- string const tmp_j2k = opt->frame_out_path (frame, true);
+ string const tmp_j2k = film->frame_out_path (frame, true);
FILE* f = fopen (tmp_j2k.c_str (), "wb");
fwrite (_data, 1, _size, f);
fclose (f);
- string const real_j2k = opt->frame_out_path (frame, false);
+ string const real_j2k = film->frame_out_path (frame, false);
/* Rename the file from foo.j2c.tmp to foo.j2c now that it is complete */
boost::filesystem::rename (tmp_j2k, real_j2k);
/* Write a file containing the hash */
- string const hash = opt->hash_out_path (frame, false);
+ string const hash = film->hash_out_path (frame, false);
ofstream h (hash.c_str());
h << md5_digest (_data, _size) << "\n";
h.close ();
*/
class FilmState;
-class EncodeOptions;
+class Film;
class ServerDescription;
class Scaler;
class Image;
virtual ~EncodedData () {}
void send (boost::shared_ptr<Socket> socket);
- void write (boost::shared_ptr<const EncodeOptions>, SourceFrame);
+ void write (boost::shared_ptr<const Film>, SourceFrame);
/** @return data */
uint8_t* data () const {
#include "config.h"
#include "dcp_video_frame.h"
#include "server.h"
+#include "format.h"
#include "cross.h"
using std::pair;
/** @param f Film that we are encoding.
* @param o Options.
*/
-Encoder::Encoder (shared_ptr<const Film> f, shared_ptr<const EncodeOptions> o)
+Encoder::Encoder (shared_ptr<const Film> f)
: _film (f)
- , _opt (o)
, _just_skipped (false)
, _video_frame (0)
, _audio_frame (0)
/* We write mono files */
sf_info.channels = 1;
sf_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
- SNDFILE* f = sf_open (_opt->multichannel_audio_out_path (i, true).c_str (), SFM_WRITE, &sf_info);
+ SNDFILE* f = sf_open (_film->multichannel_audio_out_path (i, true).c_str (), SFM_WRITE, &sf_info);
if (f == 0) {
- throw CreateFileError (_opt->multichannel_audio_out_path (i, true));
+ throw CreateFileError (_film->multichannel_audio_out_path (i, true));
}
_sound_files.push_back (f);
}
/* Rename .wav.tmp files to .wav */
for (int i = 0; i < dcp_audio_channels (_film->audio_channels()); ++i) {
- if (boost::filesystem::exists (_opt->multichannel_audio_out_path (i, false))) {
- boost::filesystem::remove (_opt->multichannel_audio_out_path (i, false));
+ if (boost::filesystem::exists (_film->multichannel_audio_out_path (i, false))) {
+ boost::filesystem::remove (_film->multichannel_audio_out_path (i, false));
}
- boost::filesystem::rename (_opt->multichannel_audio_out_path (i, true), _opt->multichannel_audio_out_path (i, false));
+ boost::filesystem::rename (_film->multichannel_audio_out_path (i, true), _film->multichannel_audio_out_path (i, false));
}
}
_film->log()->log (String::compose ("Encode left-over frame %1", (*i)->frame ()));
try {
shared_ptr<EncodedData> e = (*i)->encode_locally ();
- e->write (_opt, (*i)->frame ());
+ e->write (_film, (*i)->frame ());
frame_done ();
} catch (std::exception& e) {
_film->log()->log (String::compose ("Local encode failed (%1)", e.what ()));
/* Now do links (or copies on windows) to duplicate frames */
for (list<pair<int, int> >::iterator i = _links_required.begin(); i != _links_required.end(); ++i) {
- link (_opt->frame_out_path (i->first, false), _opt->frame_out_path (i->second, false));
- link (_opt->hash_out_path (i->first, false), _opt->hash_out_path (i->second, false));
+ link (_film->frame_out_path (i->first, false), _film->frame_out_path (i->second, false));
+ link (_film->hash_out_path (i->first, false), _film->hash_out_path (i->second, false));
}
}
void
Encoder::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Subtitle> sub)
{
- if (_opt->video_skip && (_video_frame % 2)) {
+ DCPFrameRate dfr (_film->frames_per_second ());
+
+ if (dfr.skip && (_video_frame % 2)) {
++_video_frame;
return;
}
- if (_opt->video_range) {
- pair<SourceFrame, SourceFrame> const r = _opt->video_range.get();
+ if (_film->video_range ()) {
+ pair<SourceFrame, SourceFrame> const r = _film->video_range().get();
if (_video_frame < r.first || _video_frame >= r.second) {
++_video_frame;
return;
}
/* Only do the processing if we don't already have a file for this frame */
- if (boost::filesystem::exists (_opt->frame_out_path (_video_frame, false))) {
+ if (boost::filesystem::exists (_film->frame_out_path (_video_frame, false))) {
frame_skipped ();
return;
}
TIMING ("adding to queue of %1", _queue.size ());
_queue.push_back (boost::shared_ptr<DCPVideoFrame> (
new DCPVideoFrame (
- image, sub, _opt->out_size, _opt->padding, _film->subtitle_offset(), _film->subtitle_scale(),
+ image, sub, _film->format()->dcp_size(), _film->format()->dcp_padding (_film),
+ _film->subtitle_offset(), _film->subtitle_scale(),
_film->scaler(), _video_frame, _film->frames_per_second(), s.second,
_film->colour_lut(), _film->j2k_bandwidth(),
_film->log()
void
Encoder::process_audio (shared_ptr<AudioBuffers> data)
{
- if (_opt->audio_range) {
+ if (_film->audio_range ()) {
shared_ptr<AudioBuffers> trimmed (new AudioBuffers (*data.get ()));
/* Range that we are encoding */
- pair<int64_t, int64_t> required_range = _opt->audio_range.get();
+ pair<int64_t, int64_t> required_range = _film->audio_range().get();
/* Range of this block of data */
pair<int64_t, int64_t> this_range (_audio_frame, _audio_frame + trimmed->frames());
}
if (encoded) {
- encoded->write (_opt, vf->frame ());
+ encoded->write (_film, vf->frame ());
frame_done ();
} else {
lock.lock ();
#include "video_sink.h"
#include "audio_sink.h"
-class EncodeOptions;
class Image;
class Subtitle;
class AudioBuffers;
class Encoder : public VideoSink, public AudioSink
{
public:
- Encoder (boost::shared_ptr<const Film> f, boost::shared_ptr<const EncodeOptions> o);
+ Encoder (boost::shared_ptr<const Film> f);
virtual ~Encoder ();
/** Called to indicate that a processing run is about to begin */
/** Film that we are encoding */
boost::shared_ptr<const Film> _film;
- /** Options */
- boost::shared_ptr<const EncodeOptions> _opt;
/** Mutex for _time_history, _just_skipped and _last_frame */
mutable boost::mutex _history_mutex;
throw MissingSettingError ("name");
}
- shared_ptr<EncodeOptions> oe (new EncodeOptions (j2k_dir(), ".j2c", dir ("wavs")));
- oe->out_size = format()->dcp_size ();
- oe->padding = format()->dcp_padding (shared_from_this ());
- if (dcp_length ()) {
- oe->video_range = make_pair (dcp_trim_start(), dcp_trim_start() + dcp_length().get());
- if (audio_stream()) {
- DCPFrameRate dfr (frames_per_second ());
- oe->audio_range = make_pair (
-
- video_frames_to_audio_frames (
- oe->video_range.get().first,
- dcp_audio_sample_rate (audio_stream()->sample_rate()),
- dfr.frames_per_second
- ),
-
- video_frames_to_audio_frames (
- oe->video_range.get().second,
- dcp_audio_sample_rate (audio_stream()->sample_rate()),
- dfr.frames_per_second
- )
- );
- }
-
- }
-
- oe->video_skip = DCPFrameRate (frames_per_second()).skip;
-
shared_ptr<DecodeOptions> od (new DecodeOptions);
od->decode_subtitles = with_subtitles ();
if (transcode) {
if (dcp_ab()) {
- r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od, oe, shared_ptr<Job> ())));
+ r = JobManager::instance()->add (shared_ptr<Job> (new ABTranscodeJob (shared_from_this(), od, shared_ptr<Job> ())));
} else {
- r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od, oe, shared_ptr<Job> ())));
+ r = JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (shared_from_this(), od, shared_ptr<Job> ())));
}
}
- r = JobManager::instance()->add (shared_ptr<Job> (new CheckHashesJob (shared_from_this(), od, oe, r)));
- JobManager::instance()->add (shared_ptr<Job> (new MakeDCPJob (shared_from_this(), oe, r)));
+ r = JobManager::instance()->add (shared_ptr<Job> (new CheckHashesJob (shared_from_this(), od, r)));
+ JobManager::instance()->add (shared_ptr<Job> (new MakeDCPJob (shared_from_this(), r)));
}
/** Start a job to examine our content file */
return _external_audio_stream;
}
+
+/** @param f Source frame index.
+ * @param t true to return a temporary file path, otherwise a permanent one.
+ * @return The path to write this video frame to.
+ */
+string
+Film::frame_out_path (SourceFrame f, bool t) const
+{
+ stringstream s;
+ s << j2k_dir() << "/";
+ s.width (8);
+ s << std::setfill('0') << f << ".j2c";
+
+ if (t) {
+ s << ".tmp";
+ }
+
+ return s.str ();
+}
+
+string
+Film::hash_out_path (SourceFrame f, bool t) const
+{
+ return frame_out_path (f, t) + ".md5";
+}
+
+/** @param c Audio channel index.
+ * @param t true to return a temporary file path, otherwise a permanent one.
+ * @return The path to write this audio file to.
+ */
+string
+Film::multichannel_audio_out_path (int c, bool t) const
+{
+ stringstream s;
+ s << dir ("wavs") << "/" << (c + 1) << ".wav";
+ if (t) {
+ s << ".tmp";
+ }
+
+ return s.str ();
+}
+
+boost::optional<pair<SourceFrame, SourceFrame> >
+Film::video_range () const
+{
+ if (!dcp_length()) {
+ return boost::optional<pair<SourceFrame, SourceFrame> > ();
+ }
+
+ return make_pair (dcp_trim_start(), dcp_trim_start() + dcp_length().get());
+}
+
+boost::optional<pair<int64_t, int64_t> >
+Film::audio_range () const
+{
+ boost::optional<pair<SourceFrame, SourceFrame> > vr = video_range ();
+ if (!vr || !audio_stream()) {
+ return boost::optional<pair<int64_t, int64_t> > ();
+ }
+
+ DCPFrameRate dfr (frames_per_second ());
+ return make_pair (
+
+ video_frames_to_audio_frames (
+ vr.get().first,
+ dcp_audio_sample_rate (audio_stream()->sample_rate()),
+ dfr.frames_per_second
+ ),
+
+ video_frames_to_audio_frames (
+ vr.get().second,
+ dcp_audio_sample_rate (audio_stream()->sample_rate()),
+ dfr.frames_per_second
+ )
+ );
+}
std::string file (std::string f) const;
std::string dir (std::string d) const;
+ std::string frame_out_path (SourceFrame f, bool t) const;
+ std::string hash_out_path (SourceFrame f, bool t) const;
+ std::string multichannel_audio_out_path (int c, bool t) const;
+
std::string content_path () const;
ContentType content_type () const;
}
int audio_channels () const;
+ boost::optional<std::pair<SourceFrame, SourceFrame> > video_range () const;
+ boost::optional<std::pair<int64_t, int64_t> > audio_range () const;
void set_dci_date_today ();
#include "options.h"
#include "imagemagick_decoder.h"
#include "film.h"
+#include "format.h"
using std::string;
using std::cout;
/** @param f Film we are making the DCP for.
* @param o Options.
*/
-MakeDCPJob::MakeDCPJob (shared_ptr<Film> f, shared_ptr<const EncodeOptions> o, shared_ptr<Job> req)
+MakeDCPJob::MakeDCPJob (shared_ptr<Film> f, shared_ptr<Job> req)
: Job (f, req)
- , _opt (o)
{
}
DCPFrameRate dfr (_film->frames_per_second());
int const mult = dfr.skip ? 2 : 1;
SourceFrame const s = ((f + offset) * mult) + _film->dcp_trim_start();
- return _opt->frame_out_path (s, false);
+ return _film->frame_out_path (s, false);
}
string
MakeDCPJob::wav_path (libdcp::Channel c) const
{
- return _opt->multichannel_audio_out_path (int (c), false);
+ return _film->multichannel_audio_out_path (int (c), false);
}
void
&dcp.Progress,
dfr.frames_per_second,
this_time,
- _opt->out_size.width,
- _opt->out_size.height
+ _film->format()->dcp_size().width,
+ _film->format()->dcp_size().height
)
);
#include "job.h"
-class EncodeOptions;
-
/** @class MakeDCPJob
* @brief A job to create DCPs
*/
class MakeDCPJob : public Job
{
public:
- MakeDCPJob (boost::shared_ptr<Film>, boost::shared_ptr<const EncodeOptions>, boost::shared_ptr<Job> req);
+ MakeDCPJob (boost::shared_ptr<Film>, boost::shared_ptr<Job> req);
std::string name () const;
void run ();
void dcp_progress (float);
std::string j2c_path (int, int) const;
std::string wav_path (libdcp::Channel) const;
-
- boost::shared_ptr<const EncodeOptions> _opt;
};
#include <boost/optional.hpp>
#include "util.h"
-/** @class EncodeOptions
- * @brief EncodeOptions for an encoding operation.
- *
- * These are settings which may be different, in different circumstances, for
- * the same film; ie they are options for a particular operation.
- */
-class EncodeOptions
-{
-public:
-
- EncodeOptions (std::string f, std::string e, std::string m)
- : padding (0)
- , video_skip (false)
- , _frame_out_path (f)
- , _frame_out_extension (e)
- , _multichannel_audio_out_path (m)
- {}
-
- /** @return The path to write video frames to */
- std::string frame_out_path () const {
- return _frame_out_path;
- }
-
- /** @param f Source frame index.
- * @param t true to return a temporary file path, otherwise a permanent one.
- * @return The path to write this video frame to.
- */
- std::string frame_out_path (SourceFrame f, bool t) const {
- std::stringstream s;
- s << _frame_out_path << "/";
- s.width (8);
- s << std::setfill('0') << f << _frame_out_extension;
-
- if (t) {
- s << ".tmp";
- }
-
- return s.str ();
- }
-
- std::string hash_out_path (SourceFrame f, bool t) const {
- return frame_out_path (f, t) + ".md5";
- }
-
- /** @return Path to write multichannel audio data to */
- std::string multichannel_audio_out_path () const {
- return _multichannel_audio_out_path;
- }
-
- /** @param c Audio channel index.
- * @param t true to return a temporary file path, otherwise a permanent one.
- * @return The path to write this audio file to.
- */
- std::string multichannel_audio_out_path (int c, bool t) const {
- std::stringstream s;
- s << _multichannel_audio_out_path << "/" << (c + 1) << ".wav";
- if (t) {
- s << ".tmp";
- }
-
- return s.str ();
- }
-
- Size out_size; ///< size of output images
- int padding; ///< number of pixels of padding (in terms of the output size) each side of the image
-
- /** Range of video frames to encode (in DCP frames) */
- boost::optional<std::pair<int, int> > video_range;
- /** Range of audio frames to decode (in the DCP's sampling rate) */
- boost::optional<std::pair<int64_t, int64_t> > audio_range;
-
- /** true to skip every other frame */
- SourceFrame video_skip;
-
-private:
- /** Path of the directory to write video frames to */
- std::string _frame_out_path;
- /** Extension to use for video frame files (including the leading .) */
- std::string _frame_out_extension;
- /** Path of the directory to write audio files to */
- std::string _multichannel_audio_out_path;
-};
-
-
class DecodeOptions
{
public:
* @param o Options.
* @param req Job that must be completed before this job is run.
*/
-TranscodeJob::TranscodeJob (shared_ptr<Film> f, shared_ptr<const DecodeOptions> od, shared_ptr<const EncodeOptions> oe, shared_ptr<Job> req)
+TranscodeJob::TranscodeJob (shared_ptr<Film> f, shared_ptr<const DecodeOptions> od, shared_ptr<Job> req)
: Job (f, req)
, _decode_opt (od)
- , _encode_opt (oe)
{
}
_film->log()->log ("Transcode job starting");
_film->log()->log (String::compose ("Audio delay is %1ms", _film->audio_delay()));
- _encoder.reset (new Encoder (_film, _encode_opt));
+ _encoder.reset (new Encoder (_film));
Transcoder w (_film, _decode_opt, this, _encoder);
w.go ();
set_progress (1);
class Encoder;
class DecodeOptions;
-class EncodeOptions;
/** @class TranscodeJob
* @brief A job which transcodes from one format to another.
class TranscodeJob : public Job
{
public:
- TranscodeJob (boost::shared_ptr<Film> f, boost::shared_ptr<const DecodeOptions> od, boost::shared_ptr<const EncodeOptions> oe, boost::shared_ptr<Job> req);
+ TranscodeJob (boost::shared_ptr<Film> f, boost::shared_ptr<const DecodeOptions> od, boost::shared_ptr<Job> req);
std::string name () const;
void run ();
private:
boost::shared_ptr<const DecodeOptions> _decode_opt;
- boost::shared_ptr<const EncodeOptions> _encode_opt;
boost::shared_ptr<Encoder> _encoder;
};
class VideoDecoder;
class AudioDecoder;
class DelayLine;
-class EncodeOptions;
class DecodeOptions;
/** @class Transcoder