OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/filters/android/media_codec_audio_decoder.h" | 5 #include "media/filters/android/media_codec_audio_decoder.h" |
6 | 6 |
7 #include "base/android/build_info.h" | 7 #include "base/android/build_info.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 MediaCodecAudioDecoder::~MediaCodecAudioDecoder() { | 79 MediaCodecAudioDecoder::~MediaCodecAudioDecoder() { |
80 DVLOG(1) << __FUNCTION__; | 80 DVLOG(1) << __FUNCTION__; |
81 | 81 |
82 media_codec_.reset(); | 82 media_codec_.reset(); |
83 | 83 |
84 if (media_drm_bridge_cdm_context_) { | 84 if (media_drm_bridge_cdm_context_) { |
85 DCHECK(cdm_registration_id_); | 85 DCHECK(cdm_registration_id_); |
86 media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_); | 86 media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_); |
87 } | 87 } |
88 | 88 |
89 ClearInputQueue(kAborted); | 89 ClearInputQueue(DecodeStatus::ABORTED); |
90 } | 90 } |
91 | 91 |
92 std::string MediaCodecAudioDecoder::GetDisplayName() const { | 92 std::string MediaCodecAudioDecoder::GetDisplayName() const { |
93 return "MediaCodecAudioDecoder"; | 93 return "MediaCodecAudioDecoder"; |
94 } | 94 } |
95 | 95 |
96 void MediaCodecAudioDecoder::Initialize(const AudioDecoderConfig& config, | 96 void MediaCodecAudioDecoder::Initialize(const AudioDecoderConfig& config, |
97 CdmContext* cdm_context, | 97 CdmContext* cdm_context, |
98 const InitCB& init_cb, | 98 const InitCB& init_cb, |
99 const OutputCB& output_cb) { | 99 const OutputCB& output_cb) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 bound_init_cb.Run(true); | 141 bound_init_cb.Run(true); |
142 } | 142 } |
143 | 143 |
144 void MediaCodecAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 144 void MediaCodecAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
145 const DecodeCB& decode_cb) { | 145 const DecodeCB& decode_cb) { |
146 DecodeCB bound_decode_cb = BindToCurrentLoop(decode_cb); | 146 DecodeCB bound_decode_cb = BindToCurrentLoop(decode_cb); |
147 | 147 |
148 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) { | 148 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) { |
149 DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString() | 149 DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString() |
150 << ": no timestamp, skipping this buffer"; | 150 << ": no timestamp, skipping this buffer"; |
151 bound_decode_cb.Run(kDecodeError); | 151 bound_decode_cb.Run(DecodeStatus::DECODE_ERROR); |
152 return; | 152 return; |
153 } | 153 } |
154 | 154 |
155 if (state_ == STATE_ERROR) { | 155 if (state_ == STATE_ERROR) { |
156 // We get here if an error happens in DequeueOutput() or Reset(). | 156 // We get here if an error happens in DequeueOutput() or Reset(). |
157 DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString() | 157 DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString() |
158 << ": Error state, returning decode error for all buffers"; | 158 << ": Error state, returning decode error for all buffers"; |
159 ClearInputQueue(kDecodeError); | 159 ClearInputQueue(DecodeStatus::DECODE_ERROR); |
160 bound_decode_cb.Run(kDecodeError); | 160 bound_decode_cb.Run(DecodeStatus::DECODE_ERROR); |
161 return; | 161 return; |
162 } | 162 } |
163 | 163 |
164 DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString(); | 164 DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString(); |
165 | 165 |
166 DCHECK_EQ(state_, STATE_READY) << " unexpected state " << AsString(state_); | 166 DCHECK_EQ(state_, STATE_READY) << " unexpected state " << AsString(state_); |
167 | 167 |
168 // AudioDecoder requires that "Only one decode may be in flight at any given | 168 // AudioDecoder requires that "Only one decode may be in flight at any given |
169 // time". | 169 // time". |
170 DCHECK(input_queue_.empty()); | 170 DCHECK(input_queue_.empty()); |
171 | 171 |
172 input_queue_.push_back(std::make_pair(buffer, bound_decode_cb)); | 172 input_queue_.push_back(std::make_pair(buffer, bound_decode_cb)); |
173 | 173 |
174 DoIOTask(); | 174 DoIOTask(); |
175 } | 175 } |
176 | 176 |
177 void MediaCodecAudioDecoder::Reset(const base::Closure& closure) { | 177 void MediaCodecAudioDecoder::Reset(const base::Closure& closure) { |
178 DVLOG(1) << __FUNCTION__; | 178 DVLOG(1) << __FUNCTION__; |
179 | 179 |
180 io_timer_.Stop(); | 180 io_timer_.Stop(); |
181 | 181 |
182 ClearInputQueue(kAborted); | 182 ClearInputQueue(DecodeStatus::ABORTED); |
183 | 183 |
184 // Flush if we can, otherwise completely recreate and reconfigure the codec. | 184 // Flush if we can, otherwise completely recreate and reconfigure the codec. |
185 // Prior to JellyBean-MR2, flush() had several bugs (b/8125974, b/8347958) so | 185 // Prior to JellyBean-MR2, flush() had several bugs (b/8125974, b/8347958) so |
186 // we have to completely destroy and recreate the codec there. | 186 // we have to completely destroy and recreate the codec there. |
187 bool success = false; | 187 bool success = false; |
188 if (state_ != STATE_ERROR && state_ != STATE_DRAINED && | 188 if (state_ != STATE_ERROR && state_ != STATE_DRAINED && |
189 base::android::BuildInfo::GetInstance()->sdk_int() >= 18) { | 189 base::android::BuildInfo::GetInstance()->sdk_int() >= 18) { |
190 // media_codec_->Reset() calls MediaCodec.flush(). | 190 // media_codec_->Reset() calls MediaCodec.flush(). |
191 success = (media_codec_->Reset() == MEDIA_CODEC_OK); | 191 success = (media_codec_->Reset() == MEDIA_CODEC_OK); |
192 } | 192 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 | 311 |
312 if (state_ == STATE_WAITING_FOR_KEY || state_ == STATE_DRAINING || | 312 if (state_ == STATE_WAITING_FOR_KEY || state_ == STATE_DRAINING || |
313 state_ == STATE_DRAINED) | 313 state_ == STATE_DRAINED) |
314 return false; | 314 return false; |
315 | 315 |
316 // DequeueInputBuffer() may set STATE_ERROR. | 316 // DequeueInputBuffer() may set STATE_ERROR. |
317 InputBufferInfo input_info = DequeueInputBuffer(); | 317 InputBufferInfo input_info = DequeueInputBuffer(); |
318 | 318 |
319 if (input_info.buf_index == kInvalidBufferIndex) { | 319 if (input_info.buf_index == kInvalidBufferIndex) { |
320 if (state_ == STATE_ERROR) | 320 if (state_ == STATE_ERROR) |
321 ClearInputQueue(kDecodeError); | 321 ClearInputQueue(DecodeStatus::DECODE_ERROR); |
322 | 322 |
323 return false; | 323 return false; |
324 } | 324 } |
325 | 325 |
326 // EnqueueInputBuffer() may set STATE_DRAINING, STATE_WAITING_FOR_KEY or | 326 // EnqueueInputBuffer() may set STATE_DRAINING, STATE_WAITING_FOR_KEY or |
327 // STATE_ERROR. | 327 // STATE_ERROR. |
328 bool did_work = EnqueueInputBuffer(input_info); | 328 bool did_work = EnqueueInputBuffer(input_info); |
329 | 329 |
330 switch (state_) { | 330 switch (state_) { |
331 case STATE_READY: { | 331 case STATE_READY: { |
332 const DecodeCB& decode_cb = input_queue_.front().second; | 332 const DecodeCB& decode_cb = input_queue_.front().second; |
333 decode_cb.Run(kOk); | 333 decode_cb.Run(DecodeStatus::OK); |
334 input_queue_.pop_front(); | 334 input_queue_.pop_front(); |
335 } break; | 335 } break; |
336 | 336 |
337 case STATE_DRAINING: | 337 case STATE_DRAINING: |
338 // After queueing EOS we need to flush decoder, i.e. receive this EOS at | 338 // After queueing EOS we need to flush decoder, i.e. receive this EOS at |
339 // the output, and then call corresponding decoder_cb. | 339 // the output, and then call corresponding decoder_cb. |
340 // Keep the EOS buffer in the input queue. | 340 // Keep the EOS buffer in the input queue. |
341 break; | 341 break; |
342 | 342 |
343 case STATE_WAITING_FOR_KEY: | 343 case STATE_WAITING_FOR_KEY: |
344 // Keep trying to enqueue the same input buffer. | 344 // Keep trying to enqueue the same input buffer. |
345 // The buffer is owned by us (not the MediaCodec) and is filled with data. | 345 // The buffer is owned by us (not the MediaCodec) and is filled with data. |
346 break; | 346 break; |
347 | 347 |
348 case STATE_ERROR: | 348 case STATE_ERROR: |
349 ClearInputQueue(kDecodeError); | 349 ClearInputQueue(DecodeStatus::DECODE_ERROR); |
350 break; | 350 break; |
351 | 351 |
352 default: | 352 default: |
353 NOTREACHED() << ": internal error, unexpected state " << AsString(state_); | 353 NOTREACHED() << ": internal error, unexpected state " << AsString(state_); |
354 SetState(STATE_ERROR); | 354 SetState(STATE_ERROR); |
355 ClearInputQueue(kDecodeError); | 355 ClearInputQueue(DecodeStatus::DECODE_ERROR); |
356 did_work = false; | 356 did_work = false; |
357 break; | 357 break; |
358 } | 358 } |
359 | 359 |
360 return did_work; | 360 return did_work; |
361 } | 361 } |
362 | 362 |
363 MediaCodecAudioDecoder::InputBufferInfo | 363 MediaCodecAudioDecoder::InputBufferInfo |
364 MediaCodecAudioDecoder::DequeueInputBuffer() { | 364 MediaCodecAudioDecoder::DequeueInputBuffer() { |
365 DVLOG(2) << __FUNCTION__; | 365 DVLOG(2) << __FUNCTION__; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 break; | 461 break; |
462 | 462 |
463 default: | 463 default: |
464 NOTREACHED() << "Unknown Queue(Secure)InputBuffer status " << status; | 464 NOTREACHED() << "Unknown Queue(Secure)InputBuffer status " << status; |
465 SetState(STATE_ERROR); | 465 SetState(STATE_ERROR); |
466 break; | 466 break; |
467 } | 467 } |
468 return did_work; | 468 return did_work; |
469 } | 469 } |
470 | 470 |
471 void MediaCodecAudioDecoder::ClearInputQueue(Status decode_status) { | 471 void MediaCodecAudioDecoder::ClearInputQueue(DecodeStatus decode_status) { |
472 DVLOG(2) << __FUNCTION__; | 472 DVLOG(2) << __FUNCTION__; |
473 | 473 |
474 for (const auto& entry : input_queue_) | 474 for (const auto& entry : input_queue_) |
475 entry.second.Run(decode_status); | 475 entry.second.Run(decode_status); |
476 | 476 |
477 input_queue_.clear(); | 477 input_queue_.clear(); |
478 } | 478 } |
479 | 479 |
480 bool MediaCodecAudioDecoder::DequeueOutput() { | 480 bool MediaCodecAudioDecoder::DequeueOutput() { |
481 DVLOG(2) << __FUNCTION__; | 481 DVLOG(2) << __FUNCTION__; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 | 570 |
571 DCHECK_EQ(state_, STATE_DRAINING); | 571 DCHECK_EQ(state_, STATE_DRAINING); |
572 | 572 |
573 media_codec_->ReleaseOutputBuffer(out.buf_index, false); | 573 media_codec_->ReleaseOutputBuffer(out.buf_index, false); |
574 | 574 |
575 // Report the end of decoding for EOS DecoderBuffer. | 575 // Report the end of decoding for EOS DecoderBuffer. |
576 DCHECK(!input_queue_.empty()); | 576 DCHECK(!input_queue_.empty()); |
577 DCHECK(input_queue_.front().first->end_of_stream()); | 577 DCHECK(input_queue_.front().first->end_of_stream()); |
578 | 578 |
579 const DecodeCB& decode_cb = input_queue_.front().second; | 579 const DecodeCB& decode_cb = input_queue_.front().second; |
580 decode_cb.Run(kOk); | 580 decode_cb.Run(DecodeStatus::OK); |
581 | 581 |
582 // Remove the EOS buffer from the input queue. | 582 // Remove the EOS buffer from the input queue. |
583 input_queue_.pop_front(); | 583 input_queue_.pop_front(); |
584 | 584 |
585 // Set state STATE_DRAINED after we have received EOS frame at the output. | 585 // Set state STATE_DRAINED after we have received EOS frame at the output. |
586 // media_decoder_job.cc says: once output EOS has occurred, we should | 586 // media_decoder_job.cc says: once output EOS has occurred, we should |
587 // not be asked to decode again. | 587 // not be asked to decode again. |
588 SetState(STATE_DRAINED); | 588 SetState(STATE_DRAINED); |
589 } | 589 } |
590 | 590 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 RETURN_STRING(STATE_DRAINED); | 668 RETURN_STRING(STATE_DRAINED); |
669 RETURN_STRING(STATE_ERROR); | 669 RETURN_STRING(STATE_ERROR); |
670 } | 670 } |
671 NOTREACHED() << "Unknown state " << state; | 671 NOTREACHED() << "Unknown state " << state; |
672 return nullptr; | 672 return nullptr; |
673 } | 673 } |
674 | 674 |
675 #undef RETURN_STRING | 675 #undef RETURN_STRING |
676 | 676 |
677 } // namespace media | 677 } // namespace media |
OLD | NEW |