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

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: 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
« no previous file with comments | « content/common/gpu/media/omx_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..473c73929f38cb0d0ef6b7deff210b198275e68d 100644
--- a/content/common/gpu/media/omx_video_decode_accelerator.cc
+++ b/content/common/gpu/media/omx_video_decode_accelerator.cc
@@ -36,6 +36,10 @@ OMXGetComponentsOfRole omx_get_components_of_role = NULL;
OMXFreeHandle omx_free_handle = NULL;
OMXDeinit omx_deinit = NULL;
+static PFNEGLCREATESYNCKHRPROC egl_create_sync_khr = NULL;
+static PFNEGLGETSYNCATTRIBKHRPROC egl_get_sync_attrib_khr = NULL;
+static PFNEGLDESTROYSYNCKHRPROC egl_destroy_sync_khr = NULL;
+
// Maps h264-related Profile enum values to OMX_VIDEO_AVCPROFILETYPE values.
static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) {
switch (profile) {
@@ -386,9 +390,106 @@ void OmxVideoDecodeAccelerator::AssignPictureBuffers(
return;
}
+class OmxVideoDecodeAccelerator::PictureSyncObject {
+ public:
+ PictureSyncObject();
+ ~PictureSyncObject();
+
+ // Create a sync object and insert into the GPU command stream.
+ // Returns false on failure.
+ bool Create(EGLDisplay egl_display);
Ami GONE FROM CHROMIUM 2012/10/12 17:20:05 All of the error conditions that can cause creates
Pawel Osciak 2012/10/12 17:50:50 Not sure what you mean, egl_create_sync_khr may fa
Ami GONE FROM CHROMIUM 2012/10/12 17:57:28 Where does the spec permit that? Do you mean s/rea
Pawel Osciak 2012/10/12 18:39:28 Well, mostly things like out of memory or driver i
+ // Check the status of the sync object. Return true if synced or if an error
+ // occurred so as not to wait forever.
+ bool IsSynced();
+
+ private:
+ EGLSyncKHR egl_sync_obj_;
+ EGLDisplay egl_display_;
+};
+
+OmxVideoDecodeAccelerator::PictureSyncObject::PictureSyncObject()
+ : egl_sync_obj_(EGL_NO_SYNC_KHR),
+ egl_display_(EGL_NO_DISPLAY) {
+}
+
+OmxVideoDecodeAccelerator::PictureSyncObject::~PictureSyncObject() {
+ if (egl_sync_obj_ != EGL_NO_SYNC_KHR && egl_display_ != EGL_NO_SYNC_KHR)
+ egl_destroy_sync_khr(egl_display_, egl_sync_obj_);
+}
+
+bool OmxVideoDecodeAccelerator::PictureSyncObject::Create(
+ EGLDisplay egl_display) {
+
+ egl_display_ = egl_display;
+
+ // Create a sync object and insert it into the command stream.
+ egl_sync_obj_ = egl_create_sync_khr(egl_display_, EGL_SYNC_FENCE_KHR, 0);
Ami GONE FROM CHROMIUM 2012/10/12 17:20:05 s/0/NULL/
Pawel Osciak 2012/10/12 18:39:28 Done.
+ if (egl_sync_obj_ == EGL_NO_SYNC_KHR) {
+ DLOG(WARNING) << "Could not create EGL sync object, will not sync.";
+ return false;
+ }
+
+ return true;
+}
+
+bool OmxVideoDecodeAccelerator::PictureSyncObject::IsSynced() {
+ EGLint value;
+ EGLBoolean ret = egl_get_sync_attrib_khr(
+ egl_display_, egl_sync_obj_, EGL_SYNC_STATUS_KHR, &value);
+ if (ret == EGL_TRUE && value == EGL_UNSIGNALED_KHR)
+ return false;
+
+ // The object has been signalled or we got an error polling the state. If we
+ // got an error (ret == EGL_FALSE), we allow to continue as well. Worst case,
+ // we'll get some corruption, but the decoding can continue safely.
+ DCHECK(ret) << "EGL sync failed, continuing without syncing.";
Ami GONE FROM CHROMIUM 2012/10/12 17:20:05 lolwat? In Debug, ain't nuthin' continuing after a
Pawel Osciak 2012/10/12 17:50:50 lolled myself, not sure what I was thinking. I'm n
Pawel Osciak 2012/10/12 18:39:28 Done.
+ return true;
+}
+
void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
+ DCHECK_EQ(message_loop_, MessageLoop::current());
TRACE_EVENT1("Video Decoder", "OVDA::ReusePictureBuffer",
"Picture id", picture_buffer_id);
+ scoped_ptr<PictureSyncObject> egl_sync_obj(new PictureSyncObject);
+
+
+ if (!egl_sync_obj->Create(egl_display_)) {
+ // If creating the sync object failed, just requeue it, we might
+ // get artifacts, but decoding will continue.
+ QueuePictureBuffer(picture_buffer_id);
+ return;
+ }
+
+ // Inserted the object successfully, start checking it periodically.
+ CheckPictureStatus(picture_buffer_id, egl_sync_obj.Pass());
+}
+
+void OmxVideoDecodeAccelerator::CheckPictureStatus(
+ int32 picture_buffer_id,
+ scoped_ptr<PictureSyncObject> egl_sync_obj) {
+ DCHECK_EQ(message_loop_, MessageLoop::current());
+
+ // It's possible for this task to get cancelled if the decoder is being
Ami GONE FROM CHROMIUM 2012/10/12 17:20:05 s/get cancelled/never run/
Ami GONE FROM CHROMIUM 2012/10/12 17:20:05 s/decoder is destroyed/messageloop is stopped/
Pawel Osciak 2012/10/12 18:39:28 Done.
Pawel Osciak 2012/10/12 18:39:28 Done.
+ // destroyed. In that case we may never call QueuePictureBuffer().
+ // This is fine though, because all pictures, irrespective of their state,
+ // are in pictures_ map and that's what will be used to do the clean up.
+ // 5ms feels like a good compromise, allowing some decoding ahead
+ // (up to 3 frames/vsync) to compensate for more difficult frames.
+ if (!egl_sync_obj->IsSynced()) {
+ MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(
+ &OmxVideoDecodeAccelerator::CheckPictureStatus, base::Unretained(this),
Ami GONE FROM CHROMIUM 2012/10/12 17:20:05 s/base::Unretained(this)/weak_this_/ because what
Pawel Osciak 2012/10/12 18:39:28 Another brain fart, must've still been in the sub-
+ picture_buffer_id, base::Passed(egl_sync_obj.Pass())),
Ami GONE FROM CHROMIUM 2012/10/12 17:20:05 replace egl_sync_obj.Pass() with &egl_sync_obj
Pawel Osciak 2012/10/12 18:39:28 Ok. FWIW got inspired by http://code.google.com/se
Ami GONE FROM CHROMIUM 2012/10/12 19:34:46 Huh; filed bug 155593 to eradicate that pattern.
+ base::TimeDelta::FromMilliseconds(5));
+ return;
+ }
+
+ // Synced successfully or getting sync status failed. Queue the buffer for
Ami GONE FROM CHROMIUM 2012/10/12 17:20:05 drop "failed" clause
Pawel Osciak 2012/10/12 18:39:28 Done.
+ // reuse, in the latter case we might get some corruption, but decoding can
+ // continue safely.
+ QueuePictureBuffer(picture_buffer_id);
+}
+
+void OmxVideoDecodeAccelerator::QueuePictureBuffer(int32 picture_buffer_id) {
DCHECK_EQ(message_loop_, MessageLoop::current());
// During port-flushing, do not call OMX FillThisBuffer.
@@ -397,7 +498,11 @@ void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
return;
}
- RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,);
+ // We might have started destroying while waiting for the picture. It's safe
+ // to drop it here, because we will free all the pictures regardless of their
+ // state using the pictures_ map.
+ if (!CanFillBuffer())
+ return;
OutputPictureById::iterator it = pictures_.find(picture_buffer_id);
RETURN_ON_FAILURE(it != pictures_.end(),
@@ -1091,8 +1196,17 @@ bool OmxVideoDecodeAccelerator::PostSandboxInitialization() {
reinterpret_cast<OMXFreeHandle>(dlsym(omx_handle, "OMX_FreeHandle"));
omx_deinit =
reinterpret_cast<OMXDeinit>(dlsym(omx_handle, "OMX_Deinit"));
+
+ egl_create_sync_khr = reinterpret_cast<PFNEGLCREATESYNCKHRPROC>(
+ eglGetProcAddress("eglCreateSyncKHR"));
+ egl_get_sync_attrib_khr = reinterpret_cast<PFNEGLGETSYNCATTRIBKHRPROC>(
+ eglGetProcAddress("eglGetSyncAttribKHR"));
+ egl_destroy_sync_khr = reinterpret_cast<PFNEGLDESTROYSYNCKHRPROC>(
+ eglGetProcAddress("eglDestroySyncKHR"));
+
return (omx_init && omx_gethandle && omx_get_components_of_role &&
- omx_free_handle && omx_deinit);
+ omx_free_handle && omx_deinit && egl_create_sync_khr &&
+ egl_get_sync_attrib_khr && egl_destroy_sync_khr);
}
// static
« no previous file with comments | « content/common/gpu/media/omx_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698