From 59de84a29b81ac32477a4b804ca8bb9ec2760e67 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 6 Mar 2013 00:46:10 +0000 Subject: First cut. --- src/lib/video_decoder.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/lib/video_decoder.h') diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index 5e9c60d08..7d43c9e82 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -67,7 +67,6 @@ protected: void emit_video (boost::shared_ptr, double); void emit_subtitle (boost::shared_ptr); - void repeat_last_video (double t); /** Subtitle stream to use when decoding */ boost::shared_ptr _subtitle_stream; @@ -81,9 +80,6 @@ private: double _last_source_time; boost::shared_ptr _timed_subtitle; - - boost::shared_ptr _last_image; - boost::shared_ptr _last_subtitle; }; #endif -- cgit v1.2.3 From a0fedb33cab65a1be1c49319b7f14319897991f3 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 6 Mar 2013 01:04:23 +0000 Subject: Small simplification. --- src/lib/video_decoder.cc | 15 ++------------- src/lib/video_decoder.h | 2 -- 2 files changed, 2 insertions(+), 15 deletions(-) (limited to 'src/lib/video_decoder.h') diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index 7fff93c45..8461b1635 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -52,21 +52,10 @@ VideoDecoder::emit_video (shared_ptr image, double t) sub = _timed_subtitle->subtitle (); } - signal_video (image, false, sub, t); - _last_source_time = t; -} - -/** Emit our signal to say that some video data is ready. - * @param image Video frame. - * @param same true if `image' is the same as the last one we emitted. - * @param sub Subtitle for this frame, or 0. - */ -void -VideoDecoder::signal_video (shared_ptr image, bool same, shared_ptr sub, double t) -{ - TIMING (N_("Decoder emits %1"), _video_frame); Video (image, same, sub, t); ++_video_frame; + + _last_source_time = t; } /** Set up the current subtitle. This will be put onto frames that diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index 7d43c9e82..1a02272a5 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -74,8 +74,6 @@ protected: std::vector > _subtitle_streams; private: - void signal_video (boost::shared_ptr, bool, boost::shared_ptr, double); - int _video_frame; double _last_source_time; -- cgit v1.2.3 From b0802a7644c12bc039c070367440439f7afe133a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 6 Mar 2013 22:55:11 +0000 Subject: Hopefully fix up still-image generation. --- src/lib/ffmpeg_decoder.cc | 2 +- src/lib/imagemagick_decoder.cc | 15 +++++---- src/lib/imagemagick_decoder.h | 6 +--- src/lib/matcher.cc | 72 ++++++++++++++++++++---------------------- src/lib/matcher.h | 16 ---------- src/lib/video_decoder.cc | 4 +-- src/lib/video_decoder.h | 2 +- 7 files changed, 47 insertions(+), 70 deletions(-) (limited to 'src/lib/video_decoder.h') diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index e1834d7f6..2d7092789 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -520,7 +520,7 @@ FFmpegDecoder::filter_and_emit_video () for (list >::iterator i = images.begin(); i != images.end(); ++i) { int64_t const bet = av_frame_get_best_effort_timestamp (_frame); if (bet != AV_NOPTS_VALUE) { - emit_video (*i, bet * av_q2d (_format_context->streams[_video_stream]->time_base)); + emit_video (*i, false, bet * av_q2d (_format_context->streams[_video_stream]->time_base)); } else { _film->log()->log ("Dropping frame without PTS"); } diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index 119f05792..5ce22c296 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -31,8 +31,6 @@ using std::cout; using boost::shared_ptr; using libdcp::Size; -/* XXX: reads a directory and then ignores it */ - ImageMagickDecoder::ImageMagickDecoder ( boost::shared_ptr f, DecodeOptions o) : Decoder (f, o) @@ -79,8 +77,7 @@ ImageMagickDecoder::pass () return true; } - /* XXX: timestamp */ - emit_video (_image, 0); + emit_video (_image, true, double (video_frame()) / frames_per_second()); return false; } @@ -105,8 +102,7 @@ ImageMagickDecoder::pass () _image = image->crop (_film->crop(), true); - /* XXX: timestamp */ - emit_video (_image, 0); + emit_video (_image, false, double (video_frame()) / frames_per_second()); ++_iter; return false; @@ -134,7 +130,6 @@ ImageMagickDecoder::seek_to_last () bool ImageMagickDecoder::seek (double t) { - /* XXX: frames_per_second == 0 */ int const f = t * frames_per_second(); _iter = _files.begin (); @@ -155,3 +150,9 @@ ImageMagickDecoder::film_changed (Film::Property p) OutputChanged (); } } + +float +ImageMagickDecoder::frames_per_second () const +{ + return _film->source_frame_rate (); +} diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h index ef550c651..ca8e819d3 100644 --- a/src/lib/imagemagick_decoder.h +++ b/src/lib/imagemagick_decoder.h @@ -28,10 +28,7 @@ class ImageMagickDecoder : public VideoDecoder public: ImageMagickDecoder (boost::shared_ptr, DecodeOptions); - float frames_per_second () const { - /* We don't know */ - return 0; - } + float frames_per_second () const; libdcp::Size native_size () const; @@ -88,5 +85,4 @@ private: std::list::iterator _iter; boost::shared_ptr _image; - }; diff --git a/src/lib/matcher.cc b/src/lib/matcher.cc index 93531dbc5..fbd3e3e76 100644 --- a/src/lib/matcher.cc +++ b/src/lib/matcher.cc @@ -49,37 +49,35 @@ Matcher::process_video (boost::shared_ptr image, bool same, boost::shared if (!_first_input) { _first_input = t; } + + /* Video before audio is fine, since we can make up an arbitrary difference + with audio samples (contrasting with video which is quantised to frames) + */ + + /* Difference between where this video is and where it should be */ + double const delta = t - _first_input.get() - _video_frames / _frames_per_second; + double const one_frame = 1 / _frames_per_second; + + if (delta > one_frame) { + /* Insert frames to make up the difference */ + int const extra = rint (delta / one_frame); + for (int i = 0; i < extra; ++i) { + repeat_last_video (); + _log->log (String::compose ("Extra video frame inserted at %1s", _video_frames / _frames_per_second)); + } + } + + if (delta > -one_frame) { + Video (image, same, sub); + ++_video_frames; + } else { + /* We are omitting a frame to keep things right */ + _log->log (String::compose ("Frame removed at %1s", t)); + } - if (_audio_frames == 0 && _pending_audio.empty ()) { - /* No audio yet; we must postpone this frame until we have some */ - _pending_video.push_back (VideoRecord (image, same, sub, t)); - } else if (!_pending_audio.empty() && _pending_video.empty ()) { + if (!_pending_audio.empty() && _video_frames == 1) { /* First video since we got audio */ - _pending_video.push_back (VideoRecord (image, same, sub, t)); fix_start (); - } else { - /* Normal running */ - - /* Difference between where this video is and where it should be */ - double const delta = t - _first_input.get() - _video_frames / _frames_per_second; - double const one_frame = 1 / _frames_per_second; - - if (delta > one_frame) { - /* Insert frames to make up the difference */ - int const extra = rint (delta / one_frame); - for (int i = 0; i < extra; ++i) { - repeat_last_video (); - _log->log (String::compose ("Extra video frame inserted at %1s", _video_frames / _frames_per_second)); - } - } - - if (delta > -one_frame) { - Video (image, same, sub); - ++_video_frames; - } else { - /* We are omitting a frame to keep things right */ - _log->log (String::compose ("Frame removed at %1s", t)); - } } _last_image = image; @@ -95,10 +93,10 @@ Matcher::process_audio (boost::shared_ptr b, double t) _first_input = t; } - if (_video_frames == 0 && _pending_video.empty ()) { + if (_video_frames == 0) { /* No video yet; we must postpone these data until we have some */ _pending_audio.push_back (AudioRecord (b, t)); - } else if (!_pending_video.empty() && _pending_audio.empty ()) { + } else if (_video_frames > 0 && _pending_audio.empty ()) { /* First audio since we got video */ _pending_audio.push_back (AudioRecord (b, t)); fix_start (); @@ -126,22 +124,20 @@ Matcher::process_end () void Matcher::fix_start () { - assert (!_pending_video.empty ()); assert (!_pending_audio.empty ()); + assert (_first_input); - _log->log (String::compose ("Fixing start; video at %1, audio at %2", _pending_video.front().time, _pending_audio.front().time)); - - match (_pending_video.front().time - _pending_audio.front().time); + _log->log (String::compose ("Fixing start; start at %1, audio at %2", _first_input.get(), _pending_audio.front().time)); - for (list::iterator i = _pending_video.begin(); i != _pending_video.end(); ++i) { - process_video (i->image, i->same, i->subtitle, i->time); - } + /* This will not add any video frames, since the input parameter will always be -ve. + Indeed, it cannot add any, since we've already started adding "real" video. + */ + match (_first_input.get() - _pending_audio.front().time); for (list::iterator i = _pending_audio.begin(); i != _pending_audio.end(); ++i) { process_audio (i->audio, i->time); } - _pending_video.clear (); _pending_audio.clear (); } diff --git a/src/lib/matcher.h b/src/lib/matcher.h index 2f580b589..84ae2f73e 100644 --- a/src/lib/matcher.h +++ b/src/lib/matcher.h @@ -42,22 +42,6 @@ private: boost::optional _size; boost::optional _channels; - struct VideoRecord { - VideoRecord (boost::shared_ptr i, bool s, boost::shared_ptr sub, double t) - : image (i) - , same (s) - , subtitle (sub) - , time (t) - {} - - boost::shared_ptr image; - bool same; - boost::shared_ptr subtitle; - double time; - }; - - std::list _pending_video; - struct AudioRecord { AudioRecord (boost::shared_ptr a, double t) : audio (a) diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc index 9c0d2bbe3..16a076698 100644 --- a/src/lib/video_decoder.cc +++ b/src/lib/video_decoder.cc @@ -45,14 +45,14 @@ VideoDecoder::VideoDecoder (shared_ptr f, DecodeOptions o) * @param t Time of the frame within the source, in seconds. */ void -VideoDecoder::emit_video (shared_ptr image, double t) +VideoDecoder::emit_video (shared_ptr image, bool same, double t) { shared_ptr sub; if (_timed_subtitle && _timed_subtitle->displayed_at (t)) { sub = _timed_subtitle->subtitle (); } - Video (image, false, sub, t); + Video (image, same, sub, t); ++_video_frame; _last_source_time = t; diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index 1a02272a5..6e4fd48c0 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -65,7 +65,7 @@ protected: virtual PixelFormat pixel_format () const = 0; - void emit_video (boost::shared_ptr, double); + void emit_video (boost::shared_ptr, bool, double); void emit_subtitle (boost::shared_ptr); /** Subtitle stream to use when decoding */ -- cgit v1.2.3 From 3f2365fcf3a1ffc50901eb2e4af246aa4c83e272 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 15 Apr 2013 16:24:03 +0100 Subject: Repair very bad merge. Mysterious. --- src/lib/ab_transcoder.cc | 4 ++-- src/lib/audio_decoder.h | 2 +- src/lib/audio_sink.h | 7 +++++++ src/lib/audio_source.cc | 6 ++++++ src/lib/audio_source.h | 12 ++++++++++++ src/lib/combiner.cc | 8 ++++---- src/lib/combiner.h | 6 +++--- src/lib/delay_line.cc | 4 ++-- src/lib/delay_line.h | 4 ++-- src/lib/matcher.cc | 2 +- src/lib/matcher.h | 6 +++--- src/lib/processor.h | 17 +++++++++++++++++ src/lib/sndfile_decoder.cc | 5 +++-- src/lib/transcoder.cc | 9 --------- src/lib/video_decoder.h | 2 +- src/lib/video_sink.h | 12 ++++++++++++ src/lib/video_source.cc | 6 ++++++ src/lib/video_source.h | 23 +++++++++++++++++++++-- 18 files changed, 103 insertions(+), 32 deletions(-) (limited to 'src/lib/video_decoder.h') diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc index 7db13afcc..6eef397c2 100644 --- a/src/lib/ab_transcoder.cc +++ b/src/lib/ab_transcoder.cc @@ -70,8 +70,8 @@ ABTranscoder::ABTranscoder ( _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); diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index 9bef8e0e7..cfe94b528 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -31,7 +31,7 @@ /** @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, DecodeOptions); diff --git a/src/lib/audio_sink.h b/src/lib/audio_sink.h index 11d578a60..f34b24f88 100644 --- a/src/lib/audio_sink.h +++ b/src/lib/audio_sink.h @@ -27,4 +27,11 @@ public: virtual void process_audio (boost::shared_ptr) = 0; }; +class TimedAudioSink +{ +public: + /** Call with some audio data */ + virtual void process_audio (boost::shared_ptr, double t) = 0; +}; + #endif diff --git a/src/lib/audio_source.cc b/src/lib/audio_source.cc index 53b0dda15..bca3562cf 100644 --- a/src/lib/audio_source.cc +++ b/src/lib/audio_source.cc @@ -28,3 +28,9 @@ AudioSource::connect_audio (shared_ptr s) { Audio.connect (bind (&AudioSink::process_audio, s, _1)); } + +void +TimedAudioSource::connect_audio (shared_ptr s) +{ + Audio.connect (bind (&TimedAudioSink::process_audio, s, _1, _2)); +} diff --git a/src/lib/audio_source.h b/src/lib/audio_source.h index 5a1510d3c..3dc998cca 100644 --- a/src/lib/audio_source.h +++ b/src/lib/audio_source.h @@ -28,6 +28,7 @@ class AudioBuffers; class AudioSink; +class TimedAudioSink; /** A class that emits audio data */ class AudioSource @@ -39,4 +40,15 @@ public: void connect_audio (boost::shared_ptr); }; + +/** A class that emits audio data with timestamps */ +class TimedAudioSource +{ +public: + /** Emitted when some audio data is ready */ + boost::signals2::signal, double)> Audio; + + void connect_audio (boost::shared_ptr); +}; + #endif diff --git a/src/lib/combiner.cc b/src/lib/combiner.cc index 12ce4a96e..006dd2697 100644 --- a/src/lib/combiner.cc +++ b/src/lib/combiner.cc @@ -23,7 +23,7 @@ using boost::shared_ptr; Combiner::Combiner (shared_ptr log) - : VideoProcessor (log) + : TimedVideoProcessor (log) { } @@ -33,7 +33,7 @@ Combiner::Combiner (shared_ptr log) * @param image Frame image. */ void -Combiner::process_video (shared_ptr image, bool, shared_ptr) +Combiner::process_video (shared_ptr image, bool, shared_ptr, double t) { _image = image; } @@ -43,7 +43,7 @@ Combiner::process_video (shared_ptr image, bool, shared_ptr) * @param sub Subtitle (which will be put onto the whole frame) */ void -Combiner::process_video_b (shared_ptr image, bool, shared_ptr sub) +Combiner::process_video_b (shared_ptr image, bool, shared_ptr sub, double t) { /* Copy the right half of this image into our _image */ /* XXX: this should probably be in the Image class */ @@ -62,6 +62,6 @@ Combiner::process_video_b (shared_ptr image, bool, shared_ptr s } } - Video (_image, false, sub); + Video (_image, false, sub, t); _image.reset (); } diff --git a/src/lib/combiner.h b/src/lib/combiner.h index 68026eaff..a8f1fa804 100644 --- a/src/lib/combiner.h +++ b/src/lib/combiner.h @@ -28,13 +28,13 @@ * 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); - void process_video (boost::shared_ptr i, bool, boost::shared_ptr s); - void process_video_b (boost::shared_ptr i, bool, boost::shared_ptr s); + void process_video (boost::shared_ptr i, bool, boost::shared_ptr s, double); + void process_video_b (boost::shared_ptr i, bool, boost::shared_ptr 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 c8e593a18..9e6baeba8 100644 --- a/src/lib/delay_line.cc +++ b/src/lib/delay_line.cc @@ -30,14 +30,14 @@ using boost::shared_ptr; /* @param seconds Delay in seconds, +ve to move audio later. */ DelayLine::DelayLine (shared_ptr log, double seconds) - : Processor (log) + : TimedAudioVideoProcessor (log) , _seconds (seconds) { } void -DelayLine::process_audio (shared_ptr data) +DelayLine::process_audio (shared_ptr data, double t) { if (_seconds > 0) { t += _seconds; diff --git a/src/lib/delay_line.h b/src/lib/delay_line.h index 7a8b11c69..90f1dcfa7 100644 --- a/src/lib/delay_line.h +++ b/src/lib/delay_line.h @@ -20,8 +20,8 @@ #include #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, double); diff --git a/src/lib/matcher.cc b/src/lib/matcher.cc index 69d12e2c4..34ddc86d6 100644 --- a/src/lib/matcher.cc +++ b/src/lib/matcher.cc @@ -29,7 +29,7 @@ using std::list; using boost::shared_ptr; Matcher::Matcher (shared_ptr 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) diff --git a/src/lib/matcher.h b/src/lib/matcher.h index 4ec0a3e96..f54aa4b6a 100644 --- a/src/lib/matcher.h +++ b/src/lib/matcher.h @@ -21,12 +21,12 @@ #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, int sample_rate, float frames_per_second); - void process_video (boost::shared_ptr i, bool, boost::shared_ptr s); - void process_audio (boost::shared_ptr); + void process_video (boost::shared_ptr i, bool, boost::shared_ptr s, double); + void process_audio (boost::shared_ptr, double); void process_end (); private: diff --git a/src/lib/processor.h b/src/lib/processor.h index 1ba396f2f..603239f8f 100644 --- a/src/lib/processor.h +++ b/src/lib/processor.h @@ -67,6 +67,15 @@ public: {} }; +class TimedAudioVideoProcessor : public Processor, public TimedVideoSource, public TimedVideoSink, public TimedAudioSource, public TimedAudioSink +{ +public: + TimedAudioVideoProcessor (boost::shared_ptr log) + : Processor (log) + {} +}; + + /** @class AudioProcessor * @brief A processor which handles just audio data. */ @@ -95,4 +104,12 @@ public: {} }; +class TimedVideoProcessor : public Processor, public TimedVideoSource, public TimedVideoSink +{ +public: + TimedVideoProcessor (boost::shared_ptr log) + : Processor (log) + {} +}; + #endif diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc index 0e3e5e234..af59c049c 100644 --- a/src/lib/sndfile_decoder.cc +++ b/src/lib/sndfile_decoder.cc @@ -113,8 +113,8 @@ SndfileDecoder::pass () to what FFmpeg (and in particular the resampler) can cope with. */ sf_count_t const block = _audio_stream->sample_rate() / 2; - shared_ptr 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) { @@ -126,7 +126,8 @@ SndfileDecoder::pass () } audio->set_frames (this_time); - Audio (audio); + Audio (audio, double(done) / _audio_stream->sample_rate()); + done += this_time; frames -= this_time; } diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc index 8046080de..23fb5b788 100644 --- a/src/lib/transcoder.cc +++ b/src/lib/transcoder.cc @@ -63,18 +63,9 @@ Transcoder::Transcoder (shared_ptr f, DecodeOptions o, Job* j, shared_ptr< _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); diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index f8612dff2..6e4fd48c0 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -24,7 +24,7 @@ #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, DecodeOptions); diff --git a/src/lib/video_sink.h b/src/lib/video_sink.h index 7c128cf73..32c7f3b38 100644 --- a/src/lib/video_sink.h +++ b/src/lib/video_sink.h @@ -37,4 +37,16 @@ public: virtual void process_video (boost::shared_ptr i, bool same, boost::shared_ptr 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 i, bool same, boost::shared_ptr s, double t) = 0; +}; + #endif diff --git a/src/lib/video_source.cc b/src/lib/video_source.cc index 56742e2b4..af6f941fd 100644 --- a/src/lib/video_source.cc +++ b/src/lib/video_source.cc @@ -28,3 +28,9 @@ VideoSource::connect_video (shared_ptr s) { Video.connect (bind (&VideoSink::process_video, s, _1, _2, _3)); } + +void +TimedVideoSource::connect_video (shared_ptr s) +{ + Video.connect (bind (&TimedVideoSink::process_video, s, _1, _2, _3, _4)); +} diff --git a/src/lib/video_source.h b/src/lib/video_source.h index 893629160..705b0023a 100644 --- a/src/lib/video_source.h +++ b/src/lib/video_source.h @@ -29,11 +29,12 @@ #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 { @@ -49,4 +50,22 @@ public: void connect_video (boost::shared_ptr); }; +/** @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, bool, boost::shared_ptr, double)> Video; + + void connect_video (boost::shared_ptr); +}; + #endif -- cgit v1.2.3