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

Side by Side Diff: content/common/gpu/media/omx_video_decode_accelerator.cc

Issue 9724030: Description: Video decode in hardware on ARM platform. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 8 years, 9 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
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 = 4 }; 22 enum { kNumPictureBuffers = 4 };
23 23
24 // Open the libnvomx here for now. 24 // Open the libOmxCore here for now.
25 void* omx_handle = dlopen("libnvomx.so", RTLD_NOW); 25 void* omx_handle = dlopen("libOmxCore.so", RTLD_NOW);
26 26
27 typedef OMX_ERRORTYPE (*OMXInit)(); 27 typedef OMX_ERRORTYPE (*OMXInit)();
28 typedef OMX_ERRORTYPE (*OMXGetHandle)( 28 typedef OMX_ERRORTYPE (*OMXGetHandle)(
29 OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*); 29 OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*);
30 typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**); 30 typedef OMX_ERRORTYPE (*OMXGetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**);
31 typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE); 31 typedef OMX_ERRORTYPE (*OMXFreeHandle)(OMX_HANDLETYPE);
32 typedef OMX_ERRORTYPE (*OMXDeinit)(); 32 typedef OMX_ERRORTYPE (*OMXDeinit)();
33 33
34 OMXInit omx_init = reinterpret_cast<OMXInit>(dlsym(omx_handle, "OMX_Init")); 34 OMXInit omx_init = reinterpret_cast<OMXInit>(dlsym(omx_handle, "OMX_Init"));
35 OMXGetHandle omx_gethandle = 35 OMXGetHandle omx_gethandle =
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 153
154 if (!CreateComponent()) // Does its own RETURN_ON_FAILURE dances. 154 if (!CreateComponent()) // Does its own RETURN_ON_FAILURE dances.
155 return false; 155 return false;
156 156
157 DCHECK_EQ(current_state_change_, NO_TRANSITION); 157 DCHECK_EQ(current_state_change_, NO_TRANSITION);
158 current_state_change_ = INITIALIZING; 158 current_state_change_ = INITIALIZING;
159 BeginTransitionToState(OMX_StateIdle); 159 BeginTransitionToState(OMX_StateIdle);
160 160
161 if (!AllocateInputBuffers()) // Does its own RETURN_ON_FAILURE dances. 161 if (!AllocateInputBuffers()) // Does its own RETURN_ON_FAILURE dances.
162 return false; 162 return false;
163 if (!AllocateFakeOutputBuffers()) // Does its own RETURN_ON_FAILURE dances.
164 return false;
163 165
164 return true; 166 return true;
165 } 167 }
166 168
167 bool OmxVideoDecodeAccelerator::CreateComponent() { 169 bool OmxVideoDecodeAccelerator::CreateComponent() {
168 DCHECK_EQ(message_loop_, MessageLoop::current()); 170 DCHECK_EQ(message_loop_, MessageLoop::current());
169 OMX_CALLBACKTYPE omx_accelerator_callbacks = { 171 OMX_CALLBACKTYPE omx_accelerator_callbacks = {
170 &OmxVideoDecodeAccelerator::EventHandler, 172 &OmxVideoDecodeAccelerator::EventHandler,
171 &OmxVideoDecodeAccelerator::EmptyBufferCallback, 173 &OmxVideoDecodeAccelerator::EmptyBufferCallback,
172 &OmxVideoDecodeAccelerator::FillBufferCallback 174 &OmxVideoDecodeAccelerator::FillBufferCallback
(...skipping 19 matching lines...) Expand all
192 this, &omx_accelerator_callbacks); 194 this, &omx_accelerator_callbacks);
193 RETURN_ON_OMX_FAILURE(result, 195 RETURN_ON_OMX_FAILURE(result,
194 "Failed to OMX_GetHandle on: " << component.get(), 196 "Failed to OMX_GetHandle on: " << component.get(),
195 PLATFORM_FAILURE, false); 197 PLATFORM_FAILURE, false);
196 client_state_ = OMX_StateLoaded; 198 client_state_ = OMX_StateLoaded;
197 199
198 component_name_is_nvidia_h264ext_ = !strcmp( 200 component_name_is_nvidia_h264ext_ = !strcmp(
199 reinterpret_cast<char *>(component.get()), 201 reinterpret_cast<char *>(component.get()),
200 "OMX.Nvidia.h264ext.decode"); 202 "OMX.Nvidia.h264ext.decode");
201 203
204 bool component_name_is_sec_h264ext = !strcmp(
205 reinterpret_cast<char *>(component.get()),
206 "OMX.SEC.AVC.Decoder");
207 Gles2TextureToEglImageTranslator* texture_to_egl_image_translator =
208 new Gles2TextureToEglImageTranslator(component_name_is_sec_h264ext);
209 texture_to_egl_image_translator_.reset(texture_to_egl_image_translator);
210
202 // Get the port information. This will obtain information about the number of 211 // Get the port information. This will obtain information about the number of
203 // ports and index of the first port. 212 // ports and index of the first port.
204 OMX_PORT_PARAM_TYPE port_param; 213 OMX_PORT_PARAM_TYPE port_param;
205 InitParam(*this, &port_param); 214 InitParam(*this, &port_param);
206 result = OMX_GetParameter(component_handle_, OMX_IndexParamVideoInit, 215 result = OMX_GetParameter(component_handle_, OMX_IndexParamVideoInit,
207 &port_param); 216 &port_param);
208 RETURN_ON_FAILURE(result == OMX_ErrorNone && port_param.nPorts == 2, 217 RETURN_ON_FAILURE(result == OMX_ErrorNone && port_param.nPorts == 2,
209 "Failed to get Port Param: " << result << ", " 218 "Failed to get Port Param: " << result << ", "
210 << port_param.nPorts, 219 << port_param.nPorts,
211 PLATFORM_FAILURE, false); 220 PLATFORM_FAILURE, false);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 // stream's real dimensions (which can only happen once some Decode() work has 269 // stream's real dimensions (which can only happen once some Decode() work has
261 // been done). 270 // been done).
262 port_format.format.video.nFrameWidth = -1; 271 port_format.format.video.nFrameWidth = -1;
263 port_format.format.video.nFrameHeight = -1; 272 port_format.format.video.nFrameHeight = -1;
264 result = OMX_SetParameter(component_handle_, 273 result = OMX_SetParameter(component_handle_,
265 OMX_IndexParamPortDefinition, 274 OMX_IndexParamPortDefinition,
266 &port_format); 275 &port_format);
267 RETURN_ON_OMX_FAILURE(result, 276 RETURN_ON_OMX_FAILURE(result,
268 "SetParameter(OMX_IndexParamPortDefinition) failed", 277 "SetParameter(OMX_IndexParamPortDefinition) failed",
269 PLATFORM_FAILURE, false); 278 PLATFORM_FAILURE, false);
270
271 // Fill the component with fake output buffers. This seems to be required for
272 // the component to move from Loaded to Idle. How bogus.
273 for (int i = 0; i < kNumPictureBuffers; ++i) {
274 OMX_BUFFERHEADERTYPE* buffer;
275 result = OMX_UseBuffer(component_handle_, &buffer, output_port_,
276 NULL, 0, reinterpret_cast<OMX_U8*>(0x1));
277 RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer failed",
278 PLATFORM_FAILURE, false);
279 buffer->pAppPrivate = NULL;
280 buffer->nTimeStamp = -1;
281 buffer->nOutputPortIndex = output_port_;
282 CHECK(fake_output_buffers_.insert(buffer).second);
283 }
284 return true; 279 return true;
285 } 280 }
286 281
287 void OmxVideoDecodeAccelerator::Decode( 282 void OmxVideoDecodeAccelerator::Decode(
288 const media::BitstreamBuffer& bitstream_buffer) { 283 const media::BitstreamBuffer& bitstream_buffer) {
289 TRACE_EVENT1("Video Decoder", "OVDA::Decode", 284 TRACE_EVENT1("Video Decoder", "OVDA::Decode",
290 "Buffer id", bitstream_buffer.id()); 285 "Buffer id", bitstream_buffer.id());
291 DCHECK_EQ(message_loop_, MessageLoop::current()); 286 DCHECK_EQ(message_loop_, MessageLoop::current());
292 287
293 if (current_state_change_ == RESETTING || 288 if (current_state_change_ == RESETTING ||
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 332
338 void OmxVideoDecodeAccelerator::AssignPictureBuffers( 333 void OmxVideoDecodeAccelerator::AssignPictureBuffers(
339 const std::vector<media::PictureBuffer>& buffers) { 334 const std::vector<media::PictureBuffer>& buffers) {
340 DCHECK_EQ(message_loop_, MessageLoop::current()); 335 DCHECK_EQ(message_loop_, MessageLoop::current());
341 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,); 336 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,);
342 337
343 DCHECK_EQ(output_buffers_at_component_, 0); 338 DCHECK_EQ(output_buffers_at_component_, 0);
344 DCHECK_EQ(fake_output_buffers_.size(), 0U); 339 DCHECK_EQ(fake_output_buffers_.size(), 0U);
345 DCHECK_EQ(pictures_.size(), 0U); 340 DCHECK_EQ(pictures_.size(), 0U);
346 341
347 static Gles2TextureToEglImageTranslator texture2eglImage_translator;
348 for (size_t i = 0; i < buffers.size(); ++i) { 342 for (size_t i = 0; i < buffers.size(); ++i) {
349 EGLImageKHR egl_image = texture2eglImage_translator.TranslateToEglImage( 343 EGLImageKHR egl_image =
350 egl_display_, egl_context_, buffers[i].texture_id()); 344 texture_to_egl_image_translator_->TranslateToEglImage(
345 egl_display_, egl_context_,
346 buffers[i].texture_id(),
347 last_requested_picture_buffer_dimensions_);
351 CHECK(pictures_.insert(std::make_pair( 348 CHECK(pictures_.insert(std::make_pair(
352 buffers[i].id(), OutputPicture(buffers[i], NULL, egl_image))).second); 349 buffers[i].id(), OutputPicture(buffers[i], NULL, egl_image))).second);
353 } 350 }
354 351
355 if (pictures_.size() < kNumPictureBuffers) 352 if (pictures_.size() < kNumPictureBuffers)
356 return; // get all the buffers first. 353 return; // get all the buffers first.
357 DCHECK_EQ(pictures_.size(), kNumPictureBuffers); 354 DCHECK_EQ(pictures_.size(), kNumPictureBuffers);
358 355
359 // These do their own RETURN_ON_FAILURE dances. 356 // These do their own RETURN_ON_FAILURE dances.
360 if (!AllocateOutputBuffers()) 357 if (!AllocateOutputBuffers())
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer() Input buffer error", 647 RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer() Input buffer error",
651 PLATFORM_FAILURE, false); 648 PLATFORM_FAILURE, false);
652 buffer->nInputPortIndex = input_port_; 649 buffer->nInputPortIndex = input_port_;
653 buffer->nOffset = 0; 650 buffer->nOffset = 0;
654 buffer->nFlags = 0; 651 buffer->nFlags = 0;
655 free_input_buffers_.push(buffer); 652 free_input_buffers_.push(buffer);
656 } 653 }
657 return true; 654 return true;
658 } 655 }
659 656
657 bool OmxVideoDecodeAccelerator::AllocateFakeOutputBuffers() {
658 // Fill the component with fake output buffers.
659 for (unsigned int i = 0; i < kNumPictureBuffers; ++i) {
660 OMX_BUFFERHEADERTYPE* buffer;
661 OMX_ERRORTYPE result;
662 result = OMX_AllocateBuffer(component_handle_, &buffer, output_port_,
663 NULL, 0);
664 RETURN_ON_OMX_FAILURE(result, "OMX_AllocateBuffer failed",
665 PLATFORM_FAILURE, false);
666 buffer->pAppPrivate = NULL;
667 buffer->nTimeStamp = -1;
668 buffer->nOutputPortIndex = output_port_;
669 CHECK(fake_output_buffers_.insert(buffer).second);
670 }
671 return true;
672 }
673
660 bool OmxVideoDecodeAccelerator::AllocateOutputBuffers() { 674 bool OmxVideoDecodeAccelerator::AllocateOutputBuffers() {
661 DCHECK_EQ(message_loop_, MessageLoop::current()); 675 DCHECK_EQ(message_loop_, MessageLoop::current());
662 676
663 DCHECK(!pictures_.empty()); 677 DCHECK(!pictures_.empty());
664 for (OutputPictureById::iterator it = pictures_.begin(); 678 for (OutputPictureById::iterator it = pictures_.begin();
665 it != pictures_.end(); ++it) { 679 it != pictures_.end(); ++it) {
666 media::PictureBuffer& picture_buffer = it->second.picture_buffer; 680 media::PictureBuffer& picture_buffer = it->second.picture_buffer;
667 OMX_BUFFERHEADERTYPE** omx_buffer = &it->second.omx_buffer_header; 681 OMX_BUFFERHEADERTYPE** omx_buffer = &it->second.omx_buffer_header;
668 DCHECK(!*omx_buffer); 682 DCHECK(!*omx_buffer);
669 OMX_ERRORTYPE result = OMX_UseEGLImage( 683 OMX_ERRORTYPE result = OMX_UseEGLImage(
(...skipping 19 matching lines...) Expand all
689 free_input_buffers_.pop(); 703 free_input_buffers_.pop();
690 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer); 704 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer);
691 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", PLATFORM_FAILURE,); 705 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", PLATFORM_FAILURE,);
692 } 706 }
693 } 707 }
694 708
695 void OmxVideoDecodeAccelerator::FreeOutputBuffers() { 709 void OmxVideoDecodeAccelerator::FreeOutputBuffers() {
696 DCHECK_EQ(message_loop_, MessageLoop::current()); 710 DCHECK_EQ(message_loop_, MessageLoop::current());
697 // Calls to OMX to free buffers. 711 // Calls to OMX to free buffers.
698 OMX_ERRORTYPE result; 712 OMX_ERRORTYPE result;
699 static Gles2TextureToEglImageTranslator texture2eglImage_translator;
700 for (OutputPictureById::iterator it = pictures_.begin(); 713 for (OutputPictureById::iterator it = pictures_.begin();
701 it != pictures_.end(); ++it) { 714 it != pictures_.end(); ++it) {
702 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; 715 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header;
703 DCHECK(omx_buffer); 716 DCHECK(omx_buffer);
704 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); 717 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate);
705 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); 718 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer);
706 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", PLATFORM_FAILURE,); 719 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer", PLATFORM_FAILURE,);
707 texture2eglImage_translator.DestroyEglImage(egl_display_, 720 texture_to_egl_image_translator_->DestroyEglImage(egl_display_,
708 it->second.egl_image); 721 it->second.egl_image);
709 if (client_) 722 if (client_)
710 client_->DismissPictureBuffer(it->first); 723 client_->DismissPictureBuffer(it->first);
711 } 724 }
712 pictures_.clear(); 725 pictures_.clear();
713 } 726 }
714 727
715 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { 728 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() {
716 DCHECK_EQ(message_loop_, MessageLoop::current()); 729 DCHECK_EQ(message_loop_, MessageLoop::current());
717 OMX_PARAM_PORTDEFINITIONTYPE port_format; 730 OMX_PARAM_PORTDEFINITIONTYPE port_format;
718 InitParam(*this, &port_format); 731 InitParam(*this, &port_format);
719 port_format.nPortIndex = output_port_; 732 port_format.nPortIndex = output_port_;
720 OMX_ERRORTYPE result = OMX_GetParameter( 733 OMX_ERRORTYPE result = OMX_GetParameter(
721 component_handle_, OMX_IndexParamPortDefinition, &port_format); 734 component_handle_, OMX_IndexParamPortDefinition, &port_format);
722 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter", PLATFORM_FAILURE,); 735 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter", PLATFORM_FAILURE,);
723 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers); 736 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers);
724 737
725 // TODO(fischman): to support mid-stream resize, need to free/dismiss any 738 // 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 739 // |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). 740 // this (there's already freeing logic there, which should not be duplicated).
728 741
729 // Request picture buffers to be handed to the component. 742 // Request picture buffers to be handed to the component.
730 // ProvidePictureBuffers() will trigger AssignPictureBuffers, which ultimately 743 // ProvidePictureBuffers() will trigger AssignPictureBuffers, which ultimately
731 // assigns the textures to the component and re-enables the port. 744 // assigns the textures to the component and re-enables the port.
732 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; 745 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video;
746 last_requested_picture_buffer_dimensions_.SetSize(vformat.nFrameWidth,
747 vformat.nFrameHeight);
733 if (client_) { 748 if (client_) {
734 client_->ProvidePictureBuffers( 749 client_->ProvidePictureBuffers(
735 kNumPictureBuffers, 750 kNumPictureBuffers,
736 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight)); 751 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight));
737 } 752 }
738 } 753 }
739 754
740 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { 755 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() {
741 DCHECK_EQ(message_loop_, MessageLoop::current()); 756 DCHECK_EQ(message_loop_, MessageLoop::current());
742 757
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 1048
1034 bool OmxVideoDecodeAccelerator::SendCommandToPort( 1049 bool OmxVideoDecodeAccelerator::SendCommandToPort(
1035 OMX_COMMANDTYPE cmd, int port_index) { 1050 OMX_COMMANDTYPE cmd, int port_index) {
1036 DCHECK_EQ(message_loop_, MessageLoop::current()); 1051 DCHECK_EQ(message_loop_, MessageLoop::current());
1037 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, 1052 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_,
1038 cmd, port_index, 0); 1053 cmd, port_index, 0);
1039 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, 1054 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd,
1040 PLATFORM_FAILURE, false); 1055 PLATFORM_FAILURE, false);
1041 return true; 1056 return true;
1042 } 1057 }
OLDNEW
« no previous file with comments | « content/common/gpu/media/omx_video_decode_accelerator.h ('k') | content/common/gpu/media/video_decode_accelerator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698