#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)
+ , _video_frames_in (0)
+ , _audio_frames_in (0)
+ , _video_frames_out (0)
+ , _audio_frames_out (0)
#ifdef HAVE_SWRESAMPLE
, _swr_context (0)
#endif
- , _audio_frames_written (0)
, _terminate_encoder (false)
, _writer_thread (0)
, _terminate_writer (false)
/* 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));
}
}
return _just_skipped;
}
-/** @return Number of video frames that have been received */
-SourceFrame
-Encoder::video_frame () const
+/** @return Number of video frames that have been sent out */
+int
+Encoder::video_frames_out () const
{
boost::mutex::scoped_lock (_history_mutex);
- return _video_frame;
+ return _video_frames_out;
}
/** Should be called when a frame has been encoded successfully.
void
Encoder::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Subtitle> sub)
{
- if (_opt->video_skip != 0 && (_video_frame % _opt->video_skip) != 0) {
- ++_video_frame;
+ DCPFrameRate dfr (_film->frames_per_second ());
+
+ if (dfr.skip && (_video_frames_in % 2)) {
+ ++_video_frames_in;
return;
}
- if (_opt->video_range) {
- pair<SourceFrame, SourceFrame> const r = _opt->video_range.get();
- if (_video_frame < r.first || _video_frame >= r.second) {
- ++_video_frame;
- return;
- }
- }
-
boost::mutex::scoped_lock lock (_worker_mutex);
/* Wait until the queue has gone down a bit */
}
/* 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_frames_out, false))) {
frame_skipped ();
return;
}
as on windows the link is really a copy and the reference frame might not have
finished encoding yet.
*/
- _links_required.push_back (make_pair (_last_real_frame.get(), _video_frame));
+ _links_required.push_back (make_pair (_last_real_frame.get(), _video_frames_out));
} else {
/* Queue this new frame for encoding */
pair<string, string> const s = Filter::ffmpeg_strings (_film->filters());
TIMING ("adding to queue of %1", _encode_queue.size ());
_encode_queue.push_back (boost::shared_ptr<DCPVideoFrame> (
new DCPVideoFrame (
- image, sub, _opt->out_size, _opt->padding, _film->subtitle_offset(), _film->subtitle_scale(),
- _film->scaler(), _video_frame, _film->frames_per_second(), s.second,
- Config::instance()->colour_lut_index (), Config::instance()->j2k_bandwidth (),
+ image, sub, _film->format()->dcp_size(), _film->format()->dcp_padding (_film),
+ _film->subtitle_offset(), _film->subtitle_scale(),
+ _film->scaler(), _video_frames_out, _film->frames_per_second(), s.second,
+ _film->colour_lut(), _film->j2k_bandwidth(),
_film->log()
)
));
_worker_condition.notify_all ();
- _last_real_frame = _video_frame;
+ _last_real_frame = _video_frames_out;
}
- ++_video_frame;
+ ++_video_frames_in;
+ ++_video_frames_out;
+
+ if (dfr.repeat) {
+ _links_required.push_back (make_pair (_video_frames_out, _video_frames_out - 1));
+ ++_video_frames_out;
+ }
}
void
Encoder::process_audio (shared_ptr<AudioBuffers> data)
{
- if (_opt->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();
- /* Range of this block of data */
- pair<int64_t, int64_t> this_range (_audio_frame, _audio_frame + trimmed->frames());
-
- if (this_range.second < required_range.first || required_range.second < this_range.first) {
- /* No part of this audio is within the required range */
- return;
- } else if (required_range.first >= this_range.first && required_range.first < this_range.second) {
- /* Trim start */
- int64_t const shift = required_range.first - this_range.first;
- trimmed->move (shift, 0, trimmed->frames() - shift);
- trimmed->set_frames (trimmed->frames() - shift);
- } else if (required_range.second >= this_range.first && required_range.second < this_range.second) {
- /* Trim end */
- trimmed->set_frames (required_range.second - this_range.first);
- }
-
- data = trimmed;
- }
-
#if HAVE_SWRESAMPLE
/* Maybe sample-rate convert */
if (_swr_context) {
write_audio (data);
- _audio_frame += data->frames ();
+ _audio_frames_in += data->frames ();
}
void
sf_write_float (_sound_files[i], audio->data(i), audio->frames());
}
- _audio_frames_written += audio->frames ();
+ _audio_frames_out += audio->frames ();
}
void