*/
#include <iostream>
-#include <sigc++/signal.h>
+#include <boost/signals2.hpp>
#include "transcoder.h"
#include "encoder.h"
#include "decoder_factory.h"
+#include "film.h"
+#include "matcher.h"
+#include "delay_line.h"
+#include "options.h"
+#include "gain.h"
+#include "video_decoder.h"
+#include "audio_decoder.h"
-using namespace std;
-using namespace boost;
+using std::string;
+using boost::shared_ptr;
+using boost::dynamic_pointer_cast;
/** Construct a transcoder using a Decoder that we create and a supplied Encoder.
* @param f Film that we are transcoding.
Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j, shared_ptr<Encoder> e)
: _job (j)
, _encoder (e)
- , _decoder (decoder_factory (f, o, j))
+ , _decoders (decoder_factory (f, o, j))
{
assert (_encoder);
+
+ if (f->audio_stream()) {
+ 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));
+ _gain.reset (new Gain (f->log(), f->audio_gain()));
+ }
+
+ /* Set up the decoder to use the film's set streams */
+ _decoders.first->set_subtitle_stream (f->subtitle_stream ());
+ _decoders.second->set_audio_stream (f->audio_stream ());
+
+ if (_matcher) {
+ _decoders.first->connect_video (_matcher);
+ _matcher->connect_video (_encoder);
+ } else {
+ _decoders.first->connect_video (_encoder);
+ }
- _decoder->Video.connect (sigc::mem_fun (*e, &Encoder::process_video));
- _decoder->Audio.connect (sigc::mem_fun (*e, &Encoder::process_audio));
+ if (_matcher && _delay_line) {
+ _decoders.second->connect_audio (_delay_line);
+ _delay_line->connect_audio (_matcher);
+ _matcher->connect_audio (_gain);
+ _gain->connect_audio (_encoder);
+ }
}
/** Run the decoder, passing its output to the encoder, until the decoder
void
Transcoder::go ()
{
- _encoder->process_begin (_decoder->audio_channel_layout());
+ _encoder->process_begin ();
try {
- _decoder->go ();
+ while (1) {
+ bool const v = _decoders.first->pass ();
+
+ bool a = false;
+ if (dynamic_pointer_cast<Decoder> (_decoders.second) != dynamic_pointer_cast<Decoder> (_decoders.first)) {
+ a = _decoders.second->pass ();
+ }
+
+ if (v && a) {
+ break;
+ }
+ }
+
} catch (...) {
/* process_end() is important as the decoder may have worker
threads that need to be cleaned up.