blob: 3a8baa8ce3faa84ce94f600b71061cc7f8000279 [file] [log] [blame]
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/platform/graphics/decoding_image_generator.h"
#include <utility>
#include <memory>
#include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
#include "third_party/blink/renderer/platform/instrumentation/platform_instrumentation.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/skia/include/core/SkData.h"
namespace blink {
// static
std::unique_ptr<SkImageGenerator>
DecodingImageGenerator::CreateAsSkImageGenerator(sk_sp<SkData> data) {
scoped_refptr<SegmentReader> segment_reader =
SegmentReader::CreateFromSkData(std::move(data));
// We just need the size of the image, so we have to temporarily create an
// ImageDecoder. Since we only need the size, the premul and gamma settings
// don't really matter.
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
segment_reader, true, ImageDecoder::kAlphaPremultiplied,
ColorBehavior::TransformToSRGB());
if (!decoder || !decoder->IsSizeAvailable())
return nullptr;
const IntSize size = decoder->Size();
const SkImageInfo info =
SkImageInfo::MakeN32(size.Width(), size.Height(), kPremul_SkAlphaType,
decoder->ColorSpaceForSkImages());
scoped_refptr<ImageFrameGenerator> frame = ImageFrameGenerator::Create(
SkISize::Make(size.Width(), size.Height()), false,
decoder->GetColorBehavior(), decoder->GetSupportedDecodeSizes());
if (!frame)
return nullptr;
std::vector<FrameMetadata> frames = {FrameMetadata()};
sk_sp<DecodingImageGenerator> generator = DecodingImageGenerator::Create(
std::move(frame), info, std::move(segment_reader), std::move(frames),
PaintImage::GetNextContentId(), true);
return std::make_unique<SkiaPaintImageGenerator>(
std::move(generator), PaintImage::kDefaultFrameIndex);
}
// static
sk_sp<DecodingImageGenerator> DecodingImageGenerator::Create(
scoped_refptr<ImageFrameGenerator> frame_generator,
const SkImageInfo& info,
scoped_refptr<SegmentReader> data,
std::vector<FrameMetadata> frames,
PaintImage::ContentId content_id,
bool all_data_received) {
return sk_sp<DecodingImageGenerator>(new DecodingImageGenerator(
std::move(frame_generator), info, std::move(data), std::move(frames),
content_id, all_data_received));
}
DecodingImageGenerator::DecodingImageGenerator(
scoped_refptr<ImageFrameGenerator> frame_generator,
const SkImageInfo& info,
scoped_refptr<SegmentReader> data,
std::vector<FrameMetadata> frames,
PaintImage::ContentId complete_frame_content_id,
bool all_data_received)
: PaintImageGenerator(info, std::move(frames)),
frame_generator_(std::move(frame_generator)),
data_(std::move(data)),
all_data_received_(all_data_received),
can_yuv_decode_(false),
complete_frame_content_id_(complete_frame_content_id) {}
DecodingImageGenerator::~DecodingImageGenerator() = default;
sk_sp<SkData> DecodingImageGenerator::GetEncodedData() const {
TRACE_EVENT0("blink", "DecodingImageGenerator::refEncodedData");
// getAsSkData() may require copying, but the clients of this function are
// serializers, which want the data even if it requires copying, and even
// if the data is incomplete. (Otherwise they would potentially need to
// decode the partial image in order to re-encode it.)
return data_->GetAsSkData();
}
bool DecodingImageGenerator::GetPixels(const SkImageInfo& dst_info,
void* pixels,
size_t row_bytes,
size_t frame_index,
uint32_t lazy_pixel_ref) {
TRACE_EVENT1("blink", "DecodingImageGenerator::getPixels", "frame index",
static_cast<int>(frame_index));
// Implementation only supports decoding to a supported size.
if (dst_info.dimensions() != GetSupportedDecodeSize(dst_info.dimensions())) {
return false;
}
// TODO(vmpstr): We could do the color type conversion here by getting N32
// colortype decode first, and then converting to whatever was requested.
if (dst_info.colorType() != kN32_SkColorType) {
return false;
}
// Skip the check for alphaType. blink::ImageFrame may have changed the
// owning SkBitmap to kOpaque_SkAlphaType after fully decoding the image
// frame, so if we see a request for opaque, that is ok even if our initial
// alpha type was not opaque.
// Pass decodeColorSpace to the decoder. That is what we can expect the
// output to be.
SkColorSpace* decode_color_space = GetSkImageInfo().colorSpace();
SkImageInfo decode_info =
dst_info.makeColorSpace(sk_ref_sp(decode_color_space));
const bool needs_color_xform =
decode_color_space && dst_info.colorSpace() &&
!SkColorSpace::Equals(decode_color_space, dst_info.colorSpace());
ImageDecoder::AlphaOption alpha_option = ImageDecoder::kAlphaPremultiplied;
if (needs_color_xform && !decode_info.isOpaque()) {
alpha_option = ImageDecoder::kAlphaNotPremultiplied;
decode_info = decode_info.makeAlphaType(kUnpremul_SkAlphaType);
}
PlatformInstrumentation::WillDecodeLazyPixelRef(lazy_pixel_ref);
const bool decoded = frame_generator_->DecodeAndScale(
data_.get(), all_data_received_, frame_index, decode_info, pixels,
row_bytes, alpha_option);
PlatformInstrumentation::DidDecodeLazyPixelRef();
if (decoded && needs_color_xform) {
TRACE_EVENT0("blink", "DecodingImageGenerator::getPixels - apply xform");
SkPixmap src(decode_info, pixels, row_bytes);
// kIgnore ensures that we perform the premultiply (if necessary) in the dst
// space.
const bool converted = src.readPixels(dst_info, pixels, row_bytes, 0, 0,
SkTransferFunctionBehavior::kIgnore);
DCHECK(converted);
}
return decoded;
}
bool DecodingImageGenerator::QueryYUV8(SkYUVSizeInfo* size_info,
SkYUVColorSpace* color_space) const {
// YUV decoding does not currently support progressive decoding. See comment
// in ImageFrameGenerator.h.
if (!can_yuv_decode_ || !all_data_received_)
return false;
TRACE_EVENT0("blink", "DecodingImageGenerator::queryYUV8");
if (color_space)
*color_space = kJPEG_SkYUVColorSpace;
return frame_generator_->GetYUVComponentSizes(data_.get(), size_info);
}
bool DecodingImageGenerator::GetYUV8Planes(const SkYUVSizeInfo& size_info,
void* planes[3],
size_t frame_index,
uint32_t lazy_pixel_ref) {
// YUV decoding does not currently support progressive decoding. See comment
// in ImageFrameGenerator.h.
DCHECK(can_yuv_decode_);
DCHECK(all_data_received_);
TRACE_EVENT0("blink", "DecodingImageGenerator::getYUV8Planes");
PlatformInstrumentation::WillDecodeLazyPixelRef(lazy_pixel_ref);
bool decoded =
frame_generator_->DecodeToYUV(data_.get(), frame_index, size_info.fSizes,
planes, size_info.fWidthBytes);
PlatformInstrumentation::DidDecodeLazyPixelRef();
return decoded;
}
SkISize DecodingImageGenerator::GetSupportedDecodeSize(
const SkISize& requested_size) const {
return frame_generator_->GetSupportedDecodeSize(requested_size);
}
PaintImage::ContentId DecodingImageGenerator::GetContentIdForFrame(
size_t frame_index) const {
DCHECK_LT(frame_index, GetFrameMetadata().size());
// If we have all the data for the image, or this particular frame, we can
// consider the decoded frame constant.
if (all_data_received_ || GetFrameMetadata().at(frame_index).complete)
return complete_frame_content_id_;
return PaintImageGenerator::GetContentIdForFrame(frame_index);
}
} // namespace blink