Commit 20fd8605 authored by Wan-Teh Chang's avatar Wan-Teh Chang Committed by Commit Bot

Handle multiple incomplete lazy decoded frames

Handle multiple incomplete lazy decoded frames in
DeferredImageDecoder::PrepareLazyDecodedFrames().

This allows blink::ImageDecoder::DecodeFrameCount() to return the true
frame count even when not all frames' encoded data are available.

Change blink::AVIFImageDecoder::DecodeFrameCount() to return the true
frame count.

Change blink::AVIFImageDecoder::FrameIsReceivedAtIndex() to actually
check if the frame's encoded data has been received.

Bug: 1148577
Bug: 1136922
Change-Id: I2423472b406b130fb460cbfe65b5b3890c106344
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2538696
Commit-Queue: Wan-Teh Chang <wtc@google.com>
Reviewed-by: default avatarKhushal <khushalsagar@chromium.org>
Reviewed-by: default avatarPeter Kasting <pkasting@chromium.org>
Reviewed-by: default avatarChris Blume <cblume@chromium.org>
Cr-Commit-Position: refs/heads/master@{#828390}
parent 2a30fbc5
...@@ -440,15 +440,12 @@ void DeferredImageDecoder::PrepareLazyDecodedFrames() { ...@@ -440,15 +440,12 @@ void DeferredImageDecoder::PrepareLazyDecodedFrames() {
frame_data_[i].duration_ = metadata_decoder_->FrameDurationAtIndex(i); frame_data_[i].duration_ = metadata_decoder_->FrameDurationAtIndex(i);
frame_data_[i].orientation_ = metadata_decoder_->Orientation(); frame_data_[i].orientation_ = metadata_decoder_->Orientation();
frame_data_[i].density_corrected_size_ = metadata_decoder_->DensityCorrectedSize(); frame_data_[i].density_corrected_size_ = metadata_decoder_->DensityCorrectedSize();
frame_data_[i].is_received_ = metadata_decoder_->FrameIsReceivedAtIndex(i);
} }
// The last lazy decoded frame created from previous call might be // Update the is_received_ state of incomplete frames.
// incomplete so update its state. while (received_frame_count_ < frame_data_.size() &&
if (previous_size) { metadata_decoder_->FrameIsReceivedAtIndex(received_frame_count_)) {
const size_t last_frame = previous_size - 1; frame_data_[received_frame_count_++].is_received_ = true;
frame_data_[last_frame].is_received_ =
metadata_decoder_->FrameIsReceivedAtIndex(last_frame);
} }
can_yuv_decode_ = can_yuv_decode_ =
......
...@@ -131,6 +131,9 @@ class PLATFORM_EXPORT DeferredImageDecoder final { ...@@ -131,6 +131,9 @@ class PLATFORM_EXPORT DeferredImageDecoder final {
// Caches frame state information. // Caches frame state information.
Vector<DeferredFrameData> frame_data_; Vector<DeferredFrameData> frame_data_;
// The number of received/complete frames in |frame_data_|. Note: This is also
// the index of the first unreceived/incomplete frame in |frame_data_|.
size_t received_frame_count_ = 0;
scoped_refptr<ImageFrameGenerator> frame_generator_; scoped_refptr<ImageFrameGenerator> frame_generator_;
DISALLOW_COPY_AND_ASSIGN(DeferredImageDecoder); DISALLOW_COPY_AND_ASSIGN(DeferredImageDecoder);
......
...@@ -464,11 +464,9 @@ bool AVIFImageDecoder::FrameIsReceivedAtIndex(size_t index) const { ...@@ -464,11 +464,9 @@ bool AVIFImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
return false; return false;
if (decoded_frame_count_ == 1) if (decoded_frame_count_ == 1)
return ImageDecoder::FrameIsReceivedAtIndex(index); return ImageDecoder::FrameIsReceivedAtIndex(index);
// frame_buffer_cache_.size() is equal to the return value of return index < frame_buffer_cache_.size() &&
// DecodeFrameCount(). Since DecodeFrameCount() returns the number of frames (IsAllDataReceived() ||
// whose encoded data have been received, we can return true if |index| is avifDecoderNthImageReady(decoder_.get(), index) == AVIF_RESULT_OK);
// valid for frame_buffer_cache_. See crbug.com/1148577.
return index < frame_buffer_cache_.size();
} }
base::TimeDelta AVIFImageDecoder::FrameDurationAtIndex(size_t index) const { base::TimeDelta AVIFImageDecoder::FrameDurationAtIndex(size_t index) const {
...@@ -530,19 +528,8 @@ void AVIFImageDecoder::DecodeSize() { ...@@ -530,19 +528,8 @@ void AVIFImageDecoder::DecodeSize() {
size_t AVIFImageDecoder::DecodeFrameCount() { size_t AVIFImageDecoder::DecodeFrameCount() {
if (!Failed()) if (!Failed())
ParseMetadata(); ParseMetadata();
if (!IsDecodedSizeAvailable()) return IsDecodedSizeAvailable() ? decoded_frame_count_
return frame_buffer_cache_.size(); : frame_buffer_cache_.size();
if (decoded_frame_count_ == 1 || IsAllDataReceived())
return decoded_frame_count_;
// For a multi-frame image, Chrome expects DecodeFrameCount() to return the
// number of frames whose encoded data have been received.
size_t index;
for (index = frame_buffer_cache_.size(); index < decoded_frame_count_;
++index) {
if (avifDecoderNthImageReady(decoder_.get(), index) != AVIF_RESULT_OK)
break;
}
return index;
} }
void AVIFImageDecoder::InitializeNewFrame(size_t index) { void AVIFImageDecoder::InitializeNewFrame(size_t index) {
......
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