Chromium Code Reviews| 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, |