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

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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 #define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \ 94 #define RETURN_ON_OMX_FAILURE(omx_result, log, error, ret_val) \
95 RETURN_ON_FAILURE( \ 95 RETURN_ON_FAILURE( \
96 ((omx_result) == OMX_ErrorNone), \ 96 ((omx_result) == OMX_ErrorNone), \
97 log << ", OMX result: 0x" << std::hex << omx_result, \ 97 log << ", OMX result: 0x" << std::hex << omx_result, \
98 error, ret_val) 98 error, ret_val)
99 99
100 OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator( 100 OmxVideoDecodeAccelerator::OmxVideoDecodeAccelerator(
101 media::VideoDecodeAccelerator::Client* client) 101 media::VideoDecodeAccelerator::Client* client)
102 : message_loop_(MessageLoop::current()), 102 : message_loop_(MessageLoop::current()),
103 component_handle_(NULL), 103 component_handle_(NULL),
104 weak_this_(base::AsWeakPtr(this)),
104 init_begun_(false), 105 init_begun_(false),
105 client_state_(OMX_StateMax), 106 client_state_(OMX_StateMax),
106 current_state_change_(NO_TRANSITION), 107 current_state_change_(NO_TRANSITION),
107 input_buffer_count_(0), 108 input_buffer_count_(0),
108 input_buffer_size_(0), 109 input_buffer_size_(0),
109 input_port_(0), 110 input_port_(0),
110 input_buffers_at_component_(0), 111 input_buffers_at_component_(0),
111 output_port_(0), 112 output_port_(0),
112 output_buffers_at_component_(0), 113 output_buffers_at_component_(0),
113 client_(client), 114 client_(client),
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 OMX_U32 num_components = 1; 184 OMX_U32 num_components = 1;
184 scoped_array<OMX_U8> component(new OMX_U8[OMX_MAX_STRINGNAME_SIZE]); 185 scoped_array<OMX_U8> component(new OMX_U8[OMX_MAX_STRINGNAME_SIZE]);
185 OMX_ERRORTYPE result = omx_get_components_of_role( 186 OMX_ERRORTYPE result = omx_get_components_of_role(
186 role_name, &num_components, reinterpret_cast<OMX_U8**>(&component)); 187 role_name, &num_components, reinterpret_cast<OMX_U8**>(&component));
187 RETURN_ON_OMX_FAILURE(result, "Unsupport role: " << role_name, 188 RETURN_ON_OMX_FAILURE(result, "Unsupport role: " << role_name,
188 PLATFORM_FAILURE, false); 189 PLATFORM_FAILURE, false);
189 RETURN_ON_FAILURE(num_components == 1, "No components for: " << role_name, 190 RETURN_ON_FAILURE(num_components == 1, "No components for: " << role_name,
190 PLATFORM_FAILURE, false); 191 PLATFORM_FAILURE, false);
191 192
192 // Get the handle to the component. 193 // Get the handle to the component.
193 AddRef(); // To reflect passing |this| to OMX_GetHandle below.
194 result = omx_gethandle( 194 result = omx_gethandle(
195 &component_handle_, reinterpret_cast<OMX_STRING>(component.get()), 195 &component_handle_, reinterpret_cast<OMX_STRING>(component.get()),
196 this, &omx_accelerator_callbacks); 196 this, &omx_accelerator_callbacks);
197 RETURN_ON_OMX_FAILURE(result, 197 RETURN_ON_OMX_FAILURE(result,
198 "Failed to OMX_GetHandle on: " << component.get(), 198 "Failed to OMX_GetHandle on: " << component.get(),
199 PLATFORM_FAILURE, false); 199 PLATFORM_FAILURE, false);
200 client_state_ = OMX_StateLoaded; 200 client_state_ = OMX_StateLoaded;
201 201
202 component_name_is_nvidia_h264ext_ = !strcmp( 202 component_name_is_nvidia_h264ext_ = !strcmp(
203 reinterpret_cast<char *>(component.get()), 203 reinterpret_cast<char *>(component.get()),
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 } 430 }
431 431
432 void OmxVideoDecodeAccelerator::Reset() { 432 void OmxVideoDecodeAccelerator::Reset() {
433 DCHECK_EQ(message_loop_, MessageLoop::current()); 433 DCHECK_EQ(message_loop_, MessageLoop::current());
434 DCHECK_EQ(current_state_change_, NO_TRANSITION); 434 DCHECK_EQ(current_state_change_, NO_TRANSITION);
435 DCHECK_EQ(client_state_, OMX_StateExecuting); 435 DCHECK_EQ(client_state_, OMX_StateExecuting);
436 current_state_change_ = RESETTING; 436 current_state_change_ = RESETTING;
437 BeginTransitionToState(OMX_StatePause); 437 BeginTransitionToState(OMX_StatePause);
438 } 438 }
439 439
440 void OmxVideoDecodeAccelerator::Destroy() { 440 void OmxVideoDecodeAccelerator::Destroy(
441 scoped_ptr<VideoDecodeAccelerator> self) {
441 DCHECK_EQ(message_loop_, MessageLoop::current()); 442 DCHECK_EQ(message_loop_, MessageLoop::current());
442 if (current_state_change_ == ERRORING || 443 if (current_state_change_ == ERRORING ||
443 current_state_change_ == DESTROYING) { 444 current_state_change_ == DESTROYING) {
444 return; 445 return;
445 } 446 }
446 447
447 DCHECK(current_state_change_ == NO_TRANSITION || 448 DCHECK(current_state_change_ == NO_TRANSITION ||
448 current_state_change_ == FLUSHING || 449 current_state_change_ == FLUSHING ||
449 current_state_change_ == RESETTING) << current_state_change_; 450 current_state_change_ == RESETTING) << current_state_change_;
450 451
451 // If we were never initializeed there's no teardown to do. 452 // If we were never initializeed there's no teardown to do.
452 if (client_state_ == OMX_StateMax) 453 if (client_state_ == OMX_StateMax)
453 return; 454 return;
454 // If we can already call OMX_FreeHandle, simply do so. 455 // If we can already call OMX_FreeHandle, simply do so.
455 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateLoaded) { 456 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateLoaded) {
456 ShutdownComponent(); 457 ShutdownComponent();
457 return; 458 return;
458 } 459 }
459 DCHECK(client_state_ == OMX_StateExecuting || 460 DCHECK(client_state_ == OMX_StateExecuting ||
460 client_state_ == OMX_StateIdle || 461 client_state_ == OMX_StateIdle ||
461 client_state_ == OMX_StatePause); 462 client_state_ == OMX_StatePause);
462 current_state_change_ = DESTROYING; 463 current_state_change_ = DESTROYING;
463 client_ = NULL; 464 client_ = NULL;
464 BeginTransitionToState(OMX_StateIdle); 465 BeginTransitionToState(OMX_StateIdle);
465 BusyLoopInDestroying(); 466 BusyLoopInDestroying(self.Pass());
466 } 467 }
467 468
468 void OmxVideoDecodeAccelerator::BeginTransitionToState( 469 void OmxVideoDecodeAccelerator::BeginTransitionToState(
469 OMX_STATETYPE new_state) { 470 OMX_STATETYPE new_state) {
470 DCHECK_EQ(message_loop_, MessageLoop::current()); 471 DCHECK_EQ(message_loop_, MessageLoop::current());
471 DCHECK_NE(current_state_change_, NO_TRANSITION); 472 DCHECK_NE(current_state_change_, NO_TRANSITION);
472 DCHECK_NE(current_state_change_, ERRORING); 473 DCHECK_NE(current_state_change_, ERRORING);
473 if (current_state_change_ == NO_TRANSITION || 474 if (current_state_change_ == NO_TRANSITION ||
474 current_state_change_ == ERRORING) { 475 current_state_change_ == ERRORING) {
475 return; 476 return;
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 client_->NotifyResetDone(); 556 client_->NotifyResetDone();
556 } 557 }
557 558
558 // Alert: HORROR ahead! OMX shutdown is an asynchronous dance but our clients 559 // 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 560 // enjoy the fire-and-forget nature of a synchronous Destroy() call that
560 // ensures no further callbacks are made. Since the interface between OMX 561 // 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 562 // 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 563 // outlives the shutdown dance, even during process shutdown. We do this by
563 // repeatedly enqueuing a no-op task until shutdown is complete, since 564 // repeatedly enqueuing a no-op task until shutdown is complete, since
564 // MessageLoop's shutdown drains pending tasks. 565 // MessageLoop's shutdown drains pending tasks.
565 void OmxVideoDecodeAccelerator::BusyLoopInDestroying() { 566 void OmxVideoDecodeAccelerator::BusyLoopInDestroying(
567 scoped_ptr<VideoDecodeAccelerator> self) {
566 if (!component_handle_) return; 568 if (!component_handle_) return;
567 // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed 569 // Can't use PostDelayedTask here because MessageLoop doesn't drain delayed
568 // tasks. Instead we sleep for 5ms. Really. 570 // tasks. Instead we sleep for 5ms. Really.
569 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5)); 571 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5));
570 message_loop_->PostTask( 572 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
571 FROM_HERE, base::Bind( 573 &OmxVideoDecodeAccelerator::BusyLoopInDestroying,
572 &OmxVideoDecodeAccelerator::BusyLoopInDestroying, this)); 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 decoder->weak_this(), 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, decoder->weak_this(),
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, decoder->weak_this(),
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