From: Carl Hetherington Date: Thu, 10 Jan 2019 21:47:11 +0000 (+0000) Subject: Fix a crash due the assertion in emit_audio failing when applying X-Git-Tag: v2.13.98~6 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=70684e31a96bd7d4c7b09d525902959345b76526 Fix a crash due the assertion in emit_audio failing when applying trims which do not land precisely on a DCP audio sample boundary (at least, I think that's what triggers it). --- diff --git a/src/lib/audio_ring_buffers.cc b/src/lib/audio_ring_buffers.cc index d26fb9eb7..21c4b6a5c 100644 --- a/src/lib/audio_ring_buffers.cc +++ b/src/lib/audio_ring_buffers.cc @@ -46,10 +46,11 @@ AudioRingBuffers::put (shared_ptr data, DCPTime time, int fr if (!_buffers.empty()) { DCPOMATIC_ASSERT (_buffers.front().first->channels() == data->channels()); - if ((_buffers.back().second + DCPTime::from_frames(_buffers.back().first->frames(), frame_rate)) != time) { + DCPTime const end = (_buffers.back().second + DCPTime::from_frames(_buffers.back().first->frames(), frame_rate)); + if (labs(end.get() - time.get()) > 1) { cout << "bad put " << to_string(_buffers.back().second) << " " << _buffers.back().first->frames() << " " << to_string(time) << "\n"; } - DCPOMATIC_ASSERT ((_buffers.back().second + DCPTime::from_frames(_buffers.back().first->frames(), frame_rate)) == time); + DCPOMATIC_ASSERT (labs(end.get() - time.get()) < 2); } _buffers.push_back(make_pair(data, time)); diff --git a/src/lib/player.cc b/src/lib/player.cc index fa6c1b055..f80adcbf4 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -1093,12 +1093,12 @@ void Player::emit_audio (shared_ptr data, DCPTime time) { /* Log if the assert below is about to fail */ - if (_last_audio_time && time != *_last_audio_time) { + if (_last_audio_time && labs(time.get() - _last_audio_time->get()) > 1) { _film->log()->log(String::compose("Out-of-sequence emit %1 vs %2", to_string(time), to_string(*_last_audio_time)), LogEntry::TYPE_WARNING); } - /* This audio must follow on from the previous */ - DCPOMATIC_ASSERT (!_last_audio_time || time == *_last_audio_time); + /* This audio must follow on from the previous, allowing for half a sample (at 48kHz) leeway */ + DCPOMATIC_ASSERT (!_last_audio_time || labs(time.get() - _last_audio_time->get()) < 2); Audio (data, time, _film->audio_frame_rate()); _last_audio_time = time + DCPTime::from_frames (data->frames(), _film->audio_frame_rate()); } diff --git a/test/player_test.cc b/test/player_test.cc index 7e2631cc9..9d6641cb2 100644 --- a/test/player_test.cc +++ b/test/player_test.cc @@ -37,6 +37,7 @@ #include "lib/text_content.h" #include "lib/butler.h" #include "lib/compose.hpp" +#include "lib/cross.h" #include "test.h" #include #include @@ -317,3 +318,28 @@ BOOST_AUTO_TEST_CASE (player_ignore_video_and_audio_test) BOOST_CHECK_EQUAL (out.size(), 6); } + +/** Trigger a crash due to the assertion failure in Player::emit_audio */ +BOOST_AUTO_TEST_CASE (player_trim_crash) +{ + shared_ptr film = new_test_film2 ("player_trim_crash"); + shared_ptr boon = content_factory(private_data / "boon_telly.mkv").front(); + film->examine_and_add_content (boon); + BOOST_REQUIRE (!wait_for_jobs()); + + shared_ptr player (new Player(film, film->playlist())); + player->set_fast (); + shared_ptr butler (new Butler(player, AudioMapping(), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), false, true)); + + /* Wait for the butler to fill */ + dcpomatic_sleep (5); + + boon->set_trim_start (ContentTime::from_seconds(5)); + + butler->seek (DCPTime(), true); + + /* Wait for the butler to refill */ + dcpomatic_sleep (5); + + butler->rethrow (); +}