Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/android_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
| 13 #include "base/callback_helpers.h" | |
| 13 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 14 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 16 #include "base/logging.h" |
| 16 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| 17 #include "base/metrics/histogram.h" | 18 #include "base/metrics/histogram.h" |
| 18 #include "base/task_runner_util.h" | 19 #include "base/task_runner_util.h" |
| 19 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
| 20 #include "content/common/gpu/media/android_copying_backing_strategy.h" | 21 #include "content/common/gpu/media/android_copying_backing_strategy.h" |
| 21 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h " | 22 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h " |
| 22 #include "content/common/gpu/media/avda_return_on_failure.h" | 23 #include "content/common/gpu/media/avda_return_on_failure.h" |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 | 286 |
| 286 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( | 287 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
| 287 const MakeGLContextCurrentCallback& make_context_current_cb, | 288 const MakeGLContextCurrentCallback& make_context_current_cb, |
| 288 const GetGLES2DecoderCallback& get_gles2_decoder_cb) | 289 const GetGLES2DecoderCallback& get_gles2_decoder_cb) |
| 289 : client_(NULL), | 290 : client_(NULL), |
| 290 make_context_current_cb_(make_context_current_cb), | 291 make_context_current_cb_(make_context_current_cb), |
| 291 get_gles2_decoder_cb_(get_gles2_decoder_cb), | 292 get_gles2_decoder_cb_(get_gles2_decoder_cb), |
| 292 is_encrypted_(false), | 293 is_encrypted_(false), |
| 293 state_(NO_ERROR), | 294 state_(NO_ERROR), |
| 294 picturebuffers_requested_(false), | 295 picturebuffers_requested_(false), |
| 296 drain_type_(DRAIN_TYPE_NONE), | |
| 295 media_drm_bridge_cdm_context_(nullptr), | 297 media_drm_bridge_cdm_context_(nullptr), |
| 296 cdm_registration_id_(0), | 298 cdm_registration_id_(0), |
| 297 pending_input_buf_index_(-1), | 299 pending_input_buf_index_(-1), |
| 298 error_sequence_token_(0), | 300 error_sequence_token_(0), |
| 299 defer_errors_(false), | 301 defer_errors_(false), |
| 300 deferred_initialization_pending_(false), | 302 deferred_initialization_pending_(false), |
| 301 weak_this_factory_(this) {} | 303 weak_this_factory_(this) {} |
| 302 | 304 |
| 303 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 305 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
| 304 DCHECK(thread_checker_.CalledOnValidThread()); | 306 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 521 | 523 |
| 522 DCHECK_NE(input_buf_index, -1); | 524 DCHECK_NE(input_buf_index, -1); |
| 523 | 525 |
| 524 media::BitstreamBuffer bitstream_buffer = pending_bitstream_buffers_.front(); | 526 media::BitstreamBuffer bitstream_buffer = pending_bitstream_buffers_.front(); |
| 525 | 527 |
| 526 if (bitstream_buffer.id() == -1) { | 528 if (bitstream_buffer.id() == -1) { |
| 527 pending_bitstream_buffers_.pop(); | 529 pending_bitstream_buffers_.pop(); |
| 528 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", | 530 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
| 529 pending_bitstream_buffers_.size()); | 531 pending_bitstream_buffers_.size()); |
| 530 | 532 |
| 531 DCHECK_NE(state_, ERROR); | |
| 532 state_ = WAITING_FOR_EOS; | |
| 533 media_codec_->QueueEOS(input_buf_index); | 533 media_codec_->QueueEOS(input_buf_index); |
| 534 return true; | 534 return true; |
| 535 } | 535 } |
| 536 | 536 |
| 537 std::unique_ptr<SharedMemoryRegion> shm; | 537 std::unique_ptr<SharedMemoryRegion> shm; |
| 538 | 538 |
| 539 if (pending_input_buf_index_ == -1) { | 539 if (pending_input_buf_index_ == -1) { |
| 540 // When |pending_input_buf_index_| is not -1, the buffer is already dequeued | 540 // When |pending_input_buf_index_| is not -1, the buffer is already dequeued |
| 541 // from MediaCodec, filled with data and bitstream_buffer.handle() is | 541 // from MediaCodec, filled with data and bitstream_buffer.handle() is |
| 542 // closed. | 542 // closed. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 641 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput"); | 641 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput"); |
| 642 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( | 642 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( |
| 643 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, | 643 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, |
| 644 &eos, NULL); | 644 &eos, NULL); |
| 645 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status, | 645 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status, |
| 646 "presentation_timestamp (ms)", | 646 "presentation_timestamp (ms)", |
| 647 presentation_timestamp.InMilliseconds()); | 647 presentation_timestamp.InMilliseconds()); |
| 648 | 648 |
| 649 switch (status) { | 649 switch (status) { |
| 650 case media::MEDIA_CODEC_ERROR: | 650 case media::MEDIA_CODEC_ERROR: |
| 651 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); | 651 // Do not post an error if we are draining for reset. Instead, try |
|
watk
2016/04/18 21:12:18
Remove "try" since we are unconditionally running
Tima Vaisburd
2016/04/20 01:54:19
Done.
| |
| 652 // to run the drain completion callback. | |
| 653 if (IsDrainingForReset()) { | |
| 654 state_ = ERROR; | |
| 655 DCHECK(!drain_completed_cb_.is_null()); | |
| 656 base::ResetAndReturn(&drain_completed_cb_).Run(); | |
| 657 } else { | |
| 658 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); | |
| 659 } | |
| 652 return false; | 660 return false; |
| 653 | 661 |
| 654 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 662 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
| 655 return false; | 663 return false; |
| 656 | 664 |
| 657 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { | 665 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { |
| 666 if (IsDrainingForReset()) | |
| 667 return true; | |
| 668 | |
| 658 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { | 669 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { |
| 659 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); | 670 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); |
| 660 return false; | 671 return false; |
| 661 } | 672 } |
| 673 | |
| 662 DVLOG(3) << __FUNCTION__ | 674 DVLOG(3) << __FUNCTION__ |
| 663 << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString(); | 675 << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString(); |
| 664 | 676 |
| 665 // Don't request picture buffers if we already have some. This avoids | 677 // Don't request picture buffers if we already have some. This avoids |
| 666 // having to dismiss the existing buffers which may actively reference | 678 // having to dismiss the existing buffers which may actively reference |
| 667 // decoded images. Breaking their connection to the decoded image will | 679 // decoded images. Breaking their connection to the decoded image will |
| 668 // cause rendering of black frames. Instead, we let the existing | 680 // cause rendering of black frames. Instead, we let the existing |
| 669 // PictureBuffers live on and we simply update their size the next time | 681 // PictureBuffers live on and we simply update their size the next time |
| 670 // they're attachted to an image of the new resolution. See the | 682 // they're attachted to an image of the new resolution. See the |
| 671 // size update in |SendDecodedFrameToClient| and https://crbug/587994. | 683 // size update in |SendDecodedFrameToClient| and https://crbug/587994. |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 700 if (eos) { | 712 if (eos) { |
| 701 DVLOG(3) << __FUNCTION__ << ": Resetting codec state after EOS"; | 713 DVLOG(3) << __FUNCTION__ << ": Resetting codec state after EOS"; |
| 702 | 714 |
| 703 // If we were waiting for an EOS, clear the state and reset the MediaCodec | 715 // If we were waiting for an EOS, clear the state and reset the MediaCodec |
| 704 // as normal. Otherwise, enter the ERROR state which will force destruction | 716 // as normal. Otherwise, enter the ERROR state which will force destruction |
| 705 // of MediaCodec during ResetCodecState(). | 717 // of MediaCodec during ResetCodecState(). |
| 706 // | 718 // |
| 707 // Some Android platforms seem to send an EOS buffer even when we're not | 719 // Some Android platforms seem to send an EOS buffer even when we're not |
| 708 // expecting it. In this case, destroy and reset the codec but don't notify | 720 // expecting it. In this case, destroy and reset the codec but don't notify |
| 709 // flush done since it violates the state machine. http://crbug.com/585959. | 721 // flush done since it violates the state machine. http://crbug.com/585959. |
| 710 const bool was_waiting_for_eos = state_ == WAITING_FOR_EOS; | 722 if (drain_completed_cb_.is_null()) { |
| 711 state_ = was_waiting_for_eos ? NO_ERROR : ERROR; | 723 // Unexpected EOS. |
| 712 | 724 state_ = ERROR; |
| 713 ResetCodecState(); | 725 ResetCodecState(base::Closure()); |
| 714 // |media_codec_| might still be null. | 726 } else { |
| 715 if (was_waiting_for_eos) { | 727 base::ResetAndReturn(&drain_completed_cb_).Run(); |
| 716 base::MessageLoop::current()->PostTask( | |
| 717 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, | |
| 718 weak_this_factory_.GetWeakPtr())); | |
| 719 } | 728 } |
| 720 return false; | 729 return false; |
| 721 } | 730 } |
| 722 | 731 |
| 732 if (IsDrainingForReset()) { | |
| 733 media_codec_->ReleaseOutputBuffer(buf_index, false); | |
| 734 return true; | |
| 735 } | |
| 736 | |
| 723 if (!picturebuffers_requested_) { | 737 if (!picturebuffers_requested_) { |
| 724 // If, somehow, we get a decoded frame back before a FORMAT_CHANGED | 738 // If, somehow, we get a decoded frame back before a FORMAT_CHANGED |
| 725 // message, then we might not have any picture buffers to use. This | 739 // message, then we might not have any picture buffers to use. This |
| 726 // isn't supposed to happen (see EncodeDecodeTest.java#617). | 740 // isn't supposed to happen (see EncodeDecodeTest.java#617). |
| 727 // Log a metric to see how common this is. | 741 // Log a metric to see how common this is. |
| 728 RecordFormatChangedMetric(FormatChangedValue::MissingFormatChanged); | 742 RecordFormatChangedMetric(FormatChangedValue::MissingFormatChanged); |
| 729 media_codec_->ReleaseOutputBuffer(buf_index, false); | 743 media_codec_->ReleaseOutputBuffer(buf_index, false); |
| 730 POST_ERROR(PLATFORM_FAILURE, "Dequeued buffers before FORMAT_CHANGED."); | 744 POST_ERROR(PLATFORM_FAILURE, "Dequeued buffers before FORMAT_CHANGED."); |
| 731 return false; | 745 return false; |
| 732 } | 746 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 841 void AndroidVideoDecodeAccelerator::DecodeBuffer( | 855 void AndroidVideoDecodeAccelerator::DecodeBuffer( |
| 842 const media::BitstreamBuffer& bitstream_buffer) { | 856 const media::BitstreamBuffer& bitstream_buffer) { |
| 843 pending_bitstream_buffers_.push(bitstream_buffer); | 857 pending_bitstream_buffers_.push(bitstream_buffer); |
| 844 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", | 858 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
| 845 pending_bitstream_buffers_.size()); | 859 pending_bitstream_buffers_.size()); |
| 846 | 860 |
| 847 DoIOTask(true); | 861 DoIOTask(true); |
| 848 } | 862 } |
| 849 | 863 |
| 850 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { | 864 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { |
| 851 client_->ProvidePictureBuffers(kNumPictureBuffers, 1, | 865 if (client_) |
| 852 strategy_->GetPictureBufferSize(), | 866 client_->ProvidePictureBuffers(kNumPictureBuffers, 1, |
| 853 strategy_->GetTextureTarget()); | 867 strategy_->GetPictureBufferSize(), |
| 868 strategy_->GetTextureTarget()); | |
| 854 } | 869 } |
| 855 | 870 |
| 856 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( | 871 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( |
| 857 const std::vector<media::PictureBuffer>& buffers) { | 872 const std::vector<media::PictureBuffer>& buffers) { |
| 858 DCHECK(thread_checker_.CalledOnValidThread()); | 873 DCHECK(thread_checker_.CalledOnValidThread()); |
| 859 DCHECK(output_picture_buffers_.empty()); | 874 DCHECK(output_picture_buffers_.empty()); |
| 860 DCHECK(free_picture_ids_.empty()); | 875 DCHECK(free_picture_ids_.empty()); |
| 861 | 876 |
| 862 if (buffers.size() < kNumPictureBuffers) { | 877 if (buffers.size() < kNumPictureBuffers) { |
| 863 POST_ERROR(INVALID_ARGUMENT, "Not enough picture buffers assigned."); | 878 POST_ERROR(INVALID_ARGUMENT, "Not enough picture buffers assigned."); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 901 return; | 916 return; |
| 902 } | 917 } |
| 903 | 918 |
| 904 strategy_->ReuseOnePictureBuffer(i->second); | 919 strategy_->ReuseOnePictureBuffer(i->second); |
| 905 DoIOTask(true); | 920 DoIOTask(true); |
| 906 } | 921 } |
| 907 | 922 |
| 908 void AndroidVideoDecodeAccelerator::Flush() { | 923 void AndroidVideoDecodeAccelerator::Flush() { |
| 909 DCHECK(thread_checker_.CalledOnValidThread()); | 924 DCHECK(thread_checker_.CalledOnValidThread()); |
| 910 | 925 |
| 911 DecodeBuffer(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); | 926 base::Closure notification_cb = media::BindToCurrentLoop( |
| 927 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, | |
| 928 weak_this_factory_.GetWeakPtr())); | |
| 929 | |
| 930 RequestDrain(DRAIN_FOR_FLUSH, | |
| 931 base::Bind(&AndroidVideoDecodeAccelerator::ResetCodecState, | |
| 932 weak_this_factory_.GetWeakPtr(), notification_cb)); | |
| 912 } | 933 } |
| 913 | 934 |
| 914 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { | 935 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { |
| 915 DCHECK(thread_checker_.CalledOnValidThread()); | 936 DCHECK(thread_checker_.CalledOnValidThread()); |
| 916 | 937 |
| 917 // It's probably okay just to return here, since the codec will be configured | 938 // It's probably okay just to return here, since the codec will be configured |
| 918 // asynchronously. It's unclear that any state for the new request could | 939 // asynchronously. It's unclear that any state for the new request could |
| 919 // be different, unless somebody modifies |codec_config_| while we're already | 940 // be different, unless somebody modifies |codec_config_| while we're already |
| 920 // waiting for a codec. One shouldn't do that for thread safety. | 941 // waiting for a codec. One shouldn't do that for thread safety. |
| 921 DCHECK_NE(state_, WAITING_FOR_CODEC); | 942 DCHECK_NE(state_, WAITING_FOR_CODEC); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 989 if (!media_codec_) { | 1010 if (!media_codec_) { |
| 990 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec."); | 1011 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec."); |
| 991 return; | 1012 return; |
| 992 } | 1013 } |
| 993 | 1014 |
| 994 state_ = NO_ERROR; | 1015 state_ = NO_ERROR; |
| 995 | 1016 |
| 996 ManageTimer(true); | 1017 ManageTimer(true); |
| 997 } | 1018 } |
| 998 | 1019 |
| 999 void AndroidVideoDecodeAccelerator::ResetCodecState() { | 1020 void AndroidVideoDecodeAccelerator::RequestDrain( |
|
watk
2016/04/18 21:12:18
IMO RequestDrain makes it sound like there's a cha
Tima Vaisburd
2016/04/20 01:54:19
Renamed to StartCodecDrain(). I have to strong pre
| |
| 1021 DrainType drain_type, | |
| 1022 base::Closure drain_completed_cb) { | |
|
watk
2016/04/18 21:12:18
I'm wondering if it would be clearer to structure
Tima Vaisburd
2016/04/20 01:54:19
Yes, thank you! I tried now, and I think this way
| |
| 1023 DVLOG(2) << __FUNCTION__ << " drain_type:" << drain_type; | |
| 1024 | |
| 1025 // We assume that DRAIN_FOR_FLUSH and DRAIN_FOR_RESET cannot come while | |
| 1026 // another drain request is present, but DRAIN_FOR_DESTROY can. | |
| 1027 DCHECK(drain_completed_cb_.is_null() || drain_type == DRAIN_FOR_DESTROY); | |
| 1028 | |
| 1029 drain_completed_cb_ = drain_completed_cb; | |
| 1030 drain_type_ = drain_type; | |
| 1031 DecodeBuffer(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); | |
|
watk
2016/04/18 21:12:18
If there's an EOS already queued for a DRAIN_FOR_F
Tima Vaisburd
2016/04/20 01:54:19
Done.
| |
| 1032 } | |
| 1033 | |
| 1034 bool AndroidVideoDecodeAccelerator::IsDrainingForReset() const { | |
| 1035 return !drain_completed_cb_.is_null() && | |
| 1036 (drain_type_ == DRAIN_FOR_RESET || drain_type_ == DRAIN_FOR_DESTROY); | |
| 1037 } | |
| 1038 | |
| 1039 void AndroidVideoDecodeAccelerator::ResetCodecState( | |
| 1040 base::Closure notification_cb) { | |
|
watk
2016/04/18 21:12:18
I would be inclined to name this consistently with
Tima Vaisburd
2016/04/20 01:54:19
Done.
| |
| 1000 DCHECK(thread_checker_.CalledOnValidThread()); | 1041 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1001 | 1042 |
| 1002 // If there is already a reset in flight, then that counts. This can really | 1043 // If there is already a reset in flight, then that counts. This can really |
| 1003 // only happen if somebody calls Reset. | 1044 // only happen if somebody calls Reset. |
| 1004 if (state_ == WAITING_FOR_CODEC) | 1045 if (state_ == WAITING_FOR_CODEC) { |
| 1046 if (!notification_cb.is_null()) | |
| 1047 notification_cb.Run(); | |
| 1005 return; | 1048 return; |
| 1049 } | |
| 1006 | 1050 |
| 1007 bitstream_buffers_in_decoder_.clear(); | 1051 bitstream_buffers_in_decoder_.clear(); |
| 1008 | 1052 |
| 1009 if (pending_input_buf_index_ != -1) { | 1053 if (pending_input_buf_index_ != -1) { |
| 1010 // The data for that index exists in the input buffer, but corresponding | 1054 // The data for that index exists in the input buffer, but corresponding |
| 1011 // shm block been deleted. Check that it is safe to flush the coec, i.e. | 1055 // shm block been deleted. Check that it is safe to flush the coec, i.e. |
| 1012 // |pending_bitstream_buffers_| is empty. | 1056 // |pending_bitstream_buffers_| is empty. |
| 1013 // TODO(timav): keep shm block for that buffer and remove this restriction. | 1057 // TODO(timav): keep shm block for that buffer and remove this restriction. |
| 1014 DCHECK(pending_bitstream_buffers_.empty()); | 1058 DCHECK(pending_bitstream_buffers_.empty()); |
| 1015 pending_input_buf_index_ = -1; | 1059 pending_input_buf_index_ = -1; |
| 1016 } | 1060 } |
| 1017 | 1061 |
| 1018 if (state_ == WAITING_FOR_KEY) | 1062 const bool did_codec_error_happen = (state_ == ERROR); |
| 1019 state_ = NO_ERROR; | 1063 state_ = NO_ERROR; |
| 1020 | 1064 |
| 1021 // We might increment error_sequence_token here to cancel any delayed errors, | 1065 // We might increment error_sequence_token here to cancel any delayed errors, |
| 1022 // but right now it's unclear that it's safe to do so. If we are in an error | 1066 // but right now it's unclear that it's safe to do so. If we are in an error |
| 1023 // state because of a codec error, then it would be okay. Otherwise, it's | 1067 // state because of a codec error, then it would be okay. Otherwise, it's |
| 1024 // less obvious that we are exiting the error state. Since deferred errors | 1068 // less obvious that we are exiting the error state. Since deferred errors |
| 1025 // are only intended for fullscreen transitions right now, we take the more | 1069 // are only intended for fullscreen transitions right now, we take the more |
| 1026 // conservative approach and let the errors post. | 1070 // conservative approach and let the errors post. |
| 1027 // TODO(liberato): revisit this once we sort out the error state a bit more. | 1071 // TODO(liberato): revisit this once we sort out the error state a bit more. |
| 1028 | 1072 |
| 1029 // When codec is not in error state we can quickly reset (internally calls | 1073 // When codec is not in error state we can quickly reset (internally calls |
| 1030 // flush()) for JB-MR2 and beyond. Prior to JB-MR2, flush() had several bugs | 1074 // flush()) for JB-MR2 and beyond. Prior to JB-MR2, flush() had several bugs |
| 1031 // (b/8125974, b/8347958) so we must delete the MediaCodec and create a new | 1075 // (b/8125974, b/8347958) so we must delete the MediaCodec and create a new |
| 1032 // one. The full reconfigure is much slower and may cause visible freezing if | 1076 // one. The full reconfigure is much slower and may cause visible freezing if |
| 1033 // done mid-stream. | 1077 // done mid-stream. |
| 1034 if (state_ == NO_ERROR && | 1078 if (!did_codec_error_happen && |
| 1035 base::android::BuildInfo::GetInstance()->sdk_int() >= 18) { | 1079 base::android::BuildInfo::GetInstance()->sdk_int() >= 18) { |
| 1036 DVLOG(3) << __FUNCTION__ << " Doing fast MediaCodec reset (flush)."; | 1080 DVLOG(3) << __FUNCTION__ << " Doing fast MediaCodec reset (flush)."; |
| 1037 media_codec_->Reset(); | 1081 media_codec_->Reset(); |
| 1038 // Since we just flushed all the output buffers, make sure that nothing is | 1082 // Since we just flushed all the output buffers, make sure that nothing is |
| 1039 // using them. | 1083 // using them. |
| 1040 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); | 1084 strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_); |
| 1041 } else { | 1085 } else { |
| 1042 DVLOG(3) << __FUNCTION__ | 1086 DVLOG(3) << __FUNCTION__ |
| 1043 << " Deleting the MediaCodec and creating a new one."; | 1087 << " Deleting the MediaCodec and creating a new one."; |
| 1044 g_avda_timer.Pointer()->StopTimer(this); | 1088 g_avda_timer.Pointer()->StopTimer(this); |
| 1045 // Changing the codec will also notify the strategy to forget about any | 1089 // Changing the codec will also notify the strategy to forget about any |
| 1046 // output buffers it has currently. | 1090 // output buffers it has currently. |
| 1047 state_ = NO_ERROR; | |
| 1048 ConfigureMediaCodecAsynchronously(); | 1091 ConfigureMediaCodecAsynchronously(); |
| 1049 } | 1092 } |
| 1093 | |
| 1094 if (!notification_cb.is_null()) | |
| 1095 notification_cb.Run(); | |
| 1050 } | 1096 } |
| 1051 | 1097 |
| 1052 void AndroidVideoDecodeAccelerator::Reset() { | 1098 void AndroidVideoDecodeAccelerator::Reset() { |
| 1099 DVLOG(1) << __FUNCTION__; | |
| 1100 | |
| 1053 DCHECK(thread_checker_.CalledOnValidThread()); | 1101 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1054 TRACE_EVENT0("media", "AVDA::Reset"); | 1102 TRACE_EVENT0("media", "AVDA::Reset"); |
| 1055 | 1103 |
| 1056 while (!pending_bitstream_buffers_.empty()) { | 1104 while (!pending_bitstream_buffers_.empty()) { |
| 1057 int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().id(); | 1105 int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().id(); |
| 1058 pending_bitstream_buffers_.pop(); | 1106 pending_bitstream_buffers_.pop(); |
| 1059 | 1107 |
| 1060 if (bitstream_buffer_id != -1) { | 1108 if (bitstream_buffer_id != -1) { |
| 1061 base::MessageLoop::current()->PostTask( | 1109 base::MessageLoop::current()->PostTask( |
| 1062 FROM_HERE, | 1110 FROM_HERE, |
| 1063 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 1111 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
| 1064 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); | 1112 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); |
| 1065 } | 1113 } |
| 1066 } | 1114 } |
| 1067 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); | 1115 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); |
| 1068 bitstreams_notified_in_advance_.clear(); | 1116 bitstreams_notified_in_advance_.clear(); |
| 1069 | 1117 |
| 1070 // Any error that is waiting to post can be ignored. | 1118 // Any error that is waiting to post can be ignored. |
| 1071 error_sequence_token_++; | 1119 error_sequence_token_++; |
| 1072 | 1120 |
| 1073 ResetCodecState(); | 1121 DCHECK(strategy_); |
| 1122 strategy_->ReleaseCodecBuffers(output_picture_buffers_); | |
| 1074 | 1123 |
| 1075 // Note that |media_codec_| might not yet be ready, but we can still post | 1124 base::Closure notification_cb = media::BindToCurrentLoop( |
|
watk
2016/04/18 21:12:18
I don't think you need BindToCurrentLoop because t
Tima Vaisburd
2016/04/20 01:54:19
Removed BindToCurrentLoop. The original code alway
| |
| 1076 // this anyway. | 1125 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
| 1077 base::MessageLoop::current()->PostTask( | 1126 weak_this_factory_.GetWeakPtr())); |
| 1078 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, | 1127 |
| 1079 weak_this_factory_.GetWeakPtr())); | 1128 // Some VP8 files require complete MediaCodec drain before we can call |
| 1129 // MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963. | |
| 1130 if (codec_config_->codec_ == media::kCodecVP8) { | |
| 1131 // Postpone ResetCodecState() after the drain. | |
| 1132 RequestDrain(DRAIN_FOR_RESET, | |
| 1133 base::Bind(&AndroidVideoDecodeAccelerator::ResetCodecState, | |
| 1134 weak_this_factory_.GetWeakPtr(), notification_cb)); | |
| 1135 } else { | |
| 1136 ResetCodecState(notification_cb); | |
| 1137 } | |
| 1080 } | 1138 } |
| 1081 | 1139 |
| 1082 void AndroidVideoDecodeAccelerator::Destroy() { | 1140 void AndroidVideoDecodeAccelerator::Destroy() { |
| 1141 DVLOG(1) << __FUNCTION__; | |
| 1142 | |
|
watk
2016/04/18 21:12:18
nit: Remove empty line to keep the LOG and thread
Tima Vaisburd
2016/04/20 01:54:19
Done.
| |
| 1083 DCHECK(thread_checker_.CalledOnValidThread()); | 1143 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1084 | 1144 |
| 1085 bool have_context = make_context_current_cb_.Run(); | 1145 bool have_context = make_context_current_cb_.Run(); |
| 1086 if (!have_context) | 1146 if (!have_context) |
| 1087 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; | 1147 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; |
| 1088 | 1148 |
| 1089 if (strategy_) | 1149 if (strategy_) |
| 1090 strategy_->Cleanup(have_context, output_picture_buffers_); | 1150 strategy_->Cleanup(have_context, output_picture_buffers_); |
| 1091 | 1151 |
| 1092 // If we have an OnFrameAvailable handler, tell it that we're going away. | 1152 // If we have an OnFrameAvailable handler, tell it that we're going away. |
| 1093 if (on_frame_available_handler_) { | 1153 if (on_frame_available_handler_) { |
| 1094 on_frame_available_handler_->ClearOwner(); | 1154 on_frame_available_handler_->ClearOwner(); |
| 1095 on_frame_available_handler_ = nullptr; | 1155 on_frame_available_handler_ = nullptr; |
| 1096 } | 1156 } |
| 1097 | 1157 |
| 1158 client_ = nullptr; | |
| 1159 | |
| 1160 // Some VP8 files require complete MediaCodec drain before we can call | |
| 1161 // MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963. | |
| 1162 if (media_codec_ && codec_config_->codec_ == media::kCodecVP8) { | |
| 1163 // Clear pending_bitstream_buffers_. | |
| 1164 while (!pending_bitstream_buffers_.empty()) | |
| 1165 pending_bitstream_buffers_.pop(); | |
| 1166 | |
| 1167 // Postpone ActualDestroy after the drain. | |
| 1168 RequestDrain(DRAIN_FOR_DESTROY, | |
| 1169 media::BindToCurrentLoop( | |
| 1170 base::Bind(&AndroidVideoDecodeAccelerator::ActualDestroy, | |
| 1171 weak_this_factory_.GetWeakPtr()))); | |
| 1172 } else { | |
| 1173 ActualDestroy(); | |
| 1174 } | |
| 1175 } | |
| 1176 | |
| 1177 void AndroidVideoDecodeAccelerator::ActualDestroy() { | |
| 1178 DVLOG(1) << __FUNCTION__; | |
| 1098 // Note that async codec construction might still be in progress. In that | 1179 // Note that async codec construction might still be in progress. In that |
| 1099 // case, the codec will be deleted when it completes once we invalidate all | 1180 // case, the codec will be deleted when it completes once we invalidate all |
| 1100 // our weak refs. | 1181 // our weak refs. |
| 1101 weak_this_factory_.InvalidateWeakPtrs(); | 1182 weak_this_factory_.InvalidateWeakPtrs(); |
| 1102 if (media_codec_) { | 1183 if (media_codec_) { |
| 1103 g_avda_timer.Pointer()->StopTimer(this); | 1184 g_avda_timer.Pointer()->StopTimer(this); |
| 1104 media_codec_.reset(); | 1185 media_codec_.reset(); |
| 1105 } | 1186 } |
| 1106 delete this; | 1187 delete this; |
| 1107 } | 1188 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1194 void AndroidVideoDecodeAccelerator::OnKeyAdded() { | 1275 void AndroidVideoDecodeAccelerator::OnKeyAdded() { |
| 1195 DVLOG(1) << __FUNCTION__; | 1276 DVLOG(1) << __FUNCTION__; |
| 1196 | 1277 |
| 1197 if (state_ == WAITING_FOR_KEY) | 1278 if (state_ == WAITING_FOR_KEY) |
| 1198 state_ = NO_ERROR; | 1279 state_ = NO_ERROR; |
| 1199 | 1280 |
| 1200 DoIOTask(true); | 1281 DoIOTask(true); |
| 1201 } | 1282 } |
| 1202 | 1283 |
| 1203 void AndroidVideoDecodeAccelerator::NotifyInitializationComplete(bool success) { | 1284 void AndroidVideoDecodeAccelerator::NotifyInitializationComplete(bool success) { |
| 1204 client_->NotifyInitializationComplete(success); | 1285 if (client_) |
| 1286 client_->NotifyInitializationComplete(success); | |
| 1205 } | 1287 } |
| 1206 | 1288 |
| 1207 void AndroidVideoDecodeAccelerator::NotifyPictureReady( | 1289 void AndroidVideoDecodeAccelerator::NotifyPictureReady( |
| 1208 const media::Picture& picture) { | 1290 const media::Picture& picture) { |
| 1209 client_->PictureReady(picture); | 1291 if (client_) |
| 1292 client_->PictureReady(picture); | |
| 1210 } | 1293 } |
| 1211 | 1294 |
| 1212 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( | 1295 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
| 1213 int input_buffer_id) { | 1296 int input_buffer_id) { |
| 1214 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); | 1297 if (client_) |
| 1298 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); | |
| 1215 } | 1299 } |
| 1216 | 1300 |
| 1217 void AndroidVideoDecodeAccelerator::NotifyFlushDone() { | 1301 void AndroidVideoDecodeAccelerator::NotifyFlushDone() { |
| 1218 client_->NotifyFlushDone(); | 1302 if (client_) |
| 1303 client_->NotifyFlushDone(); | |
| 1219 } | 1304 } |
| 1220 | 1305 |
| 1221 void AndroidVideoDecodeAccelerator::NotifyResetDone() { | 1306 void AndroidVideoDecodeAccelerator::NotifyResetDone() { |
| 1222 client_->NotifyResetDone(); | 1307 if (client_) |
| 1308 client_->NotifyResetDone(); | |
| 1223 } | 1309 } |
| 1224 | 1310 |
| 1225 void AndroidVideoDecodeAccelerator::NotifyError( | 1311 void AndroidVideoDecodeAccelerator::NotifyError( |
| 1226 media::VideoDecodeAccelerator::Error error, | 1312 media::VideoDecodeAccelerator::Error error, |
| 1227 int token) { | 1313 int token) { |
| 1228 DVLOG(1) << __FUNCTION__ << ": error: " << error << " token: " << token | 1314 DVLOG(1) << __FUNCTION__ << ": error: " << error << " token: " << token |
| 1229 << " current: " << error_sequence_token_; | 1315 << " current: " << error_sequence_token_; |
| 1230 if (token != error_sequence_token_) | 1316 if (token != error_sequence_token_) |
| 1231 return; | 1317 return; |
| 1232 | 1318 |
| 1233 client_->NotifyError(error); | 1319 if (client_) |
| 1320 client_->NotifyError(error); | |
| 1234 } | 1321 } |
| 1235 | 1322 |
| 1236 void AndroidVideoDecodeAccelerator::ManageTimer(bool did_work) { | 1323 void AndroidVideoDecodeAccelerator::ManageTimer(bool did_work) { |
| 1237 bool should_be_running = true; | 1324 bool should_be_running = true; |
| 1238 | 1325 |
| 1239 base::TimeTicks now = base::TimeTicks::Now(); | 1326 base::TimeTicks now = base::TimeTicks::Now(); |
| 1240 if (!did_work && !most_recent_work_.is_null()) { | 1327 if (!did_work && !most_recent_work_.is_null()) { |
| 1241 // Make sure that we have done work recently enough, else stop the timer. | 1328 // Make sure that we have done work recently enough, else stop the timer. |
| 1242 if (now - most_recent_work_ > IdleTimerTimeOut()) { | 1329 if (now - most_recent_work_ > IdleTimerTimeOut()) { |
| 1243 most_recent_work_ = base::TimeTicks(); | 1330 most_recent_work_ = base::TimeTicks(); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1321 media::VideoDecodeAccelerator::Capabilities:: | 1408 media::VideoDecodeAccelerator::Capabilities:: |
| 1322 SUPPORTS_EXTERNAL_OUTPUT_SURFACE | | 1409 SUPPORTS_EXTERNAL_OUTPUT_SURFACE | |
| 1323 media::VideoDecodeAccelerator::Capabilities:: | 1410 media::VideoDecodeAccelerator::Capabilities:: |
| 1324 SUPPORTS_DEFERRED_INITIALIZATION; | 1411 SUPPORTS_DEFERRED_INITIALIZATION; |
| 1325 } | 1412 } |
| 1326 | 1413 |
| 1327 return capabilities; | 1414 return capabilities; |
| 1328 } | 1415 } |
| 1329 | 1416 |
| 1330 } // namespace content | 1417 } // namespace content |
| OLD | NEW |