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

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

Issue 11076009: OVDA: Perform an egl sync before reusing a texture. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: LOG()->DLOG() Created 8 years, 2 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/omx_video_decode_accelerator.cc
diff --git a/content/common/gpu/media/omx_video_decode_accelerator.cc b/content/common/gpu/media/omx_video_decode_accelerator.cc
index a72756012b6c73c58183afb348725da7a437cd6e..f9d832f448dafb36d19d30b2fe8ae1aba6a3e641 100644
--- a/content/common/gpu/media/omx_video_decode_accelerator.cc
+++ b/content/common/gpu/media/omx_video_decode_accelerator.cc
@@ -20,6 +20,7 @@
typedef std::pair<scoped_ptr<base::SharedMemory>, int32> SharedMemoryAndId;
enum { kNumPictureBuffers = 8 };
+enum { kSyncTimeoutNanosec = 50000000 };
void* omx_handle = NULL;
@@ -36,6 +37,21 @@ OMXGetComponentsOfRole omx_get_components_of_role = NULL;
OMXFreeHandle omx_free_handle = NULL;
OMXDeinit omx_deinit = NULL;
+static PFNEGLCREATESYNCKHRPROC egl_create_sync_khr =
+ reinterpret_cast<PFNEGLCREATESYNCKHRPROC>(
+ eglGetProcAddress("eglCreateSyncKHR"));
piman 2012/10/06 06:42:40 No static initialization. Realize that this code r
Pawel Osciak 2012/10/10 17:37:52 Ok, I was inspired by Gles2TextureToEglImageTransl
+static PFNEGLCLIENTWAITSYNCKHRPROC egl_client_wait_sync_khr =
+ reinterpret_cast<PFNEGLCLIENTWAITSYNCKHRPROC>(
+ eglGetProcAddress("eglClientWaitSyncKHR"));
+static PFNEGLDESTROYSYNCKHRPROC egl_destroy_sync_khr =
+ reinterpret_cast<PFNEGLDESTROYSYNCKHRPROC>(
+ eglGetProcAddress("eglDestroySyncKHR"));
+
+static bool AreEGLExtensionsInitialized() {
+ return egl_create_sync_khr && egl_client_wait_sync_khr &&
+ egl_destroy_sync_khr;
+}
+
// Maps h264-related Profile enum values to OMX_VIDEO_AVCPROFILETYPE values.
static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) {
switch (profile) {
@@ -111,7 +127,10 @@ OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator(
client_(client),
codec_(UNKNOWN),
h264_profile_(OMX_VIDEO_AVCProfileMax),
- component_name_is_nvidia_h264ext_(false) {
+ component_name_is_nvidia_h264ext_(false),
+ sync_thread_("OVDASyncThread") {
+ RETURN_ON_FAILURE(AreEGLExtensionsInitialized(),
+ "Failed to load EGL extensions", PLATFORM_FAILURE,);
static bool omx_functions_initialized = PostSandboxInitialization();
RETURN_ON_FAILURE(omx_functions_initialized,
"Failed to load openmax library", PLATFORM_FAILURE,);
@@ -150,6 +169,8 @@ bool OmxVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
INVALID_ARGUMENT, false);
}
+ CHECK(sync_thread_.Start());
+
if (!CreateComponent()) // Does its own RETURN_ON_FAILURE dances.
return false;
@@ -387,8 +408,50 @@ void OmxVideoDecodeAccelerator::AssignPictureBuffers(
}
void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
+ DCHECK_EQ(message_loop_, MessageLoop::current());
TRACE_EVENT1("Video Decoder", "OVDA::ReusePictureBuffer",
"Picture id", picture_buffer_id);
+
+ // Create a sync object and insert it into the command stream.
+ EGLSyncKHR egl_sync_obj = egl_create_sync_khr(egl_display_,
sheu 2012/10/06 21:54:53 I'd be concerned about this leaking an EGLSyncKHR
sheu 2012/10/06 21:56:00 I meant: "if you eventually make these callbacks c
Pawel Osciak 2012/10/10 17:37:52 Yes, not happening now, but if we go with PostDela
+ EGL_SYNC_FENCE_KHR,
+ 0);
+ if (egl_sync_obj == EGL_NO_SYNC_KHR) {
+ DLOG(WARNING) << "Could not create EGL sync object.";
+ // If creating the sync object failed, just requeue it, we will lose
+ // the synchronization and could possible have artifacts, but decoding
+ // will continue. QueuePictureBuffer(picture_buffer_id);
+ return;
+ }
+
+ // Inserted the object successfully, wait on the sync_thread_ for it to
+ // become signalled.
+ sync_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &OmxVideoDecodeAccelerator::WaitForPictureSync, weak_this_,
piman 2012/10/06 06:42:40 You can't pass a weak pointer to another thread. I
Pawel Osciak 2012/10/10 17:37:52 I'll just use Unretained and weakptr back. This is
+ picture_buffer_id, egl_sync_obj));
+}
+
+void OmxVideoDecodeAccelerator::WaitForPictureSync(int32 picture_buffer_id,
+ EGLSyncKHR egl_sync_obj) {
+ DCHECK_EQ(sync_thread_.message_loop(), MessageLoop::current());
+
+ EGLint ret = egl_client_wait_sync_khr(egl_display_, egl_sync_obj,
piman 2012/10/06 06:42:40 How do you know it's safe to access egl_display_ w
Pawel Osciak 2012/10/10 17:37:52 The thread is a member of this, so this can't be d
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+ kSyncTimeoutNanosec);
piman 2012/10/06 06:42:40 Why using a timeout at all? A lock with a timeout
Pawel Osciak 2012/10/10 17:37:52 Well, the idea was to not block the whole thing fo
+ // If the sync fails, ignore it. Worst case we'll get some artifacts, but
+ // will continue decoding.
+ if (ret != EGL_CONDITION_SATISFIED_KHR)
+ DLOG(WARNING) << "Failed EGL sync.";
+
+ egl_destroy_sync_khr(egl_display_, egl_sync_obj);
+
+ // Post back onto main thread to queue the picture for future use.
+ message_loop_->PostTask(FROM_HERE, base::Bind(
piman 2012/10/06 06:42:40 Same here, accessing message_loop_ isn't safe. Ins
Pawel Osciak 2012/10/10 17:37:52 Passing weak pointer to sync_thread is wrong and y
+ &OmxVideoDecodeAccelerator::QueuePictureBuffer, weak_this_,
+ picture_buffer_id));
+}
+
+void OmxVideoDecodeAccelerator::QueuePictureBuffer(int32 picture_buffer_id) {
DCHECK_EQ(message_loop_, MessageLoop::current());
// During port-flushing, do not call OMX FillThisBuffer.

Powered by Google App Engine
This is Rietveld 408576698