_db.video->set_subtitle_stream (_film_a->subtitle_stream ());
_da.audio->set_audio_stream (_film_a->audio_stream ());
- _da.video->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3));
- _db.video->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3));
+ _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);
/** @class AudioDecoder.
* @brief Parent class for audio decoders.
*/
-class AudioDecoder : public AudioSource, public virtual Decoder
+class AudioDecoder : public TimedAudioSource, public virtual Decoder
{
public:
AudioDecoder (boost::shared_ptr<Film>, DecodeOptions);
virtual void process_audio (boost::shared_ptr<AudioBuffers>) = 0;
};
+class TimedAudioSink
+{
+public:
+ /** Call with some audio data */
+ virtual void process_audio (boost::shared_ptr<AudioBuffers>, double t) = 0;
+};
+
#endif
{
Audio.connect (bind (&AudioSink::process_audio, s, _1));
}
+
+void
+TimedAudioSource::connect_audio (shared_ptr<TimedAudioSink> s)
+{
+ Audio.connect (bind (&TimedAudioSink::process_audio, s, _1, _2));
+}
class AudioBuffers;
class AudioSink;
+class TimedAudioSink;
/** A class that emits audio data */
class AudioSource
void connect_audio (boost::shared_ptr<AudioSink>);
};
+
+/** A class that emits audio data with timestamps */
+class TimedAudioSource
+{
+public:
+ /** Emitted when some audio data is ready */
+ boost::signals2::signal<void (boost::shared_ptr<AudioBuffers>, double)> Audio;
+
+ void connect_audio (boost::shared_ptr<TimedAudioSink>);
+};
+
#endif
using boost::shared_ptr;
Combiner::Combiner (shared_ptr<Log> log)
- : VideoProcessor (log)
+ : TimedVideoProcessor (log)
{
}
* @param image Frame image.
*/
void
-Combiner::process_video (shared_ptr<Image> image, bool, shared_ptr<Subtitle>)
+Combiner::process_video (shared_ptr<Image> image, bool, shared_ptr<Subtitle>, double t)
{
_image = image;
}
* @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)
+Combiner::process_video_b (shared_ptr<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 */
}
}
- Video (_image, false, sub);
+ Video (_image, false, sub, t);
_image.reset ();
}
* one image used for the left half of the screen and the other for
* the right.
*/
-class Combiner : public VideoProcessor
+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);
- void process_video_b (boost::shared_ptr<Image> i, bool, boost::shared_ptr<Subtitle> s);
+ 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);
private:
/** The image that we are currently working on */
/* @param seconds Delay in seconds, +ve to move audio later.
*/
DelayLine::DelayLine (shared_ptr<Log> log, double seconds)
- : Processor (log)
+ : TimedAudioVideoProcessor (log)
, _seconds (seconds)
{
}
void
-DelayLine::process_audio (shared_ptr<AudioBuffers> data)
+DelayLine::process_audio (shared_ptr<AudioBuffers> data, double t)
{
if (_seconds > 0) {
t += _seconds;
#include <boost/shared_ptr.hpp>
#include "processor.h"
-/** A delay line for audio */
-class DelayLine : public Processor, public TimedAudioSink, public TimedAudioSource, public TimedVideoSink, public TimedVideoSource
+/** A delay line */
+class DelayLine : public TimedAudioVideoProcessor
{
public:
DelayLine (boost::shared_ptr<Log> log, double);
using boost::shared_ptr;
Matcher::Matcher (shared_ptr<Log> log, int sample_rate, float frames_per_second)
- : AudioVideoProcessor (log)
+ : Processor (log)
, _sample_rate (sample_rate)
, _frames_per_second (frames_per_second)
, _video_frames (0)
#include "processor.h"
#include "ffmpeg_compatibility.h"
-class Matcher : public AudioVideoProcessor
+class Matcher : public Processor, public TimedAudioSink, public TimedVideoSink, public AudioSource, public VideoSource
{
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);
- void process_audio (boost::shared_ptr<AudioBuffers>);
+ 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_end ();
private:
{}
};
+class TimedAudioVideoProcessor : public Processor, public TimedVideoSource, public TimedVideoSink, public TimedAudioSource, public TimedAudioSink
+{
+public:
+ TimedAudioVideoProcessor (boost::shared_ptr<Log> log)
+ : Processor (log)
+ {}
+};
+
+
/** @class AudioProcessor
* @brief A processor which handles just audio data.
*/
{}
};
+class TimedVideoProcessor : public Processor, public TimedVideoSource, public TimedVideoSink
+{
+public:
+ TimedVideoProcessor (boost::shared_ptr<Log> log)
+ : Processor (log)
+ {}
+};
+
#endif
to what FFmpeg (and in particular the resampler) can cope with.
*/
sf_count_t const block = _audio_stream->sample_rate() / 2;
-
shared_ptr<AudioBuffers> audio (new AudioBuffers (_audio_stream->channels(), block));
+ sf_count_t done = 0;
while (frames > 0) {
sf_count_t const this_time = min (block, frames);
for (size_t i = 0; i < sndfiles.size(); ++i) {
}
audio->set_frames (this_time);
- Audio (audio);
+ Audio (audio, double(done) / _audio_stream->sample_rate());
+ done += this_time;
frames -= this_time;
}
_decoders.video->set_subtitle_stream (f->subtitle_stream ());
_decoders.audio->set_audio_stream (f->audio_stream ());
-<<<<<<< HEAD
_decoders.video->connect_video (_delay_line);
_delay_line->connect_video (_matcher);
_matcher->connect_video (_encoder);
-=======
- if (_matcher) {
- _decoders.video->connect_video (_matcher);
- _matcher->connect_video (_encoder);
- } else {
- _decoders.video->connect_video (_encoder);
- }
->>>>>>> master
_decoders.audio->connect_audio (_delay_line);
_delay_line->connect_audio (_matcher);
#include "stream.h"
#include "decoder.h"
-class VideoDecoder : public VideoSource, public virtual Decoder
+class VideoDecoder : public TimedVideoSource, public virtual Decoder
{
public:
VideoDecoder (boost::shared_ptr<Film>, DecodeOptions);
virtual void process_video (boost::shared_ptr<Image> i, bool same, boost::shared_ptr<Subtitle> s) = 0;
};
+class TimedVideoSink
+{
+public:
+ /** Call with a frame of video.
+ * @param i Video frame image.
+ * @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.
+ * @param t Source timestamp.
+ */
+ virtual void process_video (boost::shared_ptr<Image> i, bool same, boost::shared_ptr<Subtitle> s, double t) = 0;
+};
+
#endif
{
Video.connect (bind (&VideoSink::process_video, s, _1, _2, _3));
}
+
+void
+TimedVideoSource::connect_video (shared_ptr<TimedVideoSink> s)
+{
+ Video.connect (bind (&TimedVideoSink::process_video, s, _1, _2, _3, _4));
+}
#include "util.h"
class VideoSink;
+class TimedVideoSink;
class Subtitle;
class Image;
-/** @class VideoSink
- * @param A class that emits video data.
+/** @class VideoSource
+ * @param A class that emits video data without timestamps.
*/
class VideoSource
{
void connect_video (boost::shared_ptr<VideoSink>);
};
+/** @class TimedVideoSource
+ * @param A class that emits video data with timestamps.
+ */
+class TimedVideoSource
+{
+public:
+
+ /** Emitted when a video frame is ready.
+ * First parameter is the video image.
+ * 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.
+ * Fourth parameter is the source timestamp of this frame.
+ */
+ boost::signals2::signal<void (boost::shared_ptr<Image>, bool, boost::shared_ptr<Subtitle>, double)> Video;
+
+ void connect_video (boost::shared_ptr<TimedVideoSink>);
+};
+
#endif