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

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

Issue 10749019: VideoDecodeAccelerator now SupportsWeakPtr instead of being RefCountedThreadSafe. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/gpu/media/omx_video_decode_accelerator.h" 5 #include "content/common/gpu/media/omx_video_decode_accelerator.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 OMX_U32 num_components = 1; 183 OMX_U32 num_components = 1;
184 scoped_array<OMX_U8> component(new OMX_U8[OMX_MAX_STRINGNAME_SIZE]); 184 scoped_array<OMX_U8> component(new OMX_U8[OMX_MAX_STRINGNAME_SIZE]);
185 OMX_ERRORTYPE result = omx_get_components_of_role( 185 OMX_ERRORTYPE result = omx_get_components_of_role(
186 role_name, &num_components, reinterpret_cast<OMX_U8**>(&component)); 186 role_name, &num_components, reinterpret_cast<OMX_U8**>(&component));
187 RETURN_ON_OMX_FAILURE(result, "Unsupport role: " << role_name, 187 RETURN_ON_OMX_FAILURE(result, "Unsupport role: " << role_name,
188 PLATFORM_FAILURE, false); 188 PLATFORM_FAILURE, false);
189 RETURN_ON_FAILURE(num_components == 1, "No components for: " << role_name, 189 RETURN_ON_FAILURE(num_components == 1, "No components for: " << role_name,
190 PLATFORM_FAILURE, false); 190 PLATFORM_FAILURE, false);
191 191
192 // Get the handle to the component. 192 // Get the handle to the component.
193 AddRef(); // To reflect passing |this| to OMX_GetHandle below.
194 result = omx_gethandle( 193 result = omx_gethandle(
195 &component_handle_, reinterpret_cast<OMX_STRING>(component.get()), 194 &component_handle_, reinterpret_cast<OMX_STRING>(component.get()),
196 this, &omx_accelerator_callbacks); 195 this, &omx_accelerator_callbacks);
197 RETURN_ON_OMX_FAILURE(result, 196 RETURN_ON_OMX_FAILURE(result,
198 "Failed to OMX_GetHandle on: " << component.get(), 197 "Failed to OMX_GetHandle on: " << component.get(),
199 PLATFORM_FAILURE, false); 198 PLATFORM_FAILURE, false);
200 client_state_ = OMX_StateLoaded; 199 client_state_ = OMX_StateLoaded;
201 200
202 component_name_is_nvidia_h264ext_ = !strcmp( 201 component_name_is_nvidia_h264ext_ = !strcmp(
203 reinterpret_cast<char *>(component.get()), 202 reinterpret_cast<char *>(component.get()),
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 } 429 }
431 430
432 void OmxVideoDecodeAccelerator::Reset() { 431 void OmxVideoDecodeAccelerator::Reset() {
433 DCHECK_EQ(message_loop_, MessageLoop::current()); 432 DCHECK_EQ(message_loop_, MessageLoop::current());
434 DCHECK_EQ(current_state_change_, NO_TRANSITION); 433 DCHECK_EQ(current_state_change_, NO_TRANSITION);
435 DCHECK_EQ(client_state_, OMX_StateExecuting); 434 DCHECK_EQ(client_state_, OMX_StateExecuting);
436 current_state_change_ = RESETTING; 435 current_state_change_ = RESETTING;
437 BeginTransitionToState(OMX_StatePause); 436 BeginTransitionToState(OMX_StatePause);
438 } 437 }
439 438
440 void OmxVideoDecodeAccelerator::Destroy() { 439 void OmxVideoDecodeAccelerator::Destroy(
440 scoped_ptr<VideoDecodeAccelerator> self) {
441 DCHECK_EQ(message_loop_, MessageLoop::current()); 441 DCHECK_EQ(message_loop_, MessageLoop::current());
442 if (current_state_change_ == ERRORING || 442 if (current_state_change_ == ERRORING ||
443 current_state_change_ == DESTROYING) { 443 current_state_change_ == DESTROYING) {
444 return; 444 return;
445 } 445 }
446 446
447 DCHECK(current_state_change_ == NO_TRANSITION || 447 DCHECK(current_state_change_ == NO_TRANSITION ||
448 current_state_change_ == FLUSHING || 448 current_state_change_ == FLUSHING ||
449 current_state_change_ == RESETTING) << current_state_change_; 449 current_state_change_ == RESETTING) << current_state_change_;
450 450
451 // If we were never initializeed there's no teardown to do. 451 // If we were never initializeed there's no teardown to do.
452 if (client_state_ == OMX_StateMax) 452 if (client_state_ == OMX_StateMax)
453 return; 453 return;
454 // If we can already call OMX_FreeHandle, simply do so. 454 // If we can already call OMX_FreeHandle, simply do so.
455 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateLoaded) { 455 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateLoaded) {
456 ShutdownComponent(); 456 ShutdownComponent();
457 return; 457 return;
458 } 458 }
459 DCHECK(client_state_ == OMX_StateExecuting || 459 DCHECK(client_state_ == OMX_StateExecuting ||
460 client_state_ == OMX_StateIdle || 460 client_state_ == OMX_StateIdle ||
461 client_state_ == OMX_StatePause); 461 client_state_ == OMX_StatePause);
462 current_state_change_ = DESTROYING; 462 current_state_change_ = DESTROYING;
463 client_ = NULL; 463 client_ = NULL;
464 BeginTransitionToState(OMX_StateIdle); 464 BeginTransitionToState(OMX_StateIdle);
465 BusyLoopInDestroying(); 465 BusyLoopInDestroying(self.Pass());
466 } 466 }
467 467
468 void OmxVideoDecodeAccelerator::BeginTransitionToState( 468 void OmxVideoDecodeAccelerator::BeginTransitionToState(
469 OMX_STATETYPE new_state) { 469 OMX_STATETYPE new_state) {
470 DCHECK_EQ(message_loop_, MessageLoop::current()); 470 DCHECK_EQ(message_loop_, MessageLoop::current());
471 DCHECK_NE(current_state_change_, NO_TRANSITION); 471 DCHECK_NE(current_state_change_, NO_TRANSITION);
472 DCHECK_NE(current_state_change_, ERRORING); 472 DCHECK_NE(current_state_change_, ERRORING);
473 if (current_state_change_ == NO_TRANSITION || 473 if (current_state_change_ == NO_TRANSITION ||
474 current_state_change_ == ERRORING) { 474 current_state_change_ == ERRORING) {
475 return; 475 return;
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 client_->NotifyResetDone(); 555 client_->NotifyResetDone();
556 } 556 }
557 557
558 // Alert: HORROR ahead! OMX shutdown is an asynchronous dance but our clients 558 // Alert: HORROR ahead! OMX shutdown is an asynchronous dance but our clients
559 // enjoy the fire-and-forget nature of a synchronous Destroy() call that 559 // enjoy the fire-and-forget nature of a synchronous Destroy() call that
560 // ensures no further callbacks are made. Since the interface between OMX 560 // ensures no further callbacks are made. Since the interface between OMX
561 // callbacks and this class is a MessageLoop, we need to ensure the loop 561 // callbacks and this class is a MessageLoop, we need to ensure the loop
562 // outlives the shutdown dance, even during process shutdown. We do this by 562 // outlives the shutdown dance, even during process shutdown. We do this by
563 // repeatedly enqueuing a no-op task until shutdown is complete, since 563 // repeatedly enqueuing a no-op task until shutdown is complete, since
564 // MessageLoop's shutdown drains pending tasks. 564 // MessageLoop's shutdown drains pending tasks.
565 void OmxVideoDecodeAccelerator::BusyLoopInDestroying() { 565 void OmxVideoDecodeAccelerator::BusyLoopInDestroying(
566 scoped_ptr<VideoDecodeAccelerator> self) {
566 if (!component_handle_) return; 567 if (!component_handle_) return;
567 // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed 568 // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed
568 // tasks. Instead we sleep for 5ms. Really. 569 // tasks. Instead we sleep for 5ms. Really.
569 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5)); 570 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5));
570 message_loop_->PostTask( 571 message_loop_->PostTask(
571 FROM_HERE, base::Bind( 572 FROM_HERE, base::Bind(
572 &OmxVideoDecodeAccelerator::BusyLoopInDestroying, this)); 573 &OmxVideoDecodeAccelerator::BusyLoopInDestroying,
574 base::Unretained(this), base::Passed(&self)));
573 } 575 }
574 576
575 void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() { 577 void OmxVideoDecodeAccelerator::OnReachedIdleInDestroying() {
576 DCHECK(client_state_ == OMX_StateExecuting || 578 DCHECK(client_state_ == OMX_StateExecuting ||
577 client_state_ == OMX_StateIdle || 579 client_state_ == OMX_StateIdle ||
578 client_state_ == OMX_StatePause); 580 client_state_ == OMX_StatePause);
579 client_state_ = OMX_StateIdle; 581 client_state_ = OMX_StateIdle;
580 582
581 // Note that during the Executing -> Idle transition, the OMX spec guarantees 583 // Note that during the Executing -> Idle transition, the OMX spec guarantees
582 // buffers have been returned to the client, so we don't need to do an 584 // buffers have been returned to the client, so we don't need to do an
583 // explicit FlushIOPorts(). 585 // explicit FlushIOPorts().
584 586
585 BeginTransitionToState(OMX_StateLoaded); 587 BeginTransitionToState(OMX_StateLoaded);
586 588
587 // TODO(fischman): evaluate what these conditionals are doing. What happens 589 // TODO(fischman): evaluate what these conditionals are doing. What happens
588 // if they're false?? 590 // if they're false??
589 if (!input_buffers_at_component_) 591 if (!input_buffers_at_component_)
590 FreeInputBuffers(); 592 FreeInputBuffers();
591 if (!output_buffers_at_component_) 593 if (!output_buffers_at_component_)
592 FreeOutputBuffers(); 594 FreeOutputBuffers();
593
594 BusyLoopInDestroying();
595 } 595 }
596 596
597 void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() { 597 void OmxVideoDecodeAccelerator::OnReachedLoadedInDestroying() {
598 DCHECK_EQ(client_state_, OMX_StateIdle); 598 DCHECK_EQ(client_state_, OMX_StateIdle);
599 client_state_ = OMX_StateLoaded; 599 client_state_ = OMX_StateLoaded;
600 current_state_change_ = NO_TRANSITION; 600 current_state_change_ = NO_TRANSITION;
601 ShutdownComponent(); 601 ShutdownComponent();
602 } 602 }
603 603
604 void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() { 604 void OmxVideoDecodeAccelerator::OnReachedInvalidInErroring() {
605 client_state_ = OMX_StateInvalid; 605 client_state_ = OMX_StateInvalid;
606 ShutdownComponent(); 606 ShutdownComponent();
607 } 607 }
608 608
609 void OmxVideoDecodeAccelerator::ShutdownComponent() { 609 void OmxVideoDecodeAccelerator::ShutdownComponent() {
610 OMX_ERRORTYPE result = omx_free_handle(component_handle_); 610 OMX_ERRORTYPE result = omx_free_handle(component_handle_);
611 if (result != OMX_ErrorNone) 611 if (result != OMX_ErrorNone)
612 DLOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result; 612 DLOG(ERROR) << "OMX_FreeHandle() error. Error code: " << result;
613 client_state_ = OMX_StateMax;
614 omx_deinit();
615 // Allow BusyLoopInDestroying to exit and delete |this|.
613 component_handle_ = NULL; 616 component_handle_ = NULL;
614 client_state_ = OMX_StateMax;
615 // This Release() call must happen *after* any access to |*this| because it
616 // might result in |this| being deleted.
617 Release(); // Since OMX no longer has |this| to call back to.
618 omx_deinit();
619 } 617 }
620 618
621 void OmxVideoDecodeAccelerator::StopOnError( 619 void OmxVideoDecodeAccelerator::StopOnError(
622 media::VideoDecodeAccelerator::Error error) { 620 media::VideoDecodeAccelerator::Error error) {
623 DCHECK_EQ(message_loop_, MessageLoop::current()); 621 DCHECK_EQ(message_loop_, MessageLoop::current());
624 622
625 if (client_ && init_begun_) 623 if (client_ && init_begun_)
626 client_->NotifyError(error); 624 client_->NotifyError(error);
627 client_ = NULL; 625 client_ = NULL;
628 626
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 OMX_PTR priv_data, 991 OMX_PTR priv_data,
994 OMX_EVENTTYPE event, 992 OMX_EVENTTYPE event,
995 OMX_U32 data1, 993 OMX_U32 data1,
996 OMX_U32 data2, 994 OMX_U32 data2,
997 OMX_PTR event_data) { 995 OMX_PTR event_data) {
998 // Called on the OMX thread. 996 // Called on the OMX thread.
999 OmxVideoDecodeAccelerator* decoder = 997 OmxVideoDecodeAccelerator* decoder =
1000 static_cast<OmxVideoDecodeAccelerator*>(priv_data); 998 static_cast<OmxVideoDecodeAccelerator*>(priv_data);
1001 DCHECK_EQ(component, decoder->component_handle_); 999 DCHECK_EQ(component, decoder->component_handle_);
1002 decoder->message_loop_->PostTask(FROM_HERE, base::Bind( 1000 decoder->message_loop_->PostTask(FROM_HERE, base::Bind(
1003 &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, decoder, 1001 &OmxVideoDecodeAccelerator::EventHandlerCompleteTask,
1004 event, data1, data2)); 1002 base::AsWeakPtr(decoder), event, data1, data2));
1005 return OMX_ErrorNone; 1003 return OMX_ErrorNone;
1006 } 1004 }
1007 1005
1008 // static 1006 // static
1009 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback( 1007 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback(
1010 OMX_HANDLETYPE component, 1008 OMX_HANDLETYPE component,
1011 OMX_PTR priv_data, 1009 OMX_PTR priv_data,
1012 OMX_BUFFERHEADERTYPE* buffer) { 1010 OMX_BUFFERHEADERTYPE* buffer) {
1013 TRACE_EVENT1("Video Decoder", "OVDA::EmptyBufferCallback", 1011 TRACE_EVENT1("Video Decoder", "OVDA::EmptyBufferCallback",
1014 "Buffer id", buffer->nTimeStamp); 1012 "Buffer id", buffer->nTimeStamp);
1015 // Called on the OMX thread. 1013 // Called on the OMX thread.
1016 OmxVideoDecodeAccelerator* decoder = 1014 OmxVideoDecodeAccelerator* decoder =
1017 static_cast<OmxVideoDecodeAccelerator*>(priv_data); 1015 static_cast<OmxVideoDecodeAccelerator*>(priv_data);
1018 DCHECK_EQ(component, decoder->component_handle_); 1016 DCHECK_EQ(component, decoder->component_handle_);
1019 decoder->message_loop_->PostTask(FROM_HERE, base::Bind( 1017 decoder->message_loop_->PostTask(FROM_HERE, base::Bind(
1020 &OmxVideoDecodeAccelerator::EmptyBufferDoneTask, decoder, buffer)); 1018 &OmxVideoDecodeAccelerator::EmptyBufferDoneTask, base::AsWeakPtr(decoder),
1019 buffer));
1021 return OMX_ErrorNone; 1020 return OMX_ErrorNone;
1022 } 1021 }
1023 1022
1024 // static 1023 // static
1025 OMX_ERRORTYPE OmxVideoDecodeAccelerator::FillBufferCallback( 1024 OMX_ERRORTYPE OmxVideoDecodeAccelerator::FillBufferCallback(
1026 OMX_HANDLETYPE component, 1025 OMX_HANDLETYPE component,
1027 OMX_PTR priv_data, 1026 OMX_PTR priv_data,
1028 OMX_BUFFERHEADERTYPE* buffer) { 1027 OMX_BUFFERHEADERTYPE* buffer) {
1029 media::Picture* picture = 1028 media::Picture* picture =
1030 reinterpret_cast<media::Picture*>(buffer->pAppPrivate); 1029 reinterpret_cast<media::Picture*>(buffer->pAppPrivate);
1031 int picture_buffer_id = picture ? picture->picture_buffer_id() : -1; 1030 int picture_buffer_id = picture ? picture->picture_buffer_id() : -1;
1032 TRACE_EVENT2("Video Decoder", "OVDA::FillBufferCallback", 1031 TRACE_EVENT2("Video Decoder", "OVDA::FillBufferCallback",
1033 "Buffer id", buffer->nTimeStamp, 1032 "Buffer id", buffer->nTimeStamp,
1034 "Picture id", picture_buffer_id); 1033 "Picture id", picture_buffer_id);
1035 // Called on the OMX thread. 1034 // Called on the OMX thread.
1036 OmxVideoDecodeAccelerator* decoder = 1035 OmxVideoDecodeAccelerator* decoder =
1037 static_cast<OmxVideoDecodeAccelerator*>(priv_data); 1036 static_cast<OmxVideoDecodeAccelerator*>(priv_data);
1038 DCHECK_EQ(component, decoder->component_handle_); 1037 DCHECK_EQ(component, decoder->component_handle_);
1039 decoder->message_loop_->PostTask(FROM_HERE, base::Bind( 1038 decoder->message_loop_->PostTask(FROM_HERE, base::Bind(
1040 &OmxVideoDecodeAccelerator::FillBufferDoneTask, decoder, buffer)); 1039 &OmxVideoDecodeAccelerator::FillBufferDoneTask, base::AsWeakPtr(decoder),
1040 buffer));
1041 return OMX_ErrorNone; 1041 return OMX_ErrorNone;
1042 } 1042 }
1043 1043
1044 bool OmxVideoDecodeAccelerator::CanFillBuffer() { 1044 bool OmxVideoDecodeAccelerator::CanFillBuffer() {
1045 DCHECK_EQ(message_loop_, MessageLoop::current()); 1045 DCHECK_EQ(message_loop_, MessageLoop::current());
1046 const CurrentStateChange csc = current_state_change_; 1046 const CurrentStateChange csc = current_state_change_;
1047 const OMX_STATETYPE cs = client_state_; 1047 const OMX_STATETYPE cs = client_state_;
1048 return (csc != DESTROYING && csc != ERRORING) && 1048 return (csc != DESTROYING && csc != ERRORING) &&
1049 (cs == OMX_StateIdle || cs == OMX_StateExecuting || cs == OMX_StatePause); 1049 (cs == OMX_StateIdle || cs == OMX_StateExecuting || cs == OMX_StatePause);
1050 } 1050 }
1051 1051
1052 bool OmxVideoDecodeAccelerator::SendCommandToPort( 1052 bool OmxVideoDecodeAccelerator::SendCommandToPort(
1053 OMX_COMMANDTYPE cmd, int port_index) { 1053 OMX_COMMANDTYPE cmd, int port_index) {
1054 DCHECK_EQ(message_loop_, MessageLoop::current()); 1054 DCHECK_EQ(message_loop_, MessageLoop::current());
1055 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, 1055 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_,
1056 cmd, port_index, 0); 1056 cmd, port_index, 0);
1057 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, 1057 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd,
1058 PLATFORM_FAILURE, false); 1058 PLATFORM_FAILURE, false);
1059 return true; 1059 return true;
1060 } 1060 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698