OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |