OLD | NEW |
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/debug/trace_event.h" |
7 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
8 #include "base/string_util.h" | 9 #include "base/string_util.h" |
9 #include "content/common/gpu/gpu_channel.h" | 10 #include "content/common/gpu/gpu_channel.h" |
10 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h" | 11 #include "content/common/gpu/media/gles2_texture_to_egl_image_translator.h" |
11 #include "media/base/bitstream_buffer.h" | 12 #include "media/base/bitstream_buffer.h" |
12 #include "media/video/picture.h" | 13 #include "media/video/picture.h" |
13 | 14 |
14 // Helper typedef for input buffers. This is used as the pAppPrivate field of | 15 // Helper typedef for input buffers. This is used as the pAppPrivate field of |
15 // OMX_BUFFERHEADERTYPEs of input buffers, to point to the data associated with | 16 // OMX_BUFFERHEADERTYPEs of input buffers, to point to the data associated with |
16 // them. | 17 // them. |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 buffer->nTimeStamp = -1; | 271 buffer->nTimeStamp = -1; |
271 buffer->nOutputPortIndex = output_port_; | 272 buffer->nOutputPortIndex = output_port_; |
272 CHECK(fake_output_buffers_.insert(buffer).second); | 273 CHECK(fake_output_buffers_.insert(buffer).second); |
273 } | 274 } |
274 | 275 |
275 return true; | 276 return true; |
276 } | 277 } |
277 | 278 |
278 void OmxVideoDecodeAccelerator::Decode( | 279 void OmxVideoDecodeAccelerator::Decode( |
279 const media::BitstreamBuffer& bitstream_buffer) { | 280 const media::BitstreamBuffer& bitstream_buffer) { |
| 281 TRACE_EVENT1("Video Decoder", "OVDA::Decode", |
| 282 "Buffer id", bitstream_buffer.id()); |
280 DCHECK_EQ(message_loop_, MessageLoop::current()); | 283 DCHECK_EQ(message_loop_, MessageLoop::current()); |
281 DCHECK(!free_input_buffers_.empty()); | 284 DCHECK(!free_input_buffers_.empty()); |
282 | 285 |
283 if (current_state_change_ == RESETTING || | 286 if (current_state_change_ == RESETTING || |
284 !queued_bitstream_buffers_.empty()) { | 287 !queued_bitstream_buffers_.empty()) { |
285 queued_bitstream_buffers_.push_back(bitstream_buffer); | 288 queued_bitstream_buffers_.push_back(bitstream_buffer); |
286 return; | 289 return; |
287 } | 290 } |
288 | 291 |
289 RETURN_ON_FAILURE(current_state_change_ == NO_TRANSITION && | 292 RETURN_ON_FAILURE(current_state_change_ == NO_TRANSITION && |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 DCHECK_EQ(pictures_.size(), kNumPictureBuffers); | 349 DCHECK_EQ(pictures_.size(), kNumPictureBuffers); |
347 | 350 |
348 // These do their own RETURN_ON_FAILURE dances. | 351 // These do their own RETURN_ON_FAILURE dances. |
349 if (!AllocateOutputBuffers()) | 352 if (!AllocateOutputBuffers()) |
350 return; | 353 return; |
351 if (!SendCommandToPort(OMX_CommandPortEnable, output_port_)) | 354 if (!SendCommandToPort(OMX_CommandPortEnable, output_port_)) |
352 return; | 355 return; |
353 } | 356 } |
354 | 357 |
355 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { | 358 void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) { |
| 359 TRACE_EVENT1("Video Decoder", "OVDA::ReusePictureBuffer", |
| 360 "Picture id", picture_buffer_id); |
356 DCHECK_EQ(message_loop_, MessageLoop::current()); | 361 DCHECK_EQ(message_loop_, MessageLoop::current()); |
357 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,); | 362 RETURN_ON_FAILURE(CanFillBuffer(), "Can't fill buffer", ILLEGAL_STATE,); |
358 | 363 |
359 OutputPictureById::iterator it = pictures_.find(picture_buffer_id); | 364 OutputPictureById::iterator it = pictures_.find(picture_buffer_id); |
360 RETURN_ON_FAILURE(it != pictures_.end(), | 365 RETURN_ON_FAILURE(it != pictures_.end(), |
361 "Missing picture buffer id: " << picture_buffer_id, | 366 "Missing picture buffer id: " << picture_buffer_id, |
362 INVALID_ARGUMENT,); | 367 INVALID_ARGUMENT,); |
363 OutputPicture& output_picture = it->second; | 368 OutputPicture& output_picture = it->second; |
364 | 369 |
365 ++output_buffers_at_component_; | 370 ++output_buffers_at_component_; |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 omx_buffer->nOutputPortIndex = output_port_; | 734 omx_buffer->nOutputPortIndex = output_port_; |
730 ++output_buffers_at_component_; | 735 ++output_buffers_at_component_; |
731 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer); | 736 OMX_ERRORTYPE result = OMX_FillThisBuffer(component_handle_, omx_buffer); |
732 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed", | 737 RETURN_ON_OMX_FAILURE(result, "OMX_FillThisBuffer() failed", |
733 PLATFORM_FAILURE,); | 738 PLATFORM_FAILURE,); |
734 } | 739 } |
735 } | 740 } |
736 | 741 |
737 void OmxVideoDecodeAccelerator::FillBufferDoneTask( | 742 void OmxVideoDecodeAccelerator::FillBufferDoneTask( |
738 OMX_BUFFERHEADERTYPE* buffer) { | 743 OMX_BUFFERHEADERTYPE* buffer) { |
| 744 media::Picture* picture = |
| 745 reinterpret_cast<media::Picture*>(buffer->pAppPrivate); |
| 746 int picture_buffer_id = picture ? picture->picture_buffer_id() : -1; |
| 747 TRACE_EVENT2("Video Decoder", "OVDA::FillBufferDoneTask", |
| 748 "Buffer id", buffer->nTimeStamp, |
| 749 "Picture id", picture_buffer_id); |
739 DCHECK_EQ(message_loop_, MessageLoop::current()); | 750 DCHECK_EQ(message_loop_, MessageLoop::current()); |
740 DCHECK_GT(output_buffers_at_component_, 0); | 751 DCHECK_GT(output_buffers_at_component_, 0); |
741 --output_buffers_at_component_; | 752 --output_buffers_at_component_; |
742 | 753 |
743 if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) { | 754 if (fake_output_buffers_.size() && fake_output_buffers_.count(buffer)) { |
744 CHECK_EQ(fake_output_buffers_.erase(buffer), 1U); | 755 CHECK_EQ(fake_output_buffers_.erase(buffer), 1U); |
745 OMX_ERRORTYPE result = | 756 OMX_ERRORTYPE result = |
746 OMX_FreeBuffer(component_handle_, output_port_, buffer); | 757 OMX_FreeBuffer(component_handle_, output_port_, buffer); |
747 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed", PLATFORM_FAILURE,); | 758 RETURN_ON_OMX_FAILURE(result, "OMX_FreeBuffer failed", PLATFORM_FAILURE,); |
748 return; | 759 return; |
749 } | 760 } |
750 CHECK(!fake_output_buffers_.size()); | 761 CHECK(!fake_output_buffers_.size()); |
751 | 762 |
752 if (current_state_change_ == FLUSHING && | 763 if (current_state_change_ == FLUSHING && |
753 buffer->nFlags & OMX_BUFFERFLAG_EOS) { | 764 buffer->nFlags & OMX_BUFFERFLAG_EOS) { |
754 DCHECK(!saw_eos_during_flush_); | 765 DCHECK(!saw_eos_during_flush_); |
755 saw_eos_during_flush_ = true; | 766 saw_eos_during_flush_ = true; |
756 } | 767 } |
757 | 768 |
758 DCHECK(buffer->pAppPrivate); | |
759 media::Picture* picture = | |
760 reinterpret_cast<media::Picture*>(buffer->pAppPrivate); | |
761 int picture_buffer_id = picture->picture_buffer_id(); | |
762 | |
763 // During the transition from Executing to Idle, and during port-flushing, all | 769 // During the transition from Executing to Idle, and during port-flushing, all |
764 // pictures are sent back through here. Avoid giving them to the client. | 770 // pictures are sent back through here. Avoid giving them to the client. |
765 // Also avoid sending the (fake) EOS buffer to the client. | 771 // Also avoid sending the (fake) EOS buffer to the client. |
766 if ((current_state_change_ != NO_TRANSITION && | 772 if ((current_state_change_ != NO_TRANSITION && |
767 current_state_change_ != FLUSHING) || | 773 current_state_change_ != FLUSHING) || |
768 saw_eos_during_flush_) { | 774 saw_eos_during_flush_) { |
769 if (current_state_change_ == RESETTING) | 775 if (current_state_change_ == RESETTING) |
770 queued_picture_buffer_ids_.push_back(picture_buffer_id); | 776 queued_picture_buffer_ids_.push_back(picture_buffer_id); |
771 return; | 777 return; |
772 } | 778 } |
773 | 779 |
| 780 DCHECK(picture); |
774 // See Decode() for an explanation of this abuse of nTimeStamp. | 781 // See Decode() for an explanation of this abuse of nTimeStamp. |
775 picture->set_bitstream_buffer_id(buffer->nTimeStamp); | 782 picture->set_bitstream_buffer_id(buffer->nTimeStamp); |
776 if (client_) | 783 if (client_) |
777 client_->PictureReady(*picture); | 784 client_->PictureReady(*picture); |
778 } | 785 } |
779 | 786 |
780 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( | 787 void OmxVideoDecodeAccelerator::EmptyBufferDoneTask( |
781 OMX_BUFFERHEADERTYPE* buffer) { | 788 OMX_BUFFERHEADERTYPE* buffer) { |
| 789 TRACE_EVENT1("Video Decoder", "OVDA::EmptyBufferDoneTask", |
| 790 "Buffer id", buffer->nTimeStamp); |
782 DCHECK_EQ(message_loop_, MessageLoop::current()); | 791 DCHECK_EQ(message_loop_, MessageLoop::current()); |
783 DCHECK_GT(input_buffers_at_component_, 0); | 792 DCHECK_GT(input_buffers_at_component_, 0); |
784 free_input_buffers_.push(buffer); | 793 free_input_buffers_.push(buffer); |
785 input_buffers_at_component_--; | 794 input_buffers_at_component_--; |
786 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) | 795 if (buffer->nFlags & OMX_BUFFERFLAG_EOS) |
787 return; | 796 return; |
788 | 797 |
789 // Retrieve the corresponding BitstreamBuffer's id and notify the client of | 798 // Retrieve the corresponding BitstreamBuffer's id and notify the client of |
790 // its completion. | 799 // its completion. |
791 SharedMemoryAndId* input_buffer_details = | 800 SharedMemoryAndId* input_buffer_details = |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
962 decoder, &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, | 971 decoder, &OmxVideoDecodeAccelerator::EventHandlerCompleteTask, |
963 event, data1, data2)); | 972 event, data1, data2)); |
964 return OMX_ErrorNone; | 973 return OMX_ErrorNone; |
965 } | 974 } |
966 | 975 |
967 // static | 976 // static |
968 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback( | 977 OMX_ERRORTYPE OmxVideoDecodeAccelerator::EmptyBufferCallback( |
969 OMX_HANDLETYPE component, | 978 OMX_HANDLETYPE component, |
970 OMX_PTR priv_data, | 979 OMX_PTR priv_data, |
971 OMX_BUFFERHEADERTYPE* buffer) { | 980 OMX_BUFFERHEADERTYPE* buffer) { |
| 981 TRACE_EVENT1("Video Decoder", "OVDA::EmptyBufferCallback", |
| 982 "Buffer id", buffer->nTimeStamp); |
972 // Called on the OMX thread. | 983 // Called on the OMX thread. |
973 OmxVideoDecodeAccelerator* decoder = | 984 OmxVideoDecodeAccelerator* decoder = |
974 static_cast<OmxVideoDecodeAccelerator*>(priv_data); | 985 static_cast<OmxVideoDecodeAccelerator*>(priv_data); |
975 DCHECK_EQ(component, decoder->component_handle_); | 986 DCHECK_EQ(component, decoder->component_handle_); |
976 decoder->message_loop_->PostTask( | 987 decoder->message_loop_->PostTask( |
977 FROM_HERE, | 988 FROM_HERE, |
978 NewRunnableMethod(decoder, | 989 NewRunnableMethod(decoder, |
979 &OmxVideoDecodeAccelerator::EmptyBufferDoneTask, | 990 &OmxVideoDecodeAccelerator::EmptyBufferDoneTask, |
980 buffer)); | 991 buffer)); |
981 return OMX_ErrorNone; | 992 return OMX_ErrorNone; |
982 } | 993 } |
983 | 994 |
984 // static | 995 // static |
985 OMX_ERRORTYPE OmxVideoDecodeAccelerator::FillBufferCallback( | 996 OMX_ERRORTYPE OmxVideoDecodeAccelerator::FillBufferCallback( |
986 OMX_HANDLETYPE component, | 997 OMX_HANDLETYPE component, |
987 OMX_PTR priv_data, | 998 OMX_PTR priv_data, |
988 OMX_BUFFERHEADERTYPE* buffer) { | 999 OMX_BUFFERHEADERTYPE* buffer) { |
| 1000 media::Picture* picture = |
| 1001 reinterpret_cast<media::Picture*>(buffer->pAppPrivate); |
| 1002 int picture_buffer_id = picture ? picture->picture_buffer_id() : -1; |
| 1003 TRACE_EVENT2("Video Decoder", "OVDA::FillBufferCallback", |
| 1004 "Buffer id", buffer->nTimeStamp, |
| 1005 "Picture id", picture_buffer_id); |
989 // Called on the OMX thread. | 1006 // Called on the OMX thread. |
990 OmxVideoDecodeAccelerator* decoder = | 1007 OmxVideoDecodeAccelerator* decoder = |
991 static_cast<OmxVideoDecodeAccelerator*>(priv_data); | 1008 static_cast<OmxVideoDecodeAccelerator*>(priv_data); |
992 DCHECK_EQ(component, decoder->component_handle_); | 1009 DCHECK_EQ(component, decoder->component_handle_); |
993 decoder->message_loop_->PostTask( | 1010 decoder->message_loop_->PostTask( |
994 FROM_HERE, | 1011 FROM_HERE, |
995 NewRunnableMethod(decoder, | 1012 NewRunnableMethod(decoder, |
996 &OmxVideoDecodeAccelerator::FillBufferDoneTask, | 1013 &OmxVideoDecodeAccelerator::FillBufferDoneTask, |
997 buffer)); | 1014 buffer)); |
998 return OMX_ErrorNone; | 1015 return OMX_ErrorNone; |
(...skipping 12 matching lines...) Expand all Loading... |
1011 | 1028 |
1012 bool OmxVideoDecodeAccelerator::SendCommandToPort( | 1029 bool OmxVideoDecodeAccelerator::SendCommandToPort( |
1013 OMX_COMMANDTYPE cmd, int port_index) { | 1030 OMX_COMMANDTYPE cmd, int port_index) { |
1014 DCHECK_EQ(message_loop_, MessageLoop::current()); | 1031 DCHECK_EQ(message_loop_, MessageLoop::current()); |
1015 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, | 1032 OMX_ERRORTYPE result = OMX_SendCommand(component_handle_, |
1016 cmd, port_index, 0); | 1033 cmd, port_index, 0); |
1017 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, | 1034 RETURN_ON_OMX_FAILURE(result, "SendCommand() failed" << cmd, |
1018 PLATFORM_FAILURE, false); | 1035 PLATFORM_FAILURE, false); |
1019 return true; | 1036 return true; |
1020 } | 1037 } |
OLD | NEW |