WIP: more 1771-resample-glitches-take4
authorCarl Hetherington <cth@carlh.net>
Thu, 6 May 2021 22:21:16 +0000 (00:21 +0200)
committerCarl Hetherington <cth@carlh.net>
Fri, 7 May 2021 07:29:59 +0000 (09:29 +0200)
src/lib/audio_buffers.cc
src/lib/audio_buffers.h
src/lib/audio_decoder.cc
src/lib/audio_decoder.h
src/lib/dcp_decoder.cc
src/lib/ffmpeg_decoder.cc
src/lib/piece.cc
src/lib/player.cc
test/torture_test.cc

index 9f91810e0c4ab14387b55eef574a1362bf1c6fdf..89e889749313e234b59485b7409f539693478eb7 100644 (file)
@@ -395,3 +395,12 @@ AudioBuffers::trim_start (int32_t frames)
        move (_frames - frames, frames, 0);
        set_frames (_frames - frames);
 }
+
+
+void
+AudioBuffers::trim_end (int32_t frames)
+{
+       DCPOMATIC_ASSERT (frames <= _frames);
+       set_frames (_frames - frames);
+}
+
index 146d5bd3e2d8f88c260b3f7776d0104cd66d8c0b..5427766b8762ae13a4c043bfb788e0fb07e7dc30 100644 (file)
@@ -84,6 +84,7 @@ public:
        void accumulate_frames (AudioBuffers const * from, int32_t frames, int32_t read_offset, int32_t write_offset);
        void append (std::shared_ptr<const AudioBuffers> other);
        void trim_start (int32_t frames);
+       void trim_end (int32_t frames);
 
 private:
        void allocate (int channels, int32_t frames);
index 643fc8be41e9868dc2423826a2bb18b26a5dd652..f7eb550ddf2049fed3668191f10865f348061316 100644 (file)
 */
 
 
-#include "audio_decoder.h"
 #include "audio_buffers.h"
 #include "audio_content.h"
+#include "audio_decoder.h"
+#include "compose.hpp"
 #include "dcpomatic_log.h"
 #include "log.h"
-#include "resampler.h"
-#include "compose.hpp"
 #include <iostream>
 
 #include "i18n.h"
@@ -53,7 +52,7 @@ AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> cont
 
 /** @param time_already_delayed true if the delay should not be added to time */
 void
-AudioDecoder::emit (shared_ptr<const Film> film, AudioStreamPtr stream, shared_ptr<const AudioBuffers> data, ContentTime time, bool time_already_delayed)
+AudioDecoder::emit (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data, ContentTime time, bool time_already_delayed)
 {
        if (ignore ()) {
                return;
@@ -65,7 +64,7 @@ AudioDecoder::emit (shared_ptr<const Film> film, AudioStreamPtr stream, shared_p
         */
        static Frame const slack_frames = 48000 / 24;
 
-       int const resampled_rate = _content->resampled_frame_rate(film);
+       auto const frame_rate = stream->frame_rate();
        if (!time_already_delayed) {
                time += ContentTime::from_seconds (_content->delay() / 1000.0);
        }
@@ -84,18 +83,18 @@ AudioDecoder::emit (shared_ptr<const Film> film, AudioStreamPtr stream, shared_p
                        silence (_content->delay ());
                }
                reset = true;
-       } else if (std::abs(_positions[stream] - time.frames_round(resampled_rate)) > slack_frames) {
+       } else if (std::abs(_positions[stream] - time.frames_round(frame_rate)) > slack_frames) {
                reset = true;
                LOG_GENERAL (
                        "Reset audio position: was %1, new data at %2, slack: %3 frames",
                        _positions[stream],
-                       time.frames_round(resampled_rate),
-                       std::abs(_positions[stream] - time.frames_round(resampled_rate))
+                       time.frames_round(frame_rate),
+                       std::abs(_positions[stream] - time.frames_round(frame_rate))
                        );
        }
 
        if (reset) {
-               _positions[stream] = time.frames_round (resampled_rate);
+               _positions[stream] = time.frames_round (frame_rate);
        }
 
        Data(stream, data, _positions[stream]);
@@ -109,7 +108,7 @@ AudioDecoder::stream_position (shared_ptr<const Film> film, AudioStreamPtr strea
 {
        auto i = _positions.find (stream);
        DCPOMATIC_ASSERT (i != _positions.end ());
-       return ContentTime::from_frames (i->second, _content->resampled_frame_rate(film));
+       return ContentTime::from_frames (i->second, stream->frame_rate());
 }
 
 
index e5698c4f5decd289027fab218fedd19e68ff7437..4cb2f17bf8d9c76d70ec16bc8b859e14a129a032 100644 (file)
@@ -52,7 +52,7 @@ public:
        AudioDecoder (Decoder* parent, std::shared_ptr<const AudioContent> content);
 
        boost::optional<dcpomatic::ContentTime> position (std::shared_ptr<const Film> film) const;
-       void emit (std::shared_ptr<const Film> film, AudioStreamPtr stream, std::shared_ptr<const AudioBuffers>, dcpomatic::ContentTime, bool time_already_delayed = false);
+       void emit (AudioStreamPtr stream, std::shared_ptr<const AudioBuffers>, dcpomatic::ContentTime, bool time_already_delayed = false);
        void seek ();
        void flush ();
 
index 23815bef336674867819d49e5ad3b4878dc6e93e..73b45b219fbef9ede1cac95c893f7ebf700ee13e 100644 (file)
@@ -217,7 +217,7 @@ DCPDecoder::do_pass ()
                        }
                }
 
-               audio->emit (film(), _dcp_content->audio->stream(), data, ContentTime::from_frames (_offset, vfr) + _next);
+               audio->emit (_dcp_content->audio->stream(), data, ContentTime::from_frames (_offset, vfr) + _next);
        }
 
        if (_atmos_reader) {
index c661240c3961e1f4f3c928a039fdcab04528fde5..5e09bb8fa603cc9704f7c0e8ddf9c63386d144f4 100644 (file)
@@ -164,7 +164,7 @@ FFmpegDecoder::flush ()
                                auto to_do = min (full_length - a, ContentTime::from_seconds (0.1));
                                auto silence = make_shared<AudioBuffers>(i->channels(), to_do.frames_ceil (i->frame_rate()));
                                silence->make_silent ();
-                               audio->emit (film(), i, silence, a, true);
+                               audio->emit (i, silence, a, true);
                                a += to_do;
                        }
                }
@@ -479,7 +479,6 @@ FFmpegDecoder::process_audio_frame (shared_ptr<FFmpegAudioStream> stream)
                data->move (data->frames() - remove, remove, 0);
                data->set_frames (data->frames() - remove);
                ct += ContentTime::from_frames (remove, stream->frame_rate());
-               std::cout << "FF discarded " << remove << "\n";
        }
 
        if (ct < ContentTime()) {
@@ -496,7 +495,7 @@ FFmpegDecoder::process_audio_frame (shared_ptr<FFmpegAudioStream> stream)
 
        /* Give this data provided there is some, and its time is sane */
        if (ct >= ContentTime() && data->frames() > 0) {
-               audio->emit (film(), stream, data, ct);
+               audio->emit (stream, data, ct);
        }
 }
 
index b8d587cbcfe678b6b0e9d7ef7d5ed24ab68bace9..86e8e9bc6efba5cc29414df6408ad0516d3b58c0 100644 (file)
@@ -119,17 +119,21 @@ Piece::audio (shared_ptr<const Content> content, AudioStreamPtr stream_ptr, shar
         * start thinking about frame indices into the piece.  Here's the last chance for us to apply this content's
         * trim, so we'll take it.
         */
-       auto const start_trim = content->trim_start().frames_round(stream_ptr->frame_rate());
-       auto const remove_from_start = std::max(Frame(0), start_trim - frame);
-       if (remove_from_start > 0) {
+       auto const sfr = stream_ptr->frame_rate();
+       auto const remove_from_start = std::max(Frame(0), content->trim_start().frames_round(sfr) - frame);
+       auto const remove_from_end = std::max(Frame(0), frame + audio->frames() - ContentTime(content->full_length_content() - content->trim_end()).frames_round(sfr));
+       if ((remove_from_start + remove_from_end) >= audio->frames()) {
+               std::cout << "trim whole block.\n";
+               return;
+       }
+       if (remove_from_start || remove_from_end) {
+               std::cout << "trim " << remove_from_start << " " << remove_from_end << "\n";
                auto trimmed = make_shared<AudioBuffers>(audio);
                trimmed->trim_start (remove_from_start);
-               frame += remove_from_start;
+               trimmed->trim_end (remove_from_end);
+               audio = trimmed;
        }
 
-       auto const end_trim = content->trim_send().frames_round(stream_ptr->frame_rate());
-
-
        auto content_streams = content->audio->streams();
        auto content_stream_iter = std::find(content_streams.begin(), content_streams.end(), stream_ptr);
        DCPOMATIC_ASSERT (content_stream_iter != content_streams.end());
@@ -167,7 +171,6 @@ Piece::audio (shared_ptr<const Content> content, AudioStreamPtr stream_ptr, shar
                stream.position = frame;
        }
 
-       std::cout << "piece sends frame " << stream.position << " " << to_string(resampled_audio_to_dcp(stream.position) << "\n";
        Audio (PieceAudio(index, audio, resampled_audio_to_dcp(stream.position), stream_ptr->mapping()));
        stream.position += audio->frames();
 }
index 8b785f0fe7d7c040dba0a6598dbe53c83a0e7cd9..7e915296ed1dfc06dc16b0535557671d85cebe53 100644 (file)
@@ -906,7 +906,10 @@ Player::audio (weak_ptr<Piece> wp, PieceAudio audio)
        /* The end of this block in the DCP */
        int const rfr = piece->resampled_audio_frame_rate ();
        auto end = audio.time + DCPTime::from_frames(audio.audio->frames(), rfr);
-       std::cout << "Player gets " << to_string(audio.time) << "\n";
+
+       /* XXX: is this still necessary? don't the checks in Piece take care of this now?
+        * Maybe replace with some assertions & run tests.
+        */
 
        /* Remove anything that comes before the start or after the end of the content */
        if (audio.time < piece->position()) {
index c9bffaac7acf02aac11bc95f9ed37859253cc8b5..9635aea73db9728bbbe802dad0a651e61d54c458 100644 (file)
@@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE (torture_test1)
                for (int i = 0; i < fr->samples(); ++i) {
                        for (int j = 0; j < 6; ++j) {
                                if (j == 2) {
-                                       BOOST_CHECK_EQUAL ((fr->get(j, i) + 128) >> 8, stair * 2);
+                                       BOOST_CHECK_MESSAGE (((fr->get(j, i) + 128) >> 8) == (stair * 2), "sample=" << i << " channel=" << j << " frame has " << ((fr->get(j, i) + 128) >> 8) << " instead of " << (stair * 2));
                                        ++stair;
                                } else {
                                        BOOST_CHECK_EQUAL (fr->get(j, i), 0);