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 
UpdateYUVAInfoPlanarConfigAndWidthBytes(ImageDecoder * decoder,SkYUVAInfo::PlanarConfig * config,size_t component_width_bytes[SkYUVAInfo::kMaxPlanes])41 static bool UpdateYUVAInfoPlanarConfigAndWidthBytes(
42     ImageDecoder* decoder,
43     SkYUVAInfo::PlanarConfig* config,
44     size_t component_width_bytes[SkYUVAInfo::kMaxPlanes]) {
45   switch (decoder->GetYUVSubsampling()) {
46     case cc::YUVSubsampling::k410:
47       *config = SkYUVAInfo::PlanarConfig::kY_U_V_410;
48       break;
49     case cc::YUVSubsampling::k411:
50       *config = SkYUVAInfo::PlanarConfig::kY_U_V_411;
51       break;
52     case cc::YUVSubsampling::k420:
53       *config = SkYUVAInfo::PlanarConfig::kY_U_V_420;
54       break;
55     case cc::YUVSubsampling::k422:
56       *config = SkYUVAInfo::PlanarConfig::kY_U_V_422;
57       break;
58     case cc::YUVSubsampling::k440:
59       *config = SkYUVAInfo::PlanarConfig::kY_U_V_440;
60       break;
61     case cc::YUVSubsampling::k444:
62       *config = SkYUVAInfo::PlanarConfig::kY_U_V_444;
63       break;
64     default:
65       return false;
66   }
67   component_width_bytes[0] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kY);
68   component_width_bytes[1] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kU);
69   component_width_bytes[2] = decoder->DecodedYUVWidthBytes(cc::YUVIndex::kV);
70   // TODO(crbug/910276): Alpha plane is currently unsupported.
71   component_width_bytes[3] = 0;
72   return true;
73 }
74 
ImageFrameGenerator(const SkISize & full_size,bool is_multi_frame,const ColorBehavior & color_behavior,Vector<SkISize> supported_sizes)75 ImageFrameGenerator::ImageFrameGenerator(const SkISize& full_size,
76                                          bool is_multi_frame,
77                                          const ColorBehavior& color_behavior,
78                                          Vector<SkISize> supported_sizes)
79     : full_size_(full_size),
80       decoder_color_behavior_(color_behavior),
81       is_multi_frame_(is_multi_frame),
82       supported_sizes_(std::move(supported_sizes)) {
83 #if DCHECK_IS_ON()
84   // Verify that sizes are in an increasing order, since
85   // GetSupportedDecodeSize() depends on it.
86   SkISize last_size = SkISize::MakeEmpty();
87   for (auto& size : supported_sizes_) {
88     DCHECK_GE(size.width(), last_size.width());
89     DCHECK_GE(size.height(), last_size.height());
90   }
91 #endif
92 }
93 
~ImageFrameGenerator()94 ImageFrameGenerator::~ImageFrameGenerator() {
95   // We expect all image decoders to be unlocked and catch with DCHECKs if not.
96   ImageDecodingStore::Instance().RemoveCacheIndexedByGenerator(this);
97 }
98 
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)99 bool ImageFrameGenerator::DecodeAndScale(
100     SegmentReader* data,
101     bool all_data_received,
102     size_t index,
103     const SkImageInfo& info,
104     void* pixels,
105     size_t row_bytes,
106     ImageDecoder::AlphaOption alpha_option,
107     cc::PaintImage::GeneratorClientId client_id) {
108   {
109     MutexLocker lock(generator_mutex_);
110     if (decode_failed_)
111       return false;
112   }
113 
114   TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "generator",
115                this);
116 
117   // This implementation does not support arbitrary scaling so check the
118   // requested size.
119   SkISize scaled_size = SkISize::Make(info.width(), info.height());
120   CHECK(GetSupportedDecodeSize(scaled_size) == scaled_size);
121 
122   ImageDecoder::HighBitDepthDecodingOption high_bit_depth_decoding_option =
123       ImageDecoder::kDefaultBitDepth;
124   if (info.colorType() == kRGBA_F16_SkColorType) {
125     high_bit_depth_decoding_option = ImageDecoder::kHighBitDepthToHalfFloat;
126   }
127 
128   size_t frame_count = 0u;
129   bool has_alpha = true;
130 
131   // |decode_failed| indicates a failure due to a corrupt image.
132   bool decode_failed = false;
133   // |current_decode_succeeded| indicates a failure to decode the current frame.
134   // Its possible to have a valid but fail to decode a frame in the case where
135   // we don't have enough data to decode this particular frame yet.
136   bool current_decode_succeeded = false;
137   {
138     // Lock the mutex, so only one thread can use the decoder at once.
139     ClientMutexLocker lock(this, client_id);
140     ImageDecoderWrapper decoder_wrapper(
141         this, data, scaled_size, alpha_option, decoder_color_behavior_,
142         high_bit_depth_decoding_option, index, info, pixels, row_bytes,
143         all_data_received, client_id);
144     current_decode_succeeded = decoder_wrapper.Decode(
145         image_decoder_factory_.get(), &frame_count, &has_alpha);
146     decode_failed = decoder_wrapper.decode_failed();
147   }
148 
149   MutexLocker lock(generator_mutex_);
150   decode_failed_ = decode_failed;
151   if (decode_failed_) {
152     DCHECK(!current_decode_succeeded);
153     return false;
154   }
155 
156   if (!current_decode_succeeded)
157     return false;
158 
159   SetHasAlpha(index, has_alpha);
160   if (frame_count != 0u)
161     frame_count_ = frame_count;
162 
163   return true;
164 }
165 
DecodeToYUV(SegmentReader * data,size_t index,SkColorType color_type,const SkISize component_sizes[cc::kNumYUVPlanes],void * planes[cc::kNumYUVPlanes],const size_t row_bytes[cc::kNumYUVPlanes])166 bool ImageFrameGenerator::DecodeToYUV(
167     SegmentReader* data,
168     size_t index,
169     SkColorType color_type,
170     const SkISize component_sizes[cc::kNumYUVPlanes],
171     void* planes[cc::kNumYUVPlanes],
172     const size_t row_bytes[cc::kNumYUVPlanes]) {
173   MutexLocker lock(generator_mutex_);
174   DCHECK_EQ(index, 0u);
175 
176   // TODO (scroggo): The only interesting thing this uses from the
177   // ImageFrameGenerator is m_decodeFailed. Move this into
178   // DecodingImageGenerator, which is the only class that calls it.
179   if (decode_failed_ || yuv_decoding_failed_)
180     return false;
181 
182   if (!planes || !planes[0] || !planes[1] || !planes[2] || !row_bytes ||
183       !row_bytes[0] || !row_bytes[1] || !row_bytes[2]) {
184     return false;
185   }
186   const bool all_data_received = true;
187   std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
188       data, all_data_received, ImageDecoder::kAlphaPremultiplied,
189       ImageDecoder::kDefaultBitDepth, decoder_color_behavior_);
190   // getYUVComponentSizes was already called and was successful, so
191   // ImageDecoder::create must succeed.
192   DCHECK(decoder);
193 
194   std::unique_ptr<ImagePlanes> image_planes =
195       std::make_unique<ImagePlanes>(planes, row_bytes, color_type);
196   // TODO(crbug.com/943519): Don't forget to initialize planes to black or
197   // transparent for incremental decoding.
198   decoder->SetImagePlanes(std::move(image_planes));
199 
200   DCHECK(decoder->CanDecodeToYUV());
201 
202   {
203     // This is the YUV analog of ImageFrameGenerator::decode.
204     TRACE_EVENT0("blink,benchmark", "ImageFrameGenerator::decodeToYUV");
205     decoder->DecodeToYUV();
206   }
207 
208   if (!decoder->Failed()) {
209     // TODO(crbug.com/910276): Set this properly for alpha support.
210     SetHasAlpha(index, false);
211     return true;
212   }
213 
214   DCHECK(decoder->Failed());
215   yuv_decoding_failed_ = true;
216   return false;
217 }
218 
SetHasAlpha(size_t index,bool has_alpha)219 void ImageFrameGenerator::SetHasAlpha(size_t index, bool has_alpha) {
220   generator_mutex_.AssertAcquired();
221 
222   if (index >= has_alpha_.size()) {
223     const size_t old_size = has_alpha_.size();
224     has_alpha_.resize(index + 1);
225     for (size_t i = old_size; i < has_alpha_.size(); ++i)
226       has_alpha_[i] = true;
227   }
228   has_alpha_[index] = has_alpha;
229 }
230 
HasAlpha(size_t index)231 bool ImageFrameGenerator::HasAlpha(size_t index) {
232   MutexLocker lock(generator_mutex_);
233 
234   if (index < has_alpha_.size())
235     return has_alpha_[index];
236   return true;
237 }
238 
GetYUVAInfo(SegmentReader * data,const SkYUVAPixmapInfo::SupportedDataTypes & supported_data_types,SkYUVAPixmapInfo * info)239 bool ImageFrameGenerator::GetYUVAInfo(
240     SegmentReader* data,
241     const SkYUVAPixmapInfo::SupportedDataTypes& supported_data_types,
242     SkYUVAPixmapInfo* info) {
243   TRACE_EVENT2("blink", "ImageFrameGenerator::GetYUVAInfo", "width",
244                full_size_.width(), "height", full_size_.height());
245 
246   MutexLocker lock(generator_mutex_);
247 
248   if (yuv_decoding_failed_)
249     return false;
250   std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
251       data, true /* data_complete */, ImageDecoder::kAlphaPremultiplied,
252       ImageDecoder::kDefaultBitDepth, decoder_color_behavior_);
253   DCHECK(decoder);
254 
255   DCHECK(decoder->CanDecodeToYUV());
256   SkYUVAInfo::PlanarConfig config;
257   size_t width_bytes[SkYUVAInfo::kMaxPlanes];
258   if (!UpdateYUVAInfoPlanarConfigAndWidthBytes(decoder.get(), &config,
259                                                width_bytes)) {
260     return false;
261   }
262   SkYUVAInfo yuva_info(full_size_, config, decoder->GetYUVColorSpace());
263   SkYUVAPixmapInfo::DataType dataType;
264   if (decoder->GetYUVBitDepth() > 8) {
265     if (supported_data_types.supported(config,
266                                        SkYUVAPixmapInfo::DataType::kUnorm16)) {
267       dataType = SkYUVAPixmapInfo::DataType::kUnorm16;
268     } else if (supported_data_types.supported(
269                    config, SkYUVAPixmapInfo::DataType::kFloat16)) {
270       dataType = SkYUVAPixmapInfo::DataType::kFloat16;
271     } else {
272       return false;
273     }
274   } else if (supported_data_types.supported(
275                  config, SkYUVAPixmapInfo::DataType::kUnorm8)) {
276     dataType = SkYUVAPixmapInfo::DataType::kUnorm8;
277   } else {
278     return false;
279   }
280   *info = SkYUVAPixmapInfo(yuva_info, dataType, width_bytes);
281   DCHECK(info->isSupported(supported_data_types));
282 
283   return true;
284 }
285 
GetSupportedDecodeSize(const SkISize & requested_size) const286 SkISize ImageFrameGenerator::GetSupportedDecodeSize(
287     const SkISize& requested_size) const {
288   for (auto& size : supported_sizes_) {
289     if (size.width() >= requested_size.width() &&
290         size.height() >= requested_size.height()) {
291       return size;
292     }
293   }
294   return full_size_;
295 }
296 
ClientMutexLocker(ImageFrameGenerator * generator,cc::PaintImage::GeneratorClientId client_id)297 ImageFrameGenerator::ClientMutexLocker::ClientMutexLocker(
298     ImageFrameGenerator* generator,
299     cc::PaintImage::GeneratorClientId client_id)
300     : generator_(generator), client_id_(client_id) {
301   {
302     MutexLocker lock(generator_->generator_mutex_);
303     auto it = generator_->mutex_map_.find(client_id_);
304     ClientMutex* client_mutex;
305     if (it == generator_->mutex_map_.end()) {
306       auto result = generator_->mutex_map_.insert(
307           client_id_, std::make_unique<ClientMutex>());
308       client_mutex = result.stored_value->value.get();
309     } else {
310       client_mutex = it->value.get();
311     }
312     client_mutex->ref_count++;
313     mutex_ = &client_mutex->mutex;
314   }
315 
316   mutex_->lock();
317 }
318 
~ClientMutexLocker()319 ImageFrameGenerator::ClientMutexLocker::~ClientMutexLocker() {
320   mutex_->unlock();
321 
322   MutexLocker lock(generator_->generator_mutex_);
323   auto it = generator_->mutex_map_.find(client_id_);
324   DCHECK(it != generator_->mutex_map_.end());
325   it->value->ref_count--;
326 
327   if (it->value->ref_count == 0)
328     generator_->mutex_map_.erase(it);
329 }
330 
331 }  // namespace blink
332