Skip to content
This repository has been archived by the owner on Aug 20, 2020. It is now read-only.

Commit

Permalink
Add check for vaLockBuffer apis support.
Browse files Browse the repository at this point in the history
If libva supports vaLockBuffer Apis, such as Tizen libva, we can use the
DRM VDA method to reach better video playback performance; on the
other hand, if libva doesn't support vaLockBuffer Apis, we can still use
the MapBuffer method.
  • Loading branch information
shaochangbin committed Sep 3, 2014
1 parent 1645d4f commit e87d301
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 12 deletions.
84 changes: 72 additions & 12 deletions media/vaapi_video_decode_accelerator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "ozone/media/vaapi_video_decode_accelerator.h"

#include <string>

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
Expand Down Expand Up @@ -93,6 +95,9 @@ class VaapiVideoDecodeAccelerator::TFPPicture : public base::NonThreadSafe {
return va_image_.get();
}

// Upload vaimage data to texture. Needs to be called every frame.
bool Upload(VASurfaceID id);

// Bind EGL image to texture. Needs to be called every frame.
bool Bind();
bool UpdateEGLImage(VASurfaceID id);
Expand Down Expand Up @@ -203,6 +208,49 @@ bool VaapiVideoDecodeAccelerator::TFPPicture::UpdateEGLImage(
return true;
}

bool VaapiVideoDecodeAccelerator::TFPPicture::Upload(VASurfaceID surface) {
DCHECK(CalledOnValidThread());

if (!make_context_current_.Run())
return false;

if (!va_wrapper_->PutSurfaceIntoImage(surface, va_image_.get())) {
DVLOG(1) << "Failed to put va surface to image";
return false;
}

void* buffer = NULL;
if (!va_wrapper_->MapImage(va_image_.get(), &buffer)) {
DVLOG(1) << "Failed to map VAImage";
return false;
}

gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

// See bug https://crosswalk-project.org/jira/browse/XWALK-2265.
// The following small piece of code is a workaround for the current VDA
// texture output implementation. It can be removed when zero buffer copy
// is implemented.
unsigned int al = 4 * size_.width();
if (al != va_image_->pitches[0]) {
// Not aligned phenomenon occurs only in special size video in None-X11.
// So re-check RGBA data alignment and realign filled video frame in need.
unsigned char* bhandle = static_cast<unsigned char*>(buffer);
for (int i = 0; i < size_.height(); i++) {
memcpy(bhandle + (i * al), bhandle + (i * (va_image_->pitches[0])), al);
}
}

glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, size_.width(), size_.height(),
0, GL_BGRA, GL_UNSIGNED_BYTE, buffer);

va_wrapper_->UnmapImage(va_image_.get());

return true;
}

bool VaapiVideoDecodeAccelerator::TFPPicture::Bind() {
DCHECK(CalledOnValidThread());
if (!make_context_current_.Run())
Expand Down Expand Up @@ -316,6 +364,11 @@ bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
return false;
}

supports_valockBuffer_apis_ = vaapi_wrapper_->SupportsVaLockBufferApis();
std::string query =
supports_valockBuffer_apis_ ? "supports" : "doesn't support";
LOG(INFO) << "VAAPI " << query << " vaLockBuffer Apis";

decoder_.reset(
new VaapiH264Decoder(
vaapi_wrapper_.get(),
Expand Down Expand Up @@ -363,22 +416,29 @@ void VaapiVideoDecodeAccelerator::OutputPicture(
DVLOG(3) << "Outputting VASurface " << va_surface->id()
<< " into texture bound to picture buffer id " << output_id;

RETURN_AND_NOTIFY_ON_FAILURE(
vaapi_wrapper_->PutSurfaceIntoImage(
if (supports_valockBuffer_apis_) {
RETURN_AND_NOTIFY_ON_FAILURE(
vaapi_wrapper_->PutSurfaceIntoImage(
va_surface->id(),
tfp_picture->va_image()),
"Failed putting surface into vaimage",
PLATFORM_FAILURE, ); //NOLINT
"Failed putting surface into vaimage",
PLATFORM_FAILURE, ); //NOLINT

RETURN_AND_NOTIFY_ON_FAILURE(
tfp_picture->UpdateEGLImage(va_surface->id()),
"Failed to update egl image per vaimage info",
PLATFORM_FAILURE, ); //NOLINT
RETURN_AND_NOTIFY_ON_FAILURE(
tfp_picture->UpdateEGLImage(va_surface->id()),
"Failed to update egl image per vaimage info",
PLATFORM_FAILURE, ); //NOLINT

RETURN_AND_NOTIFY_ON_FAILURE(
tfp_picture->Bind(),
"Failed to bind egl image to texture",
PLATFORM_FAILURE, ); //NOLINT
RETURN_AND_NOTIFY_ON_FAILURE(
tfp_picture->Bind(),
"Failed to bind egl image to texture",
PLATFORM_FAILURE, ); //NOLINT
} else {
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_;
Expand Down
3 changes: 3 additions & 0 deletions media/vaapi_video_decode_accelerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ class VaapiVideoDecodeAccelerator
// The WeakPtrFactory for |weak_this_|.
base::WeakPtrFactory<VaapiVideoDecodeAccelerator> weak_this_factory_;

// Whether VaapiWrapper supports vaLockBuffer Apis.
bool supports_valockBuffer_apis_;

DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator);
};

Expand Down
26 changes: 26 additions & 0 deletions media/vaapi_wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ using media_media::StubPathMap;
static const base::FilePath::CharType kVaLib[] =
FILE_PATH_LITERAL("libva-wayland.so.1");

static const char kVaLockBufferSymbol[] = "vaLockBuffer";
static const char kVaUnlockBufferSymbol[] = "vaUnlockBuffer";

#define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \
do { \
DVLOG(1) << err_msg \
Expand Down Expand Up @@ -394,6 +397,19 @@ void VaapiWrapper::DestroyImage(VAImage* image) {
vaDestroyImage(va_display_, image->image_id);
}

bool VaapiWrapper::MapImage(VAImage* image, void** buffer) {
base::AutoLock auto_lock(va_lock_);

VAStatus va_res = vaMapBuffer(va_display_, image->buf, buffer);
VA_SUCCESS_OR_RETURN(va_res, "Failed to map image", false);
return true;
}

void VaapiWrapper::UnmapImage(VAImage* image) {
base::AutoLock auto_lock(va_lock_);
vaUnmapBuffer(va_display_, image->buf);
}

bool VaapiWrapper::PutSurfaceIntoImage(VASurfaceID va_surface_id,
VAImage* image) {
base::AutoLock auto_lock(va_lock_);
Expand Down Expand Up @@ -477,4 +493,14 @@ bool VaapiWrapper::PostSandboxInitialization() {
return ret;
}

bool VaapiWrapper::SupportsVaLockBufferApis() {
void* handle = dlopen(kVaLib, RTLD_LAZY);
if (!handle) {
LOG(ERROR) << "Could not open " << kVaLib;
return false;
}
return dlsym(handle, kVaLockBufferSymbol) &&
dlsym(handle, kVaUnlockBufferSymbol);
}

} // namespace media
6 changes: 6 additions & 0 deletions media/vaapi_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ class CONTENT_EXPORT VaapiWrapper {
bool CreateRGBImage(gfx::Size size, VAImage* image);
void DestroyImage(VAImage* image);

bool MapImage(VAImage* image, void** buffer);
void UnmapImage(VAImage* image);

// Put data from |va_surface_id| into |va_image|, converting/scaling it.
bool PutSurfaceIntoImage(VASurfaceID va_surface_id,
VAImage* va_image);
Expand All @@ -101,6 +104,9 @@ class CONTENT_EXPORT VaapiWrapper {
// GetVaImage(). This is intended for testing only.
void ReturnVaImageForTesting(VAImage* image);

// Return true if libva supports vaLockBuffer & vaUnlockBuffer Apis.
bool SupportsVaLockBufferApis();

private:
VaapiWrapper();

Expand Down

0 comments on commit e87d301

Please sign in to comment.