Coverage Report

Created: 2026-06-07 07:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibMedia/Video/VP8/Decoder.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2026, Nico Weber <thakis@chromium.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <LibGfx/ImageFormats/WebPLoaderLossy.h>
8
#include <LibGfx/Painter.h>
9
10
#include "Decoder.h"
11
12
#if defined(AK_COMPILER_GCC)
13
#    pragma GCC optimize("O3")
14
#endif
15
16
namespace Media::Video::VP8 {
17
18
DecoderErrorOr<void> BitmapVideoFrame::output_to_bitmap(Gfx::Bitmap& bitmap)
19
0
{
20
    // FIXME: This is a wasteful copy, see class-level FIXME.
21
0
    Gfx::Painter painter(bitmap);
22
0
    painter.blit({ 0, 0 }, *m_bitmap, m_bitmap->rect());
23
0
    return {};
24
0
}
25
26
Decoder::Decoder()
27
0
{
28
0
}
29
30
Decoder::~Decoder()
31
0
{
32
0
}
33
34
DecoderErrorOr<void> Decoder::receive_sample(Duration timestamp, ReadonlyBytes data)
35
0
{
36
0
    NonnullRefPtr<Gfx::Bitmap> bitmap = DECODER_TRY(DecoderErrorCategory::Invalid, [&] -> ErrorOr<NonnullRefPtr<Gfx::Bitmap>> {
37
0
        auto header = TRY(Gfx::decode_webp_chunk_VP8_header(data));
38
0
        if (!header.keyframe_data.has_value()) {
39
0
            if (!m_last_keyframe)
40
0
                return Error::from_string_literal("VP8: non-keyframe without previous keyframe");
41
42
            // For now, replace non-keyframes with the last keyframe.
43
            // FIXME: Add support for decoding non-keyframes.
44
0
            return *m_last_keyframe;
45
0
        }
46
47
0
        auto bitmap = TRY(Gfx::decode_webp_chunk_VP8_contents(header, false));
48
0
        m_last_keyframe = bitmap;
49
0
        return bitmap;
50
0
    }());
51
52
    // These values are only used by SubsampledYUVFrame::output_to_bitmap() as far as I can tell.
53
    // Since we don't currently use SubsampledYUVFrame, exact values here don't currently matter.
54
0
    CodingIndependentCodePoints cicp(ColorPrimaries::BT601, TransferCharacteristics::SRGB, MatrixCoefficients::BT601, VideoFullRangeFlag::Studio);
55
0
    auto video_frame = make<BitmapVideoFrame>(timestamp, Gfx::Size<u32>(bitmap->width(), bitmap->height()), 8, cicp, bitmap);
56
0
    m_video_frame_queue.enqueue(move(video_frame));
57
58
0
    return {};
59
0
}
60
61
DecoderErrorOr<NonnullOwnPtr<VideoFrame>> Decoder::get_decoded_frame()
62
0
{
63
0
    if (m_video_frame_queue.is_empty())
64
0
        return DecoderError::format(DecoderErrorCategory::NeedsMoreInput, "No video frame in queue.");
65
66
0
    return m_video_frame_queue.dequeue();
67
0
}
68
69
void Decoder::flush()
70
0
{
71
0
    m_video_frame_queue.clear();
72
0
}
73
74
}