Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(598)

Side by Side Diff: media/filters/skcanvas_video_renderer.cc

Issue 512733003: Do YUV conversion on the GPU when copying video frames into a GPU-accelerated canvas. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/filters/skcanvas_video_renderer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "skia/ext/refptr.h"
10 #include "third_party/libyuv/include/libyuv.h" 11 #include "third_party/libyuv/include/libyuv.h"
11 #include "third_party/skia/include/core/SkCanvas.h" 12 #include "third_party/skia/include/core/SkCanvas.h"
13 #include "third_party/skia/include/gpu/SkGr.h"
14 #include "third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.h"
12 #include "ui/gfx/skbitmap_operations.h" 15 #include "ui/gfx/skbitmap_operations.h"
13 16
14 // Skia internal format depends on a platform. On Android it is ABGR, on others 17 // Skia internal format depends on a platform. On Android it is ABGR, on others
15 // it is ARGB. 18 // it is ARGB.
16 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \ 19 #if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
17 SK_A32_SHIFT == 24 20 SK_A32_SHIFT == 24
18 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB 21 #define LIBYUV_I420_TO_ARGB libyuv::I420ToARGB
19 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB 22 #define LIBYUV_I422_TO_ARGB libyuv::I422ToARGB
20 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ 23 #elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
21 SK_A32_SHIFT == 24 24 SK_A32_SHIFT == 24
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 177
175 default: 178 default:
176 NOTREACHED(); 179 NOTREACHED();
177 break; 180 break;
178 } 181 }
179 bitmap->notifyPixelsChanged(); 182 bitmap->notifyPixelsChanged();
180 bitmap->unlockPixels(); 183 bitmap->unlockPixels();
181 } 184 }
182 185
183 SkCanvasVideoRenderer::SkCanvasVideoRenderer() 186 SkCanvasVideoRenderer::SkCanvasVideoRenderer()
184 : last_frame_timestamp_(media::kNoTimestamp()) { 187 : last_frame_timestamp_(media::kNoTimestamp()),
188 yuv_planes_timestamp_(media::kNoTimestamp()) {
185 } 189 }
186 190
187 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} 191 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {}
188 192
189 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, 193 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame,
190 SkCanvas* canvas, 194 SkCanvas* canvas,
191 const gfx::RectF& dest_rect, 195 const gfx::RectF& dest_rect,
192 uint8 alpha, 196 uint8 alpha,
193 SkXfermode::Mode mode, 197 SkXfermode::Mode mode,
194 VideoRotation video_rotation) { 198 VideoRotation video_rotation) {
195 if (alpha == 0) { 199 if (alpha == 0) {
196 return; 200 return;
197 } 201 }
198 202
199 SkRect dest; 203 SkRect dest;
200 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); 204 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
201 205
202 SkPaint paint; 206 SkPaint paint;
203 paint.setAlpha(alpha); 207 paint.setAlpha(alpha);
204 208
205 // Paint black rectangle if there isn't a frame available or the 209 // Paint black rectangle if there isn't a frame available or the
206 // frame has an unexpected format. 210 // frame has an unexpected format.
207 if (!video_frame || !IsYUVOrNative(video_frame->format())) { 211 if (!video_frame || !IsYUVOrNative(video_frame->format())) {
208 canvas->drawRect(dest, paint); 212 canvas->drawRect(dest, paint);
209 return; 213 return;
210 } 214 }
211 215
216 // If we have a hardware accelerated canvas, we can try to do YUV conversion
217 // directly from our frame to the output canvas.
218 if (canvas->getGrContext() &&
219 HardwarePaint(
220 video_frame, canvas->getGrContext(), dest, mode, video_rotation)) {
221 // If HardwarePaint() succeeded, then we're all done!
222 return;
223 }
224
212 // Check if we should convert and update |last_frame_|. 225 // Check if we should convert and update |last_frame_|.
213 if (last_frame_.isNull() || 226 if (last_frame_.isNull() ||
214 video_frame->timestamp() != last_frame_timestamp_) { 227 video_frame->timestamp() != last_frame_timestamp_) {
215 ConvertVideoFrameToBitmap(video_frame, &last_frame_); 228 ConvertVideoFrameToBitmap(video_frame, &last_frame_);
216 229
217 switch (video_rotation) { 230 switch (video_rotation) {
218 case VIDEO_ROTATION_0: 231 case VIDEO_ROTATION_0:
219 break; 232 break;
220 case VIDEO_ROTATION_90: 233 case VIDEO_ROTATION_90:
221 last_frame_ = SkBitmapOperations::Rotate( 234 last_frame_ = SkBitmapOperations::Rotate(
(...skipping 22 matching lines...) Expand all
244 void SkCanvasVideoRenderer::Copy(media::VideoFrame* video_frame, 257 void SkCanvasVideoRenderer::Copy(media::VideoFrame* video_frame,
245 SkCanvas* canvas) { 258 SkCanvas* canvas) {
246 Paint(video_frame, 259 Paint(video_frame,
247 canvas, 260 canvas,
248 video_frame->visible_rect(), 261 video_frame->visible_rect(),
249 0xff, 262 0xff,
250 SkXfermode::kSrc_Mode, 263 SkXfermode::kSrc_Mode,
251 media::VIDEO_ROTATION_0); 264 media::VIDEO_ROTATION_0);
252 } 265 }
253 266
267 bool SkCanvasVideoRenderer::HardwarePaint(media::VideoFrame* video_frame,
268 GrContext* gr,
269 const SkRect& dest_rect,
270 SkXfermode::Mode mode,
271 VideoRotation video_rotation) {
272 if (!IsYUV(video_frame->format()) ||
273 video_frame->format() == VideoFrame::YV12A)
274 return false;
275
276 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane),
277 video_frame->stride(media::VideoFrame::kVPlane));
278
279 // Wrap our planes in SkBitmaps.
280 if (video_frame->timestamp() != yuv_planes_timestamp_) {
281 yuv_planes_[0].installPixels(
282 SkImageInfo::MakeA8(video_frame->coded_size().width(),
283 video_frame->coded_size().height()),
284 video_frame->data(VideoFrame::kYPlane),
285 video_frame->stride(VideoFrame::kYPlane));
286 yuv_planes_[1].installPixels(
287 SkImageInfo::MakeA8(video_frame->coded_size().width() / 2,
288 video_frame->coded_size().height() / 2),
289 video_frame->data(VideoFrame::kUPlane),
290 video_frame->stride(VideoFrame::kUPlane));
291 yuv_planes_[2].installPixels(
292 SkImageInfo::MakeA8(video_frame->coded_size().width() / 2,
293 video_frame->coded_size().height() / 2),
294 video_frame->data(VideoFrame::kVPlane),
295 video_frame->stride(VideoFrame::kVPlane));
296 }
297
298 // Populate GrTextures from the bitmaps. We let Ganesh handle caching here.
299 GrTexture* planes[3];
300 planes[0] = GrLockAndRefCachedBitmapTexture(gr, yuv_planes_[0], NULL);
301 planes[1] = GrLockAndRefCachedBitmapTexture(gr, yuv_planes_[1], NULL);
302 planes[2] = GrLockAndRefCachedBitmapTexture(gr, yuv_planes_[2], NULL);
303
304 skia::RefPtr<GrEffect> effect = skia::AdoptRef<GrEffect>(
305 GrYUVtoRGBEffect::Create(planes[0], planes[1], planes[2]));
306
307 if (!effect)
308 return false;
309
310 SkXfermode::Coeff src, dest;
311 if (!SkXfermode::ModeAsCoeff(mode, &src, &dest))
312 return false;
313
314 GrPaint paint;
315 paint.addColorEffect(effect.get());
316 paint.setBlendFunc(sk_blend_to_grblend(src), sk_blend_to_grblend(dest));
317
318 GrContext::AutoMatrix auto_matrix;
319 auto_matrix.setIdentity(gr, &paint);
320 SkMatrix rotation;
321
322 switch (video_rotation) {
323 case VIDEO_ROTATION_0:
324 rotation.reset();
325 break;
326 case VIDEO_ROTATION_90:
327 rotation.setRotate(90);
328 rotation.postTranslate(video_frame->coded_size().height(), 0);
329 break;
330 case VIDEO_ROTATION_180:
331 rotation.setRotate(180);
332 rotation.postTranslate(video_frame->coded_size().width(),
333 video_frame->coded_size().height());
334 break;
335 case VIDEO_ROTATION_270:
336 rotation.setRotate(270);
337 rotation.postTranslate(0, video_frame->coded_size().width());
338 break;
339 }
340
341 gr->concatMatrix(rotation);
342 gr->drawRect(paint, dest_rect);
343
344 GrUnlockAndUnrefCachedBitmapTexture(planes[0]);
345 GrUnlockAndUnrefCachedBitmapTexture(planes[1]);
346 GrUnlockAndUnrefCachedBitmapTexture(planes[2]);
347
348 gr->flush();
349
350 yuv_planes_timestamp_ = video_frame->timestamp();
351
352 return true;
353 }
354
254 } // namespace media 355 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/skcanvas_video_renderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698