| 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 |