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 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
27
28 #include <memory>
29 #include <utility>
30
31 #include "base/macros.h"
32 #include "third_party/blink/renderer/platform/graphics/image_decoder_wrapper.h"
33 #include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
34 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
35 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
36 #include "third_party/skia/include/core/SkData.h"
37 #include "third_party/skia/include/core/SkYUVASizeInfo.h"
38
39 namespace blink {
40
UpdateYUVComponentSizes(ImageDecoder * decoder,SkISize component_sizes[4],size_t component_width_bytes[4])41 static bool UpdateYUVComponentSizes(ImageDecoder* decoder,
42 SkISize component_sizes[4],
43 size_t component_width_bytes[4]) {
44 DCHECK(decoder->CanDecodeToYUV());
45 // Initialize sizes for decoder if not already set.
46 bool size_available = decoder->IsSizeAvailable();
47 DCHECK(size_available);
48
49 for (int yuv_index = 0; yuv_index < 3; ++yuv_index) {
50 IntSize size = decoder->DecodedYUVSize(yuv_index);
51 component_sizes[yuv_index].set(size.Width(), size.Height());
52 component_width_bytes[yuv_index] = decoder->DecodedYUVWidthBytes(yuv_index);
53 }
54 // TODO(crbug/910276): Alpha plane is currently unsupported.
55 component_sizes[3] = SkISize::MakeEmpty();
56 component_width_bytes[3] = 0;
57
58 return true;
59 }
60
ImageFrameGenerator(const SkISize & full_size,bool is_multi_frame,const ColorBehavior & color_behavior,Vector<SkISize> supported_sizes)61 ImageFrameGenerator::ImageFrameGenerator(const SkISize& full_size,
62 bool is_multi_frame,
63 const ColorBehavior& color_behavior,
64 Vector<SkISize> supported_sizes)
65 : full_size_(full_size),
66 decoder_color_behavior_(color_behavior),
67 is_multi_frame_(is_multi_frame),
68 supported_sizes_(std::move(supported_sizes)) {
69 #if DCHECK_IS_ON()
70 // Verify that sizes are in an increasing order, since
71 // GetSupportedDecodeSize() depends on it.
72 SkISize last_size = SkISize::MakeEmpty();
73 for (auto& size : supported_sizes_) {
74 DCHECK_GE(size.width(), last_size.width());
75 DCHECK_GE(size.height(), last_size.height());
76 }
77 #endif
78 }
79
~ImageFrameGenerator()80 ImageFrameGenerator::~ImageFrameGenerator() {
81 // We expect all image decoders to be unlocked and catch with DCHECKs if not.
82 ImageDecodingStore::Instance().RemoveCacheIndexedByGenerator(this);
83 }
84
DecodeAndScale(SegmentReader * data,bool all_data_received,size_t index,const SkImageInfo & info,void * pixels,size_t row_bytes,ImageDecoder::AlphaOption alpha_option,cc::PaintImage::GeneratorClientId client_id)85 bool ImageFrameGenerator::DecodeAndScale(
86 SegmentReader* data,
87 bool all_data_received,
88 size_t index,
89 const SkImageInfo& info,
90 void* pixels,
91 size_t row_bytes,
92 ImageDecoder::AlphaOption alpha_option,
93 cc::PaintImage::GeneratorClientId client_id) {
94 {
95 MutexLocker lock(generator_mutex_);
96 if (decode_failed_)
97 return false;
98 }
99
100 TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "generator",
101 this);
102
103 // This implementation does not support arbitrary scaling so check the
104 // requested size.
105 SkISize scaled_size = SkISize::Make(info.width(), info.height());
106 CHECK(GetSupportedDecodeSize(scaled_size) == scaled_size);
107
108 ImageDecoder::HighBitDepthDecodingOption high_bit_depth_decoding_option =
109 ImageDecoder::kDefaultBitDepth;
110 if (info.colorType() == kRGBA_F16_SkColorType) {
111 high_bit_depth_decoding_option = ImageDecoder::kHighBitDepthToHalfFloat;
112 }
113
114 size_t frame_count = 0u;
115 bool has_alpha = true;
116
117 // |decode_failed| indicates a failure due to a corrupt image.
118 bool decode_failed = false;
119 // |current_decode_succeeded| indicates a failure to decode the current frame.
120 // Its possible to have a valid but fail to decode a frame in the case where
121 // we don't have enough data to decode this particular frame yet.
122 bool current_decode_succeeded = false;
123 {
124 // Lock the mutex, so only one thread can use the decoder at once.
125 ClientMutexLocker lock(this, client_id);
126 ImageDecoderWrapper decoder_wrapper(
127 this, data, scaled_size, alpha_option, decoder_color_behavior_,
128 high_bit_depth_decoding_option, index, info, pixels, row_bytes,
129 all_data_received, client_id);
130 current_decode_succeeded = decoder_wrapper.Decode(
131 image_decoder_factory_.get(), &frame_count, &has_alpha);
132 decode_failed = decoder_wrapper.decode_failed();
133 }
134
135 MutexLocker lock(generator_mutex_);
136 decode_failed_ = decode_failed;
137 if (decode_failed_) {
138 DCHECK(!current_decode_succeeded);
139 return false;
140 }
141
142 if (!current_decode_succeeded)
143 return false;
144
145 SetHasAlpha(index, has_alpha);
146 if (frame_count != 0u)
147 frame_count_ = frame_count;
148
149 return true;
150 }
151
DecodeToYUV(SegmentReader * data,size_t index,const SkISize component_sizes[3],void * planes[3],const size_t row_bytes[3])152 bool ImageFrameGenerator::DecodeToYUV(SegmentReader* data,
153 size_t index,
154 const SkISize component_sizes[3],
155 void* planes[3],
156 const size_t row_bytes[3]) {
157 MutexLocker lock(generator_mutex_);
158 DCHECK_EQ(index, 0u);
159
160 // TODO (scroggo): The only interesting thing this uses from the
161 // ImageFrameGenerator is m_decodeFailed. Move this into
162 // DecodingImageGenerator, which is the only class that calls it.
163 if (decode_failed_ || yuv_decoding_failed_)
164 return false;
165
166 if (!planes || !planes[0] || !planes[1] || !planes[2] || !row_bytes ||
167 !row_bytes[0] || !row_bytes[1] || !row_bytes[2]) {
168 return false;
169 }
170 const bool all_data_received = true;
171 std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
172 data, all_data_received, ImageDecoder::kAlphaPremultiplied,
173 ImageDecoder::kDefaultBitDepth, decoder_color_behavior_);
174 // getYUVComponentSizes was already called and was successful, so
175 // ImageDecoder::create must succeed.
176 DCHECK(decoder);
177
178 std::unique_ptr<ImagePlanes> image_planes =
179 std::make_unique<ImagePlanes>(planes, row_bytes);
180 // TODO(crbug.com/943519): Don't forget to initialize planes to black or
181 // transparent for incremental decoding.
182 decoder->SetImagePlanes(std::move(image_planes));
183
184 DCHECK(decoder->CanDecodeToYUV());
185
186 {
187 // This is the YUV analog of ImageFrameGenerator::decode.
188 TRACE_EVENT0("blink,benchmark", "ImageFrameGenerator::decodeToYUV");
189 decoder->DecodeToYUV();
190 }
191
192 if (!decoder->Failed()) {
193 // TODO(crbug.com/910276): Set this properly for alpha support.
194 SetHasAlpha(index, false);
195 return true;
196 }
197
198 DCHECK(decoder->Failed());
199 yuv_decoding_failed_ = true;
200 return false;
201 }
202
SetHasAlpha(size_t index,bool has_alpha)203 void ImageFrameGenerator::SetHasAlpha(size_t index, bool has_alpha) {
204 generator_mutex_.AssertAcquired();
205
206 if (index >= has_alpha_.size()) {
207 const size_t old_size = has_alpha_.size();
208 has_alpha_.resize(index + 1);
209 for (size_t i = old_size; i < has_alpha_.size(); ++i)
210 has_alpha_[i] = true;
211 }
212 has_alpha_[index] = has_alpha;
213 }
214
HasAlpha(size_t index)215 bool ImageFrameGenerator::HasAlpha(size_t index) {
216 MutexLocker lock(generator_mutex_);
217
218 if (index < has_alpha_.size())
219 return has_alpha_[index];
220 return true;
221 }
222
GetYUVComponentSizes(SegmentReader * data,SkYUVASizeInfo * size_info,SkYUVColorSpace * yuv_color_space)223 bool ImageFrameGenerator::GetYUVComponentSizes(
224 SegmentReader* data,
225 SkYUVASizeInfo* size_info,
226 SkYUVColorSpace* yuv_color_space) {
227 TRACE_EVENT2("blink", "ImageFrameGenerator::getYUVComponentSizes", "width",
228 full_size_.width(), "height", full_size_.height());
229
230 MutexLocker lock(generator_mutex_);
231
232 if (yuv_decoding_failed_)
233 return false;
234 std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
235 data, true /* data_complete */, ImageDecoder::kAlphaPremultiplied,
236 ImageDecoder::kDefaultBitDepth, decoder_color_behavior_);
237 DCHECK(decoder);
238
239 DCHECK(decoder->CanDecodeToYUV());
240 *yuv_color_space = decoder->GetYUVColorSpace();
241
242 return UpdateYUVComponentSizes(decoder.get(), size_info->fSizes,
243 size_info->fWidthBytes);
244 }
245
GetSupportedDecodeSize(const SkISize & requested_size) const246 SkISize ImageFrameGenerator::GetSupportedDecodeSize(
247 const SkISize& requested_size) const {
248 for (auto& size : supported_sizes_) {
249 if (size.width() >= requested_size.width() &&
250 size.height() >= requested_size.height()) {
251 return size;
252 }
253 }
254 return full_size_;
255 }
256
ClientMutexLocker(ImageFrameGenerator * generator,cc::PaintImage::GeneratorClientId client_id)257 ImageFrameGenerator::ClientMutexLocker::ClientMutexLocker(
258 ImageFrameGenerator* generator,
259 cc::PaintImage::GeneratorClientId client_id)
260 : generator_(generator), client_id_(client_id) {
261 {
262 MutexLocker lock(generator_->generator_mutex_);
263 auto it = generator_->mutex_map_.find(client_id_);
264 ClientMutex* client_mutex;
265 if (it == generator_->mutex_map_.end()) {
266 auto result = generator_->mutex_map_.insert(
267 client_id_, std::make_unique<ClientMutex>());
268 client_mutex = result.stored_value->value.get();
269 } else {
270 client_mutex = it->value.get();
271 }
272 client_mutex->ref_count++;
273 mutex_ = &client_mutex->mutex;
274 }
275
276 mutex_->lock();
277 }
278
~ClientMutexLocker()279 ImageFrameGenerator::ClientMutexLocker::~ClientMutexLocker() {
280 mutex_->unlock();
281
282 MutexLocker lock(generator_->generator_mutex_);
283 auto it = generator_->mutex_map_.find(client_id_);
284 DCHECK(it != generator_->mutex_map_.end());
285 it->value->ref_count--;
286
287 if (it->value->ref_count == 0)
288 generator_->mutex_map_.erase(it);
289 }
290
291 } // namespace blink
292