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

Side by Side Diff: media/base/android/media_decoder_job.cc

Issue 898843002: Use cached Key frames to avoid browser seek (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nits Created 5 years, 10 months 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/base/android/media_decoder_job.h ('k') | media/base/android/media_source_player.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/base/android/media_decoder_job.h ('k') | media/base/android/media_source_player.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698