diff options
Diffstat (limited to 'src/lib/encoder.cc')
| -rw-r--r-- | src/lib/encoder.cc | 98 |
1 files changed, 38 insertions, 60 deletions
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 731a39042..0f48310ef 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -34,6 +34,7 @@ #include "config.h" #include "dcp_video_frame.h" #include "server.h" +#include "format.h" #include "cross.h" using std::pair; @@ -50,16 +51,16 @@ int const Encoder::_history_size = 25; /** @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) @@ -74,9 +75,9 @@ Encoder::Encoder (shared_ptr<const Film> f, shared_ptr<const EncodeOptions> o) /* 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); } @@ -170,10 +171,10 @@ Encoder::process_end () /* 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)); } } @@ -208,7 +209,7 @@ Encoder::process_end () _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 ())); @@ -222,8 +223,8 @@ Encoder::process_end () /* 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)); } } @@ -252,12 +253,12 @@ Encoder::skipping () const 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. @@ -290,19 +291,13 @@ Encoder::frame_skipped () 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 */ @@ -317,7 +312,7 @@ Encoder::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Su } /* 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; } @@ -327,54 +322,37 @@ Encoder::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Su 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) { @@ -418,7 +396,7 @@ Encoder::process_audio (shared_ptr<AudioBuffers> data) write_audio (data); - _audio_frame += data->frames (); + _audio_frames_in += data->frames (); } void @@ -428,7 +406,7 @@ Encoder::write_audio (shared_ptr<const AudioBuffers> audio) sf_write_float (_sound_files[i], audio->data(i), audio->frames()); } - _audio_frames_written += audio->frames (); + _audio_frames_out += audio->frames (); } void |
