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

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: rebase Created 7 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
« no previous file with comments | « media/filters/pipeline_integration_test.cc ('k') | media/filters/vpx_video_decoder.h » ('j') | 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 "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 29 matching lines...) Expand all
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 = media::YV16;
72 int y_shift = 0; 83 int y_shift = 0;
73 if (video_frame->format() == media::VideoFrame::YV12) { 84 if (video_frame->format() == media::VideoFrame::YV12 ||
85 video_frame->format() == media::VideoFrame::YV12A) {
74 yuv_type = media::YV12; 86 yuv_type = media::YV12;
75 y_shift = 1; 87 y_shift = 1;
76 } 88 }
77 89
78 // Transform the destination rectangle to local coordinates. 90 // Transform the destination rectangle to local coordinates.
79 const SkMatrix& local_matrix = canvas->getTotalMatrix(); 91 const SkMatrix& local_matrix = canvas->getTotalMatrix();
80 SkRect local_dest_rect; 92 SkRect local_dest_rect;
81 local_matrix.mapRect(&local_dest_rect, dest_rect); 93 local_matrix.mapRect(&local_dest_rect, dest_rect);
82 94
83 // After projecting the destination rectangle to local coordinates, round 95 // 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); 175 media::FILTER_BILINEAR);
164 bitmap.unlockPixels(); 176 bitmap.unlockPixels();
165 } 177 }
166 178
167 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data. 179 // Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data.
168 // 180 //
169 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|. 181 // |bitmap| will be (re)allocated to match the dimensions of |video_frame|.
170 static void ConvertVideoFrameToBitmap( 182 static void ConvertVideoFrameToBitmap(
171 const scoped_refptr<media::VideoFrame>& video_frame, 183 const scoped_refptr<media::VideoFrame>& video_frame,
172 SkBitmap* bitmap) { 184 SkBitmap* bitmap) {
173 DCHECK(IsEitherYV12OrYV16OrNative(video_frame->format())) 185 DCHECK(IsEitherYV12OrYV12AOrYV16OrNative(video_frame->format()))
174 << video_frame->format(); 186 << video_frame->format();
175 if (IsEitherYV12OrYV16(video_frame->format())) { 187 if (IsEitherYV12OrYV12AOrYV16(video_frame->format())) {
176 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane), 188 DCHECK_EQ(video_frame->stride(media::VideoFrame::kUPlane),
177 video_frame->stride(media::VideoFrame::kVPlane)); 189 video_frame->stride(media::VideoFrame::kVPlane));
178 } 190 }
179 191
180 // Check if |bitmap| needs to be (re)allocated. 192 // Check if |bitmap| needs to be (re)allocated.
181 if (bitmap->isNull() || 193 if (bitmap->isNull() ||
182 bitmap->width() != video_frame->visible_rect().width() || 194 bitmap->width() != video_frame->visible_rect().width() ||
183 bitmap->height() != video_frame->visible_rect().height()) { 195 bitmap->height() != video_frame->visible_rect().height()) {
184 bitmap->setConfig(SkBitmap::kARGB_8888_Config, 196 bitmap->setConfig(SkBitmap::kARGB_8888_Config,
185 video_frame->visible_rect().width(), 197 video_frame->visible_rect().width(),
186 video_frame->visible_rect().height()); 198 video_frame->visible_rect().height());
187 bitmap->allocPixels(); 199 bitmap->allocPixels();
188 bitmap->setIsVolatile(true); 200 bitmap->setIsVolatile(true);
189 } 201 }
190 202
191 bitmap->lockPixels(); 203 bitmap->lockPixels();
192 if (IsEitherYV12OrYV16(video_frame->format())) {
193 media::YUVType yuv_type = media::YV16;
194 int y_shift = 0;
195 if (video_frame->format() == media::VideoFrame::YV12) {
196 yuv_type = media::YV12;
197 y_shift = 1;
198 }
199 204
205 size_t y_offset = 0;
206 size_t uv_offset = 0;
207 if (IsEitherYV12OrYV12AOrYV16(video_frame->format())) {
208 int y_shift = (video_frame->format() == media::VideoFrame::YV16) ? 0 : 1;
200 // Use the "left" and "top" of the destination rect to locate the offset 209 // Use the "left" and "top" of the destination rect to locate the offset
201 // in Y, U and V planes. 210 // in Y, U and V planes.
202 size_t y_offset = (video_frame->stride(media::VideoFrame::kYPlane) * 211 y_offset = (video_frame->stride(media::VideoFrame::kYPlane) *
203 video_frame->visible_rect().y()) + 212 video_frame->visible_rect().y()) +
204 video_frame->visible_rect().x(); 213 video_frame->visible_rect().x();
205
206 // For format YV12, there is one U, V value per 2x2 block. 214 // 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. 215 // For format YV16, there is one U, V value per 2x1 block.
208 size_t uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) * 216 uv_offset = (video_frame->stride(media::VideoFrame::kUPlane) *
209 (video_frame->visible_rect().y() >> y_shift)) + 217 (video_frame->visible_rect().y() >> y_shift)) +
210 (video_frame->visible_rect().x() >> 1); 218 (video_frame->visible_rect().x() >> 1);
211 uint8* frame_clip_y = 219 }
212 video_frame->data(media::VideoFrame::kYPlane) + y_offset; 220 switch (video_frame->format()) {
213 uint8* frame_clip_u = 221 case media::VideoFrame::YV12:
214 video_frame->data(media::VideoFrame::kUPlane) + uv_offset; 222 media::ConvertYUVToRGB32(
215 uint8* frame_clip_v = 223 video_frame->data(media::VideoFrame::kYPlane) + y_offset,
216 video_frame->data(media::VideoFrame::kVPlane) + uv_offset; 224 video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
225 video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
226 static_cast<uint8*>(bitmap->getPixels()),
227 video_frame->visible_rect().width(),
228 video_frame->visible_rect().height(),
229 video_frame->stride(media::VideoFrame::kYPlane),
230 video_frame->stride(media::VideoFrame::kUPlane),
231 bitmap->rowBytes(),
232 media::YV12);
233 break;
217 234
218 media::ConvertYUVToRGB32(frame_clip_y, 235 case media::VideoFrame::YV16:
219 frame_clip_u, 236 media::ConvertYUVToRGB32(
220 frame_clip_v, 237 video_frame->data(media::VideoFrame::kYPlane) + y_offset,
221 static_cast<uint8*>(bitmap->getPixels()), 238 video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
222 video_frame->visible_rect().width(), 239 video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
223 video_frame->visible_rect().height(), 240 static_cast<uint8*>(bitmap->getPixels()),
224 video_frame->stride(media::VideoFrame::kYPlane), 241 video_frame->visible_rect().width(),
225 video_frame->stride(media::VideoFrame::kUPlane), 242 video_frame->visible_rect().height(),
226 bitmap->rowBytes(), 243 video_frame->stride(media::VideoFrame::kYPlane),
227 yuv_type); 244 video_frame->stride(media::VideoFrame::kUPlane),
228 } else { 245 bitmap->rowBytes(),
229 DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE); 246 media::YV16);
230 video_frame->ReadPixelsFromNativeTexture(*bitmap); 247 break;
248
249 case media::VideoFrame::YV12A:
250 media::ConvertYUVAToARGB(
251 video_frame->data(media::VideoFrame::kYPlane) + y_offset,
252 video_frame->data(media::VideoFrame::kUPlane) + uv_offset,
253 video_frame->data(media::VideoFrame::kVPlane) + uv_offset,
254 video_frame->data(media::VideoFrame::kAPlane),
255 static_cast<uint8*>(bitmap->getPixels()),
256 video_frame->visible_rect().width(),
257 video_frame->visible_rect().height(),
258 video_frame->stride(media::VideoFrame::kYPlane),
259 video_frame->stride(media::VideoFrame::kUPlane),
260 video_frame->stride(media::VideoFrame::kAPlane),
261 bitmap->rowBytes(),
262 media::YV12);
263 break;
264
265 case media::VideoFrame::NATIVE_TEXTURE:
266 DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE);
267 video_frame->ReadPixelsFromNativeTexture(*bitmap);
268 break;
269
270 default:
271 NOTREACHED();
272 break;
231 } 273 }
232 bitmap->notifyPixelsChanged(); 274 bitmap->notifyPixelsChanged();
233 bitmap->unlockPixels(); 275 bitmap->unlockPixels();
234 } 276 }
235 277
236 SkCanvasVideoRenderer::SkCanvasVideoRenderer() 278 SkCanvasVideoRenderer::SkCanvasVideoRenderer()
237 : last_frame_timestamp_(media::kNoTimestamp()) { 279 : last_frame_timestamp_(media::kNoTimestamp()) {
238 } 280 }
239 281
240 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} 282 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {}
241 283
242 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, 284 void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame,
243 SkCanvas* canvas, 285 SkCanvas* canvas,
244 const gfx::RectF& dest_rect, 286 const gfx::RectF& dest_rect,
245 uint8_t alpha) { 287 uint8_t alpha) {
246 if (alpha == 0) { 288 if (alpha == 0) {
247 return; 289 return;
248 } 290 }
249 291
250 SkRect dest; 292 SkRect dest;
251 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); 293 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
252 294
253 SkPaint paint; 295 SkPaint paint;
254 paint.setAlpha(alpha); 296 paint.setAlpha(alpha);
255 297
256 // Paint black rectangle if there isn't a frame available or the 298 // Paint black rectangle if there isn't a frame available or the
257 // frame has an unexpected format. 299 // frame has an unexpected format.
258 if (!video_frame || !IsEitherYV12OrYV16OrNative(video_frame->format())) { 300 if (!video_frame ||
301 !IsEitherYV12OrYV12AOrYV16OrNative(video_frame->format())) {
259 canvas->drawRect(dest, paint); 302 canvas->drawRect(dest, paint);
260 return; 303 return;
261 } 304 }
262 305
263 // Scale and convert to RGB in one step if we can. 306 // Scale and convert to RGB in one step if we can.
264 if (CanFastPaint(canvas, alpha, video_frame->format())) { 307 if (CanFastPaint(canvas, alpha, video_frame->format())) {
265 FastPaint(video_frame, canvas, dest); 308 FastPaint(video_frame, canvas, dest);
266 return; 309 return;
267 } 310 }
268 311
269 // Check if we should convert and update |last_frame_|. 312 // Check if we should convert and update |last_frame_|.
270 if (last_frame_.isNull() || 313 if (last_frame_.isNull() ||
271 video_frame->GetTimestamp() != last_frame_timestamp_) { 314 video_frame->GetTimestamp() != last_frame_timestamp_) {
272 ConvertVideoFrameToBitmap(video_frame, &last_frame_); 315 ConvertVideoFrameToBitmap(video_frame, &last_frame_);
273 last_frame_timestamp_ = video_frame->GetTimestamp(); 316 last_frame_timestamp_ = video_frame->GetTimestamp();
274 } 317 }
275 318
276 // Do a slower paint using |last_frame_|. 319 // Do a slower paint using |last_frame_|.
277 paint.setFilterBitmap(true); 320 paint.setFilterBitmap(true);
278 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); 321 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint);
279 } 322 }
280 323
281 } // namespace media 324 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/pipeline_integration_test.cc ('k') | media/filters/vpx_video_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698