Commit 518d30a5 authored by jan.koester's avatar jan.koester
Browse files

test

parent bceb73e2
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
mediadb (20260422+64) unstable; urgency=low

  * Speed up preview generation (webp/jpeg):
    - Set probesize/max_analyze_duration before avformat_open_input so
      format detection reads less data over cluster I/O.
    - Use JPEG lowres decoding when target dimensions are much smaller
      than source (avoids full-resolution decode of large photos).
    - Tune WebP encoder: compression_level=0, quality=80, preset=photo
      for significantly faster encoding with minimal quality loss.

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

mediadb (20260422+63) unstable; urgency=low

  * Speed up raw media data delivery:
+25 −5
Original line number Diff line number Diff line
@@ -577,9 +577,11 @@ std::optional<PreviewResult> FFmpegPreviewer::encode_frame(AVFrame* frame, const
    std::string mime = "image/jpeg";
    AVPixelFormat encoder_pix_fmt = static_cast<AVPixelFormat>(frame->format);

    bool is_webp = false;
    if (fmt == "webp") {
        encoder = avcodec_find_encoder(AV_CODEC_ID_WEBP);
        mime = "image/webp";
        is_webp = true;
    } else if (fmt == "png") {
        encoder = avcodec_find_encoder(AV_CODEC_ID_PNG);
        mime = "image/png";
@@ -611,7 +613,12 @@ std::optional<PreviewResult> FFmpegPreviewer::encode_frame(AVFrame* frame, const
    enc_ctx->pix_fmt = encoder_pix_fmt;
    enc_ctx->time_base = AVRational{1, 25};

    if (fmt == "avif") {
    if (is_webp) {
        // Fastest compression — quality 80 is visually fine for previews.
        av_opt_set_int(enc_ctx->priv_data, "compression_level", 0, 0);
        av_opt_set_int(enc_ctx->priv_data, "quality", 80, 0);
        av_opt_set(enc_ctx->priv_data, "preset", "photo", 0);
    } else if (fmt == "avif") {
        enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        enc_ctx->bit_rate = 0;
        av_opt_set(enc_ctx->priv_data, "crf", "32", 0);
@@ -796,6 +803,10 @@ std::optional<PreviewResult> FFmpegPreviewer::render_streaming(MediaBackendApi&
    if (!format_ctx) { avio_context_free(&avio_ctx); error_out = "avformat_alloc_context failed"; return std::nullopt; }
    format_ctx->pb = avio_ctx;
    format_ctx->flags |= AVFMT_FLAG_CUSTOM_IO;
    // Limit probing *before* open so format detection reads less data
    // over cluster I/O.
    format_ctx->probesize = 1024 * 1024;
    format_ctx->max_analyze_duration = 2 * AV_TIME_BASE;

    int rc = avformat_open_input(&format_ctx, nullptr, nullptr, nullptr);
    if (rc < 0) {
@@ -809,10 +820,6 @@ std::optional<PreviewResult> FFmpegPreviewer::render_streaming(MediaBackendApi&
    };
    std::unique_ptr<AVFormatContext, decltype(format_deleter)> format_guard(format_ctx, format_deleter);

    // Limit probe to 1 MB / 2s — avoids reading large amounts of data
    // over cluster I/O just to detect codec parameters.
    format_ctx->probesize = 1024 * 1024;
    format_ctx->max_analyze_duration = 2 * AV_TIME_BASE;
    rc = avformat_find_stream_info(format_ctx, nullptr);
    if (rc < 0) {
        error_out = "avformat_find_stream_info failed: " + ff_err2str(rc);
@@ -840,6 +847,19 @@ std::optional<PreviewResult> FFmpegPreviewer::render_streaming(MediaBackendApi&
    // Use multi-threaded decoding — significant speedup for H.264/H.265
    dec_ctx->thread_count = 0;  // auto-detect (usually hardware_concurrency)
    dec_ctx->thread_type = FF_THREAD_FRAME | FF_THREAD_SLICE;

    // For JPEG/MJPEG: use lowres to decode at reduced resolution when the
    // target is much smaller than the source.  Avoids decoding a 30 MP
    // photo at full resolution just to scale it down to 1280px.
    if (decoder->id == AV_CODEC_ID_MJPEG || decoder->id == AV_CODEC_ID_JPEG2000) {
        const int src_dim = std::max(stream->codecpar->width, stream->codecpar->height);
        const int tgt_dim = std::max(width, height);
        if (tgt_dim > 0 && src_dim > tgt_dim * 4)
            dec_ctx->lowres = (src_dim > tgt_dim * 8) ? 3 : 2;
        else if (tgt_dim > 0 && src_dim > tgt_dim * 2)
            dec_ctx->lowres = 1;
    }

    rc = avcodec_open2(dec_ctx, decoder, nullptr);
    if (rc < 0) { error_out = "avcodec_open2 decoder failed"; return std::nullopt; }