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" |
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 = 4 }; | 22 enum { kNumPictureBuffers = 4 }; |
23 | 23 |
24 int width_ = 0; | |
25 int height_ = 0; | |
Ami GONE FROM CHROMIUM
2012/02/07 17:05:40
No. These are mutable static globals, and are a b
| |
24 // Open the libnvomx here for now. | 26 // Open the libnvomx here for now. |
25 void* omx_handle = dlopen("libnvomx.so", RTLD_NOW); | 27 void* omx_handle = dlopen("libnvomx.so", RTLD_NOW); |
26 | 28 |
27 typedef OMX_ERRORTYPE (*OMXInit)(); | 29 typedef OMX_ERRORTYPE (*OMXInit)(); |
28 typedef OMX_ERRORTYPE (*OMXGetHandle)( | 30 typedef OMX_ERRORTYPE (*OMXGetHandle)( |
29 OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*); | 31 OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*); |
30 typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**); | 32 typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**); |
31 typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE); | 33 typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE); |
32 typedef OMX_ERRORTYPE (*OMXDeinit)(); | 34 typedef OMX_ERRORTYPE (*OMXDeinit)(); |
33 | 35 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
104 client_state_(OMX_StateMax), | 106 client_state_(OMX_StateMax), |
105 current_state_change_(NO_TRANSITION), | 107 current_state_change_(NO_TRANSITION), |
106 input_buffer_count_(0), | 108 input_buffer_count_(0), |
107 input_buffer_size_(0), | 109 input_buffer_size_(0), |
108 input_port_(0), | 110 input_port_(0), |
109 input_buffers_at_component_(0), | 111 input_buffers_at_component_(0), |
110 output_port_(0), | 112 output_port_(0), |
111 output_buffers_at_component_(0), | 113 output_buffers_at_component_(0), |
112 client_(client), | 114 client_(client), |
113 profile_(OMX_VIDEO_AVCProfileMax), | 115 profile_(OMX_VIDEO_AVCProfileMax), |
114 component_name_is_nvidia_h264ext_(false) { | 116 component_name_is_nvidia_h264ext_(false), |
117 component_name_is_sec_h264ext_(false) { | |
115 RETURN_ON_FAILURE(AreOMXFunctionPointersInitialized(), | 118 RETURN_ON_FAILURE(AreOMXFunctionPointersInitialized(), |
116 "Failed to load openmax library", PLATFORM_FAILURE,); | 119 "Failed to load openmax library", PLATFORM_FAILURE,); |
117 RETURN_ON_OMX_FAILURE(omx_init(), "Failed to init OpenMAX core", | 120 RETURN_ON_OMX_FAILURE(omx_init(), "Failed to init OpenMAX core", |
118 PLATFORM_FAILURE,); | 121 PLATFORM_FAILURE,); |
119 } | 122 } |
120 | 123 |
121 OmxVideoDecodeAccelerator::~OmxVideoDecodeAccelerator() { | 124 OmxVideoDecodeAccelerator::~OmxVideoDecodeAccelerator() { |
122 DCHECK_EQ(message_loop_, MessageLoop::current()); | 125 DCHECK_EQ(message_loop_, MessageLoop::current()); |
123 DCHECK(free_input_buffers_.empty()); | 126 DCHECK(free_input_buffers_.empty()); |
124 DCHECK_EQ(0, input_buffers_at_component_); | 127 DCHECK_EQ(0, input_buffers_at_component_); |
125 DCHECK_EQ(0, output_buffers_at_component_); | 128 DCHECK_EQ(0, output_buffers_at_component_); |
126 DCHECK(pictures_.empty()); | 129 DCHECK(pictures_.empty()); |
127 } | 130 } |
128 | 131 |
129 void OmxVideoDecodeAccelerator::SetEglState( | 132 void OmxVideoDecodeAccelerator::SetEglState( |
130 EGLDisplay egl_display, EGLContext egl_context) { | 133 Display* x_display, EGLDisplay egl_display, |
134 EGLContext egl_context, EGLSurface egl_surface) { | |
131 DCHECK_EQ(message_loop_, MessageLoop::current()); | 135 DCHECK_EQ(message_loop_, MessageLoop::current()); |
136 x_display_ = x_display; | |
132 egl_display_ = egl_display; | 137 egl_display_ = egl_display; |
133 egl_context_ = egl_context; | 138 egl_context_ = egl_context; |
139 egl_surface_ = egl_surface; | |
134 } | 140 } |
135 | 141 |
136 // This is to initialize the OMX data structures to default values. | 142 // This is to initialize the OMX data structures to default values. |
137 template <typename T> | 143 template <typename T> |
138 static void InitParam(const OmxVideoDecodeAccelerator& dec, T* param) { | 144 static void InitParam(const OmxVideoDecodeAccelerator& dec, T* param) { |
139 memset(param, 0, sizeof(T)); | 145 memset(param, 0, sizeof(T)); |
140 param->nVersion.nVersion = 0x00000101; | 146 param->nVersion.nVersion = 0x00000101; |
141 param->nSize = sizeof(T); | 147 param->nSize = sizeof(T); |
142 } | 148 } |
143 | 149 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
192 this, &omx_accelerator_callbacks); | 198 this, &omx_accelerator_callbacks); |
193 RETURN_ON_OMX_FAILURE(result, | 199 RETURN_ON_OMX_FAILURE(result, |
194 "Failed to OMX_GetHandle on: " << component.get(), | 200 "Failed to OMX_GetHandle on: " << component.get(), |
195 PLATFORM_FAILURE, false); | 201 PLATFORM_FAILURE, false); |
196 client_state_ = OMX_StateLoaded; | 202 client_state_ = OMX_StateLoaded; |
197 | 203 |
198 component_name_is_nvidia_h264ext_ = !strcmp( | 204 component_name_is_nvidia_h264ext_ = !strcmp( |
199 reinterpret_cast<char *>(component.get()), | 205 reinterpret_cast<char *>(component.get()), |
200 "OMX.Nvidia.h264ext.decode"); | 206 "OMX.Nvidia.h264ext.decode"); |
201 | 207 |
208 component_name_is_sec_h264ext_ = !strcmp( | |
209 reinterpret_cast<char *>(component.get()), | |
210 "OMX.SEC.AVC.Decoder"); | |
Ami GONE FROM CHROMIUM
2012/02/07 17:05:40
What is "SEC"? can you add a comment identifying
| |
211 | |
202 // Get the port information. This will obtain information about the number of | 212 // Get the port information. This will obtain information about the number of |
203 // ports and index of the first port. | 213 // ports and index of the first port. |
204 OMX_PORT_PARAM_TYPE port_param; | 214 OMX_PORT_PARAM_TYPE port_param; |
205 InitParam(*this, &port_param); | 215 InitParam(*this, &port_param); |
206 result = OMX_GetParameter(component_handle_, OMX_IndexParamVideoInit, | 216 result = OMX_GetParameter(component_handle_, OMX_IndexParamVideoInit, |
207 &port_param); | 217 &port_param); |
208 RETURN_ON_FAILURE(result == OMX_ErrorNone && port_param.nPorts == 2, | 218 RETURN_ON_FAILURE(result == OMX_ErrorNone && port_param.nPorts == 2, |
209 "Failed to get Port Param: " << result << ", " | 219 "Failed to get Port Param: " << result << ", " |
210 << port_param.nPorts, | 220 << port_param.nPorts, |
211 PLATFORM_FAILURE, false); | 221 PLATFORM_FAILURE, false); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 const std::vector<media::PictureBuffer>& buffers) { | 349 const std::vector<media::PictureBuffer>& buffers) { |
340 DCHECK_EQ(message_loop_, MessageLoop::current()); | 350 DCHECK_EQ(message_loop_, MessageLoop::current()); |
341 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,); | 351 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,); |
342 | 352 |
343 DCHECK_EQ(output_buffers_at_component_, 0); | 353 DCHECK_EQ(output_buffers_at_component_, 0); |
344 DCHECK_EQ(fake_output_buffers_.size(), 0U); | 354 DCHECK_EQ(fake_output_buffers_.size(), 0U); |
345 DCHECK_EQ(pictures_.size(), 0U); | 355 DCHECK_EQ(pictures_.size(), 0U); |
346 | 356 |
347 static Gles2TextureToEglImageTranslator texture2eglImage_translator; | 357 static Gles2TextureToEglImageTranslator texture2eglImage_translator; |
348 for (size_t i = 0; i < buffers.size(); ++i) { | 358 for (size_t i = 0; i < buffers.size(); ++i) { |
349 EGLImageKHR egl_image = texture2eglImage_translator.TranslateToEglImage( | 359 EGLImageKHR egl_image; |
350 egl_display_, egl_context_, buffers[i].texture_id()); | 360 if(component_name_is_sec_h264ext_) { |
361 egl_image = texture2eglImage_translator.CreateEglImage( | |
362 x_display_, egl_display_, egl_context_, egl_surface_, | |
363 buffers[i].texture_id(), width_, height_); | |
364 } | |
365 else { | |
366 egl_image = texture2eglImage_translator.TranslateToEglImage( | |
367 egl_display_, egl_context_, buffers[i].texture_id()); | |
368 } | |
351 CHECK(pictures_.insert(std::make_pair( | 369 CHECK(pictures_.insert(std::make_pair( |
352 buffers[i].id(), OutputPicture(buffers[i], NULL, egl_image))).second); | 370 buffers[i].id(), OutputPicture(buffers[i], NULL, egl_image))).second); |
353 } | 371 } |
354 | 372 |
355 if (pictures_.size() < kNumPictureBuffers) | 373 if (pictures_.size() < kNumPictureBuffers) |
356 return; // get all the buffers first. | 374 return; // get all the buffers first. |
357 DCHECK_EQ(pictures_.size(), kNumPictureBuffers); | 375 DCHECK_EQ(pictures_.size(), kNumPictureBuffers); |
358 | 376 |
359 // These do their own RETURN_ON_FAILURE dances. | 377 // These do their own RETURN_ON_FAILURE dances. |
360 if (!AllocateOutputBuffers()) | 378 if (!AllocateOutputBuffers()) |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
697 // Calls to OMX to free buffers. | 715 // Calls to OMX to free buffers. |
698 OMX_ERRORTYPE result; | 716 OMX_ERRORTYPE result; |
699 static Gles2TextureToEglImageTranslator texture2eglImage_translator; | 717 static Gles2TextureToEglImageTranslator texture2eglImage_translator; |
700 for (OutputPictureById::iterator it = pictures_.begin(); | 718 for (OutputPictureById::iterator it = pictures_.begin(); |
701 it != pictures_.end(); ++it) { | 719 it != pictures_.end(); ++it) { |
702 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; | 720 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; |
703 DCHECK(omx_buffer); | 721 DCHECK(omx_buffer); |
704 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); | 722 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); |
705 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); | 723 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); |
706 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", PLATFORM_FAILURE,); | 724 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", PLATFORM_FAILURE,); |
707 texture2eglImage_translator.DestroyEglImage(egl_display_, | 725 texture2eglImage_translator.DestroyEglImage(x_display_, egl_display_, |
708 it->second.egl_image); | 726 it->second.egl_image); |
709 if (client_) | 727 if (client_) |
710 client_->DismissPictureBuffer(it->first); | 728 client_->DismissPictureBuffer(it->first); |
711 } | 729 } |
712 pictures_.clear(); | 730 pictures_.clear(); |
713 } | 731 } |
714 | 732 |
715 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { | 733 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { |
716 DCHECK_EQ(message_loop_, MessageLoop::current()); | 734 DCHECK_EQ(message_loop_, MessageLoop::current()); |
717 OMX_PARAM_PORTDEFINITIONTYPE port_format; | 735 OMX_PARAM_PORTDEFINITIONTYPE port_format; |
718 InitParam(*this, &port_format); | 736 InitParam(*this, &port_format); |
719 port_format.nPortIndex = output_port_; | 737 port_format.nPortIndex = output_port_; |
720 OMX_ERRORTYPE result = OMX_GetParameter( | 738 OMX_ERRORTYPE result = OMX_GetParameter( |
721 component_handle_, OMX_IndexParamPortDefinition, &port_format); | 739 component_handle_, OMX_IndexParamPortDefinition, &port_format); |
722 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter", PLATFORM_FAILURE,); | 740 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter", PLATFORM_FAILURE,); |
723 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers); | 741 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers); |
724 | 742 |
725 // TODO(fischman): to support mid-stream resize, need to free/dismiss any | 743 // TODO(fischman): to support mid-stream resize, need to free/dismiss any |
726 // |pictures_| we already have. Make sure that the shutdown-path agrees with | 744 // |pictures_| we already have. Make sure that the shutdown-path agrees with |
727 // this (there's already freeing logic there, which should not be duplicated). | 745 // this (there's already freeing logic there, which should not be duplicated). |
728 | 746 |
729 // Request picture buffers to be handed to the component. | 747 // Request picture buffers to be handed to the component. |
730 // ProvidePictureBuffers() will trigger AssignPictureBuffers, which ultimately | 748 // ProvidePictureBuffers() will trigger AssignPictureBuffers, which ultimately |
731 // assigns the textures to the component and re-enables the port. | 749 // assigns the textures to the component and re-enables the port. |
732 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; | 750 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; |
751 width_ = vformat.nFrameWidth; | |
752 height_ = vformat.nFrameHeight; | |
753 | |
733 if (client_) { | 754 if (client_) { |
734 client_->ProvidePictureBuffers( | 755 client_->ProvidePictureBuffers( |
735 kNumPictureBuffers, | 756 kNumPictureBuffers, |
736 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight)); | 757 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight)); |
737 } | 758 } |
738 } | 759 } |
739 | 760 |
740 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { | 761 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { |
741 DCHECK_EQ(message_loop_, MessageLoop::current()); | 762 DCHECK_EQ(message_loop_, MessageLoop::current()); |
742 | 763 |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1033 | 1054 |
1034 bool OmxVideoDecodeAccelerator::SendCommandToPort( | 1055 bool OmxVideoDecodeAccelerator::SendCommandToPort( |
1035 OMX_COMMANDTYPE cmd, int port_index) { | 1056 OMX_COMMANDTYPE cmd, int port_index) { |
1036 DCHECK_EQ(message_loop_, MessageLoop::current()); | 1057 DCHECK_EQ(message_loop_, MessageLoop::current()); |
1037 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, | 1058 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, |
1038 cmd, port_index, 0); | 1059 cmd, port_index, 0); |
1039 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, | 1060 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, |
1040 PLATFORM_FAILURE, false); | 1061 PLATFORM_FAILURE, false); |
1041 return true; | 1062 return true; |
1042 } | 1063 } |
OLD | NEW |