diff --git a/src/control/controlmodel.cpp b/src/control/controlmodel.cpp index 04ecd863b79..923be754b2d 100644 --- a/src/control/controlmodel.cpp +++ b/src/control/controlmodel.cpp @@ -22,7 +22,6 @@ void ControlModel::addControl(const ConfigKey& key, info.title = title; info.description = description; info.pControl = new ControlProxy(info.key, this); - info.pControl->initialize(); beginInsertRows(QModelIndex(), m_controls.size(), m_controls.size()); diff --git a/src/sources/soundsourceffmpeg.cpp b/src/sources/soundsourceffmpeg.cpp index d9648c97dae..9c9ab16e371 100644 --- a/src/sources/soundsourceffmpeg.cpp +++ b/src/sources/soundsourceffmpeg.cpp @@ -1185,7 +1185,23 @@ ReadableSampleFrames SoundSourceFFmpeg::readSampleFramesClamped( << "writableRange" << writableRange << "missingFrameCount" << missingFrameCount; #endif + // readFrameIndex + // | + // v + // | missingFrameCount |<- decodedFrameRange ->| DEBUG_ASSERT(readFrameIndex <= decodedFrameRange.start()); + if (readFrameIndex < decodedFrameRange.start()) { + // The decoder has skipped some sample data that needs to + // be filled with silence to continue decoding! This is supposed + // to occur only at the beginning of a stream for the very first + // decoded frame with a lead-in due to start_time > 0. But not all + // encoded streams seem to account for this by correctly setting + // the start_time property. + kLogger.warning() + << "Generating silence for unavailable sample data" + << IndexRange::between(readFrameIndex, decodedFrameRange.start()); + } + // NOTE: Decoding might start at a negative position for the first // frame of the file! In this case readFrameIndex < decodedFrameRange().start(), // i.e. the decoded frame starts outside of the track's valid range! @@ -1200,22 +1216,10 @@ ReadableSampleFrames SoundSourceFFmpeg::readSampleFramesClamped( break; } - // readFrameIndex - // | - // v - // | missingFrameCount |<- decodedFrameRange ->| - - if (readFrameIndex > writableRange.start()) { - // The decoder has skipped some sample data that needs to - // be filled with silence to continue decoding! - const auto missingRange = IndexRange::between(writableRange.start(), readFrameIndex); - // This should only happen at the beginning of a stream - // with a lead-in due to start_time > 0. - VERIFY_OR_DEBUG_ASSERT(intersect(missingRange, getStreamFrameIndexRange(*m_pavStream)).empty()) { - kLogger.warning() - << "Missing sample data within decoded stream" - << intersect(missingRange, getStreamFrameIndexRange(*m_pavStream)); - } + if (writableRange.start() < readFrameIndex) { + const auto missingRange = IndexRange::between( + writableRange.start(), + readFrameIndex); const auto clearRange = intersect(missingRange, writableRange); if (clearRange.length() > 0) { const auto clearSampleCount = @@ -1229,6 +1233,7 @@ ReadableSampleFrames SoundSourceFFmpeg::readSampleFramesClamped( writableRange.shrinkFront(clearRange.length()); } } + DEBUG_ASSERT(writableRange.start() >= readFrameIndex); // Skip all missing and decoded ranges that do not overlap // with writableRange, i.e. that precede writableRange. diff --git a/src/test/autodjprocessor_test.cpp b/src/test/autodjprocessor_test.cpp index aff28911ac6..77bad5411c7 100644 --- a/src/test/autodjprocessor_test.cpp +++ b/src/test/autodjprocessor_test.cpp @@ -541,6 +541,11 @@ TEST_F(AutoDJProcessorTest, TransitionTimeLoadedFromConfig) { EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel2]"))).Times(1); EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel3]"))).Times(1); EXPECT_CALL(*pPlayerManager, getPlayer(QString("[Channel4]"))).Times(1); + + // We need to call reset *before* constructing a new MockAutoDJProcessor, + // because otherwise the new object will try to create COs that already + // exist because they were created by the previous instance. + pProcessor.reset(); pProcessor.reset(new MockAutoDJProcessor( nullptr, config(), pPlayerManager.data(), trackCollections(), m_iAutoDJPlaylistId));