Commit 6075df5b authored by Wan-Teh Chang's avatar Wan-Teh Chang Committed by Commit Bot

Implement our own avifIO reader.

The avifIO reader allows blink::AVIFImageDecoder to support incremental
decoding partially. blink::AVIFImageDecoder still cannot output parts
of a frame incrementally (such as row by row), but for a multi-frame
image, it can output full frames incrementally. In addition, it can
decode image metadata (such as image size and frame count)
incrementally before IsAllDataReceived() becomes true.

Implement the FrameIsReceivedAtIndex() method. Change DecodeFrameCount()
to return increasing frame count as frames are received.

This change requires including avif.h in avif_image_decoder.h. As a
result, forward declarations of libavif types are removed from
avif_image_decoder.h.

TestInvalidStaticImage() needs to call IsSizeAvailable() explicitly
because blink::ImageDecoder::SetData() with all_data_received=true no
longer causes size to be decoded.

Bug: 1136922
Bug: 1148577
Change-Id: I089f34711547f31030a1ea39d1f58f42106582e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2530221
Commit-Queue: Wan-Teh Chang <wtc@google.com>
Reviewed-by: default avatarPeter Kasting <pkasting@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#827569}
parent 2ade52bc
...@@ -8,14 +8,11 @@ ...@@ -8,14 +8,11 @@
#include <memory> #include <memory>
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h" #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/libavif/src/include/avif/avif.h"
#include "third_party/skia/include/core/SkData.h" #include "third_party/skia/include/core/SkImageInfo.h"
#include "ui/gfx/color_space.h" #include "ui/gfx/color_space.h"
#include "ui/gfx/color_transform.h" #include "ui/gfx/color_transform.h"
struct avifDecoder;
struct avifImage;
namespace blink { namespace blink {
class FastSharedBufferReader; class FastSharedBufferReader;
...@@ -42,6 +39,7 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder { ...@@ -42,6 +39,7 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder {
uint8_t GetYUVBitDepth() const override; uint8_t GetYUVBitDepth() const override;
void DecodeToYUV() override; void DecodeToYUV() override;
int RepetitionCount() const override; int RepetitionCount() const override;
bool FrameIsReceivedAtIndex(size_t) const override;
base::TimeDelta FrameDurationAtIndex(size_t) const override; base::TimeDelta FrameDurationAtIndex(size_t) const override;
bool ImageHasBothStillAndAnimatedSubImages() const override; bool ImageHasBothStillAndAnimatedSubImages() const override;
...@@ -52,6 +50,14 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder { ...@@ -52,6 +50,14 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder {
gfx::ColorTransform* GetColorTransformForTesting(); gfx::ColorTransform* GetColorTransformForTesting();
private: private:
struct AvifIOData {
blink::SegmentReader* reader = nullptr;
std::vector<uint8_t> buffer;
bool all_data_received = false;
};
void ParseMetadata();
// ImageDecoder: // ImageDecoder:
void DecodeSize() override; void DecodeSize() override;
size_t DecodeFrameCount() override; size_t DecodeFrameCount() override;
...@@ -59,12 +65,19 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder { ...@@ -59,12 +65,19 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder {
void Decode(size_t) override; void Decode(size_t) override;
bool CanReusePreviousFrameBuffer(size_t) const override; bool CanReusePreviousFrameBuffer(size_t) const override;
// Creates |decoder_| and decodes the size and frame count. // Implements avifIOReadFunc, the |read| function in the avifIO struct.
bool MaybeCreateDemuxer(); static avifResult ReadFromSegmentReader(avifIO* io,
uint32_t read_flags,
uint64_t offset,
size_t size,
avifROData* out);
// Creates |decoder_| if not yet created and decodes the size and frame count.
bool UpdateDemuxer();
// Decodes the frame at index |index|. The decoded frame is available in // Decodes the frame at index |index|. The decoded frame is available in
// decoder_->image. Returns whether decoding completed successfully. // decoder_->image.
bool DecodeImage(size_t index); avifResult DecodeImage(size_t index);
// Updates or creates |color_transform_| for YUV-to-RGB conversion. // Updates or creates |color_transform_| for YUV-to-RGB conversion.
void UpdateColorTransform(const gfx::ColorSpace& frame_cs, int bit_depth); void UpdateColorTransform(const gfx::ColorSpace& frame_cs, int bit_depth);
...@@ -77,24 +90,24 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder { ...@@ -77,24 +90,24 @@ class PLATFORM_EXPORT AVIFImageDecoder final : public ImageDecoder {
// desired. // desired.
void ColorCorrectImage(ImageFrame* buffer); void ColorCorrectImage(ImageFrame* buffer);
bool have_parsed_current_data_ = false;
// The bit depth from the container. // The bit depth from the container.
uint8_t bit_depth_ = 0; uint8_t bit_depth_ = 0;
bool decode_to_half_float_ = false; bool decode_to_half_float_ = false;
// The YUV format from the container. Stores an avifPixelFormat enum value.
// Declared as uint8_t because we can't forward-declare an enum type in C++.
uint8_t avif_yuv_format_ = 0; // AVIF_PIXEL_FORMAT_NONE
uint8_t chroma_shift_x_ = 0; uint8_t chroma_shift_x_ = 0;
uint8_t chroma_shift_y_ = 0; uint8_t chroma_shift_y_ = 0;
// The YUV format from the container.
avifPixelFormat avif_yuv_format_ = AVIF_PIXEL_FORMAT_NONE;
size_t decoded_frame_count_ = 0; size_t decoded_frame_count_ = 0;
SkYUVColorSpace yuv_color_space_ = SkYUVColorSpace::kIdentity_SkYUVColorSpace; SkYUVColorSpace yuv_color_space_ = SkYUVColorSpace::kIdentity_SkYUVColorSpace;
std::unique_ptr<avifDecoder, void (*)(avifDecoder*)> decoder_{nullptr, std::unique_ptr<avifDecoder, void (*)(avifDecoder*)> decoder_{nullptr,
nullptr}; nullptr};
avifIO avif_io_ = {};
AvifIOData avif_io_data_;
std::unique_ptr<gfx::ColorTransform> color_transform_; std::unique_ptr<gfx::ColorTransform> color_transform_;
const AnimationOption animation_option_; const AnimationOption animation_option_;
sk_sp<SkData> image_data_;
}; };
} // namespace blink } // namespace blink
......
...@@ -480,10 +480,12 @@ void TestInvalidStaticImage(const char* avif_file, ErrorPhase error_phase) { ...@@ -480,10 +480,12 @@ void TestInvalidStaticImage(const char* avif_file, ErrorPhase error_phase) {
decoder->SetData(data.get(), true); decoder->SetData(data.get(), true);
if (error_phase == ErrorPhase::kParse) { if (error_phase == ErrorPhase::kParse) {
EXPECT_FALSE(decoder->IsSizeAvailable());
EXPECT_TRUE(decoder->Failed()); EXPECT_TRUE(decoder->Failed());
EXPECT_EQ(0u, decoder->FrameCount()); EXPECT_EQ(0u, decoder->FrameCount());
EXPECT_FALSE(decoder->DecodeFrameBufferAtIndex(0)); EXPECT_FALSE(decoder->DecodeFrameBufferAtIndex(0));
} else { } else {
EXPECT_TRUE(decoder->IsSizeAvailable());
EXPECT_FALSE(decoder->Failed()); EXPECT_FALSE(decoder->Failed());
EXPECT_GT(decoder->FrameCount(), 0u); EXPECT_GT(decoder->FrameCount(), 0u);
ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0); ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment