Index: media/filters/skcanvas_video_renderer.cc |
diff --git a/media/filters/skcanvas_video_renderer.cc b/media/filters/skcanvas_video_renderer.cc |
index 003c1951a9b4010e93e612a347d645b22aa3f66a..c6a2b6b21b7010ad4b0bc3b5408d5b5eec7fb7af 100644 |
--- a/media/filters/skcanvas_video_renderer.cc |
+++ b/media/filters/skcanvas_video_renderer.cc |
@@ -9,6 +9,7 @@ |
#include "media/base/yuv_convert.h" |
#include "third_party/libyuv/include/libyuv.h" |
#include "third_party/skia/include/core/SkCanvas.h" |
+#include "third_party/skia/include/core/SkImageGenerator.h" |
#include "ui/gfx/skbitmap_operations.h" |
// Skia internal format depends on a platform. On Android it is ABGR, on others |
@@ -40,12 +41,11 @@ static bool IsYUVOrNative(media::VideoFrame::Format format) { |
return IsYUV(format) || format == media::VideoFrame::NATIVE_TEXTURE; |
} |
-// Converts a VideoFrame containing YUV data to a SkBitmap containing RGB data. |
-// |
-// |bitmap| will be (re)allocated to match the dimensions of |video_frame|. |
-static void ConvertVideoFrameToBitmap( |
+// Converts a |video_frame| to raw |rgb_pixels|. |
+static void ConvertVideoFrameToRGBPixels( |
const scoped_refptr<media::VideoFrame>& video_frame, |
- SkBitmap* bitmap) { |
+ void* rgb_pixels, |
+ size_t row_bytes) { |
DCHECK(IsYUVOrNative(video_frame->format())) |
<< video_frame->format(); |
if (IsYUV(video_frame->format())) { |
@@ -53,17 +53,6 @@ static void ConvertVideoFrameToBitmap( |
video_frame->stride(media::VideoFrame::kVPlane)); |
} |
- // Check if |bitmap| needs to be (re)allocated. |
- if (bitmap->isNull() || |
- bitmap->width() != video_frame->visible_rect().width() || |
- bitmap->height() != video_frame->visible_rect().height()) { |
- bitmap->allocN32Pixels(video_frame->visible_rect().width(), |
- video_frame->visible_rect().height()); |
- bitmap->setIsVolatile(true); |
- } |
- |
- bitmap->lockPixels(); |
- |
size_t y_offset = 0; |
size_t uv_offset = 0; |
if (IsYUV(video_frame->format())) { |
@@ -80,6 +69,8 @@ static void ConvertVideoFrameToBitmap( |
(video_frame->visible_rect().x() >> 1); |
} |
+ SkBitmap tmp; |
+ |
switch (video_frame->format()) { |
case media::VideoFrame::YV12: |
case media::VideoFrame::I420: |
@@ -90,8 +81,8 @@ static void ConvertVideoFrameToBitmap( |
video_frame->stride(media::VideoFrame::kUPlane), |
video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
video_frame->stride(media::VideoFrame::kVPlane), |
- static_cast<uint8*>(bitmap->getPixels()), |
- bitmap->rowBytes(), |
+ static_cast<uint8*>(rgb_pixels), |
+ row_bytes, |
video_frame->visible_rect().width(), |
video_frame->visible_rect().height()); |
break; |
@@ -101,12 +92,12 @@ static void ConvertVideoFrameToBitmap( |
video_frame->data(media::VideoFrame::kYPlane) + y_offset, |
video_frame->data(media::VideoFrame::kUPlane) + uv_offset, |
video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
- static_cast<uint8*>(bitmap->getPixels()), |
+ static_cast<uint8*>(rgb_pixels), |
video_frame->visible_rect().width(), |
video_frame->visible_rect().height(), |
video_frame->stride(media::VideoFrame::kYPlane), |
video_frame->stride(media::VideoFrame::kUPlane), |
- bitmap->rowBytes(), |
+ row_bytes, |
media::YV12J); |
break; |
@@ -118,8 +109,8 @@ static void ConvertVideoFrameToBitmap( |
video_frame->stride(media::VideoFrame::kUPlane), |
video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
video_frame->stride(media::VideoFrame::kVPlane), |
- static_cast<uint8*>(bitmap->getPixels()), |
- bitmap->rowBytes(), |
+ static_cast<uint8*>(rgb_pixels), |
+ row_bytes, |
video_frame->visible_rect().width(), |
video_frame->visible_rect().height()); |
break; |
@@ -133,13 +124,13 @@ static void ConvertVideoFrameToBitmap( |
video_frame->data(media::VideoFrame::kUPlane) + uv_offset, |
video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
video_frame->data(media::VideoFrame::kAPlane), |
- static_cast<uint8*>(bitmap->getPixels()), |
+ static_cast<uint8*>(rgb_pixels), |
video_frame->visible_rect().width(), |
video_frame->visible_rect().height(), |
video_frame->stride(media::VideoFrame::kYPlane), |
video_frame->stride(media::VideoFrame::kUPlane), |
video_frame->stride(media::VideoFrame::kAPlane), |
- bitmap->rowBytes(), |
+ row_bytes, |
media::YV12); |
break; |
@@ -151,17 +142,17 @@ static void ConvertVideoFrameToBitmap( |
video_frame->stride(media::VideoFrame::kUPlane), |
video_frame->data(media::VideoFrame::kVPlane) + uv_offset, |
video_frame->stride(media::VideoFrame::kVPlane), |
- static_cast<uint8*>(bitmap->getPixels()), |
- bitmap->rowBytes(), |
+ static_cast<uint8*>(rgb_pixels), |
+ row_bytes, |
video_frame->visible_rect().width(), |
video_frame->visible_rect().height()); |
#if SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \ |
SK_A32_SHIFT == 24 |
libyuv::ARGBToABGR( |
- static_cast<uint8*>(bitmap->getPixels()), |
- bitmap->rowBytes(), |
- static_cast<uint8*>(bitmap->getPixels()), |
- bitmap->rowBytes(), |
+ static_cast<uint8*>(rgb_pixels), |
+ row_bytes, |
+ static_cast<uint8*>(rgb_pixels), |
+ row_bytes, |
video_frame->visible_rect().width(), |
video_frame->visible_rect().height()); |
#endif |
@@ -169,24 +160,75 @@ static void ConvertVideoFrameToBitmap( |
case media::VideoFrame::NATIVE_TEXTURE: |
DCHECK_EQ(video_frame->format(), media::VideoFrame::NATIVE_TEXTURE); |
- video_frame->ReadPixelsFromNativeTexture(*bitmap); |
+ tmp.installPixels( |
+ SkImageInfo::MakeN32Premul(video_frame->visible_rect().width(), |
+ video_frame->visible_rect().height()), |
+ rgb_pixels, |
+ row_bytes); |
+ video_frame->ReadPixelsFromNativeTexture(tmp); |
break; |
default: |
NOTREACHED(); |
break; |
} |
- bitmap->notifyPixelsChanged(); |
- bitmap->unlockPixels(); |
} |
+// Generates an RGB image from a VideoFrame. |
+class VideoImageGenerator : public SkImageGenerator { |
+ public: |
+ VideoImageGenerator(scoped_refptr<VideoFrame> frame) : frame_(frame) {} |
scherkus (not reviewing)
2014/09/03 22:51:50
const-ref
|
+ protected: |
scherkus (not reviewing)
2014/09/03 22:51:50
don't forget to declare a virtual dtor
|
+ virtual bool onGetInfo(SkImageInfo* info) OVERRIDE { |
+ info->fWidth = frame_->visible_rect().width(); |
+ info->fHeight = frame_->visible_rect().height(); |
+ info->fColorType = kBGRA_8888_SkColorType; |
+ info->fAlphaType = kPremul_SkAlphaType; |
+ return true; |
+ } |
+ |
+ virtual bool onGetPixels(const SkImageInfo& info, |
+ void* pixels, |
+ size_t rowBytes, |
+ SkPMColor ctable[], |
+ int* ctableCount) OVERRIDE { |
+ // If skia couldn't do the YUV conversion, we will. |
+ ConvertVideoFrameToRGBPixels(frame_, pixels, rowBytes); |
+ return true; |
+ } |
+ |
+ virtual bool onGetYUV8Planes(SkISize sizes[3], |
+ void* planes[3], |
+ size_t rowBytes[3]) OVERRIDE { |
+ // Currently Skia only supports JPEG color range YUV. |
+ if (frame_->format() != VideoFrame::YV12J) |
+ return false; |
+ for (int plane = VideoFrame::kYPlane; plane <= VideoFrame::kVPlane; |
+ ++plane) { |
+ gfx::Size size; |
+ if (sizes) { |
+ size = VideoFrame::PlaneSize( |
+ frame_->format(), plane, frame_->coded_size()); |
+ sizes[plane].set(size.width(), size.height()); |
+ } |
+ if (rowBytes) |
+ rowBytes[plane] = frame_->row_bytes(plane); |
+ if (planes) |
+ planes[plane] = frame_->data(plane); |
+ } |
+ return true; |
+ } |
+ private: |
+ VideoFrame* frame_; |
scherkus (not reviewing)
2014/09/03 22:51:50
should we be holding onto a ref?
|
+}; |
+ |
SkCanvasVideoRenderer::SkCanvasVideoRenderer() |
: last_frame_timestamp_(media::kNoTimestamp()) { |
} |
SkCanvasVideoRenderer::~SkCanvasVideoRenderer() {} |
-void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, |
+void SkCanvasVideoRenderer::Paint(scoped_refptr<VideoFrame> video_frame, |
SkCanvas* canvas, |
const gfx::RectF& dest_rect, |
uint8 alpha, |
@@ -212,8 +254,14 @@ void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, |
// Check if we should convert and update |last_frame_|. |
if (last_frame_.isNull() || |
video_frame->timestamp() != last_frame_timestamp_) { |
- ConvertVideoFrameToBitmap(video_frame, &last_frame_); |
+ if (!SkInstallDiscardablePixelRef(new VideoImageGenerator(video_frame), |
+ &last_frame_)) { |
+ NOTREACHED(); |
+ } |
+ |
+ // FIXME: Perform this rotation on the canvas, rather than allocating a new |
scherkus (not reviewing)
2014/09/03 22:51:50
s/FIXME/TODO(username)/
rileya (GONE FROM CHROMIUM)
2014/09/05 20:03:08
done.
|
+ // bitmap and copying. |
switch (video_rotation) { |
case VIDEO_ROTATION_0: |
break; |
@@ -241,7 +289,7 @@ void SkCanvasVideoRenderer::Paint(media::VideoFrame* video_frame, |
canvas->drawBitmapRect(last_frame_, NULL, dest, &paint); |
} |
-void SkCanvasVideoRenderer::Copy(media::VideoFrame* video_frame, |
+void SkCanvasVideoRenderer::Copy(scoped_refptr<VideoFrame> video_frame, |
SkCanvas* canvas) { |
Paint(video_frame, |
canvas, |