summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2017-07-26 17:08:00 +0100
committerCarl Hetherington <cth@carlh.net>2017-07-26 17:08:00 +0100
commit0302594838ce422afb3346ecc91a1bdfd26c00de (patch)
treed1087c24b51044ad4870c4b9017144d686b60852 /src/lib
parente1093a718c15e1c9ca98abbf514ec54293f0723a (diff)
Basic multithread of DCP decryption during export.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/dcp_encoder.cc4
-rw-r--r--src/lib/dcp_encoder.h4
-rw-r--r--src/lib/encoder.cc4
-rw-r--r--src/lib/encoder.h8
-rw-r--r--src/lib/ffmpeg_encoder.cc50
-rw-r--r--src/lib/ffmpeg_encoder.h11
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;
};