Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Side by Side Diff: media/gpu/android_video_decode_accelerator.cc

Issue 2563533002: media: AVDA now doesn't queue EOS for a flush if the codec is empty (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/gpu/android_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "media/gpu/android_video_decode_accelerator.h" 5 #include "media/gpu/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
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 224
225 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( 225 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator(
226 const MakeGLContextCurrentCallback& make_context_current_cb, 226 const MakeGLContextCurrentCallback& make_context_current_cb,
227 const GetGLES2DecoderCallback& get_gles2_decoder_cb) 227 const GetGLES2DecoderCallback& get_gles2_decoder_cb)
228 : client_(NULL), 228 : client_(NULL),
229 make_context_current_cb_(make_context_current_cb), 229 make_context_current_cb_(make_context_current_cb),
230 get_gles2_decoder_cb_(get_gles2_decoder_cb), 230 get_gles2_decoder_cb_(get_gles2_decoder_cb),
231 state_(NO_ERROR), 231 state_(NO_ERROR),
232 picturebuffers_requested_(false), 232 picturebuffers_requested_(false),
233 picture_buffer_manager_(this), 233 picture_buffer_manager_(this),
234 drain_type_(DRAIN_TYPE_NONE),
235 media_drm_bridge_cdm_context_(nullptr), 234 media_drm_bridge_cdm_context_(nullptr),
236 cdm_registration_id_(0), 235 cdm_registration_id_(0),
237 pending_input_buf_index_(-1), 236 pending_input_buf_index_(-1),
238 deferred_initialization_pending_(false), 237 deferred_initialization_pending_(false),
239 codec_needs_reset_(false), 238 codec_needs_reset_(false),
240 defer_surface_creation_(false), 239 defer_surface_creation_(false),
241 weak_this_factory_(this) {} 240 weak_this_factory_(this) {}
242 241
243 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { 242 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
244 DCHECK(thread_checker_.CalledOnValidThread()); 243 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 MediaCodecStatus status = media_codec_->DequeueOutputBuffer( 585 MediaCodecStatus status = media_codec_->DequeueOutputBuffer(
587 NoWaitTimeOut, &buf_index, &offset, &size, &presentation_timestamp, 586 NoWaitTimeOut, &buf_index, &offset, &size, &presentation_timestamp,
588 &eos, NULL); 587 &eos, NULL);
589 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status, 588 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status,
590 "presentation_timestamp (ms)", 589 "presentation_timestamp (ms)",
591 presentation_timestamp.InMilliseconds()); 590 presentation_timestamp.InMilliseconds());
592 591
593 switch (status) { 592 switch (status) {
594 case MEDIA_CODEC_ERROR: 593 case MEDIA_CODEC_ERROR:
595 // Do not post an error if we are draining for reset and destroy. 594 // Do not post an error if we are draining for reset and destroy.
596 // Instead, run the drain completion task. 595 // Instead, signal completion of the drain.
597 if (IsDrainingForResetOrDestroy()) { 596 if (IsDrainingForResetOrDestroy()) {
598 DVLOG(1) << __func__ << ": error while codec draining"; 597 DVLOG(1) << __func__ << ": error while draining";
599 state_ = ERROR; 598 state_ = ERROR;
600 OnDrainCompleted(); 599 OnDrainCompleted();
601 } else { 600 } else {
602 NOTIFY_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed."); 601 NOTIFY_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed.");
603 } 602 }
604 return false; 603 return false;
605 604
606 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: 605 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
607 return false; 606 return false;
608 607
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 763
765 if (defer_surface_creation_ && !InitializePictureBufferManager()) { 764 if (defer_surface_creation_ && !InitializePictureBufferManager()) {
766 NOTIFY_ERROR(PLATFORM_FAILURE, 765 NOTIFY_ERROR(PLATFORM_FAILURE,
767 "Failed deferred surface and MediaCodec initialization."); 766 "Failed deferred surface and MediaCodec initialization.");
768 return; 767 return;
769 } 768 }
770 769
771 // If we previously deferred a codec restart, take care of it now. This can 770 // If we previously deferred a codec restart, take care of it now. This can
772 // happen on older devices where configuration changes require a codec reset. 771 // happen on older devices where configuration changes require a codec reset.
773 if (codec_needs_reset_) { 772 if (codec_needs_reset_) {
774 DCHECK_EQ(drain_type_, DRAIN_TYPE_NONE); 773 DCHECK(!drain_type_);
775 ResetCodecState(); 774 ResetCodecState();
776 } 775 }
777 776
778 if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) { 777 if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) {
779 DecodeBuffer(bitstream_buffer); 778 DecodeBuffer(bitstream_buffer);
780 return; 779 return;
781 } 780 }
782 781
783 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) 782 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
784 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); 783 base::SharedMemory::CloseHandle(bitstream_buffer.handle());
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 return; 856 return;
858 } 857 }
859 858
860 picture_buffer_manager_.ReuseOnePictureBuffer(it->second); 859 picture_buffer_manager_.ReuseOnePictureBuffer(it->second);
861 DoIOTask(true); 860 DoIOTask(true);
862 } 861 }
863 862
864 void AndroidVideoDecodeAccelerator::Flush() { 863 void AndroidVideoDecodeAccelerator::Flush() {
865 DVLOG(1) << __func__; 864 DVLOG(1) << __func__;
866 DCHECK(thread_checker_.CalledOnValidThread()); 865 DCHECK(thread_checker_.CalledOnValidThread());
867 866 StartCodecDrain(DRAIN_FOR_FLUSH);
868 if (state_ == SURFACE_DESTROYED || defer_surface_creation_)
watk 2016/12/07 23:30:32 These both imply media_codec == nullptr so I used
869 NotifyFlushDone();
870 else
871 StartCodecDrain(DRAIN_FOR_FLUSH);
872 } 867 }
873 868
874 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { 869 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() {
875 DCHECK(thread_checker_.CalledOnValidThread()); 870 DCHECK(thread_checker_.CalledOnValidThread());
876 871
877 DCHECK_NE(state_, WAITING_FOR_CODEC); 872 DCHECK_NE(state_, WAITING_FOR_CODEC);
878 state_ = WAITING_FOR_CODEC; 873 state_ = WAITING_FOR_CODEC;
879 874
880 if (media_codec_) { 875 if (media_codec_) {
881 AVDACodecAllocator::Instance()->ReleaseMediaCodec( 876 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 950
956 state_ = NO_ERROR; 951 state_ = NO_ERROR;
957 952
958 ManageTimer(true); 953 ManageTimer(true);
959 } 954 }
960 955
961 void AndroidVideoDecodeAccelerator::StartCodecDrain(DrainType drain_type) { 956 void AndroidVideoDecodeAccelerator::StartCodecDrain(DrainType drain_type) {
962 DVLOG(2) << __func__ << " drain_type:" << drain_type; 957 DVLOG(2) << __func__ << " drain_type:" << drain_type;
963 DCHECK(thread_checker_.CalledOnValidThread()); 958 DCHECK(thread_checker_.CalledOnValidThread());
964 959
965 // We assume that DRAIN_FOR_FLUSH and DRAIN_FOR_RESET cannot come while 960 auto previous_drain_type = drain_type_;
966 // another drain request is present, but DRAIN_FOR_DESTROY can.
967 DCHECK_NE(drain_type, DRAIN_TYPE_NONE);
968 DCHECK(drain_type_ == DRAIN_TYPE_NONE || drain_type == DRAIN_FOR_DESTROY)
969 << "Unexpected StartCodecDrain() with drain type " << drain_type
970 << " while already draining with drain type " << drain_type_;
971
972 const bool enqueue_eos = drain_type_ == DRAIN_TYPE_NONE;
973 drain_type_ = drain_type; 961 drain_type_ = drain_type;
974 962
975 if (enqueue_eos) 963 // Only DRAIN_FOR_DESTROY is allowed while a drain is already in progress.
964 DCHECK(!previous_drain_type || drain_type == DRAIN_FOR_DESTROY)
965 << "StartCodecDrain(" << drain_type
966 << ") while already draining with type " << previous_drain_type.value();
967
968 // Skip the drain if possible. We still need to drain VP8 for destroy and
969 // reset because MediaCodec might hang in release() or flush() if we don't.
DaleCurtis 2016/12/08 00:11:13 Comment is a bit misleading, code skips drain if t
970 // http://crbug.com/598963
971 if (!media_codec_ || (pending_bitstream_records_.empty() &&
DaleCurtis 2016/12/08 00:11:14 Maybe clarify that in the case of Reset() pending
972 bitstream_buffers_in_decoder_.empty()) ||
973 (drain_type != DRAIN_FOR_FLUSH && codec_config_->codec != kCodecVP8)) {
974 OnDrainCompleted();
975 return;
976 }
977
978 // Queue EOS if one is not already queued.
979 if (!previous_drain_type)
976 DecodeBuffer(BitstreamBuffer(-1, base::SharedMemoryHandle(), 0)); 980 DecodeBuffer(BitstreamBuffer(-1, base::SharedMemoryHandle(), 0));
977 } 981 }
978 982
979 bool AndroidVideoDecodeAccelerator::IsDrainingForResetOrDestroy() const { 983 bool AndroidVideoDecodeAccelerator::IsDrainingForResetOrDestroy() const {
980 return drain_type_ == DRAIN_FOR_RESET || drain_type_ == DRAIN_FOR_DESTROY; 984 return drain_type_ == DRAIN_FOR_RESET || drain_type_ == DRAIN_FOR_DESTROY;
981 } 985 }
982 986
983 void AndroidVideoDecodeAccelerator::OnDrainCompleted() { 987 void AndroidVideoDecodeAccelerator::OnDrainCompleted() {
984 DVLOG(2) << __func__; 988 DVLOG(2) << __func__;
985 DCHECK(thread_checker_.CalledOnValidThread()); 989 DCHECK(thread_checker_.CalledOnValidThread());
986 990
987 // If we were waiting for an EOS, clear the state and reset the MediaCodec 991 // Sometimes MediaCodec returns an EOS buffer even if we didn't queue one.
988 // as normal. 992 // Consider it an error. http://crbug.com/585959.
989 // 993 if (!drain_type_) {
990 // Some Android platforms seem to send an EOS buffer even when we're not 994 state_ = ERROR;
991 // expecting it. In this case, destroy and reset the codec but don't notify 995 ResetCodecState();
992 // flush done since it violates the state machine. http://crbug.com/585959. 996 return;
997 }
993 998
994 switch (drain_type_) { 999 ResetCodecState();
995 case DRAIN_TYPE_NONE: 1000 switch (*drain_type_) {
996 // Unexpected EOS.
997 state_ = ERROR;
998 ResetCodecState();
999 break;
1000 case DRAIN_FOR_FLUSH: 1001 case DRAIN_FOR_FLUSH:
1001 ResetCodecState();
1002 base::ThreadTaskRunnerHandle::Get()->PostTask( 1002 base::ThreadTaskRunnerHandle::Get()->PostTask(
1003 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone, 1003 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone,
1004 weak_this_factory_.GetWeakPtr())); 1004 weak_this_factory_.GetWeakPtr()));
1005 break; 1005 break;
1006 case DRAIN_FOR_RESET: 1006 case DRAIN_FOR_RESET:
1007 ResetCodecState();
1008 base::ThreadTaskRunnerHandle::Get()->PostTask( 1007 base::ThreadTaskRunnerHandle::Get()->PostTask(
1009 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, 1008 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone,
1010 weak_this_factory_.GetWeakPtr())); 1009 weak_this_factory_.GetWeakPtr()));
1011 break; 1010 break;
1012 case DRAIN_FOR_DESTROY: 1011 case DRAIN_FOR_DESTROY:
1013 ResetCodecState();
1014 base::ThreadTaskRunnerHandle::Get()->PostTask( 1012 base::ThreadTaskRunnerHandle::Get()->PostTask(
1015 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::ActualDestroy, 1013 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::ActualDestroy,
1016 weak_this_factory_.GetWeakPtr())); 1014 weak_this_factory_.GetWeakPtr()));
1017 break; 1015 break;
1018 } 1016 }
1019 drain_type_ = DRAIN_TYPE_NONE; 1017 drain_type_.reset();
1020 } 1018 }
1021 1019
1022 void AndroidVideoDecodeAccelerator::ResetCodecState() { 1020 void AndroidVideoDecodeAccelerator::ResetCodecState() {
1023 DCHECK(thread_checker_.CalledOnValidThread()); 1021 DCHECK(thread_checker_.CalledOnValidThread());
1024 1022
1025 // If there is already a reset in flight, then that counts. This can really 1023 // If there is already a reset in flight, then that counts. This can really
1026 // only happen if somebody calls Reset. 1024 // only happen if somebody calls Reset.
1027 // If the surface is destroyed there's nothing to do. 1025 // If the surface is destroyed there's nothing to do.
1028 if (state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED) 1026 if (state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED)
1029 return; 1027 return;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 base::ThreadTaskRunnerHandle::Get()->PostTask( 1088 base::ThreadTaskRunnerHandle::Get()->PostTask(
1091 FROM_HERE, 1089 FROM_HERE,
1092 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer, 1090 base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer,
1093 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); 1091 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id));
1094 } 1092 }
1095 } 1093 }
1096 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); 1094 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0);
1097 bitstreams_notified_in_advance_.clear(); 1095 bitstreams_notified_in_advance_.clear();
1098 1096
1099 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_); 1097 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_);
1100 1098 StartCodecDrain(DRAIN_FOR_RESET);
1101 // Some VP8 files require complete MediaCodec drain before we can call
1102 // MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963.
1103 if (media_codec_ && codec_config_->codec == kCodecVP8 &&
1104 !bitstream_buffers_in_decoder_.empty()) {
1105 // Postpone ResetCodecState() after the drain.
1106 StartCodecDrain(DRAIN_FOR_RESET);
1107 } else {
1108 ResetCodecState();
1109 base::ThreadTaskRunnerHandle::Get()->PostTask(
1110 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone,
1111 weak_this_factory_.GetWeakPtr()));
1112 }
1113 } 1099 }
1114 1100
1115 void AndroidVideoDecodeAccelerator::SetSurface(int32_t surface_id) { 1101 void AndroidVideoDecodeAccelerator::SetSurface(int32_t surface_id) {
1116 DVLOG(1) << __func__; 1102 DVLOG(1) << __func__;
1117 DCHECK(thread_checker_.CalledOnValidThread()); 1103 DCHECK(thread_checker_.CalledOnValidThread());
1118 1104
1119 if (surface_id == config_.surface_id) { 1105 if (surface_id == config_.surface_id) {
1120 pending_surface_id_.reset(); 1106 pending_surface_id_.reset();
1121 return; 1107 return;
1122 } 1108 }
1123 1109
1124 // Surface changes never take effect immediately, they will be handled during 1110 // Surface changes never take effect immediately, they will be handled during
1125 // DequeOutput() once we get to a good switch point or immediately during an 1111 // DequeOutput() once we get to a good switch point or immediately during an
1126 // OnSurfaceDestroyed() call. 1112 // OnSurfaceDestroyed() call.
1127 pending_surface_id_ = surface_id; 1113 pending_surface_id_ = surface_id;
1128 } 1114 }
1129 1115
1130 void AndroidVideoDecodeAccelerator::Destroy() { 1116 void AndroidVideoDecodeAccelerator::Destroy() {
1131 DVLOG(1) << __func__; 1117 DVLOG(1) << __func__;
1132 DCHECK(thread_checker_.CalledOnValidThread()); 1118 DCHECK(thread_checker_.CalledOnValidThread());
1133 1119
1134 picture_buffer_manager_.Destroy(output_picture_buffers_); 1120 picture_buffer_manager_.Destroy(output_picture_buffers_);
1135 1121
1136 client_ = nullptr; 1122 client_ = nullptr;
1137 1123
1138 // Some VP8 files require a complete MediaCodec drain before we can call 1124 // We don't want to queue more inputs while draining.
1139 // MediaCodec.flush() or MediaCodec.release(). http://crbug.com/598963. In 1125 while (!pending_bitstream_records_.empty())
DaleCurtis 2016/12/08 00:29:35 Because I was curious and have been benchmarking t
1140 // that case, postpone ActualDestroy() until after the drain. 1126 pending_bitstream_records_.pop();
1141 if (media_codec_ && codec_config_->codec == kCodecVP8) { 1127 StartCodecDrain(DRAIN_FOR_DESTROY);
1142 // Clear |pending_bitstream_records_|.
1143 while (!pending_bitstream_records_.empty())
1144 pending_bitstream_records_.pop();
1145
1146 StartCodecDrain(DRAIN_FOR_DESTROY);
1147 } else {
1148 ActualDestroy();
1149 }
1150 } 1128 }
1151 1129
1152 void AndroidVideoDecodeAccelerator::ActualDestroy() { 1130 void AndroidVideoDecodeAccelerator::ActualDestroy() {
1153 DVLOG(1) << __func__; 1131 DVLOG(1) << __func__;
1154 DCHECK(thread_checker_.CalledOnValidThread()); 1132 DCHECK(thread_checker_.CalledOnValidThread());
1155 1133
1156 // Note that async codec construction might still be in progress. In that 1134 // Note that async codec construction might still be in progress. In that
1157 // case, the codec will be deleted when it completes once we invalidate all 1135 // case, the codec will be deleted when it completes once we invalidate all
1158 // our weak refs. 1136 // our weak refs.
1159 weak_this_factory_.InvalidateWeakPtrs(); 1137 weak_this_factory_.InvalidateWeakPtrs();
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 // SURFACE_DESTROYED. 1193 // SURFACE_DESTROYED.
1216 state_ = SURFACE_DESTROYED; 1194 state_ = SURFACE_DESTROYED;
1217 if (media_codec_) { 1195 if (media_codec_) {
1218 AVDACodecAllocator::Instance()->ReleaseMediaCodec( 1196 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1219 std::move(media_codec_), codec_config_->task_type, config_.surface_id); 1197 std::move(media_codec_), codec_config_->task_type, config_.surface_id);
1220 picture_buffer_manager_.CodecChanged(nullptr); 1198 picture_buffer_manager_.CodecChanged(nullptr);
1221 } 1199 }
1222 1200
1223 // If we're draining, signal completion now because the drain can no longer 1201 // If we're draining, signal completion now because the drain can no longer
1224 // proceed. 1202 // proceed.
1225 if (drain_type_ != DRAIN_TYPE_NONE) 1203 if (drain_type_)
1226 OnDrainCompleted(); 1204 OnDrainCompleted();
1227 } 1205 }
1228 1206
1229 void AndroidVideoDecodeAccelerator::InitializeCdm() { 1207 void AndroidVideoDecodeAccelerator::InitializeCdm() {
1230 DVLOG(2) << __func__ << ": " << config_.cdm_id; 1208 DVLOG(2) << __func__ << ": " << config_.cdm_id;
1231 1209
1232 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 1210 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
1233 NOTIMPLEMENTED(); 1211 NOTIMPLEMENTED();
1234 NotifyInitializationComplete(false); 1212 NotifyInitializationComplete(false);
1235 #else 1213 #else
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 AVDACodecAllocator::Instance()->DeallocateSurface(this, new_surface_id); 1488 AVDACodecAllocator::Instance()->DeallocateSurface(this, new_surface_id);
1511 } 1489 }
1512 1490
1513 // Regardless of whether we succeeded, we no longer own the previous surface. 1491 // Regardless of whether we succeeded, we no longer own the previous surface.
1514 AVDACodecAllocator::Instance()->DeallocateSurface(this, previous_surface_id); 1492 AVDACodecAllocator::Instance()->DeallocateSurface(this, previous_surface_id);
1515 1493
1516 return success; 1494 return success;
1517 } 1495 }
1518 1496
1519 } // namespace media 1497 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/android_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698