summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwilliam.xie <william.xie@intel.com>2015-06-26 04:18:33 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-26 11:19:11 +0000
commit3c16245b5b52fc947a9a2765ab038d13b375d5e3 (patch)
tree99da17417665a4985992b6c4c8c043642822b52f
parent17fce99eb549c36e92ac2a35312aaf65803290e7 (diff)
downloadchromium_src-3c16245b5b52fc947a9a2765ab038d13b375d5e3.zip
chromium_src-3c16245b5b52fc947a9a2765ab038d13b375d5e3.tar.gz
chromium_src-3c16245b5b52fc947a9a2765ab038d13b375d5e3.tar.bz2
[Ozone] enable video scaling when playing on overlay
When video playback on overlay, framebuffer needs to be scaled according to the display size. Considerring overlay hardware doesn't support scaling well, this CL is target to enable video scaling by VPP (video post processing unit) to get video playback working with correct size on overlay. BUG=499220 TEST=Enable Ozone hardware overlay, play h264 video, zoom webpage, verify that video is scaling along with webpage Review URL: https://codereview.chromium.org/1156893002 Cr-Commit-Position: refs/heads/master@{#336352}
-rw-r--r--content/common/gpu/media/vaapi_drm_picture.cc119
-rw-r--r--content/common/gpu/media/vaapi_drm_picture.h22
-rw-r--r--ui/ozone/platform/cast/surface_factory_cast.cc4
-rw-r--r--ui/ozone/platform/drm/gpu/gbm_buffer.cc37
-rw-r--r--ui/ozone/platform/drm/gpu/gbm_buffer.h7
-rw-r--r--ui/ozone/public/native_pixmap.h10
6 files changed, 173 insertions, 26 deletions
diff --git a/content/common/gpu/media/vaapi_drm_picture.cc b/content/common/gpu/media/vaapi_drm_picture.cc
index bf694d2..66e4328 100644
--- a/content/common/gpu/media/vaapi_drm_picture.cc
+++ b/content/common/gpu/media/vaapi_drm_picture.cc
@@ -28,7 +28,8 @@ VaapiDrmPicture::VaapiDrmPicture(
const gfx::Size& size)
: VaapiPicture(picture_buffer_id, texture_id, size),
vaapi_wrapper_(vaapi_wrapper),
- make_context_current_(make_context_current) {
+ make_context_current_(make_context_current),
+ weak_this_factory_(this) {
}
VaapiDrmPicture::~VaapiDrmPicture() {
@@ -40,37 +41,24 @@ VaapiDrmPicture::~VaapiDrmPicture() {
}
}
-bool VaapiDrmPicture::Initialize() {
- // We want to create a VASurface and an EGLImage out of the same
- // memory buffer, so we can output decoded pictures to it using
- // VAAPI and also use it to paint with GL.
- ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
- ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
-
- // Create a buffer from Ozone.
- pixmap_ = factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size(),
- ui::SurfaceFactoryOzone::BGRA_8888,
- ui::SurfaceFactoryOzone::SCANOUT);
- if (!pixmap_) {
- LOG(ERROR) << "Failed creating an Ozone NativePixmap";
- return false;
- }
-
+scoped_refptr<VASurface> VaapiDrmPicture::CreateVASurfaceForPixmap(
+ scoped_refptr<ui::NativePixmap> pixmap,
+ gfx::Size pixmap_size) {
// Get the dmabuf of the created buffer.
- int dmabuf_fd = pixmap_->GetDmaBufFd();
+ int dmabuf_fd = pixmap->GetDmaBufFd();
if (dmabuf_fd < 0) {
LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap";
- return false;
+ return nullptr;
}
- int dmabuf_pitch = pixmap_->GetDmaBufPitch();
+ int dmabuf_pitch = pixmap->GetDmaBufPitch();
// Create a VASurface out of the created buffer using the dmabuf.
VASurfaceAttribExternalBuffers va_attrib_extbuf;
memset(&va_attrib_extbuf, 0, sizeof(va_attrib_extbuf));
va_attrib_extbuf.pixel_format = VA_FOURCC_BGRX;
- va_attrib_extbuf.width = size().width();
- va_attrib_extbuf.height = size().height();
- va_attrib_extbuf.data_size = size().height() * dmabuf_pitch;
+ va_attrib_extbuf.width = pixmap_size.width();
+ va_attrib_extbuf.height = pixmap_size.height();
+ va_attrib_extbuf.data_size = pixmap_size.height() * dmabuf_pitch;
va_attrib_extbuf.num_planes = 1;
va_attrib_extbuf.pitches[0] = dmabuf_pitch;
va_attrib_extbuf.offsets[0] = 0;
@@ -92,13 +80,49 @@ bool VaapiDrmPicture::Initialize() {
va_attribs[1].value.type = VAGenericValueTypePointer;
va_attribs[1].value.value.p = &va_attrib_extbuf;
- va_surface_ = vaapi_wrapper_->CreateUnownedSurface(VA_RT_FORMAT_RGB32, size(),
- va_attribs);
- if (!va_surface_) {
+ scoped_refptr<VASurface> va_surface = vaapi_wrapper_->CreateUnownedSurface(
+ VA_RT_FORMAT_RGB32, pixmap_size, va_attribs);
+ if (!va_surface) {
LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap";
+ return nullptr;
+ }
+
+ return va_surface;
+}
+
+scoped_refptr<ui::NativePixmap> VaapiDrmPicture::CreateNativePixmap(
+ gfx::Size size) {
+ ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
+ ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
+
+ // Create a buffer from Ozone.
+ return factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size,
+ ui::SurfaceFactoryOzone::BGRA_8888,
+ ui::SurfaceFactoryOzone::SCANOUT);
+}
+
+bool VaapiDrmPicture::Initialize() {
+ // We want to create a VASurface and an EGLImage out of the same
+ // memory buffer, so we can output decoded pictures to it using
+ // VAAPI and also use it to paint with GL.
+ pixmap_ = CreateNativePixmap(size());
+ if (!pixmap_) {
+ LOG(ERROR) << "Failed creating an Ozone NativePixmap";
+ return false;
+ }
+
+ va_surface_ = CreateVASurfaceForPixmap(pixmap_, size());
+ if (!va_surface_) {
+ LOG(ERROR) << "Failed creating VASurface for NativePixmap";
return false;
}
+ // Weak pointers can only bind to methods without return values,
+ // hence we cannot bind ScalePixmap here. Instead we use a
+ // static function to solve this problem.
+ pixmap_->SetScalingCallback(base::Bind(&VaapiDrmPicture::CallScalePixmap,
+ weak_this_factory_.GetWeakPtr()));
+
if (!make_context_current_.Run())
return false;
@@ -124,6 +148,49 @@ bool VaapiDrmPicture::DownloadFromSurface(
va_surface_->id(), va_surface_->size());
}
+// static
+scoped_refptr<ui::NativePixmap> VaapiDrmPicture::CallScalePixmap(
+ base::WeakPtr<VaapiDrmPicture> weak_ptr,
+ gfx::Size new_size) {
+ if (!weak_ptr.get()) {
+ LOG(ERROR) << "Failed scaling NativePixmap as scaling "
+ "unit(VaapiDrmPicture) is deleted";
+ return nullptr;
+ }
+ return weak_ptr->ScalePixmap(new_size);
+}
+
+scoped_refptr<ui::NativePixmap> VaapiDrmPicture::ScalePixmap(
+ gfx::Size new_size) {
+ if (!scaled_va_surface_.get() || scaled_va_surface_->size() != new_size) {
+ scaled_pixmap_ = CreateNativePixmap(new_size);
+ if (!scaled_pixmap_) {
+ LOG(ERROR) << "Failed creating an Ozone NativePixmap for scaling";
+ scaled_va_surface_ = nullptr;
+ return nullptr;
+ }
+ scaled_va_surface_ = CreateVASurfaceForPixmap(scaled_pixmap_, new_size);
+ if (!scaled_va_surface_) {
+ LOG(ERROR) << "Failed creating VA Surface for pixmap";
+ scaled_pixmap_ = nullptr;
+ return nullptr;
+ }
+ }
+
+ DCHECK(scaled_pixmap_);
+ bool vpp_result = vaapi_wrapper_->BlitSurface(
+ va_surface_->id(), va_surface_->size(), scaled_va_surface_->id(),
+ scaled_va_surface_->size());
+ if (!vpp_result) {
+ LOG(ERROR) << "Failed scaling NativePixmap";
+ scaled_pixmap_ = nullptr;
+ scaled_va_surface_ = nullptr;
+ return nullptr;
+ }
+
+ return scaled_pixmap_;
+}
+
scoped_refptr<gfx::GLImage> VaapiDrmPicture::GetImageToBind() {
return gl_image_;
}
diff --git a/content/common/gpu/media/vaapi_drm_picture.h b/content/common/gpu/media/vaapi_drm_picture.h
index e982b59..4a0b83b 100644
--- a/content/common/gpu/media/vaapi_drm_picture.h
+++ b/content/common/gpu/media/vaapi_drm_picture.h
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/gpu/media/vaapi_picture.h"
#include "ui/gfx/geometry/size.h"
@@ -46,18 +47,39 @@ class VaapiDrmPicture : public VaapiPicture {
bool AllowOverlay() const override;
private:
+ // Calls ScalePixmap() if weak_ptr is not NULL.
+ static scoped_refptr<ui::NativePixmap> CallScalePixmap(
+ base::WeakPtr<VaapiDrmPicture> weak_ptr,
+ gfx::Size new_size);
+ // Use VPP to scale underlying pixmap_ to |new_size| and return the
+ // scaling result with a new pixmap.
+ scoped_refptr<ui::NativePixmap> ScalePixmap(gfx::Size new_size);
+ scoped_refptr<VASurface> CreateVASurfaceForPixmap(
+ scoped_refptr<ui::NativePixmap> pixmap,
+ gfx::Size pixmap_size);
+ scoped_refptr<ui::NativePixmap> CreateNativePixmap(gfx::Size size);
+
VaapiWrapper* vaapi_wrapper_; // Not owned.
base::Callback<bool(void)> make_context_current_;
// Ozone buffer, the storage of the EGLImage and the VASurface.
scoped_refptr<ui::NativePixmap> pixmap_;
+ // Ozone buffer, the storage of the scaled buffer for overlay.
+ scoped_refptr<ui::NativePixmap> scaled_pixmap_;
+
// EGLImage bound to the GL textures used by the VDA client.
scoped_refptr<gfx::GLImage> gl_image_;
// VASurface used to transfer from the decoder's pixel format.
scoped_refptr<VASurface> va_surface_;
+ // VaSurface used to apply scaling.
+ scoped_refptr<VASurface> scaled_va_surface_;
+
+ // The WeakPtrFactory for VaapiDrmPicture.
+ base::WeakPtrFactory<VaapiDrmPicture> weak_this_factory_;
+
DISALLOW_COPY_AND_ASSIGN(VaapiDrmPicture);
};
diff --git a/ui/ozone/platform/cast/surface_factory_cast.cc b/ui/ozone/platform/cast/surface_factory_cast.cc
index 9a0a466..3288f43 100644
--- a/ui/ozone/platform/cast/surface_factory_cast.cc
+++ b/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -197,6 +197,10 @@ scoped_refptr<NativePixmap> SurfaceFactoryCast::CreateNativePixmap(
const gfx::RectF& crop_rect) override {
return true;
}
+ void SetScalingCallback(const ScalingCallback& scaling_callback) override {}
+ scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) override {
+ return nullptr;
+ }
private:
~CastPixmap() override {}
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
index 8da5e5d..c92ba44 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
+#include "ui/gfx/geometry/size_conversions.h"
#include "ui/ozone/platform/drm/gpu/drm_window.h"
#include "ui/ozone/platform/drm/gpu/gbm_device.h"
@@ -83,6 +84,14 @@ bool GbmPixmap::Initialize() {
return true;
}
+void GbmPixmap::SetScalingCallback(const ScalingCallback& scaling_callback) {
+ scaling_callback_ = scaling_callback;
+}
+
+scoped_refptr<NativePixmap> GbmPixmap::GetScaledPixmap(gfx::Size new_size) {
+ return scaling_callback_.Run(new_size);
+}
+
GbmPixmap::~GbmPixmap() {
if (dma_buf_ > 0)
close(dma_buf_);
@@ -105,9 +114,37 @@ bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
gfx::OverlayTransform plane_transform,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) {
+ gfx::Size required_size;
+ if (plane_z_order &&
+ ShouldApplyScaling(display_bounds, crop_rect, &required_size)) {
+ scoped_refptr<NativePixmap> scaled_pixmap = GetScaledPixmap(required_size);
+ if (scaled_pixmap) {
+ return scaled_pixmap->ScheduleOverlayPlane(
+ widget, plane_z_order, plane_transform, display_bounds, crop_rect);
+ } else {
+ return false;
+ }
+ }
+
screen_manager_->GetWindow(widget)->QueueOverlayPlane(OverlayPlane(
buffer_, plane_z_order, plane_transform, display_bounds, crop_rect));
return true;
}
+bool GbmPixmap::ShouldApplyScaling(const gfx::Rect& display_bounds,
+ const gfx::RectF& crop_rect,
+ gfx::Size* required_size) {
+ if (crop_rect.width() == 0 || crop_rect.height() == 0) {
+ PLOG(ERROR) << "ShouldApplyScaling passed zero scaling target.";
+ return false;
+ }
+
+ gfx::Size pixmap_size = buffer_->GetSize();
+ // If the required size is not integer-sized, round it to the next integer.
+ *required_size = gfx::ToCeiledSize(
+ gfx::SizeF(display_bounds.width() / crop_rect.width(),
+ display_bounds.height() / crop_rect.height()));
+ return pixmap_size != *required_size;
+}
+
} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.h b/ui/ozone/platform/drm/gpu/gbm_buffer.h
index 3f0c5d7..4f420e7 100644
--- a/ui/ozone/platform/drm/gpu/gbm_buffer.h
+++ b/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -39,6 +39,8 @@ class GbmPixmap : public NativePixmap {
GbmPixmap(const scoped_refptr<GbmBuffer>& buffer,
ScreenManager* screen_manager);
bool Initialize();
+ void SetScalingCallback(const ScalingCallback& scaling_callback) override;
+ scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) override;
// NativePixmap:
void* GetEGLClientBuffer() override;
@@ -54,12 +56,17 @@ class GbmPixmap : public NativePixmap {
private:
~GbmPixmap() override;
+ bool ShouldApplyScaling(const gfx::Rect& display_bounds,
+ const gfx::RectF& crop_rect,
+ gfx::Size* required_size);
scoped_refptr<GbmBuffer> buffer_;
int dma_buf_ = -1;
ScreenManager* screen_manager_; // Not owned.
+ ScalingCallback scaling_callback_;
+
DISALLOW_COPY_AND_ASSIGN(GbmPixmap);
};
diff --git a/ui/ozone/public/native_pixmap.h b/ui/ozone/public/native_pixmap.h
index a1204f7..0251a12 100644
--- a/ui/ozone/public/native_pixmap.h
+++ b/ui/ozone/public/native_pixmap.h
@@ -5,6 +5,7 @@
#ifndef UI_OZONE_PUBLIC_NATIVE_PIXMAP_H_
#define UI_OZONE_PUBLIC_NATIVE_PIXMAP_H_
+#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/overlay_transform.h"
@@ -43,6 +44,15 @@ class NativePixmap : public base::RefCountedThreadSafe<NativePixmap> {
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) = 0;
+ // This represents a callback function pointing to scaling unit like VPP
+ // to do scaling operations on native pixmap with required size.
+ typedef base::Callback<scoped_refptr<NativePixmap>(gfx::Size)>
+ ScalingCallback;
+
+ // Set callback function for the pixmap used for scaling.
+ virtual void SetScalingCallback(const ScalingCallback& scaling_callback) = 0;
+ virtual scoped_refptr<NativePixmap> GetScaledPixmap(gfx::Size new_size) = 0;
+
protected:
virtual ~NativePixmap() {}