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

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

Issue 12263013: media: Add support for playback of VP8 Alpha video streams (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressing comments on patchset 2 Created 7 years, 9 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 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 static bool IsEitherYV12OrYV12AOrYV16(media::VideoFrame::Format format) {
25 return IsEitherYV12OrYV16(format) ||
26 format == media::VideoFrame::YV12A;
27 }
28
29 static bool IsEitherYV12OrYV12AOrYV16OrNative(
30 media::VideoFrame::Format format) {
31 return IsEitherYV12OrYV16OrNative(format) ||
32 format == media::VideoFrame::YV12A;
33 }
34
24 // CanFastPaint is a helper method to determine the conditions for fast 35 // CanFastPaint is a helper method to determine the conditions for fast
25 // painting. The conditions are: 36 // painting. The conditions are:
26 // 1. No skew in canvas matrix. 37 // 1. No skew in canvas matrix.
27 // 2. No flipping nor mirroring. 38 // 2. No flipping nor mirroring.
28 // 3. Canvas has pixel format ARGB8888. 39 // 3. Canvas has pixel format ARGB8888.
29 // 4. Canvas is opaque. 40 // 4. Canvas is opaque.
30 // 5. Frame format is YV12 or YV16. 41 // 5. Frame format is YV12 or YV16.
31 // 42 //
32 // TODO(hclam): The fast paint method should support flipping and mirroring. 43 // TODO(hclam): The fast paint method should support flipping and mirroring.
33 // Disable the flipping and mirroring checks once we have it. 44 // Disable the flipping and mirroring checks once we have it.
(...skipping 27 matching lines...) Expand all
61 // CanFastPaint() is used to determine the conditions. 72 // CanFastPaint() is used to determine the conditions.
62 static void FastPaint( 73 static void FastPaint(
63 const scoped_refptr<media::VideoFrame>& video_frame, 74 const scoped_refptr<media::VideoFrame>& video_frame,
64 SkCanvas* canvas, 75 SkCanvas* canvas,
65 const SkRect& dest_rect) { 76 const SkRect& dest_rect) {
66 DCHECK(IsEitherYV12OrYV16(video_frame->format())) << video_frame->format(); 77 DCHECK(IsEitherYV12OrYV16(video_frame->format())) << video_frame->format();
67 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), 78 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane),
68 video_frame->stride(media::VideoFrame::kVPlane)); 79 video_frame->stride(media::VideoFrame::kVPlane));
69 80
70 const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true); 81 const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(true);
71 media::YUVType yuv_type = media::YV16; 82 media::YUVType yuv_type = video_frame->format() == media::VideoFrame::YV12 ||
83 video_frame->format() == media::VideoFrame::YV12A ?
84 media::YV12 : media::YV16;
72 int y_shift = 0; 85 int y_shift = 0;
73 if (video_frame->format() == media::VideoFrame::YV12) { 86 if (video_frame->format() == media::VideoFrame::YV12 ||
87 video_frame->format() == media::VideoFrame::YV12A) {
74 yuv_type = media::YV12; 88 yuv_type = media::YV12;
75 y_shift = 1; 89 y_shift = 1;
76 } 90 }
77 91
78 // Transform the destination rectangle to local coordinates. 92 // Transform the destination rectangle to local coordinates.
79 const SkMatrix& local_matrix = canvas->getTotalMatrix(); 93 const SkMatrix& local_matrix = canvas->getTotalMatrix();
80 SkRect local_dest_rect; 94 SkRect local_dest_rect;
81 local_matrix.mapRect(&local_dest_rect, dest_rect); 95 local_matrix.mapRect(&local_dest_rect, dest_rect);
82 96
83 // After projecting the destination rectangle to local coordinates, round 97 // After projecting the destination rectangle to local coordinates, round
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 media::FILTER_BILINEAR); 177 media::FILTER_BILINEAR);
164 bitmap.unlockPixels(); 178 bitmap.unlockPixels();
165 } 179 }
166 180
167 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data. 181 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data.
168 // 182 //
169 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|. 183 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|.
170 static void ConvertVideoFrameToBitmap( 184 static void ConvertVideoFrameToBitmap(
171 const scoped_refptr<media::VideoFrame>& video_frame, 185 const scoped_refptr<media::VideoFrame>& video_frame,
172 SkBitmap* bitmap) { 186 SkBitmap* bitmap) {
173 DCHECK(IsEitherYV12OrYV16OrNative(video_frame->format())) 187 DCHECK(IsEitherYV12OrYV12AOrYV16OrNative(video_frame->format()))
174 << video_frame->format(); 188 << video_frame->format();
175 if (IsEitherYV12OrYV16(video_frame->format())) { 189 if (IsEitherYV12OrYV12AOrYV16(video_frame->format())) {
176 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), 190 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane),
177 video_frame->stride(media::VideoFrame::kVPlane)); 191 video_frame->stride(media::VideoFrame::kVPlane));
178 } 192 }
179 193
180 // Check if |bitmap| needs to be (re)allocated. 194 // Check if |bitmap| needs to be (re)allocated.
181 if (bitmap->isNull() || 195 if (bitmap->isNull() ||
182 bitmap->width() != video_frame->visible_rect().width() || 196 bitmap->width() != video_frame->visible_rect().width() ||
183 bitmap->height() != video_frame->visible_rect().height()) { 197 bitmap->height() != video_frame->visible_rect().height()) {
184 bitmap->setConfig(SkBitmap::kARGB_8888_Config, 198 bitmap->setConfig(SkBitmap::kARGB_8888_Config,
185 video_frame->visible_rect().width(), 199 video_frame->visible_rect().width(),
186 video_frame->visible_rect().height()); 200 video_frame->visible_rect().height());
187 bitmap->allocPixels(); 201 bitmap->allocPixels();
188 bitmap->setIsVolatile(true); 202 bitmap->setIsVolatile(true);
189 } 203 }
190 204
191 bitmap->lockPixels(); 205 bitmap->lockPixels();
192 if (IsEitherYV12OrYV16(video_frame->format())) { 206
193 media::YUVType yuv_type = media::YV16; 207 media::YUVType yuv_type;
208 uint8* frame_clip_y;
209 uint8* frame_clip_u;
210 uint8* frame_clip_v;
211 if (IsEitherYV12OrYV12AOrYV16(video_frame->format())) {
212 yuv_type = media::YV16;
213
194 int y_shift = 0; 214 int y_shift = 0;
195 if (video_frame->format() == media::VideoFrame::YV12) { 215 if (video_frame->format() == media::VideoFrame::YV12 ||
216 video_frame->format() == media::VideoFrame::YV12A) {
196 yuv_type = media::YV12; 217 yuv_type = media::YV12;
197 y_shift = 1; 218 y_shift = 1;
198 } 219 }
199 220
200 // Use the "left" and "top" of the destination rect to locate the offset 221 // Use the "left" and "top" of the destination rect to locate the offset
201 // in Y, U and V planes. 222 // in Y, U and V planes.
202 size_t y_offset = (video_frame->stride(media::VideoFrame::kYPlane) * 223 size_t y_offset = (video_frame->stride(media::VideoFrame::kYPlane) *
203 video_frame->visible_rect().y()) + 224 video_frame->visible_rect().y()) +
204 video_frame->visible_rect().x(); 225 video_frame->visible_rect().x();
205 226
206 // For format YV12, there is one U, V value per 2x2 block. 227 // For format YV12, there is one U, V value per 2x2 block.
207 // For format YV16, there is one U, V value per 2x1 block. 228 // For format YV16, there is one U, V value per 2x1 block.
208 size_t uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) * 229 size_t uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) *
209 (video_frame->visible_rect().y() >> y_shift)) + 230 (video_frame->visible_rect().y() >> y_shift)) +
210 (video_frame->visible_rect().x() >> 1); 231 (video_frame->visible_rect().x() >> 1);
211 uint8* frame_clip_y = 232 frame_clip_y = video_frame->data(media::VideoFrame::kYPlane) + y_offset;
212 video_frame->data(media::VideoFrame::kYPlane) + y_offset; 233 frame_clip_u = video_frame->data(media::VideoFrame::kUPlane) + uv_offset;
213 uint8* frame_clip_u = 234 frame_clip_v = video_frame->data(media::VideoFrame::kVPlane) + uv_offset;
214 video_frame->data(media::VideoFrame::kUPlane) + uv_offset; 235 }
215 uint8* frame_clip_v = 236 switch (video_frame->format()) {
216 video_frame->data(media::VideoFrame::kVPlane) + uv_offset; 237 case media::VideoFrame::YV12:
238 case media::VideoFrame::YV16:
239 media::ConvertYUVToRGB32(frame_clip_y,
240 frame_clip_u,
241 frame_clip_v,
242 static_cast<uint8*>(bitmap->getPixels()),
243 video_frame->visible_rect().width(),
244 video_frame->visible_rect().height(),
245 video_frame->stride(media::VideoFrame::kYPlane),
246 video_frame->stride(media::VideoFrame::kUPlane),
247 bitmap->rowBytes(),
248 yuv_type);
249 break;
217 250
218 media::ConvertYUVToRGB32(frame_clip_y, 251 case media::VideoFrame::YV12A:
219 frame_clip_u, 252 media::ConvertYUVAToARGB(frame_clip_y,
220 frame_clip_v, 253 frame_clip_u,
221 static_cast<uint8*>(bitmap->getPixels()), 254 frame_clip_v,
222 video_frame->visible_rect().width(), 255 video_frame->data(media::VideoFrame::kAPlane),
223 video_frame->visible_rect().height(), 256 static_cast<uint8*>(bitmap->getPixels()),
224 video_frame->stride(media::VideoFrame::kYPlane), 257 video_frame->visible_rect().width(),
225 video_frame->stride(media::VideoFrame::kUPlane), 258 video_frame->visible_rect().height(),
226 bitmap->rowBytes(), 259 video_frame->stride(media::VideoFrame::kYPlane),
227 yuv_type); 260 video_frame->stride(media::VideoFrame::kUPlane),
228 } else { 261 video_frame->stride(media::VideoFrame::kAPlane),
229 DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE); 262 bitmap->rowBytes(),
230 video_frame->ReadPixelsFromNativeTexture(bitmap->getPixels()); 263 media::YV12);
Tom Finegan 2013/02/25 22:56:06 Do we need a comment here about why this is YV12?
264 break;
265
266 case media::VideoFrame::NATIVE_TEXTURE:
267 DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE);
268 video_frame->ReadPixelsFromNativeTexture(bitmap->getPixels());
269 break;
270
271 default:
272 NOTREACHED();
273 break;
231 } 274 }
232 bitmap->notifyPixelsChanged(); 275 bitmap->notifyPixelsChanged();
233 bitmap->unlockPixels(); 276 bitmap->unlockPixels();
234 } 277 }
235 278
236 SkCanvasVideoRenderer::SkCanvasVideoRenderer() 279 SkCanvasVideoRenderer::SkCanvasVideoRenderer()
237 : last_frame_timestamp_(media::kNoTimestamp()) { 280 : last_frame_timestamp_(media::kNoTimestamp()) {
238 } 281 }
239 282
240 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} 283 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {}
241 284
242 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, 285 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame,
243 SkCanvas* canvas, 286 SkCanvas* canvas,
244 const gfx::RectF& dest_rect, 287 const gfx::RectF& dest_rect,
245 uint8_t alpha) { 288 uint8_t alpha) {
246 if (alpha == 0) { 289 if (alpha == 0) {
247 return; 290 return;
248 } 291 }
249 292
250 SkRect dest; 293 SkRect dest;
251 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); 294 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
252 295
253 SkPaint paint; 296 SkPaint paint;
254 paint.setAlpha(alpha); 297 paint.setAlpha(alpha);
255 298
256 // Paint black rectangle if there isn't a frame available or the 299 // Paint black rectangle if there isn't a frame available or the
257 // frame has an unexpected format. 300 // frame has an unexpected format.
258 if (!video_frame || !IsEitherYV12OrYV16OrNative(video_frame->format())) { 301 if (!video_frame ||
302 !IsEitherYV12OrYV12AOrYV16OrNative(video_frame->format())) {
259 canvas->drawRect(dest, paint); 303 canvas->drawRect(dest, paint);
260 return; 304 return;
261 } 305 }
262 306
263 // Scale and convert to RGB in one step if we can. 307 // Scale and convert to RGB in one step if we can.
264 if (CanFastPaint(canvas, alpha, video_frame->format())) { 308 if (CanFastPaint(canvas, alpha, video_frame->format())) {
265 FastPaint(video_frame, canvas, dest); 309 FastPaint(video_frame, canvas, dest);
266 return; 310 return;
267 } 311 }
268 312
269 // Check if we should convert and update |last_frame_|. 313 // Check if we should convert and update |last_frame_|.
270 if (last_frame_.isNull() || 314 if (last_frame_.isNull() ||
271 video_frame->GetTimestamp() != last_frame_timestamp_) { 315 video_frame->GetTimestamp() != last_frame_timestamp_) {
272 ConvertVideoFrameToBitmap(video_frame, &last_frame_); 316 ConvertVideoFrameToBitmap(video_frame, &last_frame_);
273 last_frame_timestamp_ = video_frame->GetTimestamp(); 317 last_frame_timestamp_ = video_frame->GetTimestamp();
274 } 318 }
275 319
276 // Do a slower paint using |last_frame_|. 320 // Do a slower paint using |last_frame_|.
277 paint.setFilterBitmap(true); 321 paint.setFilterBitmap(true);
278 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); 322 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint);
279 } 323 }
280 324
281 } // namespace media 325 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698