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_); |