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

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

Issue 1344133002: MediaCodecPlayer implementation - stage 7 (DRM) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-drm-prepare
Patch Set: Renamed a variable Created 5 years, 2 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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_codec_decoder.h" 5 #include "media/base/android/media_codec_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 19 matching lines...) Expand all
30 // Timeout for dequeuing an output buffer from MediaCodec in milliseconds. 30 // Timeout for dequeuing an output buffer from MediaCodec in milliseconds.
31 const int kOutputBufferTimeout = 20; 31 const int kOutputBufferTimeout = 20;
32 } 32 }
33 33
34 MediaCodecDecoder::MediaCodecDecoder( 34 MediaCodecDecoder::MediaCodecDecoder(
35 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, 35 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
36 const base::Closure& external_request_data_cb, 36 const base::Closure& external_request_data_cb,
37 const base::Closure& starvation_cb, 37 const base::Closure& starvation_cb,
38 const base::Closure& decoder_drained_cb, 38 const base::Closure& decoder_drained_cb,
39 const base::Closure& stop_done_cb, 39 const base::Closure& stop_done_cb,
40 const base::Closure& waiting_for_decryption_key_cb,
40 const base::Closure& error_cb, 41 const base::Closure& error_cb,
41 const char* decoder_thread_name) 42 const char* decoder_thread_name)
42 : media_task_runner_(media_task_runner), 43 : media_task_runner_(media_task_runner),
43 decoder_thread_(decoder_thread_name), 44 decoder_thread_(decoder_thread_name),
44 needs_reconfigure_(false), 45 needs_reconfigure_(false),
45 drain_decoder_(false), 46 drain_decoder_(false),
46 always_reconfigure_for_tests_(false), 47 always_reconfigure_for_tests_(false),
47 external_request_data_cb_(external_request_data_cb), 48 external_request_data_cb_(external_request_data_cb),
48 starvation_cb_(starvation_cb), 49 starvation_cb_(starvation_cb),
49 decoder_drained_cb_(decoder_drained_cb), 50 decoder_drained_cb_(decoder_drained_cb),
50 stop_done_cb_(stop_done_cb), 51 stop_done_cb_(stop_done_cb),
52 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb),
51 error_cb_(error_cb), 53 error_cb_(error_cb),
52 state_(kStopped), 54 state_(kStopped),
53 is_prepared_(false), 55 is_prepared_(false),
54 eos_enqueued_(false), 56 eos_enqueued_(false),
57 missing_key_reported_(false),
55 completed_(false), 58 completed_(false),
56 last_frame_posted_(false), 59 last_frame_posted_(false),
57 is_data_request_in_progress_(false), 60 is_data_request_in_progress_(false),
58 is_incoming_data_invalid_(false), 61 is_incoming_data_invalid_(false),
59 #ifndef NDEBUG 62 #ifndef NDEBUG
60 verify_next_frame_is_key_(false), 63 verify_next_frame_is_key_(false),
61 #endif 64 #endif
62 weak_factory_(this) { 65 weak_factory_(this) {
63 DCHECK(media_task_runner_->BelongsToCurrentThread()); 66 DCHECK(media_task_runner_->BelongsToCurrentThread());
64 67
(...skipping 19 matching lines...) Expand all
84 DVLOG(1) << class_name() << "::" << __FUNCTION__; 87 DVLOG(1) << class_name() << "::" << __FUNCTION__;
85 88
86 DCHECK_EQ(GetState(), kStopped); 89 DCHECK_EQ(GetState(), kStopped);
87 90
88 // Flush() is a part of the Seek request. Whenever we request a seek we need 91 // Flush() is a part of the Seek request. Whenever we request a seek we need
89 // to invalidate the current data request. 92 // to invalidate the current data request.
90 if (is_data_request_in_progress_) 93 if (is_data_request_in_progress_)
91 is_incoming_data_invalid_ = true; 94 is_incoming_data_invalid_ = true;
92 95
93 eos_enqueued_ = false; 96 eos_enqueued_ = false;
97 missing_key_reported_ = false;
94 completed_ = false; 98 completed_ = false;
95 drain_decoder_ = false; 99 drain_decoder_ = false;
96 au_queue_.Flush(); 100 au_queue_.Flush();
97 101
98 // |is_prepared_| is set on the decoder thread, it shouldn't be running now. 102 // |is_prepared_| is set on the decoder thread, it shouldn't be running now.
99 DCHECK(!decoder_thread_.IsRunning()); 103 DCHECK(!decoder_thread_.IsRunning());
100 is_prepared_ = false; 104 is_prepared_ = false;
101 105
102 #ifndef NDEBUG 106 #ifndef NDEBUG
103 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 107 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 (!is_prepared_ || preroll_timestamp_ != base::TimeDelta()); 176 (!is_prepared_ || preroll_timestamp_ != base::TimeDelta());
173 } 177 }
174 178
175 void MediaCodecDecoder::SetPrerollTimestamp(base::TimeDelta preroll_timestamp) { 179 void MediaCodecDecoder::SetPrerollTimestamp(base::TimeDelta preroll_timestamp) {
176 DCHECK(media_task_runner_->BelongsToCurrentThread()); 180 DCHECK(media_task_runner_->BelongsToCurrentThread());
177 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": " << preroll_timestamp; 181 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": " << preroll_timestamp;
178 182
179 preroll_timestamp_ = preroll_timestamp; 183 preroll_timestamp_ = preroll_timestamp;
180 } 184 }
181 185
182 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { 186 void MediaCodecDecoder::SetNeedsReconfigure() {
183 base::android::ScopedJavaLocalRef<jobject> media_crypto; 187 DCHECK(media_task_runner_->BelongsToCurrentThread());
184 188
185 // TODO(timav): implement DRM. 189 DVLOG(1) << class_name() << "::" << __FUNCTION__;
186 // drm_bridge_ is not implemented 190
187 // if (drm_bridge_) 191 needs_reconfigure_ = true;
188 // media_crypto = drm_bridge_->GetMediaCrypto();
189 return media_crypto;
190 } 192 }
191 193
192 void MediaCodecDecoder::Prefetch(const base::Closure& prefetch_done_cb) { 194 void MediaCodecDecoder::Prefetch(const base::Closure& prefetch_done_cb) {
193 DCHECK(media_task_runner_->BelongsToCurrentThread()); 195 DCHECK(media_task_runner_->BelongsToCurrentThread());
194 196
195 DVLOG(1) << class_name() << "::" << __FUNCTION__; 197 DVLOG(1) << class_name() << "::" << __FUNCTION__;
196 198
197 DCHECK(GetState() == kStopped); 199 DCHECK(GetState() == kStopped);
198 200
199 prefetch_done_cb_ = prefetch_done_cb; 201 prefetch_done_cb_ = prefetch_done_cb;
200 202
201 SetState(kPrefetching); 203 SetState(kPrefetching);
202 PrefetchNextChunk(); 204 PrefetchNextChunk();
203 } 205 }
204 206
205 MediaCodecDecoder::ConfigStatus MediaCodecDecoder::Configure() { 207 MediaCodecDecoder::ConfigStatus MediaCodecDecoder::Configure(
208 jobject media_crypto) {
206 DCHECK(media_task_runner_->BelongsToCurrentThread()); 209 DCHECK(media_task_runner_->BelongsToCurrentThread());
207 210
208 DVLOG(1) << class_name() << "::" << __FUNCTION__; 211 DVLOG(1) << class_name() << "::" << __FUNCTION__;
209 212
210 if (GetState() == kError) { 213 if (GetState() == kError) {
211 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; 214 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError";
212 return kConfigFailure; 215 return kConfigFailure;
213 } 216 }
214 217
215 if (needs_reconfigure_) { 218 if (needs_reconfigure_) {
(...skipping 10 matching lines...) Expand all
226 } 229 }
227 230
228 // Read all |kConfigChanged| units preceding the data one. 231 // Read all |kConfigChanged| units preceding the data one.
229 AccessUnitQueue::Info au_info = au_queue_.GetInfo(); 232 AccessUnitQueue::Info au_info = au_queue_.GetInfo();
230 while (au_info.configs) { 233 while (au_info.configs) {
231 SetDemuxerConfigs(*au_info.configs); 234 SetDemuxerConfigs(*au_info.configs);
232 au_queue_.Advance(); 235 au_queue_.Advance();
233 au_info = au_queue_.GetInfo(); 236 au_info = au_queue_.GetInfo();
234 } 237 }
235 238
236 MediaCodecDecoder::ConfigStatus result = ConfigureInternal(); 239 MediaCodecDecoder::ConfigStatus result = ConfigureInternal(media_crypto);
237 240
238 #ifndef NDEBUG 241 #ifndef NDEBUG
239 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 242 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
240 // This DCHECK ensures we won't need to lock this variable. 243 // This DCHECK ensures we won't need to lock this variable.
241 DCHECK(!decoder_thread_.IsRunning()); 244 DCHECK(!decoder_thread_.IsRunning());
242 245
243 // For video the first frame after reconfiguration must be key frame. 246 // For video the first frame after reconfiguration must be key frame.
244 if (result == kConfigOk) 247 if (result == kConfigOk)
245 verify_next_frame_is_key_ = true; 248 verify_next_frame_is_key_ = true;
246 #endif 249 #endif
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 DCHECK(media_task_runner_->BelongsToCurrentThread()); 397 DCHECK(media_task_runner_->BelongsToCurrentThread());
395 398
396 DVLOG(1) << class_name() << "::" << __FUNCTION__ 399 DVLOG(1) << class_name() << "::" << __FUNCTION__
397 << " eos_encountered:" << eos_encountered; 400 << " eos_encountered:" << eos_encountered;
398 401
399 decoder_thread_.Stop(); // synchronous 402 decoder_thread_.Stop(); // synchronous
400 403
401 SetState(kStopped); 404 SetState(kStopped);
402 completed_ = (eos_encountered && !drain_decoder_); 405 completed_ = (eos_encountered && !drain_decoder_);
403 406
407 missing_key_reported_ = false;
408
404 // If the stream is completed during preroll we need to report it since 409 // If the stream is completed during preroll we need to report it since
405 // another stream might be running and the player waits for two callbacks. 410 // another stream might be running and the player waits for two callbacks.
406 if (completed_ && !preroll_done_cb_.is_null()) { 411 if (completed_ && !preroll_done_cb_.is_null()) {
407 preroll_timestamp_ = base::TimeDelta(); 412 preroll_timestamp_ = base::TimeDelta();
408 media_task_runner_->PostTask(FROM_HERE, 413 media_task_runner_->PostTask(FROM_HERE,
409 base::ResetAndReturn(&preroll_done_cb_)); 414 base::ResetAndReturn(&preroll_done_cb_));
410 } 415 }
411 416
412 if (eos_encountered && drain_decoder_) { 417 if (eos_encountered && drain_decoder_) {
413 drain_decoder_ = false; 418 drain_decoder_ = false;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 DVLOG(1) << class_name() << "::" << __FUNCTION__; 496 DVLOG(1) << class_name() << "::" << __FUNCTION__;
492 497
493 // After this method returns, decoder thread will not be running. 498 // After this method returns, decoder thread will not be running.
494 499
495 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). 500 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
496 SetState(kInEmergencyStop); 501 SetState(kInEmergencyStop);
497 502
498 decoder_thread_.Stop(); // synchronous 503 decoder_thread_.Stop(); // synchronous
499 504
500 SetState(kStopped); 505 SetState(kStopped);
506
507 missing_key_reported_ = false;
501 } 508 }
502 509
503 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, 510 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered,
504 bool has_delayed_tasks) { 511 bool has_delayed_tasks) {
505 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 512 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
506 513
507 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; 514 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks;
508 515
509 if (last_frame_when_stopping || eos_encountered) { 516 if (last_frame_when_stopping || eos_encountered) {
510 media_task_runner_->PostTask( 517 media_task_runner_->PostTask(
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 614
608 // Returns false if we should stop decoding process. Right now 615 // Returns false if we should stop decoding process. Right now
609 // it happens if we got MediaCodec error or detected starvation. 616 // it happens if we got MediaCodec error or detected starvation.
610 bool MediaCodecDecoder::EnqueueInputBuffer() { 617 bool MediaCodecDecoder::EnqueueInputBuffer() {
611 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 618 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
612 619
613 DVLOG(2) << class_name() << "::" << __FUNCTION__; 620 DVLOG(2) << class_name() << "::" << __FUNCTION__;
614 621
615 if (eos_enqueued_) { 622 if (eos_enqueued_) {
616 DVLOG(1) << class_name() << "::" << __FUNCTION__ 623 DVLOG(1) << class_name() << "::" << __FUNCTION__
617 << ": eos_enqueued, returning"; 624 << ": EOS enqueued, returning";
618 return true; // Nothing to do 625 return true; // Nothing to do
619 } 626 }
620 627
628 if (missing_key_reported_) {
629 DVLOG(1) << class_name() << "::" << __FUNCTION__
630 << ": NO KEY reported, returning";
631 return true; // Nothing to do
632 }
633
621 // Keep the number pending video frames low, ideally maintaining 634 // Keep the number pending video frames low, ideally maintaining
622 // the same audio and video duration after stop request 635 // the same audio and video duration after stop request
623 if (NumDelayedRenderTasks() > 1) { 636 if (NumDelayedRenderTasks() > 1) {
624 DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers (" 637 DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers ("
625 << NumDelayedRenderTasks() << ") exceeds 1, returning"; 638 << NumDelayedRenderTasks() << ") exceeds 1, returning";
626 return true; // Nothing to do 639 return true; // Nothing to do
627 } 640 }
628 641
629 // Get the next frame from the queue. As we go, request more data and 642 // Get the next frame from the queue. As we go, request more data and
630 // consume |kConfigChanged| units. 643 // consume |kConfigChanged| units.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 const AccessUnit* unit = au_info.front_unit; 700 const AccessUnit* unit = au_info.front_unit;
688 701
689 if (drain_decoder_ || unit->is_end_of_stream) { 702 if (drain_decoder_ || unit->is_end_of_stream) {
690 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS"; 703 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS";
691 media_codec_bridge_->QueueEOS(index); 704 media_codec_bridge_->QueueEOS(index);
692 eos_enqueued_ = true; 705 eos_enqueued_ = true;
693 return true; 706 return true;
694 } 707 }
695 708
696 DCHECK(unit); 709 DCHECK(unit);
710 DCHECK(!unit->data.empty());
697 711
698 DVLOG(2) << class_name() << "::" << __FUNCTION__ 712 if (unit->key_id.empty() || unit->iv.empty()) {
699 << ": QueueInputBuffer pts:" << unit->timestamp; 713 DVLOG(2) << class_name() << "::" << __FUNCTION__
714 << ": QueueInputBuffer pts:" << unit->timestamp;
700 715
701 status = media_codec_bridge_->QueueInputBuffer( 716 status = media_codec_bridge_->QueueInputBuffer(
702 index, &unit->data[0], unit->data.size(), unit->timestamp); 717 index, &unit->data[0], unit->data.size(), unit->timestamp);
718 } else {
719 DVLOG(2) << class_name() << "::" << __FUNCTION__
720 << ": QueueSecureInputBuffer pts:" << unit->timestamp
721 << " key_id size:" << unit->key_id.size()
722 << " iv size:" << unit->iv.size()
723 << " subsamples size:" << unit->subsamples.size();
703 724
704 if (status == MEDIA_CODEC_ERROR) { 725 status = media_codec_bridge_->QueueSecureInputBuffer(
705 DVLOG(0) << class_name() << "::" << __FUNCTION__ 726 index, &unit->data[0], unit->data.size(),
706 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed"; 727 reinterpret_cast<const uint8_t*>(&unit->key_id[0]), unit->key_id.size(),
707 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 728 reinterpret_cast<const uint8_t*>(&unit->iv[0]), unit->iv.size(),
708 return false; 729 unit->subsamples.empty() ? nullptr : &unit->subsamples[0],
730 unit->subsamples.size(), unit->timestamp);
731 }
732
733 switch (status) {
734 case MEDIA_CODEC_OK:
735 break;
736
737 case MEDIA_CODEC_ERROR:
738 DVLOG(0) << class_name() << "::" << __FUNCTION__
739 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed";
740 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
741 return false;
742
743 case MEDIA_CODEC_NO_KEY:
744 DVLOG(1) << class_name() << "::" << __FUNCTION__
745 << ": MEDIA_CODEC_NO_KEY";
746 media_task_runner_->PostTask(FROM_HERE, waiting_for_decryption_key_cb_);
747
748 // In response to the |waiting_for_decryption_key_cb_| the player will
749 // request to stop decoder. We need to keep running to properly perform
750 // the stop, but prevent enqueuing the same frame over and over again so
751 // we won't generate more |waiting_for_decryption_key_cb_|.
752 missing_key_reported_ = true;
753 return true;
754
755 default:
756 NOTREACHED() << class_name() << "::" << __FUNCTION__
757 << ": unexpected error code " << status;
758 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
759 return false;
709 } 760 }
710 761
711 // Have successfully queued input buffer, go to next access unit. 762 // Have successfully queued input buffer, go to next access unit.
712 au_queue_.Advance(); 763 au_queue_.Advance();
713 return true; 764 return true;
714 } 765 }
715 766
716 AccessUnitQueue::Info MediaCodecDecoder::AdvanceAccessUnitQueue( 767 AccessUnitQueue::Info MediaCodecDecoder::AdvanceAccessUnitQueue(
717 bool* drain_decoder) { 768 bool* drain_decoder) {
718 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 769 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 RETURN_STRING(kStopping); 947 RETURN_STRING(kStopping);
897 RETURN_STRING(kInEmergencyStop); 948 RETURN_STRING(kInEmergencyStop);
898 RETURN_STRING(kError); 949 RETURN_STRING(kError);
899 } 950 }
900 return nullptr; // crash early 951 return nullptr; // crash early
901 } 952 }
902 953
903 #undef RETURN_STRING 954 #undef RETURN_STRING
904 955
905 } // namespace media 956 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/media_codec_decoder.h ('k') | media/base/android/media_codec_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698