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

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

Issue 7088021: OmxVideoDecodeAcceleratorTest is born! (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: brettw CR response. Created 9 years, 6 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/omx_video_decode_accelerator.h" 5 #include "content/common/gpu/omx_video_decode_accelerator.h"
6 6
7 #include "base/stl_util-inl.h" 7 #include "base/stl_util-inl.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "content/common/gpu/gles2_texture_to_egl_image_translator.h" 9 #include "content/common/gpu/gles2_texture_to_egl_image_translator.h"
10 #include "content/common/gpu/gpu_channel.h" 10 #include "content/common/gpu/gpu_channel.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 height_(-1), 48 height_(-1),
49 input_buffer_count_(0), 49 input_buffer_count_(0),
50 input_buffer_size_(0), 50 input_buffer_size_(0),
51 input_port_(0), 51 input_port_(0),
52 input_buffers_at_component_(0), 52 input_buffers_at_component_(0),
53 output_buffer_count_(0), 53 output_buffer_count_(0),
54 output_buffer_size_(0), 54 output_buffer_size_(0),
55 output_port_(0), 55 output_port_(0),
56 output_buffers_at_component_(0), 56 output_buffers_at_component_(0),
57 uses_egl_image_(false), 57 uses_egl_image_(false),
58 client_(client) { 58 client_(client),
59 on_port_disable_event_func_(NULL),
60 on_port_enable_event_func_(NULL),
61 on_state_event_func_(NULL),
62 on_flush_event_func_(NULL),
63 on_buffer_flag_event_func_(NULL) {
59 if (!AreOMXFunctionPointersInitialized()) { 64 if (!AreOMXFunctionPointersInitialized()) {
60 LOG(ERROR) << "Failed to load openmax library"; 65 LOG(ERROR) << "Failed to load openmax library";
61 return; 66 return;
62 } 67 }
63 OMX_ERRORTYPE result = omx_init(); 68 OMX_ERRORTYPE result = omx_init();
64 if (result != OMX_ErrorNone) 69 if (result != OMX_ErrorNone)
65 LOG(ERROR) << "Failed to init OpenMAX core"; 70 LOG(ERROR) << "Failed to init OpenMAX core";
66 } 71 }
67 72
68 OmxVideoDecodeAccelerator::~OmxVideoDecodeAccelerator() { 73 OmxVideoDecodeAccelerator::~OmxVideoDecodeAccelerator() {
69 DCHECK(free_input_buffers_.empty()); 74 DCHECK(free_input_buffers_.empty());
70 DCHECK_EQ(0, input_buffers_at_component_); 75 DCHECK_EQ(0, input_buffers_at_component_);
71 DCHECK_EQ(0, output_buffers_at_component_); 76 DCHECK_EQ(0, output_buffers_at_component_);
72 DCHECK(output_pictures_.empty()); 77 DCHECK(output_pictures_.empty());
73 } 78 }
74 79
80 void OmxVideoDecodeAccelerator::SetEglState(
81 EGLDisplay egl_display, EGLContext egl_context) {
82 egl_display_ = egl_display;
83 egl_context_ = egl_context;
84 }
85
75 void OmxVideoDecodeAccelerator::GetConfigs( 86 void OmxVideoDecodeAccelerator::GetConfigs(
76 const std::vector<uint32>& requested_configs, 87 const std::vector<uint32>& requested_configs,
77 std::vector<uint32>* matched_configs) { 88 std::vector<uint32>* matched_configs) {
78 // TODO(vhiremath@nvidia.com) use this properly 89 // TODO(vhiremath@nvidia.com) use this properly
79 NOTIMPLEMENTED(); 90 NOTIMPLEMENTED();
80 } 91 }
81 92
82 // This is to initialize the OMX data structures to default values. 93 // This is to initialize the OMX data structures to default values.
83 template <typename T> 94 template <typename T>
84 static void InitParam(const OmxVideoDecodeAccelerator& dec, T* param) { 95 static void InitParam(const OmxVideoDecodeAccelerator& dec, T* param) {
85 memset(param, 0, sizeof(T)); 96 memset(param, 0, sizeof(T));
86 param->nVersion.nVersion = 0x00000101; 97 param->nVersion.nVersion = 0x00000101;
87 param->nSize = sizeof(T); 98 param->nSize = sizeof(T);
88 } 99 }
89 100
90 bool OmxVideoDecodeAccelerator::Initialize(const std::vector<uint32>& config) { 101 bool OmxVideoDecodeAccelerator::Initialize(const std::vector<uint32>& config) {
91 // TODO(vhiremath@nvidia.com) get these actual values from config 102 // TODO(vhiremath@nvidia.com) get these actual values from config
92 // Assume qvga for now 103 // Assume qvga for now
93 width_ = 320; 104 width_ = 320;
94 height_ = 240; 105 height_ = 240;
95 106
96 client_state_ = OMX_StateLoaded; 107 client_state_ = OMX_StateLoaded;
97 if (!CreateComponent()) { 108 if (!CreateComponent()) {
98 StopOnError(); 109 StopOnError();
99 return false; 110 return false;
100 } 111 }
112
101 // Transition component to Idle state 113 // Transition component to Idle state
114 DCHECK(!on_state_event_func_);
102 on_state_event_func_ = 115 on_state_event_func_ =
103 &OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle; 116 &OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle;
104 if (!TransitionToState(OMX_StateIdle)) 117 if (!TransitionToState(OMX_StateIdle)) {
118 LOG(ERROR) << "TransitionToState(OMX_StateIdle) error";
119 StopOnError();
105 return false; 120 return false;
121 }
106 122
107 if (!AllocateInputBuffers()) { 123 if (!AllocateInputBuffers()) {
108 LOG(ERROR) << "OMX_AllocateBuffer() Input buffer error"; 124 LOG(ERROR) << "OMX_AllocateBuffer() Input buffer error";
109 StopOnError(); 125 StopOnError();
110 return false; 126 return false;
111 } 127 }
112 128
113 // After AllocateInputBuffers ideally this should be AllocateOutputBuffers. 129 // After AllocateInputBuffers ideally this should be AllocateOutputBuffers.
114 // Since in this case app provides the output buffers, 130 // Since in this case app provides the output buffers,
115 // we query this through ProvidePictureBuffers. 131 // we query this through ProvidePictureBuffers.
116 // This is call to ppapi to provide the output buffers initially. 132 // This is call to ppapi to provide the output buffers initially.
117 // ProvidePictureBuffers will provide 133 // ProvidePictureBuffers will provide
118 // - SharedMemHandle in case of decoding to system memory. 134 // - SharedMemHandle in case of decoding to system memory.
119 // - Textures in case of decoding to egl-images. 135 // - Textures in case of decoding to egl-images.
120 136
121 // Output buffers will be eventually handed to us via 137 // Output buffers will be eventually handed to us via
122 // Assign{GLES,Sysmem}Buffers(). 138 // Assign{GLES,Sysmem}Buffers().
123 output_buffer_count_ = kNumPictureBuffers; 139 output_buffer_count_ = kNumPictureBuffers;
124 client_->ProvidePictureBuffers( 140 message_loop_->PostTask(
125 output_buffer_count_, gfx::Size(width_, height_), 141 FROM_HERE,
126 PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE); 142 base::Bind(&Client::ProvidePictureBuffers, base::Unretained(client_),
143 output_buffer_count_, gfx::Size(width_, height_),
144 PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE));
127 // TODO(fischman): we always ask for GLES buffers above. So why maintain the 145 // TODO(fischman): we always ask for GLES buffers above. So why maintain the
128 // !uses_egl_image_ path in this class at all? Theoretically it could be 146 // !uses_egl_image_ path in this class at all? Theoretically it could be
129 // useful for testing, but today there's no such testing. Consider ripping it 147 // useful for testing, but today there's no such testing. Consider ripping it
130 // out of this class and replacing AssignSysmemBuffers() with 148 // out of this class and replacing AssignSysmemBuffers() with
131 // NOTIMPLEMENTED(). 149 // NOTIMPLEMENTED().
150
132 return true; 151 return true;
133 } 152 }
134 153
135 bool OmxVideoDecodeAccelerator::CreateComponent() { 154 bool OmxVideoDecodeAccelerator::CreateComponent() {
136 OMX_CALLBACKTYPE omx_accelerator_callbacks = { 155 OMX_CALLBACKTYPE omx_accelerator_callbacks = {
137 &OmxVideoDecodeAccelerator::EventHandler, 156 &OmxVideoDecodeAccelerator::EventHandler,
138 &OmxVideoDecodeAccelerator::EmptyBufferCallback, 157 &OmxVideoDecodeAccelerator::EmptyBufferCallback,
139 &OmxVideoDecodeAccelerator::FillBufferCallback 158 &OmxVideoDecodeAccelerator::FillBufferCallback
140 }; 159 };
141 OMX_ERRORTYPE result = OMX_ErrorNone; 160 OMX_ERRORTYPE result = OMX_ErrorNone;
142 161
143 // 1. Set the role and get all components of this role. 162 // 1. Set the role and get all components of this role.
144 // TODO(vhiremath@nvidia.com) Get this role_name from the configs 163 // TODO(vhiremath@nvidia.com) Get this role_name from the configs
145 // For now hard coding to avc. 164 // For now hard coding to avc.
146 const char* role_name = "video_decoder.avc"; 165 const char* role_name = "video_decoder.avc";
147 OMX_U32 num_roles = 0; 166 OMX_U32 num_roles = 0;
148 // Get all the components with this role. 167 // Get all the components with this role.
149 result = (*omx_get_components_of_role)( 168 result = (*omx_get_components_of_role)(
150 const_cast<OMX_STRING>(role_name), &num_roles, 0); 169 const_cast<OMX_STRING>(role_name), &num_roles, 0);
151 if (result != OMX_ErrorNone || num_roles == 0) { 170 if (result != OMX_ErrorNone || num_roles == 0) {
152 LOG(ERROR) << "Unsupported Role: " << role_name; 171 LOG(ERROR) << "Unsupported Role: " << role_name << ", " << result;
153 StopOnError(); 172 StopOnError();
154 return false; 173 return false;
155 } 174 }
156 175
157 // We haven't seen HW that needs more yet, 176 // We haven't seen HW that needs more yet,
158 // but there is no reason not to raise. 177 // but there is no reason not to raise.
159 const OMX_U32 kMaxRolePerComponent = 3; 178 const OMX_U32 kMaxRolePerComponent = 3;
160 CHECK_LT(num_roles, kMaxRolePerComponent); 179 CHECK_LT(num_roles, kMaxRolePerComponent);
161 180
162 scoped_array<scoped_array<OMX_U8> > component_names( 181 scoped_array<scoped_array<OMX_U8> > component_names(
(...skipping 27 matching lines...) Expand all
190 return false; 209 return false;
191 } 210 }
192 211
193 // 4. Get the port information. This will obtain information about the 212 // 4. Get the port information. This will obtain information about the
194 // number of ports and index of the first port. 213 // number of ports and index of the first port.
195 OMX_PORT_PARAM_TYPE port_param; 214 OMX_PORT_PARAM_TYPE port_param;
196 InitParam(*this, &port_param); 215 InitParam(*this, &port_param);
197 result = OMX_GetParameter(component_handle_, OMX_IndexParamVideoInit, 216 result = OMX_GetParameter(component_handle_, OMX_IndexParamVideoInit,
198 &port_param); 217 &port_param);
199 if ((result != OMX_ErrorNone) || (port_param.nPorts != 2)) { 218 if ((result != OMX_ErrorNone) || (port_param.nPorts != 2)) {
200 LOG(ERROR) << "Failed to get Port Param"; 219 LOG(ERROR) << "Failed to get Port Param: "
220 << result << ", " << port_param.nPorts;
201 StopOnError(); 221 StopOnError();
202 return false; 222 return false;
203 } 223 }
204 input_port_ = port_param.nStartPortNumber; 224 input_port_ = port_param.nStartPortNumber;
205 output_port_ = input_port_ + 1; 225 output_port_ = input_port_ + 1;
206 // 5. Set role for the component because components can have multiple roles. 226 // 5. Set role for the component because components can have multiple roles.
207 OMX_PARAM_COMPONENTROLETYPE role_type; 227 OMX_PARAM_COMPONENTROLETYPE role_type;
208 InitParam(*this, &role_type); 228 InitParam(*this, &role_type);
209 base::strlcpy(reinterpret_cast<char*>(role_type.cRole), 229 base::strlcpy(reinterpret_cast<char*>(role_type.cRole),
210 role_name, 230 role_name,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 // not make any assumptions about its completion. 306 // not make any assumptions about its completion.
287 omx_buff_ids_.insert(std::make_pair( 307 omx_buff_ids_.insert(std::make_pair(
288 omx_buffer, std::make_pair(shm.release(), bitstream_buffer.id()))); 308 omx_buffer, std::make_pair(shm.release(), bitstream_buffer.id())));
289 return true; 309 return true;
290 } 310 }
291 311
292 // NOTE: this is only partially-implemented as never unsets uses_egl_image_ once 312 // NOTE: this is only partially-implemented as never unsets uses_egl_image_ once
293 // set. 313 // set.
294 void OmxVideoDecodeAccelerator::AssignGLESBuffers( 314 void OmxVideoDecodeAccelerator::AssignGLESBuffers(
295 const std::vector<media::GLESBuffer>& buffers) { 315 const std::vector<media::GLESBuffer>& buffers) {
316 CHECK_EQ(message_loop_, MessageLoop::current());
296 uses_egl_image_ = true; 317 uses_egl_image_ = true;
297 std::vector<media::BaseBuffer*> base_buffers(buffers.size()); 318 std::vector<media::BaseBuffer*> base_buffers(buffers.size());
298 for (size_t i = 0; i < buffers.size(); ++i) 319 for (size_t i = 0; i < buffers.size(); ++i)
299 base_buffers[i] = new media::GLESBuffer(buffers[i]); 320 base_buffers[i] = new media::GLESBuffer(buffers[i]);
300 AssignBuffersHelper(base_buffers); 321 AssignBuffersHelper(base_buffers);
301 } 322 }
302 323
303 void OmxVideoDecodeAccelerator::AssignSysmemBuffers( 324 void OmxVideoDecodeAccelerator::AssignSysmemBuffers(
304 const std::vector<media::SysmemBuffer>& buffers) { 325 const std::vector<media::SysmemBuffer>& buffers) {
326 CHECK_EQ(message_loop_, MessageLoop::current());
305 DCHECK(!uses_egl_image_); 327 DCHECK(!uses_egl_image_);
306 std::vector<media::BaseBuffer*> base_buffers(buffers.size()); 328 std::vector<media::BaseBuffer*> base_buffers(buffers.size());
307 for (size_t i = 0; i < buffers.size(); ++i) 329 for (size_t i = 0; i < buffers.size(); ++i)
308 base_buffers[i] = new media::SysmemBuffer(buffers[i]); 330 base_buffers[i] = new media::SysmemBuffer(buffers[i]);
309 AssignBuffersHelper(base_buffers); 331 AssignBuffersHelper(base_buffers);
310 } 332 }
311 333
312 void OmxVideoDecodeAccelerator::AssignBuffersHelper( 334 void OmxVideoDecodeAccelerator::AssignBuffersHelper(
313 const std::vector<media::BaseBuffer*>& buffers) { 335 const std::vector<media::BaseBuffer*>& buffers) {
314 assigned_picture_buffers_.insert( 336 assigned_picture_buffers_.insert(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 return; 371 return;
350 } 372 }
351 } else { 373 } else {
352 output_buffer_count_ = port_format.nBufferCountActual; 374 output_buffer_count_ = port_format.nBufferCountActual;
353 } 375 }
354 output_buffer_size_ = port_format.nBufferSize; 376 output_buffer_size_ = port_format.nBufferSize;
355 377
356 if (!AllocateOutputBuffers()) { 378 if (!AllocateOutputBuffers()) {
357 LOG(ERROR) << "OMX_AllocateBuffer() Output buffer error"; 379 LOG(ERROR) << "OMX_AllocateBuffer() Output buffer error";
358 StopOnError(); 380 StopOnError();
381 return;
359 } 382 }
360 } 383 }
361 384
362 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { 385 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
363 // TODO(vhiremath@nvidia.com) Avoid leaking of the picture buffer. 386 // TODO(vhiremath@nvidia.com) Avoid leaking of the picture buffer.
364 if (!CanFillBuffer()) 387 if (!CanFillBuffer())
365 return; 388 return;
366 389
367 for (int i = 0; i < output_buffer_count_; ++i) { 390 for (int i = 0; i < output_buffer_count_; ++i) {
368 if (picture_buffer_id != assigned_picture_buffers_[i]->id()) 391 if (picture_buffer_id != assigned_picture_buffers_[i]->id())
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 OMX_GetState(component_handle_, &il_state); 427 OMX_GetState(component_handle_, &il_state);
405 DCHECK_EQ(il_state, OMX_StateExecuting); 428 DCHECK_EQ(il_state, OMX_StateExecuting);
406 if (il_state != OMX_StateExecuting) { 429 if (il_state != OMX_StateExecuting) {
407 client_->NotifyFlushDone(); 430 client_->NotifyFlushDone();
408 return false; 431 return false;
409 } 432 }
410 on_buffer_flag_event_func_ = &OmxVideoDecodeAccelerator::FlushBegin; 433 on_buffer_flag_event_func_ = &OmxVideoDecodeAccelerator::FlushBegin;
411 434
412 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); 435 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front();
413 free_input_buffers_.pop(); 436 free_input_buffers_.pop();
437
414 omx_buffer->nFilledLen = 0; 438 omx_buffer->nFilledLen = 0;
415 omx_buffer->nAllocLen = omx_buffer->nFilledLen; 439 omx_buffer->nAllocLen = omx_buffer->nFilledLen;
416 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; 440 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS;
417 omx_buffer->nTimeStamp = 0; 441 omx_buffer->nTimeStamp = 0;
418 // Give this buffer to OMX. 442 // Give this buffer to OMX.
419 OMX_ERRORTYPE result = OMX_ErrorNone; 443 OMX_ERRORTYPE result = OMX_ErrorNone;
420 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); 444 result = OMX_EmptyThisBuffer(component_handle_, omx_buffer);
421 if (result != OMX_ErrorNone) { 445 if (result != OMX_ErrorNone) {
422 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result; 446 LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result;
423 StopOnError(); 447 StopOnError();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 } 479 }
456 } 480 }
457 481
458 void OmxVideoDecodeAccelerator::PortFlushDone(int port) { 482 void OmxVideoDecodeAccelerator::PortFlushDone(int port) {
459 DCHECK_NE(port, static_cast<int>(OMX_ALL)); 483 DCHECK_NE(port, static_cast<int>(OMX_ALL));
460 484
461 if (port == input_port_) { 485 if (port == input_port_) {
462 VLOG(1) << "Input Port had been flushed"; 486 VLOG(1) << "Input Port had been flushed";
463 DCHECK_EQ(input_buffers_at_component_, 0); 487 DCHECK_EQ(input_buffers_at_component_, 0);
464 // Flush output port next. 488 // Flush output port next.
489 on_flush_event_func_ = &OmxVideoDecodeAccelerator::PortFlushDone;
465 OMX_ERRORTYPE result; 490 OMX_ERRORTYPE result;
466 result = OMX_SendCommand(component_handle_, 491 result = OMX_SendCommand(component_handle_,
467 OMX_CommandFlush, 492 OMX_CommandFlush,
468 output_port_, 0); 493 output_port_, 0);
469 if (result != OMX_ErrorNone) { 494 if (result != OMX_ErrorNone) {
470 LOG(ERROR) << "OMX_SendCommand(OMX_CommandFlush) failed"; 495 LOG(ERROR) << "OMX_SendCommand(OMX_CommandFlush) failed";
471 StopOnError(); 496 StopOnError();
472 return; 497 return;
473 } 498 }
474 return; 499 return;
475 } 500 }
476 501
477 if (port == output_port_) { 502 if (port == output_port_) {
478 VLOG(1) << "Output Port had been flushed"; 503 VLOG(1) << "Output Port had been flushed";
479 DCHECK_EQ(output_buffers_at_component_, 0); 504 DCHECK_EQ(output_buffers_at_component_, 0);
480 } 505 }
481 506
482 client_state_ = OMX_StatePause; 507 client_state_ = OMX_StatePause;
483 // So Finally call OnPortCommandFlush which should 508 // So Finally call OnPortCommandFlush which should
484 // internally call DismissPictureBuffer(); 509 // internally call DismissPictureBuffer();
485 OnPortCommandFlush(OMX_StateExecuting); 510 OnPortCommandFlush(OMX_StateExecuting);
486 } 511 }
487 512
488 bool OmxVideoDecodeAccelerator::Abort() { 513 bool OmxVideoDecodeAccelerator::Abort() {
514 CHECK_EQ(message_loop_, MessageLoop::current());
489 // TODO(vhiremath@nvidia.com) 515 // TODO(vhiremath@nvidia.com)
490 // Need more thinking on this to handle w.r.t OMX. 516 // Need more thinking on this to handle w.r.t OMX.
491 // There is no explicit UnInitialize call for this. 517 // There is no explicit UnInitialize call for this.
492 // Also review again for trick modes. 518 // Also review again for trick modes.
493 client_->NotifyAbortDone(); 519 client_->NotifyAbortDone();
494 return true; 520 return true;
495 } 521 }
496 522
497 // Event callback during initialization to handle DoneStateSet to idle 523 // Event callback during initialization to handle DoneStateSet to idle
498 void OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle(OMX_STATETYPE state) { 524 void OmxVideoDecodeAccelerator::OnStateChangeLoadedToIdle(OMX_STATETYPE state) {
525 CHECK_EQ(message_loop_, MessageLoop::current());
526 DCHECK(!on_state_event_func_);
499 DCHECK_EQ(client_state_, OMX_StateLoaded); 527 DCHECK_EQ(client_state_, OMX_StateLoaded);
500 DCHECK_EQ(OMX_StateIdle, state); 528 DCHECK_EQ(OMX_StateIdle, state);
529
501 VLOG(1) << "OMX video decode engine is in Idle"; 530 VLOG(1) << "OMX video decode engine is in Idle";
502 531
532 client_->NotifyInitializeDone();
vhiremath 2011/06/03 11:01:20 Ami, What is plugin's reaction to this notificatio
Ami GONE FROM CHROMIUM 2011/06/03 17:43:59 Great catch! Fixed. I was in fact seeing deadlo
533
503 on_state_event_func_ = 534 on_state_event_func_ =
504 &OmxVideoDecodeAccelerator::OnStateChangeIdleToExecuting; 535 &OmxVideoDecodeAccelerator::OnStateChangeIdleToExecuting;
505 if (!TransitionToState(OMX_StateExecuting)) 536 if (!TransitionToState(OMX_StateExecuting))
506 return; 537 return;
507 } 538 }
508 539
509 // Event callback during initialization to handle DoneStateSet to executing 540 // Event callback during initialization to handle DoneStateSet to executing
510 void OmxVideoDecodeAccelerator::OnStateChangeIdleToExecuting( 541 void OmxVideoDecodeAccelerator::OnStateChangeIdleToExecuting(
511 OMX_STATETYPE state) { 542 OMX_STATETYPE state) {
543 DCHECK(!on_state_event_func_);
512 DCHECK_EQ(OMX_StateExecuting, state); 544 DCHECK_EQ(OMX_StateExecuting, state);
545 DCHECK(!on_state_event_func_);
513 VLOG(1) << "OMX video decode engine is in Executing"; 546 VLOG(1) << "OMX video decode engine is in Executing";
514 547
515 client_state_ = OMX_StateExecuting; 548 client_state_ = OMX_StateExecuting;
516 on_state_event_func_ = NULL;
517 // This will kickoff the actual decoding 549 // This will kickoff the actual decoding
518 InitialFillBuffer(); 550 InitialFillBuffer();
519 } 551 }
520 552
521 // Send state transition command to component. 553 // Send state transition command to component.
522 bool OmxVideoDecodeAccelerator::TransitionToState(OMX_STATETYPE new_state) { 554 bool OmxVideoDecodeAccelerator::TransitionToState(OMX_STATETYPE new_state) {
523 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, 555 DCHECK(on_state_event_func_);
524 OMX_CommandStateSet, 556 OMX_ERRORTYPE result = OMX_SendCommand(
525 new_state, 0); 557 component_handle_, OMX_CommandStateSet, new_state, 0);
526 if (result != OMX_ErrorNone) { 558 if (result != OMX_ErrorNone) {
527 LOG(ERROR) << "SendCommand(OMX_CommandStateSet) failed"; 559 LOG(ERROR) << "SendCommand(OMX_CommandStateSet) failed";
528 StopOnError(); 560 StopOnError();
529 return false; 561 return false;
530 } 562 }
531 return true; 563 return true;
532 } 564 }
533 565
534 void OmxVideoDecodeAccelerator::OnPortCommandFlush(OMX_STATETYPE state) { 566 void OmxVideoDecodeAccelerator::OnPortCommandFlush(OMX_STATETYPE state) {
535 DCHECK_EQ(state, OMX_StateExecuting); 567 DCHECK_EQ(state, OMX_StateExecuting);
568 CHECK_EQ(message_loop_, MessageLoop::current());
536 569
537 VLOG(1) << "Deinit from Executing"; 570 VLOG(1) << "Deinit from Executing";
571 DCHECK(!on_state_event_func_);
538 on_state_event_func_ = 572 on_state_event_func_ =
539 &OmxVideoDecodeAccelerator::OnStateChangeExecutingToIdle; 573 &OmxVideoDecodeAccelerator::OnStateChangeExecutingToIdle;
540 TransitionToState(OMX_StateIdle); 574 TransitionToState(OMX_StateIdle);
541 for (int i = 0; i < output_buffer_count_; ++i) { 575 for (int i = 0; i < output_buffer_count_; ++i) {
542 OutputPicture output_picture = output_pictures_[i]; 576 OutputPicture output_picture = output_pictures_[i];
543 client_->DismissPictureBuffer(output_picture.first); 577 client_->DismissPictureBuffer(output_picture.first);
544 } 578 }
545 STLDeleteElements(&assigned_picture_buffers_); 579 STLDeleteElements(&assigned_picture_buffers_);
546 } 580 }
547 581
548 void OmxVideoDecodeAccelerator::OnStateChangeExecutingToIdle( 582 void OmxVideoDecodeAccelerator::OnStateChangeExecutingToIdle(
549 OMX_STATETYPE state) { 583 OMX_STATETYPE state) {
550 DCHECK_EQ(state, OMX_StateIdle); 584 DCHECK_EQ(state, OMX_StateIdle);
585 DCHECK(!on_state_event_func_);
551 586
552 VLOG(1) << "Deinit from Idle"; 587 VLOG(1) << "Deinit from Idle";
553 on_state_event_func_ = 588 on_state_event_func_ =
554 &OmxVideoDecodeAccelerator::OnStateChangeIdleToLoaded; 589 &OmxVideoDecodeAccelerator::OnStateChangeIdleToLoaded;
555 TransitionToState(OMX_StateLoaded); 590 TransitionToState(OMX_StateLoaded);
556 591
557 if (!input_buffers_at_component_) 592 if (!input_buffers_at_component_)
558 FreeInputBuffers(); 593 FreeInputBuffers();
559 594
560 if (!output_buffers_at_component_) 595 if (!output_buffers_at_component_)
561 FreeOutputBuffers(); 596 FreeOutputBuffers();
562 } 597 }
563 598
564 void OmxVideoDecodeAccelerator::OnStateChangeIdleToLoaded(OMX_STATETYPE state) { 599 void OmxVideoDecodeAccelerator::OnStateChangeIdleToLoaded(OMX_STATETYPE state) {
565 DCHECK_EQ(state, OMX_StateLoaded); 600 DCHECK_EQ(state, OMX_StateLoaded);
601 CHECK_EQ(message_loop_, MessageLoop::current());
602 DCHECK(!on_state_event_func_);
566 603
567 VLOG(1) << "Idle to Loaded"; 604 VLOG(1) << "Idle to Loaded";
568 605
569 if (component_handle_) { 606 if (component_handle_) {
570 OMX_ERRORTYPE result = (*omx_free_handle)(component_handle_); 607 OMX_ERRORTYPE result = (*omx_free_handle)(component_handle_);
571 if (result != OMX_ErrorNone) 608 if (result != OMX_ErrorNone)
572 LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result; 609 LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result;
573 component_handle_ = NULL; 610 component_handle_ = NULL;
574 } 611 }
575 client_state_ = OMX_StateLoaded; 612 client_state_ = OMX_StateLoaded;
(...skipping 16 matching lines...) Expand all
592 case OMX_StateLoaded: 629 case OMX_StateLoaded:
593 OnStateChangeIdleToLoaded(OMX_StateLoaded); 630 OnStateChangeIdleToLoaded(OMX_StateLoaded);
594 return; 631 return;
595 default: 632 default:
596 // LOG unexpected state or just ignore? 633 // LOG unexpected state or just ignore?
597 return; 634 return;
598 } 635 }
599 } 636 }
600 637
601 bool OmxVideoDecodeAccelerator::AllocateInputBuffers() { 638 bool OmxVideoDecodeAccelerator::AllocateInputBuffers() {
602 scoped_array<uint8> data(new uint8[input_buffer_size_]);
603
604 for (int i = 0; i < input_buffer_count_; ++i) { 639 for (int i = 0; i < input_buffer_count_; ++i) {
605 OMX_BUFFERHEADERTYPE* buffer; 640 OMX_BUFFERHEADERTYPE* buffer;
606 OMX_ERRORTYPE result = 641 OMX_ERRORTYPE result =
607 OMX_UseBuffer(component_handle_, &buffer, input_port_, 642 OMX_AllocateBuffer(component_handle_, &buffer, input_port_,
608 this, input_buffer_size_, data.get()); 643 this, input_buffer_size_);
609 if (result != OMX_ErrorNone) 644 if (result != OMX_ErrorNone)
610 return false; 645 return false;
611 buffer->nInputPortIndex = input_port_; 646 buffer->nInputPortIndex = input_port_;
612 buffer->nOffset = 0; 647 buffer->nOffset = 0;
613 buffer->nFlags = 0; 648 buffer->nFlags = 0;
614 free_input_buffers_.push(buffer); 649 free_input_buffers_.push(buffer);
615 } 650 }
616 return true; 651 return true;
617 } 652 }
618 653
619 bool OmxVideoDecodeAccelerator::AllocateOutputBuffers() { 654 bool OmxVideoDecodeAccelerator::AllocateOutputBuffers() {
620 static Gles2TextureToEglImageTranslator* texture2eglImage_translator( 655 CHECK_EQ(message_loop_, MessageLoop::current());
621 new Gles2TextureToEglImageTranslator(NULL, 0)); 656 static Gles2TextureToEglImageTranslator texture2eglImage_translator;
622 657
623 gfx::Size decoded_pixel_size(width_, height_); 658 gfx::Size decoded_pixel_size(width_, height_);
624 gfx::Size visible_pixel_size(width_, height_); 659 gfx::Size visible_pixel_size(width_, height_);
625 // TODO(fischman): remove garbage bitstream buffer id's below (42 and 24) when 660 // TODO(fischman): remove garbage bitstream buffer id's below (42 and 24) when
626 // the bitstream_buffer_id field is removed from Picture. 661 // the bitstream_buffer_id field is removed from Picture.
627 if (uses_egl_image_) { 662 if (uses_egl_image_) {
628 for (uint32 i = 0; i < assigned_picture_buffers_.size(); i++) { 663 for (uint32 i = 0; i < assigned_picture_buffers_.size(); i++) {
629 media::GLESBuffer* gles_buffer = 664 media::GLESBuffer* gles_buffer =
630 reinterpret_cast<media::GLESBuffer*>(assigned_picture_buffers_[i]); 665 reinterpret_cast<media::GLESBuffer*>(assigned_picture_buffers_[i]);
631 OMX_BUFFERHEADERTYPE* omx_buffer; 666 OMX_BUFFERHEADERTYPE* omx_buffer;
632 void* egl = texture2eglImage_translator->TranslateToEglImage( 667 void* egl = texture2eglImage_translator.TranslateToEglImage(
633 gles_buffer->texture_id()); 668 egl_display_, egl_context_, gles_buffer->texture_id());
634 OMX_ERRORTYPE result = OMX_UseEGLImage( 669 OMX_ERRORTYPE result = OMX_UseEGLImage(
635 component_handle_, &omx_buffer, output_port_, gles_buffer, egl); 670 component_handle_, &omx_buffer, output_port_, gles_buffer, egl);
636 if (result != OMX_ErrorNone) { 671 if (result != OMX_ErrorNone) {
637 LOG(ERROR) << "OMX_UseEGLImage failed"; 672 LOG(ERROR) << "OMX_UseEGLImage failed with: " << result;
638 return false; 673 return false;
639 } 674 }
640 omx_buffer->pAppPrivate = 675 omx_buffer->pAppPrivate =
641 new media::Picture(gles_buffer->id(), 676 new media::Picture(gles_buffer->id(),
642 42 /* garbage bitstreambuffer id */, 677 42 /* garbage bitstreambuffer id */,
643 decoded_pixel_size, visible_pixel_size); 678 decoded_pixel_size, visible_pixel_size);
644 output_pictures_.push_back( 679 output_pictures_.push_back(
645 std::make_pair(assigned_picture_buffers_[i]->id(), omx_buffer)); 680 std::make_pair(assigned_picture_buffers_[i]->id(), omx_buffer));
646 } 681 }
647 } else { 682 } else {
(...skipping 19 matching lines...) Expand all
667 702
668 void OmxVideoDecodeAccelerator::FreeInputBuffers() { 703 void OmxVideoDecodeAccelerator::FreeInputBuffers() {
669 // Calls to OMX to free buffers. 704 // Calls to OMX to free buffers.
670 OMX_ERRORTYPE result; 705 OMX_ERRORTYPE result;
671 OMX_BUFFERHEADERTYPE* omx_buffer; 706 OMX_BUFFERHEADERTYPE* omx_buffer;
672 while (!free_input_buffers_.empty()) { 707 while (!free_input_buffers_.empty()) {
673 omx_buffer = free_input_buffers_.front(); 708 omx_buffer = free_input_buffers_.front();
674 free_input_buffers_.pop(); 709 free_input_buffers_.pop();
675 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer); 710 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer);
676 if (result != OMX_ErrorNone) { 711 if (result != OMX_ErrorNone) {
677 LOG(ERROR) << "SendCommand(OMX_CommandPortDisable) failed"; 712 LOG(ERROR) << "OMX_CommandPortDisable failed with: " << result;
678 StopOnError(); 713 StopOnError();
679 return; 714 return;
680 } 715 }
681 } 716 }
682 } 717 }
683 718
684 void OmxVideoDecodeAccelerator::FreeOutputBuffers() { 719 void OmxVideoDecodeAccelerator::FreeOutputBuffers() {
685 // Calls to OMX to free buffers. 720 // Calls to OMX to free buffers.
686 OMX_ERRORTYPE result; 721 OMX_ERRORTYPE result;
687 for (size_t i = 0; i < output_pictures_.size(); ++i) { 722 for (size_t i = 0; i < output_pictures_.size(); ++i) {
688 OMX_BUFFERHEADERTYPE* omx_buffer = output_pictures_[i].second; 723 OMX_BUFFERHEADERTYPE* omx_buffer = output_pictures_[i].second;
689 CHECK(omx_buffer); 724 CHECK(omx_buffer);
690 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); 725 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate);
691 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); 726 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer);
692 if (result != OMX_ErrorNone) { 727 if (result != OMX_ErrorNone) {
693 LOG(ERROR) << "SendCommand(OMX_CommandPortDisable) failed"; 728 LOG(ERROR) << "OMX_FreeBuffer failed with: " << result;
694 StopOnError(); 729 StopOnError();
695 return; 730 return;
696 } 731 }
697 } 732 }
698 output_pictures_.clear(); 733 output_pictures_.clear();
699 } 734 }
700 735
701 void OmxVideoDecodeAccelerator::OnPortSettingsChangedRun( 736 void OmxVideoDecodeAccelerator::OnPortSettingsChangedRun(
702 int port, OMX_INDEXTYPE index) { 737 int port, OMX_INDEXTYPE index) {
703 // TODO(vhiremath@nvidia.com) visit again later 738 // TODO(vhiremath@nvidia.com) visit again later
704 // Port settings changes can be called during run time 739 // Port settings changes can be called during run time
705 // changes in the resolution of video playback. 740 // changes in the resolution of video playback.
706 // In this case, the component detects PortSettingsChanged 741 // In this case, the component detects PortSettingsChanged
707 // and sends the particular event to the IL-client. 742 // and sends the particular event to the IL-client.
708 // This needs to be handled in this method. 743 // This needs to be handled in this method.
709 return; 744 return;
710 } 745 }
711 746
712 void OmxVideoDecodeAccelerator::FillBufferDoneTask( 747 void OmxVideoDecodeAccelerator::FillBufferDoneTask(
713 OMX_BUFFERHEADERTYPE* buffer) { 748 OMX_BUFFERHEADERTYPE* buffer) {
749 CHECK_EQ(message_loop_, MessageLoop::current());
714 DCHECK_GT(output_buffers_at_component_, 0); 750 DCHECK_GT(output_buffers_at_component_, 0);
715 output_buffers_at_component_--; 751 output_buffers_at_component_--;
716 client_->PictureReady(*reinterpret_cast<media::Picture*>( 752 client_->PictureReady(*reinterpret_cast<media::Picture*>(
717 buffer->pAppPrivate)); 753 buffer->pAppPrivate));
718 } 754 }
719 755
720 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( 756 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask(
721 OMX_BUFFERHEADERTYPE* buffer) { 757 OMX_BUFFERHEADERTYPE* buffer) {
722 DCHECK_GT(input_buffers_at_component_, 0); 758 DCHECK_GT(input_buffers_at_component_, 0);
759 CHECK_EQ(message_loop_, MessageLoop::current());
723 free_input_buffers_.push(buffer); 760 free_input_buffers_.push(buffer);
724 input_buffers_at_component_--; 761 input_buffers_at_component_--;
725 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) 762 if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
726 return; 763 return;
764
727 // Retrieve the corresponding BitstreamBuffer's id and notify the client of 765 // Retrieve the corresponding BitstreamBuffer's id and notify the client of
728 // its completion. 766 // its completion.
729 OMXBufferIdMap::iterator it = omx_buff_ids_.find(buffer); 767 OMXBufferIdMap::iterator it = omx_buff_ids_.find(buffer);
730 if (it == omx_buff_ids_.end()) { 768 if (it == omx_buff_ids_.end()) {
731 LOG(ERROR) << "Unexpectedly failed to find a buffer id."; 769 LOG(ERROR) << "Unexpectedly failed to find a buffer id.";
732 StopOnError(); 770 StopOnError();
733 return; 771 return;
734 } 772 }
735 delete it->second.first; 773 delete it->second.first;
736 client_->NotifyEndOfBitstreamBuffer(it->second.second); 774 client_->NotifyEndOfBitstreamBuffer(it->second.second);
737 omx_buff_ids_.erase(it); 775 omx_buff_ids_.erase(it);
738 } 776 }
739 777
740 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, 778 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event,
741 OMX_U32 data1, 779 OMX_U32 data1,
742 OMX_U32 data2) { 780 OMX_U32 data2) {
781 DCHECK_EQ(MessageLoop::current(), message_loop_);
743 switch (event) { 782 switch (event) {
744 case OMX_EventCmdComplete: { 783 case OMX_EventCmdComplete: {
745 // If the last command was successful, we have completed 784 // If the last command was successful, we have completed
746 // a state transition. So notify that we have done it 785 // a state transition. So notify that we have done it
747 // accordingly. 786 // accordingly.
748 OMX_COMMANDTYPE cmd = static_cast<OMX_COMMANDTYPE>(data1); 787 OMX_COMMANDTYPE cmd = static_cast<OMX_COMMANDTYPE>(data1);
749 switch (cmd) { 788 switch (cmd) {
750 case OMX_CommandPortDisable: { 789 case OMX_CommandPortDisable:
751 if (on_port_disable_event_func_) 790 if (on_port_disable_event_func_) {
752 (this->*on_port_disable_event_func_)(static_cast<int>(data2)); 791 void (OmxVideoDecodeAccelerator::*func)(int) = NULL;
792 std::swap(func, on_port_disable_event_func_);
793 (this->*func)(static_cast<int>(data2));
753 } 794 }
754 break; 795 break;
755 case OMX_CommandPortEnable: { 796 case OMX_CommandPortEnable:
756 if (on_port_enable_event_func_) 797 if (on_port_enable_event_func_) {
757 (this->*on_port_enable_event_func_)(static_cast<int>(data2)); 798 void (OmxVideoDecodeAccelerator::*func)(int) = NULL;
799 std::swap(func, on_port_enable_event_func_);
800 (this->*func)(static_cast<int>(data2));
758 } 801 }
759 break; 802 break;
760 case OMX_CommandStateSet: 803 case OMX_CommandStateSet:
761 (this->*on_state_event_func_)(static_cast<OMX_STATETYPE>(data2)); 804 {
805 void (OmxVideoDecodeAccelerator::*func)(OMX_STATETYPE state) = NULL;
806 std::swap(func, on_state_event_func_);
807 (this->*func)(static_cast<OMX_STATETYPE>(data2));
808 }
762 break; 809 break;
763 case OMX_CommandFlush: 810 case OMX_CommandFlush:
764 (this->*on_flush_event_func_)(data2); 811 {
812 void (OmxVideoDecodeAccelerator::*func)(int) = NULL;
813 std::swap(func, on_flush_event_func_);
814 (this->*func)(data2);
815 }
765 break; 816 break;
766 default: 817 default:
767 LOG(ERROR) << "Unknown command completed\n" << data1; 818 LOG(ERROR) << "Unknown command completed\n" << data1;
768 break; 819 break;
769 } 820 }
770 break; 821 break;
771 } 822 }
772 case OMX_EventError: 823 case OMX_EventError:
773 if (static_cast<OMX_ERRORTYPE>(data1) == OMX_ErrorInvalidState) 824 if (static_cast<OMX_ERRORTYPE>(data1) == OMX_ErrorInvalidState)
774 StopOnError(); 825 StopOnError();
775 break; 826 break;
776 case OMX_EventPortSettingsChanged: 827 case OMX_EventPortSettingsChanged:
777 // TODO(vhiremath@nvidia.com) remove this hack 828 // TODO(vhiremath@nvidia.com) remove this hack
778 // when all vendors observe same spec. 829 // when all vendors observe same spec.
779 if (data1 < OMX_IndexComponentStartUnused) { 830 if (data1 < OMX_IndexComponentStartUnused) {
780 OnPortSettingsChangedRun(static_cast<int>(data1), 831 OnPortSettingsChangedRun(static_cast<int>(data1),
781 static_cast<OMX_INDEXTYPE>(data2)); 832 static_cast<OMX_INDEXTYPE>(data2));
782 } else { 833 } else {
783 OnPortSettingsChangedRun(static_cast<int>(data2), 834 OnPortSettingsChangedRun(static_cast<int>(data2),
784 static_cast<OMX_INDEXTYPE>(data1)); 835 static_cast<OMX_INDEXTYPE>(data1));
785 } 836 }
786 break; 837 break;
787 case OMX_EventBufferFlag: 838 case OMX_EventBufferFlag:
788 if (data1 == static_cast<OMX_U32>(output_port_)) { 839 if (data1 == static_cast<OMX_U32>(output_port_)) {
789 (this->*on_buffer_flag_event_func_)(); 840 void (OmxVideoDecodeAccelerator::*func)() = NULL;
841 std::swap(func, on_buffer_flag_event_func_);
842 (this->*func)();
790 } 843 }
791 break; 844 break;
792 default: 845 default:
793 LOG(ERROR) << "Warning - Unknown event received\n"; 846 LOG(ERROR) << "Warning - Unknown event received\n";
794 break; 847 break;
795 } 848 }
796 } 849 }
797 850
798 // static 851 // static
799 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, 852 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
869 StopOnError(); 922 StopOnError();
870 return false; 923 return false;
871 } 924 }
872 return (il_state == OMX_StateExecuting); 925 return (il_state == OMX_StateExecuting);
873 } 926 }
874 927
875 // Send command to disable/enable port. 928 // Send command to disable/enable port.
876 void OmxVideoDecodeAccelerator::ChangePort( 929 void OmxVideoDecodeAccelerator::ChangePort(
877 OMX_COMMANDTYPE cmd, int port_index) { 930 OMX_COMMANDTYPE cmd, int port_index) {
878 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, 931 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_,
879 cmd, port_index, 0); 932 cmd, port_index, 0);
880 if (result != OMX_ErrorNone) { 933 if (result != OMX_ErrorNone) {
881 LOG(ERROR) << "SendCommand(OMX_CommandPortDisable) failed"; 934 LOG(ERROR) << "SendCommand(OMX_CommandPortDisable) failed";
882 StopOnError(); 935 StopOnError();
883 return; 936 return;
884 } 937 }
885 } 938 }
886 939
887 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator); 940 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698