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

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

Issue 222563002: Remove redundant I420-to-YV12 conversion in MediaStreamVideoTrack. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Allow I420 as acceptable default YUV format in ppapi tests. Created 6 years, 8 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 | Annotate | Revision Log
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 "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 media { 13 namespace media {
14 14
15 static bool IsEitherYV12OrYV16(media::VideoFrame::Format format) { 15 static bool IsYUV(media::VideoFrame::Format format) {
16 return format == media::VideoFrame::YV12 || 16 return format == media::VideoFrame::YV12 ||
17 format == media::VideoFrame::I420 ||
17 format == media::VideoFrame::YV16 || 18 format == media::VideoFrame::YV16 ||
18 format == media::VideoFrame::YV12J; 19 format == media::VideoFrame::YV12J;
19 } 20 }
20 21
21 static bool IsEitherYV12OrYV16OrNative(media::VideoFrame::Format format) { 22 static bool IsEitherYUVOrNative(media::VideoFrame::Format format) {
22 return IsEitherYV12OrYV16(format) || 23 return IsYUV(format) || format == media::VideoFrame::NATIVE_TEXTURE;
23 format == media::VideoFrame::NATIVE_TEXTURE;
24 } 24 }
25 25
26 static bool IsEitherYV12OrYV12AOrYV16(media::VideoFrame::Format format) { 26 static bool IsEitherYUVOrYUVA(media::VideoFrame::Format format) {
27 return IsEitherYV12OrYV16(format) || 27 return IsYUV(format) || format == media::VideoFrame::YV12A;
28 format == media::VideoFrame::YV12A;
29 } 28 }
30 29
31 static bool IsEitherYV12OrYV12AOrYV16OrNative( 30 static bool IsEitherYUVOrYUVAOrNative(media::VideoFrame::Format format) {
32 media::VideoFrame::Format format) { 31 return IsEitherYUVOrNative(format) || format == media::VideoFrame::YV12A;
33 return IsEitherYV12OrYV16OrNative(format) ||
34 format == media::VideoFrame::YV12A;
35 } 32 }
36 33
37 // CanFastPaint is a helper method to determine the conditions for fast 34 // CanFastPaint is a helper method to determine the conditions for fast
38 // painting. The conditions are: 35 // painting. The conditions are:
39 // 1. No skew in canvas matrix. 36 // 1. No skew in canvas matrix.
40 // 2. No flipping nor mirroring. 37 // 2. No flipping nor mirroring.
41 // 3. Canvas has pixel format ARGB8888. 38 // 3. Canvas has pixel format ARGB8888.
42 // 4. Canvas is opaque. 39 // 4. Canvas is opaque.
43 // 5. Frame format is YV12 or YV16. 40 // 5. Frame format is YV12, I420 or YV16.
44 // 41 //
45 // TODO(hclam): The fast paint method should support flipping and mirroring. 42 // TODO(hclam): The fast paint method should support flipping and mirroring.
46 // Disable the flipping and mirroring checks once we have it. 43 // Disable the flipping and mirroring checks once we have it.
47 static bool CanFastPaint(SkCanvas* canvas, uint8 alpha, 44 static bool CanFastPaint(SkCanvas* canvas, uint8 alpha,
48 media::VideoFrame::Format format) { 45 media::VideoFrame::Format format) {
49 if (alpha != 0xFF || !IsEitherYV12OrYV16(format)) 46 if (alpha != 0xFF || !IsYUV(format))
50 return false; 47 return false;
51 48
52 const SkMatrix& total_matrix = canvas->getTotalMatrix(); 49 const SkMatrix& total_matrix = canvas->getTotalMatrix();
53 // Perform the following checks here: 50 // Perform the following checks here:
54 // 1. Check for skewing factors of the transformation matrix. They should be 51 // 1. Check for skewing factors of the transformation matrix. They should be
55 // zero. 52 // zero.
56 // 2. Check for mirroring and flipping. Make sure they are greater than zero. 53 // 2. Check for mirroring and flipping. Make sure they are greater than zero.
57 if (SkScalarNearlyZero(total_matrix.getSkewX()) && 54 if (SkScalarNearlyZero(total_matrix.getSkewX()) &&
58 SkScalarNearlyZero(total_matrix.getSkewY()) && 55 SkScalarNearlyZero(total_matrix.getSkewY()) &&
59 total_matrix.getScaleX() > 0 && 56 total_matrix.getScaleX() > 0 &&
60 total_matrix.getScaleY() > 0) { 57 total_matrix.getScaleY() > 0) {
61 SkBaseDevice* device = canvas->getDevice(); 58 SkBaseDevice* device = canvas->getDevice();
62 const SkBitmap::Config config = device->config(); 59 const SkBitmap::Config config = device->config();
63 60
64 if (config == SkBitmap::kARGB_8888_Config && device->isOpaque()) { 61 if (config == SkBitmap::kARGB_8888_Config && device->isOpaque()) {
65 return true; 62 return true;
66 } 63 }
67 } 64 }
68 65
69 return false; 66 return false;
70 } 67 }
71 68
72 // Fast paint does YUV => RGB, scaling, blitting all in one step into the 69 // Fast paint does YUV => RGB, scaling, blitting all in one step into the
73 // canvas. It's not always safe and appropriate to perform fast paint. 70 // canvas. It's not always safe and appropriate to perform fast paint.
74 // CanFastPaint() is used to determine the conditions. 71 // CanFastPaint() is used to determine the conditions.
75 static void FastPaint( 72 static void FastPaint(
76 const scoped_refptr<media::VideoFrame>& video_frame, 73 const scoped_refptr<media::VideoFrame>& video_frame,
77 SkCanvas* canvas, 74 SkCanvas* canvas,
78 const SkRect& dest_rect) { 75 const SkRect& dest_rect) {
79 DCHECK(IsEitherYV12OrYV16(video_frame->format())) << video_frame->format(); 76 DCHECK(IsYUV(video_frame->format())) << video_frame->format();
80 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), 77 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane),
81 video_frame->stride(media::VideoFrame::kVPlane)); 78 video_frame->stride(media::VideoFrame::kVPlane));
82 79
83 const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true); 80 const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true);
84 media::YUVType yuv_type = media::YV16; 81 media::YUVType yuv_type = media::YV16;
85 int y_shift = 0; 82 int y_shift = 0;
86 if (video_frame->format() == media::VideoFrame::YV12 || 83 if (video_frame->format() == media::VideoFrame::YV12 ||
84 video_frame->format() == media::VideoFrame::I420 ||
87 video_frame->format() == media::VideoFrame::YV12A) { 85 video_frame->format() == media::VideoFrame::YV12A) {
88 yuv_type = media::YV12; 86 yuv_type = media::YV12;
89 y_shift = 1; 87 y_shift = 1;
90 } 88 }
91 89
92 if (video_frame->format() == media::VideoFrame::YV12J) { 90 if (video_frame->format() == media::VideoFrame::YV12J) {
93 yuv_type = media::YV12; 91 yuv_type = media::YV12;
94 y_shift = 1; 92 y_shift = 1;
95 } 93 }
96 94
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 media::FILTER_BILINEAR); 180 media::FILTER_BILINEAR);
183 bitmap.unlockPixels(); 181 bitmap.unlockPixels();
184 } 182 }
185 183
186 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data. 184 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data.
187 // 185 //
188 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|. 186 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|.
189 static void ConvertVideoFrameToBitmap( 187 static void ConvertVideoFrameToBitmap(
190 const scoped_refptr<media::VideoFrame>& video_frame, 188 const scoped_refptr<media::VideoFrame>& video_frame,
191 SkBitmap* bitmap) { 189 SkBitmap* bitmap) {
192 DCHECK(IsEitherYV12OrYV12AOrYV16OrNative(video_frame->format())) 190 DCHECK(IsEitherYUVOrYUVAOrNative(video_frame->format()))
193 << video_frame->format(); 191 << video_frame->format();
194 if (IsEitherYV12OrYV12AOrYV16(video_frame->format())) { 192 if (IsEitherYUVOrYUVA(video_frame->format())) {
195 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), 193 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane),
196 video_frame->stride(media::VideoFrame::kVPlane)); 194 video_frame->stride(media::VideoFrame::kVPlane));
197 } 195 }
198 196
199 // Check if |bitmap| needs to be (re)allocated. 197 // Check if |bitmap| needs to be (re)allocated.
200 if (bitmap->isNull() || 198 if (bitmap->isNull() ||
201 bitmap->width() != video_frame->visible_rect().width() || 199 bitmap->width() != video_frame->visible_rect().width() ||
202 bitmap->height() != video_frame->visible_rect().height()) { 200 bitmap->height() != video_frame->visible_rect().height()) {
203 bitmap->setConfig(SkBitmap::kARGB_8888_Config, 201 bitmap->setConfig(SkBitmap::kARGB_8888_Config,
204 video_frame->visible_rect().width(), 202 video_frame->visible_rect().width(),
205 video_frame->visible_rect().height()); 203 video_frame->visible_rect().height());
206 bitmap->allocPixels(); 204 bitmap->allocPixels();
207 bitmap->setIsVolatile(true); 205 bitmap->setIsVolatile(true);
208 } 206 }
209 207
210 bitmap->lockPixels(); 208 bitmap->lockPixels();
211 209
212 size_t y_offset = 0; 210 size_t y_offset = 0;
213 size_t uv_offset = 0; 211 size_t uv_offset = 0;
214 if (IsEitherYV12OrYV12AOrYV16(video_frame->format())) { 212 if (IsEitherYUVOrYUVA(video_frame->format())) {
215 int y_shift = (video_frame->format() == media::VideoFrame::YV16) ? 0 : 1; 213 int y_shift = (video_frame->format() == media::VideoFrame::YV16) ? 0 : 1;
216 // Use the "left" and "top" of the destination rect to locate the offset 214 // Use the "left" and "top" of the destination rect to locate the offset
217 // in Y, U and V planes. 215 // in Y, U and V planes.
218 y_offset = (video_frame->stride(media::VideoFrame::kYPlane) * 216 y_offset = (video_frame->stride(media::VideoFrame::kYPlane) *
219 video_frame->visible_rect().y()) + 217 video_frame->visible_rect().y()) +
220 video_frame->visible_rect().x(); 218 video_frame->visible_rect().x();
221 // For format YV12, there is one U, V value per 2x2 block. 219 // For format YV12, there is one U, V value per 2x2 block.
222 // For format YV16, there is one U, V value per 2x1 block. 220 // For format YV16, there is one U, V value per 2x1 block.
223 uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) * 221 uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) *
224 (video_frame->visible_rect().y() >> y_shift)) + 222 (video_frame->visible_rect().y() >> y_shift)) +
225 (video_frame->visible_rect().x() >> 1); 223 (video_frame->visible_rect().x() >> 1);
226 } 224 }
227 225
228 switch (video_frame->format()) { 226 switch (video_frame->format()) {
229 case media::VideoFrame::YV12: 227 case media::VideoFrame::YV12:
228 case media::VideoFrame::I420:
230 case media::VideoFrame::YV12J: 229 case media::VideoFrame::YV12J:
231 media::ConvertYUVToRGB32( 230 media::ConvertYUVToRGB32(
232 video_frame->data(media::VideoFrame::kYPlane) + y_offset, 231 video_frame->data(media::VideoFrame::kYPlane) + y_offset,
233 video_frame->data(media::VideoFrame::kUPlane) + uv_offset, 232 video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
234 video_frame->data(media::VideoFrame::kVPlane) + uv_offset, 233 video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
235 static_cast<uint8*>(bitmap->getPixels()), 234 static_cast<uint8*>(bitmap->getPixels()),
236 video_frame->visible_rect().width(), 235 video_frame->visible_rect().width(),
237 video_frame->visible_rect().height(), 236 video_frame->visible_rect().height(),
238 video_frame->stride(media::VideoFrame::kYPlane), 237 video_frame->stride(media::VideoFrame::kYPlane),
239 video_frame->stride(media::VideoFrame::kUPlane), 238 video_frame->stride(media::VideoFrame::kUPlane),
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 } 298 }
300 299
301 SkRect dest; 300 SkRect dest;
302 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); 301 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
303 302
304 SkPaint paint; 303 SkPaint paint;
305 paint.setAlpha(alpha); 304 paint.setAlpha(alpha);
306 305
307 // Paint black rectangle if there isn't a frame available or the 306 // Paint black rectangle if there isn't a frame available or the
308 // frame has an unexpected format. 307 // frame has an unexpected format.
309 if (!video_frame || 308 if (!video_frame || !IsEitherYUVOrYUVAOrNative(video_frame->format())) {
310 !IsEitherYV12OrYV12AOrYV16OrNative(video_frame->format())) {
311 canvas->drawRect(dest, paint); 309 canvas->drawRect(dest, paint);
312 return; 310 return;
313 } 311 }
314 312
315 // Scale and convert to RGB in one step if we can. 313 // Scale and convert to RGB in one step if we can.
316 if (CanFastPaint(canvas, alpha, video_frame->format())) { 314 if (CanFastPaint(canvas, alpha, video_frame->format())) {
317 FastPaint(video_frame, canvas, dest); 315 FastPaint(video_frame, canvas, dest);
318 return; 316 return;
319 } 317 }
320 318
321 // Check if we should convert and update |last_frame_|. 319 // Check if we should convert and update |last_frame_|.
322 if (last_frame_.isNull() || 320 if (last_frame_.isNull() ||
323 video_frame->GetTimestamp() != last_frame_timestamp_) { 321 video_frame->GetTimestamp() != last_frame_timestamp_) {
324 ConvertVideoFrameToBitmap(video_frame, &last_frame_); 322 ConvertVideoFrameToBitmap(video_frame, &last_frame_);
325 last_frame_timestamp_ = video_frame->GetTimestamp(); 323 last_frame_timestamp_ = video_frame->GetTimestamp();
326 } 324 }
327 325
328 // Do a slower paint using |last_frame_|. 326 // Do a slower paint using |last_frame_|.
329 paint.setFilterBitmap(true); 327 paint.setFilterBitmap(true);
330 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); 328 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint);
331 } 329 }
332 330
333 } // namespace media 331 } // namespace media
OLDNEW
« no previous file with comments | « content/renderer/media/webmediaplayer_ms.cc ('k') | media/tools/player_x11/gl_video_renderer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698