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 "media/filters/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 media { |
14 | 14 |
15 static bool IsEitherYV12OrYV16(media::VideoFrame::Format format) { | 15 static bool IsEitherYV12OrYV16(media::VideoFrame::Format format) { |
16 return format == media::VideoFrame::YV12 || format == media::VideoFrame::YV16; | 16 return format == media::VideoFrame::YV12 || format == media::VideoFrame::YV16; |
17 } | 17 } |
18 | 18 |
19 static bool IsEitherYV12OrYV16OrNative(media::VideoFrame::Format format) { | 19 static bool IsEitherYV12OrYV16OrNative(media::VideoFrame::Format format) { |
20 return IsEitherYV12OrYV16(format) || | 20 return IsEitherYV12OrYV16(format) || |
21 format == media::VideoFrame::NATIVE_TEXTURE; | 21 format == media::VideoFrame::NATIVE_TEXTURE; |
22 } | 22 } |
23 | 23 |
24 // CanFastPaint is a helper method to determine the conditions for fast | 24 // CanFastPaint is a helper method to determine the conditions for fast |
25 // painting. The conditions are: | 25 // painting. The conditions are: |
26 // 1. No skew in canvas matrix. | 26 // 1. No skew in canvas matrix. |
27 // 2. No flipping nor mirroring. | 27 // 2. No flipping nor mirroring. |
28 // 3. Canvas has pixel format ARGB8888. | 28 // 3. Canvas has pixel format ARGB8888. |
29 // 4. Canvas is opaque. | 29 // 4. Canvas is opaque. |
30 // 5. Frame format is YV12 or YV16. | 30 // 5. Frame format is YV12 or YV16. |
31 // | 31 // |
32 // TODO(hclam): The fast paint method should support flipping and mirroring. | 32 // TODO(hclam): The fast paint method should support flipping and mirroring. |
33 // Disable the flipping and mirroring checks once we have it. | 33 // Disable the flipping and mirroring checks once we have it. |
34 static bool CanFastPaint(SkCanvas* canvas, const gfx::Rect& dest_rect, | 34 static bool CanFastPaint(SkCanvas* canvas, uint8_t alpha, |
35 uint8_t alpha, media::VideoFrame::Format format) { | 35 media::VideoFrame::Format format) { |
36 if (alpha != 0xFF || !IsEitherYV12OrYV16(format)) | 36 if (alpha != 0xFF || !IsEitherYV12OrYV16(format)) |
37 return false; | 37 return false; |
38 | 38 |
39 const SkMatrix& total_matrix = canvas->getTotalMatrix(); | 39 const SkMatrix& total_matrix = canvas->getTotalMatrix(); |
40 // Perform the following checks here: | 40 // Perform the following checks here: |
41 // 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 |
42 // zero. | 42 // zero. |
43 // 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. |
44 if (SkScalarNearlyZero(total_matrix.getSkewX()) && | 44 if (SkScalarNearlyZero(total_matrix.getSkewX()) && |
45 SkScalarNearlyZero(total_matrix.getSkewY()) && | 45 SkScalarNearlyZero(total_matrix.getSkewY()) && |
46 total_matrix.getScaleX() > 0 && | 46 total_matrix.getScaleX() > 0 && |
47 total_matrix.getScaleY() > 0) { | 47 total_matrix.getScaleY() > 0) { |
48 SkDevice* device = canvas->getDevice(); | 48 SkDevice* device = canvas->getDevice(); |
49 const SkBitmap::Config config = device->config(); | 49 const SkBitmap::Config config = device->config(); |
50 | 50 |
51 if (config == SkBitmap::kARGB_8888_Config && device->isOpaque()) { | 51 if (config == SkBitmap::kARGB_8888_Config && device->isOpaque()) { |
52 return true; | 52 return true; |
53 } | 53 } |
54 } | 54 } |
55 | 55 |
56 return false; | 56 return false; |
57 } | 57 } |
58 | 58 |
59 // 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 |
60 // 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. |
61 // CanFastPaint() is used to determine the conditions. | 61 // CanFastPaint() is used to determine the conditions. |
62 static void FastPaint( | 62 static void FastPaint( |
63 const scoped_refptr<media::VideoFrame>& video_frame, | 63 const scoped_refptr<media::VideoFrame>& video_frame, |
64 SkCanvas* canvas, | 64 SkCanvas* canvas, |
65 const gfx::Rect& dest_rect) { | 65 const SkRect& dest_rect) { |
66 DCHECK(IsEitherYV12OrYV16(video_frame->format())) << video_frame->format(); | 66 DCHECK(IsEitherYV12OrYV16(video_frame->format())) << video_frame->format(); |
67 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), | 67 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), |
68 video_frame->stride(media::VideoFrame::kVPlane)); | 68 video_frame->stride(media::VideoFrame::kVPlane)); |
69 | 69 |
70 const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true); | 70 const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true); |
71 media::YUVType yuv_type = (video_frame->format() == media::VideoFrame::YV12) ? | 71 media::YUVType yuv_type = (video_frame->format() == media::VideoFrame::YV12) ? |
72 media::YV12 : media::YV16; | 72 media::YV12 : media::YV16; |
73 int y_shift = yuv_type; // 1 for YV12, 0 for YV16. | 73 int y_shift = yuv_type; // 1 for YV12, 0 for YV16. |
74 | 74 |
75 // Create a rectangle backed by SkScalar. | |
76 SkRect scalar_dest_rect; | |
77 scalar_dest_rect.iset(dest_rect.x(), dest_rect.y(), | |
78 dest_rect.right(), dest_rect.bottom()); | |
79 | |
80 // Transform the destination rectangle to local coordinates. | 75 // Transform the destination rectangle to local coordinates. |
81 const SkMatrix& local_matrix = canvas->getTotalMatrix(); | 76 const SkMatrix& local_matrix = canvas->getTotalMatrix(); |
82 SkRect local_dest_rect; | 77 SkRect local_dest_rect; |
83 local_matrix.mapRect(&local_dest_rect, scalar_dest_rect); | 78 local_matrix.mapRect(&local_dest_rect, dest_rect); |
84 | 79 |
85 // After projecting the destination rectangle to local coordinates, round | 80 // After projecting the destination rectangle to local coordinates, round |
86 // the projected rectangle to integer values, this will give us pixel values | 81 // the projected rectangle to integer values, this will give us pixel values |
87 // of the rectangle. | 82 // of the rectangle. |
88 SkIRect local_dest_irect, local_dest_irect_saved; | 83 SkIRect local_dest_irect, local_dest_irect_saved; |
89 local_dest_rect.round(&local_dest_irect); | 84 local_dest_rect.round(&local_dest_irect); |
90 local_dest_rect.round(&local_dest_irect_saved); | 85 local_dest_rect.round(&local_dest_irect_saved); |
91 | 86 |
92 // No point painting if the destination rect doesn't intersect with the | 87 // No point painting if the destination rect doesn't intersect with the |
93 // clip rect. | 88 // clip rect. |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 } | 207 } |
213 | 208 |
214 SkCanvasVideoRenderer::SkCanvasVideoRenderer() | 209 SkCanvasVideoRenderer::SkCanvasVideoRenderer() |
215 : last_frame_timestamp_(media::kNoTimestamp()) { | 210 : last_frame_timestamp_(media::kNoTimestamp()) { |
216 } | 211 } |
217 | 212 |
218 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} | 213 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} |
219 | 214 |
220 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, | 215 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, |
221 SkCanvas* canvas, | 216 SkCanvas* canvas, |
222 const gfx::Rect& dest_rect, | 217 const gfx::RectF& dest_rect, |
223 uint8_t alpha) { | 218 uint8_t alpha) { |
224 if (alpha == 0) { | 219 if (alpha == 0) { |
225 return; | 220 return; |
226 } | 221 } |
227 | 222 |
228 SkRect dest; | 223 SkRect dest; |
229 dest.set(SkIntToScalar(dest_rect.x()), SkIntToScalar(dest_rect.y()), | 224 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); |
230 SkIntToScalar(dest_rect.right()), SkIntToScalar(dest_rect.bottom())); | |
231 | 225 |
232 SkPaint paint; | 226 SkPaint paint; |
233 paint.setAlpha(alpha); | 227 paint.setAlpha(alpha); |
234 | 228 |
235 // Paint black rectangle if there isn't a frame available or the | 229 // Paint black rectangle if there isn't a frame available or the |
236 // frame has an unexpected format. | 230 // frame has an unexpected format. |
237 if (!video_frame || !IsEitherYV12OrYV16OrNative(video_frame->format())) { | 231 if (!video_frame || !IsEitherYV12OrYV16OrNative(video_frame->format())) { |
238 canvas->drawRect(dest, paint); | 232 canvas->drawRect(dest, paint); |
239 return; | 233 return; |
240 } | 234 } |
241 | 235 |
242 // Scale and convert to RGB in one step if we can. | 236 // Scale and convert to RGB in one step if we can. |
243 if (CanFastPaint(canvas, dest_rect, alpha, video_frame->format())) { | 237 if (CanFastPaint(canvas, alpha, video_frame->format())) { |
244 FastPaint(video_frame, canvas, dest_rect); | 238 FastPaint(video_frame, canvas, dest); |
245 return; | 239 return; |
246 } | 240 } |
247 | 241 |
248 // Check if we should convert and update |last_frame_|. | 242 // Check if we should convert and update |last_frame_|. |
249 if (last_frame_.isNull() || | 243 if (last_frame_.isNull() || |
250 video_frame->GetTimestamp() != last_frame_timestamp_) { | 244 video_frame->GetTimestamp() != last_frame_timestamp_) { |
251 ConvertVideoFrameToBitmap(video_frame, &last_frame_); | 245 ConvertVideoFrameToBitmap(video_frame, &last_frame_); |
252 last_frame_timestamp_ = video_frame->GetTimestamp(); | 246 last_frame_timestamp_ = video_frame->GetTimestamp(); |
253 } | 247 } |
254 | 248 |
255 // Do a slower paint using |last_frame_|. | 249 // Do a slower paint using |last_frame_|. |
256 paint.setFilterBitmap(true); | 250 paint.setFilterBitmap(true); |
257 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); | 251 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); |
258 } | 252 } |
259 | 253 |
260 } // namespace webkit_media | 254 } // namespace media |
OLD | NEW |