| OLD | NEW |
| 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 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 DCHECK_EQ(client_state_, OMX_StateExecuting); | 503 DCHECK_EQ(client_state_, OMX_StateExecuting); |
| 504 current_state_change_ = FLUSHING; | 504 current_state_change_ = FLUSHING; |
| 505 | 505 |
| 506 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); | 506 Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); |
| 507 } | 507 } |
| 508 | 508 |
| 509 void OmxVideoDecodeAccelerator::OnReachedEOSInFlushing() { | 509 void OmxVideoDecodeAccelerator::OnReachedEOSInFlushing() { |
| 510 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 510 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 511 DCHECK_EQ(client_state_, OMX_StateExecuting); | 511 DCHECK_EQ(client_state_, OMX_StateExecuting); |
| 512 current_state_change_ = NO_TRANSITION; | 512 current_state_change_ = NO_TRANSITION; |
| 513 if (client_) | 513 if (client_.get()) |
| 514 client_->NotifyFlushDone(); | 514 client_->NotifyFlushDone(); |
| 515 } | 515 } |
| 516 | 516 |
| 517 void OmxVideoDecodeAccelerator::FlushIOPorts() { | 517 void OmxVideoDecodeAccelerator::FlushIOPorts() { |
| 518 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 518 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 519 | 519 |
| 520 // Flush input port first. | 520 // Flush input port first. |
| 521 if (!SendCommandToPort(OMX_CommandFlush, input_port_)) | 521 if (!SendCommandToPort(OMX_CommandFlush, input_port_)) |
| 522 return; | 522 return; |
| 523 } | 523 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 639 // dimension mismatch. | 639 // dimension mismatch. |
| 640 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it = | 640 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it = |
| 641 fake_output_buffers_.begin(); | 641 fake_output_buffers_.begin(); |
| 642 it != fake_output_buffers_.end(); ++it) { | 642 it != fake_output_buffers_.end(); ++it) { |
| 643 OMX_BUFFERHEADERTYPE* buffer = *it; | 643 OMX_BUFFERHEADERTYPE* buffer = *it; |
| 644 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer); | 644 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, buffer); |
| 645 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer()", PLATFORM_FAILURE,); | 645 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer()", PLATFORM_FAILURE,); |
| 646 ++output_buffers_at_component_; | 646 ++output_buffers_at_component_; |
| 647 } | 647 } |
| 648 | 648 |
| 649 if (client_) | 649 if (client_.get()) |
| 650 client_->NotifyInitializeDone(); | 650 client_->NotifyInitializeDone(); |
| 651 } | 651 } |
| 652 | 652 |
| 653 void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() { | 653 void OmxVideoDecodeAccelerator::OnReachedPauseInResetting() { |
| 654 DCHECK_EQ(client_state_, OMX_StateExecuting); | 654 DCHECK_EQ(client_state_, OMX_StateExecuting); |
| 655 client_state_ = OMX_StatePause; | 655 client_state_ = OMX_StatePause; |
| 656 FlushIOPorts(); | 656 FlushIOPorts(); |
| 657 } | 657 } |
| 658 | 658 |
| 659 void OmxVideoDecodeAccelerator::DecodeQueuedBitstreamBuffers() { | 659 void OmxVideoDecodeAccelerator::DecodeQueuedBitstreamBuffers() { |
| 660 BitstreamBufferList buffers; | 660 BitstreamBufferList buffers; |
| 661 buffers.swap(queued_bitstream_buffers_); | 661 buffers.swap(queued_bitstream_buffers_); |
| 662 if (current_state_change_ == DESTROYING || | 662 if (current_state_change_ == DESTROYING || |
| 663 current_state_change_ == ERRORING) { | 663 current_state_change_ == ERRORING) { |
| 664 return; | 664 return; |
| 665 } | 665 } |
| 666 for (size_t i = 0; i < buffers.size(); ++i) | 666 for (size_t i = 0; i < buffers.size(); ++i) |
| 667 Decode(buffers[i]); | 667 Decode(buffers[i]); |
| 668 } | 668 } |
| 669 | 669 |
| 670 void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() { | 670 void OmxVideoDecodeAccelerator::OnReachedExecutingInResetting() { |
| 671 DCHECK_EQ(client_state_, OMX_StatePause); | 671 DCHECK_EQ(client_state_, OMX_StatePause); |
| 672 client_state_ = OMX_StateExecuting; | 672 client_state_ = OMX_StateExecuting; |
| 673 current_state_change_ = NO_TRANSITION; | 673 current_state_change_ = NO_TRANSITION; |
| 674 if (!client_) | 674 if (!client_.get()) |
| 675 return; | 675 return; |
| 676 | 676 |
| 677 // Drain queues of input & output buffers held during the reset. | 677 // Drain queues of input & output buffers held during the reset. |
| 678 DecodeQueuedBitstreamBuffers(); | 678 DecodeQueuedBitstreamBuffers(); |
| 679 for (size_t i = 0; i < queued_picture_buffer_ids_.size(); ++i) | 679 for (size_t i = 0; i < queued_picture_buffer_ids_.size(); ++i) |
| 680 ReusePictureBuffer(queued_picture_buffer_ids_[i]); | 680 ReusePictureBuffer(queued_picture_buffer_ids_[i]); |
| 681 queued_picture_buffer_ids_.clear(); | 681 queued_picture_buffer_ids_.clear(); |
| 682 | 682 |
| 683 client_->NotifyResetDone(); | 683 client_->NotifyResetDone(); |
| 684 } | 684 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 component_handle_ = NULL; | 739 component_handle_ = NULL; |
| 740 } | 740 } |
| 741 | 741 |
| 742 void OmxVideoDecodeAccelerator::StopOnError( | 742 void OmxVideoDecodeAccelerator::StopOnError( |
| 743 media::VideoDecodeAccelerator::Error error) { | 743 media::VideoDecodeAccelerator::Error error) { |
| 744 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 744 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 745 | 745 |
| 746 if (current_state_change_ == ERRORING) | 746 if (current_state_change_ == ERRORING) |
| 747 return; | 747 return; |
| 748 | 748 |
| 749 if (client_ && init_begun_) | 749 if (client_.get() && init_begun_) |
| 750 client_->NotifyError(error); | 750 client_->NotifyError(error); |
| 751 client_ptr_factory_.InvalidateWeakPtrs(); | 751 client_ptr_factory_.InvalidateWeakPtrs(); |
| 752 | 752 |
| 753 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax) | 753 if (client_state_ == OMX_StateInvalid || client_state_ == OMX_StateMax) |
| 754 return; | 754 return; |
| 755 | 755 |
| 756 BeginTransitionToState(OMX_StateInvalid); | 756 BeginTransitionToState(OMX_StateInvalid); |
| 757 current_state_change_ = ERRORING; | 757 current_state_change_ = ERRORING; |
| 758 } | 758 } |
| 759 | 759 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 DCHECK(omx_buffer); | 838 DCHECK(omx_buffer); |
| 839 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); | 839 delete reinterpret_cast<media::Picture*>(omx_buffer->pAppPrivate); |
| 840 OMX_ERRORTYPE result = | 840 OMX_ERRORTYPE result = |
| 841 OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); | 841 OMX_FreeBuffer(component_handle_, output_port_, omx_buffer); |
| 842 if (result != OMX_ErrorNone) { | 842 if (result != OMX_ErrorNone) { |
| 843 DLOG(ERROR) << "OMX_FreeBuffer failed: 0x" << std::hex << result; | 843 DLOG(ERROR) << "OMX_FreeBuffer failed: 0x" << std::hex << result; |
| 844 failure_seen = true; | 844 failure_seen = true; |
| 845 } | 845 } |
| 846 texture_to_egl_image_translator_->DestroyEglImage(egl_display_, | 846 texture_to_egl_image_translator_->DestroyEglImage(egl_display_, |
| 847 it->second.egl_image); | 847 it->second.egl_image); |
| 848 if (client_) | 848 if (client_.get()) |
| 849 client_->DismissPictureBuffer(it->first); | 849 client_->DismissPictureBuffer(it->first); |
| 850 } | 850 } |
| 851 pictures_.clear(); | 851 pictures_.clear(); |
| 852 | 852 |
| 853 // Delete pending fake_output_buffers_ | 853 // Delete pending fake_output_buffers_ |
| 854 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it = | 854 for (std::set<OMX_BUFFERHEADERTYPE*>::iterator it = |
| 855 fake_output_buffers_.begin(); | 855 fake_output_buffers_.begin(); |
| 856 it != fake_output_buffers_.end(); ++it) { | 856 it != fake_output_buffers_.end(); ++it) { |
| 857 OMX_BUFFERHEADERTYPE* buffer = *it; | 857 OMX_BUFFERHEADERTYPE* buffer = *it; |
| 858 OMX_ERRORTYPE result = | 858 OMX_ERRORTYPE result = |
| 859 OMX_FreeBuffer(component_handle_, output_port_, buffer); | 859 OMX_FreeBuffer(component_handle_, output_port_, buffer); |
| 860 if (result != OMX_ErrorNone) { | 860 if (result != OMX_ErrorNone) { |
| 861 DLOG(ERROR) << "OMX_FreeBuffer failed: 0x" << std::hex << result; | 861 DLOG(ERROR) << "OMX_FreeBuffer failed: 0x" << std::hex << result; |
| 862 failure_seen = true; | 862 failure_seen = true; |
| 863 } | 863 } |
| 864 } | 864 } |
| 865 fake_output_buffers_.clear(); | 865 fake_output_buffers_.clear(); |
| 866 | 866 |
| 867 // Dequeue pending queued_picture_buffer_ids_ | 867 // Dequeue pending queued_picture_buffer_ids_ |
| 868 if (client_) { | 868 if (client_.get()) { |
| 869 for (size_t i = 0; i < queued_picture_buffer_ids_.size(); ++i) | 869 for (size_t i = 0; i < queued_picture_buffer_ids_.size(); ++i) |
| 870 client_->DismissPictureBuffer(queued_picture_buffer_ids_[i]); | 870 client_->DismissPictureBuffer(queued_picture_buffer_ids_[i]); |
| 871 } | 871 } |
| 872 queued_picture_buffer_ids_.clear(); | 872 queued_picture_buffer_ids_.clear(); |
| 873 | 873 |
| 874 RETURN_ON_FAILURE(!failure_seen, "OMX_FreeBuffer", PLATFORM_FAILURE,); | 874 RETURN_ON_FAILURE(!failure_seen, "OMX_FreeBuffer", PLATFORM_FAILURE,); |
| 875 } | 875 } |
| 876 | 876 |
| 877 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { | 877 void OmxVideoDecodeAccelerator::OnOutputPortDisabled() { |
| 878 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 878 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 879 OMX_PARAM_PORTDEFINITIONTYPE port_format; | 879 OMX_PARAM_PORTDEFINITIONTYPE port_format; |
| 880 InitParam(*this, &port_format); | 880 InitParam(*this, &port_format); |
| 881 port_format.nPortIndex = output_port_; | 881 port_format.nPortIndex = output_port_; |
| 882 OMX_ERRORTYPE result = OMX_GetParameter( | 882 OMX_ERRORTYPE result = OMX_GetParameter( |
| 883 component_handle_, OMX_IndexParamPortDefinition, &port_format); | 883 component_handle_, OMX_IndexParamPortDefinition, &port_format); |
| 884 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter", PLATFORM_FAILURE,); | 884 RETURN_ON_OMX_FAILURE(result, "OMX_GetParameter", PLATFORM_FAILURE,); |
| 885 DCHECK_LE(port_format.nBufferCountMin, kNumPictureBuffers); | 885 DCHECK_LE(port_format.nBufferCountMin, kNumPictureBuffers); |
| 886 | 886 |
| 887 // TODO(fischman): to support mid-stream resize, need to free/dismiss any | 887 // TODO(fischman): to support mid-stream resize, need to free/dismiss any |
| 888 // |pictures_| we already have. Make sure that the shutdown-path agrees with | 888 // |pictures_| we already have. Make sure that the shutdown-path agrees with |
| 889 // this (there's already freeing logic there, which should not be duplicated). | 889 // this (there's already freeing logic there, which should not be duplicated). |
| 890 | 890 |
| 891 // Request picture buffers to be handed to the component. | 891 // Request picture buffers to be handed to the component. |
| 892 // ProvidePictureBuffers() will trigger AssignPictureBuffers, which ultimately | 892 // ProvidePictureBuffers() will trigger AssignPictureBuffers, which ultimately |
| 893 // assigns the textures to the component and re-enables the port. | 893 // assigns the textures to the component and re-enables the port. |
| 894 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; | 894 const OMX_VIDEO_PORTDEFINITIONTYPE& vformat = port_format.format.video; |
| 895 last_requested_picture_buffer_dimensions_.SetSize(vformat.nFrameWidth, | 895 last_requested_picture_buffer_dimensions_.SetSize(vformat.nFrameWidth, |
| 896 vformat.nFrameHeight); | 896 vformat.nFrameHeight); |
| 897 if (client_) { | 897 if (client_.get()) { |
| 898 client_->ProvidePictureBuffers( | 898 client_->ProvidePictureBuffers( |
| 899 kNumPictureBuffers, | 899 kNumPictureBuffers, |
| 900 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight), | 900 gfx::Size(vformat.nFrameWidth, vformat.nFrameHeight), |
| 901 GL_TEXTURE_2D); | 901 GL_TEXTURE_2D); |
| 902 } | 902 } |
| 903 } | 903 } |
| 904 | 904 |
| 905 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { | 905 void OmxVideoDecodeAccelerator::OnOutputPortEnabled() { |
| 906 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 906 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 907 | 907 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 // During the transition from Executing to Idle, and during port-flushing, all | 976 // During the transition from Executing to Idle, and during port-flushing, all |
| 977 // pictures are sent back through here. Avoid giving them to the client. | 977 // pictures are sent back through here. Avoid giving them to the client. |
| 978 if (current_state_change_ == RESETTING) { | 978 if (current_state_change_ == RESETTING) { |
| 979 queued_picture_buffer_ids_.push_back(picture_buffer_id); | 979 queued_picture_buffer_ids_.push_back(picture_buffer_id); |
| 980 return; | 980 return; |
| 981 } | 981 } |
| 982 | 982 |
| 983 DCHECK(picture); | 983 DCHECK(picture); |
| 984 // See Decode() for an explanation of this abuse of nTimeStamp. | 984 // See Decode() for an explanation of this abuse of nTimeStamp. |
| 985 picture->set_bitstream_buffer_id(buffer->nTimeStamp); | 985 picture->set_bitstream_buffer_id(buffer->nTimeStamp); |
| 986 if (client_) | 986 if (client_.get()) |
| 987 client_->PictureReady(*picture); | 987 client_->PictureReady(*picture); |
| 988 } | 988 } |
| 989 | 989 |
| 990 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( | 990 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( |
| 991 OMX_BUFFERHEADERTYPE* buffer) { | 991 OMX_BUFFERHEADERTYPE* buffer) { |
| 992 TRACE_EVENT1("Video Decoder", "OVDA::EmptyBufferDoneTask", | 992 TRACE_EVENT1("Video Decoder", "OVDA::EmptyBufferDoneTask", |
| 993 "Buffer id", buffer->nTimeStamp); | 993 "Buffer id", buffer->nTimeStamp); |
| 994 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 994 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 995 DCHECK_GT(input_buffers_at_component_, 0); | 995 DCHECK_GT(input_buffers_at_component_, 0); |
| 996 free_input_buffers_.push(buffer); | 996 free_input_buffers_.push(buffer); |
| 997 input_buffers_at_component_--; | 997 input_buffers_at_component_--; |
| 998 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) | 998 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) |
| 999 return; | 999 return; |
| 1000 | 1000 |
| 1001 // Retrieve the corresponding BitstreamBuffer's id and notify the client of | 1001 // Retrieve the corresponding BitstreamBuffer's id and notify the client of |
| 1002 // its completion. | 1002 // its completion. |
| 1003 SharedMemoryAndId* input_buffer_details = | 1003 SharedMemoryAndId* input_buffer_details = |
| 1004 reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate); | 1004 reinterpret_cast<SharedMemoryAndId*>(buffer->pAppPrivate); |
| 1005 DCHECK(input_buffer_details); | 1005 DCHECK(input_buffer_details); |
| 1006 buffer->pAppPrivate = NULL; | 1006 buffer->pAppPrivate = NULL; |
| 1007 if (client_) | 1007 if (client_.get()) |
| 1008 client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second); | 1008 client_->NotifyEndOfBitstreamBuffer(input_buffer_details->second); |
| 1009 delete input_buffer_details; | 1009 delete input_buffer_details; |
| 1010 | 1010 |
| 1011 DecodeQueuedBitstreamBuffers(); | 1011 DecodeQueuedBitstreamBuffers(); |
| 1012 } | 1012 } |
| 1013 | 1013 |
| 1014 void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) { | 1014 void OmxVideoDecodeAccelerator::DispatchStateReached(OMX_STATETYPE reached) { |
| 1015 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 1015 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 1016 switch (current_state_change_) { | 1016 switch (current_state_change_) { |
| 1017 case INITIALIZING: | 1017 case INITIALIZING: |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 OMX_COMMANDTYPE cmd, int port_index) { | 1250 OMX_COMMANDTYPE cmd, int port_index) { |
| 1251 DCHECK_EQ(message_loop_, base::MessageLoop::current()); | 1251 DCHECK_EQ(message_loop_, base::MessageLoop::current()); |
| 1252 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, | 1252 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, |
| 1253 cmd, port_index, 0); | 1253 cmd, port_index, 0); |
| 1254 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, | 1254 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, |
| 1255 PLATFORM_FAILURE, false); | 1255 PLATFORM_FAILURE, false); |
| 1256 return true; | 1256 return true; |
| 1257 } | 1257 } |
| 1258 | 1258 |
| 1259 } // namespace content | 1259 } // namespace content |
| OLD | NEW |