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 <memory> | 9 #include <memory> |
10 | 10 |
11 #include "base/android/build_info.h" | 11 #include "base/android/build_info.h" |
12 #include "base/auto_reset.h" | 12 #include "base/auto_reset.h" |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
| 15 #include "base/callback_helpers.h" |
15 #include "base/command_line.h" | 16 #include "base/command_line.h" |
16 #include "base/lazy_instance.h" | 17 #include "base/lazy_instance.h" |
17 #include "base/logging.h" | 18 #include "base/logging.h" |
18 #include "base/message_loop/message_loop.h" | 19 #include "base/message_loop/message_loop.h" |
19 #include "base/metrics/histogram.h" | 20 #include "base/metrics/histogram.h" |
20 #include "base/task_runner_util.h" | 21 #include "base/task_runner_util.h" |
21 #include "base/threading/thread_checker.h" | 22 #include "base/threading/thread_checker.h" |
22 #include "base/trace_event/trace_event.h" | 23 #include "base/trace_event/trace_event.h" |
23 #include "content/common/gpu/media/android_copying_backing_strategy.h" | 24 #include "content/common/gpu/media/android_copying_backing_strategy.h" |
24 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" | 25 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 | 305 |
305 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( | 306 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( |
306 const MakeGLContextCurrentCallback& make_context_current_cb, | 307 const MakeGLContextCurrentCallback& make_context_current_cb, |
307 const GetGLES2DecoderCallback& get_gles2_decoder_cb) | 308 const GetGLES2DecoderCallback& get_gles2_decoder_cb) |
308 : client_(NULL), | 309 : client_(NULL), |
309 make_context_current_cb_(make_context_current_cb), | 310 make_context_current_cb_(make_context_current_cb), |
310 get_gles2_decoder_cb_(get_gles2_decoder_cb), | 311 get_gles2_decoder_cb_(get_gles2_decoder_cb), |
311 is_encrypted_(false), | 312 is_encrypted_(false), |
312 state_(NO_ERROR), | 313 state_(NO_ERROR), |
313 picturebuffers_requested_(false), | 314 picturebuffers_requested_(false), |
| 315 drain_type_(DRAIN_TYPE_NONE), |
314 media_drm_bridge_cdm_context_(nullptr), | 316 media_drm_bridge_cdm_context_(nullptr), |
315 cdm_registration_id_(0), | 317 cdm_registration_id_(0), |
316 pending_input_buf_index_(-1), | 318 pending_input_buf_index_(-1), |
317 error_sequence_token_(0), | 319 error_sequence_token_(0), |
318 defer_errors_(false), | 320 defer_errors_(false), |
319 deferred_initialization_pending_(false), | 321 deferred_initialization_pending_(false), |
320 weak_this_factory_(this) {} | 322 weak_this_factory_(this) {} |
321 | 323 |
322 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 324 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
323 DCHECK(thread_checker_.CalledOnValidThread()); | 325 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 | 550 |
549 DCHECK_NE(input_buf_index, -1); | 551 DCHECK_NE(input_buf_index, -1); |
550 | 552 |
551 media::BitstreamBuffer bitstream_buffer = pending_bitstream_buffers_.front(); | 553 media::BitstreamBuffer bitstream_buffer = pending_bitstream_buffers_.front(); |
552 | 554 |
553 if (bitstream_buffer.id() == -1) { | 555 if (bitstream_buffer.id() == -1) { |
554 pending_bitstream_buffers_.pop(); | 556 pending_bitstream_buffers_.pop(); |
555 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", | 557 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
556 pending_bitstream_buffers_.size()); | 558 pending_bitstream_buffers_.size()); |
557 | 559 |
558 DCHECK_NE(state_, ERROR); | |
559 state_ = WAITING_FOR_EOS; | |
560 media_codec_->QueueEOS(input_buf_index); | 560 media_codec_->QueueEOS(input_buf_index); |
561 return true; | 561 return true; |
562 } | 562 } |
563 | 563 |
564 std::unique_ptr<SharedMemoryRegion> shm; | 564 std::unique_ptr<SharedMemoryRegion> shm; |
565 | 565 |
566 if (pending_input_buf_index_ == -1) { | 566 if (pending_input_buf_index_ == -1) { |
567 // When |pending_input_buf_index_| is not -1, the buffer is already dequeued | 567 // When |pending_input_buf_index_| is not -1, the buffer is already dequeued |
568 // from MediaCodec, filled with data and bitstream_buffer.handle() is | 568 // from MediaCodec, filled with data and bitstream_buffer.handle() is |
569 // closed. | 569 // closed. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput"); | 668 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput"); |
669 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( | 669 media::MediaCodecStatus status = media_codec_->DequeueOutputBuffer( |
670 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, | 670 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, |
671 &eos, NULL); | 671 &eos, NULL); |
672 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status, | 672 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status, |
673 "presentation_timestamp (ms)", | 673 "presentation_timestamp (ms)", |
674 presentation_timestamp.InMilliseconds()); | 674 presentation_timestamp.InMilliseconds()); |
675 | 675 |
676 switch (status) { | 676 switch (status) { |
677 case media::MEDIA_CODEC_ERROR: | 677 case media::MEDIA_CODEC_ERROR: |
678 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); | 678 // Do not post an error if we are draining for reset and destroy. |
| 679 // Instead, run the drain completion task. |
| 680 if (IsDrainingForResetOrDestroy()) { |
| 681 DVLOG(1) << __FUNCTION__ << ": error while codec draining"; |
| 682 state_ = ERROR; |
| 683 OnDrainCompleted(); |
| 684 } else { |
| 685 POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); |
| 686 } |
679 return false; | 687 return false; |
680 | 688 |
681 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 689 case media::MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
682 return false; | 690 return false; |
683 | 691 |
684 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { | 692 case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: { |
| 693 // An OUTPUT_FORMAT_CHANGED is not reported after flush() if the frame |
| 694 // size does not change. Therefore we have to keep track on the format |
| 695 // even if draining, unless we are draining for destroy. |
| 696 if (drain_type_ == DRAIN_FOR_DESTROY) |
| 697 return true; // ignore |
| 698 |
685 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { | 699 if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) { |
686 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); | 700 POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed."); |
687 return false; | 701 return false; |
688 } | 702 } |
| 703 |
689 DVLOG(3) << __FUNCTION__ | 704 DVLOG(3) << __FUNCTION__ |
690 << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString(); | 705 << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString(); |
691 | 706 |
692 // Don't request picture buffers if we already have some. This avoids | 707 // Don't request picture buffers if we already have some. This avoids |
693 // having to dismiss the existing buffers which may actively reference | 708 // having to dismiss the existing buffers which may actively reference |
694 // decoded images. Breaking their connection to the decoded image will | 709 // decoded images. Breaking their connection to the decoded image will |
695 // cause rendering of black frames. Instead, we let the existing | 710 // cause rendering of black frames. Instead, we let the existing |
696 // PictureBuffers live on and we simply update their size the next time | 711 // PictureBuffers live on and we simply update their size the next time |
697 // they're attachted to an image of the new resolution. See the | 712 // they're attachted to an image of the new resolution. See the |
698 // size update in |SendDecodedFrameToClient| and https://crbug/587994. | 713 // size update in |SendDecodedFrameToClient| and https://crbug/587994. |
(...skipping 19 matching lines...) Expand all Loading... |
718 << " size:" << size << " eos:" << eos; | 733 << " size:" << size << " eos:" << eos; |
719 break; | 734 break; |
720 | 735 |
721 default: | 736 default: |
722 NOTREACHED(); | 737 NOTREACHED(); |
723 break; | 738 break; |
724 } | 739 } |
725 } while (buf_index < 0); | 740 } while (buf_index < 0); |
726 | 741 |
727 if (eos) { | 742 if (eos) { |
728 DVLOG(3) << __FUNCTION__ << ": Resetting codec state after EOS"; | 743 OnDrainCompleted(); |
| 744 return false; |
| 745 } |
729 | 746 |
730 // If we were waiting for an EOS, clear the state and reset the MediaCodec | 747 if (IsDrainingForResetOrDestroy()) { |
731 // as normal. Otherwise, enter the ERROR state which will force destruction | 748 media_codec_->ReleaseOutputBuffer(buf_index, false); |
732 // of MediaCodec during ResetCodecState(). | 749 return true; |
733 // | |
734 // Some Android platforms seem to send an EOS buffer even when we're not | |
735 // expecting it. In this case, destroy and reset the codec but don't notify | |
736 // flush done since it violates the state machine. http://crbug.com/585959. | |
737 const bool was_waiting_for_eos = state_ == WAITING_FOR_EOS; | |
738 state_ = was_waiting_for_eos ? NO_ERROR : ERROR; | |
739 | |
740 ResetCodecState(); | |
741 // |media_codec_| might still be null. | |
742 if (was_waiting_for_eos) { | |
743 base::MessageLoop::current()->PostTask( | |
744 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, | |
745 weak_this_factory_.GetWeakPtr())); | |
746 } | |
747 return false; | |
748 } | 750 } |
749 | 751 |
750 if (!picturebuffers_requested_) { | 752 if (!picturebuffers_requested_) { |
751 // If, somehow, we get a decoded frame back before a FORMAT_CHANGED | 753 // If, somehow, we get a decoded frame back before a FORMAT_CHANGED |
752 // message, then we might not have any picture buffers to use. This | 754 // message, then we might not have any picture buffers to use. This |
753 // isn't supposed to happen (see EncodeDecodeTest.java#617). | 755 // isn't supposed to happen (see EncodeDecodeTest.java#617). |
754 // Log a metric to see how common this is. | 756 // Log a metric to see how common this is. |
755 RecordFormatChangedMetric(FormatChangedValue::MissingFormatChanged); | 757 RecordFormatChangedMetric(FormatChangedValue::MissingFormatChanged); |
756 media_codec_->ReleaseOutputBuffer(buf_index, false); | 758 media_codec_->ReleaseOutputBuffer(buf_index, false); |
757 POST_ERROR(PLATFORM_FAILURE, "Dequeued buffers before FORMAT_CHANGED."); | 759 POST_ERROR(PLATFORM_FAILURE, "Dequeued buffers before FORMAT_CHANGED."); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 void AndroidVideoDecodeAccelerator::DecodeBuffer( | 870 void AndroidVideoDecodeAccelerator::DecodeBuffer( |
869 const media::BitstreamBuffer& bitstream_buffer) { | 871 const media::BitstreamBuffer& bitstream_buffer) { |
870 pending_bitstream_buffers_.push(bitstream_buffer); | 872 pending_bitstream_buffers_.push(bitstream_buffer); |
871 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", | 873 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", |
872 pending_bitstream_buffers_.size()); | 874 pending_bitstream_buffers_.size()); |
873 | 875 |
874 DoIOTask(true); | 876 DoIOTask(true); |
875 } | 877 } |
876 | 878 |
877 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { | 879 void AndroidVideoDecodeAccelerator::RequestPictureBuffers() { |
878 client_->ProvidePictureBuffers(kNumPictureBuffers, 1, | 880 if (client_) { |
879 strategy_->GetPictureBufferSize(), | 881 client_->ProvidePictureBuffers(kNumPictureBuffers, 1, |
880 strategy_->GetTextureTarget()); | 882 strategy_->GetPictureBufferSize(), |
| 883 strategy_->GetTextureTarget()); |
| 884 } |
881 } | 885 } |
882 | 886 |
883 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( | 887 void AndroidVideoDecodeAccelerator::AssignPictureBuffers( |
884 const std::vector<media::PictureBuffer>& buffers) { | 888 const std::vector<media::PictureBuffer>& buffers) { |
885 DCHECK(thread_checker_.CalledOnValidThread()); | 889 DCHECK(thread_checker_.CalledOnValidThread()); |
886 DCHECK(output_picture_buffers_.empty()); | 890 DCHECK(output_picture_buffers_.empty()); |
887 DCHECK(free_picture_ids_.empty()); | 891 DCHECK(free_picture_ids_.empty()); |
888 | 892 |
889 if (buffers.size() < kNumPictureBuffers) { | 893 if (buffers.size() < kNumPictureBuffers) { |
890 POST_ERROR(INVALID_ARGUMENT, "Not enough picture buffers assigned."); | 894 POST_ERROR(INVALID_ARGUMENT, "Not enough picture buffers assigned."); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 POST_ERROR(PLATFORM_FAILURE, "Can't find PictureBuffer id " | 930 POST_ERROR(PLATFORM_FAILURE, "Can't find PictureBuffer id " |
927 << picture_buffer_id); | 931 << picture_buffer_id); |
928 return; | 932 return; |
929 } | 933 } |
930 | 934 |
931 strategy_->ReuseOnePictureBuffer(i->second); | 935 strategy_->ReuseOnePictureBuffer(i->second); |
932 DoIOTask(true); | 936 DoIOTask(true); |
933 } | 937 } |
934 | 938 |
935 void AndroidVideoDecodeAccelerator::Flush() { | 939 void AndroidVideoDecodeAccelerator::Flush() { |
| 940 DVLOG(1) << __FUNCTION__; |
936 DCHECK(thread_checker_.CalledOnValidThread()); | 941 DCHECK(thread_checker_.CalledOnValidThread()); |
937 | 942 |
938 DecodeBuffer(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); | 943 StartCodecDrain(DRAIN_FOR_FLUSH); |
939 } | 944 } |
940 | 945 |
941 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { | 946 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { |
942 DCHECK(thread_checker_.CalledOnValidThread()); | 947 DCHECK(thread_checker_.CalledOnValidThread()); |
943 | 948 |
944 // It's probably okay just to return here, since the codec will be configured | 949 // It's probably okay just to return here, since the codec will be configured |
945 // asynchronously. It's unclear that any state for the new request could | 950 // asynchronously. It's unclear that any state for the new request could |
946 // be different, unless somebody modifies |codec_config_| while we're already | 951 // be different, unless somebody modifies |codec_config_| while we're already |
947 // waiting for a codec. One shouldn't do that for thread safety. | 952 // waiting for a codec. One shouldn't do that for thread safety. |
948 DCHECK_NE(state_, WAITING_FOR_CODEC); | 953 DCHECK_NE(state_, WAITING_FOR_CODEC); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1020 if (!media_codec_) { | 1025 if (!media_codec_) { |
1021 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec."); | 1026 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec."); |
1022 return; | 1027 return; |
1023 } | 1028 } |
1024 | 1029 |
1025 state_ = NO_ERROR; | 1030 state_ = NO_ERROR; |
1026 | 1031 |
1027 ManageTimer(true); | 1032 ManageTimer(true); |
1028 } | 1033 } |
1029 | 1034 |
1030 void AndroidVideoDecodeAccelerator::ResetCodecState() { | 1035 void AndroidVideoDecodeAccelerator::StartCodecDrain(DrainType drain_type) { |
| 1036 DVLOG(2) << __FUNCTION__ << " drain_type:" << drain_type; |
| 1037 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1038 |
| 1039 // We assume that DRAIN_FOR_FLUSH and DRAIN_FOR_RESET cannot come while |
| 1040 // another drain request is present, but DRAIN_FOR_DESTROY can. |
| 1041 DCHECK_NE(drain_type, DRAIN_TYPE_NONE); |
| 1042 DCHECK(drain_type_ == DRAIN_TYPE_NONE || drain_type == DRAIN_FOR_DESTROY) |
| 1043 << "Unexpected StartCodecDrain() with drain type " << drain_type |
| 1044 << " while already draining with drain type " << drain_type_; |
| 1045 |
| 1046 const bool enqueue_eos = drain_type_ == DRAIN_TYPE_NONE; |
| 1047 drain_type_ = drain_type; |
| 1048 |
| 1049 if (enqueue_eos) |
| 1050 DecodeBuffer(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); |
| 1051 } |
| 1052 |
| 1053 bool AndroidVideoDecodeAccelerator::IsDrainingForResetOrDestroy() const { |
| 1054 return drain_type_ == DRAIN_FOR_RESET || drain_type_ == DRAIN_FOR_DESTROY; |
| 1055 } |
| 1056 |
| 1057 void AndroidVideoDecodeAccelerator::OnDrainCompleted() { |
| 1058 DVLOG(2) << __FUNCTION__; |
| 1059 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1060 |
| 1061 // If we were waiting for an EOS, clear the state and reset the MediaCodec |
| 1062 // as normal. Otherwise, enter the ERROR state which will force destruction |
| 1063 // of MediaCodec during ResetCodecState(). |
| 1064 // |
| 1065 // Some Android platforms seem to send an EOS buffer even when we're not |
| 1066 // expecting it. In this case, destroy and reset the codec but don't notify |
| 1067 // flush done since it violates the state machine. http://crbug.com/585959. |
| 1068 |
| 1069 switch (drain_type_) { |
| 1070 case DRAIN_TYPE_NONE: |
| 1071 // Unexpected EOS. |
| 1072 state_ = ERROR; |
| 1073 ResetCodecState(base::Closure()); |
| 1074 break; |
| 1075 case DRAIN_FOR_FLUSH: |
| 1076 ResetCodecState(media::BindToCurrentLoop( |
| 1077 base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, |
| 1078 weak_this_factory_.GetWeakPtr()))); |
| 1079 break; |
| 1080 case DRAIN_FOR_RESET: |
| 1081 ResetCodecState(media::BindToCurrentLoop( |
| 1082 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
| 1083 weak_this_factory_.GetWeakPtr()))); |
| 1084 break; |
| 1085 case DRAIN_FOR_DESTROY: |
| 1086 base::MessageLoop::current()->PostTask( |
| 1087 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::ActualDestroy, |
| 1088 weak_this_factory_.GetWeakPtr())); |
| 1089 break; |
| 1090 } |
| 1091 drain_type_ = DRAIN_TYPE_NONE; |
| 1092 } |
| 1093 |
| 1094 void AndroidVideoDecodeAccelerator::ResetCodecState( |
| 1095 const base::Closure& done_cb) { |
1031 DCHECK(thread_checker_.CalledOnValidThread()); | 1096 DCHECK(thread_checker_.CalledOnValidThread()); |
1032 | 1097 |
1033 // If there is already a reset in flight, then that counts. This can really | 1098 // If there is already a reset in flight, then that counts. This can really |
1034 // only happen if somebody calls Reset. | 1099 // only happen if somebody calls Reset. |
1035 if (state_ == WAITING_FOR_CODEC) | 1100 if (state_ == WAITING_FOR_CODEC) { |
| 1101 if (!done_cb.is_null()) |
| 1102 done_cb.Run(); |
1036 return; | 1103 return; |
| 1104 } |
1037 | 1105 |
1038 bitstream_buffers_in_decoder_.clear(); | 1106 bitstream_buffers_in_decoder_.clear(); |
1039 | 1107 |
1040 if (pending_input_buf_index_ != -1) { | 1108 if (pending_input_buf_index_ != -1) { |
1041 // The data for that index exists in the input buffer, but corresponding | 1109 // The data for that index exists in the input buffer, but corresponding |
1042 // shm block been deleted. Check that it is safe to flush the coec, i.e. | 1110 // shm block been deleted. Check that it is safe to flush the coec, i.e. |
1043 // |pending_bitstream_buffers_| is empty. | 1111 // |pending_bitstream_buffers_| is empty. |
1044 // TODO(timav): keep shm block for that buffer and remove this restriction. | 1112 // TODO(timav): keep shm block for that buffer and remove this restriction. |
1045 DCHECK(pending_bitstream_buffers_.empty()); | 1113 DCHECK(pending_bitstream_buffers_.empty()); |
1046 pending_input_buf_index_ = -1; | 1114 pending_input_buf_index_ = -1; |
1047 } | 1115 } |
1048 | 1116 |
1049 if (state_ == WAITING_FOR_KEY) | 1117 const bool did_codec_error_happen = state_ == ERROR; |
1050 state_ = NO_ERROR; | 1118 state_ = NO_ERROR; |
1051 | 1119 |
1052 // We might increment error_sequence_token here to cancel any delayed errors, | 1120 // We might increment error_sequence_token here to cancel any delayed errors, |
1053 // but right now it's unclear that it's safe to do so. If we are in an error | 1121 // but right now it's unclear that it's safe to do so. If we are in an error |
1054 // state because of a codec error, then it would be okay. Otherwise, it's | 1122 // state because of a codec error, then it would be okay. Otherwise, it's |
1055 // less obvious that we are exiting the error state. Since deferred errors | 1123 // less obvious that we are exiting the error state. Since deferred errors |
1056 // are only intended for fullscreen transitions right now, we take the more | 1124 // are only intended for fullscreen transitions right now, we take the more |
1057 // conservative approach and let the errors post. | 1125 // conservative approach and let the errors post. |
1058 // TODO(liberato): revisit this once we sort out the error state a bit more. | 1126 // TODO(liberato): revisit this once we sort out the error state a bit more. |
1059 | 1127 |
1060 // When codec is not in error state we can quickly reset (internally calls | 1128 // When codec is not in error state we can quickly reset (internally calls |
1061 // flush()) for JB-MR2 and beyond. Prior to JB-MR2, flush() had several bugs | 1129 // flush()) for JB-MR2 and beyond. Prior to JB-MR2, flush() had several bugs |
1062 // (b/8125974, b/8347958) so we must delete the MediaCodec and create a new | 1130 // (b/8125974, b/8347958) so we must delete the MediaCodec and create a new |
1063 // one. The full reconfigure is much slower and may cause visible freezing if | 1131 // one. The full reconfigure is much slower and may cause visible freezing if |
1064 // done mid-stream. | 1132 // done mid-stream. |
1065 if (state_ == NO_ERROR && | 1133 if (!did_codec_error_happen && |
1066 base::android::BuildInfo::GetInstance()->sdk_int() >= 18) { | 1134 base::android::BuildInfo::GetInstance()->sdk_int() >= 18) { |
1067 DVLOG(3) << __FUNCTION__ << " Doing fast MediaCodec reset (flush)."; | 1135 DVLOG(3) << __FUNCTION__ << " Doing fast MediaCodec reset (flush)."; |
1068 media_codec_->Reset(); | 1136 media_codec_->Reset(); |
1069 // Since we just flushed all the output buffers, make sure that nothing is | 1137 // Since we just flushed all the output buffers, make sure that nothing is |
1070 // using them. | 1138 // using them. |
1071 strategy_->CodecChanged(media_codec_.get()); | 1139 strategy_->CodecChanged(media_codec_.get()); |
1072 } else { | 1140 } else { |
1073 DVLOG(3) << __FUNCTION__ | 1141 DVLOG(3) << __FUNCTION__ |
1074 << " Deleting the MediaCodec and creating a new one."; | 1142 << " Deleting the MediaCodec and creating a new one."; |
1075 g_avda_timer.Pointer()->StopTimer(this); | 1143 g_avda_timer.Pointer()->StopTimer(this); |
1076 // Changing the codec will also notify the strategy to forget about any | 1144 // Changing the codec will also notify the strategy to forget about any |
1077 // output buffers it has currently. | 1145 // output buffers it has currently. |
1078 state_ = NO_ERROR; | |
1079 ConfigureMediaCodecAsynchronously(); | 1146 ConfigureMediaCodecAsynchronously(); |
1080 } | 1147 } |
| 1148 |
| 1149 if (!done_cb.is_null()) |
| 1150 done_cb.Run(); |
1081 } | 1151 } |
1082 | 1152 |
1083 void AndroidVideoDecodeAccelerator::Reset() { | 1153 void AndroidVideoDecodeAccelerator::Reset() { |
| 1154 DVLOG(1) << __FUNCTION__; |
1084 DCHECK(thread_checker_.CalledOnValidThread()); | 1155 DCHECK(thread_checker_.CalledOnValidThread()); |
1085 TRACE_EVENT0("media", "AVDA::Reset"); | 1156 TRACE_EVENT0("media", "AVDA::Reset"); |
1086 | 1157 |
1087 while (!pending_bitstream_buffers_.empty()) { | 1158 while (!pending_bitstream_buffers_.empty()) { |
1088 int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().id(); | 1159 int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().id(); |
1089 pending_bitstream_buffers_.pop(); | 1160 pending_bitstream_buffers_.pop(); |
1090 | 1161 |
1091 if (bitstream_buffer_id != -1) { | 1162 if (bitstream_buffer_id != -1) { |
1092 base::MessageLoop::current()->PostTask( | 1163 base::MessageLoop::current()->PostTask( |
1093 FROM_HERE, | 1164 FROM_HERE, |
1094 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, | 1165 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, |
1095 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); | 1166 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); |
1096 } | 1167 } |
1097 } | 1168 } |
1098 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); | 1169 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); |
1099 bitstreams_notified_in_advance_.clear(); | 1170 bitstreams_notified_in_advance_.clear(); |
1100 | 1171 |
1101 // Any error that is waiting to post can be ignored. | 1172 // Any error that is waiting to post can be ignored. |
1102 error_sequence_token_++; | 1173 error_sequence_token_++; |
1103 | 1174 |
1104 ResetCodecState(); | 1175 DCHECK(strategy_); |
| 1176 strategy_->ReleaseCodecBuffers(output_picture_buffers_); |
1105 | 1177 |
1106 // Note that |media_codec_| might not yet be ready, but we can still post | 1178 // Some VP8 files require complete MediaCodec drain before we can call |
1107 // this anyway. | 1179 // MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963. |
1108 base::MessageLoop::current()->PostTask( | 1180 if (media_codec_ && codec_config_->codec_ == media::kCodecVP8) { |
1109 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, | 1181 // Postpone ResetCodecState() after the drain. |
1110 weak_this_factory_.GetWeakPtr())); | 1182 StartCodecDrain(DRAIN_FOR_RESET); |
| 1183 } else { |
| 1184 ResetCodecState(media::BindToCurrentLoop( |
| 1185 base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, |
| 1186 weak_this_factory_.GetWeakPtr()))); |
| 1187 } |
1111 } | 1188 } |
1112 | 1189 |
1113 void AndroidVideoDecodeAccelerator::Destroy() { | 1190 void AndroidVideoDecodeAccelerator::Destroy() { |
| 1191 DVLOG(1) << __FUNCTION__; |
1114 DCHECK(thread_checker_.CalledOnValidThread()); | 1192 DCHECK(thread_checker_.CalledOnValidThread()); |
1115 | 1193 |
1116 bool have_context = make_context_current_cb_.Run(); | 1194 bool have_context = make_context_current_cb_.Run(); |
1117 if (!have_context) | 1195 if (!have_context) |
1118 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; | 1196 LOG(WARNING) << "Failed make GL context current for Destroy, continuing."; |
1119 | 1197 |
1120 if (strategy_) | 1198 if (strategy_) |
1121 strategy_->Cleanup(have_context, output_picture_buffers_); | 1199 strategy_->Cleanup(have_context, output_picture_buffers_); |
1122 | 1200 |
1123 // If we have an OnFrameAvailable handler, tell it that we're going away. | 1201 // If we have an OnFrameAvailable handler, tell it that we're going away. |
1124 if (on_frame_available_handler_) { | 1202 if (on_frame_available_handler_) { |
1125 on_frame_available_handler_->ClearOwner(); | 1203 on_frame_available_handler_->ClearOwner(); |
1126 on_frame_available_handler_ = nullptr; | 1204 on_frame_available_handler_ = nullptr; |
1127 } | 1205 } |
1128 | 1206 |
| 1207 client_ = nullptr; |
| 1208 |
| 1209 // Some VP8 files require complete MediaCodec drain before we can call |
| 1210 // MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963. |
| 1211 if (media_codec_ && codec_config_->codec_ == media::kCodecVP8) { |
| 1212 // Clear pending_bitstream_buffers_. |
| 1213 while (!pending_bitstream_buffers_.empty()) |
| 1214 pending_bitstream_buffers_.pop(); |
| 1215 |
| 1216 // Postpone ActualDestroy after the drain. |
| 1217 StartCodecDrain(DRAIN_FOR_DESTROY); |
| 1218 } else { |
| 1219 ActualDestroy(); |
| 1220 } |
| 1221 } |
| 1222 |
| 1223 void AndroidVideoDecodeAccelerator::ActualDestroy() { |
| 1224 DVLOG(1) << __FUNCTION__; |
| 1225 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1226 |
1129 // Note that async codec construction might still be in progress. In that | 1227 // Note that async codec construction might still be in progress. In that |
1130 // case, the codec will be deleted when it completes once we invalidate all | 1228 // case, the codec will be deleted when it completes once we invalidate all |
1131 // our weak refs. | 1229 // our weak refs. |
1132 weak_this_factory_.InvalidateWeakPtrs(); | 1230 weak_this_factory_.InvalidateWeakPtrs(); |
1133 if (media_codec_) { | 1231 if (media_codec_) { |
1134 g_avda_timer.Pointer()->StopTimer(this); | 1232 g_avda_timer.Pointer()->StopTimer(this); |
1135 media_codec_.reset(); | 1233 media_codec_.reset(); |
1136 } | 1234 } |
1137 delete this; | 1235 delete this; |
1138 } | 1236 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1225 void AndroidVideoDecodeAccelerator::OnKeyAdded() { | 1323 void AndroidVideoDecodeAccelerator::OnKeyAdded() { |
1226 DVLOG(1) << __FUNCTION__; | 1324 DVLOG(1) << __FUNCTION__; |
1227 | 1325 |
1228 if (state_ == WAITING_FOR_KEY) | 1326 if (state_ == WAITING_FOR_KEY) |
1229 state_ = NO_ERROR; | 1327 state_ = NO_ERROR; |
1230 | 1328 |
1231 DoIOTask(true); | 1329 DoIOTask(true); |
1232 } | 1330 } |
1233 | 1331 |
1234 void AndroidVideoDecodeAccelerator::NotifyInitializationComplete(bool success) { | 1332 void AndroidVideoDecodeAccelerator::NotifyInitializationComplete(bool success) { |
1235 client_->NotifyInitializationComplete(success); | 1333 if (client_) |
| 1334 client_->NotifyInitializationComplete(success); |
1236 } | 1335 } |
1237 | 1336 |
1238 void AndroidVideoDecodeAccelerator::NotifyPictureReady( | 1337 void AndroidVideoDecodeAccelerator::NotifyPictureReady( |
1239 const media::Picture& picture) { | 1338 const media::Picture& picture) { |
1240 client_->PictureReady(picture); | 1339 if (client_) |
| 1340 client_->PictureReady(picture); |
1241 } | 1341 } |
1242 | 1342 |
1243 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( | 1343 void AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
1244 int input_buffer_id) { | 1344 int input_buffer_id) { |
1245 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); | 1345 if (client_) |
| 1346 client_->NotifyEndOfBitstreamBuffer(input_buffer_id); |
1246 } | 1347 } |
1247 | 1348 |
1248 void AndroidVideoDecodeAccelerator::NotifyFlushDone() { | 1349 void AndroidVideoDecodeAccelerator::NotifyFlushDone() { |
1249 client_->NotifyFlushDone(); | 1350 if (client_) |
| 1351 client_->NotifyFlushDone(); |
1250 } | 1352 } |
1251 | 1353 |
1252 void AndroidVideoDecodeAccelerator::NotifyResetDone() { | 1354 void AndroidVideoDecodeAccelerator::NotifyResetDone() { |
1253 client_->NotifyResetDone(); | 1355 if (client_) |
| 1356 client_->NotifyResetDone(); |
1254 } | 1357 } |
1255 | 1358 |
1256 void AndroidVideoDecodeAccelerator::NotifyError( | 1359 void AndroidVideoDecodeAccelerator::NotifyError( |
1257 media::VideoDecodeAccelerator::Error error, | 1360 media::VideoDecodeAccelerator::Error error, |
1258 int token) { | 1361 int token) { |
1259 DVLOG(1) << __FUNCTION__ << ": error: " << error << " token: " << token | 1362 DVLOG(1) << __FUNCTION__ << ": error: " << error << " token: " << token |
1260 << " current: " << error_sequence_token_; | 1363 << " current: " << error_sequence_token_; |
1261 if (token != error_sequence_token_) | 1364 if (token != error_sequence_token_) |
1262 return; | 1365 return; |
1263 | 1366 |
1264 client_->NotifyError(error); | 1367 if (client_) |
| 1368 client_->NotifyError(error); |
1265 } | 1369 } |
1266 | 1370 |
1267 void AndroidVideoDecodeAccelerator::ManageTimer(bool did_work) { | 1371 void AndroidVideoDecodeAccelerator::ManageTimer(bool did_work) { |
1268 bool should_be_running = true; | 1372 bool should_be_running = true; |
1269 | 1373 |
1270 base::TimeTicks now = base::TimeTicks::Now(); | 1374 base::TimeTicks now = base::TimeTicks::Now(); |
1271 if (!did_work && !most_recent_work_.is_null()) { | 1375 if (!did_work && !most_recent_work_.is_null()) { |
1272 // Make sure that we have done work recently enough, else stop the timer. | 1376 // Make sure that we have done work recently enough, else stop the timer. |
1273 if (now - most_recent_work_ > IdleTimerTimeOut()) { | 1377 if (now - most_recent_work_ > IdleTimerTimeOut()) { |
1274 most_recent_work_ = base::TimeTicks(); | 1378 most_recent_work_ = base::TimeTicks(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1354 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { | 1458 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { |
1355 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: | 1459 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: |
1356 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1460 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
1357 } | 1461 } |
1358 } | 1462 } |
1359 | 1463 |
1360 return capabilities; | 1464 return capabilities; |
1361 } | 1465 } |
1362 | 1466 |
1363 } // namespace content | 1467 } // namespace content |
OLD | NEW |