Fix a crash due the assertion in emit_audio failing when applying
authorCarl Hetherington <cth@carlh.net>
Thu, 10 Jan 2019 21:47:11 +0000 (21:47 +0000)
committerCarl Hetherington <cth@carlh.net>
Thu, 10 Jan 2019 21:47:11 +0000 (21:47 +0000)
trims which do not land precisely on a DCP audio sample boundary
(at least, I think that's what triggers it).

src/lib/audio_ring_buffers.cc
src/lib/player.cc
test/player_test.cc

index d26fb9eb7907b8a31790530225b335405d2841c5..21c4b6a5c1084123c71d82706653615e96aab709 100644 (file)
@@ -46,10 +46,11 @@ AudioRingBuffers::put (shared_ptr<const AudioBuffers> 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));
index fa6c1b055a6670750ed10388eb6d2a6f01e24386..f80adcbf4581731ae0f675e57b7dbd10dad97b7d 100644 (file)
@@ -1093,12 +1093,12 @@ void
 Player::emit_audio (shared_ptr<AudioBuffers> 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());
 }
index 7e2631cc98da0337f445ff27565eeec031c5bb28..9d6641cb26ea5dfb04b0ff724164f178c2f2e359 100644 (file)
@@ -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 <boost/test/unit_test.hpp>
 #include <iostream>
@@ -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> film = new_test_film2 ("player_trim_crash");
+       shared_ptr<Content> boon = content_factory(private_data / "boon_telly.mkv").front();
+       film->examine_and_add_content (boon);
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       shared_ptr<Player> player (new Player(film, film->playlist()));
+       player->set_fast ();
+       shared_ptr<Butler> 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 ();
+}