summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2012-11-12 21:04:06 +0000
committerCarl Hetherington <cth@carlh.net>2012-11-12 21:04:06 +0000
commit17cea71c34ed6bdba67aac8614572c7511844c2a (patch)
tree41464576c5e2e6ab360789faf4b5fcc4358ee556 /src
parent13b935067e892875ea9e76c3d63fcc11d2c429b0 (diff)
Untested; more movement of stuff out of decoder.
Diffstat (limited to 'src')
-rw-r--r--src/lib/ab_transcoder.cc17
-rw-r--r--src/lib/ab_transcoder.h3
-rw-r--r--src/lib/decoder.cc89
-rw-r--r--src/lib/decoder.h23
-rw-r--r--src/lib/delay_line.cc32
-rw-r--r--src/lib/delay_line.h10
-rw-r--r--src/lib/encoder.cc29
-rw-r--r--src/lib/encoder.h25
-rw-r--r--src/lib/imagemagick_encoder.cc16
-rw-r--r--src/lib/imagemagick_encoder.h4
-rw-r--r--src/lib/j2k_still_encoder.cc4
-rw-r--r--src/lib/j2k_still_encoder.h4
-rw-r--r--src/lib/j2k_wav_encoder.cc12
-rw-r--r--src/lib/j2k_wav_encoder.h4
-rw-r--r--src/lib/transcode_job.cc2
-rw-r--r--src/lib/transcoder.cc17
-rw-r--r--src/lib/transcoder.h3
-rw-r--r--src/lib/wscript3
18 files changed, 112 insertions, 185 deletions
diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc
index 4183749c8..868ce9079 100644
--- a/src/lib/ab_transcoder.cc
+++ b/src/lib/ab_transcoder.cc
@@ -50,14 +50,13 @@ ABTranscoder::ABTranscoder (
, _opt (o)
, _job (j)
, _encoder (e)
- , _last_frame (0)
{
_da = decoder_factory (_film_a, o, j);
_db = decoder_factory (_film_b, o, j);
- _da->Video.connect (bind (&ABTranscoder::process_video, this, _1, _2, _3, 0));
- _db->Video.connect (bind (&ABTranscoder::process_video, this, _1, _2, _3, 1));
- _da->Audio.connect (bind (&Encoder::process_audio, e, _1, _2));
+ _da->Video.connect (bind (&ABTranscoder::process_video, this, _1, _2, 0));
+ _db->Video.connect (bind (&ABTranscoder::process_video, this, _1, _2, 1));
+ _da->Audio.connect (bind (&Encoder::process_audio, e, _1));
}
ABTranscoder::~ABTranscoder ()
@@ -66,7 +65,7 @@ ABTranscoder::~ABTranscoder ()
}
void
-ABTranscoder::process_video (shared_ptr<Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub, int index)
+ABTranscoder::process_video (shared_ptr<Image> yuv, shared_ptr<Subtitle> sub, int index)
{
if (index == 0) {
/* Keep this image around until we get the other half */
@@ -89,11 +88,9 @@ ABTranscoder::process_video (shared_ptr<Image> yuv, SourceFrame frame, shared_pt
}
/* And pass it to the encoder */
- _encoder->process_video (_image, frame, sub);
+ _encoder->process_video (_image, sub);
_image.reset ();
}
-
- _last_frame = frame;
}
@@ -101,8 +98,6 @@ void
ABTranscoder::go ()
{
_encoder->process_begin ();
- _da->process_begin ();
- _db->process_begin ();
while (1) {
bool const a = _da->pass ();
@@ -114,7 +109,5 @@ ABTranscoder::go ()
}
_encoder->process_end ();
- _da->process_end ();
- _db->process_end ();
}
diff --git a/src/lib/ab_transcoder.h b/src/lib/ab_transcoder.h
index a136fd270..c75398b5c 100644
--- a/src/lib/ab_transcoder.h
+++ b/src/lib/ab_transcoder.h
@@ -55,7 +55,7 @@ public:
void go ();
private:
- void process_video (boost::shared_ptr<Image>, SourceFrame, boost::shared_ptr<Subtitle>, int);
+ void process_video (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>, int);
boost::shared_ptr<Film> _film_a;
boost::shared_ptr<Film> _film_b;
@@ -64,6 +64,5 @@ private:
boost::shared_ptr<Encoder> _encoder;
boost::shared_ptr<Decoder> _da;
boost::shared_ptr<Decoder> _db;
- SourceFrame _last_frame;
boost::shared_ptr<Image> _image;
};
diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc
index eb9667471..73e17e7ea 100644
--- a/src/lib/decoder.cc
+++ b/src/lib/decoder.cc
@@ -56,89 +56,14 @@ Decoder::Decoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o,
, _opt (o)
, _job (j)
, _video_frame (0)
- , _audio_frame (0)
- , _delay_line (0)
- , _delay_in_frames (0)
{
}
-Decoder::~Decoder ()
-{
- delete _delay_line;
-}
-
-/** Start off a decode processing run. This should only be called once on
- * a given Decoder object.
- */
-void
-Decoder::process_begin ()
-{
- if (_audio_stream) {
- _delay_in_frames = _film->audio_delay() * _audio_stream.get().sample_rate() / 1000;
- _delay_line = new DelayLine (_audio_stream.get().channels(), _delay_in_frames);
- }
-}
-
-/** Finish off a decode processing run */
-void
-Decoder::process_end ()
-{
- if (_delay_in_frames < 0 && _opt->decode_audio && _audio_stream) {
- shared_ptr<AudioBuffers> b (new AudioBuffers (_audio_stream.get().channels(), -_delay_in_frames));
- b->make_silent ();
- emit_audio (b);
- }
-
- if (_opt->decode_audio && _audio_stream) {
-
- /* Ensure that our video and audio emissions are the same length */
-
- int64_t audio_short_by_frames = video_frames_to_audio_frames (_video_frame, _audio_stream.get().sample_rate(), frames_per_second()) - _audio_frame;
-
- _film->log()->log (
- String::compose (
- "Decoder has emitted %1 video frames (which equals %2 audio frames) and %3 audio frames",
- _video_frame,
- video_frames_to_audio_frames (_video_frame, _audio_stream.get().sample_rate(), frames_per_second()),
- _audio_frame
- )
- );
-
- if (audio_short_by_frames < 0) {
-
- _film->log()->log (String::compose ("Emitted %1 too many audio frames", -audio_short_by_frames));
-
- /* We have emitted more audio than video. Emit enough black video frames so that we reverse this */
- int const black_video_frames = ceil (-audio_short_by_frames * frames_per_second() / _audio_stream.get().sample_rate());
-
- _film->log()->log (String::compose ("Emitting %1 frames of black video", black_video_frames));
-
- shared_ptr<Image> black (new CompactImage (pixel_format(), native_size()));
- black->make_black ();
- for (int i = 0; i < black_video_frames; ++i) {
- emit_video (black, shared_ptr<Subtitle> ());
- }
-
- /* Now recompute our check value */
- audio_short_by_frames = video_frames_to_audio_frames (_video_frame, _audio_stream.get().sample_rate(), frames_per_second()) - _audio_frame;
- }
-
- if (audio_short_by_frames > 0) {
- _film->log()->log (String::compose ("Emitted %1 too few audio frames", audio_short_by_frames));
- shared_ptr<AudioBuffers> b (new AudioBuffers (_audio_stream.get().channels(), audio_short_by_frames));
- b->make_silent ();
- emit_audio (b);
- }
- }
-}
-
/** Start decoding */
void
Decoder::go ()
{
- process_begin ();
-
if (_job && !_film->dcp_length()) {
_job->set_progress_unknown ();
}
@@ -148,8 +73,6 @@ Decoder::go ()
_job->set_progress (float (_video_frame) / _film->length().get());
}
}
-
- process_end ();
}
/** Called to tell the world that some audio data is ready
@@ -168,8 +91,7 @@ Decoder::process_audio (shared_ptr<AudioBuffers> audio)
}
}
- _delay_line->feed (audio);
- emit_audio (audio);
+ Audio (audio);
}
/** Called by subclasses to tell the world that some video data is ready.
@@ -221,7 +143,7 @@ void
Decoder::emit_video (shared_ptr<Image> image, shared_ptr<Subtitle> sub)
{
TIMING ("Decoder emits %1", _video_frame);
- Video (image, _video_frame, sub);
+ Video (image, sub);
++_video_frame;
_last_image = image;
@@ -229,13 +151,6 @@ Decoder::emit_video (shared_ptr<Image> image, shared_ptr<Subtitle> sub)
}
void
-Decoder::emit_audio (shared_ptr<AudioBuffers> audio)
-{
- Audio (audio, _audio_frame);
- _audio_frame += audio->frames ();
-}
-
-void
Decoder::process_subtitle (shared_ptr<TimedSubtitle> s)
{
_timed_subtitle = s;
diff --git a/src/lib/decoder.h b/src/lib/decoder.h
index d0e20b03a..71dfed1e0 100644
--- a/src/lib/decoder.h
+++ b/src/lib/decoder.h
@@ -31,6 +31,8 @@
#include <boost/signals2.hpp>
#include "util.h"
#include "stream.h"
+#include "video_source.h"
+#include "audio_source.h"
class Job;
class Options;
@@ -49,11 +51,11 @@ class FilterGraph;
* (by calling ::go), and they emit signals when video or audio data is ready for something else
* to process.
*/
-class Decoder
+class Decoder : public VideoSource, public AudioSource
{
public:
Decoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *);
- virtual ~Decoder ();
+ virtual ~Decoder () {}
/* Methods to query our input video */
@@ -67,9 +69,7 @@ public:
virtual int sample_aspect_ratio_numerator () const = 0;
virtual int sample_aspect_ratio_denominator () const = 0;
- void process_begin ();
virtual bool pass () = 0;
- void process_end ();
void go ();
SourceFrame video_frame () const {
@@ -95,16 +95,6 @@ public:
return _subtitle_streams;
}
- /** Emitted when a video frame is ready.
- * First parameter is the frame within the source.
- * Second parameter is its index within the content.
- * Third parameter is either 0 or a subtitle that should be on this frame.
- */
- boost::signals2::signal<void (boost::shared_ptr<Image>, SourceFrame, boost::shared_ptr<Subtitle>)> Video;
-
- /** Emitted when some audio data is ready */
- boost::signals2::signal<void (boost::shared_ptr<AudioBuffers>, int64_t)> Audio;
-
protected:
virtual PixelFormat pixel_format () const = 0;
@@ -129,16 +119,11 @@ protected:
private:
void emit_video (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>);
- void emit_audio (boost::shared_ptr<AudioBuffers>);
SourceFrame _video_frame;
- int64_t _audio_frame;
std::list<boost::shared_ptr<FilterGraph> > _filter_graphs;
- DelayLine* _delay_line;
- int _delay_in_frames;
-
boost::shared_ptr<TimedSubtitle> _timed_subtitle;
boost::shared_ptr<Image> _last_image;
diff --git a/src/lib/delay_line.cc b/src/lib/delay_line.cc
index e7cd8dc94..45d8e9d9d 100644
--- a/src/lib/delay_line.cc
+++ b/src/lib/delay_line.cc
@@ -30,28 +30,25 @@ using boost::shared_ptr;
/** @param channels Number of channels of audio.
* @param frames Delay in frames, +ve to move audio later.
*/
-DelayLine::DelayLine (int channels, int frames)
- : _negative_delay_remaining (0)
+DelayLine::DelayLine (Log* log, int channels, int frames)
+ : AudioProcessor (log)
+ , _negative_delay_remaining (0)
+ , _frames (frames)
{
- if (frames > 0) {
+ if (_frames > 0) {
/* We need a buffer to keep some data in */
- _buffers.reset (new AudioBuffers (channels, frames));
+ _buffers.reset (new AudioBuffers (channels, _frames));
_buffers->make_silent ();
- } else if (frames < 0) {
+ } else if (_frames < 0) {
/* We can do -ve delays just by chopping off
the start, so no buffer needed.
*/
- _negative_delay_remaining = -frames;
+ _negative_delay_remaining = -_frames;
}
}
-DelayLine::~DelayLine ()
-{
-
-}
-
void
-DelayLine::feed (shared_ptr<AudioBuffers> data)
+DelayLine::process_audio (shared_ptr<AudioBuffers> data)
{
if (_buffers) {
/* We have some buffers, so we are moving the audio later */
@@ -91,4 +88,15 @@ DelayLine::feed (shared_ptr<AudioBuffers> data)
_negative_delay_remaining -= to_do;
}
}
+
+ Audio (data);
+}
+
+void
+DelayLine::process_end ()
+{
+ if (_frames < 0) {
+ _buffers->make_silent ();
+ Audio (_buffers);
+ }
}
diff --git a/src/lib/delay_line.h b/src/lib/delay_line.h
index e8d9560af..fa2870ae7 100644
--- a/src/lib/delay_line.h
+++ b/src/lib/delay_line.h
@@ -18,19 +18,21 @@
*/
#include <boost/shared_ptr.hpp>
+#include "processor.h"
class AudioBuffers;
/** A delay line for audio */
-class DelayLine
+class DelayLine : public AudioProcessor
{
public:
- DelayLine (int channels, int frames);
- ~DelayLine ();
+ DelayLine (Log* log, int channels, int frames);
- void feed (boost::shared_ptr<AudioBuffers>);
+ void process_audio (boost::shared_ptr<AudioBuffers>);
+ void process_end ();
private:
boost::shared_ptr<AudioBuffers> _buffers;
int _negative_delay_remaining; ///< number of frames of negative delay that remain to emit
+ int _frames;
};
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index b322be04c..17a6726a6 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -37,7 +37,8 @@ Encoder::Encoder (shared_ptr<const Film> f, shared_ptr<const Options> o)
: _film (f)
, _opt (o)
, _just_skipped (false)
- , _last_frame (0)
+ , _video_frame (0)
+ , _audio_frame (0)
{
}
@@ -68,23 +69,22 @@ Encoder::skipping () const
return _just_skipped;
}
-/** @return Index of last frame to be successfully encoded */
+/** @return Number of video frames that have been received */
SourceFrame
-Encoder::last_frame () const
+Encoder::video_frame () const
{
boost::mutex::scoped_lock (_history_mutex);
- return _last_frame;
+ return _video_frame;
}
/** Should be called when a frame has been encoded successfully.
* @param n Source frame index.
*/
void
-Encoder::frame_done (SourceFrame n)
+Encoder::frame_done ()
{
boost::mutex::scoped_lock lock (_history_mutex);
_just_skipped = false;
- _last_frame = n;
struct timeval tv;
gettimeofday (&tv, 0);
@@ -105,24 +105,27 @@ Encoder::frame_skipped ()
}
void
-Encoder::process_video (shared_ptr<const Image> i, SourceFrame f, boost::shared_ptr<Subtitle> s)
+Encoder::process_video (shared_ptr<Image> i, boost::shared_ptr<Subtitle> s)
{
- if (_opt->decode_video_skip != 0 && (f % _opt->decode_video_skip) != 0) {
+ if (_opt->decode_video_skip != 0 && (_video_frame % _opt->decode_video_skip) != 0) {
+ ++_video_frame;
return;
}
if (_opt->video_decode_range) {
pair<SourceFrame, SourceFrame> const r = _opt->video_decode_range.get();
- if (f < r.first || f >= r.second) {
+ if (_video_frame < r.first || _video_frame >= r.second) {
+ ++_video_frame;
return;
}
}
- do_process_video (i, f, s);
+ do_process_video (i, s);
+ ++_video_frame;
}
void
-Encoder::process_audio (shared_ptr<const AudioBuffers> data, int64_t f)
+Encoder::process_audio (shared_ptr<AudioBuffers> data)
{
if (_opt->audio_decode_range) {
@@ -131,7 +134,7 @@ Encoder::process_audio (shared_ptr<const AudioBuffers> data, int64_t f)
/* Range that we are encoding */
pair<int64_t, int64_t> required_range = _opt->audio_decode_range.get();
/* Range of this block of data */
- pair<int64_t, int64_t> this_range (f, f + trimmed->frames());
+ 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 */
@@ -150,4 +153,6 @@ Encoder::process_audio (shared_ptr<const AudioBuffers> data, int64_t f)
}
do_process_audio (data);
+
+ _audio_frame += data->frames ();
}
diff --git a/src/lib/encoder.h b/src/lib/encoder.h
index e04397f78..68a5f6139 100644
--- a/src/lib/encoder.h
+++ b/src/lib/encoder.h
@@ -32,6 +32,8 @@ extern "C" {
#include <libavutil/samplefmt.h>
}
#include "util.h"
+#include "video_sink.h"
+#include "audio_sink.h"
class Options;
class Image;
@@ -49,7 +51,7 @@ class Film;
* some way and write it to disk.
*/
-class Encoder
+class Encoder : public VideoSink, public AudioSink
{
public:
Encoder (boost::shared_ptr<const Film> f, boost::shared_ptr<const Options> o);
@@ -59,34 +61,32 @@ public:
/** Call with a frame of video.
* @param i Video frame image.
- * @param f Frame number within the film's source.
* @param s A subtitle that should be on this frame, or 0.
*/
- void process_video (boost::shared_ptr<const Image> i, SourceFrame f, boost::shared_ptr<Subtitle> s);
+ void process_video (boost::shared_ptr<Image> i, boost::shared_ptr<Subtitle> s);
/** Call with some audio data */
- void process_audio (boost::shared_ptr<const AudioBuffers>, int64_t);
+ void process_audio (boost::shared_ptr<AudioBuffers>);
/** Called when a processing run has finished */
virtual void process_end () {}
float current_frames_per_second () const;
bool skipping () const;
- SourceFrame last_frame () const;
+ SourceFrame video_frame () const;
protected:
/** Called with a frame of video.
* @param i Video frame image.
- * @param f Frame number within the film's source.
* @param s A subtitle that should be on this frame, or 0.
*/
- virtual void do_process_video (boost::shared_ptr<const Image> i, SourceFrame f, boost::shared_ptr<Subtitle> s) = 0;
+ virtual void do_process_video (boost::shared_ptr<Image> i, boost::shared_ptr<Subtitle> s) = 0;
/** Called with some audio data */
- virtual void do_process_audio (boost::shared_ptr<const AudioBuffers>) = 0;
+ virtual void do_process_audio (boost::shared_ptr<AudioBuffers>) = 0;
- void frame_done (SourceFrame n);
+ void frame_done ();
void frame_skipped ();
/** Film that we are encoding */
@@ -104,8 +104,11 @@ protected:
static int const _history_size;
/** true if the last frame we processed was skipped (because it was already done) */
bool _just_skipped;
- /** Source index of the last frame to be processed */
- SourceFrame _last_frame;
+
+ /** Number of video frames received so far */
+ SourceFrame _video_frame;
+ /** Number of audio frames received so far */
+ int64_t _audio_frame;
};
#endif
diff --git a/src/lib/imagemagick_encoder.cc b/src/lib/imagemagick_encoder.cc
index 6c70e3749..480dec8bc 100644
--- a/src/lib/imagemagick_encoder.cc
+++ b/src/lib/imagemagick_encoder.cc
@@ -50,22 +50,22 @@ ImageMagickEncoder::ImageMagickEncoder (shared_ptr<const Film> f, shared_ptr<con
}
void
-ImageMagickEncoder::do_process_video (shared_ptr<const Image> image, SourceFrame frame, shared_ptr<Subtitle> sub)
+ImageMagickEncoder::do_process_video (shared_ptr<Image> image, shared_ptr<Subtitle> sub)
{
shared_ptr<Image> scaled = image->scale_and_convert_to_rgb (_opt->out_size, _opt->padding, _film->scaler());
shared_ptr<Image> compact (new CompactImage (scaled));
- string tmp_file = _opt->frame_out_path (frame, true);
+ string tmp_file = _opt->frame_out_path (_video_frame, true);
Magick::Image thumb (compact->size().width, compact->size().height, "RGB", MagickCore::CharPixel, compact->data()[0]);
thumb.magick ("PNG");
thumb.write (tmp_file);
- boost::filesystem::rename (tmp_file, _opt->frame_out_path (frame, false));
+ boost::filesystem::rename (tmp_file, _opt->frame_out_path (_video_frame, false));
if (sub) {
float const x_scale = float (_opt->out_size.width) / _film->size().width;
float const y_scale = float (_opt->out_size.height) / _film->size().height;
- string tmp_metadata_file = _opt->frame_out_path (frame, false, ".sub");
+ string tmp_metadata_file = _opt->frame_out_path (_video_frame, false, ".sub");
ofstream metadata (tmp_metadata_file.c_str ());
Size new_size = sub->image()->size ();
@@ -74,18 +74,18 @@ ImageMagickEncoder::do_process_video (shared_ptr<const Image> image, SourceFrame
shared_ptr<Image> scaled = sub->image()->scale (new_size, _film->scaler());
shared_ptr<Image> compact (new CompactImage (scaled));
- string tmp_sub_file = _opt->frame_out_path (frame, true, ".sub.png");
+ string tmp_sub_file = _opt->frame_out_path (_video_frame, true, ".sub.png");
Magick::Image sub_thumb (compact->size().width, compact->size().height, "RGBA", MagickCore::CharPixel, compact->data()[0]);
sub_thumb.magick ("PNG");
sub_thumb.write (tmp_sub_file);
- boost::filesystem::rename (tmp_sub_file, _opt->frame_out_path (frame, false, ".sub.png"));
+ boost::filesystem::rename (tmp_sub_file, _opt->frame_out_path (_video_frame, false, ".sub.png"));
metadata << "x " << sub->position().x << "\n"
<< "y " << sub->position().y << "\n";
metadata.close ();
- boost::filesystem::rename (tmp_metadata_file, _opt->frame_out_path (frame, false, ".sub"));
+ boost::filesystem::rename (tmp_metadata_file, _opt->frame_out_path (_video_frame, false, ".sub"));
}
- frame_done (frame);
+ frame_done ();
}
diff --git a/src/lib/imagemagick_encoder.h b/src/lib/imagemagick_encoder.h
index 02458fc5b..dfc741cb2 100644
--- a/src/lib/imagemagick_encoder.h
+++ b/src/lib/imagemagick_encoder.h
@@ -37,6 +37,6 @@ public:
ImageMagickEncoder (boost::shared_ptr<const Film> f, boost::shared_ptr<const Options> o);
private:
- void do_process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
- void do_process_audio (boost::shared_ptr<const AudioBuffers>) {}
+ void do_process_video (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>);
+ void do_process_audio (boost::shared_ptr<AudioBuffers>) {}
};
diff --git a/src/lib/j2k_still_encoder.cc b/src/lib/j2k_still_encoder.cc
index 2d6c457fc..a4ac54e7a 100644
--- a/src/lib/j2k_still_encoder.cc
+++ b/src/lib/j2k_still_encoder.cc
@@ -49,7 +49,7 @@ J2KStillEncoder::J2KStillEncoder (shared_ptr<const Film> f, shared_ptr<const Opt
}
void
-J2KStillEncoder::do_process_video (shared_ptr<const Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub)
+J2KStillEncoder::do_process_video (shared_ptr<Image> yuv, shared_ptr<Subtitle> sub)
{
pair<string, string> const s = Filter::ffmpeg_strings (_film->filters());
DCPVideoFrame* f = new DCPVideoFrame (
@@ -77,6 +77,6 @@ J2KStillEncoder::do_process_video (shared_ptr<const Image> yuv, SourceFrame fram
boost::filesystem::copy_file (real, link);
#endif
}
- frame_done (0);
+ frame_done ();
}
}
diff --git a/src/lib/j2k_still_encoder.h b/src/lib/j2k_still_encoder.h
index 65cfa7cac..4ffe876af 100644
--- a/src/lib/j2k_still_encoder.h
+++ b/src/lib/j2k_still_encoder.h
@@ -37,6 +37,6 @@ public:
J2KStillEncoder (boost::shared_ptr<const Film>, boost::shared_ptr<const Options>);
private:
- void do_process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
- void do_process_audio (boost::shared_ptr<const AudioBuffers>) {}
+ void do_process_video (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>);
+ void do_process_audio (boost::shared_ptr<AudioBuffers>) {}
};
diff --git a/src/lib/j2k_wav_encoder.cc b/src/lib/j2k_wav_encoder.cc
index 108320d32..847ee9486 100644
--- a/src/lib/j2k_wav_encoder.cc
+++ b/src/lib/j2k_wav_encoder.cc
@@ -108,7 +108,7 @@ J2KWAVEncoder::close_sound_files ()
}
void
-J2KWAVEncoder::do_process_video (shared_ptr<const Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub)
+J2KWAVEncoder::do_process_video (shared_ptr<Image> yuv, shared_ptr<Subtitle> sub)
{
boost::mutex::scoped_lock lock (_worker_mutex);
@@ -124,13 +124,13 @@ J2KWAVEncoder::do_process_video (shared_ptr<const Image> yuv, SourceFrame frame,
}
/* Only do the processing if we don't already have a file for this frame */
- if (!boost::filesystem::exists (_opt->frame_out_path (frame, false))) {
+ if (!boost::filesystem::exists (_opt->frame_out_path (_video_frame, false))) {
pair<string, string> const s = Filter::ffmpeg_strings (_film->filters());
TIMING ("adding to queue of %1", _queue.size ());
_queue.push_back (boost::shared_ptr<DCPVideoFrame> (
new DCPVideoFrame (
yuv, sub, _opt->out_size, _opt->padding, _film->subtitle_offset(), _film->subtitle_scale(),
- _film->scaler(), frame, _film->frames_per_second(), s.second,
+ _film->scaler(), _video_frame, _film->frames_per_second(), s.second,
Config::instance()->colour_lut_index (), Config::instance()->j2k_bandwidth (),
_film->log()
)
@@ -207,7 +207,7 @@ J2KWAVEncoder::encoder_thread (ServerDescription* server)
if (encoded) {
encoded->write (_opt, vf->frame ());
- frame_done (vf->frame ());
+ frame_done ();
} else {
lock.lock ();
_film->log()->log (
@@ -305,7 +305,7 @@ J2KWAVEncoder::process_end ()
try {
shared_ptr<EncodedData> e = (*i)->encode_locally ();
e->write (_opt, (*i)->frame ());
- frame_done ((*i)->frame ());
+ frame_done ();
} catch (std::exception& e) {
_film->log()->log (String::compose ("Local encode failed (%1)", e.what ()));
}
@@ -355,7 +355,7 @@ J2KWAVEncoder::process_end ()
}
void
-J2KWAVEncoder::do_process_audio (shared_ptr<const AudioBuffers> audio)
+J2KWAVEncoder::do_process_audio (shared_ptr<AudioBuffers> audio)
{
shared_ptr<AudioBuffers> resampled;
diff --git a/src/lib/j2k_wav_encoder.h b/src/lib/j2k_wav_encoder.h
index 5cf508cff..f3340ba72 100644
--- a/src/lib/j2k_wav_encoder.h
+++ b/src/lib/j2k_wav_encoder.h
@@ -55,8 +55,8 @@ public:
private:
- void do_process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
- void do_process_audio (boost::shared_ptr<const AudioBuffers>);
+ void do_process_video (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>);
+ void do_process_audio (boost::shared_ptr<AudioBuffers>);
void write_audio (boost::shared_ptr<const AudioBuffers> audio);
void encoder_thread (ServerDescription *);
diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc
index 25581c8f5..5e9e58667 100644
--- a/src/lib/transcode_job.cc
+++ b/src/lib/transcode_job.cc
@@ -116,6 +116,6 @@ TranscodeJob::remaining_time () const
}
/* We assume that dcp_length() is valid */
- SourceFrame const left = _film->dcp_trim_start() + _film->dcp_length().get() - _encoder->last_frame();
+ SourceFrame const left = _film->dcp_trim_start() + _film->dcp_length().get() - _encoder->video_frame();
return left / fps;
}
diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc
index ac908768e..f53fc4001 100644
--- a/src/lib/transcoder.cc
+++ b/src/lib/transcoder.cc
@@ -30,6 +30,8 @@
#include "encoder.h"
#include "decoder_factory.h"
#include "film.h"
+#include "matcher.h"
+#include "delay_line.h"
using std::string;
using boost::shared_ptr;
@@ -47,12 +49,21 @@ Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j,
{
assert (_encoder);
+ AudioStream st = f->audio_stream().get();
+
+ _matcher.reset (new Matcher (f->log(), st.sample_rate(), f->frames_per_second()));
+ _delay_line.reset (new DelayLine (f->log(), st.channels(), f->audio_delay() * st.sample_rate() / 1000));
+
/* Set up the decoder to use the film's set streams */
_decoder->set_audio_stream (f->audio_stream ());
_decoder->set_subtitle_stream (f->subtitle_stream ());
-
- _decoder->Video.connect (bind (&Encoder::process_video, e, _1, _2, _3));
- _decoder->Audio.connect (bind (&Encoder::process_audio, e, _1, _2));
+
+ _decoder->connect_video (_matcher);
+ _matcher->connect_video (_encoder);
+
+ _decoder->connect_audio (_delay_line);
+ _delay_line->connect_audio (_matcher);
+ _matcher->connect_audio (_delay_line);
}
/** Run the decoder, passing its output to the encoder, until the decoder
diff --git a/src/lib/transcoder.h b/src/lib/transcoder.h
index 79ef89a18..d5597ad0e 100644
--- a/src/lib/transcoder.h
+++ b/src/lib/transcoder.h
@@ -30,6 +30,7 @@ class Film;
class Job;
class Encoder;
class FilmState;
+class Matcher;
/** @class Transcoder
* @brief A class which takes a FilmState and some Options, then uses those to transcode a Film.
@@ -56,4 +57,6 @@ protected:
boost::shared_ptr<Encoder> _encoder;
/** The decoder that we will use */
boost::shared_ptr<Decoder> _decoder;
+ boost::shared_ptr<Matcher> _matcher;
+ boost::shared_ptr<DelayLine> _delay_line;
};
diff --git a/src/lib/wscript b/src/lib/wscript
index 969a69606..4fc839097 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -8,6 +8,7 @@ def build(bld):
obj.source = """
ab_transcode_job.cc
ab_transcoder.cc
+ audio_source.cc
check_hashes_job.cc
config.cc
copy_from_dvd_job.cc
@@ -38,6 +39,7 @@ def build(bld):
log.cc
lut.cc
make_dcp_job.cc
+ matcher.cc
scp_dcp_job.cc
scaler.cc
screen.cc
@@ -52,6 +54,7 @@ def build(bld):
ui_signaller.cc
util.cc
version.cc
+ video_source.cc
"""
if not bld.env.DISABLE_PLAYER: