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

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

Issue 569313003: Pass YUV color space information to Skia in VideoImageGenerator. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@videoimagegenerator
Patch Set: comment Created 6 years, 2 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 | « no previous file | 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 "third_party/libyuv/include/libyuv.h" 10 #include "third_party/libyuv/include/libyuv.h"
(...skipping 11 matching lines...) Expand all
22 SK_A32_SHIFT == 24 22 SK_A32_SHIFT == 24
23 #define LIBYUV_I420_TO_ARGB libyuv::I420ToABGR 23 #define LIBYUV_I420_TO_ARGB libyuv::I420ToABGR
24 #define LIBYUV_I422_TO_ARGB libyuv::I422ToABGR 24 #define LIBYUV_I422_TO_ARGB libyuv::I422ToABGR
25 #else 25 #else
26 #error Unexpected Skia ARGB_8888 layout! 26 #error Unexpected Skia ARGB_8888 layout!
27 #endif 27 #endif
28 28
29 namespace media { 29 namespace media {
30 30
31 static bool IsYUV(media::VideoFrame::Format format) { 31 static bool IsYUV(media::VideoFrame::Format format) {
32 return format == media::VideoFrame::YV12 || 32 switch (format) {
33 format == media::VideoFrame::YV16 || 33 case VideoFrame::YV12:
34 format == media::VideoFrame::I420 || 34 case VideoFrame::YV16:
35 format == media::VideoFrame::YV12A || 35 case VideoFrame::I420:
36 format == media::VideoFrame::YV12J || 36 case VideoFrame::YV12A:
37 format == media::VideoFrame::YV24; 37 case VideoFrame::YV12J:
38 case VideoFrame::YV24:
39 case VideoFrame::NV12:
40 return true;
41 case VideoFrame::UNKNOWN:
42 case VideoFrame::NATIVE_TEXTURE:
43 #if defined(VIDEO_HOLE)
44 case VideoFrame::HOLE:
45 #endif // defined(VIDEO_HOLE)
46 return false;
47 }
48 NOTREACHED() << "Invalid videoframe format provided: " << format;
49 return false;
50 }
51
52 static bool IsJPEGColorSpace(media::VideoFrame::Format format) {
53 switch (format) {
54 case VideoFrame::YV12J:
55 return true;
56 case VideoFrame::YV12:
57 case VideoFrame::YV16:
58 case VideoFrame::I420:
59 case VideoFrame::YV12A:
60 case VideoFrame::YV24:
61 case VideoFrame::NV12:
62 case VideoFrame::UNKNOWN:
63 case VideoFrame::NATIVE_TEXTURE:
64 #if defined(VIDEO_HOLE)
65 case VideoFrame::HOLE:
66 #endif // defined(VIDEO_HOLE)
67 return false;
68 }
69 NOTREACHED() << "Invalid videoframe format provided: " << format;
70 return false;
38 } 71 }
39 72
40 static bool IsYUVOrNative(media::VideoFrame::Format format) { 73 static bool IsYUVOrNative(media::VideoFrame::Format format) {
41 return IsYUV(format) || format == media::VideoFrame::NATIVE_TEXTURE; 74 return IsYUV(format) || format == media::VideoFrame::NATIVE_TEXTURE;
42 } 75 }
43 76
44 // Converts a |video_frame| to raw |rgb_pixels|. 77 // Converts a |video_frame| to raw |rgb_pixels|.
45 static void ConvertVideoFrameToRGBPixels( 78 static void ConvertVideoFrameToRGBPixels(
46 const scoped_refptr<media::VideoFrame>& video_frame, 79 const scoped_refptr<media::VideoFrame>& video_frame,
47 void* rgb_pixels, 80 void* rgb_pixels,
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 break; 204 break;
172 } 205 }
173 } 206 }
174 207
175 // Generates an RGB image from a VideoFrame. 208 // Generates an RGB image from a VideoFrame.
176 class VideoImageGenerator : public SkImageGenerator { 209 class VideoImageGenerator : public SkImageGenerator {
177 public: 210 public:
178 VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) : frame_(frame) {} 211 VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) : frame_(frame) {}
179 virtual ~VideoImageGenerator() {} 212 virtual ~VideoImageGenerator() {}
180 213
214 void set_frame(const scoped_refptr<VideoFrame>& frame) { frame_ = frame; }
215
181 protected: 216 protected:
182 virtual bool onGetInfo(SkImageInfo* info) OVERRIDE { 217 virtual bool onGetInfo(SkImageInfo* info) OVERRIDE {
183 info->fWidth = frame_->visible_rect().width(); 218 info->fWidth = frame_->visible_rect().width();
184 info->fHeight = frame_->visible_rect().height(); 219 info->fHeight = frame_->visible_rect().height();
185 info->fColorType = kN32_SkColorType; 220 info->fColorType = kN32_SkColorType;
186 info->fAlphaType = kPremul_SkAlphaType; 221 info->fAlphaType = kPremul_SkAlphaType;
187 return true; 222 return true;
188 } 223 }
189 224
190 virtual bool onGetPixels(const SkImageInfo& info, 225 virtual bool onGetPixels(const SkImageInfo& info,
191 void* pixels, 226 void* pixels,
192 size_t row_bytes, 227 size_t row_bytes,
193 SkPMColor ctable[], 228 SkPMColor ctable[],
194 int* ctable_count) OVERRIDE { 229 int* ctable_count) OVERRIDE {
195 if (!frame_.get()) 230 if (!frame_.get())
196 return false; 231 return false;
197 if (!pixels) 232 if (!pixels)
198 return true; 233 return true;
199 // If skia couldn't do the YUV conversion, we will. 234 // If skia couldn't do the YUV conversion, we will.
200 ConvertVideoFrameToRGBPixels(frame_, pixels, row_bytes); 235 ConvertVideoFrameToRGBPixels(frame_, pixels, row_bytes);
201 frame_ = NULL; 236 frame_ = NULL;
202 return true; 237 return true;
203 } 238 }
204 239
205 virtual bool onGetYUV8Planes(SkISize sizes[3], 240 virtual bool onGetYUV8Planes(SkISize sizes[3],
206 void* planes[3], 241 void* planes[3],
207 size_t row_bytes[3]) OVERRIDE { 242 size_t row_bytes[3],
208 if (!frame_.get()) 243 SkYUVColorSpace* color_space) OVERRIDE {
244 if (!frame_.get() || !IsYUV(frame_->format()))
209 return false; 245 return false;
210 // Currently Skia only supports JPEG color range YUV. 246
211 if (frame_->format() != VideoFrame::YV12J) 247 if (color_space) {
212 return false; 248 if (IsJPEGColorSpace(frame_->format()))
249 *color_space = kJPEG_SkYUVColorSpace;
250 else
251 *color_space = kRec601_SkYUVColorSpace;
252 }
253
213 for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane; 254 for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane;
214 ++plane) { 255 ++plane) {
215 if (sizes) { 256 if (sizes) {
216 gfx::Size size; 257 gfx::Size size;
217 size = VideoFrame::PlaneSize( 258 size =
218 frame_->format(), plane, frame_->coded_size()); 259 VideoFrame::PlaneSize(frame_->format(),
260 plane,
261 gfx::Size(frame_->visible_rect().width(),
262 frame_->visible_rect().height()));
219 sizes[plane].set(size.width(), size.height()); 263 sizes[plane].set(size.width(), size.height());
220 } 264 }
221 if (row_bytes) 265 if (row_bytes && planes) {
222 row_bytes[plane] = frame_->stride(plane); 266 size_t offset;
223 if (planes) 267 int y_shift = (frame_->format() == media::VideoFrame::YV16) ? 0 : 1;
224 planes[plane] = frame_->data(plane); 268 if (plane == media::VideoFrame::kYPlane) {
269 offset = (frame_->stride(media::VideoFrame::kYPlane) *
270 frame_->visible_rect().y()) +
271 frame_->visible_rect().x();
272 } else {
273 offset = (frame_->stride(media::VideoFrame::kUPlane) *
274 (frame_->visible_rect().y() >> y_shift)) +
275 (frame_->visible_rect().x() >> 1);
276 }
277 row_bytes[plane] = static_cast<size_t>(frame_->stride(plane));
278 planes[plane] = frame_->data(plane) + offset;
279 }
225 } 280 }
226 if (planes && row_bytes) 281 if (planes && row_bytes)
227 frame_ = NULL; 282 frame_ = NULL;
228 return true; 283 return true;
229 } 284 }
230 public:
231
232 virtual void set_frame(const scoped_refptr<VideoFrame>& frame) {
233 frame_ = frame;
234 }
235 285
236 private: 286 private:
237 scoped_refptr<VideoFrame> frame_; 287 scoped_refptr<VideoFrame> frame_;
238 }; 288 };
239 289
240 SkCanvasVideoRenderer::SkCanvasVideoRenderer() 290 SkCanvasVideoRenderer::SkCanvasVideoRenderer()
241 : generator_(NULL), 291 : generator_(NULL), last_frame_timestamp_(media::kNoTimestamp()) {
242 last_frame_timestamp_(media::kNoTimestamp()) {
243 last_frame_.setIsVolatile(true); 292 last_frame_.setIsVolatile(true);
244 } 293 }
245 294
246 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} 295 SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {}
247 296
248 void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame, 297 void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
249 SkCanvas* canvas, 298 SkCanvas* canvas,
250 const gfx::RectF& dest_rect, 299 const gfx::RectF& dest_rect,
251 uint8 alpha, 300 uint8 alpha,
252 SkXfermode::Mode mode, 301 SkXfermode::Mode mode,
253 VideoRotation video_rotation) { 302 VideoRotation video_rotation) {
254 if (alpha == 0) { 303 if (alpha == 0) {
255 return; 304 return;
256 } 305 }
257 306
258 SkRect dest; 307 SkRect dest;
259 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom()); 308 dest.set(dest_rect.x(), dest_rect.y(), dest_rect.right(), dest_rect.bottom());
260 309
261 SkPaint paint; 310 SkPaint paint;
262 paint.setAlpha(alpha); 311 paint.setAlpha(alpha);
263 312
264 // Paint black rectangle if there isn't a frame available or the 313 // Paint black rectangle if there isn't a frame available or the
265 // frame has an unexpected format. 314 // frame has an unexpected format.
266 if (!video_frame.get() || !IsYUVOrNative(video_frame->format())) { 315 if (!video_frame.get() || !IsYUVOrNative(video_frame->format())) {
267 canvas->drawRect(dest, paint); 316 canvas->drawRect(dest, paint);
317 canvas->flush();
268 return; 318 return;
269 } 319 }
270 320
271 // Check if we should convert and update |last_frame_|. 321 // Check if we should convert and update |last_frame_|.
272 if (last_frame_.isNull() || 322 if (last_frame_.isNull() ||
273 video_frame->timestamp() != last_frame_timestamp_) { 323 video_frame->timestamp() != last_frame_timestamp_) {
274 generator_ = new VideoImageGenerator(video_frame); 324 generator_ = new VideoImageGenerator(video_frame);
275 325
276 // Note: This takes ownership of |generator_|. 326 // Note: This takes ownership of |generator_|.
277 if (!SkInstallDiscardablePixelRef(generator_, &last_frame_)) { 327 if (!SkInstallDiscardablePixelRef(generator_, &last_frame_)) {
(...skipping 12 matching lines...) Expand all
290 case VIDEO_ROTATION_180: 340 case VIDEO_ROTATION_180:
291 last_frame_ = SkBitmapOperations::Rotate( 341 last_frame_ = SkBitmapOperations::Rotate(
292 last_frame_, SkBitmapOperations::ROTATION_180_CW); 342 last_frame_, SkBitmapOperations::ROTATION_180_CW);
293 break; 343 break;
294 case VIDEO_ROTATION_270: 344 case VIDEO_ROTATION_270:
295 last_frame_ = SkBitmapOperations::Rotate( 345 last_frame_ = SkBitmapOperations::Rotate(
296 last_frame_, SkBitmapOperations::ROTATION_270_CW); 346 last_frame_, SkBitmapOperations::ROTATION_270_CW);
297 break; 347 break;
298 } 348 }
299 349
350 // We copied the frame into a new bitmap and threw out the old one, so we
351 // no longer have a |generator_| around. This should be removed when the
352 // above TODO is addressed.
353 if (video_rotation != VIDEO_ROTATION_0)
354 generator_ = NULL;
355
300 last_frame_timestamp_ = video_frame->timestamp(); 356 last_frame_timestamp_ = video_frame->timestamp();
301 } else { 357 } else if (generator_) {
302 generator_->set_frame(video_frame); 358 generator_->set_frame(video_frame);
303 } 359 }
304 360
305 paint.setXfermodeMode(mode); 361 paint.setXfermodeMode(mode);
306 362
307 // Paint using |last_frame_|. 363 // Paint using |last_frame_|.
308 paint.setFilterLevel(SkPaint::kLow_FilterLevel); 364 paint.setFilterLevel(SkPaint::kLow_FilterLevel);
309 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); 365 canvas->drawBitmapRect(last_frame_, NULL, dest, &paint);
366 canvas->flush();
310 } 367 }
311 368
312 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame, 369 void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame,
313 SkCanvas* canvas) { 370 SkCanvas* canvas) {
314 Paint(video_frame, 371 Paint(video_frame,
315 canvas, 372 canvas,
316 video_frame->visible_rect(), 373 video_frame->visible_rect(),
317 0xff, 374 0xff,
318 SkXfermode::kSrc_Mode, 375 SkXfermode::kSrc_Mode,
319 media::VIDEO_ROTATION_0); 376 media::VIDEO_ROTATION_0);
320 } 377 }
321 378
322 } // namespace media 379 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698