Commit 5c5b21b5 authored by jan.koester's avatar jan.koester
Browse files

deb

parent 2b846b58
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
mediadb (20260424+76) unstable; urgency=medium

  * Fix: remove render_pool_, run FFmpeg inline on HTTP worker threads.
    Separate render pool caused thread starvation and UI hangs. io_pool_
    now exclusively serves prefetch I/O; semaphore provides backpressure.

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 24 Apr 2026 00:00:00 +0200

mediadb (20260424+75) unstable; urgency=medium

  * Fix: split single io_pool into separate render_pool (CPU-heavy FFmpeg)
+13 −26
Original line number Diff line number Diff line
@@ -695,10 +695,9 @@ std::optional<PreviewResult> FFmpegPreviewer::encode_frame(AVFrame* frame, const

PreviewService::PreviewService(BlobCache& cache, MediaBackendApi& db, std::size_t render_threads)
    : cache_(cache), db_(db),
      render_pool_(render_threads > 0 ? render_threads
                       : std::max(2u, std::min(8u, std::thread::hardware_concurrency() / 2))),
      io_pool_(std::max(4u, std::min(16u, std::thread::hardware_concurrency()))),
      render_sem_(render_pool_.size()) {}
      render_sem_(render_threads > 0 ? render_threads
                      : std::max(1u, std::thread::hardware_concurrency())) {}

std::string PreviewService::make_key(const std::string& media_id,
                                      int width, int height, const std::string& fmt,
@@ -759,31 +758,19 @@ std::shared_ptr<const BlobValue> PreviewService::get_or_create_streaming(const M
        ~SemGuard() { self->render_sem_.release(); }
    } sem_guard{this};

    // Run FFmpeg on the io_pool with a timeout.  This prevents a stuck
    // FFmpeg render from blocking the HTTP worker thread indefinitely.
    // Captures are by value so the lambda is safe if we return on timeout.
    std::string mid = media.id;
    std::uint64_t msize = media.size_bytes;
    std::string mkind = media.media_kind;

    auto fut = render_pool_.submit([this, mid, msize, mkind, width, height, fmt, t_seconds, duration]() {
        std::string err;
        auto res = ffmpeg_.render_streaming(db_, io_pool_, cache_,
                                            mid, msize, mkind,
                                            width, height, fmt, t_seconds, duration, err);
        return std::make_pair(std::move(res), std::move(err));
    });

    auto status = fut.wait_for(std::chrono::seconds(60));

    if (status == std::future_status::timeout) {
        error_out = "preview render timed out after 60s";
        return nullptr;
    // Run FFmpeg inline on the HTTP worker thread.  The semaphore above
    // limits concurrency; io_pool_ handles prefetch I/O independently.
    std::optional<PreviewResult> result;
    try {
        result = ffmpeg_.render_streaming(db_, io_pool_, cache_,
                                          media.id, media.size_bytes, media.media_kind,
                                          width, height, fmt, t_seconds, duration, error_out);
    } catch (const std::exception& e) {
        error_out = std::string("render exception: ") + e.what();
    } catch (...) {
        error_out = "render crashed";
    }

    auto [result, render_err] = fut.get();
    error_out = std::move(render_err);

    if (!result.has_value()) {
        return nullptr;
    }
+2 −3
Original line number Diff line number Diff line
@@ -82,9 +82,8 @@ private:
    BlobCache& cache_;
    MediaBackendApi& db_;
    FFmpegPreviewer ffmpeg_;
    ThreadPool render_pool_;   // CPU-heavy FFmpeg decode/encode — never shares threads with I/O
    ThreadPool io_pool_;       // prefetch I/O only — always has free threads for cluster reads
    std::counting_semaphore<256> render_sem_;  // backpressure: rejects after 30s wait
    ThreadPool io_pool_;       // prefetch I/O only — never blocked by renders
    std::counting_semaphore<256> render_sem_;  // backpressure: limits concurrent renders on HTTP workers
    std::mutex inflight_mutex_;
    std::condition_variable inflight_cv_;
    std::unordered_set<std::string> inflight_;