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

Unified Diff: content/common/gpu/media/vaapi_video_decode_accelerator.cc

Issue 490233002: VaapiVideoAccelerator: make Vaapi accelerator work with ozone (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Don't limit h264_bitstream_buffer_unittest to x11 Created 6 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: content/common/gpu/media/vaapi_video_decode_accelerator.cc
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
index 0b3001272ac8e8349362fe10fbd4612e5cbc8e3e..3ee4eededfdd76a2b751201fa175bbc4f61c7bb0 100644
--- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc
+++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -9,13 +9,11 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
-#include "base/threading/non_thread_safe.h"
#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
#include "media/base/bind_to_current_loop.h"
#include "media/video/picture.h"
#include "ui/gl/gl_bindings.h"
-#include "ui/gl/scoped_binders.h"
static void ReportToUMA(
content::VaapiH264Decoder::VAVDAH264DecoderFailure failure) {
@@ -61,175 +59,16 @@ void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
}
}
-// TFPPicture allocates X Pixmaps and binds them to textures passed
-// in PictureBuffers from clients to them. TFPPictures are created as
-// a consequence of receiving a set of PictureBuffers from clients and released
-// at the end of decode (or when a new set of PictureBuffers is required).
-//
-// TFPPictures are used for output, contents of VASurfaces passed from decoder
-// are put into the associated pixmap memory and sent to client.
-class VaapiVideoDecodeAccelerator::TFPPicture : public base::NonThreadSafe {
- public:
- ~TFPPicture();
-
- static linked_ptr<TFPPicture> Create(
- const base::Callback<bool(void)>& make_context_current,
- const GLXFBConfig& fb_config,
- Display* x_display,
- int32 picture_buffer_id,
- uint32 texture_id,
- gfx::Size size);
-
- int32 picture_buffer_id() {
- return picture_buffer_id_;
- }
-
- gfx::Size size() {
- return size_;
- }
-
- int x_pixmap() {
- return x_pixmap_;
- }
-
- // Bind texture to pixmap. Needs to be called every frame.
- bool Bind();
-
- private:
- TFPPicture(const base::Callback<bool(void)>& make_context_current,
- Display* x_display,
- int32 picture_buffer_id,
- uint32 texture_id,
- gfx::Size size);
-
- bool Initialize(const GLXFBConfig& fb_config);
-
- base::Callback<bool(void)> make_context_current_;
-
- Display* x_display_;
-
- // Output id for the client.
- int32 picture_buffer_id_;
- uint32 texture_id_;
-
- gfx::Size size_;
-
- // Pixmaps bound to this texture.
- Pixmap x_pixmap_;
- GLXPixmap glx_pixmap_;
-
- DISALLOW_COPY_AND_ASSIGN(TFPPicture);
-};
-
-VaapiVideoDecodeAccelerator::TFPPicture::TFPPicture(
- const base::Callback<bool(void)>& make_context_current,
- Display* x_display,
- int32 picture_buffer_id,
- uint32 texture_id,
- gfx::Size size)
- : make_context_current_(make_context_current),
- x_display_(x_display),
- picture_buffer_id_(picture_buffer_id),
- texture_id_(texture_id),
- size_(size),
- x_pixmap_(0),
- glx_pixmap_(0) {
- DCHECK(!make_context_current_.is_null());
-};
-
-linked_ptr<VaapiVideoDecodeAccelerator::TFPPicture>
-VaapiVideoDecodeAccelerator::TFPPicture::Create(
- const base::Callback<bool(void)>& make_context_current,
- const GLXFBConfig& fb_config,
- Display* x_display,
- int32 picture_buffer_id,
- uint32 texture_id,
- gfx::Size size) {
-
- linked_ptr<TFPPicture> tfp_picture(
- new TFPPicture(make_context_current, x_display, picture_buffer_id,
- texture_id, size));
-
- if (!tfp_picture->Initialize(fb_config))
- tfp_picture.reset();
-
- return tfp_picture;
-}
-
-bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
- const GLXFBConfig& fb_config) {
- DCHECK(CalledOnValidThread());
- if (!make_context_current_.Run())
- return false;
-
- XWindowAttributes win_attr;
- int screen = DefaultScreen(x_display_);
- XGetWindowAttributes(x_display_, RootWindow(x_display_, screen), &win_attr);
- //TODO(posciak): pass the depth required by libva, not the RootWindow's depth
- x_pixmap_ = XCreatePixmap(x_display_, RootWindow(x_display_, screen),
- size_.width(), size_.height(), win_attr.depth);
- if (!x_pixmap_) {
- DVLOG(1) << "Failed creating an X Pixmap for TFP";
- return false;
- }
-
- static const int pixmap_attr[] = {
- GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
- GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
- GL_NONE,
- };
-
- glx_pixmap_ = glXCreatePixmap(x_display_, fb_config, x_pixmap_, pixmap_attr);
- if (!glx_pixmap_) {
- // x_pixmap_ will be freed in the destructor.
- DVLOG(1) << "Failed creating a GLX Pixmap for TFP";
- return false;
- }
-
- return true;
-}
-
-VaapiVideoDecodeAccelerator::TFPPicture::~TFPPicture() {
- DCHECK(CalledOnValidThread());
- // Unbind surface from texture and deallocate resources.
- if (glx_pixmap_ && make_context_current_.Run()) {
- glXReleaseTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
- glXDestroyPixmap(x_display_, glx_pixmap_);
- }
-
- if (x_pixmap_)
- XFreePixmap(x_display_, x_pixmap_);
- XSync(x_display_, False); // Needed to work around buggy vdpau-driver.
-}
-
-bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() {
- DCHECK(CalledOnValidThread());
- DCHECK(x_pixmap_);
- DCHECK(glx_pixmap_);
- if (!make_context_current_.Run())
- return false;
-
- gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
- glXBindTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL);
-
- return true;
-}
-
-VaapiVideoDecodeAccelerator::TFPPicture*
- VaapiVideoDecodeAccelerator::TFPPictureById(int32 picture_buffer_id) {
- TFPPictures::iterator it = tfp_pictures_.find(picture_buffer_id);
- if (it == tfp_pictures_.end()) {
- DVLOG(1) << "Picture id " << picture_buffer_id << " does not exist";
- return NULL;
- }
-
- return it->second.get();
+VaapiPictureProvider::Picture* VaapiVideoDecodeAccelerator::PictureById(
+ int32 picture_buffer_id) {
+ VaapiPictureProvider::Picture* picture = pictures_.get(picture_buffer_id);
+ return picture;
}
VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
- Display* x_display,
+ gfx::GLContext* gl_context,
const base::Callback<bool(void)>& make_context_current)
- : x_display_(x_display),
+ : gl_context_(gl_context),
make_context_current_(make_context_current),
state_(kUninitialized),
input_ready_(&lock_),
@@ -249,35 +88,8 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
DCHECK_EQ(message_loop_, base::MessageLoop::current());
-}
-
-class XFreeDeleter {
- public:
- void operator()(void* x) const {
- ::XFree(x);
- }
-};
-
-bool VaapiVideoDecodeAccelerator::InitializeFBConfig() {
- const int fbconfig_attr[] = {
- GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
- GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
- GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE,
- GLX_Y_INVERTED_EXT, GL_TRUE,
- GL_NONE,
- };
-
- int num_fbconfigs;
- scoped_ptr<GLXFBConfig, XFreeDeleter> glx_fb_configs(
- glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr,
- &num_fbconfigs));
- if (!glx_fb_configs)
- return false;
- if (!num_fbconfigs)
- return false;
-
- fb_config_ = glx_fb_configs.get()[0];
- return true;
+ // Make sure pictures are destroyed before the picture provider is.
+ pictures_.clear();
Pawel Osciak 2014/09/24 11:27:12 Looks like each Picture should rather have a refpt
llandwerlin-old 2014/10/02 14:14:23 Right, thanks, the comment is misleading here (lef
}
bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
@@ -291,18 +103,23 @@ bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
DCHECK_EQ(state_, kUninitialized);
DVLOG(2) << "Initializing VAVDA, profile: " << profile;
- if (!make_context_current_.Run())
+#if defined(USE_X11)
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) {
+ DVLOG(1) << "HW video decode acceleration not available without "
+ "DesktopGL (GLX).";
return false;
-
- if (!InitializeFBConfig()) {
- DVLOG(1) << "Could not get a usable FBConfig";
+ }
+#else
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) {
+ DVLOG(1) << "HW video decode acceleration not available without "
+ "EGLGLES2.";
return false;
}
+#endif // USE_X11
vaapi_wrapper_ = VaapiWrapper::Create(
VaapiWrapper::kDecode,
profile,
- x_display_,
base::Bind(&ReportToUMA, content::VaapiH264Decoder::VAAPI_ERROR));
if (!vaapi_wrapper_.get()) {
@@ -310,6 +127,16 @@ bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
return false;
}
+ vaapi_picture_provider_ = VaapiPictureProvider::Create(
+ vaapi_wrapper_->GetDisplay(),
Pawel Osciak 2014/09/24 11:27:12 Could the provider get its own display? Or better,
llandwerlin-old 2014/10/02 14:14:23 You need to have the all VA objects (VASurface/VAC
Pawel Osciak 2014/10/08 08:17:21 Yes, please. I'd really prefer to use a common Vaa
+ gl_context_,
+ make_context_current_);
+
+ if (!vaapi_picture_provider_.get()) {
+ DVLOG(1) << "Failed initializing VAAPI Picture Provider";
+ return false;
+ }
+
decoder_.reset(
new VaapiH264Decoder(
vaapi_wrapper_.get(),
@@ -344,10 +171,10 @@ void VaapiVideoDecodeAccelerator::SurfaceReady(
void VaapiVideoDecodeAccelerator::OutputPicture(
const scoped_refptr<VASurface>& va_surface,
int32 input_id,
- TFPPicture* tfp_picture) {
+ VaapiPictureProvider::Picture* picture) {
DCHECK_EQ(message_loop_, base::MessageLoop::current());
- int32 output_id = tfp_picture->picture_buffer_id();
+ int32 output_id = picture->picture_buffer_id();
TRACE_EVENT2("Video Decoder", "VAVDA::OutputSurface",
"input_id", input_id,
@@ -356,15 +183,10 @@ void VaapiVideoDecodeAccelerator::OutputPicture(
DVLOG(3) << "Outputting VASurface " << va_surface->id()
<< " into pixmap bound to picture buffer id " << output_id;
- RETURN_AND_NOTIFY_ON_FAILURE(tfp_picture->Bind(),
- "Failed binding texture to pixmap",
- PLATFORM_FAILURE, );
-
RETURN_AND_NOTIFY_ON_FAILURE(
- vaapi_wrapper_->PutSurfaceIntoPixmap(va_surface->id(),
- tfp_picture->x_pixmap(),
- tfp_picture->size()),
- "Failed putting surface into pixmap", PLATFORM_FAILURE, );
+ vaapi_picture_provider_->PutSurfaceIntoPicture(va_surface->id(), picture),
+ "Failed putting surface into pixmap",
+ PLATFORM_FAILURE, );
// Notify the client a picture is ready to be displayed.
++num_frames_at_client_;
@@ -375,7 +197,7 @@ void VaapiVideoDecodeAccelerator::OutputPicture(
// (crbug.com/402760).
if (client_)
client_->PictureReady(
- media::Picture(output_id, input_id, gfx::Rect(tfp_picture->size())));
+ media::Picture(output_id, input_id, gfx::Rect(picture->size())));
}
void VaapiVideoDecodeAccelerator::TryOutputSurface() {
@@ -391,11 +213,11 @@ void VaapiVideoDecodeAccelerator::TryOutputSurface() {
OutputCB output_cb = pending_output_cbs_.front();
pending_output_cbs_.pop();
- TFPPicture* tfp_picture = TFPPictureById(output_buffers_.front());
- DCHECK(tfp_picture);
+ VaapiPictureProvider::Picture* picture = PictureById(output_buffers_.front());
+ DCHECK(picture);
output_buffers_.pop();
- output_cb.Run(tfp_picture);
+ output_cb.Run(picture);
if (finish_flush_pending_ && pending_output_cbs_.empty())
FinishFlush();
@@ -598,7 +420,7 @@ void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
return;
if (!pending_output_cbs_.empty() ||
- tfp_pictures_.size() != available_va_surfaces_.size()) {
+ pictures_.size() != available_va_surfaces_.size()) {
// Either:
// 1. Not all pending pending output callbacks have been executed yet.
// Wait for the client to return enough pictures and retry later.
@@ -616,13 +438,13 @@ void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
available_va_surfaces_.clear();
vaapi_wrapper_->DestroySurfaces();
- for (TFPPictures::iterator iter = tfp_pictures_.begin();
- iter != tfp_pictures_.end(); ++iter) {
+ for (Pictures::iterator iter = pictures_.begin(); iter != pictures_.end();
+ ++iter) {
DVLOG(2) << "Dismissing picture id: " << iter->first;
if (client_)
client_->DismissPictureBuffer(iter->first);
}
- tfp_pictures_.clear();
+ pictures_.clear();
// And ask for a new set as requested.
DVLOG(1) << "Requesting " << requested_num_pics_ << " pictures of size: "
@@ -682,7 +504,7 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
DCHECK_EQ(message_loop_, base::MessageLoop::current());
base::AutoLock auto_lock(lock_);
- DCHECK(tfp_pictures_.empty());
+ DCHECK(pictures_.empty());
while (!output_buffers_.empty())
output_buffers_.pop();
@@ -701,23 +523,27 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
"Failed creating VA Surfaces", PLATFORM_FAILURE, );
DCHECK_EQ(va_surface_ids.size(), buffers.size());
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ vaapi_picture_provider_->SetCodedSurfacesSize(requested_pic_size_),
+ "Failed to update VA picture provider surface size", PLATFORM_FAILURE, );
+
for (size_t i = 0; i < buffers.size(); ++i) {
DVLOG(2) << "Assigning picture id: " << buffers[i].id()
<< " to texture id: " << buffers[i].texture_id()
<< " VASurfaceID: " << va_surface_ids[i];
- linked_ptr<TFPPicture> tfp_picture(
- TFPPicture::Create(make_context_current_, fb_config_, x_display_,
- buffers[i].id(), buffers[i].texture_id(),
- requested_pic_size_));
+ scoped_ptr<VaapiPictureProvider::Picture> picture(
+ vaapi_picture_provider_->CreatePicture(buffers[i].id(),
+ buffers[i].texture_id(),
+ requested_pic_size_));
RETURN_AND_NOTIFY_ON_FAILURE(
- tfp_picture.get(), "Failed assigning picture buffer to a texture.",
+ picture.get(),
+ "Failed assigning picture buffer to a texture.",
PLATFORM_FAILURE, );
- bool inserted = tfp_pictures_.insert(std::make_pair(
- buffers[i].id(), tfp_picture)).second;
- DCHECK(inserted);
+ DCHECK(!pictures_.contains(buffers[i].id()));
Pawel Osciak 2014/09/24 11:27:12 I think this should be s/!// ? Are you testing on
llandwerlin-old 2014/10/02 14:14:23 I might be wrong, but the purpose here is to check
Pawel Osciak 2014/10/08 08:17:21 Ah you are right, sorry. As for building chrome, I
+ pictures_.set(buffers[i].id(), picture.Pass());
output_buffers_.push(buffers[i].id());
available_va_surfaces_.push_back(va_surface_ids[i]);

Powered by Google App Engine
This is Rietveld 408576698