1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "third_party/blink/renderer/platform/graphics/decoding_image_generator.h"
27 
28 #include <memory>
29 #include <utility>
30 
31 #include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
32 #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
33 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
34 #include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
35 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
36 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
37 #include "third_party/skia/include/core/SkData.h"
38 #include "third_party/skia/include/core/SkImageInfo.h"
39 
40 namespace blink {
41 
42 // static
43 std::unique_ptr<SkImageGenerator>
CreateAsSkImageGenerator(sk_sp<SkData> data)44 DecodingImageGenerator::CreateAsSkImageGenerator(sk_sp<SkData> data) {
45   scoped_refptr<SegmentReader> segment_reader =
46       SegmentReader::CreateFromSkData(std::move(data));
47   // We just need the size of the image, so we have to temporarily create an
48   // ImageDecoder. Since we only need the size, the premul, high bit depth and
49   // gamma settings don't really matter.
50   const bool data_complete = true;
51   std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
52       segment_reader, data_complete, ImageDecoder::kAlphaPremultiplied,
53       ImageDecoder::kDefaultBitDepth, ColorBehavior::Ignore());
54   if (!decoder || !decoder->IsSizeAvailable())
55     return nullptr;
56 
57   const IntSize size = decoder->Size();
58   const SkImageInfo info =
59       SkImageInfo::MakeN32(size.Width(), size.Height(), kPremul_SkAlphaType,
60                            decoder->ColorSpaceForSkImages());
61 
62   scoped_refptr<ImageFrameGenerator> frame = ImageFrameGenerator::Create(
63       SkISize::Make(size.Width(), size.Height()), false,
64       decoder->GetColorBehavior(), decoder->GetSupportedDecodeSizes());
65   if (!frame)
66     return nullptr;
67 
68   WebVector<FrameMetadata> frames;
69   frames.emplace_back(FrameMetadata());
70   cc::ImageHeaderMetadata image_metadata =
71       decoder->MakeMetadataForDecodeAcceleration();
72   image_metadata.all_data_received_prior_to_decode = true;
73   sk_sp<DecodingImageGenerator> generator = DecodingImageGenerator::Create(
74       std::move(frame), info, std::move(segment_reader), std::move(frames),
75       PaintImage::GetNextContentId(), true /* all_data_received */,
76       false /* can_yuv_decode */, image_metadata);
77   return std::make_unique<SkiaPaintImageGenerator>(
78       std::move(generator), PaintImage::kDefaultFrameIndex,
79       PaintImage::kDefaultGeneratorClientId);
80 }
81 
82 // static
Create(scoped_refptr<ImageFrameGenerator> frame_generator,const SkImageInfo & info,scoped_refptr<SegmentReader> data,WebVector<FrameMetadata> frames,PaintImage::ContentId content_id,bool all_data_received,bool can_yuv_decode,const cc::ImageHeaderMetadata & image_metadata)83 sk_sp<DecodingImageGenerator> DecodingImageGenerator::Create(
84     scoped_refptr<ImageFrameGenerator> frame_generator,
85     const SkImageInfo& info,
86     scoped_refptr<SegmentReader> data,
87     WebVector<FrameMetadata> frames,
88     PaintImage::ContentId content_id,
89     bool all_data_received,
90     bool can_yuv_decode,
91     const cc::ImageHeaderMetadata& image_metadata) {
92   return sk_sp<DecodingImageGenerator>(new DecodingImageGenerator(
93       std::move(frame_generator), info, std::move(data), std::move(frames),
94       content_id, all_data_received, can_yuv_decode, image_metadata));
95 }
96 
DecodingImageGenerator(scoped_refptr<ImageFrameGenerator> frame_generator,const SkImageInfo & info,scoped_refptr<SegmentReader> data,WebVector<FrameMetadata> frames,PaintImage::ContentId complete_frame_content_id,bool all_data_received,bool can_yuv_decode,const cc::ImageHeaderMetadata & image_metadata)97 DecodingImageGenerator::DecodingImageGenerator(
98     scoped_refptr<ImageFrameGenerator> frame_generator,
99     const SkImageInfo& info,
100     scoped_refptr<SegmentReader> data,
101     WebVector<FrameMetadata> frames,
102     PaintImage::ContentId complete_frame_content_id,
103     bool all_data_received,
104     bool can_yuv_decode,
105     const cc::ImageHeaderMetadata& image_metadata)
106     : PaintImageGenerator(info, frames.ReleaseVector()),
107       frame_generator_(std::move(frame_generator)),
108       data_(std::move(data)),
109       all_data_received_(all_data_received),
110       can_yuv_decode_(can_yuv_decode),
111       complete_frame_content_id_(complete_frame_content_id),
112       image_metadata_(image_metadata) {}
113 
114 DecodingImageGenerator::~DecodingImageGenerator() = default;
115 
GetEncodedData() const116 sk_sp<SkData> DecodingImageGenerator::GetEncodedData() const {
117   TRACE_EVENT0("blink", "DecodingImageGenerator::refEncodedData");
118 
119   // getAsSkData() may require copying, but the clients of this function are
120   // serializers, which want the data even if it requires copying, and even
121   // if the data is incomplete. (Otherwise they would potentially need to
122   // decode the partial image in order to re-encode it.)
123   return data_->GetAsSkData();
124 }
125 
GetPixels(const SkImageInfo & dst_info,void * pixels,size_t row_bytes,size_t frame_index,PaintImage::GeneratorClientId client_id,uint32_t lazy_pixel_ref)126 bool DecodingImageGenerator::GetPixels(const SkImageInfo& dst_info,
127                                        void* pixels,
128                                        size_t row_bytes,
129                                        size_t frame_index,
130                                        PaintImage::GeneratorClientId client_id,
131                                        uint32_t lazy_pixel_ref) {
132   TRACE_EVENT2("blink", "DecodingImageGenerator::getPixels", "frame index",
133                static_cast<int>(frame_index), "client_id", client_id);
134 
135   // Implementation only supports decoding to a supported size.
136   if (dst_info.dimensions() != GetSupportedDecodeSize(dst_info.dimensions())) {
137     return false;
138   }
139 
140   // Color type can be N32 or F16. Otherwise, decode to N32 and convert to
141   // the requested color type from N32.
142   SkImageInfo target_info = dst_info;
143   char* memory = static_cast<char*>(pixels);
144   std::unique_ptr<char[]> memory_ref_ptr;
145   size_t adjusted_row_bytes = row_bytes;
146   if ((target_info.colorType() != kN32_SkColorType) &&
147       (target_info.colorType() != kRGBA_F16_SkColorType)) {
148     target_info = target_info.makeColorType(kN32_SkColorType);
149     // row_bytes is the size of scanline, so it should be >= info.minRowBytes().
150     DCHECK(row_bytes >= dst_info.minRowBytes());
151     // row_bytes must be a multiple of dst_info.bytesPerPixel().
152     DCHECK_EQ(0ul, row_bytes % dst_info.bytesPerPixel());
153     adjusted_row_bytes =
154         target_info.bytesPerPixel() * (row_bytes / dst_info.bytesPerPixel());
155     memory_ref_ptr.reset(new char[target_info.computeMinByteSize()]);
156     memory = memory_ref_ptr.get();
157   }
158 
159   // Skip the check for alphaType.  blink::ImageFrame may have changed the
160   // owning SkBitmap to kOpaque_SkAlphaType after fully decoding the image
161   // frame, so if we see a request for opaque, that is ok even if our initial
162   // alpha type was not opaque.
163 
164   // Pass decodeColorSpace to the decoder.  That is what we can expect the
165   // output to be.
166   sk_sp<SkColorSpace> decode_color_space = GetSkImageInfo().refColorSpace();
167   SkImageInfo decode_info = target_info.makeColorSpace(decode_color_space);
168 
169   const bool needs_color_xform = !ApproximatelyEqualSkColorSpaces(
170       decode_color_space, target_info.refColorSpace());
171   ImageDecoder::AlphaOption alpha_option = ImageDecoder::kAlphaPremultiplied;
172   if (needs_color_xform && !decode_info.isOpaque()) {
173     alpha_option = ImageDecoder::kAlphaNotPremultiplied;
174     decode_info = decode_info.makeAlphaType(kUnpremul_SkAlphaType);
175   }
176 
177   bool decoded = false;
178   {
179     TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
180                  "Decode LazyPixelRef", "LazyPixelRef", lazy_pixel_ref);
181     decoded = frame_generator_->DecodeAndScale(
182         data_.get(), all_data_received_, frame_index, decode_info, memory,
183         adjusted_row_bytes, alpha_option, client_id);
184   }
185 
186   if (decoded && needs_color_xform) {
187     TRACE_EVENT0("blink", "DecodingImageGenerator::getPixels - apply xform");
188     SkPixmap src(decode_info, memory, adjusted_row_bytes);
189     decoded = src.readPixels(target_info, memory, adjusted_row_bytes);
190     DCHECK(decoded);
191   }
192 
193   // Convert the color type to the requested one if necessary
194   if (decoded && target_info.colorType() != dst_info.colorType()) {
195     // Convert the color type by readPixels if dithering is not necessary
196     // (readPixels is potentially cheaper than a full-blown drawBitmap).
197     if (SkColorTypeBytesPerPixel(target_info.colorType()) <=
198         SkColorTypeBytesPerPixel(dst_info.colorType())) {
199       decoded = SkPixmap{target_info, memory, adjusted_row_bytes}.readPixels(
200           SkPixmap{dst_info, pixels, row_bytes});
201       DCHECK(decoded);
202     } else {  // Do dithering by drawBitmap() if dithering is necessary
203       auto canvas = SkCanvas::MakeRasterDirect(dst_info, pixels, row_bytes);
204       DCHECK(canvas);
205 
206       SkPaint paint;
207       paint.setDither(true);
208       paint.setBlendMode(SkBlendMode::kSrc);
209 
210       SkBitmap bitmap;
211       decoded = bitmap.installPixels(target_info, memory, adjusted_row_bytes);
212       DCHECK(decoded);
213 
214       canvas->drawBitmap(bitmap, 0, 0, &paint);
215     }
216   }
217   return decoded;
218 }
219 
QueryYUVA8(SkYUVASizeInfo * size_info,SkYUVAIndex indices[SkYUVAIndex::kIndexCount],SkYUVColorSpace * color_space) const220 bool DecodingImageGenerator::QueryYUVA8(
221     SkYUVASizeInfo* size_info,
222     SkYUVAIndex indices[SkYUVAIndex::kIndexCount],
223     SkYUVColorSpace* color_space) const {
224   if (!can_yuv_decode_)
225     return false;
226 
227   TRACE_EVENT0("blink", "DecodingImageGenerator::queryYUVA8");
228 
229   // Indicate that we have three separate planes
230   indices[SkYUVAIndex::kY_Index] = {0, SkColorChannel::kR};
231   indices[SkYUVAIndex::kU_Index] = {1, SkColorChannel::kR};
232   indices[SkYUVAIndex::kV_Index] = {2, SkColorChannel::kR};
233   indices[SkYUVAIndex::kA_Index] = {-1, SkColorChannel::kR};
234 
235   DCHECK(all_data_received_);
236   return frame_generator_->GetYUVComponentSizes(data_.get(), size_info,
237                                                 color_space);
238 }
239 
GetYUVA8Planes(const SkYUVASizeInfo & size_info,const SkYUVAIndex indices[4],void * planes[3],size_t frame_index,uint32_t lazy_pixel_ref)240 bool DecodingImageGenerator::GetYUVA8Planes(const SkYUVASizeInfo& size_info,
241                                             const SkYUVAIndex indices[4],
242                                             void* planes[3],
243                                             size_t frame_index,
244                                             uint32_t lazy_pixel_ref) {
245   // TODO(crbug.com/943519): YUV decoding does not currently support incremental
246   // decoding. See comment in image_frame_generator.h.
247   DCHECK(can_yuv_decode_);
248   DCHECK(all_data_received_);
249 
250   TRACE_EVENT0("blink", "DecodingImageGenerator::getYUVA8Planes");
251   TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
252                "Decode LazyPixelRef", "LazyPixelRef", lazy_pixel_ref);
253 
254   // Verify sizes and indices
255   for (int i = 0; i < 3; ++i) {
256     if (size_info.fSizes[i].isEmpty() || !size_info.fWidthBytes[i]) {
257       return false;
258     }
259   }
260   if (!size_info.fSizes[3].isEmpty() || size_info.fWidthBytes[3]) {
261     return false;
262   }
263   int numPlanes;
264   if (!SkYUVAIndex::AreValidIndices(indices, &numPlanes) || numPlanes != 3) {
265     return false;
266   }
267 
268   bool decoded =
269       frame_generator_->DecodeToYUV(data_.get(), frame_index, size_info.fSizes,
270                                     planes, size_info.fWidthBytes);
271   return decoded;
272 }
273 
GetSupportedDecodeSize(const SkISize & requested_size) const274 SkISize DecodingImageGenerator::GetSupportedDecodeSize(
275     const SkISize& requested_size) const {
276   return frame_generator_->GetSupportedDecodeSize(requested_size);
277 }
278 
GetContentIdForFrame(size_t frame_index) const279 PaintImage::ContentId DecodingImageGenerator::GetContentIdForFrame(
280     size_t frame_index) const {
281   DCHECK_LT(frame_index, GetFrameMetadata().size());
282 
283   // If we have all the data for the image, or this particular frame, we can
284   // consider the decoded frame constant.
285   if (all_data_received_ || GetFrameMetadata().at(frame_index).complete)
286     return complete_frame_content_id_;
287 
288   return PaintImageGenerator::GetContentIdForFrame(frame_index);
289 }
290 
291 const cc::ImageHeaderMetadata*
GetMetadataForDecodeAcceleration() const292 DecodingImageGenerator::GetMetadataForDecodeAcceleration() const {
293   return &image_metadata_;
294 }
295 
296 }  // namespace blink
297