Commit cbe6d73d authored by jan.koester's avatar jan.koester
Browse files

deb

parent 3af8cfb0
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
mediadb (20260423+72) unstable; urgency=medium

  * Preview: flush FFmpeg decoder after read loop so codecs that buffer
    the single frame (e.g. WebP VP8X with XMP/EXIF chunks) emit it.
    Fixes "could not decode a frame" for extended-format WebP images.
  * Track premature EOF in PrefetchBuffer: when cluster data is
    unavailable, report "cluster data timed out" so the error triggers
    503 + Retry-After instead of a permanent 422.

 -- Jan Koester <jan.koester@tuxist.de>  Wed, 23 Apr 2026 20:10:00 +0200

mediadb (20260423+71) unstable; urgency=medium

  * Read client pool: replace single read_client_ with a pool of 4
+17 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ struct PrefetchBuffer {
    std::string      media_id;
    std::uint64_t    total_size;
    std::uint64_t    pos = 0;
    bool             premature_eof = false;  // set when read returns empty before total_size

    // prefetch ring — holds in-flight async reads
    struct PendingBlock {
@@ -131,7 +132,7 @@ struct PrefetchBuffer {
            std::uint64_t remaining = total_size - pos;
            std::uint64_t to_read = std::min<std::uint64_t>(want, remaining);
            auto data = db->read_media_data_range(media_id, pos, to_read);
            if (data.empty()) return AVERROR_EOF;
            if (data.empty()) { premature_eof = (pos < total_size); return AVERROR_EOF; }
            std::memcpy(buf, data.data(), data.size());
            pos += data.size();
            return static_cast<int>(data.size());
@@ -143,6 +144,7 @@ struct PrefetchBuffer {
        }

        if (front.data.empty()) {
            premature_eof = (pos < total_size);
            ring.pop_front();
            return AVERROR_EOF;
        }
@@ -951,7 +953,20 @@ std::optional<PreviewResult> FFmpegPreviewer::render_streaming(MediaBackendApi&
        }
        if (have_frame) break;
    }
    // Flush decoder — some codecs (notably WebP with extended format /
    // VP8X chunks) buffer the single frame until they receive an EOF
    // signal via a NULL packet.
    if (!have_frame) {
        avcodec_send_packet(dec_ctx, nullptr);
        while (avcodec_receive_frame(dec_ctx, decoded) >= 0) {
            have_frame = true;
            break;
        }
    }
    if (!have_frame) {
        if (prefetch_buf.premature_eof)
            error_out = "could not decode a frame: cluster data timed out";
        else
            error_out = "could not decode a frame";
        return std::nullopt;
    }