0

Only dlopen() OMX/VAAPI libs in the GPU process, and only lazily dlsym() their symbols.

This reinstates r150007, which was reverted in r150009.

TBR=piman@chromium.org
BUG=140412


Review URL: https://chromiumcodereview.appspot.com/10827173

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150024 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
fischman@chromium.org
2012-08-04 08:38:10 +00:00
parent 150f5ecaae
commit d254e7e05b
9 changed files with 184 additions and 69 deletions

@ -21,8 +21,7 @@ typedef std::pair<scoped_ptr<base::SharedMemory>, int32> SharedMemoryAndId;
enum { kNumPictureBuffers = 4 };
// Open the libOmxCore here for now.
void* omx_handle = dlopen("libOmxCore.so", RTLD_NOW);
void* omx_handle = NULL;
typedef OMX_ERRORTYPE (*OMXInit)();
typedef OMX_ERRORTYPE (*OMXGetHandle)(
@ -31,21 +30,11 @@ typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**);
typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE);
typedef OMX_ERRORTYPE (*OMXDeinit)();
OMXInit omx_init = reinterpret_cast<OMXInit>(dlsym(omx_handle, "OMX_Init"));
OMXGetHandle omx_gethandle =
reinterpret_cast<OMXGetHandle>(dlsym(omx_handle, "OMX_GetHandle"));
OMXGetComponentsOfRole omx_get_components_of_role =
reinterpret_cast<OMXGetComponentsOfRole>(
dlsym(omx_handle, "OMX_GetComponentsOfRole"));
OMXFreeHandle omx_free_handle =
reinterpret_cast<OMXFreeHandle>(dlsym(omx_handle, "OMX_FreeHandle"));
OMXDeinit omx_deinit =
reinterpret_cast<OMXDeinit>(dlsym(omx_handle, "OMX_Deinit"));
static bool AreOMXFunctionPointersInitialized() {
return (omx_init && omx_gethandle && omx_get_components_of_role &&
omx_free_handle && omx_deinit);
}
OMXInit omx_init = NULL;
OMXGetHandle omx_gethandle = NULL;
OMXGetComponentsOfRole omx_get_components_of_role = NULL;
OMXFreeHandle omx_free_handle = NULL;
OMXDeinit omx_deinit = NULL;
// Maps h264-related Profile enum values to OMX_VIDEO_AVCPROFILETYPE values.
static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) {
@ -97,6 +86,9 @@ static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) {
log << ", OMX result: 0x" << std::hex << omx_result, \
error, ret_val)
// static
bool OmxVideoDecodeAccelerator::pre_sandbox_init_done_ = false;
OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator(
EGLDisplay egl_display, EGLContext egl_context,
media::VideoDecodeAccelerator::Client* client)
@ -118,7 +110,8 @@ OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator(
codec_(UNKNOWN),
h264_profile_(OMX_VIDEO_AVCProfileMax),
component_name_is_nvidia_h264ext_(false) {
RETURN_ON_FAILURE(AreOMXFunctionPointersInitialized(),
static bool omx_functions_initialized = PostSandboxInitialization();
RETURN_ON_FAILURE(omx_functions_initialized,
"Failed to load openmax library", PLATFORM_FAILURE,);
RETURN_ON_OMX_FAILURE(omx_init(), "Failed to init OpenMAX core",
PLATFORM_FAILURE,);
@ -993,6 +986,32 @@ void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event,
}
}
// static
void OmxVideoDecodeAccelerator::PreSandboxInitialization() {
DCHECK(!pre_sandbox_init_done_);
omx_handle = dlopen("libOmxCore.so", RTLD_NOW);
pre_sandbox_init_done_ = omx_handle != NULL;
}
// static
bool OmxVideoDecodeAccelerator::PostSandboxInitialization() {
if (!pre_sandbox_init_done_)
return false;
omx_init = reinterpret_cast<OMXInit>(dlsym(omx_handle, "OMX_Init"));
omx_gethandle =
reinterpret_cast<OMXGetHandle>(dlsym(omx_handle, "OMX_GetHandle"));
omx_get_components_of_role =
reinterpret_cast<OMXGetComponentsOfRole>(
dlsym(omx_handle, "OMX_GetComponentsOfRole"));
omx_free_handle =
reinterpret_cast<OMXFreeHandle>(dlsym(omx_handle, "OMX_FreeHandle"));
omx_deinit =
reinterpret_cast<OMXDeinit>(dlsym(omx_handle, "OMX_Deinit"));
return (omx_init && omx_gethandle && omx_get_components_of_role &&
omx_free_handle && omx_deinit);
}
// static
OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component,
OMX_PTR priv_data,

@ -54,6 +54,9 @@ class CONTENT_EXPORT OmxVideoDecodeAccelerator :
base::WeakPtr<OmxVideoDecodeAccelerator> weak_this() { return weak_this_; }
// Do any necessary initialization before the sandbox is enabled.
static void PreSandboxInitialization();
private:
// Because OMX state-transitions are described solely by the "state reached"
// (3.1.2.9.1, table 3-7 of the spec), we track what transition was requested
@ -143,6 +146,10 @@ class CONTENT_EXPORT OmxVideoDecodeAccelerator :
// Decode bitstream buffers that were queued (see queued_bitstream_buffers_).
void DecodeQueuedBitstreamBuffers();
// Lazily initialize static data after sandbox is enabled. Return false on
// init failure.
static bool PostSandboxInitialization();
// Weak pointer to |this|; used to safely trampoline calls from the OMX thread
// to the ChildThread. Since |this| is kept alive until OMX is fully shut
// down, only the OMX->Child thread direction needs to be guarded this way.
@ -207,6 +214,9 @@ class CONTENT_EXPORT OmxVideoDecodeAccelerator :
uint32 h264_profile_; // OMX_AVCProfile requested during Initialization.
bool component_name_is_nvidia_h264ext_;
// Has static initialization of pre-sandbox components completed successfully?
static bool pre_sandbox_init_done_;
// Method to handle events
void EventHandlerCompleteTask(OMX_EVENTTYPE event,
OMX_U32 data1,

@ -34,8 +34,8 @@
namespace content {
void *vaapi_handle = dlopen("libva.so", RTLD_NOW);
void *vaapi_x11_handle = dlopen("libva-x11.so", RTLD_NOW);
void *vaapi_handle = NULL;
void *vaapi_x11_handle = NULL;
typedef VADisplay (*VaapiGetDisplay)(Display *dpy);
typedef int (*VaapiDisplayIsValid)(VADisplay dpy);
@ -106,51 +106,30 @@ typedef VAStatus (*VaapiCreateBuffer)(VADisplay dpy,
typedef VAStatus (*VaapiDestroyBuffer)(VADisplay dpy, VABufferID buffer_id);
typedef const char* (*VaapiErrorStr)(VAStatus error_status);
#define VAAPI_DLSYM(name, handle) \
Vaapi##name VAAPI_##name = \
reinterpret_cast<Vaapi##name>(dlsym((handle), "va"#name))
#define VAAPI_SYM(name, handle) Vaapi##name VAAPI_##name = NULL
VAAPI_DLSYM(GetDisplay, vaapi_x11_handle);
VAAPI_DLSYM(DisplayIsValid, vaapi_handle);
VAAPI_DLSYM(Initialize, vaapi_handle);
VAAPI_DLSYM(Terminate, vaapi_handle);
VAAPI_DLSYM(GetConfigAttributes, vaapi_handle);
VAAPI_DLSYM(CreateConfig, vaapi_handle);
VAAPI_DLSYM(DestroyConfig, vaapi_handle);
VAAPI_DLSYM(CreateSurfaces, vaapi_handle);
VAAPI_DLSYM(DestroySurfaces, vaapi_handle);
VAAPI_DLSYM(CreateContext, vaapi_handle);
VAAPI_DLSYM(DestroyContext, vaapi_handle);
VAAPI_DLSYM(PutSurface, vaapi_x11_handle);
VAAPI_DLSYM(SyncSurface, vaapi_x11_handle);
VAAPI_DLSYM(BeginPicture, vaapi_handle);
VAAPI_DLSYM(RenderPicture, vaapi_handle);
VAAPI_DLSYM(EndPicture, vaapi_handle);
VAAPI_DLSYM(CreateBuffer, vaapi_handle);
VAAPI_DLSYM(DestroyBuffer, vaapi_handle);
VAAPI_DLSYM(ErrorStr, vaapi_handle);
VAAPI_SYM(GetDisplay, vaapi_x11_handle);
VAAPI_SYM(DisplayIsValid, vaapi_handle);
VAAPI_SYM(Initialize, vaapi_handle);
VAAPI_SYM(Terminate, vaapi_handle);
VAAPI_SYM(GetConfigAttributes, vaapi_handle);
VAAPI_SYM(CreateConfig, vaapi_handle);
VAAPI_SYM(DestroyConfig, vaapi_handle);
VAAPI_SYM(CreateSurfaces, vaapi_handle);
VAAPI_SYM(DestroySurfaces, vaapi_handle);
VAAPI_SYM(CreateContext, vaapi_handle);
VAAPI_SYM(DestroyContext, vaapi_handle);
VAAPI_SYM(PutSurface, vaapi_x11_handle);
VAAPI_SYM(SyncSurface, vaapi_x11_handle);
VAAPI_SYM(BeginPicture, vaapi_handle);
VAAPI_SYM(RenderPicture, vaapi_handle);
VAAPI_SYM(EndPicture, vaapi_handle);
VAAPI_SYM(CreateBuffer, vaapi_handle);
VAAPI_SYM(DestroyBuffer, vaapi_handle);
VAAPI_SYM(ErrorStr, vaapi_handle);
static bool AreVaapiFunctionPointersInitialized() {
return VAAPI_GetDisplay &&
VAAPI_DisplayIsValid &&
VAAPI_Initialize &&
VAAPI_Terminate &&
VAAPI_GetConfigAttributes &&
VAAPI_CreateConfig &&
VAAPI_DestroyConfig &&
VAAPI_CreateSurfaces &&
VAAPI_DestroySurfaces &&
VAAPI_CreateContext &&
VAAPI_DestroyContext &&
VAAPI_PutSurface &&
VAAPI_SyncSurface &&
VAAPI_BeginPicture &&
VAAPI_RenderPicture &&
VAAPI_EndPicture &&
VAAPI_CreateBuffer &&
VAAPI_DestroyBuffer &&
VAAPI_ErrorStr;
}
// static
bool VaapiH264Decoder::pre_sandbox_init_done_ = false;
class VaapiH264Decoder::DecodeSurface {
public:
@ -502,11 +481,6 @@ bool VaapiH264Decoder::Initialize(
return false;
}
if (!AreVaapiFunctionPointersInitialized()) {
DVLOG(1) << "Could not load libva";
return false;
}
if (!InitializeFBConfig()) {
DVLOG(1) << "Could not get a usable FBConfig";
return false;
@ -2132,4 +2106,61 @@ size_t VaapiH264Decoder::GetRequiredNumOfPictures() {
return kNumReqPictures;
}
// static
void VaapiH264Decoder::PreSandboxInitialization() {
DCHECK(!pre_sandbox_init_done_);
vaapi_handle = dlopen("libva.so", RTLD_NOW);
vaapi_x11_handle = dlopen("libva-x11.so", RTLD_NOW);
pre_sandbox_init_done_ = vaapi_handle && vaapi_x11_handle;
}
// static
bool VaapiH264Decoder::PostSandboxInitialization() {
if (!pre_sandbox_init_done_)
return false;
#define VAAPI_DLSYM(name, handle) \
VAAPI_##name = reinterpret_cast<Vaapi##name>(dlsym((handle), "va"#name)) \
VAAPI_DLSYM(GetDisplay, vaapi_x11_handle);
VAAPI_DLSYM(DisplayIsValid, vaapi_handle);
VAAPI_DLSYM(Initialize, vaapi_handle);
VAAPI_DLSYM(Terminate, vaapi_handle);
VAAPI_DLSYM(GetConfigAttributes, vaapi_handle);
VAAPI_DLSYM(CreateConfig, vaapi_handle);
VAAPI_DLSYM(DestroyConfig, vaapi_handle);
VAAPI_DLSYM(CreateSurfaces, vaapi_handle);
VAAPI_DLSYM(DestroySurfaces, vaapi_handle);
VAAPI_DLSYM(CreateContext, vaapi_handle);
VAAPI_DLSYM(DestroyContext, vaapi_handle);
VAAPI_DLSYM(PutSurface, vaapi_x11_handle);
VAAPI_DLSYM(SyncSurface, vaapi_x11_handle);
VAAPI_DLSYM(BeginPicture, vaapi_handle);
VAAPI_DLSYM(RenderPicture, vaapi_handle);
VAAPI_DLSYM(EndPicture, vaapi_handle);
VAAPI_DLSYM(CreateBuffer, vaapi_handle);
VAAPI_DLSYM(DestroyBuffer, vaapi_handle);
VAAPI_DLSYM(ErrorStr, vaapi_handle);
#undef VAAPI_DLSYM
return VAAPI_GetDisplay &&
VAAPI_DisplayIsValid &&
VAAPI_Initialize &&
VAAPI_Terminate &&
VAAPI_GetConfigAttributes &&
VAAPI_CreateConfig &&
VAAPI_DestroyConfig &&
VAAPI_CreateSurfaces &&
VAAPI_DestroySurfaces &&
VAAPI_CreateContext &&
VAAPI_DestroyContext &&
VAAPI_PutSurface &&
VAAPI_SyncSurface &&
VAAPI_BeginPicture &&
VAAPI_RenderPicture &&
VAAPI_EndPicture &&
VAAPI_CreateBuffer &&
VAAPI_DestroyBuffer &&
VAAPI_ErrorStr;
}
} // namespace content

@ -129,6 +129,13 @@ class VaapiH264Decoder {
// Valid after a successful DecodeInitial().
static size_t GetRequiredNumOfPictures();
// Do any necessary initialization before the sandbox is enabled.
static void PreSandboxInitialization();
// Lazily initialize static data after sandbox is enabled. Return false on
// init failure.
static bool PostSandboxInitialization();
private:
// We need to keep at least kDPBMaxSize pictures in DPB for
// reference/to display later and an additional one for the one currently
@ -333,6 +340,9 @@ class VaapiH264Decoder {
// Called by decoder when a picture should be outputted.
OutputPicCB output_pic_cb_;
// Has static initialization of pre-sandbox components completed successfully?
static bool pre_sandbox_init_done_;
DISALLOW_COPY_AND_ASSIGN(VaapiH264Decoder);
};

@ -67,6 +67,10 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
client_(client_ptr_factory_.GetWeakPtr()),
decoder_thread_("VaapiDecoderThread") {
DCHECK(client);
static bool vaapi_functions_initialized = PostSandboxInitialization();
RETURN_AND_NOTIFY_ON_FAILURE(vaapi_functions_initialized,
"Failed to initialize VAAPI libs",
PLATFORM_FAILURE, );
}
VaapiVideoDecodeAccelerator::~VaapiVideoDecodeAccelerator() {
@ -555,6 +559,16 @@ void VaapiVideoDecodeAccelerator::Destroy() {
delete this;
}
// static
void VaapiVideoDecodeAccelerator::PreSandboxInitialization() {
VaapiH264Decoder::PreSandboxInitialization();
}
// static
bool VaapiVideoDecodeAccelerator::PostSandboxInitialization() {
return VaapiH264Decoder::PostSandboxInitialization();
}
void VaapiVideoDecodeAccelerator::OutputPicCallback(int32 input_id,
int32 output_id) {
TRACE_EVENT2("Video Decoder", "VAVDA::OutputPicCallback",

@ -56,7 +56,10 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator :
virtual void Reset() OVERRIDE;
virtual void Destroy() OVERRIDE;
private:
// Do any necessary initialization before the sandbox is enabled.
static void PreSandboxInitialization();
private:
// Ensure data has been synced with the output texture and notify
// the client it is ready for displaying.
void SyncAndNotifyPictureReady(int32 input_id, int32 output_id);
@ -122,6 +125,10 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator :
// Helper for Destroy(), doing all the actual work except for deleting self.
void Cleanup();
// Lazily initialize static data after sandbox is enabled. Return false on
// init failure.
static bool PostSandboxInitialization();
// Client-provided X/GLX state.
Display* x_display_;
GLXContext glx_context_;

@ -889,6 +889,10 @@ int main(int argc, char **argv) {
#if defined(OS_WIN)
DXVAVideoDecodeAccelerator::PreSandboxInitialization();
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
OmxVideoDecodeAccelerator::PreSandboxInitialization();
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
VaapiVideoDecodeAccelerator::PreSandboxInitialization();
#endif
return RUN_ALL_TESTS();

@ -100,5 +100,15 @@
'../third_party/libXNVCtrl/libXNVCtrl.gyp:libXNVCtrl',
],
}],
['target_arch=="arm" and chromeos == 1', {
'include_dirs': [
'<(DEPTH)/third_party/openmax/il',
],
}],
['target_arch!="arm" and chromeos == 1', {
'include_dirs': [
'<(DEPTH)/third_party/libva',
],
}],
],
}

@ -30,6 +30,10 @@
#if defined(OS_WIN)
#include "content/common/gpu/media/dxva_video_decode_accelerator.h"
#include "sandbox/win/src/sandbox.h"
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
#include "content/common/gpu/media/omx_video_decode_accelerator.h"
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
#include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
#endif
#if defined(USE_X11)
@ -149,6 +153,12 @@ int GpuMain(const content::MainFunctionParams& parameters) {
TRACE_EVENT0("gpu", "Initialize sandbox");
bool do_init_sandbox = true;
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
OmxVideoDecodeAccelerator::PreSandboxInitialization();
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
VaapiVideoDecodeAccelerator::PreSandboxInitialization();
#endif
#if defined(OS_CHROMEOS) && defined(NDEBUG)
// On Chrome OS and when not on a debug build, initialize
// the GPU process' sandbox only for Intel GPUs.