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

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"
(...skipping 18 matching lines...) Expand all
29 typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**); 29 typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**);
30 typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE); 30 typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE);
31 typedef OMX_ERRORTYPE (*OMXDeinit)(); 31 typedef OMX_ERRORTYPE (*OMXDeinit)();
32 32
33 OMXInit omx_init = NULL; 33 OMXInit omx_init = NULL;
34 OMXGetHandle omx_gethandle = NULL; 34 OMXGetHandle omx_gethandle = NULL;
35 OMXGetComponentsOfRole omx_get_components_of_role = NULL; 35 OMXGetComponentsOfRole omx_get_components_of_role = NULL;
36 OMXFreeHandle omx_free_handle = NULL; 36 OMXFreeHandle omx_free_handle = NULL;
37 OMXDeinit omx_deinit = NULL; 37 OMXDeinit omx_deinit = NULL;
38 38
39 static PFNEGLCREATESYNCKHRPROC egl_create_sync_khr = NULL;
40 static PFNEGLGETSYNCATTRIBKHRPROC egl_get_sync_attrib_khr = NULL;
41 static PFNEGLDESTROYSYNCKHRPROC egl_destroy_sync_khr = NULL;
42
39 // Maps h264-related Profile enum values to OMX_VIDEO_AVCPROFILETYPE values. 43 // Maps h264-related Profile enum values to OMX_VIDEO_AVCPROFILETYPE values.
40 static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) { 44 static OMX_U32 MapH264ProfileToOMXAVCProfile(uint32 profile) {
41 switch (profile) { 45 switch (profile) {
42 case media::H264PROFILE_BASELINE: 46 case media::H264PROFILE_BASELINE:
43 return OMX_VIDEO_AVCProfileBaseline; 47 return OMX_VIDEO_AVCProfileBaseline;
44 case media::H264PROFILE_MAIN: 48 case media::H264PROFILE_MAIN:
45 return OMX_VIDEO_AVCProfileMain; 49 return OMX_VIDEO_AVCProfileMain;
46 case media::H264PROFILE_EXTENDED: 50 case media::H264PROFILE_EXTENDED:
47 return OMX_VIDEO_AVCProfileExtended; 51 return OMX_VIDEO_AVCProfileExtended;
48 case media::H264PROFILE_HIGH: 52 case media::H264PROFILE_HIGH:
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 return; // get all the buffers first. 383 return; // get all the buffers first.
380 DCHECK_EQ(pictures_.size(), kNumPictureBuffers); 384 DCHECK_EQ(pictures_.size(), kNumPictureBuffers);
381 385
382 // These do their own RETURN_ON_FAILURE dances. 386 // These do their own RETURN_ON_FAILURE dances.
383 if (!AllocateOutputBuffers()) 387 if (!AllocateOutputBuffers())
384 return; 388 return;
385 if (!SendCommandToPort(OMX_CommandPortEnable, output_port_)) 389 if (!SendCommandToPort(OMX_CommandPortEnable, output_port_))
386 return; 390 return;
387 } 391 }
388 392
393 class OmxVideoDecodeAccelerator::PictureSyncObject {
394 public:
395 PictureSyncObject();
396 ~PictureSyncObject();
397
398 // Create a sync object and insert into the GPU command stream.
399 // Returns false on failure.
400 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
401 // Check the status of the sync object. Return true if synced or if an error
402 // occurred so as not to wait forever.
403 bool IsSynced();
404
405 private:
406 EGLSyncKHR egl_sync_obj_;
407 EGLDisplay egl_display_;
408 };
409
410 OmxVideoDecodeAccelerator::PictureSyncObject::PictureSyncObject()
411 : egl_sync_obj_(EGL_NO_SYNC_KHR),
412 egl_display_(EGL_NO_DISPLAY) {
413 }
414
415 OmxVideoDecodeAccelerator::PictureSyncObject::~PictureSyncObject() {
416 if (egl_sync_obj_ != EGL_NO_SYNC_KHR && egl_display_ != EGL_NO_SYNC_KHR)
417 egl_destroy_sync_khr(egl_display_, egl_sync_obj_);
418 }
419
420 bool OmxVideoDecodeAccelerator::PictureSyncObject::Create(
421 EGLDisplay egl_display) {
422
423 egl_display_ = egl_display;
424
425 // Create a sync object and insert it into the command stream.
426 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.
427 if (egl_sync_obj_ == EGL_NO_SYNC_KHR) {
428 DLOG(WARNING) << "Could not create EGL sync object, will not sync.";
429 return false;
430 }
431
432 return true;
433 }
434
435 bool OmxVideoDecodeAccelerator::PictureSyncObject::IsSynced() {
436 EGLint value;
437 EGLBoolean ret = egl_get_sync_attrib_khr(
438 egl_display_, egl_sync_obj_, EGL_SYNC_STATUS_KHR, &value);
439 if (ret == EGL_TRUE && value == EGL_UNSIGNALED_KHR)
440 return false;
441
442 // The object has been signalled or we got an error polling the state. If we
443 // got an error (ret == EGL_FALSE), we allow to continue as well. Worst case,
444 // we'll get some corruption, but the decoding can continue safely.
445 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.
446 return true;
447 }
448
389 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { 449 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
450 DCHECK_EQ(message_loop_, MessageLoop::current());
390 TRACE_EVENT1("Video Decoder", "OVDA::ReusePictureBuffer", 451 TRACE_EVENT1("Video Decoder", "OVDA::ReusePictureBuffer",
391 "Picture id", picture_buffer_id); 452 "Picture id", picture_buffer_id);
453 scoped_ptr<PictureSyncObject> egl_sync_obj(new PictureSyncObject);
454
455
456 if (!egl_sync_obj->Create(egl_display_)) {
457 // If creating the sync object failed, just requeue it, we might
458 // get artifacts, but decoding will continue.
459 QueuePictureBuffer(picture_buffer_id);
460 return;
461 }
462
463 // Inserted the object successfully, start checking it periodically.
464 CheckPictureStatus(picture_buffer_id, egl_sync_obj.Pass());
465 }
466
467 void OmxVideoDecodeAccelerator::CheckPictureStatus(
468 int32 picture_buffer_id,
469 scoped_ptr<PictureSyncObject> egl_sync_obj) {
470 DCHECK_EQ(message_loop_, MessageLoop::current());
471
472 // 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.
473 // destroyed. In that case we may never call QueuePictureBuffer().
474 // This is fine though, because all pictures, irrespective of their state,
475 // are in pictures_ map and that's what will be used to do the clean up.
476 // 5ms feels like a good compromise, allowing some decoding ahead
477 // (up to 3 frames/vsync) to compensate for more difficult frames.
478 if (!egl_sync_obj->IsSynced()) {
479 MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(
480 &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-
481 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.
482 base::TimeDelta::FromMilliseconds(5));
483 return;
484 }
485
486 // 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.
487 // reuse, in the latter case we might get some corruption, but decoding can
488 // continue safely.
489 QueuePictureBuffer(picture_buffer_id);
490 }
491
492 void OmxVideoDecodeAccelerator::QueuePictureBuffer(int32 picture_buffer_id) {
392 DCHECK_EQ(message_loop_, MessageLoop::current()); 493 DCHECK_EQ(message_loop_, MessageLoop::current());
393 494
394 // During port-flushing, do not call OMX FillThisBuffer. 495 // During port-flushing, do not call OMX FillThisBuffer.
395 if (current_state_change_ == RESETTING) { 496 if (current_state_change_ == RESETTING) {
396 queued_picture_buffer_ids_.push_back(picture_buffer_id); 497 queued_picture_buffer_ids_.push_back(picture_buffer_id);
397 return; 498 return;
398 } 499 }
399 500
400 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,); 501 // We might have started destroying while waiting for the picture. It's safe
502 // to drop it here, because we will free all the pictures regardless of their
503 // state using the pictures_ map.
504 if (!CanFillBuffer())
505 return;
401 506
402 OutputPictureById::iterator it = pictures_.find(picture_buffer_id); 507 OutputPictureById::iterator it = pictures_.find(picture_buffer_id);
403 RETURN_ON_FAILURE(it != pictures_.end(), 508 RETURN_ON_FAILURE(it != pictures_.end(),
404 "Missing picture buffer id: " << picture_buffer_id, 509 "Missing picture buffer id: " << picture_buffer_id,
405 INVALID_ARGUMENT,); 510 INVALID_ARGUMENT,);
406 OutputPicture& output_picture = it->second; 511 OutputPicture& output_picture = it->second;
407 512
408 ++output_buffers_at_component_; 513 ++output_buffers_at_component_;
409 OMX_ERRORTYPE result = 514 OMX_ERRORTYPE result =
410 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); 515 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")); 1189 omx_init = reinterpret_cast<OMXInit>(dlsym(omx_handle, "OMX_Init"));
1085 omx_gethandle = 1190 omx_gethandle =
1086 reinterpret_cast<OMXGetHandle>(dlsym(omx_handle, "OMX_GetHandle")); 1191 reinterpret_cast<OMXGetHandle>(dlsym(omx_handle, "OMX_GetHandle"));
1087 omx_get_components_of_role = 1192 omx_get_components_of_role =
1088 reinterpret_cast<OMXGetComponentsOfRole>( 1193 reinterpret_cast<OMXGetComponentsOfRole>(
1089 dlsym(omx_handle, "OMX_GetComponentsOfRole")); 1194 dlsym(omx_handle, "OMX_GetComponentsOfRole"));
1090 omx_free_handle = 1195 omx_free_handle =
1091 reinterpret_cast<OMXFreeHandle>(dlsym(omx_handle, "OMX_FreeHandle")); 1196 reinterpret_cast<OMXFreeHandle>(dlsym(omx_handle, "OMX_FreeHandle"));
1092 omx_deinit = 1197 omx_deinit =
1093 reinterpret_cast<OMXDeinit>(dlsym(omx_handle, "OMX_Deinit")); 1198 reinterpret_cast<OMXDeinit>(dlsym(omx_handle, "OMX_Deinit"));
1199
1200 egl_create_sync_khr = reinterpret_cast<PFNEGLCREATESYNCKHRPROC>(
1201 eglGetProcAddress("eglCreateSyncKHR"));
1202 egl_get_sync_attrib_khr = reinterpret_cast<PFNEGLGETSYNCATTRIBKHRPROC>(
1203 eglGetProcAddress("eglGetSyncAttribKHR"));
1204 egl_destroy_sync_khr = reinterpret_cast<PFNEGLDESTROYSYNCKHRPROC>(
1205 eglGetProcAddress("eglDestroySyncKHR"));
1206
1094 return (omx_init && omx_gethandle && omx_get_components_of_role && 1207 return (omx_init && omx_gethandle && omx_get_components_of_role &&
1095 omx_free_handle && omx_deinit); 1208 omx_free_handle && omx_deinit && egl_create_sync_khr &&
1209 egl_get_sync_attrib_khr && egl_destroy_sync_khr);
1096 } 1210 }
1097 1211
1098 // static 1212 // static
1099 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, 1213 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component,
1100 OMX_PTR priv_data, 1214 OMX_PTR priv_data,
1101 OMX_EVENTTYPE event, 1215 OMX_EVENTTYPE event,
1102 OMX_U32 data1, 1216 OMX_U32 data1,
1103 OMX_U32 data2, 1217 OMX_U32 data2,
1104 OMX_PTR event_data) { 1218 OMX_PTR event_data) {
1105 // Called on the OMX thread. 1219 // Called on the OMX thread.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 1274
1161 bool OmxVideoDecodeAccelerator::SendCommandToPort( 1275 bool OmxVideoDecodeAccelerator::SendCommandToPort(
1162 OMX_COMMANDTYPE cmd, int port_index) { 1276 OMX_COMMANDTYPE cmd, int port_index) {
1163 DCHECK_EQ(message_loop_, MessageLoop::current()); 1277 DCHECK_EQ(message_loop_, MessageLoop::current());
1164 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, 1278 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_,
1165 cmd, port_index, 0); 1279 cmd, port_index, 0);
1166 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, 1280 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd,
1167 PLATFORM_FAILURE, false); 1281 PLATFORM_FAILURE, false);
1168 return true; 1282 return true;
1169 } 1283 }
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