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 |