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

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

Issue 7361010: Enable fire-and-forget Destroy of HW video decoder, and misc other improvements. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 5 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/media/omx_video_decode_accelerator.h" 5 #include "content/common/gpu/media/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/gpu_channel.h" 9 #include "content/common/gpu/gpu_channel.h"
10 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h" 10 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 #define RETURN_ON_FAILURE(result, log, error, ret_val) \ 50 #define RETURN_ON_FAILURE(result, log, error, ret_val) \
51 do { \ 51 do { \
52 if (!(result)) { \ 52 if (!(result)) { \
53 LOG(ERROR) << log; \ 53 LOG(ERROR) << log; \
54 StopOnError(error); \ 54 StopOnError(error); \
55 return ret_val; \ 55 return ret_val; \
56 } \ 56 } \
57 } while (0) 57 } while (0)
58 58
59 // OMX-specific version of RETURN_ON_FAILURE which compares with OMX_ErrorNone. 59 // OMX-specific version of RETURN_ON_FAILURE which compares with OMX_ErrorNone.
60 #define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \ 60 #define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \
61 RETURN_ON_FAILURE( \ 61 RETURN_ON_FAILURE( \
62 ((omx_result) == OMX_ErrorNone), \ 62 ((omx_result) == OMX_ErrorNone), \
63 log << ", OMX result: " << std::hex << std::showbase << omx_result, \ 63 log << ", OMX result: 0x" << std::hex << omx_result, \
64 error, ret_val) 64 error, ret_val)
65 65
66 OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator( 66 OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator(
67 media::VideoDecodeAccelerator::Client* client) 67 media::VideoDecodeAccelerator::Client* client)
68 : message_loop_(MessageLoop::current()), 68 : message_loop_(MessageLoop::current()),
69 component_handle_(NULL), 69 component_handle_(NULL),
70 client_state_(OMX_StateMax), 70 client_state_(OMX_StateMax),
71 current_state_change_(NO_TRANSITION), 71 current_state_change_(NO_TRANSITION),
72 saw_eos_during_flush_(false), 72 saw_eos_during_flush_(false),
73 input_buffer_count_(0), 73 input_buffer_count_(0),
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 scoped_array<OMX_U8> component(new OMX_U8[OMX_MAX_STRINGNAME_SIZE]); 175 scoped_array<OMX_U8> component(new OMX_U8[OMX_MAX_STRINGNAME_SIZE]);
176 OMX_ERRORTYPE result = omx_get_components_of_role( 176 OMX_ERRORTYPE result = omx_get_components_of_role(
177 role_name, &num_components, reinterpret_cast<OMX_U8**>(&component)); 177 role_name, &num_components, reinterpret_cast<OMX_U8**>(&component));
178 RETURN_ON_OMX_FAILURE(result, "Unsupport role: " << role_name, 178 RETURN_ON_OMX_FAILURE(result, "Unsupport role: " << role_name,
179 VIDEODECODERERROR_UNSUPPORTED, false); 179 VIDEODECODERERROR_UNSUPPORTED, false);
180 RETURN_ON_FAILURE(num_components == 1, 180 RETURN_ON_FAILURE(num_components == 1,
181 "No components for: " << role_name, 181 "No components for: " << role_name,
182 VIDEODECODERERROR_UNSUPPORTED, false); 182 VIDEODECODERERROR_UNSUPPORTED, false);
183 183
184 // Get the handle to the component. 184 // Get the handle to the component.
185 AddRef(); // To reflect passing |this| to OMX_GetHandle below.
185 result = omx_gethandle( 186 result = omx_gethandle(
186 &component_handle_, reinterpret_cast<OMX_STRING>(component.get()), 187 &component_handle_, reinterpret_cast<OMX_STRING>(component.get()),
187 this, &omx_accelerator_callbacks); 188 this, &omx_accelerator_callbacks);
188 RETURN_ON_OMX_FAILURE(result, 189 RETURN_ON_OMX_FAILURE(result,
189 "Failed to OMX_GetHandle on: " << component.get(), 190 "Failed to OMX_GetHandle on: " << component.get(),
190 VIDEODECODERERROR_INSUFFICIENT_RESOURCES, false); 191 VIDEODECODERERROR_INSUFFICIENT_RESOURCES, false);
191 client_state_ = OMX_StateLoaded; 192 client_state_ = OMX_StateLoaded;
192 193
193 // Get the port information. This will obtain information about the number of 194 // Get the port information. This will obtain information about the number of
194 // ports and index of the first port. 195 // ports and index of the first port.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 RETURN_ON_OMX_FAILURE(result, 259 RETURN_ON_OMX_FAILURE(result,
259 "SetParameter(OMX_IndexParamPortDefinition) failed", 260 "SetParameter(OMX_IndexParamPortDefinition) failed",
260 VIDEODECODERERROR_INVALIDINPUT, false); 261 VIDEODECODERERROR_INVALIDINPUT, false);
261 262
262 // Fill the component with fake output buffers. This seems to be required for 263 // Fill the component with fake output buffers. This seems to be required for
263 // the component to move from Loaded to Idle. How bogus. 264 // the component to move from Loaded to Idle. How bogus.
264 for (int i = 0; i < kNumPictureBuffers; ++i) { 265 for (int i = 0; i < kNumPictureBuffers; ++i) {
265 OMX_BUFFERHEADERTYPE* buffer; 266 OMX_BUFFERHEADERTYPE* buffer;
266 result = OMX_UseBuffer(component_handle_, &buffer, output_port_, 267 result = OMX_UseBuffer(component_handle_, &buffer, output_port_,
267 NULL, 0, reinterpret_cast<OMX_U8*>(0x1)); 268 NULL, 0, reinterpret_cast<OMX_U8*>(0x1));
268 RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer failed with: " << result, 269 RETURN_ON_OMX_FAILURE(result, "OMX_UseBuffer failed",
269 VIDEODECODERERROR_INVALIDINPUT, false); 270 VIDEODECODERERROR_INVALIDINPUT, false);
270 buffer->pAppPrivate = NULL; 271 buffer->pAppPrivate = NULL;
271 buffer->nTimeStamp = -1; 272 buffer->nTimeStamp = -1;
272 buffer->nOutputPortIndex = output_port_; 273 buffer->nOutputPortIndex = output_port_;
273 CHECK(fake_output_buffers_.insert(buffer).second); 274 CHECK(fake_output_buffers_.insert(buffer).second);
274 } 275 }
275 276
276 return true; 277 return true;
277 } 278 }
278 279
279 void OmxVideoDecodeAccelerator::Decode( 280 void OmxVideoDecodeAccelerator::Decode(
280 const media::BitstreamBuffer& bitstream_buffer) { 281 const media::BitstreamBuffer& bitstream_buffer) {
281 DCHECK_EQ(message_loop_, MessageLoop::current()); 282 DCHECK_EQ(message_loop_, MessageLoop::current());
282 DCHECK(!free_input_buffers_.empty()); 283 DCHECK(!free_input_buffers_.empty());
283 284
284 RETURN_ON_FAILURE(current_state_change_ == NO_TRANSITION && 285 RETURN_ON_FAILURE(current_state_change_ == NO_TRANSITION &&
285 (client_state_ == OMX_StateIdle || 286 (client_state_ == OMX_StateIdle ||
286 client_state_ == OMX_StateExecuting), 287 client_state_ == OMX_StateExecuting),
287 "Call to Decode() during invalid state or transition:" 288 "Call to Decode() during invalid state or transition: "
288 << current_state_change_ << ", " << client_state_, 289 << current_state_change_ << ", " << client_state_,
289 VIDEODECODERERROR_UNSUPPORTED,); 290 VIDEODECODERERROR_UNSUPPORTED,);
290 291
291 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); 292 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front();
292 free_input_buffers_.pop(); 293 free_input_buffers_.pop();
293 294
294 // Setup |omx_buffer|. 295 // Setup |omx_buffer|.
295 scoped_ptr<base::SharedMemory> shm( 296 scoped_ptr<base::SharedMemory> shm(
296 new base::SharedMemory(bitstream_buffer.handle(), true)); 297 new base::SharedMemory(bitstream_buffer.handle(), true));
297 RETURN_ON_FAILURE(shm->Map(bitstream_buffer.size()), 298 RETURN_ON_FAILURE(shm->Map(bitstream_buffer.size()),
(...skipping 10 matching lines...) Expand all
308 omx_buffer->nFilledLen = bitstream_buffer.size(); 309 omx_buffer->nFilledLen = bitstream_buffer.size();
309 omx_buffer->nAllocLen = omx_buffer->nFilledLen; 310 omx_buffer->nAllocLen = omx_buffer->nFilledLen;
310 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; 311 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
311 // Abuse the header's nTimeStamp field to propagate the bitstream buffer ID to 312 // Abuse the header's nTimeStamp field to propagate the bitstream buffer ID to
312 // the output buffer's nTimeStamp field, so we can report it back to the 313 // the output buffer's nTimeStamp field, so we can report it back to the
313 // client in PictureReady(). 314 // client in PictureReady().
314 omx_buffer->nTimeStamp = bitstream_buffer.id(); 315 omx_buffer->nTimeStamp = bitstream_buffer.id();
315 316
316 // Give this buffer to OMX. 317 // Give this buffer to OMX.
317 OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); 318 OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer);
318 RETURN_ON_OMX_FAILURE(result, 319 RETURN_ON_OMX_FAILURE(result, "OMX_EmptyThisBuffer() failed",
319 "OMX_EmptyThisBuffer() failed with result " << result,
320 VIDEODECODERERROR_INVALIDINPUT,); 320 VIDEODECODERERROR_INVALIDINPUT,);
321 321
322 input_buffers_at_component_++; 322 input_buffers_at_component_++;
323 } 323 }
324 324
325 void OmxVideoDecodeAccelerator::AssignGLESBuffers( 325 void OmxVideoDecodeAccelerator::AssignGLESBuffers(
326 const std::vector<media::GLESBuffer>& buffers) { 326 const std::vector<media::GLESBuffer>& buffers) {
327 DCHECK_EQ(message_loop_, MessageLoop::current()); 327 DCHECK_EQ(message_loop_, MessageLoop::current());
328 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", 328 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer",
329 VIDEODECODERERROR_UNSUPPORTED,); 329 VIDEODECODERERROR_UNSUPPORTED,);
(...skipping 28 matching lines...) Expand all
358 358
359 OutputPictureById::iterator it = pictures_.find(picture_buffer_id); 359 OutputPictureById::iterator it = pictures_.find(picture_buffer_id);
360 RETURN_ON_FAILURE(it != pictures_.end(), 360 RETURN_ON_FAILURE(it != pictures_.end(),
361 "Missing picture buffer id: " << picture_buffer_id, 361 "Missing picture buffer id: " << picture_buffer_id,
362 VIDEODECODERERROR_UNSUPPORTED,); 362 VIDEODECODERERROR_UNSUPPORTED,);
363 OutputPicture& output_picture = it->second; 363 OutputPicture& output_picture = it->second;
364 364
365 ++output_buffers_at_component_; 365 ++output_buffers_at_component_;
366 OMX_ERRORTYPE result = 366 OMX_ERRORTYPE result =
367 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header); 367 OMX_FillThisBuffer(component_handle_, output_picture.omx_buffer_header);
368 RETURN_ON_OMX_FAILURE(result, 368 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed",
369 "OMX_FillThisBuffer() failed with result " << result,
370 VIDEODECODERERROR_INVALIDINPUT,); 369 VIDEODECODERERROR_INVALIDINPUT,);
371 } 370 }
372 371
373 void OmxVideoDecodeAccelerator::Flush() { 372 void OmxVideoDecodeAccelerator::Flush() {
374 DCHECK_EQ(message_loop_, MessageLoop::current()); 373 DCHECK_EQ(message_loop_, MessageLoop::current());
375 DCHECK_EQ(current_state_change_, NO_TRANSITION); 374 DCHECK_EQ(current_state_change_, NO_TRANSITION);
376 DCHECK_EQ(client_state_, OMX_StateExecuting); 375 DCHECK_EQ(client_state_, OMX_StateExecuting);
377 current_state_change_ = FLUSHING; 376 current_state_change_ = FLUSHING;
378 377
379 // Cook up an empty buffer w/ EOS set and feed it to OMX. 378 // Cook up an empty buffer w/ EOS set and feed it to OMX.
380 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front(); 379 OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front();
381 free_input_buffers_.pop(); 380 free_input_buffers_.pop();
382 omx_buffer->nFilledLen = 0; 381 omx_buffer->nFilledLen = 0;
383 omx_buffer->nAllocLen = omx_buffer->nFilledLen; 382 omx_buffer->nAllocLen = omx_buffer->nFilledLen;
384 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS; 383 omx_buffer->nFlags |= OMX_BUFFERFLAG_EOS;
385 omx_buffer->nTimeStamp = -2; 384 omx_buffer->nTimeStamp = -2;
386 OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer); 385 OMX_ERRORTYPE result = OMX_EmptyThisBuffer(component_handle_, omx_buffer);
387 RETURN_ON_OMX_FAILURE(result, 386 RETURN_ON_OMX_FAILURE(result, "OMX_EmptyThisBuffer() failed",
388 "OMX_EmptyThisBuffer() failed with result " << result,
389 VIDEODECODERERROR_INVALIDINPUT,); 387 VIDEODECODERERROR_INVALIDINPUT,);
390 input_buffers_at_component_++; 388 input_buffers_at_component_++;
391 } 389 }
392 390
393 void OmxVideoDecodeAccelerator::OnReachedEOSInFlushing() { 391 void OmxVideoDecodeAccelerator::OnReachedEOSInFlushing() {
394 DCHECK_EQ(message_loop_, MessageLoop::current()); 392 DCHECK_EQ(message_loop_, MessageLoop::current());
395 BeginTransitionToState(OMX_StatePause); 393 BeginTransitionToState(OMX_StatePause);
396 } 394 }
397 395
398 void OmxVideoDecodeAccelerator::FlushIOPorts() { 396 void OmxVideoDecodeAccelerator::FlushIOPorts() {
(...skipping 21 matching lines...) Expand all
420 DCHECK_EQ(message_loop_, MessageLoop::current()); 418 DCHECK_EQ(message_loop_, MessageLoop::current());
421 DCHECK_EQ(current_state_change_, NO_TRANSITION); 419 DCHECK_EQ(current_state_change_, NO_TRANSITION);
422 DCHECK_EQ(client_state_, OMX_StateExecuting); 420 DCHECK_EQ(client_state_, OMX_StateExecuting);
423 current_state_change_ = RESETTING; 421 current_state_change_ = RESETTING;
424 BeginTransitionToState(OMX_StatePause); 422 BeginTransitionToState(OMX_StatePause);
425 } 423 }
426 424
427 void OmxVideoDecodeAccelerator::Destroy() { 425 void OmxVideoDecodeAccelerator::Destroy() {
428 DCHECK_EQ(message_loop_, MessageLoop::current()); 426 DCHECK_EQ(message_loop_, MessageLoop::current());
429 DCHECK_EQ(current_state_change_, NO_TRANSITION); 427 DCHECK_EQ(current_state_change_, NO_TRANSITION);
428 // If we were never initializeed there's no teardown to do.
429 if (client_state_ == OMX_StateMax)
430 return;
431 // If we can already call OMX_FreeHandle, simply do so.
432 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateLoaded) {
433 ShutdownComponent();
434 return;
435 }
430 DCHECK_EQ(client_state_, OMX_StateExecuting); 436 DCHECK_EQ(client_state_, OMX_StateExecuting);
431 current_state_change_ = DESTROYING; 437 current_state_change_ = DESTROYING;
438 client_ = NULL;
vhiremath 2011/07/14 14:29:15 Do we really want to do it here ? What if OVDA has
Ami GONE FROM CHROMIUM 2011/07/14 16:23:03 It is incorrect to call Destroy() while a Reset()
432 BeginTransitionToState(OMX_StateIdle); 439 BeginTransitionToState(OMX_StateIdle);
440 BusyLoopInDestroying();
433 } 441 }
434 442
435 void OmxVideoDecodeAccelerator::BeginTransitionToState( 443 void OmxVideoDecodeAccelerator::BeginTransitionToState(
436 OMX_STATETYPE new_state) { 444 OMX_STATETYPE new_state) {
437 DCHECK_EQ(message_loop_, MessageLoop::current()); 445 DCHECK_EQ(message_loop_, MessageLoop::current());
438 DCHECK_NE(current_state_change_, NO_TRANSITION); 446 DCHECK_NE(current_state_change_, NO_TRANSITION);
447 DCHECK_NE(current_state_change_, ERRORING);
448 if (current_state_change_ == NO_TRANSITION ||
449 current_state_change_ == ERRORING) {
450 return;
451 }
439 OMX_ERRORTYPE result = OMX_SendCommand( 452 OMX_ERRORTYPE result = OMX_SendCommand(
440 component_handle_, OMX_CommandStateSet, new_state, 0); 453 component_handle_, OMX_CommandStateSet, new_state, 0);
441 RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed", 454 RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed",
442 VIDEODECODERERROR_INVALIDINPUT,); 455 VIDEODECODERERROR_INVALIDINPUT,);
443 } 456 }
444 457
445 void OmxVideoDecodeAccelerator::OnReachedIdleInInitializing() { 458 void OmxVideoDecodeAccelerator::OnReachedIdleInInitializing() {
446 DCHECK_EQ(client_state_, OMX_StateLoaded); 459 DCHECK_EQ(client_state_, OMX_StateLoaded);
447 client_state_ = OMX_StateIdle; 460 client_state_ = OMX_StateIdle;
448 BeginTransitionToState(OMX_StateExecuting); 461 BeginTransitionToState(OMX_StateExecuting);
449 } 462 }
450 463
451 void OmxVideoDecodeAccelerator::OnReachedExecutingInInitializing() { 464 void OmxVideoDecodeAccelerator::OnReachedExecutingInInitializing() {
452 DCHECK_EQ(client_state_, OMX_StateIdle); 465 DCHECK_EQ(client_state_, OMX_StateIdle);
453 client_state_ = OMX_StateExecuting; 466 client_state_ = OMX_StateExecuting;
454 current_state_change_ = NO_TRANSITION; 467 current_state_change_ = NO_TRANSITION;
455 468
456 // Request filling of our fake buffers to trigger decode processing. In 469 // Request filling of our fake buffers to trigger decode processing. In
457 // reality as soon as any data is decoded these will get dismissed due to 470 // reality as soon as any data is decoded these will get dismissed due to
458 // dimension mismatch. 471 // dimension mismatch.
459 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it = 472 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it =
460 fake_output_buffers_.begin(); 473 fake_output_buffers_.begin();
461 it != fake_output_buffers_.end(); ++it) { 474 it != fake_output_buffers_.end(); ++it) {
462 OMX_BUFFERHEADERTYPE* buffer = *it; 475 OMX_BUFFERHEADERTYPE* buffer = *it;
463 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer); 476 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer);
464 RETURN_ON_OMX_FAILURE(result, 477 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer()",
465 "OMX_FillThisBuffer() failed with: " << result,
466 VIDEODECODERERROR_INVALIDINPUT,); 478 VIDEODECODERERROR_INVALIDINPUT,);
467 ++output_buffers_at_component_; 479 ++output_buffers_at_component_;
468 } 480 }
469 481
470 client_->NotifyInitializeDone(); 482 if (client_)
483 client_->NotifyInitializeDone();
471 } 484 }
472 485
473 void OmxVideoDecodeAccelerator::OnReachedPauseInFlushing() { 486 void OmxVideoDecodeAccelerator::OnReachedPauseInFlushing() {
474 DCHECK_EQ(client_state_, OMX_StateExecuting); 487 DCHECK_EQ(client_state_, OMX_StateExecuting);
475 client_state_ = OMX_StatePause; 488 client_state_ = OMX_StatePause;
476 FlushIOPorts(); 489 FlushIOPorts();
477 } 490 }
478 491
479 void OmxVideoDecodeAccelerator::OnReachedExecutingInFlushing() { 492 void OmxVideoDecodeAccelerator::OnReachedExecutingInFlushing() {
480 DCHECK_EQ(client_state_, OMX_StatePause); 493 DCHECK_EQ(client_state_, OMX_StatePause);
481 client_state_ = OMX_StateExecuting; 494 client_state_ = OMX_StateExecuting;
482 DCHECK(saw_eos_during_flush_); 495 DCHECK(saw_eos_during_flush_);
483 saw_eos_during_flush_ = false; 496 saw_eos_during_flush_ = false;
484 current_state_change_ = NO_TRANSITION; 497 current_state_change_ = NO_TRANSITION;
485 client_->NotifyFlushDone(); 498 if (client_)
499 client_->NotifyFlushDone();
486 } 500 }
487 501
488 void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() { 502 void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() {
489 DCHECK_EQ(client_state_, OMX_StateExecuting); 503 DCHECK_EQ(client_state_, OMX_StateExecuting);
490 client_state_ = OMX_StatePause; 504 client_state_ = OMX_StatePause;
491 FlushIOPorts(); 505 FlushIOPorts();
492 } 506 }
493 507
494 void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() { 508 void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() {
495 DCHECK_EQ(client_state_, OMX_StatePause); 509 DCHECK_EQ(client_state_, OMX_StatePause);
496 client_state_ = OMX_StateExecuting; 510 client_state_ = OMX_StateExecuting;
497 current_state_change_ = NO_TRANSITION; 511 current_state_change_ = NO_TRANSITION;
498 client_->NotifyResetDone(); 512 if (client_)
513 client_->NotifyResetDone();
514 }
515
516 // Alert: HORROR ahead! OMX shutdown is an asynchronous dance but our clients
517 // enjoy the fire-and-forget nature of a synchronous Destroy() call that
518 // ensures no further callbacks are made. Since the interface between OMX
519 // callbacks and this class is a MessageLoop, we need to ensure the loop
520 // outlives the shutdown dance, even during process shutdown. We do this by
521 // repeatedly enqueuing a no-op task until shutdown is complete, since
522 // MessageLoop's shutdown drains pending tasks.
523 void OmxVideoDecodeAccelerator::BusyLoopInDestroying() {
524 if (!component_handle_) return;
525 // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed
526 // tasks. Instead we sleep for 5ms. Really.
527 base::PlatformThread::Sleep(5);
vhiremath 2011/07/14 14:29:15 Why do we want to delay PostTask here ? May cause
Ami GONE FROM CHROMIUM 2011/07/14 16:23:03 To reduce the CPU load of what otherwise would be
528 message_loop_->PostTask(
529 FROM_HERE, NewRunnableMethod(
530 this, &OmxVideoDecodeAccelerator::BusyLoopInDestroying));
499 } 531 }
vhiremath 2011/07/14 14:29:15 Please explain how this logic works. Note: We have
Ami GONE FROM CHROMIUM 2011/07/14 16:23:03 I think so. The purpose of this method is simple:
500 532
501 void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() { 533 void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() {
502 DCHECK_EQ(client_state_, OMX_StateExecuting); 534 DCHECK_EQ(client_state_, OMX_StateExecuting);
503 client_state_ = OMX_StateIdle; 535 client_state_ = OMX_StateIdle;
504 536
505 // Note that during the Executing -> Idle transition, the OMX spec guarantees 537 // Note that during the Executing -> Idle transition, the OMX spec guarantees
506 // buffers have been returned to the client, so we don't need to do an 538 // buffers have been returned to the client, so we don't need to do an
507 // explicit FlushIOPorts(). 539 // explicit FlushIOPorts().
508 540
509 BeginTransitionToState(OMX_StateLoaded); 541 BeginTransitionToState(OMX_StateLoaded);
510 542
511 // TODO(fischman): evaluate what these conditionals are doing. What happens 543 // TODO(fischman): evaluate what these conditionals are doing. What happens
512 // if they're false?? 544 // if they're false??
513 if (!input_buffers_at_component_) 545 if (!input_buffers_at_component_)
514 FreeInputBuffers(); 546 FreeInputBuffers();
515 if (!output_buffers_at_component_) 547 if (!output_buffers_at_component_)
516 FreeOutputBuffers(); 548 FreeOutputBuffers();
517 }
518 549
519 void OmxVideoDecodeAccelerator::ShutdownComponent() { 550 BusyLoopInDestroying();
520 OMX_ERRORTYPE result = omx_free_handle(component_handle_);
521 if (result != OMX_ErrorNone)
522 LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result;
523 component_handle_ = NULL;
524 omx_deinit();
525 client_state_ = OMX_StateMax;
526 } 551 }
527 552
528 void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() { 553 void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() {
529 DCHECK_EQ(client_state_, OMX_StateIdle); 554 DCHECK_EQ(client_state_, OMX_StateIdle);
530 client_state_ = OMX_StateLoaded; 555 client_state_ = OMX_StateLoaded;
531 current_state_change_ = NO_TRANSITION; 556 current_state_change_ = NO_TRANSITION;
532 ShutdownComponent(); 557 ShutdownComponent();
533 client_->NotifyDestroyDone();
534 } 558 }
535 559
536 void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() { 560 void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() {
537 client_state_ = OMX_StateInvalid; 561 client_state_ = OMX_StateInvalid;
538 ShutdownComponent(); 562 ShutdownComponent();
539 } 563 }
540 564
565 void OmxVideoDecodeAccelerator::ShutdownComponent() {
566 OMX_ERRORTYPE result = omx_free_handle(component_handle_);
567 if (result != OMX_ErrorNone)
568 LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result;
569 component_handle_ = NULL;
570 client_state_ = OMX_StateMax;
571 // This Release() call must happen *after* any access to |*this| because it
572 // might result in |this| being deleted.
573 Release(); // Since OMX no longer has |this| to call back to.
574 omx_deinit();
575 }
576
541 void OmxVideoDecodeAccelerator::StopOnError( 577 void OmxVideoDecodeAccelerator::StopOnError(
542 media::VideoDecodeAccelerator::Error error) { 578 media::VideoDecodeAccelerator::Error error) {
543 DCHECK_EQ(message_loop_, MessageLoop::current()); 579 DCHECK_EQ(message_loop_, MessageLoop::current());
544 current_state_change_ = ERRORING;
545 580
546 client_->NotifyError(error); 581 if (client_)
582 client_->NotifyError(error);
547 583
548 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax) 584 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax)
549 return; 585 return;
550 586
551 BeginTransitionToState(OMX_StateInvalid); 587 BeginTransitionToState(OMX_StateInvalid);
588 current_state_change_ = ERRORING;
552 } 589 }
553 590
554 bool OmxVideoDecodeAccelerator::AllocateInputBuffers() { 591 bool OmxVideoDecodeAccelerator::AllocateInputBuffers() {
555 DCHECK_EQ(message_loop_, MessageLoop::current()); 592 DCHECK_EQ(message_loop_, MessageLoop::current());
556 for (int i = 0; i < input_buffer_count_; ++i) { 593 for (int i = 0; i < input_buffer_count_; ++i) {
557 OMX_BUFFERHEADERTYPE* buffer; 594 OMX_BUFFERHEADERTYPE* buffer;
558 // While registering the buffer header we use fake buffer information 595 // While registering the buffer header we use fake buffer information
559 // (length 0, at memory address 0x1) to fake out the "safety" check in 596 // (length 0, at memory address 0x1) to fake out the "safety" check in
560 // OMX_UseBuffer. When it comes time to actually use this header in Decode 597 // OMX_UseBuffer. When it comes time to actually use this header in Decode
561 // we set these fields to their real values (for the duration of that 598 // we set these fields to their real values (for the duration of that
(...skipping 20 matching lines...) Expand all
582 gfx::Size decoded_pixel_size(pictures_.begin()->second.gles_buffer.size()); 619 gfx::Size decoded_pixel_size(pictures_.begin()->second.gles_buffer.size());
583 gfx::Size visible_pixel_size(pictures_.begin()->second.gles_buffer.size()); 620 gfx::Size visible_pixel_size(pictures_.begin()->second.gles_buffer.size());
584 for (OutputPictureById::iterator it = pictures_.begin(); 621 for (OutputPictureById::iterator it = pictures_.begin();
585 it != pictures_.end(); ++it) { 622 it != pictures_.end(); ++it) {
586 media::GLESBuffer& gles_buffer = it->second.gles_buffer; 623 media::GLESBuffer& gles_buffer = it->second.gles_buffer;
587 OMX_BUFFERHEADERTYPE** omx_buffer = &it->second.omx_buffer_header; 624 OMX_BUFFERHEADERTYPE** omx_buffer = &it->second.omx_buffer_header;
588 DCHECK(!*omx_buffer); 625 DCHECK(!*omx_buffer);
589 OMX_ERRORTYPE result = OMX_UseEGLImage( 626 OMX_ERRORTYPE result = OMX_UseEGLImage(
590 component_handle_, omx_buffer, output_port_, &gles_buffer, 627 component_handle_, omx_buffer, output_port_, &gles_buffer,
591 it->second.egl_image); 628 it->second.egl_image);
592 RETURN_ON_OMX_FAILURE(result, "OMX_UseEGLImage failed with: " << result, 629 RETURN_ON_OMX_FAILURE(result, "OMX_UseEGLImage",
593 VIDEODECODERERROR_MEMFAILURE, false); 630 VIDEODECODERERROR_MEMFAILURE, false);
594 // Here we set a garbage bitstream buffer id, and then overwrite it before 631 // Here we set a garbage bitstream buffer id, and then overwrite it before
595 // passing to PictureReady. 632 // passing to PictureReady.
596 int garbage_bitstream_buffer_id = -1; 633 int garbage_bitstream_buffer_id = -1;
597 (*omx_buffer)->pAppPrivate = 634 (*omx_buffer)->pAppPrivate =
598 new media::Picture(gles_buffer.id(), garbage_bitstream_buffer_id, 635 new media::Picture(gles_buffer.id(), garbage_bitstream_buffer_id,
599 decoded_pixel_size, visible_pixel_size); 636 decoded_pixel_size, visible_pixel_size);
600 } 637 }
601 return true; 638 return true;
602 } 639 }
603 640
604 void OmxVideoDecodeAccelerator::FreeInputBuffers() { 641 void OmxVideoDecodeAccelerator::FreeInputBuffers() {
605 DCHECK_EQ(message_loop_, MessageLoop::current()); 642 DCHECK_EQ(message_loop_, MessageLoop::current());
606 // Calls to OMX to free buffers. 643 // Calls to OMX to free buffers.
607 OMX_ERRORTYPE result; 644 OMX_ERRORTYPE result;
608 OMX_BUFFERHEADERTYPE* omx_buffer; 645 OMX_BUFFERHEADERTYPE* omx_buffer;
609 while (!free_input_buffers_.empty()) { 646 while (!free_input_buffers_.empty()) {
610 omx_buffer = free_input_buffers_.front(); 647 omx_buffer = free_input_buffers_.front();
611 free_input_buffers_.pop(); 648 free_input_buffers_.pop();
612 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer); 649 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer);
613 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, 650 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer",
614 VIDEODECODERERROR_INVALIDINPUT,); 651 VIDEODECODERERROR_INVALIDINPUT,);
615 } 652 }
616 VLOG(1) << "Input buffers freed.";
617 } 653 }
618 654
619 void OmxVideoDecodeAccelerator::FreeOutputBuffers() { 655 void OmxVideoDecodeAccelerator::FreeOutputBuffers() {
620 DCHECK_EQ(message_loop_, MessageLoop::current()); 656 DCHECK_EQ(message_loop_, MessageLoop::current());
621 // Calls to OMX to free buffers. 657 // Calls to OMX to free buffers.
622 OMX_ERRORTYPE result; 658 OMX_ERRORTYPE result;
623 static Gles2TextureToEglImageTranslator texture2eglImage_translator; 659 static Gles2TextureToEglImageTranslator texture2eglImage_translator;
624 for (OutputPictureById::iterator it = pictures_.begin(); 660 for (OutputPictureById::iterator it = pictures_.begin();
625 it != pictures_.end(); ++it) { 661 it != pictures_.end(); ++it) {
626 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; 662 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header;
627 CHECK(omx_buffer); 663 CHECK(omx_buffer);
628 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); 664 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate);
629 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); 665 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer);
630 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, 666 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer",
631 VIDEODECODERERROR_INVALIDINPUT,); 667 VIDEODECODERERROR_INVALIDINPUT,);
632 texture2eglImage_translator.DestroyEglImage(egl_display_, 668 texture2eglImage_translator.DestroyEglImage(egl_display_,
633 it->second.egl_image); 669 it->second.egl_image);
634 client_->DismissPictureBuffer(it->first); 670 if (client_)
671 client_->DismissPictureBuffer(it->first);
635 } 672 }
636 pictures_.clear(); 673 pictures_.clear();
637 } 674 }
638 675
639 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { 676 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() {
640 DCHECK_EQ(message_loop_, MessageLoop::current()); 677 DCHECK_EQ(message_loop_, MessageLoop::current());
641 OMX_PARAM_PORTDEFINITIONTYPE port_format; 678 OMX_PARAM_PORTDEFINITIONTYPE port_format;
642 InitParam(*this, &port_format); 679 InitParam(*this, &port_format);
643 port_format.nPortIndex = output_port_; 680 port_format.nPortIndex = output_port_;
644 OMX_ERRORTYPE result = OMX_GetParameter( 681 OMX_ERRORTYPE result = OMX_GetParameter(
645 component_handle_, OMX_IndexParamPortDefinition, &port_format); 682 component_handle_, OMX_IndexParamPortDefinition, &port_format);
646 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter failed with: " << result, 683 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter",
647 VIDEODECODERERROR_UNSUPPORTED,); 684 VIDEODECODERERROR_UNSUPPORTED,);
648 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers); 685 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers);
649 686
650 // TODO(fischman): to support mid-stream resize, need to free/dismiss any 687 // TODO(fischman): to support mid-stream resize, need to free/dismiss any
651 // |pictures_| we already have. Make sure that the shutdown-path agrees with 688 // |pictures_| we already have. Make sure that the shutdown-path agrees with
652 // this (there's already freeing logic there, which should not be duplicated). 689 // this (there's already freeing logic there, which should not be duplicated).
653 690
654 // Request picture buffers to be handed to the component. 691 // Request picture buffers to be handed to the component.
655 // ProvidePictureBuffers() will trigger AssignGLESBuffers, which ultimately 692 // ProvidePictureBuffers() will trigger AssignGLESBuffers, which ultimately
656 // assigns the textures to the component and re-enables the port. 693 // assigns the textures to the component and re-enables the port.
657 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; 694 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video;
658 client_->ProvidePictureBuffers( 695 if (client_) {
659 kNumPictureBuffers, 696 client_->ProvidePictureBuffers(
660 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight), 697 kNumPictureBuffers,
661 PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE); 698 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight),
699 PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE);
700 }
662 } 701 }
663 702
664 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { 703 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() {
665 DCHECK_EQ(message_loop_, MessageLoop::current()); 704 DCHECK_EQ(message_loop_, MessageLoop::current());
666 705
667 if (!CanFillBuffer()) { 706 if (!CanFillBuffer()) {
668 StopOnError(VIDEODECODERERROR_UNSUPPORTED); // Should be STATE_ERROR. 707 StopOnError(VIDEODECODERERROR_UNSUPPORTED); // Should be STATE_ERROR.
669 return; 708 return;
670 } 709 }
671 710
672 // Provide output buffers to decoder. 711 // Provide output buffers to decoder.
673 for (OutputPictureById::iterator it = pictures_.begin(); 712 for (OutputPictureById::iterator it = pictures_.begin();
674 it != pictures_.end(); ++it) { 713 it != pictures_.end(); ++it) {
675 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; 714 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header;
676 DCHECK(omx_buffer); 715 DCHECK(omx_buffer);
677 // Clear EOS flag. 716 // Clear EOS flag.
678 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; 717 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
679 omx_buffer->nOutputPortIndex = output_port_; 718 omx_buffer->nOutputPortIndex = output_port_;
680 ++output_buffers_at_component_; 719 ++output_buffers_at_component_;
681 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer); 720 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer);
682 RETURN_ON_OMX_FAILURE(result, 721 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed",
683 "OMX_FillThisBuffer() failed with result " << result,
684 VIDEODECODERERROR_INSUFFICIENT_BUFFERS,); 722 VIDEODECODERERROR_INSUFFICIENT_BUFFERS,);
685 } 723 }
686 } 724 }
687 725
688 void OmxVideoDecodeAccelerator::FillBufferDoneTask( 726 void OmxVideoDecodeAccelerator::FillBufferDoneTask(
689 OMX_BUFFERHEADERTYPE* buffer) { 727 OMX_BUFFERHEADERTYPE* buffer) {
690 DCHECK_EQ(message_loop_, MessageLoop::current()); 728 DCHECK_EQ(message_loop_, MessageLoop::current());
691 DCHECK_GT(output_buffers_at_component_, 0); 729 DCHECK_GT(output_buffers_at_component_, 0);
692 --output_buffers_at_component_; 730 --output_buffers_at_component_;
693 731
694 if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) { 732 if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) {
695 CHECK_EQ(fake_output_buffers_.erase(buffer), 1U); 733 CHECK_EQ(fake_output_buffers_.erase(buffer), 1U);
696 OMX_ERRORTYPE result = 734 OMX_ERRORTYPE result =
697 OMX_FreeBuffer(component_handle_, output_port_, buffer); 735 OMX_FreeBuffer(component_handle_, output_port_, buffer);
698 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, 736 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed",
699 VIDEODECODERERROR_INVALIDINPUT,); 737 VIDEODECODERERROR_INVALIDINPUT,);
700 return; 738 return;
701 } 739 }
702 CHECK(!fake_output_buffers_.size()); 740 CHECK(!fake_output_buffers_.size());
703 741
704 if (current_state_change_ == FLUSHING && 742 if (current_state_change_ == FLUSHING &&
705 buffer->nFlags & OMX_BUFFERFLAG_EOS) { 743 buffer->nFlags & OMX_BUFFERFLAG_EOS) {
706 DCHECK(!saw_eos_during_flush_); 744 DCHECK(!saw_eos_during_flush_);
707 saw_eos_during_flush_ = true; 745 saw_eos_during_flush_ = true;
708 } 746 }
709 747
710 // During the transition from Executing to Idle, and during port-flushing, all 748 // During the transition from Executing to Idle, and during port-flushing, all
711 // pictures are sent back through here. Avoid giving them to the client. 749 // pictures are sent back through here. Avoid giving them to the client.
712 // Also avoid sending the (fake) EOS buffer to the client. 750 // Also avoid sending the (fake) EOS buffer to the client.
713 if ((current_state_change_ != NO_TRANSITION && 751 if ((current_state_change_ != NO_TRANSITION &&
714 current_state_change_ != FLUSHING) || 752 current_state_change_ != FLUSHING) ||
715 saw_eos_during_flush_) { 753 saw_eos_during_flush_) {
716 return; 754 return;
717 } 755 }
718 756
719 CHECK(buffer->pAppPrivate); 757 CHECK(buffer->pAppPrivate);
720 media::Picture* picture = 758 media::Picture* picture =
721 reinterpret_cast<media::Picture*>(buffer->pAppPrivate); 759 reinterpret_cast<media::Picture*>(buffer->pAppPrivate);
722 // See Decode() for an explanation of this abuse of nTimeStamp. 760 // See Decode() for an explanation of this abuse of nTimeStamp.
723 picture->set_bitstream_buffer_id(buffer->nTimeStamp); 761 picture->set_bitstream_buffer_id(buffer->nTimeStamp);
724 client_->PictureReady(*picture); 762 if (client_)
763 client_->PictureReady(*picture);
725 } 764 }
726 765
727 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( 766 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask(
728 OMX_BUFFERHEADERTYPE* buffer) { 767 OMX_BUFFERHEADERTYPE* buffer) {
729 DCHECK_EQ(message_loop_, MessageLoop::current()); 768 DCHECK_EQ(message_loop_, MessageLoop::current());
730 DCHECK_GT(input_buffers_at_component_, 0); 769 DCHECK_GT(input_buffers_at_component_, 0);
731 free_input_buffers_.push(buffer); 770 free_input_buffers_.push(buffer);
732 input_buffers_at_component_--; 771 input_buffers_at_component_--;
733 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) 772 if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
734 return; 773 return;
735 774
736 // Retrieve the corresponding BitstreamBuffer's id and notify the client of 775 // Retrieve the corresponding BitstreamBuffer's id and notify the client of
737 // its completion. 776 // its completion.
738 SharedMemoryAndId* input_buffer_details = 777 SharedMemoryAndId* input_buffer_details =
739 reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate); 778 reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate);
740 DCHECK(input_buffer_details); 779 DCHECK(input_buffer_details);
741 buffer->pAppPrivate = NULL; 780 buffer->pAppPrivate = NULL;
742 client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second); 781 if (client_)
782 client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second);
743 delete input_buffer_details; 783 delete input_buffer_details;
744 } 784 }
745 785
746 void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) { 786 void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) {
747 DCHECK_EQ(message_loop_, MessageLoop::current()); 787 DCHECK_EQ(message_loop_, MessageLoop::current());
748 switch (current_state_change_) { 788 switch (current_state_change_) {
749 case INITIALIZING: 789 case INITIALIZING:
750 switch (reached) { 790 switch (reached) {
751 case OMX_StateIdle: 791 case OMX_StateIdle:
752 OnReachedIdleInInitializing(); 792 OnReachedIdleInInitializing();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 NOTREACHED() << "Unexpected state in " << current_state_change_ 834 NOTREACHED() << "Unexpected state in " << current_state_change_
795 << ": " << reached; 835 << ": " << reached;
796 } 836 }
797 } 837 }
798 838
799 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, 839 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event,
800 OMX_U32 data1, 840 OMX_U32 data1,
801 OMX_U32 data2) { 841 OMX_U32 data2) {
802 DCHECK_EQ(message_loop_, MessageLoop::current()); 842 DCHECK_EQ(message_loop_, MessageLoop::current());
803 switch (event) { 843 switch (event) {
804 case OMX_EventCmdComplete: { 844 case OMX_EventCmdComplete:
805 // If the last command was successful, we have completed 845 switch (data1) {
806 // a state transition. So notify that we have done it
807 // accordingly.
808 OMX_COMMANDTYPE cmd = static_cast<OMX_COMMANDTYPE>(data1);
809 switch (cmd) {
810 case OMX_CommandPortDisable: 846 case OMX_CommandPortDisable:
811 DCHECK_EQ(data2, output_port_); 847 DCHECK_EQ(data2, output_port_);
812 OnOutputPortDisabled(); 848 OnOutputPortDisabled();
813 break; 849 return;
814 case OMX_CommandPortEnable: 850 case OMX_CommandPortEnable:
815 DCHECK_EQ(data2, output_port_); 851 DCHECK_EQ(data2, output_port_);
816 OnOutputPortEnabled(); 852 OnOutputPortEnabled();
817 break; 853 return;
818 case OMX_CommandStateSet: 854 case OMX_CommandStateSet:
819 DispatchStateReached(static_cast<OMX_STATETYPE>(data2)); 855 DispatchStateReached(static_cast<OMX_STATETYPE>(data2));
820 break; 856 return;
821 case OMX_CommandFlush: 857 case OMX_CommandFlush:
822 DCHECK(current_state_change_ == FLUSHING || 858 DCHECK(current_state_change_ == FLUSHING ||
823 current_state_change_ == RESETTING || 859 current_state_change_ == RESETTING ||
824 current_state_change_ == DESTROYING); 860 current_state_change_ == DESTROYING);
825 if (data2 == input_port_) 861 if (data2 == input_port_)
826 InputPortFlushDone(); 862 InputPortFlushDone();
827 else if (data2 == output_port_) 863 else if (data2 == output_port_)
828 OutputPortFlushDone(); 864 OutputPortFlushDone();
829 else 865 else
830 NOTREACHED() << "Unexpected port flushed: " << data2; 866 NOTREACHED() << "Unexpected port flushed: " << data2;
831 break; 867 return;
832 default: 868 default:
833 RETURN_ON_FAILURE(false, "Unknown command completed: " << data1, 869 RETURN_ON_FAILURE(false, "Unknown command completed: " << data1,
834 VIDEODECODERERROR_HARDWARE,); 870 VIDEODECODERERROR_HARDWARE,);
835 } 871 }
836 break; 872 return;
837 }
838 case OMX_EventError: 873 case OMX_EventError:
839 RETURN_ON_FAILURE(false, "EventError: " << data1, 874 if (current_state_change_ != DESTROYING &&
840 VIDEODECODERERROR_HARDWARE,); 875 current_state_change_ != ERRORING) {
876 RETURN_ON_FAILURE(false, "EventError: 0x" << std::hex << data1,
877 VIDEODECODERERROR_HARDWARE,);
878 }
879 return;
841 case OMX_EventPortSettingsChanged: 880 case OMX_EventPortSettingsChanged:
842 if (data2 == OMX_IndexParamPortDefinition) { 881 if (data2 == OMX_IndexParamPortDefinition) {
843 DCHECK_EQ(data1, output_port_); 882 DCHECK_EQ(data1, output_port_);
844 // This event is only used for output resize; kick off handling that by 883 // This event is only used for output resize; kick off handling that by
845 // pausing the output port. 884 // pausing the output port.
846 SendCommandToPort(OMX_CommandPortDisable, output_port_); 885 SendCommandToPort(OMX_CommandPortDisable, output_port_);
847 } else if (data1 == output_port_ && 886 } else if (data1 == output_port_ &&
848 data2 == OMX_IndexConfigCommonOutputCrop) { 887 data2 == OMX_IndexConfigCommonOutputCrop) {
849 // TODO(vjain): Handle video crop rect. 888 // TODO(vjain): Handle video crop rect.
850 } else { 889 } else {
851 RETURN_ON_FAILURE(false, 890 RETURN_ON_FAILURE(false,
852 "Unexpected EventPortSettingsChanged: " 891 "Unexpected EventPortSettingsChanged: "
853 << data1 << ", " << data2, 892 << data1 << ", " << data2,
854 VIDEODECODERERROR_HARDWARE,); 893 VIDEODECODERERROR_HARDWARE,);
855 } 894 }
856 break; 895 return;
857 case OMX_EventBufferFlag: 896 case OMX_EventBufferFlag:
858 if (data1 == output_port_) { 897 if (data1 == output_port_) {
859 DCHECK_EQ(current_state_change_, FLUSHING); 898 DCHECK_EQ(current_state_change_, FLUSHING);
860 OnReachedEOSInFlushing(); 899 OnReachedEOSInFlushing();
861 } else { 900 } else {
862 RETURN_ON_FAILURE(false, 901 RETURN_ON_FAILURE(false,
863 "Unexpected OMX_EventBufferFlag: " 902 "Unexpected OMX_EventBufferFlag: "
864 << data1 << ", " << data2, 903 << data1 << ", " << data2,
865 VIDEODECODERERROR_HARDWARE,); 904 VIDEODECODERERROR_HARDWARE,);
866 } 905 }
867 break; 906 return;
868 default: 907 default:
869 RETURN_ON_FAILURE(false, "Unexpected unhandled event: " << event, 908 RETURN_ON_FAILURE(false, "Unexpected unhandled event: " << event,
870 VIDEODECODERERROR_HARDWARE,); 909 VIDEODECODERERROR_HARDWARE,);
871 } 910 }
872 } 911 }
873 912
874 // static 913 // static
875 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, 914 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component,
876 OMX_PTR priv_data, 915 OMX_PTR priv_data,
877 OMX_EVENTTYPE event, 916 OMX_EVENTTYPE event,
878 OMX_U32 data1, 917 OMX_U32 data1,
879 OMX_U32 data2, 918 OMX_U32 data2,
880 OMX_PTR event_data) { 919 OMX_PTR event_data) {
881 // Called on the OMX thread. 920 // Called on the OMX thread.
882 OmxVideoDecodeAccelerator* decoder = 921 OmxVideoDecodeAccelerator* decoder =
883 static_cast<OmxVideoDecodeAccelerator*>(priv_data); 922 static_cast<OmxVideoDecodeAccelerator*>(priv_data);
884 DCHECK_EQ(component, decoder->component_handle_); 923 DCHECK_EQ(component, decoder->component_handle_);
885 decoder->message_loop_->PostTask( 924 decoder->message_loop_->PostTask(
886 FROM_HERE, 925 FROM_HERE, NewRunnableMethod(
887 NewRunnableMethod(decoder, 926 decoder, &OmxVideoDecodeAccelerator::EventHandlerCompleteTask,
888 &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, 927 event, data1, data2));
889 event, data1, data2));
890 return OMX_ErrorNone; 928 return OMX_ErrorNone;
891 } 929 }
892 930
893 // static 931 // static
894 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback( 932 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback(
895 OMX_HANDLETYPE component, 933 OMX_HANDLETYPE component,
896 OMX_PTR priv_data, 934 OMX_PTR priv_data,
897 OMX_BUFFERHEADERTYPE* buffer) { 935 OMX_BUFFERHEADERTYPE* buffer) {
898 // Called on the OMX thread. 936 // Called on the OMX thread.
899 OmxVideoDecodeAccelerator* decoder = 937 OmxVideoDecodeAccelerator* decoder =
(...skipping 19 matching lines...) Expand all
919 decoder->message_loop_->PostTask( 957 decoder->message_loop_->PostTask(
920 FROM_HERE, 958 FROM_HERE,
921 NewRunnableMethod(decoder, 959 NewRunnableMethod(decoder,
922 &OmxVideoDecodeAccelerator::FillBufferDoneTask, 960 &OmxVideoDecodeAccelerator::FillBufferDoneTask,
923 buffer)); 961 buffer));
924 return OMX_ErrorNone; 962 return OMX_ErrorNone;
925 } 963 }
926 964
927 bool OmxVideoDecodeAccelerator::CanFillBuffer() { 965 bool OmxVideoDecodeAccelerator::CanFillBuffer() {
928 DCHECK_EQ(message_loop_, MessageLoop::current()); 966 DCHECK_EQ(message_loop_, MessageLoop::current());
967 if (current_state_change_ == DESTROYING ||
968 current_state_change_ == ERRORING) {
969 return false;
970 }
929 return client_state_ == OMX_StateIdle || 971 return client_state_ == OMX_StateIdle ||
930 client_state_ == OMX_StateExecuting || 972 client_state_ == OMX_StateExecuting ||
931 client_state_ == OMX_StatePause; 973 client_state_ == OMX_StatePause;
932 } 974 }
933 975
934 bool OmxVideoDecodeAccelerator::SendCommandToPort( 976 bool OmxVideoDecodeAccelerator::SendCommandToPort(
935 OMX_COMMANDTYPE cmd, int port_index) { 977 OMX_COMMANDTYPE cmd, int port_index) {
936 DCHECK_EQ(message_loop_, MessageLoop::current()); 978 DCHECK_EQ(message_loop_, MessageLoop::current());
937 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, 979 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_,
938 cmd, port_index, 0); 980 cmd, port_index, 0);
939 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd << ":" << result, 981 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd,
940 VIDEODECODERERROR_INVALIDINPUT, false); 982 VIDEODECODERERROR_INVALIDINPUT, false);
941 return true; 983 return true;
942 } 984 }
943
944 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698