Chromium Code Reviews| Index: content/common/gpu/media/vaapi_video_decode_accelerator_wayland.cc |
| diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator_wayland.cc |
| similarity index 83% |
| copy from content/common/gpu/media/vaapi_video_decode_accelerator.cc |
| copy to content/common/gpu/media/vaapi_video_decode_accelerator_wayland.cc |
| index 4b2c49e7d19702bd6ec446bb937dedc8063d02d7..6e9fb84609bb732db4fee597216796ca0d877ae9 100644 |
| --- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc |
| +++ b/content/common/gpu/media/vaapi_video_decode_accelerator_wayland.cc |
| @@ -1,4 +1,4 @@ |
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Copyright (c) 2014 and intel copyright. All rights reserved. |
|
Ami GONE FROM CHROMIUM
2014/04/18 22:40:25
Copyright rests with The Chromium Authors, not wit
|
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| @@ -14,7 +14,6 @@ |
| #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( |
| @@ -61,21 +60,21 @@ void VaapiVideoDecodeAccelerator::NotifyError(Error error) { |
| } |
| } |
| -// TFPPicture allocates X Pixmaps and binds them to textures passed |
| +// TFPPicture allocates VAImage 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. |
| +// are put into the associated vaimage memory and upload 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, |
| + const base::Callback<bool(void)>& make_context_current, //NOLINT |
| + wl_display* wl_display, |
| + VaapiWrapper* va_wrapper, |
| int32 picture_buffer_id, |
| uint32 texture_id, |
| gfx::Size size); |
| @@ -88,101 +87,75 @@ class VaapiVideoDecodeAccelerator::TFPPicture : public base::NonThreadSafe { |
| return size_; |
| } |
| - int x_pixmap() { |
| - return x_pixmap_; |
| - } |
| - |
| - // Bind texture to pixmap. Needs to be called every frame. |
| - bool Bind(); |
| + // Upload vaimage data to texture. Needs to be called every frame. |
| + bool Upload(VASurfaceID id); |
| private: |
| - TFPPicture(const base::Callback<bool(void)>& make_context_current, |
| - Display* x_display, |
| + TFPPicture(const base::Callback<bool(void)>& make_context_current, //NOLINT |
| + wl_display* wl_display, |
| + VaapiWrapper* va_wrapper, |
| int32 picture_buffer_id, |
| uint32 texture_id, |
| gfx::Size size); |
| - bool Initialize(const GLXFBConfig& fb_config); |
| + bool Initialize(); |
| - base::Callback<bool(void)> make_context_current_; |
| + base::Callback<bool(void)> make_context_current_; //NOLINT |
| - Display* x_display_; |
| + wl_display* wl_display_; |
| + VaapiWrapper* va_wrapper_; |
| // 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_; |
| + VAImage va_image_; |
| DISALLOW_COPY_AND_ASSIGN(TFPPicture); |
| }; |
| VaapiVideoDecodeAccelerator::TFPPicture::TFPPicture( |
| - const base::Callback<bool(void)>& make_context_current, |
| - Display* x_display, |
| + const base::Callback<bool(void)>& make_context_current, //NOLINT |
| + wl_display* wl_display, |
| + VaapiWrapper* va_wrapper, |
| int32 picture_buffer_id, |
| uint32 texture_id, |
| gfx::Size size) |
| : make_context_current_(make_context_current), |
| - x_display_(x_display), |
| + wl_display_(wl_display), |
| + va_wrapper_(va_wrapper), |
| picture_buffer_id_(picture_buffer_id), |
| texture_id_(texture_id), |
| - size_(size), |
| - x_pixmap_(0), |
| - glx_pixmap_(0) { |
| + size_(size) { |
| 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, |
| + const base::Callback<bool(void)>& make_context_current, //NOLINT |
| + wl_display* wl_display, |
| + VaapiWrapper* va_wrapper, |
| 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)); |
| + new TFPPicture(make_context_current, wl_display, va_wrapper, |
| + picture_buffer_id, texture_id, size)); |
| - if (!tfp_picture->Initialize(fb_config)) |
| + if (!tfp_picture->Initialize()) |
| tfp_picture.reset(); |
| return tfp_picture; |
| } |
| -bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize( |
| - const GLXFBConfig& fb_config) { |
| +bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize() { |
| 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"; |
| + if (!va_wrapper_->CreateRGBImage(size_, &va_image_)) { |
| + DVLOG(1) << "Failed to create VAImage"; |
| return false; |
| } |
| @@ -191,26 +164,36 @@ bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize( |
| 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. |
| + if (va_wrapper_) { |
| + va_wrapper_->DestroyImage(&va_image_); |
| + } |
| } |
| -bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() { |
| +bool VaapiVideoDecodeAccelerator::TFPPicture::Upload(VASurfaceID surface) { |
| DCHECK(CalledOnValidThread()); |
| - DCHECK(x_pixmap_); |
| - DCHECK(glx_pixmap_); |
| + |
| if (!make_context_current_.Run()) |
| return false; |
| + if (!va_wrapper_->PutSurfaceIntoImage(surface, &va_image_)) { |
| + DVLOG(1) << "Failed to put va surface to image"; |
| + return false; |
| + } |
| + |
| + void* buffer = NULL; |
| + if (!va_wrapper_->MapImage(&va_image_, &buffer)) { |
| + DVLOG(1) << "Failed to map VAImage"; |
| + return false; |
| + } |
| + |
| gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_); |
| - glXBindTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.width(), size_.height(), |
| + 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); |
| + |
| + va_wrapper_->UnmapImage(&va_image_); |
| return true; |
| } |
| @@ -227,59 +210,66 @@ VaapiVideoDecodeAccelerator::TFPPicture* |
| } |
| VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator( |
| - Display* x_display, |
| - const base::Callback<bool(void)>& make_context_current) |
| - : x_display_(x_display), |
| + const base::Callback<bool(void)>& make_context_current) //NOLINT |
| + : wl_display_(NULL), |
| make_context_current_(make_context_current), |
| state_(kUninitialized), |
| input_ready_(&lock_), |
| surfaces_available_(&lock_), |
| message_loop_(base::MessageLoop::current()), |
| + weak_this_(base::AsWeakPtr(this)), |
| + va_surface_release_cb_(media::BindToCurrentLoop(base::Bind( |
| + &VaapiVideoDecodeAccelerator::RecycleVASurfaceID, weak_this_))), |
| decoder_thread_("VaapiDecoderThread"), |
| num_frames_at_client_(0), |
| num_stream_bufs_at_decoder_(0), |
| finish_flush_pending_(false), |
| awaiting_va_surfaces_recycle_(false), |
| - requested_num_pics_(0), |
| - weak_this_factory_(this) { |
| - weak_this_ = weak_this_factory_.GetWeakPtr(); |
| - va_surface_release_cb_ = media::BindToCurrentLoop( |
| - base::Bind(&VaapiVideoDecodeAccelerator::RecycleVASurfaceID, weak_this_)); |
| + requested_num_pics_(0) { |
| } |
| VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() { |
| DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| + if (wl_display_) { |
| + wl_display_flush(wl_display_); |
| + wl_display_disconnect(wl_display_); |
| + wl_display_ = NULL; |
| + } |
| } |
| -class XFreeDeleter { |
| - public: |
| - void operator()(void* x) const { |
| - ::XFree(x); |
| +typedef struct wayland_display { |
| + wl_display* display; |
| + wl_compositor* compositor; |
| + wl_shell* shell; |
| + wl_registry* registry; |
| + int event_fd; |
| +} wayland_display; |
| + |
| +static void registry_handle_global( |
| + void* data, |
| + wl_registry* registry, |
| + uint32_t id, |
| + const char* interface, |
| + uint32_t version) { |
| + wayland_display* display_handle = |
| + reinterpret_cast<wayland_display *>(data); |
| + |
| + if (strcmp(interface, "wl_compositor") == 0) { |
| + display_handle->compositor = |
| + reinterpret_cast<wl_compositor *>(wl_registry_bind( |
| + registry, id, &wl_compositor_interface, 1)); |
| + } else if (strcmp(interface, "wl_shell") == 0) { |
| + display_handle->shell = |
| + reinterpret_cast<wl_shell *>(wl_registry_bind( |
| + registry, id, &wl_shell_interface, 1)); |
| } |
| -}; |
| - |
| -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; |
| } |
| +static const struct wl_registry_listener registry_listener = { |
| + registry_handle_global, |
| + NULL, |
| +}; |
| + |
| bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, |
| Client* client) { |
| DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| @@ -294,13 +284,19 @@ bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, |
| if (!make_context_current_.Run()) |
| return false; |
| - if (!InitializeFBConfig()) { |
| - DVLOG(1) << "Could not get a usable FBConfig"; |
| + wayland_display d; |
| + |
| + d.display = wl_display_connect(NULL); |
| + if (!d.display) |
| return false; |
| - } |
| + wl_display_set_user_data(d.display, &d); |
| + d.registry = wl_display_get_registry(d.display); |
| + wl_registry_add_listener(d.registry, ®istry_listener, &d); |
| + wl_display_dispatch(d.display); |
| + wl_display_ = d.display; |
| vaapi_wrapper_ = VaapiWrapper::Create( |
| - profile, x_display_, |
| + profile, wl_display_, |
| base::Bind(&ReportToUMA, content::VaapiH264Decoder::VAAPI_ERROR)); |
| if (!vaapi_wrapper_.get()) { |
| @@ -319,6 +315,10 @@ bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, |
| decoder_thread_proxy_ = decoder_thread_.message_loop_proxy(); |
| state_ = kIdle; |
| + |
| + message_loop_->PostTask(FROM_HERE, base::Bind( |
| + &Client::NotifyInitializeDone, client_)); |
| + |
| return true; |
| } |
| @@ -354,15 +354,9 @@ 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, ); |
| + RETURN_AND_NOTIFY_ON_FAILURE(tfp_picture->Upload(va_surface->id()), |
| + "Failed to upload VASurface to texture", |
| + PLATFORM_FAILURE, ); //NOLINT |
| // Notify the client a picture is ready to be displayed. |
| ++num_frames_at_client_; |
| @@ -403,12 +397,12 @@ void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( |
| bitstream_buffer.id()); |
| DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() |
| - << " size: " << (int)bitstream_buffer.size(); |
| + << " size: " << static_cast<int>(bitstream_buffer.size()); |
| scoped_ptr<base::SharedMemory> shm( |
| new base::SharedMemory(bitstream_buffer.handle(), true)); |
| RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(bitstream_buffer.size()), |
| - "Failed to map input buffer", UNREADABLE_INPUT,); |
| + "Failed to map input buffer", UNREADABLE_INPUT,); //NOLINT |
| base::AutoLock auto_lock(lock_); |
| @@ -492,7 +486,7 @@ bool VaapiVideoDecodeAccelerator::FeedDecoderWithOutputSurfaces_Locked() { |
| DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); |
| while (available_va_surfaces_.empty() && |
| - (state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) { |
| + (state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) { |
| surfaces_available_.Wait(); |
| } |
| @@ -560,7 +554,7 @@ void VaapiVideoDecodeAccelerator::DecodeTask() { |
| case VaapiH264Decoder::kDecodeError: |
| RETURN_AND_NOTIFY_ON_FAILURE(false, "Error decoding stream", |
| - PLATFORM_FAILURE, ); |
| + PLATFORM_FAILURE,); //NOLINT |
| return; |
| } |
| } |
| @@ -658,7 +652,7 @@ void VaapiVideoDecodeAccelerator::Decode( |
| default: |
| RETURN_AND_NOTIFY_ON_FAILURE(false, |
| "Decode request from client in invalid state: " << state_, |
| - PLATFORM_FAILURE, ); |
| + PLATFORM_FAILURE,); //NOLINT |
| break; |
| } |
| } |
| @@ -684,8 +678,8 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers( |
| RETURN_AND_NOTIFY_ON_FAILURE( |
| buffers.size() == requested_num_pics_, |
| - "Got an invalid number of picture buffers. (Got " << buffers.size() |
| - << ", requested " << requested_num_pics_ << ")", INVALID_ARGUMENT, ); |
| + "Got an invalid buffers. (Got " << buffers.size() << ", requested " |
| + << requested_num_pics_ << ")", INVALID_ARGUMENT,); //NOLINT |
| DCHECK(requested_pic_size_ == buffers[0].size()); |
| std::vector<VASurfaceID> va_surface_ids; |
| @@ -693,7 +687,7 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers( |
| vaapi_wrapper_->CreateSurfaces(requested_pic_size_, |
| buffers.size(), |
| &va_surface_ids), |
| - "Failed creating VA Surfaces", PLATFORM_FAILURE, ); |
| + "Failed creating VA Surfaces", PLATFORM_FAILURE,); //NOLINT |
| DCHECK_EQ(va_surface_ids.size(), buffers.size()); |
| for (size_t i = 0; i < buffers.size(); ++i) { |
| @@ -702,13 +696,13 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers( |
| << " 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_)); |
| + TFPPicture::Create(make_context_current_, wl_display_, |
| + vaapi_wrapper_.get(), 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.", |
| - PLATFORM_FAILURE, ); |
| + PLATFORM_FAILURE,); //NOLINT |
| bool inserted = tfp_pictures_.insert(std::make_pair( |
| buffers[i].id(), tfp_picture)).second; |
| @@ -744,7 +738,7 @@ void VaapiVideoDecodeAccelerator::FlushTask() { |
| // client to output them. |
| bool res = decoder_->Flush(); |
| RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", |
| - PLATFORM_FAILURE, ); |
| + PLATFORM_FAILURE,); //NOLINT |
| // Put the decoder in idle state, ready to resume. |
| decoder_->Reset(); |
| @@ -893,7 +887,6 @@ void VaapiVideoDecodeAccelerator::Cleanup() { |
| state_ = kDestroying; |
| client_ptr_factory_.reset(); |
| - weak_this_factory_.InvalidateWeakPtrs(); |
| { |
| base::AutoUnlock auto_unlock(lock_); |