summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2017-03-07 19:27:33 +0000
committerCarl Hetherington <cth@carlh.net>2017-04-19 23:04:32 +0100
commit4f9cb03792e85cbb5b4d554ab8ec0a3275fa7524 (patch)
tree2821608ecf5f7cc50649333903caff07d78fdbba /src/lib
parent67a68bd971ebe1b35daa3f75873b4ccb53c00ba0 (diff)
Initial butler work.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/audio_ring_buffers.cc104
-rw-r--r--src/lib/audio_ring_buffers.h54
-rw-r--r--src/lib/butler.cc111
-rw-r--r--src/lib/butler.h60
-rw-r--r--src/lib/player_video.h5
-rw-r--r--src/lib/video_ring_buffers.cc79
-rw-r--r--src/lib/video_ring_buffers.h45
-rw-r--r--src/lib/wscript2
8 files changed, 460 insertions, 0 deletions
diff --git a/src/lib/audio_ring_buffers.cc b/src/lib/audio_ring_buffers.cc
new file mode 100644
index 000000000..81072474e
--- /dev/null
+++ b/src/lib/audio_ring_buffers.cc
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "audio_ring_buffers.h"
+#include "dcpomatic_assert.h"
+#include "exceptions.h"
+#include <boost/foreach.hpp>
+
+using std::min;
+using std::cout;
+using boost::shared_ptr;
+
+AudioRingBuffers::AudioRingBuffers ()
+ : _used_in_head (0)
+{
+
+}
+
+void
+AudioRingBuffers::put (shared_ptr<const AudioBuffers> data, DCPTime time)
+{
+ boost::mutex::scoped_lock lm (_mutex);
+
+ if (!_buffers.empty ()) {
+ DCPOMATIC_ASSERT (_buffers.front()->channels() == data->channels());
+ }
+
+ _buffers.push_back (data);
+ _latest = time;
+}
+
+void
+AudioRingBuffers::get (float* out, int channels, int frames)
+{
+ boost::mutex::scoped_lock lm (_mutex);
+
+ while (frames > 0) {
+ if (_buffers.empty ()) {
+ for (int i = 0; i < frames; ++i) {
+ for (int j = 0; j < channels; ++j) {
+ *out++ = 0;
+ }
+ }
+ cout << "audio underrun; missing " << frames << "!\n";
+ return;
+ }
+
+ int const to_do = min (frames, _buffers.front()->frames() - _used_in_head);
+ float** p = _buffers.front()->data();
+ int const c = min (_buffers.front()->channels(), channels);
+ for (int i = 0; i < to_do; ++i) {
+ for (int j = 0; j < c; ++j) {
+ *out++ = p[j][i + _used_in_head];
+ }
+ for (int j = c; j < channels; ++j) {
+ *out++ = 0;
+ }
+ }
+ _used_in_head += to_do;
+ frames -= to_do;
+
+ if (_used_in_head == _buffers.front()->frames()) {
+ _buffers.pop_front ();
+ _used_in_head = 0;
+ }
+ }
+}
+
+void
+AudioRingBuffers::clear ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ _buffers.clear ();
+ _used_in_head = 0;
+ _latest = DCPTime ();
+}
+
+Frame
+AudioRingBuffers::size ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ Frame s = 0;
+ BOOST_FOREACH (shared_ptr<const AudioBuffers> i, _buffers) {
+ s += i->frames ();
+ }
+ return s - _used_in_head;
+}
diff --git a/src/lib/audio_ring_buffers.h b/src/lib/audio_ring_buffers.h
new file mode 100644
index 000000000..cec7c712a
--- /dev/null
+++ b/src/lib/audio_ring_buffers.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DCPOMATIC_AUDIO_RING_BUFFERS_H
+#define DCPOMATIC_AUDIO_RING_BUFFERS_H
+
+#include "audio_buffers.h"
+#include "types.h"
+#include "dcpomatic_time.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <list>
+
+class AudioRingBuffers : public boost::noncopyable
+{
+public:
+ AudioRingBuffers ();
+
+ void put (boost::shared_ptr<const AudioBuffers> data, DCPTime time);
+ void get (float* out, int channels, int frames);
+
+ void clear ();
+ Frame size ();
+
+ DCPTime latest () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _latest;
+ }
+
+private:
+ mutable boost::mutex _mutex;
+ std::list<boost::shared_ptr<const AudioBuffers> > _buffers;
+ DCPTime _latest;
+ int _used_in_head;
+};
+
+#endif
diff --git a/src/lib/butler.cc b/src/lib/butler.cc
new file mode 100644
index 000000000..e40ae0b24
--- /dev/null
+++ b/src/lib/butler.cc
@@ -0,0 +1,111 @@
+/*
+ Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "butler.h"
+#include "player.h"
+#include <boost/weak_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+
+using std::cout;
+using std::pair;
+using std::make_pair;
+using boost::weak_ptr;
+using boost::shared_ptr;
+using boost::bind;
+using boost::optional;
+
+/** Video readahead in frames */
+#define VIDEO_READAHEAD 10
+
+Butler::Butler (weak_ptr<const Film> film, shared_ptr<Player> player)
+ : _film (film)
+ , _player (player)
+ , _pending_seek_accurate (false)
+ , _finished (false)
+{
+ _player->Video.connect (bind (&VideoRingBuffers::put, &_video, _1, _2));
+ _thread = new boost::thread (bind (&Butler::thread, this));
+}
+
+Butler::~Butler ()
+{
+ _thread->interrupt ();
+ try {
+ _thread->join ();
+ } catch (boost::thread_interrupted& e) {
+ /* No problem */
+ }
+ delete _thread;
+}
+
+void
+Butler::thread ()
+{
+ while (true) {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ while (_video.size() > VIDEO_READAHEAD && !_pending_seek_position) {
+ _summon.wait (lm);
+ }
+
+ if (_pending_seek_position) {
+ _player->seek (*_pending_seek_position, _pending_seek_accurate);
+ _pending_seek_position = optional<DCPTime> ();
+ }
+
+ while (_video.size() < VIDEO_READAHEAD) {
+ _arrived.notify_all ();
+ if (_player->pass ()) {
+ _finished = true;
+ break;
+ }
+ }
+ }
+}
+
+pair<shared_ptr<PlayerVideo>, DCPTime>
+Butler::get_video ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ while (_video.size() == 0 && !_finished) {
+ _arrived.wait (lm);
+ }
+
+ if (_finished) {
+ return make_pair (shared_ptr<PlayerVideo>(), DCPTime());
+ }
+
+ return _video.get ();
+}
+
+void
+Butler::seek (DCPTime position, bool accurate)
+{
+ _video.clear ();
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ _finished = false;
+ _pending_seek_position = position;
+ _pending_seek_accurate = accurate;
+ }
+
+ _summon.notify_all ();
+}
diff --git a/src/lib/butler.h b/src/lib/butler.h
new file mode 100644
index 000000000..d801d6cf9
--- /dev/null
+++ b/src/lib/butler.h
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "video_ring_buffers.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/signals2.hpp>
+
+class Film;
+class Player;
+class PlayerVideo;
+
+class Butler : public boost::noncopyable
+{
+public:
+ Butler (boost::weak_ptr<const Film> film, boost::shared_ptr<Player> player);
+ ~Butler ();
+
+ void seek (DCPTime position, bool accurate);
+ std::pair<boost::shared_ptr<PlayerVideo>, DCPTime> get_video ();
+
+private:
+ void thread ();
+ void video (boost::shared_ptr<PlayerVideo> video, DCPTime time);
+
+ boost::weak_ptr<const Film> _film;
+ boost::shared_ptr<Player> _player;
+ boost::thread* _thread;
+
+ VideoRingBuffers _video;
+
+ boost::mutex _mutex;
+ boost::condition _summon;
+ boost::condition _arrived;
+ boost::optional<DCPTime> _pending_seek_position;
+ bool _pending_seek_accurate;
+
+ bool _finished;
+
+ boost::signals2::scoped_connection _player_video_connection;
+};
diff --git a/src/lib/player_video.h b/src/lib/player_video.h
index 60c9224b0..5017d0e3c 100644
--- a/src/lib/player_video.h
+++ b/src/lib/player_video.h
@@ -18,6 +18,9 @@
*/
+#ifndef DCPOMATIC_PLAYER_VIDEO_H
+#define DCPOMATIC_PLAYER_VIDEO_H
+
#include "types.h"
#include "position.h"
#include "dcpomatic_time.h"
@@ -98,3 +101,5 @@ private:
boost::optional<ColourConversion> _colour_conversion;
boost::optional<PositionImage> _subtitle;
};
+
+#endif
diff --git a/src/lib/video_ring_buffers.cc b/src/lib/video_ring_buffers.cc
new file mode 100644
index 000000000..254285456
--- /dev/null
+++ b/src/lib/video_ring_buffers.cc
@@ -0,0 +1,79 @@
+/*
+ Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "video_ring_buffers.h"
+#include "player_video.h"
+#include <boost/foreach.hpp>
+#include <list>
+#include <iostream>
+
+using std::list;
+using std::make_pair;
+using std::cout;
+using std::pair;
+using boost::shared_ptr;
+using boost::optional;
+
+void
+VideoRingBuffers::put (shared_ptr<PlayerVideo> frame, DCPTime time)
+{
+ cout << "put " << to_string(time) << "\n";
+ boost::mutex::scoped_lock lm (_mutex);
+ _data.push_back (make_pair (frame, time));
+}
+
+pair<shared_ptr<PlayerVideo>, DCPTime>
+VideoRingBuffers::get ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ if (_data.empty ()) {
+ cout << "get: no data.\n";
+ return make_pair(shared_ptr<PlayerVideo>(), DCPTime());
+ }
+ pair<shared_ptr<PlayerVideo>, DCPTime> const r = _data.front ();
+ cout << "get: here we go! " << to_string(r.second) << "\n";
+ _data.pop_front ();
+ return r;
+}
+
+Frame
+VideoRingBuffers::size () const
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ return _data.size ();
+}
+
+void
+VideoRingBuffers::clear ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ _data.clear ();
+}
+
+optional<DCPTime>
+VideoRingBuffers::latest () const
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ if (_data.empty ()) {
+ return optional<DCPTime> ();
+ }
+
+ return _data.back().second;
+}
diff --git a/src/lib/video_ring_buffers.h b/src/lib/video_ring_buffers.h
new file mode 100644
index 000000000..f728247fe
--- /dev/null
+++ b/src/lib/video_ring_buffers.h
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2016-2017 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "dcpomatic_time.h"
+#include "player_video.h"
+#include "types.h"
+#include <boost/noncopyable.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/shared_ptr.hpp>
+#include <utility>
+
+class PlayerVideo;
+
+class VideoRingBuffers : public boost::noncopyable
+{
+public:
+ void put (boost::shared_ptr<PlayerVideo> frame, DCPTime time);
+ std::pair<boost::shared_ptr<PlayerVideo>, DCPTime> get ();
+
+ void clear ();
+ Frame size () const;
+
+ boost::optional<DCPTime> latest () const;
+
+private:
+ mutable boost::mutex _mutex;
+ std::list<std::pair<boost::shared_ptr<PlayerVideo>, DCPTime> > _data;
+};
diff --git a/src/lib/wscript b/src/lib/wscript
index 2c34577d9..23e846812 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -35,6 +35,7 @@ sources = """
audio_point.cc
audio_processor.cc
audio_stream.cc
+ butler.cc
case_insensitive_sorter.cc
cinema.cc
cinema_kdms.cc
@@ -144,6 +145,7 @@ sources = """
video_mxf_content.cc
video_mxf_decoder.cc
video_mxf_examiner.cc
+ video_ring_buffers.cc
writer.cc
"""