_da = decoder_factory (_film_a, o);
_db = decoder_factory (_film_b, o);
- if (_film_a->audio_stream()) {
- shared_ptr<AudioStream> st = _film_a->audio_stream();
- _matcher.reset (new Matcher (_film_a->log(), st->sample_rate(), _film_a->source_frame_rate()));
- _delay_line.reset (new DelayLine (_film_a->log(), st->channels(), _film_a->audio_delay() * st->sample_rate() / 1000));
- _gain.reset (new Gain (_film_a->log(), _film_a->audio_gain()));
- }
+ shared_ptr<AudioStream> st = _film_a->audio_stream();
+ _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()));
/* Set up the decoder to use the film's set streams */
_da.video->set_subtitle_stream (_film_a->subtitle_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));
- if (_matcher) {
- _combiner->connect_video (_matcher);
- _matcher->connect_video (_encoder);
- } else {
- /* Remove timestamp from the output of the combiner */
- _combiner->Video.connect (bind (&Encoder::process_video, _encoder, _1, _2, _3));
- }
+ _combiner->connect_video (_delay_line);
+ _delay_line->connect_video (_matcher);
+ _matcher->connect_video (_encoder);
- if (_matcher && _delay_line) {
- _da.audio->connect_audio (_delay_line);
- _delay_line->connect_audio (_matcher);
- _matcher->connect_audio (_gain);
- _gain->connect_audio (_encoder);
- }
+ _da.audio->connect_audio (_delay_line);
+ _delay_line->connect_audio (_matcher);
+ _matcher->connect_audio (_gain);
+ _gain->connect_audio (_encoder);
}
void
using std::min;
using boost::shared_ptr;
-/** @param channels Number of channels of audio.
- * @param frames Delay in frames, +ve to move audio later.
+/* @param seconds Delay in seconds, +ve to move audio later.
*/
-DelayLine::DelayLine (Log* log, int channels, int frames)
+DelayLine::DelayLine (Log* log, double seconds)
: Processor (log)
- , _negative_delay_remaining (0)
- , _frames (frames)
+ , _seconds (seconds)
{
- if (_frames > 0) {
- /* We need a buffer to keep some data in */
- _buffers.reset (new AudioBuffers (channels, _frames));
- _buffers->make_silent ();
- } else if (_frames < 0) {
- /* We can do -ve delays just by chopping off
- the start, so no buffer needed.
- */
- _negative_delay_remaining = -_frames;
- }
+
}
-/* XXX: can we just get rid of all this and fiddle with the timestamp? */
void
DelayLine::process_audio (shared_ptr<AudioBuffers> data, double t)
{
- if (_buffers) {
- /* We have some buffers, so we are moving the audio later */
-
- /* Copy the input data */
- AudioBuffers input (*data.get ());
-
- int to_do = data->frames ();
-
- /* Write some of our buffer to the output */
- int const from_buffer = min (to_do, _buffers->frames());
- data->copy_from (_buffers.get(), from_buffer, 0, 0);
- to_do -= from_buffer;
-
- /* Write some of the input to the output */
- int const from_input = to_do;
- data->copy_from (&input, from_input, 0, from_buffer);
-
- int const left_in_buffer = _buffers->frames() - from_buffer;
-
- /* Shuffle our buffer down */
- _buffers->move (from_buffer, 0, left_in_buffer);
-
- /* Copy remaining input data to our buffer */
- _buffers->copy_from (&input, input.frames() - from_input, from_input, left_in_buffer);
-
- } else {
+ if (_seconds > 0) {
+ t += _seconds;
+ }
- /* Chop the initial data off until _negative_delay_remaining
- is zero, then just pass data.
- */
+ Audio (data, t);
+}
- int const to_do = min (data->frames(), _negative_delay_remaining);
- if (to_do) {
- data->move (to_do, 0, data->frames() - to_do);
- data->set_frames (data->frames() - to_do);
- _negative_delay_remaining -= to_do;
- }
+void
+DelayLine::process_video (boost::shared_ptr<Image> image, bool same, boost::shared_ptr<Subtitle> sub, double t)
+{
+ if (_seconds < 0) {
+ t += _seconds;
}
- Audio (data, t);
+ Video (image, same, sub, t);
}
#include <boost/shared_ptr.hpp>
#include "processor.h"
-class AudioBuffers;
-
/** A delay line for audio */
-class DelayLine : public Processor, public TimedAudioSink, public TimedAudioSource
+class DelayLine : public Processor, public TimedAudioSink, public TimedAudioSource, public TimedVideoSink, public TimedVideoSource
{
public:
- DelayLine (Log* log, int channels, int frames);
+ DelayLine (Log* log, double);
+ void process_video (boost::shared_ptr<Image>, bool, boost::shared_ptr<Subtitle>, double);
void process_audio (boost::shared_ptr<AudioBuffers>, double);
private:
- boost::shared_ptr<AudioBuffers> _buffers;
- int _negative_delay_remaining; ///< number of frames of negative delay that remain to emit
- int _frames;
+ double _seconds;
};
shared_ptr<AudioStream> st = f->audio_stream();
_matcher.reset (new Matcher (f->log(), st->sample_rate(), f->source_frame_rate()));
- _delay_line.reset (new DelayLine (f->log(), st->channels(), f->audio_delay() * st->sample_rate() / 1000));
+ _delay_line.reset (new DelayLine (f->log(), f->audio_delay() / 1000.0f));
_gain.reset (new Gain (f->log(), f->audio_gain()));
/* Set up the decoder to use the film's set streams */
_decoders.video->set_subtitle_stream (f->subtitle_stream ());
_decoders.audio->set_audio_stream (f->audio_stream ());
- _decoders.video->connect_video (_matcher);
+ _decoders.video->connect_video (_delay_line);
+ _delay_line->connect_video (_matcher);
_matcher->connect_video (_encoder);
_decoders.audio->connect_audio (_delay_line);
throw;
}
- if (_delay_line) {
- _delay_line->process_end ();
- }
- if (_matcher) {
- _matcher->process_end ();
- }
- if (_gain) {
- _gain->process_end ();
- }
+ _delay_line->process_end ();
+ _matcher->process_end ();
+ _gain->process_end ();
_encoder->process_end ();
}
#include "job_manager.h"
#include "util.h"
#include "exceptions.h"
-#include "delay_line.h"
#include "image.h"
#include "log.h"
#include "dcp_video_frame.h"
void do_log (string) {}
};
-void
-do_positive_delay_line_test (int delay_length, int data_length)
-{
- NullLog log;
-
- DelayLine d (&log, 6, delay_length);
- shared_ptr<AudioBuffers> data (new AudioBuffers (6, data_length));
-
- int in = 0;
- int out = 0;
- int returned = 0;
- int zeros = 0;
-
- for (int i = 0; i < 64; ++i) {
- for (int j = 0; j < data_length; ++j) {
- for (int c = 0; c < 6; ++c ) {
- data->data(c)[j] = in;
- ++in;
- }
- }
-
- /* This only works because the delay line modifies the parameter */
- /* XXX: timestamp is wrong */
- d.process_audio (data, 0);
- returned += data->frames ();
-
- for (int j = 0; j < data->frames(); ++j) {
- if (zeros < delay_length) {
- for (int c = 0; c < 6; ++c) {
- BOOST_CHECK_EQUAL (data->data(c)[j], 0);
- }
- ++zeros;
- } else {
- for (int c = 0; c < 6; ++c) {
- BOOST_CHECK_EQUAL (data->data(c)[j], out);
- ++out;
- }
- }
- }
- }
-
- BOOST_CHECK_EQUAL (returned, 64 * data_length);
-}
-
-void
-do_negative_delay_line_test (int delay_length, int data_length)
-{
- NullLog log;
-
- DelayLine d (&log, 6, delay_length);
- shared_ptr<AudioBuffers> data (new AudioBuffers (6, data_length));
-
- int in = 0;
- int out = -delay_length * 6;
- int returned = 0;
-
- for (int i = 0; i < 256; ++i) {
- data->set_frames (data_length);
- for (int j = 0; j < data_length; ++j) {
- for (int c = 0; c < 6; ++c) {
- data->data(c)[j] = in;
- ++in;
- }
- }
-
- /* This only works because the delay line modifies the parameter */
- /* XXX: timestamp is wrong */
- d.process_audio (data, 0);
- returned += data->frames ();
-
- for (int j = 0; j < data->frames(); ++j) {
- for (int c = 0; c < 6; ++c) {
- BOOST_CHECK_EQUAL (data->data(c)[j], out);
- ++out;
- }
- }
- }
-
- returned += -delay_length;
- BOOST_CHECK_EQUAL (returned, 256 * data_length);
-}
-
-BOOST_AUTO_TEST_CASE (delay_line_test)
-{
- do_positive_delay_line_test (64, 128);
- do_positive_delay_line_test (128, 64);
- do_positive_delay_line_test (3, 512);
- do_positive_delay_line_test (512, 3);
-
- do_positive_delay_line_test (0, 64);
-
- do_negative_delay_line_test (-64, 128);
- do_negative_delay_line_test (-128, 64);
- do_negative_delay_line_test (-3, 512);
- do_negative_delay_line_test (-512, 3);
-}
-
BOOST_AUTO_TEST_CASE (md5_digest_test)
{
string const t = md5_digest ("test/md5.test");