summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-04-26 23:49:54 +0100
committerCarl Hetherington <cth@carlh.net>2013-04-26 23:49:54 +0100
commit87a709a4ea5dffaadaf35ef94edb4b578eb3b56c (patch)
treef8a5aa8e9a2e16ebe4a38b917fd5bc9654866789 /src/lib
parentccc07eebc492d74c351c235584fd708c46b5b656 (diff)
parent86011ad6b4ea0004a51c59b0563cf89c0947546d (diff)
Merge master.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ab_transcoder.cc51
-rw-r--r--src/lib/ab_transcoder.h2
-rw-r--r--src/lib/analyse_audio_job.cc2
-rw-r--r--src/lib/analyse_audio_job.h2
-rw-r--r--src/lib/audio_sink.h4
-rw-r--r--src/lib/audio_source.cc6
-rw-r--r--src/lib/audio_source.h5
-rw-r--r--src/lib/combiner.cc11
-rw-r--r--src/lib/combiner.h4
-rw-r--r--src/lib/delay_line.cc4
-rw-r--r--src/lib/delay_line.h4
-rw-r--r--src/lib/encoder.cc8
-rw-r--r--src/lib/encoder.h4
-rw-r--r--src/lib/gain.cc2
-rw-r--r--src/lib/gain.h2
-rw-r--r--src/lib/image.cc28
-rw-r--r--src/lib/image.h1
-rw-r--r--src/lib/matcher.cc15
-rw-r--r--src/lib/matcher.h10
-rw-r--r--src/lib/transcoder.cc56
-rw-r--r--src/lib/transcoder.h2
-rw-r--r--src/lib/trimmer.cc27
-rw-r--r--src/lib/trimmer.h5
-rw-r--r--src/lib/util.cc90
-rw-r--r--src/lib/util.h1
-rw-r--r--src/lib/video_sink.h4
-rw-r--r--src/lib/video_source.cc8
-rw-r--r--src/lib/video_source.h5
28 files changed, 243 insertions, 120 deletions
diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc
index 6eef397c2..d8f13dae4 100644
--- a/src/lib/ab_transcoder.cc
+++ b/src/lib/ab_transcoder.cc
@@ -32,6 +32,7 @@
#include "delay_line.h"
#include "gain.h"
#include "combiner.h"
+#include "trimmer.h"
/** @file src/ab_transcoder.cc
* @brief A transcoder which uses one Film for the left half of the screen, and a different one
@@ -61,26 +62,48 @@ ABTranscoder::ABTranscoder (
_db = decoder_factory (_film_b, o);
shared_ptr<AudioStream> st = _film_a->audio_stream();
- _matcher.reset (new Matcher (_film_a->log(), st->sample_rate(), _film_a->source_frame_rate()));
+ if (st) {
+ _matcher.reset (new Matcher (_film_a->log(), st->sample_rate(), _film_a->source_frame_rate()));
+ }
_delay_line.reset (new DelayLine (_film_a->log(), _film_a->audio_delay() / 1000.0f));
_gain.reset (new Gain (_film_a->log(), _film_a->audio_gain()));
+ int const sr = st ? st->sample_rate() : 0;
+ int const trim_start = _film_a->trim_type() == Film::ENCODE ? _film_a->trim_start() : 0;
+ int const trim_end = _film_a->trim_type() == Film::ENCODE ? _film_a->trim_end() : 0;
+ _trimmer.reset (new Trimmer (
+ _film_a->log(), trim_start, trim_end, _film_a->length().get(),
+ sr, _film_a->source_frame_rate(), _film_a->dcp_frame_rate()
+ ));
+
/* Set up the decoder to use the film's set streams */
_da.video->set_subtitle_stream (_film_a->subtitle_stream ());
_db.video->set_subtitle_stream (_film_a->subtitle_stream ());
- _da.audio->set_audio_stream (_film_a->audio_stream ());
+ if (_film_a->audio_stream ()) {
+ _da.audio->set_audio_stream (_film_a->audio_stream ());
+ }
_da.video->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3, _4));
_db.video->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3, _4));
_combiner->connect_video (_delay_line);
- _delay_line->connect_video (_matcher);
- _matcher->connect_video (_encoder);
+ if (_matcher) {
+ _delay_line->connect_video (_matcher);
+ _matcher->connect_video (_trimmer);
+ } else {
+ _delay_line->connect_video (_trimmer);
+ }
+ _trimmer->connect_video (_encoder);
_da.audio->connect_audio (_delay_line);
- _delay_line->connect_audio (_matcher);
- _matcher->connect_audio (_gain);
- _gain->connect_audio (_encoder);
+ if (_matcher) {
+ _delay_line->connect_audio (_matcher);
+ _matcher->connect_audio (_gain);
+ } else {
+ _delay_line->connect_audio (_gain);
+ }
+ _gain->connect_audio (_trimmer);
+ _trimmer->connect_audio (_encoder);
}
void
@@ -99,25 +122,21 @@ ABTranscoder::go ()
} else {
done[2] = true;
}
-
+
if (_job) {
_da.video->set_progress (_job);
}
-
+
if (done[0] && done[1] && done[2]) {
break;
}
}
-
- if (_delay_line) {
- _delay_line->process_end ();
- }
+
+ _delay_line->process_end ();
if (_matcher) {
_matcher->process_end ();
}
- if (_gain) {
- _gain->process_end ();
- }
+ _gain->process_end ();
_encoder->process_end ();
}
diff --git a/src/lib/ab_transcoder.h b/src/lib/ab_transcoder.h
index 58a08af04..4f1b14e48 100644
--- a/src/lib/ab_transcoder.h
+++ b/src/lib/ab_transcoder.h
@@ -39,6 +39,7 @@ class Matcher;
class DelayLine;
class Gain;
class Combiner;
+class Trimmer;
/** @class ABTranscoder
* @brief A transcoder which uses one Film for the left half of the screen, and a different one
@@ -68,5 +69,6 @@ private:
boost::shared_ptr<Matcher> _matcher;
boost::shared_ptr<DelayLine> _delay_line;
boost::shared_ptr<Gain> _gain;
+ boost::shared_ptr<Trimmer> _trimmer;
boost::shared_ptr<Image> _image;
};
diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc
index 43eecbcbd..88cd65fee 100644
--- a/src/lib/analyse_audio_job.cc
+++ b/src/lib/analyse_audio_job.cc
@@ -84,7 +84,7 @@ AnalyseAudioJob::run ()
}
void
-AnalyseAudioJob::audio (shared_ptr<AudioBuffers> b)
+AnalyseAudioJob::audio (shared_ptr<const AudioBuffers> b)
{
for (int i = 0; i < b->frames(); ++i) {
for (int j = 0; j < b->channels(); ++j) {
diff --git a/src/lib/analyse_audio_job.h b/src/lib/analyse_audio_job.h
index dc1e073ee..5435e0a7c 100644
--- a/src/lib/analyse_audio_job.h
+++ b/src/lib/analyse_audio_job.h
@@ -31,7 +31,7 @@ public:
void run ();
private:
- void audio (boost::shared_ptr<AudioBuffers>);
+ void audio (boost::shared_ptr<const AudioBuffers>);
int64_t _done;
int64_t _samples_per_point;
diff --git a/src/lib/audio_sink.h b/src/lib/audio_sink.h
index f34b24f88..69b3a4b75 100644
--- a/src/lib/audio_sink.h
+++ b/src/lib/audio_sink.h
@@ -24,14 +24,14 @@ class AudioSink
{
public:
/** Call with some audio data */
- virtual void process_audio (boost::shared_ptr<AudioBuffers>) = 0;
+ virtual void process_audio (boost::shared_ptr<const AudioBuffers>) = 0;
};
class TimedAudioSink
{
public:
/** Call with some audio data */
- virtual void process_audio (boost::shared_ptr<AudioBuffers>, double t) = 0;
+ virtual void process_audio (boost::shared_ptr<const AudioBuffers>, double t) = 0;
};
#endif
diff --git a/src/lib/audio_source.cc b/src/lib/audio_source.cc
index bca3562cf..d77e89367 100644
--- a/src/lib/audio_source.cc
+++ b/src/lib/audio_source.cc
@@ -34,3 +34,9 @@ TimedAudioSource::connect_audio (shared_ptr<TimedAudioSink> s)
{
Audio.connect (bind (&TimedAudioSink::process_audio, s, _1, _2));
}
+
+void
+TimedAudioSource::connect_audio (shared_ptr<AudioSink> s)
+{
+ Audio.connect (bind (&AudioSink::process_audio, s, _1));
+}
diff --git a/src/lib/audio_source.h b/src/lib/audio_source.h
index 3dc998cca..c13f1636b 100644
--- a/src/lib/audio_source.h
+++ b/src/lib/audio_source.h
@@ -35,7 +35,7 @@ class AudioSource
{
public:
/** Emitted when some audio data is ready */
- boost::signals2::signal<void (boost::shared_ptr<AudioBuffers>)> Audio;
+ boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>)> Audio;
void connect_audio (boost::shared_ptr<AudioSink>);
};
@@ -46,8 +46,9 @@ class TimedAudioSource
{
public:
/** Emitted when some audio data is ready */
- boost::signals2::signal<void (boost::shared_ptr<AudioBuffers>, double)> Audio;
+ boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>, double)> Audio;
+ void connect_audio (boost::shared_ptr<AudioSink>);
void connect_audio (boost::shared_ptr<TimedAudioSink>);
};
diff --git a/src/lib/combiner.cc b/src/lib/combiner.cc
index 0a9eaf6b6..367cefa7f 100644
--- a/src/lib/combiner.cc
+++ b/src/lib/combiner.cc
@@ -33,9 +33,9 @@ Combiner::Combiner (shared_ptr<Log> log)
* @param image Frame image.
*/
void
-Combiner::process_video (shared_ptr<Image> image, bool, shared_ptr<Subtitle>, double)
+Combiner::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subtitle>, double)
{
- _image = image;
+ _image.reset (new SimpleImage (image));
}
/** Process video for the right half of the frame.
@@ -43,22 +43,21 @@ Combiner::process_video (shared_ptr<Image> image, bool, shared_ptr<Subtitle>, do
* @param sub Subtitle (which will be put onto the whole frame)
*/
void
-Combiner::process_video_b (shared_ptr<Image> image, bool, shared_ptr<Subtitle> sub, double t)
+Combiner::process_video_b (shared_ptr<const Image> image, bool, shared_ptr<Subtitle> sub, double t)
{
/* Copy the right half of this image into our _image */
/* XXX: this should probably be in the Image class */
for (int i = 0; i < image->components(); ++i) {
int const line_size = image->line_size()[i];
int const half_line_size = line_size / 2;
- int const stride = image->stride()[i];
uint8_t* p = _image->data()[i];
uint8_t* q = image->data()[i];
for (int j = 0; j < image->lines (i); ++j) {
memcpy (p + half_line_size, q + half_line_size, half_line_size);
- p += stride;
- q += stride;
+ p += _image->stride()[i];
+ q += image->stride()[i];
}
}
diff --git a/src/lib/combiner.h b/src/lib/combiner.h
index a8f1fa804..7ed316e26 100644
--- a/src/lib/combiner.h
+++ b/src/lib/combiner.h
@@ -33,8 +33,8 @@ class Combiner : public TimedVideoProcessor
public:
Combiner (boost::shared_ptr<Log> log);
- void process_video (boost::shared_ptr<Image> i, bool, boost::shared_ptr<Subtitle> s, double);
- void process_video_b (boost::shared_ptr<Image> i, bool, boost::shared_ptr<Subtitle> s, double);
+ void process_video (boost::shared_ptr<const Image> i, bool, boost::shared_ptr<Subtitle> s, double);
+ void process_video_b (boost::shared_ptr<const Image> i, bool, boost::shared_ptr<Subtitle> s, double);
private:
/** The image that we are currently working on */
diff --git a/src/lib/delay_line.cc b/src/lib/delay_line.cc
index 9e6baeba8..b0180800a 100644
--- a/src/lib/delay_line.cc
+++ b/src/lib/delay_line.cc
@@ -37,7 +37,7 @@ DelayLine::DelayLine (shared_ptr<Log> log, double seconds)
}
void
-DelayLine::process_audio (shared_ptr<AudioBuffers> data, double t)
+DelayLine::process_audio (shared_ptr<const AudioBuffers> data, double t)
{
if (_seconds > 0) {
t += _seconds;
@@ -47,7 +47,7 @@ DelayLine::process_audio (shared_ptr<AudioBuffers> data, double t)
}
void
-DelayLine::process_video (boost::shared_ptr<Image> image, bool same, boost::shared_ptr<Subtitle> sub, double t)
+DelayLine::process_video (shared_ptr<const Image> image, bool same, boost::shared_ptr<Subtitle> sub, double t)
{
if (_seconds < 0) {
t += _seconds;
diff --git a/src/lib/delay_line.h b/src/lib/delay_line.h
index 90f1dcfa7..781dce88a 100644
--- a/src/lib/delay_line.h
+++ b/src/lib/delay_line.h
@@ -26,8 +26,8 @@ class DelayLine : public TimedAudioVideoProcessor
public:
DelayLine (boost::shared_ptr<Log> log, double);
- void process_video (boost::shared_ptr<Image>, bool, boost::shared_ptr<Subtitle>, double);
- void process_audio (boost::shared_ptr<AudioBuffers>, double);
+ void process_video (boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, double);
+ void process_audio (boost::shared_ptr<const AudioBuffers>, double);
private:
double _seconds;
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index 7b338407e..cff9899ac 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -231,7 +231,7 @@ Encoder::frame_done ()
}
void
-Encoder::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Subtitle> sub)
+Encoder::process_video (shared_ptr<const Image> image, bool same, boost::shared_ptr<Subtitle> sub)
{
FrameRateConversion frc (_film->source_frame_rate(), _film->dcp_frame_rate());
@@ -294,7 +294,7 @@ Encoder::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Su
}
void
-Encoder::process_audio (shared_ptr<AudioBuffers> data)
+Encoder::process_audio (shared_ptr<const AudioBuffers> data)
{
#if HAVE_SWRESAMPLE
/* Maybe sample-rate convert */
@@ -333,7 +333,9 @@ Encoder::terminate_threads ()
lock.unlock ();
for (list<boost::thread *>::iterator i = _threads.begin(); i != _threads.end(); ++i) {
- (*i)->join ();
+ if ((*i)->joinable ()) {
+ (*i)->join ();
+ }
delete *i;
}
}
diff --git a/src/lib/encoder.h b/src/lib/encoder.h
index 86880bc34..70e81a7e0 100644
--- a/src/lib/encoder.h
+++ b/src/lib/encoder.h
@@ -73,10 +73,10 @@ public:
* @param same true if i is the same as the last time we were called.
* @param s A subtitle that should be on this frame, or 0.
*/
- void process_video (boost::shared_ptr<Image> i, bool same, boost::shared_ptr<Subtitle> s);
+ void process_video (boost::shared_ptr<const Image> i, bool same, boost::shared_ptr<Subtitle> s);
/** Call with some audio data */
- void process_audio (boost::shared_ptr<AudioBuffers>);
+ void process_audio (boost::shared_ptr<const AudioBuffers>);
/** Called when a processing run has finished */
virtual void process_end ();
diff --git a/src/lib/gain.cc b/src/lib/gain.cc
index df7011d2e..ccd779d71 100644
--- a/src/lib/gain.cc
+++ b/src/lib/gain.cc
@@ -30,7 +30,7 @@ Gain::Gain (shared_ptr<Log> log, float gain)
}
void
-Gain::process_audio (shared_ptr<AudioBuffers> b)
+Gain::process_audio (shared_ptr<const AudioBuffers> b)
{
if (_gain != 0) {
float const linear_gain = pow (10, _gain / 20);
diff --git a/src/lib/gain.h b/src/lib/gain.h
index d462e5aee..61fef5e85 100644
--- a/src/lib/gain.h
+++ b/src/lib/gain.h
@@ -24,7 +24,7 @@ class Gain : public AudioProcessor
public:
Gain (boost::shared_ptr<Log> log, float gain);
- void process_audio (boost::shared_ptr<AudioBuffers>);
+ void process_audio (boost::shared_ptr<const AudioBuffers>);
private:
float _gain;
diff --git a/src/lib/image.cc b/src/lib/image.cc
index 2355d22e5..1be41fecf 100644
--- a/src/lib/image.cc
+++ b/src/lib/image.cc
@@ -509,7 +509,33 @@ SimpleImage::SimpleImage (SimpleImage const & other)
allocate ();
for (int i = 0; i < components(); ++i) {
- memcpy (_data[i], other._data[i], _line_size[i] * lines(i));
+ uint8_t* p = _data[i];
+ uint8_t* q = other._data[i];
+ for (int j = 0; j < lines(i); ++j) {
+ memcpy (p, q, _line_size[i]);
+ p += stride()[i];
+ q += other.stride()[i];
+ }
+ }
+}
+
+SimpleImage::SimpleImage (shared_ptr<const Image> other)
+ : Image (*other.get())
+{
+ _size = other->size ();
+ _aligned = true;
+
+ allocate ();
+
+ for (int i = 0; i < components(); ++i) {
+ assert(line_size()[i] == other->line_size()[i]);
+ uint8_t* p = _data[i];
+ uint8_t* q = other->data()[i];
+ for (int j = 0; j < lines(i); ++j) {
+ memcpy (p, q, line_size()[i]);
+ p += stride()[i];
+ q += other->stride()[i];
+ }
}
}
diff --git a/src/lib/image.h b/src/lib/image.h
index 6b9ade99e..62961a92e 100644
--- a/src/lib/image.h
+++ b/src/lib/image.h
@@ -131,6 +131,7 @@ class SimpleImage : public Image
public:
SimpleImage (AVPixelFormat, libdcp::Size, bool);
SimpleImage (SimpleImage const &);
+ SimpleImage (boost::shared_ptr<const Image>);
SimpleImage& operator= (SimpleImage const &);
~SimpleImage ();
diff --git a/src/lib/matcher.cc b/src/lib/matcher.cc
index 34ddc86d6..9924c003a 100644
--- a/src/lib/matcher.cc
+++ b/src/lib/matcher.cc
@@ -41,7 +41,7 @@ Matcher::Matcher (shared_ptr<Log> log, int sample_rate, float frames_per_second)
}
void
-Matcher::process_video (boost::shared_ptr<Image> image, bool same, boost::shared_ptr<Subtitle> sub, double t)
+Matcher::process_video (boost::shared_ptr<const Image> image, bool same, boost::shared_ptr<Subtitle> sub, double t)
{
_pixel_format = image->pixel_format ();
_size = image->size ();
@@ -90,11 +90,15 @@ Matcher::process_video (boost::shared_ptr<Image> image, bool same, boost::shared
}
void
-Matcher::process_audio (boost::shared_ptr<AudioBuffers> b, double t)
+Matcher::process_audio (boost::shared_ptr<const AudioBuffers> b, double t)
{
_channels = b->channels ();
- _log->log (String::compose ("Matcher audio @ %1 [video=%2, audio=%3, pending_audio=%4]", t, _video_frames, _audio_frames, _pending_audio.size()));
+ _log->log (String::compose (
+ "Matcher audio (%1 frames) @ %2 [video=%3, audio=%4, pending_audio=%5]",
+ b->frames(), t, _video_frames, _audio_frames, _pending_audio.size()
+ )
+ );
if (!_first_input) {
_first_input = t;
@@ -198,8 +202,9 @@ void
Matcher::repeat_last_video ()
{
if (!_last_image) {
- _last_image.reset (new SimpleImage (_pixel_format.get(), _size.get(), true));
- _last_image->make_black ();
+ shared_ptr<Image> im (new SimpleImage (_pixel_format.get(), _size.get(), true));
+ im->make_black ();
+ _last_image = im;
}
Video (_last_image, true, _last_subtitle);
diff --git a/src/lib/matcher.h b/src/lib/matcher.h
index f54aa4b6a..41aa373a4 100644
--- a/src/lib/matcher.h
+++ b/src/lib/matcher.h
@@ -25,8 +25,8 @@ class Matcher : public Processor, public TimedAudioSink, public TimedVideoSink,
{
public:
Matcher (boost::shared_ptr<Log> log, int sample_rate, float frames_per_second);
- void process_video (boost::shared_ptr<Image> i, bool, boost::shared_ptr<Subtitle> s, double);
- void process_audio (boost::shared_ptr<AudioBuffers>, double);
+ void process_video (boost::shared_ptr<const Image> i, bool, boost::shared_ptr<Subtitle> s, double);
+ void process_audio (boost::shared_ptr<const AudioBuffers>, double);
void process_end ();
private:
@@ -43,19 +43,19 @@ private:
boost::optional<int> _channels;
struct AudioRecord {
- AudioRecord (boost::shared_ptr<AudioBuffers> a, double t)
+ AudioRecord (boost::shared_ptr<const AudioBuffers> a, double t)
: audio (a)
, time (t)
{}
- boost::shared_ptr<AudioBuffers> audio;
+ boost::shared_ptr<const AudioBuffers> audio;
double time;
};
std::list<AudioRecord> _pending_audio;
boost::optional<double> _first_input;
- boost::shared_ptr<Image> _last_image;
+ boost::shared_ptr<const Image> _last_image;
boost::shared_ptr<Subtitle> _last_subtitle;
bool _had_first_video;
diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc
index e00b2f1e0..faafcaf8b 100644
--- a/src/lib/transcoder.cc
+++ b/src/lib/transcoder.cc
@@ -36,6 +36,7 @@
#include "gain.h"
#include "video_decoder.h"
#include "audio_decoder.h"
+#include "trimmer.h"
using std::string;
using boost::shared_ptr;
@@ -61,6 +62,14 @@ Transcoder::Transcoder (shared_ptr<Film> f, DecodeOptions o, Job* j, shared_ptr<
_delay_line.reset (new DelayLine (f->log(), f->audio_delay() / 1000.0f));
_gain.reset (new Gain (f->log(), f->audio_gain()));
+ int const sr = st ? st->sample_rate() : 0;
+ int const trim_start = f->trim_type() == Film::ENCODE ? f->trim_start() : 0;
+ int const trim_end = f->trim_type() == Film::ENCODE ? f->trim_end() : 0;
+ _trimmer.reset (new Trimmer (
+ f->log(), trim_start, trim_end, f->length().get_value_or(0),
+ sr, f->source_frame_rate(), f->dcp_frame_rate()
+ ));
+
/* Set up the decoder to use the film's set streams */
_decoders.video->set_subtitle_stream (f->subtitle_stream ());
if (f->audio_stream ()) {
@@ -70,19 +79,21 @@ Transcoder::Transcoder (shared_ptr<Film> f, DecodeOptions o, Job* j, shared_ptr<
_decoders.video->connect_video (_delay_line);
if (_matcher) {
_delay_line->connect_video (_matcher);
- _matcher->connect_video (_encoder);
+ _matcher->connect_video (_trimmer);
} else {
- _delay_line->Video.connect (bind (&Encoder::process_video, _encoder, _1, _2, _3));
+ _delay_line->connect_video (_trimmer);
}
+ _trimmer->connect_video (_encoder);
_decoders.audio->connect_audio (_delay_line);
if (_matcher) {
_delay_line->connect_audio (_matcher);
_matcher->connect_audio (_gain);
} else {
- _delay_line->Audio.connect (bind (&Encoder::process_audio, _encoder, _1));
+ _delay_line->connect_audio (_gain);
}
- _gain->connect_audio (_encoder);
+ _gain->connect_audio (_trimmer);
+ _trimmer->connect_audio (_encoder);
}
/** Run the decoder, passing its output to the encoder, until the decoder
@@ -92,31 +103,26 @@ void
Transcoder::go ()
{
_encoder->process_begin ();
- try {
- bool done[2] = { false, false };
-
- while (1) {
- if (!done[0]) {
- done[0] = _decoders.video->pass ();
- if (_job) {
- _decoders.video->set_progress (_job);
- }
- }
-
- if (!done[1] && _decoders.audio && dynamic_pointer_cast<Decoder> (_decoders.audio) != dynamic_pointer_cast<Decoder> (_decoders.video)) {
- done[1] = _decoders.audio->pass ();
- } else {
- done[1] = true;
- }
- if (done[0] && done[1]) {
- break;
+ bool done[2] = { false, false };
+
+ while (1) {
+ if (!done[0]) {
+ done[0] = _decoders.video->pass ();
+ if (_job) {
+ _decoders.video->set_progress (_job);
}
}
- } catch (...) {
- _encoder->process_end ();
- throw;
+ if (!done[1] && _decoders.audio && dynamic_pointer_cast<Decoder> (_decoders.audio) != dynamic_pointer_cast<Decoder> (_decoders.video)) {
+ done[1] = _decoders.audio->pass ();
+ } else {
+ done[1] = true;
+ }
+
+ if (done[0] && done[1]) {
+ break;
+ }
}
_delay_line->process_end ();
diff --git a/src/lib/transcoder.h b/src/lib/transcoder.h
index b0c263d07..f5b8ae6e3 100644
--- a/src/lib/transcoder.h
+++ b/src/lib/transcoder.h
@@ -35,6 +35,7 @@ class Gain;
class VideoDecoder;
class AudioDecoder;
class DelayLine;
+class Trimmer;
/** @class Transcoder
* @brief A class which takes a Film and some Options, then uses those to transcode the film.
@@ -68,4 +69,5 @@ protected:
boost::shared_ptr<Matcher> _matcher;
boost::shared_ptr<DelayLine> _delay_line;
boost::shared_ptr<Gain> _gain;
+ boost::shared_ptr<Trimmer> _trimmer;
};
diff --git a/src/lib/trimmer.cc b/src/lib/trimmer.cc
index 68364e50a..b7afc9299 100644
--- a/src/lib/trimmer.cc
+++ b/src/lib/trimmer.cc
@@ -28,7 +28,8 @@ using boost::shared_ptr;
Trimmer::Trimmer (
shared_ptr<Log> log,
int video_trim_start,
- int video_trim_end, int video_length,
+ int video_trim_end,
+ int video_length,
int audio_sample_rate,
float frames_per_second,
int dcp_frames_per_second
@@ -53,12 +54,19 @@ Trimmer::Trimmer (
_audio_start = video_frames_to_audio_frames (_video_start, audio_sample_rate, frames_per_second);
_audio_end = video_frames_to_audio_frames (_video_end, audio_sample_rate, frames_per_second);
}
+
+ /* XXX: this is a hack; this flag means that no trim is happening at the end of the film, and I'm
+ using that to prevent audio trim being rounded to video trim, which breaks the current set
+ of regression tests. This could be removed if a) the regression tests are regenerated and b)
+ I can work out what DCP length should be.
+ */
+ _no_trim = (_video_start == 0) && (_video_end == (video_length - video_trim_end));
}
void
-Trimmer::process_video (shared_ptr<Image> image, bool same, shared_ptr<Subtitle> sub)
+Trimmer::process_video (shared_ptr<const Image> image, bool same, shared_ptr<Subtitle> sub)
{
- if (_video_in >= _video_start && _video_in <= _video_end) {
+ if (_no_trim || (_video_in >= _video_start && _video_in <= _video_end)) {
Video (image, same, sub);
}
@@ -66,8 +74,13 @@ Trimmer::process_video (shared_ptr<Image> image, bool same, shared_ptr<Subtitle>
}
void
-Trimmer::process_audio (shared_ptr<AudioBuffers> audio)
+Trimmer::process_audio (shared_ptr<const AudioBuffers> audio)
{
+ if (_no_trim) {
+ Audio (audio);
+ return;
+ }
+
int64_t offset = _audio_start - _audio_in;
if (offset > audio->frames()) {
_audio_in += audio->frames ();
@@ -91,8 +104,10 @@ Trimmer::process_audio (shared_ptr<AudioBuffers> audio)
_audio_in += audio->frames ();
if (offset != 0 || length != audio->frames ()) {
- audio->move (offset, 0, length);
- audio->set_frames (length);
+ shared_ptr<AudioBuffers> copy (new AudioBuffers (audio));
+ copy->move (offset, 0, length);
+ copy->set_frames (length);
+ audio = copy;
}
Audio (audio);
diff --git a/src/lib/trimmer.h b/src/lib/trimmer.h
index ff7e9514d..98a118fb2 100644
--- a/src/lib/trimmer.h
+++ b/src/lib/trimmer.h
@@ -24,8 +24,8 @@ class Trimmer : public AudioVideoProcessor
public:
Trimmer (boost::shared_ptr<Log>, int, int, int, int, float, int);
- void process_video (boost::shared_ptr<Image> i, bool, boost::shared_ptr<Subtitle> s);
- void process_audio (boost::shared_ptr<AudioBuffers>);
+ void process_video (boost::shared_ptr<const Image> i, bool, boost::shared_ptr<Subtitle> s);
+ void process_audio (boost::shared_ptr<const AudioBuffers>);
private:
friend class trimmer_test;
@@ -36,4 +36,5 @@ private:
int64_t _audio_start;
int64_t _audio_end;
int64_t _audio_in;
+ bool _no_trim;
};
diff --git a/src/lib/util.cc b/src/lib/util.cc
index e43b598ab..859aa6de7 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -63,11 +63,24 @@ extern "C" {
#include "i18n.h"
-using namespace std;
-using namespace boost;
+using std::cout;
+using std::string;
+using std::stringstream;
+using std::list;
+using std::ostream;
+using std::vector;
+using std::ifstream;
+using std::istream;
+using std::min;
+using std::max;
+using std::multimap;
+using std::pair;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using boost::optional;
using libdcp::Size;
-thread::id ui_thread;
+boost::thread::id ui_thread;
/** Convert some number of seconds to a string representation
* in hours, minutes and seconds.
@@ -87,9 +100,9 @@ seconds_to_hms (int s)
stringstream hms;
hms << h << N_(":");
hms.width (2);
- hms << setfill ('0') << m << N_(":");
+ hms << std::setfill ('0') << m << N_(":");
hms.width (2);
- hms << setfill ('0') << s;
+ hms << std::setfill ('0') << s;
return hms.str ();
}
@@ -185,7 +198,7 @@ stacktrace (ostream& out, int levels)
if (strings) {
for (i = 0; i < size && (levels == 0 || i < size_t(levels)); i++) {
- out << N_(" ") << demangle (strings[i]) << endl;
+ out << N_(" ") << demangle (strings[i]) << "\n";
}
free (strings);
@@ -243,7 +256,7 @@ dvdomatic_setup ()
Filter::setup_filters ();
SoundProcessor::setup_sound_processors ();
- ui_thread = this_thread::get_id ();
+ ui_thread = boost::this_thread::get_id ();
}
#ifdef DVDOMATIC_WINDOWS
@@ -338,7 +351,7 @@ md5_digest (void const * data, int size)
stringstream s;
for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) {
- s << hex << setfill('0') << setw(2) << ((int) digest[i]);
+ s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]);
}
return s.str ();
@@ -350,14 +363,14 @@ md5_digest (void const * data, int size)
string
md5_digest (string file)
{
- ifstream f (file.c_str(), ios::binary);
+ ifstream f (file.c_str(), std::ios::binary);
if (!f.good ()) {
throw OpenFileError (file);
}
- f.seekg (0, ios::end);
+ f.seekg (0, std::ios::end);
int bytes = f.tellg ();
- f.seekg (0, ios::beg);
+ f.seekg (0, std::ios::beg);
int const buffer_size = 64 * 1024;
char buffer[buffer_size];
@@ -376,7 +389,7 @@ md5_digest (string file)
stringstream s;
for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) {
- s << hex << setfill('0') << setw(2) << ((int) digest[i]);
+ s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]);
}
return s.str ();
@@ -441,8 +454,8 @@ best_dcp_frame_rate (float source_fps)
}
/* Pick the best one, bailing early if we hit an exact match */
- float error = numeric_limits<float>::max ();
- boost::optional<FrameRateCandidate> best;
+ float error = std::numeric_limits<float>::max ();
+ optional<FrameRateCandidate> best;
list<FrameRateCandidate>::iterator i = candidates.begin();
while (i != candidates.end()) {
@@ -509,16 +522,16 @@ Socket::Socket (int timeout)
, _socket (_io_service)
, _timeout (timeout)
{
- _deadline.expires_at (posix_time::pos_infin);
+ _deadline.expires_at (boost::posix_time::pos_infin);
check ();
}
void
Socket::check ()
{
- if (_deadline.expires_at() <= asio::deadline_timer::traits_type::now ()) {
+ if (_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now ()) {
_socket.close ();
- _deadline.expires_at (posix_time::pos_infin);
+ _deadline.expires_at (boost::posix_time::pos_infin);
}
_deadline.async_wait (boost::bind (&Socket::check, this));
@@ -528,14 +541,14 @@ Socket::check ()
* @param endpoint End-point to connect to.
*/
void
-Socket::connect (asio::ip::basic_resolver_entry<asio::ip::tcp> const & endpoint)
+Socket::connect (boost::asio::ip::basic_resolver_entry<boost::asio::ip::tcp> const & endpoint)
{
- _deadline.expires_from_now (posix_time::seconds (_timeout));
- system::error_code ec = asio::error::would_block;
- _socket.async_connect (endpoint, lambda::var(ec) = lambda::_1);
+ _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
+ boost::system::error_code ec = boost::asio::error::would_block;
+ _socket.async_connect (endpoint, boost::lambda::var(ec) = boost::lambda::_1);
do {
_io_service.run_one();
- } while (ec == asio::error::would_block);
+ } while (ec == boost::asio::error::would_block);
if (ec || !_socket.is_open ()) {
throw NetworkError (_("connect timed out"));
@@ -549,14 +562,14 @@ Socket::connect (asio::ip::basic_resolver_entry<asio::ip::tcp> const & endpoint)
void
Socket::write (uint8_t const * data, int size)
{
- _deadline.expires_from_now (posix_time::seconds (_timeout));
- system::error_code ec = asio::error::would_block;
+ _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
+ boost::system::error_code ec = boost::asio::error::would_block;
- asio::async_write (_socket, asio::buffer (data, size), lambda::var(ec) = lambda::_1);
+ boost::asio::async_write (_socket, boost::asio::buffer (data, size), boost::lambda::var(ec) = boost::lambda::_1);
do {
_io_service.run_one ();
- } while (ec == asio::error::would_block);
+ } while (ec == boost::asio::error::would_block);
if (ec) {
throw NetworkError (ec.message ());
@@ -577,14 +590,14 @@ Socket::write (uint32_t v)
void
Socket::read (uint8_t* data, int size)
{
- _deadline.expires_from_now (posix_time::seconds (_timeout));
- system::error_code ec = asio::error::would_block;
+ _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
+ boost::system::error_code ec = boost::asio::error::would_block;
- asio::async_read (_socket, asio::buffer (data, size), lambda::var(ec) = lambda::_1);
+ boost::asio::async_read (_socket, boost::asio::buffer (data, size), boost::lambda::var(ec) = boost::lambda::_1);
do {
_io_service.run_one ();
- } while (ec == asio::error::would_block);
+ } while (ec == boost::asio::error::would_block);
if (ec) {
throw NetworkError (ec.message ());
@@ -761,6 +774,21 @@ AudioBuffers::AudioBuffers (AudioBuffers const & other)
}
}
+/* XXX: it's a shame that this is a copy-and-paste of the above;
+ probably fixable with c++0x.
+*/
+AudioBuffers::AudioBuffers (boost::shared_ptr<const AudioBuffers> other)
+ : _channels (other->_channels)
+ , _frames (other->_frames)
+ , _allocated_frames (other->_frames)
+{
+ _data = new float*[_channels];
+ for (int i = 0; i < _channels; ++i) {
+ _data[i] = new float[_frames];
+ memcpy (_data[i], other->_data[i], _frames * sizeof (float));
+ }
+}
+
/** AudioBuffers destructor */
AudioBuffers::~AudioBuffers ()
{
@@ -865,7 +893,7 @@ AudioBuffers::move (int from, int to, int frames)
void
ensure_ui_thread ()
{
- assert (this_thread::get_id() == ui_thread);
+ assert (boost::this_thread::get_id() == ui_thread);
}
/** @param v Source video frame.
diff --git a/src/lib/util.h b/src/lib/util.h
index 31d0fc967..99670110e 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -241,6 +241,7 @@ class AudioBuffers
public:
AudioBuffers (int channels, int frames);
AudioBuffers (AudioBuffers const &);
+ AudioBuffers (boost::shared_ptr<const AudioBuffers>);
~AudioBuffers ();
float** data () const {
diff --git a/src/lib/video_sink.h b/src/lib/video_sink.h
index 32c7f3b38..0170c7350 100644
--- a/src/lib/video_sink.h
+++ b/src/lib/video_sink.h
@@ -34,7 +34,7 @@ public:
* @param same true if i is the same as last time we were called.
* @param s A subtitle that should be on this frame, or 0.
*/
- virtual void process_video (boost::shared_ptr<Image> i, bool same, boost::shared_ptr<Subtitle> s) = 0;
+ virtual void process_video (boost::shared_ptr<const Image> i, bool same, boost::shared_ptr<Subtitle> s) = 0;
};
class TimedVideoSink
@@ -46,7 +46,7 @@ public:
* @param s A subtitle that should be on this frame, or 0.
* @param t Source timestamp.
*/
- virtual void process_video (boost::shared_ptr<Image> i, bool same, boost::shared_ptr<Subtitle> s, double t) = 0;
+ virtual void process_video (boost::shared_ptr<const Image> i, bool same, boost::shared_ptr<Subtitle> s, double t) = 0;
};
#endif
diff --git a/src/lib/video_source.cc b/src/lib/video_source.cc
index af6f941fd..539243402 100644
--- a/src/lib/video_source.cc
+++ b/src/lib/video_source.cc
@@ -34,3 +34,11 @@ TimedVideoSource::connect_video (shared_ptr<TimedVideoSink> s)
{
Video.connect (bind (&TimedVideoSink::process_video, s, _1, _2, _3, _4));
}
+
+void
+TimedVideoSource::connect_video (shared_ptr<VideoSink> s)
+{
+ Video.connect (bind (&VideoSink::process_video, s, _1, _2, _3));
+}
+
+
diff --git a/src/lib/video_source.h b/src/lib/video_source.h
index 705b0023a..748cb6fe9 100644
--- a/src/lib/video_source.h
+++ b/src/lib/video_source.h
@@ -45,7 +45,7 @@ public:
* Second parameter is true if the image is the same as the last one that was emitted.
* Third parameter is either 0 or a subtitle that should be on this frame.
*/
- boost::signals2::signal<void (boost::shared_ptr<Image>, bool, boost::shared_ptr<Subtitle>)> Video;
+ boost::signals2::signal<void (boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>)> Video;
void connect_video (boost::shared_ptr<VideoSink>);
};
@@ -63,8 +63,9 @@ public:
* Third parameter is either 0 or a subtitle that should be on this frame.
* Fourth parameter is the source timestamp of this frame.
*/
- boost::signals2::signal<void (boost::shared_ptr<Image>, bool, boost::shared_ptr<Subtitle>, double)> Video;
+ boost::signals2::signal<void (boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, double)> Video;
+ void connect_video (boost::shared_ptr<VideoSink>);
void connect_video (boost::shared_ptr<TimedVideoSink>);
};