summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2012-11-12 21:06:47 +0000
committerCarl Hetherington <cth@carlh.net>2012-11-12 21:06:47 +0000
commitac0a9000d5d6a62c4ef3e4902611b180501e09e1 (patch)
tree6db45301529157db21ab0d54c36ce6ca4978a5e4 /src/lib
parent70447e72a5595fa03eb0a82b5e93247fcc5cad2b (diff)
Missing files.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/audio_sink.h11
-rw-r--r--src/lib/audio_source.cc11
-rw-r--r--src/lib/audio_source.h18
-rw-r--r--src/lib/matcher.cc81
-rw-r--r--src/lib/matcher.h20
-rw-r--r--src/lib/processor.h41
-rw-r--r--src/lib/video_sink.h20
-rw-r--r--src/lib/video_source.cc11
-rw-r--r--src/lib/video_source.h25
9 files changed, 238 insertions, 0 deletions
diff --git a/src/lib/audio_sink.h b/src/lib/audio_sink.h
new file mode 100644
index 000000000..93109a66d
--- /dev/null
+++ b/src/lib/audio_sink.h
@@ -0,0 +1,11 @@
+#ifndef DVDOMATIC_AUDIO_SINK_H
+#define DVDOMATIC_AUDIO_SINK_H
+
+class AudioSink
+{
+public:
+ /** Call with some audio data */
+ virtual void process_audio (boost::shared_ptr<AudioBuffers>) = 0;
+};
+
+#endif
diff --git a/src/lib/audio_source.cc b/src/lib/audio_source.cc
new file mode 100644
index 000000000..ccb82334c
--- /dev/null
+++ b/src/lib/audio_source.cc
@@ -0,0 +1,11 @@
+#include "audio_source.h"
+#include "audio_sink.h"
+
+using boost::shared_ptr;
+using boost::bind;
+
+void
+AudioSource::connect_audio (shared_ptr<AudioSink> s)
+{
+ Audio.connect (bind (&AudioSink::process_audio, s, _1));
+}
diff --git a/src/lib/audio_source.h b/src/lib/audio_source.h
new file mode 100644
index 000000000..b300e0763
--- /dev/null
+++ b/src/lib/audio_source.h
@@ -0,0 +1,18 @@
+#ifndef DVDOMATIC_AUDIO_SOURCE_H
+#define DVDOMATIC_AUDIO_SOURCE_H
+
+#include <boost/signals2.hpp>
+
+class AudioBuffers;
+class AudioSink;
+
+class AudioSource
+{
+public:
+ /** Emitted when some audio data is ready */
+ boost::signals2::signal<void (boost::shared_ptr<AudioBuffers>)> Audio;
+
+ void connect_audio (boost::shared_ptr<AudioSink>);
+};
+
+#endif
diff --git a/src/lib/matcher.cc b/src/lib/matcher.cc
new file mode 100644
index 000000000..f6eff168b
--- /dev/null
+++ b/src/lib/matcher.cc
@@ -0,0 +1,81 @@
+#include "matcher.h"
+#include "image.h"
+#include "log.h"
+
+using boost::shared_ptr;
+
+Matcher::Matcher (Log* log, int sample_rate, float frames_per_second)
+ : AudioVideoProcessor (log)
+ , _sample_rate (sample_rate)
+ , _frames_per_second (frames_per_second)
+ , _video_frames (0)
+ , _audio_frames (0)
+{
+
+}
+
+void
+Matcher::process_video (boost::shared_ptr<Image> i, boost::shared_ptr<Subtitle> s)
+{
+ Video (i, s);
+ _video_frames++;
+
+ _pixel_format = i->pixel_format ();
+ _size = i->size ();
+}
+
+void
+Matcher::process_audio (boost::shared_ptr<AudioBuffers> b)
+{
+ Audio (b);
+ _audio_frames += b->frames ();
+
+ _channels = b->channels ();
+}
+
+void
+Matcher::process_end ()
+{
+ if (_audio_frames == 0 || !_pixel_format || !_size || !_channels) {
+ /* We won't do anything */
+ return;
+ }
+
+ int64_t audio_short_by_frames = video_frames_to_audio_frames (_video_frames, _sample_rate, _frames_per_second) - _audio_frames;
+
+ _log->log (
+ String::compose (
+ "Matching processor has seen %1 video frames (which equals %2 audio frames) and %3 audio frames",
+ _video_frames,
+ video_frames_to_audio_frames (_video_frames, _sample_rate, _frames_per_second),
+ _audio_frames
+ )
+ );
+
+ if (audio_short_by_frames < 0) {
+
+ _log->log (String::compose ("%1 too many audio frames", -audio_short_by_frames));
+
+ /* We have seen 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 / _sample_rate);
+
+ _log->log (String::compose ("Emitting %1 frames of black video", black_video_frames));
+
+ shared_ptr<Image> black (new CompactImage (_pixel_format.get(), _size.get()));
+ black->make_black ();
+ for (int i = 0; i < black_video_frames; ++i) {
+ Video (black, shared_ptr<Subtitle>());
+ }
+
+ /* Now recompute our check value */
+ audio_short_by_frames = video_frames_to_audio_frames (_video_frames, _sample_rate, _frames_per_second) - _audio_frames;
+ }
+
+ if (audio_short_by_frames > 0) {
+ _log->log (String::compose ("Emitted %1 too few audio frames", audio_short_by_frames));
+ shared_ptr<AudioBuffers> b (new AudioBuffers (_channels.get(), audio_short_by_frames));
+ b->make_silent ();
+ Audio (b);
+ _audio_frames += b->frames ();
+ }
+}
diff --git a/src/lib/matcher.h b/src/lib/matcher.h
new file mode 100644
index 000000000..5f1a75ef9
--- /dev/null
+++ b/src/lib/matcher.h
@@ -0,0 +1,20 @@
+#include <boost/optional.hpp>
+#include "processor.h"
+
+class Matcher : public AudioVideoProcessor
+{
+public:
+ Matcher (Log* log, int sample_rate, float frames_per_second);
+ void process_video (boost::shared_ptr<Image> i, boost::shared_ptr<Subtitle> s);
+ void process_audio (boost::shared_ptr<AudioBuffers>);
+ void process_end ();
+
+private:
+ int _sample_rate;
+ float _frames_per_second;
+ int _video_frames;
+ int64_t _audio_frames;
+ boost::optional<AVPixelFormat> _pixel_format;
+ boost::optional<Size> _size;
+ boost::optional<int> _channels;
+};
diff --git a/src/lib/processor.h b/src/lib/processor.h
new file mode 100644
index 000000000..e99ff2d4d
--- /dev/null
+++ b/src/lib/processor.h
@@ -0,0 +1,41 @@
+#ifndef DVDOMATIC_PROCESSOR_H
+#define DVDOMATIC_PROCESSOR_H
+
+#include "video_source.h"
+#include "video_sink.h"
+#include "audio_source.h"
+#include "audio_sink.h"
+
+class Log;
+
+class Processor
+{
+public:
+ Processor (Log* log)
+ : _log (log)
+ {}
+
+ virtual void process_begin () {}
+ virtual void process_end () {}
+
+protected:
+ Log* _log;
+};
+
+class AudioVideoProcessor : public Processor, public VideoSource, public VideoSink, public AudioSource, public AudioSink
+{
+public:
+ AudioVideoProcessor (Log* log)
+ : Processor (log)
+ {}
+};
+
+class AudioProcessor : public Processor, public AudioSource, public AudioSink
+{
+public:
+ AudioProcessor (Log* log)
+ : Processor (log)
+ {}
+};
+
+#endif
diff --git a/src/lib/video_sink.h b/src/lib/video_sink.h
new file mode 100644
index 000000000..a5c16ec7f
--- /dev/null
+++ b/src/lib/video_sink.h
@@ -0,0 +1,20 @@
+#ifndef DVDOMATIC_VIDEO_SINK_H
+#define DVDOMATIC_VIDEO_SINK_H
+
+#include <boost/shared_ptr.hpp>
+#include "util.h"
+
+class Subtitle;
+class Image;
+
+class VideoSink
+{
+public:
+ /** Call with a frame of video.
+ * @param i Video frame image.
+ * @param s A subtitle that should be on this frame, or 0.
+ */
+ virtual void process_video (boost::shared_ptr<Image> i, boost::shared_ptr<Subtitle> s) = 0;
+};
+
+#endif
diff --git a/src/lib/video_source.cc b/src/lib/video_source.cc
new file mode 100644
index 000000000..87b33026e
--- /dev/null
+++ b/src/lib/video_source.cc
@@ -0,0 +1,11 @@
+#include "video_source.h"
+#include "video_sink.h"
+
+using boost::shared_ptr;
+using boost::bind;
+
+void
+VideoSource::connect_video (shared_ptr<VideoSink> s)
+{
+ Video.connect (bind (&VideoSink::process_video, s, _1, _2));
+}
diff --git a/src/lib/video_source.h b/src/lib/video_source.h
new file mode 100644
index 000000000..a93bd39d4
--- /dev/null
+++ b/src/lib/video_source.h
@@ -0,0 +1,25 @@
+#ifndef DVDOMATIC_VIDEO_SOURCE_H
+#define DVDOMATIC_VIDEO_SOURCE_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2.hpp>
+#include "util.h"
+
+class VideoSink;
+class Subtitle;
+class Image;
+
+class VideoSource
+{
+public:
+
+ /** Emitted when a video frame is ready.
+ * First parameter is the frame within the source.
+ * Second parameter is either 0 or a subtitle that should be on this frame.
+ */
+ boost::signals2::signal<void (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>)> Video;
+
+ void connect_video (boost::shared_ptr<VideoSink>);
+};
+
+#endif