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