summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2018-07-26 20:59:04 +0100
committerCarl Hetherington <cth@carlh.net>2018-07-26 20:59:04 +0100
commit3009a585f5222a83213c786e3c564c740f450d18 (patch)
treeba65c1dc9ca643656160a6b7045f14c185fdd8f8
parent8484d278ec6905502bd1178cc58d8cb7b3c12df0 (diff)
Protect the public API of Player with a mutex, since
seek() and pass() may be called from the Butler thread ad the same time as other Player methods are called from the GUI thread (by FilmViewer and ClosedCaptionViewDialog).
-rw-r--r--src/lib/butler.cc4
-rw-r--r--src/lib/player.cc45
-rw-r--r--src/lib/player.h7
-rw-r--r--src/wx/film_viewer.cc2
4 files changed, 48 insertions, 10 deletions
diff --git a/src/lib/butler.cc b/src/lib/butler.cc
index 112778e25..138ee0fbd 100644
--- a/src/lib/butler.cc
+++ b/src/lib/butler.cc
@@ -198,6 +198,7 @@ Butler::get_video ()
}
pair<shared_ptr<PlayerVideo>, DCPTime> const r = _video.get ();
+ cout << "BGV " << to_string(r.second) << " " << _video.size() << "\n";
_summon.notify_all ();
return r;
}
@@ -233,6 +234,7 @@ Butler::prepare (weak_ptr<PlayerVideo> weak_video) const
void
Butler::video (shared_ptr<PlayerVideo> video, DCPTime time)
{
+ cout << "BV: " << to_string(time) << " " << _video.size() << " " << (float(_video.size()) / 24) << "\n";
boost::mutex::scoped_lock lm (_mutex);
if (_pending_seek_position) {
/* Don't store any video while a seek is pending */
@@ -246,6 +248,7 @@ Butler::video (shared_ptr<PlayerVideo> video, DCPTime time)
void
Butler::audio (shared_ptr<AudioBuffers> audio)
{
+ cout << "BA: " << audio->frames() << " " << _audio.size() << " " << (float(_audio.size()) / 48000) << "\n";
{
boost::mutex::scoped_lock lm (_mutex);
if (_pending_seek_position || _disable_audio) {
@@ -265,6 +268,7 @@ bool
Butler::get_audio (float* out, Frame frames)
{
bool const underrun = _audio.get (out, _audio_channels, frames);
+ cout << "BGA: " << frames << " " << _audio.size() << " " << (float(_audio.size()) / 48000) << "\n";
_summon.notify_all ();
return underrun;
}
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 8b2ade1dc..f8471c752 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -258,14 +258,18 @@ Player::playlist_content_changed (weak_ptr<Content> w, int property, bool freque
void
Player::set_video_container_size (dcp::Size s)
{
- if (s == _video_container_size) {
- return;
- }
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ if (s == _video_container_size) {
+ return;
+ }
- _video_container_size = s;
+ _video_container_size = s;
- _black_image.reset (new Image (AV_PIX_FMT_RGB24, _video_container_size, true));
- _black_image->make_black ();
+ _black_image.reset (new Image (AV_PIX_FMT_RGB24, _video_container_size, true));
+ _black_image->make_black ();
+ }
Changed (PlayerProperty::VIDEO_CONTAINER_SIZE, false);
}
@@ -414,6 +418,8 @@ Player::content_time_to_dcp (shared_ptr<const Piece> piece, ContentTime t) const
list<shared_ptr<Font> >
Player::get_subtitle_fonts ()
{
+ /* Does not require a lock on _mutex as it's only called from DCPEncoder */
+
if (!_have_valid_pieces) {
setup_pieces ();
}
@@ -436,12 +442,14 @@ Player::get_subtitle_fonts ()
void
Player::set_ignore_video ()
{
+ boost::mutex::scoped_lock lm (_mutex);
_ignore_video = true;
}
void
Player::set_ignore_text ()
{
+ boost::mutex::scoped_lock lm (_mutex);
_ignore_text = true;
}
@@ -449,6 +457,7 @@ Player::set_ignore_text ()
void
Player::set_always_burn_open_subtitles ()
{
+ boost::mutex::scoped_lock lm (_mutex);
_always_burn_open_subtitles = true;
}
@@ -456,6 +465,7 @@ Player::set_always_burn_open_subtitles ()
void
Player::set_fast ()
{
+ boost::mutex::scoped_lock lm (_mutex);
_fast = true;
_have_valid_pieces = false;
}
@@ -463,6 +473,7 @@ Player::set_fast ()
void
Player::set_play_referenced ()
{
+ boost::mutex::scoped_lock lm (_mutex);
_play_referenced = true;
_have_valid_pieces = false;
}
@@ -470,6 +481,8 @@ Player::set_play_referenced ()
list<ReferencedReelAsset>
Player::get_reel_assets ()
{
+ /* Does not require a lock on _mutex as it's only called from DCPEncoder */
+
list<ReferencedReelAsset> a;
BOOST_FOREACH (shared_ptr<Content> i, _playlist->content ()) {
@@ -546,6 +559,8 @@ Player::get_reel_assets ()
bool
Player::pass ()
{
+ boost::mutex::scoped_lock lm (_mutex);
+
if (!_have_valid_pieces) {
setup_pieces ();
}
@@ -680,6 +695,7 @@ Player::pass ()
list<PlayerText>
Player::closed_captions_for_frame (DCPTime time) const
{
+ boost::mutex::scoped_lock _lm (_mutex);
return _active_texts[TEXT_CLOSED_CAPTION].get (
DCPTimePeriod(time, time + DCPTime::from_frames(1, _film->video_frame_rate()))
);
@@ -972,6 +988,8 @@ Player::subtitle_stop (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, Conte
void
Player::seek (DCPTime time, bool accurate)
{
+ boost::mutex::scoped_lock lm (_mutex);
+
if (!_have_valid_pieces) {
setup_pieces ();
}
@@ -1120,18 +1138,25 @@ Player::discard_audio (shared_ptr<const AudioBuffers> audio, DCPTime time, DCPTi
void
Player::set_dcp_decode_reduction (optional<int> reduction)
{
- if (reduction == _dcp_decode_reduction) {
- return;
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ if (reduction == _dcp_decode_reduction) {
+ return;
+ }
+
+ _dcp_decode_reduction = reduction;
+ _have_valid_pieces = false;
}
- _dcp_decode_reduction = reduction;
- _have_valid_pieces = false;
Changed (PlayerProperty::DCP_DECODE_REDUCTION, false);
}
DCPTime
Player::content_time_to_dcp (shared_ptr<Content> content, ContentTime t)
{
+ boost::mutex::scoped_lock lm (_mutex);
+
if (_have_valid_pieces) {
setup_pieces ();
}
diff --git a/src/lib/player.h b/src/lib/player.h
index 223db86b3..4a91c4c52 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -73,6 +73,7 @@ public:
std::list<boost::shared_ptr<Font> > get_subtitle_fonts ();
std::list<ReferencedReelAsset> get_reel_assets ();
dcp::Size video_container_size () const {
+ boost::mutex::scoped_lock lm (_mutex);
return _video_container_size;
}
@@ -141,6 +142,12 @@ private:
void do_emit_video (boost::shared_ptr<PlayerVideo> pv, DCPTime time);
void emit_audio (boost::shared_ptr<AudioBuffers> data, DCPTime time);
+ /** Mutex to protect the whole Player state. When it's used for the preview we have
+ seek() and pass() called from the Butler thread and lots of other stuff called
+ from the GUI thread.
+ */
+ mutable boost::mutex _mutex;
+
boost::shared_ptr<const Film> _film;
boost::shared_ptr<const Playlist> _playlist;
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index ef28018e9..8c1a79113 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -529,6 +529,8 @@ FilmViewer::start ()
_audio.startStream ();
}
+ cout << "start playback at " << to_string(_video_position) << "\n";
+
_playing = true;
_dropped = 0;
timer ();