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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/common/gpu/media/omx_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/gpu/media/omx_video_decode_accelerator.h" 5 #include "content/common/gpu/media/omx_video_decode_accelerator.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "content/common/gpu/gpu_channel.h" 12 #include "content/common/gpu/gpu_channel.h"
13 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h" 13 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h"
14 #include "media/base/bitstream_buffer.h" 14 #include "media/base/bitstream_buffer.h"
15 #include "media/video/picture.h" 15 #include "media/video/picture.h"
16 16
17 // Helper typedef for input buffers. This is used as the pAppPrivate field of 17 // Helper typedef for input buffers. This is used as the pAppPrivate field of
18 // OMX_BUFFERHEADERTYPEs of input buffers, to point to the data associated with 18 // OMX_BUFFERHEADERTYPEs of input buffers, to point to the data associated with
19 // them. 19 // them.
20 typedef std::pair<scoped_ptr<base::SharedMemory>, int32> SharedMemoryAndId; 20 typedef std::pair<scoped_ptr<base::SharedMemory>, int32> SharedMemoryAndId;
21 21
22 enum { kNumPictureBuffers = 8 }; 22 enum { kNumPictureBuffers = 8 };
23 23
24 // Delay between polling for texture sync status. 5ms feels like a good
25 // compromise, allowing some decoding ahead (up to 3 frames/vsync) to compensate
26 // for more difficult frames.
27 enum { kSyncPollDelayMs = 5 };
28
24 void* omx_handle = NULL; 29 void* omx_handle = NULL;
25 30
26 typedef OMX_ERRORTYPE (*OMXInit)(); 31 typedef OMX_ERRORTYPE (*OMXInit)();
27 typedef OMX_ERRORTYPE (*OMXGetHandle)( 32 typedef OMX_ERRORTYPE (*OMXGetHandle)(
28 OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*); 33 OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*);
29 typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**); 34 typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**);
30 typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE); 35 typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE);
31 typedef OMX_ERRORTYPE (*OMXDeinit)(); 36 typedef OMX_ERRORTYPE (*OMXDeinit)();
32 37
33 OMXInit omx_init = NULL; 38 OMXInit omx_init = NULL;
34 OMXGetHandle omx_gethandle = NULL; 39 OMXGetHandle omx_gethandle = NULL;
35 OMXGetComponentsOfRole omx_get_components_of_role = NULL; 40 OMXGetComponentsOfRole omx_get_components_of_role = NULL;
36 OMXFreeHandle omx_free_handle = NULL; 41 OMXFreeHandle omx_free_handle = NULL;
37 OMXDeinit omx_deinit = NULL; 42 OMXDeinit omx_deinit = NULL;
38 43
44 static PFNEGLCREATESYNCKHRPROC egl_create_sync_khr = NULL;
45 static PFNEGLGETSYNCATTRIBKHRPROC egl_get_sync_attrib_khr = NULL;
46 static PFNEGLDESTROYSYNCKHRPROC egl_destroy_sync_khr = NULL;
47
39 // Maps h264-related Profile enum values to OMX_VIDEO_AVCPROFILETYPE values. 48 // Maps h264-related Profile enum values to OMX_VIDEO_AVCPROFILETYPE values.
40 static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) { 49 static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) {
41 switch (profile) { 50 switch (profile) {
42 case media::H264PROFILE_BASELINE: 51 case media::H264PROFILE_BASELINE:
43 return OMX_VIDEO_AVCProfileBaseline; 52 return OMX_VIDEO_AVCProfileBaseline;
44 case media::H264PROFILE_MAIN: 53 case media::H264PROFILE_MAIN:
45 return OMX_VIDEO_AVCProfileMain; 54 return OMX_VIDEO_AVCProfileMain;
46 case media::H264PROFILE_EXTENDED: 55 case media::H264PROFILE_EXTENDED:
47 return OMX_VIDEO_AVCProfileExtended; 56 return OMX_VIDEO_AVCProfileExtended;
48 case media::H264PROFILE_HIGH: 57 case media::H264PROFILE_HIGH:
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 // OMX-specific version of RETURN_ON_FAILURE which compares with OMX_ErrorNone. 91 // OMX-specific version of RETURN_ON_FAILURE which compares with OMX_ErrorNone.
83 #define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \ 92 #define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \
84 RETURN_ON_FAILURE( \ 93 RETURN_ON_FAILURE( \
85 ((omx_result) == OMX_ErrorNone), \ 94 ((omx_result) == OMX_ErrorNone), \
86 log << ", OMX result: 0x" << std::hex << omx_result, \ 95 log << ", OMX result: 0x" << std::hex << omx_result, \
87 error, ret_val) 96 error, ret_val)
88 97
89 // static 98 // static
90 bool OmxVideoDecodeAccelerator::pre_sandbox_init_done_ = false; 99 bool OmxVideoDecodeAccelerator::pre_sandbox_init_done_ = false;
91 100
101 class OmxVideoDecodeAccelerator::PictureSyncObject {
102 public:
103 // Create a sync object and insert into the GPU command stream.
104 PictureSyncObject(EGLDisplay egl_display);
105 ~PictureSyncObject();
106
107 bool IsSynced();
108
109 private:
110 EGLSyncKHR egl_sync_obj_;
111 EGLDisplay egl_display_;
112 };
113
114 OmxVideoDecodeAccelerator::PictureSyncObject::PictureSyncObject(
115 EGLDisplay egl_display)
116 : egl_display_(egl_display) {
117 DCHECK(egl_display_ != EGL_NO_DISPLAY);
118
119 egl_sync_obj_ = egl_create_sync_khr(egl_display_, EGL_SYNC_FENCE_KHR, NULL);
120 DCHECK_NE(egl_sync_obj_, EGL_NO_SYNC_KHR);
121 }
122
123 OmxVideoDecodeAccelerator::PictureSyncObject::~PictureSyncObject() {
124 egl_destroy_sync_khr(egl_display_, egl_sync_obj_);
125 }
126
127 bool OmxVideoDecodeAccelerator::PictureSyncObject::IsSynced() {
128 EGLint value = EGL_UNSIGNALED_KHR;
129 EGLBoolean ret = egl_get_sync_attrib_khr(
130 egl_display_, egl_sync_obj_, EGL_SYNC_STATUS_KHR, &value);
131 DCHECK(ret) << "Failed getting sync object state.";
132
133 return value == EGL_SIGNALED_KHR;
134 }
135
92 OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator( 136 OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator(
93 EGLDisplay egl_display, EGLContext egl_context, 137 EGLDisplay egl_display, EGLContext egl_context,
94 media::VideoDecodeAccelerator::Client* client, 138 media::VideoDecodeAccelerator::Client* client,
95 const base::Callback<bool(void)>& make_context_current) 139 const base::Callback<bool(void)>& make_context_current)
96 : message_loop_(MessageLoop::current()), 140 : message_loop_(MessageLoop::current()),
97 component_handle_(NULL), 141 component_handle_(NULL),
98 weak_this_(base::AsWeakPtr(this)), 142 weak_this_(base::AsWeakPtr(this)),
99 init_begun_(false), 143 init_begun_(false),
100 client_state_(OMX_StateMax), 144 client_state_(OMX_StateMax),
101 current_state_change_(NO_TRANSITION), 145 current_state_change_(NO_TRANSITION),
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 DCHECK_EQ(pictures_.size(), kNumPictureBuffers); 424 DCHECK_EQ(pictures_.size(), kNumPictureBuffers);
381 425
382 // These do their own RETURN_ON_FAILURE dances. 426 // These do their own RETURN_ON_FAILURE dances.
383 if (!AllocateOutputBuffers()) 427 if (!AllocateOutputBuffers())
384 return; 428 return;
385 if (!SendCommandToPort(OMX_CommandPortEnable, output_port_)) 429 if (!SendCommandToPort(OMX_CommandPortEnable, output_port_))
386 return; 430 return;
387 } 431 }
388 432
389 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { 433 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
434 DCHECK_EQ(message_loop_, MessageLoop::current());
390 TRACE_EVENT1("Video Decoder", "OVDA::ReusePictureBuffer", 435 TRACE_EVENT1("Video Decoder", "OVDA::ReusePictureBuffer",
391 "Picture id", picture_buffer_id); 436 "Picture id", picture_buffer_id);
437 scoped_ptr<PictureSyncObject> egl_sync_obj(
438 new PictureSyncObject(egl_display_));
439
440 // Start checking sync status periodically.
441 CheckPictureStatus(picture_buffer_id, egl_sync_obj.Pass());
442 }
443
444 void OmxVideoDecodeAccelerator::CheckPictureStatus(
445 int32 picture_buffer_id,
446 scoped_ptr<PictureSyncObject> egl_sync_obj) {
447 DCHECK_EQ(message_loop_, MessageLoop::current());
448
449 // It's possible for this task to never run if the message loop is
450 // stopped. In that case we may never call QueuePictureBuffer().
451 // This is fine though, because all pictures, irrespective of their state,
452 // are in pictures_ map and that's what will be used to do the clean up.
453 if (!egl_sync_obj->IsSynced()) {
454 MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(
455 &OmxVideoDecodeAccelerator::CheckPictureStatus, weak_this_,
456 picture_buffer_id, base::Passed(&egl_sync_obj)),
457 base::TimeDelta::FromMilliseconds(kSyncPollDelayMs));
458 return;
459 }
460
461 // Synced successfully. Queue the buffer for reuse.
462 QueuePictureBuffer(picture_buffer_id);
463 }
464
465 void OmxVideoDecodeAccelerator::QueuePictureBuffer(int32 picture_buffer_id) {
392 DCHECK_EQ(message_loop_, MessageLoop::current()); 466 DCHECK_EQ(message_loop_, MessageLoop::current());
393 467
394 // During port-flushing, do not call OMX FillThisBuffer. 468 // During port-flushing, do not call OMX FillThisBuffer.
395 if (current_state_change_ == RESETTING) { 469 if (current_state_change_ == RESETTING) {
396 queued_picture_buffer_ids_.push_back(picture_buffer_id); 470 queued_picture_buffer_ids_.push_back(picture_buffer_id);
397 return; 471 return;
398 } 472 }
399 473
400 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,); 474 // We might have started destroying while waiting for the picture. It's safe
475 // to drop it here, because we will free all the pictures regardless of their
476 // state using the pictures_ map.
477 if (!CanFillBuffer())
478 return;
401 479
402 OutputPictureById::iterator it = pictures_.find(picture_buffer_id); 480 OutputPictureById::iterator it = pictures_.find(picture_buffer_id);
403 RETURN_ON_FAILURE(it != pictures_.end(), 481 RETURN_ON_FAILURE(it != pictures_.end(),
404 "Missing picture buffer id: " << picture_buffer_id, 482 "Missing picture buffer id: " << picture_buffer_id,
405 INVALID_ARGUMENT,); 483 INVALID_ARGUMENT,);
406 OutputPicture& output_picture = it->second; 484 OutputPicture& output_picture = it->second;
407 485
408 ++output_buffers_at_component_; 486 ++output_buffers_at_component_;
409 OMX_ERRORTYPE result = 487 OMX_ERRORTYPE result =
410 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); 488 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header);
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 omx_init = reinterpret_cast<OMXInit>(dlsym(omx_handle, "OMX_Init")); 1162 omx_init = reinterpret_cast<OMXInit>(dlsym(omx_handle, "OMX_Init"));
1085 omx_gethandle = 1163 omx_gethandle =
1086 reinterpret_cast<OMXGetHandle>(dlsym(omx_handle, "OMX_GetHandle")); 1164 reinterpret_cast<OMXGetHandle>(dlsym(omx_handle, "OMX_GetHandle"));
1087 omx_get_components_of_role = 1165 omx_get_components_of_role =
1088 reinterpret_cast<OMXGetComponentsOfRole>( 1166 reinterpret_cast<OMXGetComponentsOfRole>(
1089 dlsym(omx_handle, "OMX_GetComponentsOfRole")); 1167 dlsym(omx_handle, "OMX_GetComponentsOfRole"));
1090 omx_free_handle = 1168 omx_free_handle =
1091 reinterpret_cast<OMXFreeHandle>(dlsym(omx_handle, "OMX_FreeHandle")); 1169 reinterpret_cast<OMXFreeHandle>(dlsym(omx_handle, "OMX_FreeHandle"));
1092 omx_deinit = 1170 omx_deinit =
1093 reinterpret_cast<OMXDeinit>(dlsym(omx_handle, "OMX_Deinit")); 1171 reinterpret_cast<OMXDeinit>(dlsym(omx_handle, "OMX_Deinit"));
1172
1173 egl_create_sync_khr = reinterpret_cast<PFNEGLCREATESYNCKHRPROC>(
1174 eglGetProcAddress("eglCreateSyncKHR"));
1175 egl_get_sync_attrib_khr = reinterpret_cast<PFNEGLGETSYNCATTRIBKHRPROC>(
1176 eglGetProcAddress("eglGetSyncAttribKHR"));
1177 egl_destroy_sync_khr = reinterpret_cast<PFNEGLDESTROYSYNCKHRPROC>(
1178 eglGetProcAddress("eglDestroySyncKHR"));
1179
1094 return (omx_init && omx_gethandle && omx_get_components_of_role && 1180 return (omx_init && omx_gethandle && omx_get_components_of_role &&
1095 omx_free_handle && omx_deinit); 1181 omx_free_handle && omx_deinit && egl_create_sync_khr &&
1182 egl_get_sync_attrib_khr && egl_destroy_sync_khr);
1096 } 1183 }
1097 1184
1098 // static 1185 // static
1099 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, 1186 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component,
1100 OMX_PTR priv_data, 1187 OMX_PTR priv_data,
1101 OMX_EVENTTYPE event, 1188 OMX_EVENTTYPE event,
1102 OMX_U32 data1, 1189 OMX_U32 data1,
1103 OMX_U32 data2, 1190 OMX_U32 data2,
1104 OMX_PTR event_data) { 1191 OMX_PTR event_data) {
1105 // Called on the OMX thread. 1192 // Called on the OMX thread.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 1247
1161 bool OmxVideoDecodeAccelerator::SendCommandToPort( 1248 bool OmxVideoDecodeAccelerator::SendCommandToPort(
1162 OMX_COMMANDTYPE cmd, int port_index) { 1249 OMX_COMMANDTYPE cmd, int port_index) {
1163 DCHECK_EQ(message_loop_, MessageLoop::current()); 1250 DCHECK_EQ(message_loop_, MessageLoop::current());
1164 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, 1251 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_,
1165 cmd, port_index, 0); 1252 cmd, port_index, 0);
1166 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, 1253 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd,
1167 PLATFORM_FAILURE, false); 1254 PLATFORM_FAILURE, false);
1168 return true; 1255 return true;
1169 } 1256 }
OLDNEW
« 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