#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h"
#include <stdint.h>
#include <string.h>
#include <algorithm>
#include <memory>
#include <optional>
#include <utility>
#include "base/bits.h"
#include "base/containers/adapters.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/numerics/safe_conversions.h"
#include "base/timer/elapsed_timer.h"
#include "build/build_config.h"
#include "cc/base/math_util.h"
#include "media/base/video_color_space.h"
#include "skia/ext/cicp.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h"
#include "third_party/blink/renderer/platform/image-decoders/image_animation.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/image-decoders/rw_buffer.h"
#include "third_party/libavif/src/include/avif/avif.h"
#include "third_party/libavifinfo/src/avifinfo.h"
#include "third_party/libyuv/include/libyuv.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkTypes.h"
#include "third_party/skia/include/private/SkXmp.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/icc_profile.h"
#if defined(ARCH_CPU_BIG_ENDIAN)
#error Blink assumes a little-endian target.
#endif
namespace blink {
namespace {
constexpr uint64_t kMaxAvifFileSize = …;
const char* AvifDecoderErrorMessage(const avifDecoder* decoder) { … }
gfx::ColorSpace GetColorSpace(
avifColorPrimaries color_primaries,
avifTransferCharacteristics transfer_characteristics,
avifMatrixCoefficients matrix_coefficients,
avifRange yuv_range,
bool grayscale) { … }
gfx::ColorSpace GetColorSpace(const avifImage* image) { … }
int UVSize(int y_size, int chroma_shift) { … }
scoped_refptr<SegmentReader> CreateGainmapSegmentReader(
const AvifInfoFeatures& features,
const SegmentReader* input) { … }
struct AvifInfoSegmentReaderStream { … };
const uint8_t* AvifInfoSegmentReaderRead(void* void_stream, size_t num_bytes) { … }
void AvifInfoSegmentReaderSkip(void* void_stream, size_t num_bytes) { … }
float FractionToFloat(auto numerator, uint32_t denominator) {
return static_cast<double>(numerator) / denominator;
}
sk_sp<SkColorSpace> GetAltImageColorSpace(const avifImage& image) { … }
}
AVIFImageDecoder::AVIFImageDecoder(AlphaOption alpha_option,
HighBitDepthDecodingOption hbd_option,
ColorBehavior color_behavior,
wtf_size_t max_decoded_bytes,
AnimationOption animation_option)
: … { … }
AVIFImageDecoder::~AVIFImageDecoder() = default;
String AVIFImageDecoder::FilenameExtension() const { … }
const AtomicString& AVIFImageDecoder::MimeType() const { … }
bool AVIFImageDecoder::ImageIsHighBitDepth() { … }
void AVIFImageDecoder::OnSetData(scoped_refptr<SegmentReader> data) { … }
cc::YUVSubsampling AVIFImageDecoder::GetYUVSubsampling() const { … }
gfx::Size AVIFImageDecoder::DecodedYUVSize(cc::YUVIndex index) const { … }
wtf_size_t AVIFImageDecoder::DecodedYUVWidthBytes(cc::YUVIndex index) const { … }
SkYUVColorSpace AVIFImageDecoder::GetYUVColorSpace() const { … }
uint8_t AVIFImageDecoder::GetYUVBitDepth() const { … }
std::optional<gfx::HDRMetadata> AVIFImageDecoder::GetHDRMetadata() const { … }
void AVIFImageDecoder::DecodeToYUV() { … }
int AVIFImageDecoder::RepetitionCount() const { … }
bool AVIFImageDecoder::FrameIsReceivedAtIndex(wtf_size_t index) const { … }
std::optional<base::TimeDelta> AVIFImageDecoder::FrameTimestampAtIndex(
wtf_size_t index) const { … }
base::TimeDelta AVIFImageDecoder::FrameDurationAtIndex(wtf_size_t index) const { … }
bool AVIFImageDecoder::ImageHasBothStillAndAnimatedSubImages() const { … }
bool AVIFImageDecoder::MatchesAVIFSignature(
const FastSharedBufferReader& fast_reader) { … }
gfx::ColorSpace AVIFImageDecoder::GetColorSpaceForTesting() const { … }
void AVIFImageDecoder::ParseMetadata() { … }
void AVIFImageDecoder::DecodeSize() { … }
wtf_size_t AVIFImageDecoder::DecodeFrameCount() { … }
void AVIFImageDecoder::InitializeNewFrame(wtf_size_t index) { … }
void AVIFImageDecoder::Decode(wtf_size_t index) { … }
bool AVIFImageDecoder::CanReusePreviousFrameBuffer(wtf_size_t index) const { … }
avifResult AVIFImageDecoder::ReadFromSegmentReader(avifIO* io,
uint32_t read_flags,
uint64_t offset,
size_t size,
avifROData* out) { … }
bool AVIFImageDecoder::UpdateDemuxer() { … }
avifResult AVIFImageDecoder::DecodeImage(wtf_size_t index) { … }
void AVIFImageDecoder::CropDecodedImage() { … }
bool AVIFImageDecoder::RenderImage(const avifImage* image,
int from_row,
int* to_row,
ImageFrame* buffer) { … }
void AVIFImageDecoder::ColorCorrectImage(int from_row,
int to_row,
ImageFrame* buffer) { … }
bool AVIFImageDecoder::GetGainmapInfoAndData(
SkGainmapInfo& out_gainmap_info,
scoped_refptr<SegmentReader>& out_gainmap_data) const { … }
AVIFImageDecoder::AvifIOData::AvifIOData() = default;
AVIFImageDecoder::AvifIOData::AvifIOData(
scoped_refptr<const SegmentReader> reader,
bool all_data_received)
: … { … }
AVIFImageDecoder::AvifIOData::~AvifIOData() = default;
}