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

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: vrk CR responses. 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 20 matching lines...) Expand all
419 void OmxVideoDecodeAccelerator::Reset() { 417 void OmxVideoDecodeAccelerator::Reset() {
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());
427 if (current_state_change_ == ERRORING)
428 return;
429 DCHECK_EQ(current_state_change_, NO_TRANSITION); 429 DCHECK_EQ(current_state_change_, NO_TRANSITION);
430 // If we were never initializeed there's no teardown to do.
431 if (client_state_ == OMX_StateMax)
432 return;
433 // If we can already call OMX_FreeHandle, simply do so.
434 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateLoaded) {
435 ShutdownComponent();
436 return;
437 }
430 DCHECK_EQ(client_state_, OMX_StateExecuting); 438 DCHECK_EQ(client_state_, OMX_StateExecuting);
431 current_state_change_ = DESTROYING; 439 current_state_change_ = DESTROYING;
440 client_ = NULL;
432 BeginTransitionToState(OMX_StateIdle); 441 BeginTransitionToState(OMX_StateIdle);
442 BusyLoopInDestroying();
433 } 443 }
434 444
435 void OmxVideoDecodeAccelerator::BeginTransitionToState( 445 void OmxVideoDecodeAccelerator::BeginTransitionToState(
436 OMX_STATETYPE new_state) { 446 OMX_STATETYPE new_state) {
437 DCHECK_EQ(message_loop_, MessageLoop::current()); 447 DCHECK_EQ(message_loop_, MessageLoop::current());
438 DCHECK_NE(current_state_change_, NO_TRANSITION); 448 DCHECK_NE(current_state_change_, NO_TRANSITION);
449 DCHECK_NE(current_state_change_, ERRORING);
450 if (current_state_change_ == NO_TRANSITION ||
451 current_state_change_ == ERRORING) {
452 return;
453 }
439 OMX_ERRORTYPE result = OMX_SendCommand( 454 OMX_ERRORTYPE result = OMX_SendCommand(
440 component_handle_, OMX_CommandStateSet, new_state, 0); 455 component_handle_, OMX_CommandStateSet, new_state, 0);
441 RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed", 456 RETURN_ON_OMX_FAILURE(result, "SendCommand(OMX_CommandStateSet) failed",
442 VIDEODECODERERROR_INVALIDINPUT,); 457 VIDEODECODERERROR_INVALIDINPUT,);
443 } 458 }
444 459
445 void OmxVideoDecodeAccelerator::OnReachedIdleInInitializing() { 460 void OmxVideoDecodeAccelerator::OnReachedIdleInInitializing() {
446 DCHECK_EQ(client_state_, OMX_StateLoaded); 461 DCHECK_EQ(client_state_, OMX_StateLoaded);
447 client_state_ = OMX_StateIdle; 462 client_state_ = OMX_StateIdle;
448 BeginTransitionToState(OMX_StateExecuting); 463 BeginTransitionToState(OMX_StateExecuting);
449 } 464 }
450 465
451 void OmxVideoDecodeAccelerator::OnReachedExecutingInInitializing() { 466 void OmxVideoDecodeAccelerator::OnReachedExecutingInInitializing() {
452 DCHECK_EQ(client_state_, OMX_StateIdle); 467 DCHECK_EQ(client_state_, OMX_StateIdle);
453 client_state_ = OMX_StateExecuting; 468 client_state_ = OMX_StateExecuting;
454 current_state_change_ = NO_TRANSITION; 469 current_state_change_ = NO_TRANSITION;
455 470
456 // Request filling of our fake buffers to trigger decode processing. In 471 // 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 472 // reality as soon as any data is decoded these will get dismissed due to
458 // dimension mismatch. 473 // dimension mismatch.
459 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it = 474 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it =
460 fake_output_buffers_.begin(); 475 fake_output_buffers_.begin();
461 it != fake_output_buffers_.end(); ++it) { 476 it != fake_output_buffers_.end(); ++it) {
462 OMX_BUFFERHEADERTYPE* buffer = *it; 477 OMX_BUFFERHEADERTYPE* buffer = *it;
463 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer); 478 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer);
464 RETURN_ON_OMX_FAILURE(result, 479 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer()",
465 "OMX_FillThisBuffer() failed with: " << result,
466 VIDEODECODERERROR_INVALIDINPUT,); 480 VIDEODECODERERROR_INVALIDINPUT,);
467 ++output_buffers_at_component_; 481 ++output_buffers_at_component_;
468 } 482 }
469 483
470 client_->NotifyInitializeDone(); 484 if (client_)
485 client_->NotifyInitializeDone();
471 } 486 }
472 487
473 void OmxVideoDecodeAccelerator::OnReachedPauseInFlushing() { 488 void OmxVideoDecodeAccelerator::OnReachedPauseInFlushing() {
474 DCHECK_EQ(client_state_, OMX_StateExecuting); 489 DCHECK_EQ(client_state_, OMX_StateExecuting);
475 client_state_ = OMX_StatePause; 490 client_state_ = OMX_StatePause;
476 FlushIOPorts(); 491 FlushIOPorts();
477 } 492 }
478 493
479 void OmxVideoDecodeAccelerator::OnReachedExecutingInFlushing() { 494 void OmxVideoDecodeAccelerator::OnReachedExecutingInFlushing() {
480 DCHECK_EQ(client_state_, OMX_StatePause); 495 DCHECK_EQ(client_state_, OMX_StatePause);
481 client_state_ = OMX_StateExecuting; 496 client_state_ = OMX_StateExecuting;
482 DCHECK(saw_eos_during_flush_); 497 DCHECK(saw_eos_during_flush_);
483 saw_eos_during_flush_ = false; 498 saw_eos_during_flush_ = false;
484 current_state_change_ = NO_TRANSITION; 499 current_state_change_ = NO_TRANSITION;
485 client_->NotifyFlushDone(); 500 if (client_)
501 client_->NotifyFlushDone();
486 } 502 }
487 503
488 void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() { 504 void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() {
489 DCHECK_EQ(client_state_, OMX_StateExecuting); 505 DCHECK_EQ(client_state_, OMX_StateExecuting);
490 client_state_ = OMX_StatePause; 506 client_state_ = OMX_StatePause;
491 FlushIOPorts(); 507 FlushIOPorts();
492 } 508 }
493 509
494 void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() { 510 void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() {
495 DCHECK_EQ(client_state_, OMX_StatePause); 511 DCHECK_EQ(client_state_, OMX_StatePause);
496 client_state_ = OMX_StateExecuting; 512 client_state_ = OMX_StateExecuting;
497 current_state_change_ = NO_TRANSITION; 513 current_state_change_ = NO_TRANSITION;
498 client_->NotifyResetDone(); 514 if (client_)
515 client_->NotifyResetDone();
516 }
517
518 // Alert: HORROR ahead! OMX shutdown is an asynchronous dance but our clients
519 // enjoy the fire-and-forget nature of a synchronous Destroy() call that
520 // ensures no further callbacks are made. Since the interface between OMX
521 // callbacks and this class is a MessageLoop, we need to ensure the loop
522 // outlives the shutdown dance, even during process shutdown. We do this by
523 // repeatedly enqueuing a no-op task until shutdown is complete, since
524 // MessageLoop's shutdown drains pending tasks.
525 void OmxVideoDecodeAccelerator::BusyLoopInDestroying() {
526 if (!component_handle_) return;
527 // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed
528 // tasks. Instead we sleep for 5ms. Really.
529 base::PlatformThread::Sleep(5);
530 message_loop_->PostTask(
531 FROM_HERE, NewRunnableMethod(
532 this, &OmxVideoDecodeAccelerator::BusyLoopInDestroying));
499 } 533 }
500 534
501 void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() { 535 void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() {
502 DCHECK_EQ(client_state_, OMX_StateExecuting); 536 DCHECK_EQ(client_state_, OMX_StateExecuting);
503 client_state_ = OMX_StateIdle; 537 client_state_ = OMX_StateIdle;
504 538
505 // Note that during the Executing -> Idle transition, the OMX spec guarantees 539 // 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 540 // buffers have been returned to the client, so we don't need to do an
507 // explicit FlushIOPorts(). 541 // explicit FlushIOPorts().
508 542
509 BeginTransitionToState(OMX_StateLoaded); 543 BeginTransitionToState(OMX_StateLoaded);
510 544
511 // TODO(fischman): evaluate what these conditionals are doing. What happens 545 // TODO(fischman): evaluate what these conditionals are doing. What happens
512 // if they're false?? 546 // if they're false??
513 if (!input_buffers_at_component_) 547 if (!input_buffers_at_component_)
514 FreeInputBuffers(); 548 FreeInputBuffers();
515 if (!output_buffers_at_component_) 549 if (!output_buffers_at_component_)
516 FreeOutputBuffers(); 550 FreeOutputBuffers();
517 }
518 551
519 void OmxVideoDecodeAccelerator::ShutdownComponent() { 552 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 } 553 }
527 554
528 void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() { 555 void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() {
529 DCHECK_EQ(client_state_, OMX_StateIdle); 556 DCHECK_EQ(client_state_, OMX_StateIdle);
530 client_state_ = OMX_StateLoaded; 557 client_state_ = OMX_StateLoaded;
531 current_state_change_ = NO_TRANSITION; 558 current_state_change_ = NO_TRANSITION;
532 ShutdownComponent(); 559 ShutdownComponent();
533 client_->NotifyDestroyDone();
534 } 560 }
535 561
536 void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() { 562 void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() {
537 client_state_ = OMX_StateInvalid; 563 client_state_ = OMX_StateInvalid;
538 ShutdownComponent(); 564 ShutdownComponent();
539 } 565 }
540 566
567 void OmxVideoDecodeAccelerator::ShutdownComponent() {
568 OMX_ERRORTYPE result = omx_free_handle(component_handle_);
569 if (result != OMX_ErrorNone)
570 LOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result;
571 component_handle_ = NULL;
572 client_state_ = OMX_StateMax;
573 // This Release() call must happen *after* any access to |*this| because it
574 // might result in |this| being deleted.
575 Release(); // Since OMX no longer has |this| to call back to.
576 omx_deinit();
577 }
578
541 void OmxVideoDecodeAccelerator::StopOnError( 579 void OmxVideoDecodeAccelerator::StopOnError(
542 media::VideoDecodeAccelerator::Error error) { 580 media::VideoDecodeAccelerator::Error error) {
543 DCHECK_EQ(message_loop_, MessageLoop::current()); 581 DCHECK_EQ(message_loop_, MessageLoop::current());
544 current_state_change_ = ERRORING;
545 582
546 client_->NotifyError(error); 583 if (client_)
584 client_->NotifyError(error);
585 client_ = NULL;
547 586
548 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax) 587 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax)
549 return; 588 return;
550 589
551 BeginTransitionToState(OMX_StateInvalid); 590 BeginTransitionToState(OMX_StateInvalid);
591 current_state_change_ = ERRORING;
552 } 592 }
553 593
554 bool OmxVideoDecodeAccelerator::AllocateInputBuffers() { 594 bool OmxVideoDecodeAccelerator::AllocateInputBuffers() {
555 DCHECK_EQ(message_loop_, MessageLoop::current()); 595 DCHECK_EQ(message_loop_, MessageLoop::current());
556 for (int i = 0; i < input_buffer_count_; ++i) { 596 for (int i = 0; i < input_buffer_count_; ++i) {
557 OMX_BUFFERHEADERTYPE* buffer; 597 OMX_BUFFERHEADERTYPE* buffer;
558 // While registering the buffer header we use fake buffer information 598 // While registering the buffer header we use fake buffer information
559 // (length 0, at memory address 0x1) to fake out the "safety" check in 599 // (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 600 // 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 601 // 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()); 622 gfx::Size decoded_pixel_size(pictures_.begin()->second.gles_buffer.size());
583 gfx::Size visible_pixel_size(pictures_.begin()->second.gles_buffer.size()); 623 gfx::Size visible_pixel_size(pictures_.begin()->second.gles_buffer.size());
584 for (OutputPictureById::iterator it = pictures_.begin(); 624 for (OutputPictureById::iterator it = pictures_.begin();
585 it != pictures_.end(); ++it) { 625 it != pictures_.end(); ++it) {
586 media::GLESBuffer& gles_buffer = it->second.gles_buffer; 626 media::GLESBuffer& gles_buffer = it->second.gles_buffer;
587 OMX_BUFFERHEADERTYPE** omx_buffer = &it->second.omx_buffer_header; 627 OMX_BUFFERHEADERTYPE** omx_buffer = &it->second.omx_buffer_header;
588 DCHECK(!*omx_buffer); 628 DCHECK(!*omx_buffer);
589 OMX_ERRORTYPE result = OMX_UseEGLImage( 629 OMX_ERRORTYPE result = OMX_UseEGLImage(
590 component_handle_, omx_buffer, output_port_, &gles_buffer, 630 component_handle_, omx_buffer, output_port_, &gles_buffer,
591 it->second.egl_image); 631 it->second.egl_image);
592 RETURN_ON_OMX_FAILURE(result, "OMX_UseEGLImage failed with: " << result, 632 RETURN_ON_OMX_FAILURE(result, "OMX_UseEGLImage",
593 VIDEODECODERERROR_MEMFAILURE, false); 633 VIDEODECODERERROR_MEMFAILURE, false);
594 // Here we set a garbage bitstream buffer id, and then overwrite it before 634 // Here we set a garbage bitstream buffer id, and then overwrite it before
595 // passing to PictureReady. 635 // passing to PictureReady.
596 int garbage_bitstream_buffer_id = -1; 636 int garbage_bitstream_buffer_id = -1;
597 (*omx_buffer)->pAppPrivate = 637 (*omx_buffer)->pAppPrivate =
598 new media::Picture(gles_buffer.id(), garbage_bitstream_buffer_id, 638 new media::Picture(gles_buffer.id(), garbage_bitstream_buffer_id,
599 decoded_pixel_size, visible_pixel_size); 639 decoded_pixel_size, visible_pixel_size);
600 } 640 }
601 return true; 641 return true;
602 } 642 }
603 643
604 void OmxVideoDecodeAccelerator::FreeInputBuffers() { 644 void OmxVideoDecodeAccelerator::FreeInputBuffers() {
605 DCHECK_EQ(message_loop_, MessageLoop::current()); 645 DCHECK_EQ(message_loop_, MessageLoop::current());
606 // Calls to OMX to free buffers. 646 // Calls to OMX to free buffers.
607 OMX_ERRORTYPE result; 647 OMX_ERRORTYPE result;
608 OMX_BUFFERHEADERTYPE* omx_buffer; 648 OMX_BUFFERHEADERTYPE* omx_buffer;
609 while (!free_input_buffers_.empty()) { 649 while (!free_input_buffers_.empty()) {
610 omx_buffer = free_input_buffers_.front(); 650 omx_buffer = free_input_buffers_.front();
611 free_input_buffers_.pop(); 651 free_input_buffers_.pop();
612 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer); 652 result = OMX_FreeBuffer(component_handle_, input_port_, omx_buffer);
613 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, 653 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer",
614 VIDEODECODERERROR_INVALIDINPUT,); 654 VIDEODECODERERROR_INVALIDINPUT,);
615 } 655 }
616 VLOG(1) << "Input buffers freed.";
617 } 656 }
618 657
619 void OmxVideoDecodeAccelerator::FreeOutputBuffers() { 658 void OmxVideoDecodeAccelerator::FreeOutputBuffers() {
620 DCHECK_EQ(message_loop_, MessageLoop::current()); 659 DCHECK_EQ(message_loop_, MessageLoop::current());
621 // Calls to OMX to free buffers. 660 // Calls to OMX to free buffers.
622 OMX_ERRORTYPE result; 661 OMX_ERRORTYPE result;
623 static Gles2TextureToEglImageTranslator texture2eglImage_translator; 662 static Gles2TextureToEglImageTranslator texture2eglImage_translator;
624 for (OutputPictureById::iterator it = pictures_.begin(); 663 for (OutputPictureById::iterator it = pictures_.begin();
625 it != pictures_.end(); ++it) { 664 it != pictures_.end(); ++it) {
626 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; 665 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header;
627 CHECK(omx_buffer); 666 CHECK(omx_buffer);
628 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); 667 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate);
629 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); 668 result = OMX_FreeBuffer(component_handle_, output_port_, omx_buffer);
630 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, 669 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer",
631 VIDEODECODERERROR_INVALIDINPUT,); 670 VIDEODECODERERROR_INVALIDINPUT,);
632 texture2eglImage_translator.DestroyEglImage(egl_display_, 671 texture2eglImage_translator.DestroyEglImage(egl_display_,
633 it->second.egl_image); 672 it->second.egl_image);
634 client_->DismissPictureBuffer(it->first); 673 if (client_)
674 client_->DismissPictureBuffer(it->first);
635 } 675 }
636 pictures_.clear(); 676 pictures_.clear();
637 } 677 }
638 678
639 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { 679 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() {
640 DCHECK_EQ(message_loop_, MessageLoop::current()); 680 DCHECK_EQ(message_loop_, MessageLoop::current());
641 OMX_PARAM_PORTDEFINITIONTYPE port_format; 681 OMX_PARAM_PORTDEFINITIONTYPE port_format;
642 InitParam(*this, &port_format); 682 InitParam(*this, &port_format);
643 port_format.nPortIndex = output_port_; 683 port_format.nPortIndex = output_port_;
644 OMX_ERRORTYPE result = OMX_GetParameter( 684 OMX_ERRORTYPE result = OMX_GetParameter(
645 component_handle_, OMX_IndexParamPortDefinition, &port_format); 685 component_handle_, OMX_IndexParamPortDefinition, &port_format);
646 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter failed with: " << result, 686 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter",
647 VIDEODECODERERROR_UNSUPPORTED,); 687 VIDEODECODERERROR_UNSUPPORTED,);
648 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers); 688 DCHECK_EQ(port_format.nBufferCountMin, kNumPictureBuffers);
649 689
650 // TODO(fischman): to support mid-stream resize, need to free/dismiss any 690 // 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 691 // |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). 692 // this (there's already freeing logic there, which should not be duplicated).
653 693
654 // Request picture buffers to be handed to the component. 694 // Request picture buffers to be handed to the component.
655 // ProvidePictureBuffers() will trigger AssignGLESBuffers, which ultimately 695 // ProvidePictureBuffers() will trigger AssignGLESBuffers, which ultimately
656 // assigns the textures to the component and re-enables the port. 696 // assigns the textures to the component and re-enables the port.
657 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; 697 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video;
658 client_->ProvidePictureBuffers( 698 if (client_) {
659 kNumPictureBuffers, 699 client_->ProvidePictureBuffers(
660 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight), 700 kNumPictureBuffers,
661 PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE); 701 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight),
702 PICTUREBUFFER_MEMORYTYPE_GL_TEXTURE);
703 }
662 } 704 }
663 705
664 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { 706 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() {
665 DCHECK_EQ(message_loop_, MessageLoop::current()); 707 DCHECK_EQ(message_loop_, MessageLoop::current());
666 708
667 if (!CanFillBuffer()) { 709 if (!CanFillBuffer()) {
668 StopOnError(VIDEODECODERERROR_UNSUPPORTED); // Should be STATE_ERROR. 710 StopOnError(VIDEODECODERERROR_UNSUPPORTED); // Should be STATE_ERROR.
669 return; 711 return;
670 } 712 }
671 713
672 // Provide output buffers to decoder. 714 // Provide output buffers to decoder.
673 for (OutputPictureById::iterator it = pictures_.begin(); 715 for (OutputPictureById::iterator it = pictures_.begin();
674 it != pictures_.end(); ++it) { 716 it != pictures_.end(); ++it) {
675 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header; 717 OMX_BUFFERHEADERTYPE* omx_buffer = it->second.omx_buffer_header;
676 DCHECK(omx_buffer); 718 DCHECK(omx_buffer);
677 // Clear EOS flag. 719 // Clear EOS flag.
678 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS; 720 omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
679 omx_buffer->nOutputPortIndex = output_port_; 721 omx_buffer->nOutputPortIndex = output_port_;
680 ++output_buffers_at_component_; 722 ++output_buffers_at_component_;
681 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer); 723 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer);
682 RETURN_ON_OMX_FAILURE(result, 724 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed",
683 "OMX_FillThisBuffer() failed with result " << result,
684 VIDEODECODERERROR_INSUFFICIENT_BUFFERS,); 725 VIDEODECODERERROR_INSUFFICIENT_BUFFERS,);
685 } 726 }
686 } 727 }
687 728
688 void OmxVideoDecodeAccelerator::FillBufferDoneTask( 729 void OmxVideoDecodeAccelerator::FillBufferDoneTask(
689 OMX_BUFFERHEADERTYPE* buffer) { 730 OMX_BUFFERHEADERTYPE* buffer) {
690 DCHECK_EQ(message_loop_, MessageLoop::current()); 731 DCHECK_EQ(message_loop_, MessageLoop::current());
691 DCHECK_GT(output_buffers_at_component_, 0); 732 DCHECK_GT(output_buffers_at_component_, 0);
692 --output_buffers_at_component_; 733 --output_buffers_at_component_;
693 734
694 if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) { 735 if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) {
695 CHECK_EQ(fake_output_buffers_.erase(buffer), 1U); 736 CHECK_EQ(fake_output_buffers_.erase(buffer), 1U);
696 OMX_ERRORTYPE result = 737 OMX_ERRORTYPE result =
697 OMX_FreeBuffer(component_handle_, output_port_, buffer); 738 OMX_FreeBuffer(component_handle_, output_port_, buffer);
698 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed with: " << result, 739 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed",
699 VIDEODECODERERROR_INVALIDINPUT,); 740 VIDEODECODERERROR_INVALIDINPUT,);
700 return; 741 return;
701 } 742 }
702 CHECK(!fake_output_buffers_.size()); 743 CHECK(!fake_output_buffers_.size());
703 744
704 if (current_state_change_ == FLUSHING && 745 if (current_state_change_ == FLUSHING &&
705 buffer->nFlags & OMX_BUFFERFLAG_EOS) { 746 buffer->nFlags & OMX_BUFFERFLAG_EOS) {
706 DCHECK(!saw_eos_during_flush_); 747 DCHECK(!saw_eos_during_flush_);
707 saw_eos_during_flush_ = true; 748 saw_eos_during_flush_ = true;
708 } 749 }
709 750
710 // During the transition from Executing to Idle, and during port-flushing, all 751 // 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. 752 // pictures are sent back through here. Avoid giving them to the client.
712 // Also avoid sending the (fake) EOS buffer to the client. 753 // Also avoid sending the (fake) EOS buffer to the client.
713 if ((current_state_change_ != NO_TRANSITION && 754 if ((current_state_change_ != NO_TRANSITION &&
714 current_state_change_ != FLUSHING) || 755 current_state_change_ != FLUSHING) ||
715 saw_eos_during_flush_) { 756 saw_eos_during_flush_) {
716 return; 757 return;
717 } 758 }
718 759
719 CHECK(buffer->pAppPrivate); 760 CHECK(buffer->pAppPrivate);
720 media::Picture* picture = 761 media::Picture* picture =
721 reinterpret_cast<media::Picture*>(buffer->pAppPrivate); 762 reinterpret_cast<media::Picture*>(buffer->pAppPrivate);
722 // See Decode() for an explanation of this abuse of nTimeStamp. 763 // See Decode() for an explanation of this abuse of nTimeStamp.
723 picture->set_bitstream_buffer_id(buffer->nTimeStamp); 764 picture->set_bitstream_buffer_id(buffer->nTimeStamp);
724 client_->PictureReady(*picture); 765 if (client_)
766 client_->PictureReady(*picture);
725 } 767 }
726 768
727 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( 769 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask(
728 OMX_BUFFERHEADERTYPE* buffer) { 770 OMX_BUFFERHEADERTYPE* buffer) {
729 DCHECK_EQ(message_loop_, MessageLoop::current()); 771 DCHECK_EQ(message_loop_, MessageLoop::current());
730 DCHECK_GT(input_buffers_at_component_, 0); 772 DCHECK_GT(input_buffers_at_component_, 0);
731 free_input_buffers_.push(buffer); 773 free_input_buffers_.push(buffer);
732 input_buffers_at_component_--; 774 input_buffers_at_component_--;
733 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) 775 if (buffer->nFlags & OMX_BUFFERFLAG_EOS)
734 return; 776 return;
735 777
736 // Retrieve the corresponding BitstreamBuffer's id and notify the client of 778 // Retrieve the corresponding BitstreamBuffer's id and notify the client of
737 // its completion. 779 // its completion.
738 SharedMemoryAndId* input_buffer_details = 780 SharedMemoryAndId* input_buffer_details =
739 reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate); 781 reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate);
740 DCHECK(input_buffer_details); 782 DCHECK(input_buffer_details);
741 buffer->pAppPrivate = NULL; 783 buffer->pAppPrivate = NULL;
742 client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second); 784 if (client_)
785 client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second);
743 delete input_buffer_details; 786 delete input_buffer_details;
744 } 787 }
745 788
746 void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) { 789 void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) {
747 DCHECK_EQ(message_loop_, MessageLoop::current()); 790 DCHECK_EQ(message_loop_, MessageLoop::current());
748 switch (current_state_change_) { 791 switch (current_state_change_) {
749 case INITIALIZING: 792 case INITIALIZING:
750 switch (reached) { 793 switch (reached) {
751 case OMX_StateIdle: 794 case OMX_StateIdle:
752 OnReachedIdleInInitializing(); 795 OnReachedIdleInInitializing();
(...skipping 30 matching lines...) Expand all
783 switch (reached) { 826 switch (reached) {
784 case OMX_StateIdle: 827 case OMX_StateIdle:
785 OnReachedIdleInDestroying(); 828 OnReachedIdleInDestroying();
786 return; 829 return;
787 case OMX_StateLoaded: 830 case OMX_StateLoaded:
788 OnReachedLoadedInDestroying(); 831 OnReachedLoadedInDestroying();
789 return; 832 return;
790 default: 833 default:
791 NOTREACHED() << "Unexpected state in DESTROYING: " << reached; 834 NOTREACHED() << "Unexpected state in DESTROYING: " << reached;
792 } 835 }
836 case ERRORING:
837 switch (reached) {
838 case OMX_StateInvalid:
839 OnReachedInvalidInErroring();
840 return;
841 default:
842 NOTREACHED() << "Unexpected state in ERRORING: " << reached;
843 }
793 default: 844 default:
794 NOTREACHED() << "Unexpected state in " << current_state_change_ 845 NOTREACHED() << "Unexpected state in " << current_state_change_
795 << ": " << reached; 846 << ": " << reached;
796 } 847 }
797 } 848 }
798 849
799 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event, 850 void OmxVideoDecodeAccelerator::EventHandlerCompleteTask(OMX_EVENTTYPE event,
800 OMX_U32 data1, 851 OMX_U32 data1,
801 OMX_U32 data2) { 852 OMX_U32 data2) {
802 DCHECK_EQ(message_loop_, MessageLoop::current()); 853 DCHECK_EQ(message_loop_, MessageLoop::current());
803 switch (event) { 854 switch (event) {
804 case OMX_EventCmdComplete: { 855 case OMX_EventCmdComplete:
805 // If the last command was successful, we have completed 856 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: 857 case OMX_CommandPortDisable:
811 DCHECK_EQ(data2, output_port_); 858 DCHECK_EQ(data2, output_port_);
812 OnOutputPortDisabled(); 859 OnOutputPortDisabled();
813 break; 860 return;
814 case OMX_CommandPortEnable: 861 case OMX_CommandPortEnable:
815 DCHECK_EQ(data2, output_port_); 862 DCHECK_EQ(data2, output_port_);
816 OnOutputPortEnabled(); 863 OnOutputPortEnabled();
817 break; 864 return;
818 case OMX_CommandStateSet: 865 case OMX_CommandStateSet:
819 DispatchStateReached(static_cast<OMX_STATETYPE>(data2)); 866 DispatchStateReached(static_cast<OMX_STATETYPE>(data2));
820 break; 867 return;
821 case OMX_CommandFlush: 868 case OMX_CommandFlush:
822 DCHECK(current_state_change_ == FLUSHING || 869 DCHECK(current_state_change_ == FLUSHING ||
823 current_state_change_ == RESETTING || 870 current_state_change_ == RESETTING ||
824 current_state_change_ == DESTROYING); 871 current_state_change_ == DESTROYING);
825 if (data2 == input_port_) 872 if (data2 == input_port_)
826 InputPortFlushDone(); 873 InputPortFlushDone();
827 else if (data2 == output_port_) 874 else if (data2 == output_port_)
828 OutputPortFlushDone(); 875 OutputPortFlushDone();
829 else 876 else
830 NOTREACHED() << "Unexpected port flushed: " << data2; 877 NOTREACHED() << "Unexpected port flushed: " << data2;
831 break; 878 return;
832 default: 879 default:
833 RETURN_ON_FAILURE(false, "Unknown command completed: " << data1, 880 RETURN_ON_FAILURE(false, "Unknown command completed: " << data1,
834 VIDEODECODERERROR_HARDWARE,); 881 VIDEODECODERERROR_HARDWARE,);
835 } 882 }
836 break; 883 return;
837 }
838 case OMX_EventError: 884 case OMX_EventError:
839 RETURN_ON_FAILURE(false, "EventError: " << data1, 885 if (current_state_change_ != DESTROYING &&
840 VIDEODECODERERROR_HARDWARE,); 886 current_state_change_ != ERRORING) {
887 RETURN_ON_FAILURE(false, "EventError: 0x" << std::hex << data1,
888 VIDEODECODERERROR_HARDWARE,);
889 }
890 return;
841 case OMX_EventPortSettingsChanged: 891 case OMX_EventPortSettingsChanged:
842 if (data2 == OMX_IndexParamPortDefinition) { 892 if (data2 == OMX_IndexParamPortDefinition) {
843 DCHECK_EQ(data1, output_port_); 893 DCHECK_EQ(data1, output_port_);
844 // This event is only used for output resize; kick off handling that by 894 // This event is only used for output resize; kick off handling that by
845 // pausing the output port. 895 // pausing the output port.
846 SendCommandToPort(OMX_CommandPortDisable, output_port_); 896 SendCommandToPort(OMX_CommandPortDisable, output_port_);
847 } else if (data1 == output_port_ && 897 } else if (data1 == output_port_ &&
848 data2 == OMX_IndexConfigCommonOutputCrop) { 898 data2 == OMX_IndexConfigCommonOutputCrop) {
849 // TODO(vjain): Handle video crop rect. 899 // TODO(vjain): Handle video crop rect.
850 } else { 900 } else {
851 RETURN_ON_FAILURE(false, 901 RETURN_ON_FAILURE(false,
852 "Unexpected EventPortSettingsChanged: " 902 "Unexpected EventPortSettingsChanged: "
853 << data1 << ", " << data2, 903 << data1 << ", " << data2,
854 VIDEODECODERERROR_HARDWARE,); 904 VIDEODECODERERROR_HARDWARE,);
855 } 905 }
856 break; 906 return;
857 case OMX_EventBufferFlag: 907 case OMX_EventBufferFlag:
858 if (data1 == output_port_) { 908 if (data1 == output_port_) {
859 DCHECK_EQ(current_state_change_, FLUSHING); 909 DCHECK_EQ(current_state_change_, FLUSHING);
860 OnReachedEOSInFlushing(); 910 OnReachedEOSInFlushing();
861 } else { 911 } else {
862 RETURN_ON_FAILURE(false, 912 RETURN_ON_FAILURE(false,
863 "Unexpected OMX_EventBufferFlag: " 913 "Unexpected OMX_EventBufferFlag: "
864 << data1 << ", " << data2, 914 << data1 << ", " << data2,
865 VIDEODECODERERROR_HARDWARE,); 915 VIDEODECODERERROR_HARDWARE,);
866 } 916 }
867 break; 917 return;
868 default: 918 default:
869 RETURN_ON_FAILURE(false, "Unexpected unhandled event: " << event, 919 RETURN_ON_FAILURE(false, "Unexpected unhandled event: " << event,
870 VIDEODECODERERROR_HARDWARE,); 920 VIDEODECODERERROR_HARDWARE,);
871 } 921 }
872 } 922 }
873 923
874 // static 924 // static
875 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component, 925 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EventHandler(OMX_HANDLETYPE component,
876 OMX_PTR priv_data, 926 OMX_PTR priv_data,
877 OMX_EVENTTYPE event, 927 OMX_EVENTTYPE event,
878 OMX_U32 data1, 928 OMX_U32 data1,
879 OMX_U32 data2, 929 OMX_U32 data2,
880 OMX_PTR event_data) { 930 OMX_PTR event_data) {
881 // Called on the OMX thread. 931 // Called on the OMX thread.
882 OmxVideoDecodeAccelerator* decoder = 932 OmxVideoDecodeAccelerator* decoder =
883 static_cast<OmxVideoDecodeAccelerator*>(priv_data); 933 static_cast<OmxVideoDecodeAccelerator*>(priv_data);
884 DCHECK_EQ(component, decoder->component_handle_); 934 DCHECK_EQ(component, decoder->component_handle_);
885 decoder->message_loop_->PostTask( 935 decoder->message_loop_->PostTask(
886 FROM_HERE, 936 FROM_HERE, NewRunnableMethod(
887 NewRunnableMethod(decoder, 937 decoder, &OmxVideoDecodeAccelerator::EventHandlerCompleteTask,
888 &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, 938 event, data1, data2));
889 event, data1, data2));
890 return OMX_ErrorNone; 939 return OMX_ErrorNone;
891 } 940 }
892 941
893 // static 942 // static
894 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback( 943 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback(
895 OMX_HANDLETYPE component, 944 OMX_HANDLETYPE component,
896 OMX_PTR priv_data, 945 OMX_PTR priv_data,
897 OMX_BUFFERHEADERTYPE* buffer) { 946 OMX_BUFFERHEADERTYPE* buffer) {
898 // Called on the OMX thread. 947 // Called on the OMX thread.
899 OmxVideoDecodeAccelerator* decoder = 948 OmxVideoDecodeAccelerator* decoder =
(...skipping 19 matching lines...) Expand all
919 decoder->message_loop_->PostTask( 968 decoder->message_loop_->PostTask(
920 FROM_HERE, 969 FROM_HERE,
921 NewRunnableMethod(decoder, 970 NewRunnableMethod(decoder,
922 &OmxVideoDecodeAccelerator::FillBufferDoneTask, 971 &OmxVideoDecodeAccelerator::FillBufferDoneTask,
923 buffer)); 972 buffer));
924 return OMX_ErrorNone; 973 return OMX_ErrorNone;
925 } 974 }
926 975
927 bool OmxVideoDecodeAccelerator::CanFillBuffer() { 976 bool OmxVideoDecodeAccelerator::CanFillBuffer() {
928 DCHECK_EQ(message_loop_, MessageLoop::current()); 977 DCHECK_EQ(message_loop_, MessageLoop::current());
978 if (current_state_change_ == DESTROYING ||
979 current_state_change_ == ERRORING) {
980 return false;
981 }
929 return client_state_ == OMX_StateIdle || 982 return client_state_ == OMX_StateIdle ||
930 client_state_ == OMX_StateExecuting || 983 client_state_ == OMX_StateExecuting ||
931 client_state_ == OMX_StatePause; 984 client_state_ == OMX_StatePause;
932 } 985 }
933 986
934 bool OmxVideoDecodeAccelerator::SendCommandToPort( 987 bool OmxVideoDecodeAccelerator::SendCommandToPort(
935 OMX_COMMANDTYPE cmd, int port_index) { 988 OMX_COMMANDTYPE cmd, int port_index) {
936 DCHECK_EQ(message_loop_, MessageLoop::current()); 989 DCHECK_EQ(message_loop_, MessageLoop::current());
937 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, 990 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_,
938 cmd, port_index, 0); 991 cmd, port_index, 0);
939 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd << ":" << result, 992 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd,
940 VIDEODECODERERROR_INVALIDINPUT, false); 993 VIDEODECODERERROR_INVALIDINPUT, false);
941 return true; 994 return true;
942 } 995 }
943
944 DISABLE_RUNNABLE_METHOD_REFCOUNT(OmxVideoDecodeAccelerator);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698