OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/media/skcanvas_video_renderer.h" | 5 #include "webkit/media/skcanvas_video_renderer.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "media/base/video_frame.h" | 8 #include "media/base/video_frame.h" |
9 #include "media/base/yuv_convert.h" | 9 #include "media/base/yuv_convert.h" |
10 #include "third_party/skia/include/core/SkCanvas.h" | 10 #include "third_party/skia/include/core/SkCanvas.h" |
11 #include "third_party/skia/include/core/SkDevice.h" | 11 #include "third_party/skia/include/core/SkDevice.h" |
12 | 12 |
13 namespace webkit_media { | 13 namespace webkit_media { |
14 | 14 |
| 15 static bool IsEitherYV12OrYV16(media::VideoFrame::Format format) { |
| 16 return format == media::VideoFrame::YV12 || format == media::VideoFrame::YV16; |
| 17 } |
| 18 |
| 19 static bool IsEitherYV12OrYV16OrNative(media::VideoFrame::Format format) { |
| 20 return IsEitherYV12OrYV16(format) || |
| 21 format == media::VideoFrame::NATIVE_TEXTURE; |
| 22 } |
| 23 |
15 // CanFastPaint is a helper method to determine the conditions for fast | 24 // CanFastPaint is a helper method to determine the conditions for fast |
16 // painting. The conditions are: | 25 // painting. The conditions are: |
17 // 1. No skew in canvas matrix. | 26 // 1. No skew in canvas matrix. |
18 // 2. No flipping nor mirroring. | 27 // 2. No flipping nor mirroring. |
19 // 3. Canvas has pixel format ARGB8888. | 28 // 3. Canvas has pixel format ARGB8888. |
20 // 4. Canvas is opaque. | 29 // 4. Canvas is opaque. |
| 30 // 5. Frame format is YV12 or YV16. |
21 // | 31 // |
22 // TODO(hclam): The fast paint method should support flipping and mirroring. | 32 // TODO(hclam): The fast paint method should support flipping and mirroring. |
23 // Disable the flipping and mirroring checks once we have it. | 33 // Disable the flipping and mirroring checks once we have it. |
24 static bool CanFastPaint(SkCanvas* canvas, const gfx::Rect& dest_rect, | 34 static bool CanFastPaint(SkCanvas* canvas, const gfx::Rect& dest_rect, |
25 uint8_t alpha) { | 35 uint8_t alpha, media::VideoFrame::Format format) { |
26 if (alpha != 0xFF) { | 36 if (alpha != 0xFF || !IsEitherYV12OrYV16(format)) |
27 return false; | 37 return false; |
28 } | |
29 | 38 |
30 const SkMatrix& total_matrix = canvas->getTotalMatrix(); | 39 const SkMatrix& total_matrix = canvas->getTotalMatrix(); |
31 // Perform the following checks here: | 40 // Perform the following checks here: |
32 // 1. Check for skewing factors of the transformation matrix. They should be | 41 // 1. Check for skewing factors of the transformation matrix. They should be |
33 // zero. | 42 // zero. |
34 // 2. Check for mirroring and flipping. Make sure they are greater than zero. | 43 // 2. Check for mirroring and flipping. Make sure they are greater than zero. |
35 if (SkScalarNearlyZero(total_matrix.getSkewX()) && | 44 if (SkScalarNearlyZero(total_matrix.getSkewX()) && |
36 SkScalarNearlyZero(total_matrix.getSkewY()) && | 45 SkScalarNearlyZero(total_matrix.getSkewY()) && |
37 total_matrix.getScaleX() > 0 && | 46 total_matrix.getScaleX() > 0 && |
38 total_matrix.getScaleY() > 0) { | 47 total_matrix.getScaleY() > 0) { |
39 SkDevice* device = canvas->getDevice(); | 48 SkDevice* device = canvas->getDevice(); |
40 const SkBitmap::Config config = device->config(); | 49 const SkBitmap::Config config = device->config(); |
41 | 50 |
42 if (config == SkBitmap::kARGB_8888_Config && device->isOpaque()) { | 51 if (config == SkBitmap::kARGB_8888_Config && device->isOpaque()) { |
43 return true; | 52 return true; |
44 } | 53 } |
45 } | 54 } |
46 | 55 |
47 return false; | 56 return false; |
48 } | 57 } |
49 | 58 |
50 static bool IsEitherYV12OrYV16(media::VideoFrame::Format format) { | |
51 return format == media::VideoFrame::YV12 || format == media::VideoFrame::YV16; | |
52 } | |
53 | |
54 // Fast paint does YUV => RGB, scaling, blitting all in one step into the | 59 // Fast paint does YUV => RGB, scaling, blitting all in one step into the |
55 // canvas. It's not always safe and appropriate to perform fast paint. | 60 // canvas. It's not always safe and appropriate to perform fast paint. |
56 // CanFastPaint() is used to determine the conditions. | 61 // CanFastPaint() is used to determine the conditions. |
57 static void FastPaint( | 62 static void FastPaint( |
58 const scoped_refptr<media::VideoFrame>& video_frame, | 63 const scoped_refptr<media::VideoFrame>& video_frame, |
59 SkCanvas* canvas, | 64 SkCanvas* canvas, |
60 const gfx::Rect& dest_rect) { | 65 const gfx::Rect& dest_rect) { |
61 DCHECK(IsEitherYV12OrYV16(video_frame->format())) << video_frame->format(); | 66 DCHECK(IsEitherYV12OrYV16(video_frame->format())) << video_frame->format(); |
62 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), | 67 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), |
63 video_frame->stride(media::VideoFrame::kVPlane)); | 68 video_frame->stride(media::VideoFrame::kVPlane)); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 media::FILTER_BILINEAR); | 163 media::FILTER_BILINEAR); |
159 bitmap.unlockPixels(); | 164 bitmap.unlockPixels(); |
160 } | 165 } |
161 | 166 |
162 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data. | 167 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data. |
163 // | 168 // |
164 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|. | 169 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|. |
165 static void ConvertVideoFrameToBitmap( | 170 static void ConvertVideoFrameToBitmap( |
166 const scoped_refptr<media::VideoFrame>& video_frame, | 171 const scoped_refptr<media::VideoFrame>& video_frame, |
167 SkBitmap* bitmap) { | 172 SkBitmap* bitmap) { |
168 DCHECK(IsEitherYV12OrYV16(video_frame->format())) << video_frame->format(); | 173 DCHECK(IsEitherYV12OrYV16OrNative(video_frame->format())) |
169 DCHECK(video_frame->stride(media::VideoFrame::kUPlane) == | 174 << video_frame->format(); |
170 video_frame->stride(media::VideoFrame::kVPlane)); | 175 if (IsEitherYV12OrYV16(video_frame->format())) { |
| 176 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), |
| 177 video_frame->stride(media::VideoFrame::kVPlane)); |
| 178 } |
171 | 179 |
172 // Check if |bitmap| needs to be (re)allocated. | 180 // Check if |bitmap| needs to be (re)allocated. |
173 if (bitmap->isNull() || | 181 if (bitmap->isNull() || |
174 bitmap->width() != video_frame->data_size().width() || | 182 bitmap->width() != video_frame->data_size().width() || |
175 bitmap->height() != video_frame->data_size().height()) { | 183 bitmap->height() != video_frame->data_size().height()) { |
176 bitmap->setConfig(SkBitmap::kARGB_8888_Config, | 184 bitmap->setConfig(SkBitmap::kARGB_8888_Config, |
177 video_frame->data_size().width(), | 185 video_frame->data_size().width(), |
178 video_frame->data_size().height()); | 186 video_frame->data_size().height()); |
179 bitmap->allocPixels(); | 187 bitmap->allocPixels(); |
180 bitmap->setIsVolatile(true); | 188 bitmap->setIsVolatile(true); |
181 } | 189 } |
182 | 190 |
183 bitmap->lockPixels(); | 191 bitmap->lockPixels(); |
184 media::YUVType yuv_type = | 192 if (IsEitherYV12OrYV16(video_frame->format())) { |
185 (video_frame->format() == media::VideoFrame::YV12) ? | 193 media::YUVType yuv_type = |
186 media::YV12 : media::YV16; | 194 (video_frame->format() == media::VideoFrame::YV12) ? |
187 media::ConvertYUVToRGB32(video_frame->data(media::VideoFrame::kYPlane), | 195 media::YV12 : media::YV16; |
188 video_frame->data(media::VideoFrame::kUPlane), | 196 media::ConvertYUVToRGB32(video_frame->data(media::VideoFrame::kYPlane), |
189 video_frame->data(media::VideoFrame::kVPlane), | 197 video_frame->data(media::VideoFrame::kUPlane), |
190 static_cast<uint8*>(bitmap->getPixels()), | 198 video_frame->data(media::VideoFrame::kVPlane), |
191 video_frame->data_size().width(), | 199 static_cast<uint8*>(bitmap->getPixels()), |
192 video_frame->data_size().height(), | 200 video_frame->data_size().width(), |
193 video_frame->stride(media::VideoFrame::kYPlane), | 201 video_frame->data_size().height(), |
194 video_frame->stride(media::VideoFrame::kUPlane), | 202 video_frame->stride(media::VideoFrame::kYPlane), |
195 bitmap->rowBytes(), | 203 video_frame->stride(media::VideoFrame::kUPlane), |
196 yuv_type); | 204 bitmap->rowBytes(), |
| 205 yuv_type); |
| 206 } else { |
| 207 DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE); |
| 208 video_frame->ReadPixelsFromNativeTexture(bitmap->getPixels()); |
| 209 } |
197 bitmap->notifyPixelsChanged(); | 210 bitmap->notifyPixelsChanged(); |
198 bitmap->unlockPixels(); | 211 bitmap->unlockPixels(); |
199 } | 212 } |
200 | 213 |
201 SkCanvasVideoRenderer::SkCanvasVideoRenderer() | 214 SkCanvasVideoRenderer::SkCanvasVideoRenderer() |
202 : last_frame_timestamp_(media::kNoTimestamp()) { | 215 : last_frame_timestamp_(media::kNoTimestamp()) { |
203 } | 216 } |
204 | 217 |
205 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} | 218 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} |
206 | 219 |
207 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, | 220 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, |
208 SkCanvas* canvas, | 221 SkCanvas* canvas, |
209 const gfx::Rect& dest_rect, | 222 const gfx::Rect& dest_rect, |
210 uint8_t alpha) { | 223 uint8_t alpha) { |
211 if (alpha == 0) { | 224 if (alpha == 0) { |
212 return; | 225 return; |
213 } | 226 } |
214 | 227 |
215 SkRect dest; | 228 SkRect dest; |
216 dest.set(SkIntToScalar(dest_rect.x()), SkIntToScalar(dest_rect.y()), | 229 dest.set(SkIntToScalar(dest_rect.x()), SkIntToScalar(dest_rect.y()), |
217 SkIntToScalar(dest_rect.right()), SkIntToScalar(dest_rect.bottom())); | 230 SkIntToScalar(dest_rect.right()), SkIntToScalar(dest_rect.bottom())); |
218 | 231 |
219 SkPaint paint; | 232 SkPaint paint; |
220 paint.setAlpha(alpha); | 233 paint.setAlpha(alpha); |
221 | 234 |
222 // Paint black rectangle if there isn't a frame available or if the format is | 235 // Paint black rectangle if there isn't a frame available or the |
223 // unexpected (can happen e.g. when normally painting to HW textures but | 236 // frame has an unexpected format. |
224 // during shutdown path). | 237 if (!video_frame || !IsEitherYV12OrYV16OrNative(video_frame->format())) { |
225 if (!video_frame || !IsEitherYV12OrYV16(video_frame->format())) { | |
226 canvas->drawRect(dest, paint); | 238 canvas->drawRect(dest, paint); |
227 return; | 239 return; |
228 } | 240 } |
229 | 241 |
230 // Scale and convert to RGB in one step if we can. | 242 // Scale and convert to RGB in one step if we can. |
231 if (CanFastPaint(canvas, dest_rect, alpha)) { | 243 if (CanFastPaint(canvas, dest_rect, alpha, video_frame->format())) { |
232 FastPaint(video_frame, canvas, dest_rect); | 244 FastPaint(video_frame, canvas, dest_rect); |
233 return; | 245 return; |
234 } | 246 } |
235 | 247 |
236 // Check if we should convert and update |last_frame_|. | 248 // Check if we should convert and update |last_frame_|. |
237 if (last_frame_.isNull() || | 249 if (last_frame_.isNull() || |
238 video_frame->GetTimestamp() != last_frame_timestamp_) { | 250 video_frame->GetTimestamp() != last_frame_timestamp_) { |
239 ConvertVideoFrameToBitmap(video_frame, &last_frame_); | 251 ConvertVideoFrameToBitmap(video_frame, &last_frame_); |
240 last_frame_timestamp_ = video_frame->GetTimestamp(); | 252 last_frame_timestamp_ = video_frame->GetTimestamp(); |
241 } | 253 } |
242 | 254 |
243 // Do a slower paint using |last_frame_|. | 255 // Do a slower paint using |last_frame_|. |
244 paint.setFilterBitmap(true); | 256 paint.setFilterBitmap(true); |
245 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); | 257 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); |
246 } | 258 } |
247 | 259 |
248 } // namespace webkit_media | 260 } // namespace webkit_media |
OLD | NEW |