Chromium Code Reviews| 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..31af10fa7934689dc7b71fd8aaf0980beddd8ed1 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,82 @@ void OmxVideoDecodeAccelerator::AssignPictureBuffers( |
| return; |
| } |
| +class OmxVideoDecodeAccelerator::PictureSyncObject { |
|
piman
2012/10/12 19:37:10
nit: we usually don't define inner classes in the
Pawel Osciak
2012/10/12 20:33:08
Ok, if that's the convention. (The idea was to hav
|
| + public: |
| + // Create a sync object and insert into the GPU command stream. |
| + PictureSyncObject(EGLDisplay egl_display); |
| + ~PictureSyncObject(); |
| + |
| + // Check the status of the sync object. Return true if synced. |
|
Ami GONE FROM CHROMIUM
2012/10/12 19:34:46
Style-guide-sanctioned comment style would be:
//
Pawel Osciak
2012/10/12 20:33:08
Done.
|
| + bool IsSynced(); |
| + |
| + private: |
| + EGLSyncKHR egl_sync_obj_; |
| + EGLDisplay egl_display_; |
| +}; |
| + |
| +OmxVideoDecodeAccelerator::PictureSyncObject::PictureSyncObject( |
| + EGLDisplay egl_display) |
| + : egl_display_(egl_display) { |
| + DCHECK(egl_display_ != EGL_NO_DISPLAY); |
| + |
| + egl_sync_obj_ = egl_create_sync_khr(egl_display_, EGL_SYNC_FENCE_KHR, NULL); |
| + DCHECK(egl_sync_obj_ != EGL_NO_SYNC_KHR) |
| + << "Failed creating a sync object, will not sync."; |
|
Ami GONE FROM CHROMIUM
2012/10/12 19:34:46
msg is still bogus (not only will the process not
Pawel Osciak
2012/10/12 20:33:08
Heh. Somehow my brain won't acknowledge that this
|
| +} |
| + |
| +OmxVideoDecodeAccelerator::PictureSyncObject::~PictureSyncObject() { |
| + if (egl_sync_obj_ != EGL_NO_SYNC_KHR) |
|
Ami GONE FROM CHROMIUM
2012/10/12 19:34:46
Not possible for this to be false anymore, so can
Pawel Osciak
2012/10/12 20:33:08
Done.
|
| + egl_destroy_sync_khr(egl_display_, egl_sync_obj_); |
| +} |
| + |
| +bool OmxVideoDecodeAccelerator::PictureSyncObject::IsSynced() { |
| + EGLint value; |
|
piman
2012/10/12 19:37:10
nit: = 0
Ami GONE FROM CHROMIUM
2012/10/12 19:43:56
OOC: Why?
Pawel Osciak
2012/10/12 20:33:08
Are you worried the call would exit early before o
Pawel Osciak
2012/10/12 20:34:54
Oh, but that's only only in debug builds. I really
|
| + EGLBoolean ret = egl_get_sync_attrib_khr( |
| + egl_display_, egl_sync_obj_, EGL_SYNC_STATUS_KHR, &value); |
| + DCHECK(ret) << "Failed getting sync object state."; |
| + |
| + if (value == EGL_UNSIGNALED_KHR) |
|
Ami GONE FROM CHROMIUM
2012/10/12 19:34:46
l.428-431 is equiv to
return value == EGL_SIGNALED
Pawel Osciak
2012/10/12 20:33:08
Done.
|
| + return false; |
| + |
| + 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(egl_display_)); |
| + |
| + // Start checking sync status 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 never run if the message loop is |
| + // stopped. 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, weak_this_, |
| + picture_buffer_id, base::Passed(&egl_sync_obj)), |
| + base::TimeDelta::FromMilliseconds(5)); |
|
piman
2012/10/12 19:37:10
nit: can you make this a constant in global scope
Pawel Osciak
2012/10/12 20:33:08
Done.
|
| + return; |
| + } |
| + |
| + // Synced successfully. Queue the buffer for reuse. |
| + 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 +474,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 +1172,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 |