diff options
| author | Carl Hetherington <cth@carlh.net> | 2017-07-26 17:08:00 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2017-07-26 17:08:00 +0100 |
| commit | 0302594838ce422afb3346ecc91a1bdfd26c00de (patch) | |
| tree | d1087c24b51044ad4870c4b9017144d686b60852 /src/lib | |
| parent | e1093a718c15e1c9ca98abbf514ec54293f0723a (diff) | |
Basic multithread of DCP decryption during export.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/dcp_encoder.cc | 4 | ||||
| -rw-r--r-- | src/lib/dcp_encoder.h | 4 | ||||
| -rw-r--r-- | src/lib/encoder.cc | 4 | ||||
| -rw-r--r-- | src/lib/encoder.h | 8 | ||||
| -rw-r--r-- | src/lib/ffmpeg_encoder.cc | 50 | ||||
| -rw-r--r-- | src/lib/ffmpeg_encoder.h | 11 |
6 files changed, 56 insertions, 25 deletions
diff --git a/src/lib/dcp_encoder.cc b/src/lib/dcp_encoder.cc index 67235e596..5ee6cca98 100644 --- a/src/lib/dcp_encoder.cc +++ b/src/lib/dcp_encoder.cc @@ -61,6 +61,10 @@ DCPEncoder::DCPEncoder (shared_ptr<const Film> film, weak_ptr<Job> job) , _finishing (false) , _non_burnt_subtitles (false) { + _player_video_connection = _player->Video.connect (bind (&DCPEncoder::video, this, _1, _2)); + _player_audio_connection = _player->Audio.connect (bind (&DCPEncoder::audio, this, _1, _2)); + _player_subtitle_connection = _player->Subtitle.connect (bind (&DCPEncoder::subtitle, this, _1, _2)); + BOOST_FOREACH (shared_ptr<const Content> c, film->content ()) { if (c->subtitle && c->subtitle->use() && !c->subtitle->burn()) { _non_burnt_subtitles = true; diff --git a/src/lib/dcp_encoder.h b/src/lib/dcp_encoder.h index b1514efdc..0fa20c2c9 100644 --- a/src/lib/dcp_encoder.h +++ b/src/lib/dcp_encoder.h @@ -60,4 +60,8 @@ private: boost::shared_ptr<J2KEncoder> _j2k_encoder; bool _finishing; bool _non_burnt_subtitles; + + boost::signals2::scoped_connection _player_video_connection; + boost::signals2::scoped_connection _player_audio_connection; + boost::signals2::scoped_connection _player_subtitle_connection; }; diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 16d992314..535389a94 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -43,7 +43,5 @@ Encoder::Encoder (shared_ptr<const Film> film, weak_ptr<Job> job) , _job (job) , _player (new Player (film, film->playlist ())) { - _player_video_connection = _player->Video.connect (bind (&Encoder::video, this, _1, _2)); - _player_audio_connection = _player->Audio.connect (bind (&Encoder::audio, this, _1, _2)); - _player_subtitle_connection = _player->Subtitle.connect (bind (&Encoder::subtitle, this, _1, _2)); + } diff --git a/src/lib/encoder.h b/src/lib/encoder.h index 645401952..4907ed7c5 100644 --- a/src/lib/encoder.h +++ b/src/lib/encoder.h @@ -49,17 +49,9 @@ public: virtual bool finishing () const = 0; protected: - virtual void video (boost::shared_ptr<PlayerVideo>, DCPTime) = 0; - virtual void audio (boost::shared_ptr<AudioBuffers>, DCPTime) = 0; - virtual void subtitle (PlayerSubtitles, DCPTimePeriod) = 0; - boost::shared_ptr<const Film> _film; boost::weak_ptr<Job> _job; boost::shared_ptr<Player> _player; - - boost::signals2::scoped_connection _player_video_connection; - boost::signals2::scoped_connection _player_audio_connection; - boost::signals2::scoped_connection _player_subtitle_connection; }; #endif diff --git a/src/lib/ffmpeg_encoder.cc b/src/lib/ffmpeg_encoder.cc index 9dba02dd5..2a9146f11 100644 --- a/src/lib/ffmpeg_encoder.cc +++ b/src/lib/ffmpeg_encoder.cc @@ -26,6 +26,7 @@ #include "log.h" #include "image.h" #include "cross.h" +#include "butler.h" #include "compose.hpp" #include <iostream> @@ -34,6 +35,7 @@ using std::string; using std::runtime_error; using std::cout; +using std::pair; using boost::shared_ptr; using boost::bind; using boost::weak_ptr; @@ -75,24 +77,29 @@ FFmpegEncoder::FFmpegEncoder (shared_ptr<const Film> film, weak_ptr<Job> job, bo int const ch = film->audio_channels (); + AudioMapping map; if (mixdown_to_stereo) { - _audio_mapping = AudioMapping (ch, 2); + _output_audio_channels = 2; + map = AudioMapping (ch, 2); float const overall_gain = 2 / (4 + sqrt(2)); float const minus_3dB = 1 / sqrt(2); - _audio_mapping.set (dcp::LEFT, 0, overall_gain); - _audio_mapping.set (dcp::RIGHT, 1, overall_gain); - _audio_mapping.set (dcp::CENTRE, 0, overall_gain * minus_3dB); - _audio_mapping.set (dcp::CENTRE, 1, overall_gain * minus_3dB); - _audio_mapping.set (dcp::LS, 0, overall_gain); - _audio_mapping.set (dcp::RS, 1, overall_gain); + map.set (dcp::LEFT, 0, overall_gain); + map.set (dcp::RIGHT, 1, overall_gain); + map.set (dcp::CENTRE, 0, overall_gain * minus_3dB); + map.set (dcp::CENTRE, 1, overall_gain * minus_3dB); + map.set (dcp::LS, 0, overall_gain); + map.set (dcp::RS, 1, overall_gain); _pending_audio.reset (new AudioBuffers (2, 0)); } else { - _audio_mapping = AudioMapping (ch, ch); + _output_audio_channels = ch; + map = AudioMapping (ch, ch); _pending_audio.reset (new AudioBuffers (ch, 0)); for (int i = 0; i < ch; ++i) { - _audio_mapping.set (i, i, 1); + map.set (i, i, 1); } } + + _butler.reset (new Butler (film, _player, map, _output_audio_channels)); } void @@ -138,8 +145,8 @@ FFmpegEncoder::setup_audio () _audio_codec_context->bit_rate = 256 * 1024; _audio_codec_context->sample_fmt = _sample_format; _audio_codec_context->sample_rate = _film->audio_frame_rate (); - _audio_codec_context->channel_layout = av_get_default_channel_layout (_audio_mapping.output_channels ()); - _audio_codec_context->channels = _audio_mapping.output_channels (); + _audio_codec_context->channel_layout = av_get_default_channel_layout (_output_audio_channels); + _audio_codec_context->channels = _output_audio_channels; } void @@ -194,7 +201,24 @@ FFmpegEncoder::go () job->sub (_("Encoding")); } - while (!_player->pass ()) {} + DCPTime const video_frame = DCPTime::from_frames (1, _film->video_frame_rate ()); + int const audio_frames = video_frame.frames_round(_film->audio_frame_rate()); + float* interleaved = new float[_output_audio_channels * audio_frames]; + shared_ptr<AudioBuffers> deinterleaved (new AudioBuffers (_output_audio_channels, audio_frames)); + for (DCPTime i; i < _film->length(); i += video_frame) { + pair<shared_ptr<PlayerVideo>, DCPTime> v = _butler->get_video (); + video (v.first, v.second); + _butler->get_audio (interleaved, audio_frames); + /* XXX: inefficient; butler interleaves and we deinterleave again */ + float* p = interleaved; + for (int i = 0; i < audio_frames; ++i) { + for (int j = 0; j < _output_audio_channels; ++j) { + deinterleaved->data(j)[i] = *p++; + } + } + audio (deinterleaved, i); + } + delete[] interleaved; if (_pending_audio->frames() > 0) { audio_frame (_pending_audio->frames ()); @@ -308,7 +332,7 @@ FFmpegEncoder::video (shared_ptr<PlayerVideo> video, DCPTime time) void FFmpegEncoder::audio (shared_ptr<AudioBuffers> audio, DCPTime) { - _pending_audio->append (remap (audio, _audio_mapping.output_channels(), _audio_mapping)); + _pending_audio->append (audio); int frame_size = _audio_codec_context->frame_size; if (frame_size == 0) { diff --git a/src/lib/ffmpeg_encoder.h b/src/lib/ffmpeg_encoder.h index 5ab59c12d..5e6dcecf7 100644 --- a/src/lib/ffmpeg_encoder.h +++ b/src/lib/ffmpeg_encoder.h @@ -28,6 +28,9 @@ extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> } +#include <boost/thread/condition.hpp> + +class Butler; class FFmpegEncoder : public Encoder { @@ -70,7 +73,7 @@ private: AVDictionary* _video_options; std::string _video_codec_name; std::string _audio_codec_name; - AudioMapping _audio_mapping; + int _output_audio_channels; mutable boost::mutex _mutex; DCPTime _last_time; @@ -81,6 +84,12 @@ private: boost::shared_ptr<AudioBuffers> _pending_audio; + mutable boost::mutex _queue_mutex; + boost::condition _queue_full; + std::list<std::pair<boost::shared_ptr<PlayerVideo>, DCPTime> > _queue; + + boost::shared_ptr<Butler> _butler; + static int _video_stream_index; static int _audio_stream_index; }; |
