~aleteoryx/muditaos

1d807644c99508cc54c9b93a6e5543af4a612703 — Lefucjusz 3 years ago 1c27ec9
[MOS-882] Fix heap fragmentation issue during playback

Fix of the heap fragmentation issue that caused
phone crash when trying to play music files
while connecting USB cable in a certain order.
Audio stream buffering length was slightly
reduced, so that smaller contiguous block of
heap is required to store audio buffer.
M module-audio/Audio/Stream.hpp => module-audio/Audio/Stream.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 50,7 50,7 @@ namespace audio
            virtual UniqueStreamBuffer allocate(std::size_t size) = 0;
        };

        static constexpr auto defaultBufferingSize = 32U;
        static constexpr auto defaultBufferingSize = 24U;

        Stream(AudioFormat format,
               Allocator &allocator,

M module-audio/Audio/StreamFactory.cpp => module-audio/Audio/StreamFactory.cpp +9 -8
@@ 48,12 48,11 @@ auto StreamFactory::makeStream(Source &source, Sink &sink) -> std::unique_ptr<Ab
auto StreamFactory::makeStream(Traits sourceTraits, Traits sinkTraits, AudioFormat streamFormat)
    -> std::unique_ptr<Stream>
{
    auto streamBuffering     = defaultBuffering;
    auto endpointsTraits     = {sourceTraits, sinkTraits};
    const auto endpointsTraits  = {sourceTraits, sinkTraits};
    const auto timingConstraint = getTimingConstraints(std::initializer_list<std::optional<std::chrono::milliseconds>>{
        sinkTraits.timeConstraint, sourceTraits.timeConstraint, periodRequirement});
    auto blockSizeConstraint = getBlockSizeConstraint(endpointsTraits);
    auto &streamAllocator    = negotiateAllocator(endpointsTraits);
    auto timingConstraint    = getTimingConstraints(std::initializer_list<std::optional<std::chrono::milliseconds>>{
        sinkTraits.timeConstraint, sourceTraits.timeConstraint, periodRequirement});

    if (streamFormat == audio::nullFormat) {
        throw std::invalid_argument("No source format provided");


@@ 63,13 62,15 @@ auto StreamFactory::makeStream(Traits sourceTraits, Traits sinkTraits, AudioForm
        blockSizeConstraint = binary::ceilPowerOfTwo(streamFormat.microsecondsToBytes(timingConstraint));
    }

    auto blockTransferDuration =
    const auto blockTransferDuration =
        std::chrono::duration<double, std::milli>(streamFormat.bytesToMicroseconds(blockSizeConstraint.value()));
    streamBuffering = static_cast<unsigned int>(std::ceil(timingConstraint / blockTransferDuration)) * defaultBuffering;
    const auto streamBuffering =
        static_cast<unsigned int>(std::ceil(timingConstraint / blockTransferDuration)) * defaultBuffering;

    LOG_DEBUG("Creating audio stream: block size = %lu; buffering = %u",
    LOG_DEBUG("Creating audio stream: block size = %lu bytes; buffering = %u -> stream buffer size = %lu bytes",
              static_cast<unsigned long>(blockSizeConstraint.value()),
              streamBuffering);
              streamBuffering,
              static_cast<unsigned long>(blockSizeConstraint.value() * streamBuffering));

    return std::make_unique<Stream>(streamFormat, streamAllocator, blockSizeConstraint.value(), streamBuffering);
}

M module-audio/Audio/StreamFactory.hpp => module-audio/Audio/StreamFactory.hpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 32,7 32,7 @@ namespace audio
      private:
        using Traits = audio::Endpoint::Traits;

        static constexpr auto defaultBuffering = 32U;
        static constexpr auto defaultBuffering = 24U;

        auto makeStream(Traits sourceTraits, Traits sinkTraits, AudioFormat streamFormat) -> std::unique_ptr<Stream>;


M module-audio/Audio/test/unittest_stream.cpp => module-audio/Audio/test/unittest_stream.cpp +2 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <gtest/gtest.h>


@@ 21,15 21,13 @@
using audio::NonCacheableStreamAllocator;
using audio::StandardStreamAllocator;
using audio::Stream;
using audio::StreamFactory;
using testing::Return;
using testing::audio::MockStream;
using testing::audio::MockStreamEventListener;

using namespace std::chrono_literals;

constexpr std::size_t defaultBlockSize = 64U;
constexpr std::size_t defaultBuffering = 32U;
constexpr std::size_t defaultBuffering = 24U;
constexpr audio::AudioFormat format    = audio::AudioFormat(44100, 16, 2);

static std::uint8_t testData[defaultBuffering][defaultBlockSize];