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 "media/filters/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/libyuv/include/libyuv.h" | 10 #include "third_party/libyuv/include/libyuv.h" |
11 #include "third_party/skia/include/core/SkCanvas.h" | 11 #include "third_party/skia/include/core/SkCanvas.h" |
12 #include "third_party/skia/include/core/SkImageGenerator.h" | |
12 #include "ui/gfx/skbitmap_operations.h" | 13 #include "ui/gfx/skbitmap_operations.h" |
13 | 14 |
14 // Skia internal format depends on a platform. On Android it is ABGR, on others | 15 // Skia internal format depends on a platform. On Android it is ABGR, on others |
15 // it is ARGB. | 16 // it is ARGB. |
16 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ | 17 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ |
17 SK_A32_SHIFT == 24 | 18 SK_A32_SHIFT == 24 |
18 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB | 19 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB |
19 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB | 20 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB |
20 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ | 21 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ |
21 SK_A32_SHIFT == 24 | 22 SK_A32_SHIFT == 24 |
(...skipping 11 matching lines...) Expand all Loading... | |
33 format == media::VideoFrame::I420 || | 34 format == media::VideoFrame::I420 || |
34 format == media::VideoFrame::YV12A || | 35 format == media::VideoFrame::YV12A || |
35 format == media::VideoFrame::YV12J || | 36 format == media::VideoFrame::YV12J || |
36 format == media::VideoFrame::YV24; | 37 format == media::VideoFrame::YV24; |
37 } | 38 } |
38 | 39 |
39 static bool IsYUVOrNative(media::VideoFrame::Format format) { | 40 static bool IsYUVOrNative(media::VideoFrame::Format format) { |
40 return IsYUV(format) || format == media::VideoFrame::NATIVE_TEXTURE; | 41 return IsYUV(format) || format == media::VideoFrame::NATIVE_TEXTURE; |
41 } | 42 } |
42 | 43 |
43 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data. | 44 // Converts a |video_frame| to raw |rgb_pixels|. |
44 // | 45 static void ConvertVideoFrameToRGBPixels( |
45 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|. | |
46 static void ConvertVideoFrameToBitmap( | |
47 const scoped_refptr<media::VideoFrame>& video_frame, | 46 const scoped_refptr<media::VideoFrame>& video_frame, |
48 SkBitmap* bitmap) { | 47 void* rgb_pixels, |
48 size_t row_bytes) { | |
49 DCHECK(IsYUVOrNative(video_frame->format())) | 49 DCHECK(IsYUVOrNative(video_frame->format())) |
50 << video_frame->format(); | 50 << video_frame->format(); |
51 if (IsYUV(video_frame->format())) { | 51 if (IsYUV(video_frame->format())) { |
52 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), | 52 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), |
53 video_frame->stride(media::VideoFrame::kVPlane)); | 53 video_frame->stride(media::VideoFrame::kVPlane)); |
54 } | 54 } |
55 | 55 |
56 // Check if |bitmap| needs to be (re)allocated. | |
57 if (bitmap->isNull() || | |
58 bitmap->width() != video_frame->visible_rect().width() || | |
59 bitmap->height() != video_frame->visible_rect().height()) { | |
60 bitmap->allocN32Pixels(video_frame->visible_rect().width(), | |
61 video_frame->visible_rect().height()); | |
62 bitmap->setIsVolatile(true); | |
63 } | |
64 | |
65 bitmap->lockPixels(); | |
66 | |
67 size_t y_offset = 0; | 56 size_t y_offset = 0; |
68 size_t uv_offset = 0; | 57 size_t uv_offset = 0; |
69 if (IsYUV(video_frame->format())) { | 58 if (IsYUV(video_frame->format())) { |
70 int y_shift = (video_frame->format() == media::VideoFrame::YV16) ? 0 : 1; | 59 int y_shift = (video_frame->format() == media::VideoFrame::YV16) ? 0 : 1; |
71 // Use the "left" and "top" of the destination rect to locate the offset | 60 // Use the "left" and "top" of the destination rect to locate the offset |
72 // in Y, U and V planes. | 61 // in Y, U and V planes. |
73 y_offset = (video_frame->stride(media::VideoFrame::kYPlane) * | 62 y_offset = (video_frame->stride(media::VideoFrame::kYPlane) * |
74 video_frame->visible_rect().y()) + | 63 video_frame->visible_rect().y()) + |
75 video_frame->visible_rect().x(); | 64 video_frame->visible_rect().x(); |
76 // For format YV12, there is one U, V value per 2x2 block. | 65 // For format YV12, there is one U, V value per 2x2 block. |
77 // For format YV16, there is one U, V value per 2x1 block. | 66 // For format YV16, there is one U, V value per 2x1 block. |
78 uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) * | 67 uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) * |
79 (video_frame->visible_rect().y() >> y_shift)) + | 68 (video_frame->visible_rect().y() >> y_shift)) + |
80 (video_frame->visible_rect().x() >> 1); | 69 (video_frame->visible_rect().x() >> 1); |
81 } | 70 } |
82 | 71 |
72 SkBitmap tmp; | |
DaleCurtis
2014/09/09 00:32:53
Drive by, you can avoid putting this way up here i
rileya (GONE FROM CHROMIUM)
2014/09/09 00:50:13
Ah, didn't know that, thanks!
| |
73 | |
83 switch (video_frame->format()) { | 74 switch (video_frame->format()) { |
84 case media::VideoFrame::YV12: | 75 case media::VideoFrame::YV12: |
85 case media::VideoFrame::I420: | 76 case media::VideoFrame::I420: |
86 LIBYUV_I420_TO_ARGB( | 77 LIBYUV_I420_TO_ARGB( |
87 video_frame->data(media::VideoFrame::kYPlane) + y_offset, | 78 video_frame->data(media::VideoFrame::kYPlane) + y_offset, |
88 video_frame->stride(media::VideoFrame::kYPlane), | 79 video_frame->stride(media::VideoFrame::kYPlane), |
89 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, | 80 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, |
90 video_frame->stride(media::VideoFrame::kUPlane), | 81 video_frame->stride(media::VideoFrame::kUPlane), |
91 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, | 82 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
92 video_frame->stride(media::VideoFrame::kVPlane), | 83 video_frame->stride(media::VideoFrame::kVPlane), |
93 static_cast<uint8*>(bitmap->getPixels()), | 84 static_cast<uint8*>(rgb_pixels), |
94 bitmap->rowBytes(), | 85 row_bytes, |
95 video_frame->visible_rect().width(), | 86 video_frame->visible_rect().width(), |
96 video_frame->visible_rect().height()); | 87 video_frame->visible_rect().height()); |
97 break; | 88 break; |
98 | 89 |
99 case media::VideoFrame::YV12J: | 90 case media::VideoFrame::YV12J: |
100 media::ConvertYUVToRGB32( | 91 media::ConvertYUVToRGB32( |
101 video_frame->data(media::VideoFrame::kYPlane) + y_offset, | 92 video_frame->data(media::VideoFrame::kYPlane) + y_offset, |
102 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, | 93 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, |
103 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, | 94 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
104 static_cast<uint8*>(bitmap->getPixels()), | 95 static_cast<uint8*>(rgb_pixels), |
105 video_frame->visible_rect().width(), | 96 video_frame->visible_rect().width(), |
106 video_frame->visible_rect().height(), | 97 video_frame->visible_rect().height(), |
107 video_frame->stride(media::VideoFrame::kYPlane), | 98 video_frame->stride(media::VideoFrame::kYPlane), |
108 video_frame->stride(media::VideoFrame::kUPlane), | 99 video_frame->stride(media::VideoFrame::kUPlane), |
109 bitmap->rowBytes(), | 100 row_bytes, |
110 media::YV12J); | 101 media::YV12J); |
111 break; | 102 break; |
112 | 103 |
113 case media::VideoFrame::YV16: | 104 case media::VideoFrame::YV16: |
114 LIBYUV_I422_TO_ARGB( | 105 LIBYUV_I422_TO_ARGB( |
115 video_frame->data(media::VideoFrame::kYPlane) + y_offset, | 106 video_frame->data(media::VideoFrame::kYPlane) + y_offset, |
116 video_frame->stride(media::VideoFrame::kYPlane), | 107 video_frame->stride(media::VideoFrame::kYPlane), |
117 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, | 108 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, |
118 video_frame->stride(media::VideoFrame::kUPlane), | 109 video_frame->stride(media::VideoFrame::kUPlane), |
119 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, | 110 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
120 video_frame->stride(media::VideoFrame::kVPlane), | 111 video_frame->stride(media::VideoFrame::kVPlane), |
121 static_cast<uint8*>(bitmap->getPixels()), | 112 static_cast<uint8*>(rgb_pixels), |
122 bitmap->rowBytes(), | 113 row_bytes, |
123 video_frame->visible_rect().width(), | 114 video_frame->visible_rect().width(), |
124 video_frame->visible_rect().height()); | 115 video_frame->visible_rect().height()); |
125 break; | 116 break; |
126 | 117 |
127 case media::VideoFrame::YV12A: | 118 case media::VideoFrame::YV12A: |
128 // Since libyuv doesn't support YUVA, fallback to media, which is not ARM | 119 // Since libyuv doesn't support YUVA, fallback to media, which is not ARM |
129 // optimized. | 120 // optimized. |
130 // TODO(fbarchard, mtomasz): Use libyuv, then copy the alpha channel. | 121 // TODO(fbarchard, mtomasz): Use libyuv, then copy the alpha channel. |
131 media::ConvertYUVAToARGB( | 122 media::ConvertYUVAToARGB( |
132 video_frame->data(media::VideoFrame::kYPlane) + y_offset, | 123 video_frame->data(media::VideoFrame::kYPlane) + y_offset, |
133 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, | 124 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, |
134 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, | 125 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
135 video_frame->data(media::VideoFrame::kAPlane), | 126 video_frame->data(media::VideoFrame::kAPlane), |
136 static_cast<uint8*>(bitmap->getPixels()), | 127 static_cast<uint8*>(rgb_pixels), |
137 video_frame->visible_rect().width(), | 128 video_frame->visible_rect().width(), |
138 video_frame->visible_rect().height(), | 129 video_frame->visible_rect().height(), |
139 video_frame->stride(media::VideoFrame::kYPlane), | 130 video_frame->stride(media::VideoFrame::kYPlane), |
140 video_frame->stride(media::VideoFrame::kUPlane), | 131 video_frame->stride(media::VideoFrame::kUPlane), |
141 video_frame->stride(media::VideoFrame::kAPlane), | 132 video_frame->stride(media::VideoFrame::kAPlane), |
142 bitmap->rowBytes(), | 133 row_bytes, |
143 media::YV12); | 134 media::YV12); |
144 break; | 135 break; |
145 | 136 |
146 case media::VideoFrame::YV24: | 137 case media::VideoFrame::YV24: |
147 libyuv::I444ToARGB( | 138 libyuv::I444ToARGB( |
148 video_frame->data(media::VideoFrame::kYPlane) + y_offset, | 139 video_frame->data(media::VideoFrame::kYPlane) + y_offset, |
149 video_frame->stride(media::VideoFrame::kYPlane), | 140 video_frame->stride(media::VideoFrame::kYPlane), |
150 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, | 141 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, |
151 video_frame->stride(media::VideoFrame::kUPlane), | 142 video_frame->stride(media::VideoFrame::kUPlane), |
152 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, | 143 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
153 video_frame->stride(media::VideoFrame::kVPlane), | 144 video_frame->stride(media::VideoFrame::kVPlane), |
154 static_cast<uint8*>(bitmap->getPixels()), | 145 static_cast<uint8*>(rgb_pixels), |
155 bitmap->rowBytes(), | 146 row_bytes, |
156 video_frame->visible_rect().width(), | 147 video_frame->visible_rect().width(), |
157 video_frame->visible_rect().height()); | 148 video_frame->visible_rect().height()); |
158 #if SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ | 149 #if SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ |
159 SK_A32_SHIFT == 24 | 150 SK_A32_SHIFT == 24 |
160 libyuv::ARGBToABGR( | 151 libyuv::ARGBToABGR(static_cast<uint8*>(rgb_pixels), |
161 static_cast<uint8*>(bitmap->getPixels()), | 152 row_bytes, |
162 bitmap->rowBytes(), | 153 static_cast<uint8*>(rgb_pixels), |
163 static_cast<uint8*>(bitmap->getPixels()), | 154 row_bytes, |
164 bitmap->rowBytes(), | 155 video_frame->visible_rect().width(), |
165 video_frame->visible_rect().width(), | 156 video_frame->visible_rect().height()); |
166 video_frame->visible_rect().height()); | |
167 #endif | 157 #endif |
168 break; | 158 break; |
169 | 159 |
170 case media::VideoFrame::NATIVE_TEXTURE: | 160 case media::VideoFrame::NATIVE_TEXTURE: |
171 DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE); | 161 DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE); |
172 video_frame->ReadPixelsFromNativeTexture(*bitmap); | 162 tmp.installPixels( |
163 SkImageInfo::MakeN32Premul(video_frame->visible_rect().width(), | |
164 video_frame->visible_rect().height()), | |
165 rgb_pixels, | |
166 row_bytes); | |
167 video_frame->ReadPixelsFromNativeTexture(tmp); | |
173 break; | 168 break; |
174 | 169 |
175 default: | 170 default: |
176 NOTREACHED(); | 171 NOTREACHED(); |
177 break; | 172 break; |
178 } | 173 } |
179 bitmap->notifyPixelsChanged(); | |
180 bitmap->unlockPixels(); | |
181 } | 174 } |
182 | 175 |
176 // Generates an RGB image from a VideoFrame. | |
177 class VideoImageGenerator : public SkImageGenerator { | |
178 public: | |
179 VideoImageGenerator(const scoped_refptr<VideoFrame> frame) : frame_(frame) {} | |
180 virtual ~VideoImageGenerator() {} | |
181 | |
182 protected: | |
183 virtual bool onGetInfo(SkImageInfo* info) OVERRIDE { | |
184 info->fWidth = frame_->visible_rect().width(); | |
185 info->fHeight = frame_->visible_rect().height(); | |
186 info->fColorType = kBGRA_8888_SkColorType; | |
187 info->fAlphaType = kPremul_SkAlphaType; | |
188 return true; | |
189 } | |
190 | |
191 virtual bool onGetPixels(const SkImageInfo& info, | |
192 void* pixels, | |
193 size_t rowBytes, | |
scherkus (not reviewing)
2014/09/09 00:27:05
nit: I think skia has a different naming style, bu
rileya (GONE FROM CHROMIUM)
2014/09/09 00:50:13
Fixed, I'd wrongly assumed maintaining parity with
| |
194 SkPMColor ctable[], | |
195 int* ctableCount) OVERRIDE { | |
196 // If skia couldn't do the YUV conversion, we will. | |
197 ConvertVideoFrameToRGBPixels(frame_, pixels, rowBytes); | |
198 return true; | |
199 } | |
200 | |
201 virtual bool onGetYUV8Planes(SkISize sizes[3], | |
202 void* planes[3], | |
203 size_t rowBytes[3]) OVERRIDE { | |
scherkus (not reviewing)
2014/09/09 00:27:05
ditto for row_bytes
| |
204 // Currently Skia only supports JPEG color range YUV. | |
205 if (frame_->format() != VideoFrame::YV12J) | |
scherkus (not reviewing)
2014/09/09 00:27:05
if our Media.VideoPixelFormat UMA data is to belie
rileya (GONE FROM CHROMIUM)
2014/09/09 00:50:14
Yep, skia changes in progress here: https://codere
| |
206 return false; | |
scherkus (not reviewing)
2014/09/09 00:27:05
what does returning false entail?
rileya (GONE FROM CHROMIUM)
2014/09/09 00:50:13
It means we couldn't provide the YUV planes, and s
| |
207 for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane; | |
208 ++plane) { | |
209 gfx::Size size; | |
DaleCurtis
2014/09/09 00:32:53
Move inside if block.
rileya (GONE FROM CHROMIUM)
2014/09/09 00:50:14
Done.
| |
210 if (sizes) { | |
211 size = VideoFrame::PlaneSize( | |
212 frame_->format(), plane, frame_->coded_size()); | |
213 sizes[plane].set(size.width(), size.height()); | |
214 } | |
215 if (rowBytes) | |
216 rowBytes[plane] = frame_->row_bytes(plane); | |
217 if (planes) { | |
218 memcpy(planes[plane], | |
219 frame_->data(plane), | |
220 VideoFrame::PlaneAllocationSize( | |
221 frame_->format(), plane, frame_->coded_size())); | |
222 } | |
223 } | |
224 return true; | |
225 } | |
226 | |
227 private: | |
228 scoped_refptr<VideoFrame> frame_; | |
229 }; | |
230 | |
183 SkCanvasVideoRenderer::SkCanvasVideoRenderer() | 231 SkCanvasVideoRenderer::SkCanvasVideoRenderer() |
184 : last_frame_timestamp_(media::kNoTimestamp()) { | 232 : last_frame_timestamp_(media::kNoTimestamp()) { |
185 } | 233 } |
186 | 234 |
187 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} | 235 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} |
188 | 236 |
189 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, | 237 void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame> video_frame, |
190 SkCanvas* canvas, | 238 SkCanvas* canvas, |
191 const gfx::RectF& dest_rect, | 239 const gfx::RectF& dest_rect, |
192 uint8 alpha, | 240 uint8 alpha, |
193 SkXfermode::Mode mode, | 241 SkXfermode::Mode mode, |
194 VideoRotation video_rotation) { | 242 VideoRotation video_rotation) { |
195 if (alpha == 0) { | 243 if (alpha == 0) { |
196 return; | 244 return; |
197 } | 245 } |
198 | 246 |
199 SkRect dest; | 247 SkRect dest; |
200 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); | 248 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); |
201 | 249 |
202 SkPaint paint; | 250 SkPaint paint; |
203 paint.setAlpha(alpha); | 251 paint.setAlpha(alpha); |
204 | 252 |
205 // Paint black rectangle if there isn't a frame available or the | 253 // Paint black rectangle if there isn't a frame available or the |
206 // frame has an unexpected format. | 254 // frame has an unexpected format. |
207 if (!video_frame || !IsYUVOrNative(video_frame->format())) { | 255 if (!video_frame || !IsYUVOrNative(video_frame->format())) { |
208 canvas->drawRect(dest, paint); | 256 canvas->drawRect(dest, paint); |
209 return; | 257 return; |
210 } | 258 } |
211 | 259 |
212 // Check if we should convert and update |last_frame_|. | 260 // Check if we should convert and update |last_frame_|. |
213 if (last_frame_.isNull() || | 261 if (last_frame_.isNull() || |
214 video_frame->timestamp() != last_frame_timestamp_) { | 262 video_frame->timestamp() != last_frame_timestamp_) { |
215 ConvertVideoFrameToBitmap(video_frame, &last_frame_); | 263 if (!SkInstallDiscardablePixelRef(new VideoImageGenerator(video_frame), |
264 &last_frame_)) { | |
265 NOTREACHED(); | |
266 } | |
216 | 267 |
268 // TODO(rileya): Perform this rotation on the canvas, rather than allocating | |
269 // a new bitmap and copying. | |
217 switch (video_rotation) { | 270 switch (video_rotation) { |
218 case VIDEO_ROTATION_0: | 271 case VIDEO_ROTATION_0: |
219 break; | 272 break; |
220 case VIDEO_ROTATION_90: | 273 case VIDEO_ROTATION_90: |
221 last_frame_ = SkBitmapOperations::Rotate( | 274 last_frame_ = SkBitmapOperations::Rotate( |
222 last_frame_, SkBitmapOperations::ROTATION_90_CW); | 275 last_frame_, SkBitmapOperations::ROTATION_90_CW); |
223 break; | 276 break; |
224 case VIDEO_ROTATION_180: | 277 case VIDEO_ROTATION_180: |
225 last_frame_ = SkBitmapOperations::Rotate( | 278 last_frame_ = SkBitmapOperations::Rotate( |
226 last_frame_, SkBitmapOperations::ROTATION_180_CW); | 279 last_frame_, SkBitmapOperations::ROTATION_180_CW); |
227 break; | 280 break; |
228 case VIDEO_ROTATION_270: | 281 case VIDEO_ROTATION_270: |
229 last_frame_ = SkBitmapOperations::Rotate( | 282 last_frame_ = SkBitmapOperations::Rotate( |
230 last_frame_, SkBitmapOperations::ROTATION_270_CW); | 283 last_frame_, SkBitmapOperations::ROTATION_270_CW); |
231 break; | 284 break; |
232 } | 285 } |
233 | 286 |
234 last_frame_timestamp_ = video_frame->timestamp(); | 287 last_frame_timestamp_ = video_frame->timestamp(); |
235 } | 288 } |
236 | 289 |
237 paint.setXfermodeMode(mode); | 290 paint.setXfermodeMode(mode); |
238 | 291 |
239 // Paint using |last_frame_|. | 292 // Paint using |last_frame_|. |
240 paint.setFilterLevel(SkPaint::kLow_FilterLevel); | 293 paint.setFilterLevel(SkPaint::kLow_FilterLevel); |
241 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); | 294 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); |
242 } | 295 } |
243 | 296 |
244 void SkCanvasVideoRenderer::Copy(media::VideoFrame* video_frame, | 297 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame> video_frame, |
245 SkCanvas* canvas) { | 298 SkCanvas* canvas) { |
246 Paint(video_frame, | 299 Paint(video_frame, |
247 canvas, | 300 canvas, |
248 video_frame->visible_rect(), | 301 video_frame->visible_rect(), |
249 0xff, | 302 0xff, |
250 SkXfermode::kSrc_Mode, | 303 SkXfermode::kSrc_Mode, |
251 media::VIDEO_ROTATION_0); | 304 media::VIDEO_ROTATION_0); |
252 } | 305 } |
253 | 306 |
254 } // namespace media | 307 } // namespace media |
OLD | NEW |