OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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/base/android/media_decoder_job.h" | 5 #include "media/base/android/media_decoder_job.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/message_loop/message_loop_proxy.h" | 9 #include "base/message_loop/message_loop_proxy.h" |
10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 if (HasData()) { | 103 if (HasData()) { |
104 DVLOG(1) << __FUNCTION__ << " : using previously received data"; | 104 DVLOG(1) << __FUNCTION__ << " : using previously received data"; |
105 ui_task_runner_->PostTask(FROM_HERE, prefetch_cb); | 105 ui_task_runner_->PostTask(FROM_HERE, prefetch_cb); |
106 return; | 106 return; |
107 } | 107 } |
108 | 108 |
109 DVLOG(1) << __FUNCTION__ << " : requesting data"; | 109 DVLOG(1) << __FUNCTION__ << " : requesting data"; |
110 RequestData(prefetch_cb); | 110 RequestData(prefetch_cb); |
111 } | 111 } |
112 | 112 |
113 bool MediaDecoderJob::Decode( | 113 MediaDecoderJob::MediaDecoderJobStatus MediaDecoderJob::Decode( |
114 base::TimeTicks start_time_ticks, | 114 base::TimeTicks start_time_ticks, |
115 base::TimeDelta start_presentation_timestamp, | 115 base::TimeDelta start_presentation_timestamp, |
116 const DecoderCallback& callback) { | 116 const DecoderCallback& callback) { |
117 DCHECK(decode_cb_.is_null()); | 117 DCHECK(decode_cb_.is_null()); |
118 DCHECK(data_received_cb_.is_null()); | 118 DCHECK(data_received_cb_.is_null()); |
119 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 119 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
120 if (!media_codec_bridge_ || need_to_reconfig_decoder_job_) { | 120 if (!media_codec_bridge_ || need_to_reconfig_decoder_job_) { |
121 if (drain_decoder_) | 121 if (drain_decoder_) |
122 OnDecoderDrained(); | 122 OnDecoderDrained(); |
123 need_to_reconfig_decoder_job_ = !CreateMediaCodecBridge(); | 123 MediaDecoderJobStatus status = CreateMediaCodecBridge(); |
| 124 need_to_reconfig_decoder_job_ = (status != STATUS_SUCCESS); |
124 skip_eos_enqueue_ = true; | 125 skip_eos_enqueue_ = true; |
125 if (need_to_reconfig_decoder_job_) | 126 if (need_to_reconfig_decoder_job_) |
126 return false; | 127 return status; |
127 } | 128 } |
128 | 129 |
129 decode_cb_ = callback; | 130 decode_cb_ = callback; |
130 | 131 |
131 if (!HasData()) { | 132 if (!HasData()) { |
132 RequestData(base::Bind(&MediaDecoderJob::DecodeCurrentAccessUnit, | 133 RequestData(base::Bind(&MediaDecoderJob::DecodeCurrentAccessUnit, |
133 base::Unretained(this), | 134 base::Unretained(this), |
134 start_time_ticks, | 135 start_time_ticks, |
135 start_presentation_timestamp)); | 136 start_presentation_timestamp)); |
136 return true; | 137 return STATUS_SUCCESS; |
137 } | 138 } |
138 | 139 |
139 DecodeCurrentAccessUnit(start_time_ticks, start_presentation_timestamp); | 140 DecodeCurrentAccessUnit(start_time_ticks, start_presentation_timestamp); |
140 return true; | 141 return STATUS_SUCCESS; |
141 } | 142 } |
142 | 143 |
143 void MediaDecoderJob::StopDecode() { | 144 void MediaDecoderJob::StopDecode() { |
144 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 145 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
145 DCHECK(is_decoding()); | 146 DCHECK(is_decoding()); |
146 stop_decode_pending_ = true; | 147 stop_decode_pending_ = true; |
147 } | 148 } |
148 | 149 |
149 bool MediaDecoderJob::OutputEOSReached() const { | 150 bool MediaDecoderJob::OutputEOSReached() const { |
150 return !drain_decoder_ && output_eos_encountered_; | 151 return !drain_decoder_ && output_eos_encountered_; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 release_resources_pending_ = true; | 199 release_resources_pending_ = true; |
199 } | 200 } |
200 | 201 |
201 base::android::ScopedJavaLocalRef<jobject> MediaDecoderJob::GetMediaCrypto() { | 202 base::android::ScopedJavaLocalRef<jobject> MediaDecoderJob::GetMediaCrypto() { |
202 base::android::ScopedJavaLocalRef<jobject> media_crypto; | 203 base::android::ScopedJavaLocalRef<jobject> media_crypto; |
203 if (drm_bridge_) | 204 if (drm_bridge_) |
204 media_crypto = drm_bridge_->GetMediaCrypto(); | 205 media_crypto = drm_bridge_->GetMediaCrypto(); |
205 return media_crypto; | 206 return media_crypto; |
206 } | 207 } |
207 | 208 |
| 209 bool MediaDecoderJob::SetCurrentFrameToPreviouslyCachedKeyFrame() { |
| 210 const std::vector<AccessUnit>& access_units = |
| 211 received_data_[current_demuxer_data_index_].access_units; |
| 212 // If the current data chunk is empty, the player must be in an initial or |
| 213 // seek state. The next access unit will always be a key frame. |
| 214 if (access_units.size() == 0) |
| 215 return true; |
| 216 |
| 217 // Find key frame in all the access units the decoder have decoded, |
| 218 // or is about to decode. |
| 219 int i = std::min(access_unit_index_[current_demuxer_data_index_], |
| 220 access_units.size() - 1); |
| 221 for (; i >= 0; --i) { |
| 222 // Config change is always the last access unit, and it always come with |
| 223 // a key frame afterwards. |
| 224 if (access_units[i].status == DemuxerStream::kConfigChanged) |
| 225 return true; |
| 226 if (access_units[i].is_key_frame) { |
| 227 access_unit_index_[current_demuxer_data_index_] = i; |
| 228 return true; |
| 229 } |
| 230 } |
| 231 return false; |
| 232 } |
| 233 |
| 234 |
208 void MediaDecoderJob::Release() { | 235 void MediaDecoderJob::Release() { |
209 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 236 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
210 DVLOG(1) << __FUNCTION__; | 237 DVLOG(1) << __FUNCTION__; |
211 | 238 |
212 // If the decoder job is still decoding, we cannot delete the job immediately. | 239 // If the decoder job is still decoding, we cannot delete the job immediately. |
213 destroy_pending_ = is_decoding(); | 240 destroy_pending_ = is_decoding(); |
214 | 241 |
215 request_data_cb_.Reset(); | 242 request_data_cb_.Reset(); |
216 data_received_cb_.Reset(); | 243 data_received_cb_.Reset(); |
217 decode_cb_.Reset(); | 244 decode_cb_.Reset(); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 if (current_presentation_timestamp != kNoTimestamp() || | 538 if (current_presentation_timestamp != kNoTimestamp() || |
512 status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { | 539 status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { |
513 prerolling_ = false; | 540 prerolling_ = false; |
514 } | 541 } |
515 | 542 |
516 switch (status) { | 543 switch (status) { |
517 case MEDIA_CODEC_OK: | 544 case MEDIA_CODEC_OK: |
518 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: | 545 case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
519 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: | 546 case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: |
520 case MEDIA_CODEC_OUTPUT_END_OF_STREAM: | 547 case MEDIA_CODEC_OUTPUT_END_OF_STREAM: |
521 if (!input_eos_encountered_) { | 548 if (!input_eos_encountered_) |
522 CurrentDataConsumed( | |
523 CurrentAccessUnit().status == DemuxerStream::kConfigChanged); | |
524 access_unit_index_[current_demuxer_data_index_]++; | 549 access_unit_index_[current_demuxer_data_index_]++; |
525 } | |
526 break; | 550 break; |
527 | 551 |
528 case MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER: | 552 case MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER: |
529 case MEDIA_CODEC_INPUT_END_OF_STREAM: | 553 case MEDIA_CODEC_INPUT_END_OF_STREAM: |
530 case MEDIA_CODEC_NO_KEY: | 554 case MEDIA_CODEC_NO_KEY: |
531 case MEDIA_CODEC_ABORT: | 555 case MEDIA_CODEC_ABORT: |
532 case MEDIA_CODEC_ERROR: | 556 case MEDIA_CODEC_ERROR: |
533 // Do nothing. | 557 // Do nothing. |
534 break; | 558 break; |
535 | 559 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 } | 606 } |
583 | 607 |
584 void MediaDecoderJob::RequestCurrentChunkIfEmpty() { | 608 void MediaDecoderJob::RequestCurrentChunkIfEmpty() { |
585 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 609 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
586 DCHECK(HasData()); | 610 DCHECK(HasData()); |
587 if (!NoAccessUnitsRemainingInChunk(true)) | 611 if (!NoAccessUnitsRemainingInChunk(true)) |
588 return; | 612 return; |
589 | 613 |
590 // Requests new data if the the last access unit of the next chunk is not EOS. | 614 // Requests new data if the the last access unit of the next chunk is not EOS. |
591 current_demuxer_data_index_ = inactive_demuxer_data_index(); | 615 current_demuxer_data_index_ = inactive_demuxer_data_index(); |
592 const AccessUnit last_access_unit = | 616 const AccessUnit& last_access_unit = |
593 received_data_[current_demuxer_data_index_].access_units.back(); | 617 received_data_[current_demuxer_data_index_].access_units.back(); |
594 if (!last_access_unit.is_end_of_stream && | 618 if (!last_access_unit.is_end_of_stream && |
595 last_access_unit.status != DemuxerStream::kAborted) { | 619 last_access_unit.status != DemuxerStream::kAborted) { |
596 RequestData(base::Closure()); | 620 RequestData(base::Closure()); |
597 } | 621 } |
598 } | 622 } |
599 | 623 |
600 void MediaDecoderJob::InitializeReceivedData() { | 624 void MediaDecoderJob::InitializeReceivedData() { |
601 for (size_t i = 0; i < 2; ++i) { | 625 for (size_t i = 0; i < 2; ++i) { |
602 received_data_[i] = DemuxerData(); | 626 received_data_[i] = DemuxerData(); |
603 access_unit_index_[i] = 0; | 627 access_unit_index_[i] = 0; |
604 } | 628 } |
605 } | 629 } |
606 | 630 |
607 void MediaDecoderJob::OnDecoderDrained() { | 631 void MediaDecoderJob::OnDecoderDrained() { |
608 DVLOG(1) << __FUNCTION__; | 632 DVLOG(1) << __FUNCTION__; |
609 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 633 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
610 DCHECK(drain_decoder_); | 634 DCHECK(drain_decoder_); |
611 | 635 |
612 input_eos_encountered_ = false; | 636 input_eos_encountered_ = false; |
613 output_eos_encountered_ = false; | 637 output_eos_encountered_ = false; |
614 drain_decoder_ = false; | 638 drain_decoder_ = false; |
615 ReleaseMediaCodecBridge(); | 639 ReleaseMediaCodecBridge(); |
616 // Increase the access unit index so that the new decoder will not handle | 640 // Increase the access unit index so that the new decoder will not handle |
617 // the config change again. | 641 // the config change again. |
618 access_unit_index_[current_demuxer_data_index_]++; | 642 access_unit_index_[current_demuxer_data_index_]++; |
619 CurrentDataConsumed(true); | |
620 } | 643 } |
621 | 644 |
622 bool MediaDecoderJob::CreateMediaCodecBridge() { | 645 MediaDecoderJob::MediaDecoderJobStatus |
| 646 MediaDecoderJob::CreateMediaCodecBridge() { |
623 DVLOG(1) << __FUNCTION__; | 647 DVLOG(1) << __FUNCTION__; |
624 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 648 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
625 DCHECK(decode_cb_.is_null()); | 649 DCHECK(decode_cb_.is_null()); |
626 | 650 |
627 if (!HasStream()) { | 651 if (!HasStream()) { |
628 ReleaseMediaCodecBridge(); | 652 ReleaseMediaCodecBridge(); |
629 return false; | 653 return STATUS_FAILURE; |
630 } | 654 } |
631 | 655 |
632 // Create |media_codec_bridge_| only if config changes. | 656 // Create |media_codec_bridge_| only if config changes. |
633 if (media_codec_bridge_ && !need_to_reconfig_decoder_job_) | 657 if (media_codec_bridge_ && !need_to_reconfig_decoder_job_) |
634 return true; | 658 return STATUS_SUCCESS; |
635 | 659 |
636 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); | 660 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); |
637 if (is_content_encrypted_ && media_crypto.is_null()) | 661 if (is_content_encrypted_ && media_crypto.is_null()) |
638 return false; | 662 return STATUS_FAILURE; |
639 | 663 |
640 ReleaseMediaCodecBridge(); | 664 ReleaseMediaCodecBridge(); |
641 DVLOG(1) << __FUNCTION__ << " : creating new media codec bridge"; | 665 DVLOG(1) << __FUNCTION__ << " : creating new media codec bridge"; |
642 | 666 |
643 return CreateMediaCodecBridgeInternal(); | 667 return CreateMediaCodecBridgeInternal(); |
644 } | 668 } |
645 | 669 |
646 bool MediaDecoderJob::IsCodecReconfigureNeeded( | 670 bool MediaDecoderJob::IsCodecReconfigureNeeded( |
647 const DemuxerConfigs& configs) const { | 671 const DemuxerConfigs& configs) const { |
648 if (!AreDemuxerConfigsChanged(configs)) | 672 if (!AreDemuxerConfigsChanged(configs)) |
649 return false; | 673 return false; |
650 return true; | 674 return true; |
651 } | 675 } |
652 | 676 |
653 void MediaDecoderJob::OnOutputFormatChanged() {} | 677 void MediaDecoderJob::OnOutputFormatChanged() {} |
654 | 678 |
655 bool MediaDecoderJob::UpdateOutputFormat() { | 679 bool MediaDecoderJob::UpdateOutputFormat() { |
656 return false; | 680 return false; |
657 } | 681 } |
658 | 682 |
659 void MediaDecoderJob::ReleaseMediaCodecBridge() { | 683 void MediaDecoderJob::ReleaseMediaCodecBridge() { |
660 if (!media_codec_bridge_) | 684 if (!media_codec_bridge_) |
661 return; | 685 return; |
662 | 686 |
663 media_codec_bridge_.reset(); | 687 media_codec_bridge_.reset(); |
664 input_buf_index_ = -1; | 688 input_buf_index_ = -1; |
665 } | 689 } |
666 | 690 |
667 } // namespace media | 691 } // namespace media |
OLD | NEW |