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

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: Use MediaCrypto received with callback, never get it directly from MediaDrmBridge Created 5 years, 3 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"
11 #include "media/base/android/media_codec_bridge.h" 11 #include "media/base/android/media_codec_bridge.h"
12 #include "media/base/android/media_drm_bridge.h"
12 13
13 namespace media { 14 namespace media {
14 15
15 namespace { 16 namespace {
16 17
17 // Stop requesting new data in the kPrefetching state when the queue size 18 // Stop requesting new data in the kPrefetching state when the queue size
18 // reaches this limit. 19 // reaches this limit.
19 const int kPrefetchLimit = 8; 20 const int kPrefetchLimit = 8;
20 21
21 // Request new data in the kRunning state if the queue size is less than this. 22 // Request new data in the kRunning state if the queue size is less than this.
22 const int kPlaybackLowLimit = 4; 23 const int kPlaybackLowLimit = 4;
23 24
24 // Posting delay of the next frame processing, in milliseconds 25 // Posting delay of the next frame processing, in milliseconds
25 const int kNextFrameDelay = 1; 26 const int kNextFrameDelay = 1;
26 27
27 // Timeout for dequeuing an input buffer from MediaCodec in milliseconds. 28 // Timeout for dequeuing an input buffer from MediaCodec in milliseconds.
28 const int kInputBufferTimeout = 20; 29 const int kInputBufferTimeout = 20;
29 30
30 // Timeout for dequeuing an output buffer from MediaCodec in milliseconds. 31 // Timeout for dequeuing an output buffer from MediaCodec in milliseconds.
31 const int kOutputBufferTimeout = 20; 32 const int kOutputBufferTimeout = 20;
32 } 33 }
33 34
34 MediaCodecDecoder::MediaCodecDecoder( 35 MediaCodecDecoder::MediaCodecDecoder(
35 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, 36 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
36 const base::Closure& external_request_data_cb, 37 const base::Closure& external_request_data_cb,
37 const base::Closure& starvation_cb, 38 const base::Closure& starvation_cb,
38 const base::Closure& decoder_drained_cb, 39 const base::Closure& decoder_drained_cb,
39 const base::Closure& stop_done_cb, 40 const base::Closure& stop_done_cb,
41 const base::Closure& key_required_cb,
40 const base::Closure& error_cb, 42 const base::Closure& error_cb,
41 const char* decoder_thread_name) 43 const char* decoder_thread_name)
42 : media_task_runner_(media_task_runner), 44 : media_task_runner_(media_task_runner),
43 decoder_thread_(decoder_thread_name), 45 decoder_thread_(decoder_thread_name),
46 drm_bridge_(nullptr),
44 needs_reconfigure_(false), 47 needs_reconfigure_(false),
45 drain_decoder_(false), 48 drain_decoder_(false),
46 always_reconfigure_for_tests_(false), 49 always_reconfigure_for_tests_(false),
47 external_request_data_cb_(external_request_data_cb), 50 external_request_data_cb_(external_request_data_cb),
48 starvation_cb_(starvation_cb), 51 starvation_cb_(starvation_cb),
49 decoder_drained_cb_(decoder_drained_cb), 52 decoder_drained_cb_(decoder_drained_cb),
50 stop_done_cb_(stop_done_cb), 53 stop_done_cb_(stop_done_cb),
54 key_required_cb_(key_required_cb),
51 error_cb_(error_cb), 55 error_cb_(error_cb),
52 state_(kStopped), 56 state_(kStopped),
53 is_prepared_(false), 57 is_prepared_(false),
54 eos_enqueued_(false), 58 eos_enqueued_(false),
59 key_request_posted_(false),
55 completed_(false), 60 completed_(false),
56 last_frame_posted_(false), 61 last_frame_posted_(false),
57 is_data_request_in_progress_(false), 62 is_data_request_in_progress_(false),
58 is_incoming_data_invalid_(false), 63 is_incoming_data_invalid_(false),
59 #ifndef NDEBUG 64 #ifndef NDEBUG
60 verify_next_frame_is_key_(false), 65 verify_next_frame_is_key_(false),
61 #endif 66 #endif
62 weak_factory_(this) { 67 weak_factory_(this) {
63 DCHECK(media_task_runner_->BelongsToCurrentThread()); 68 DCHECK(media_task_runner_->BelongsToCurrentThread());
64 69
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 (!is_prepared_ || preroll_timestamp_ != base::TimeDelta()); 177 (!is_prepared_ || preroll_timestamp_ != base::TimeDelta());
173 } 178 }
174 179
175 void MediaCodecDecoder::SetPrerollTimestamp(base::TimeDelta preroll_timestamp) { 180 void MediaCodecDecoder::SetPrerollTimestamp(base::TimeDelta preroll_timestamp) {
176 DCHECK(media_task_runner_->BelongsToCurrentThread()); 181 DCHECK(media_task_runner_->BelongsToCurrentThread());
177 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": " << preroll_timestamp; 182 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": " << preroll_timestamp;
178 183
179 preroll_timestamp_ = preroll_timestamp; 184 preroll_timestamp_ = preroll_timestamp;
180 } 185 }
181 186
182 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { 187 void MediaCodecDecoder::SetDrmBridge(MediaDrmBridge* drm_bridge) {
183 base::android::ScopedJavaLocalRef<jobject> media_crypto; 188 DCHECK(media_task_runner_->BelongsToCurrentThread());
184 189
185 // TODO(timav): implement DRM. 190 DVLOG(1) << class_name() << "::" << __FUNCTION__;
186 // drm_bridge_ is not implemented 191
187 // if (drm_bridge_) 192 drm_bridge_ = drm_bridge;
188 // media_crypto = drm_bridge_->GetMediaCrypto(); 193
189 return media_crypto; 194 needs_reconfigure_ = true;
190 } 195 }
191 196
192 void MediaCodecDecoder::Prefetch(const base::Closure& prefetch_done_cb) { 197 void MediaCodecDecoder::Prefetch(const base::Closure& prefetch_done_cb) {
193 DCHECK(media_task_runner_->BelongsToCurrentThread()); 198 DCHECK(media_task_runner_->BelongsToCurrentThread());
194 199
195 DVLOG(1) << class_name() << "::" << __FUNCTION__; 200 DVLOG(1) << class_name() << "::" << __FUNCTION__;
196 201
197 DCHECK(GetState() == kStopped); 202 DCHECK(GetState() == kStopped);
198 203
199 prefetch_done_cb_ = prefetch_done_cb; 204 prefetch_done_cb_ = prefetch_done_cb;
200 205
201 SetState(kPrefetching); 206 SetState(kPrefetching);
202 PrefetchNextChunk(); 207 PrefetchNextChunk();
203 } 208 }
204 209
205 MediaCodecDecoder::ConfigStatus MediaCodecDecoder::Configure() { 210 MediaCodecDecoder::ConfigStatus MediaCodecDecoder::Configure(
211 jobject media_crypto) {
206 DCHECK(media_task_runner_->BelongsToCurrentThread()); 212 DCHECK(media_task_runner_->BelongsToCurrentThread());
207 213
208 DVLOG(1) << class_name() << "::" << __FUNCTION__; 214 DVLOG(1) << class_name() << "::" << __FUNCTION__;
209 215
210 if (GetState() == kError) { 216 if (GetState() == kError) {
211 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError"; 217 DVLOG(0) << class_name() << "::" << __FUNCTION__ << ": wrong state kError";
212 return kConfigFailure; 218 return kConfigFailure;
213 } 219 }
214 220
215 if (needs_reconfigure_) { 221 if (needs_reconfigure_) {
(...skipping 10 matching lines...) Expand all
226 } 232 }
227 233
228 // Read all |kConfigChanged| units preceding the data one. 234 // Read all |kConfigChanged| units preceding the data one.
229 AccessUnitQueue::Info au_info = au_queue_.GetInfo(); 235 AccessUnitQueue::Info au_info = au_queue_.GetInfo();
230 while (au_info.configs) { 236 while (au_info.configs) {
231 SetDemuxerConfigs(*au_info.configs); 237 SetDemuxerConfigs(*au_info.configs);
232 au_queue_.Advance(); 238 au_queue_.Advance();
233 au_info = au_queue_.GetInfo(); 239 au_info = au_queue_.GetInfo();
234 } 240 }
235 241
236 MediaCodecDecoder::ConfigStatus result = ConfigureInternal(); 242 MediaCodecDecoder::ConfigStatus result = ConfigureInternal(media_crypto);
237 243
238 #ifndef NDEBUG 244 #ifndef NDEBUG
239 // We check and reset |verify_next_frame_is_key_| on Decoder thread. 245 // We check and reset |verify_next_frame_is_key_| on Decoder thread.
240 // This DCHECK ensures we won't need to lock this variable. 246 // This DCHECK ensures we won't need to lock this variable.
241 DCHECK(!decoder_thread_.IsRunning()); 247 DCHECK(!decoder_thread_.IsRunning());
242 248
243 // For video the first frame after reconfiguration must be key frame. 249 // For video the first frame after reconfiguration must be key frame.
244 if (result == kConfigOk) 250 if (result == kConfigOk)
245 verify_next_frame_is_key_ = true; 251 verify_next_frame_is_key_ = true;
246 #endif 252 #endif
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 DCHECK(media_task_runner_->BelongsToCurrentThread()); 400 DCHECK(media_task_runner_->BelongsToCurrentThread());
395 401
396 DVLOG(1) << class_name() << "::" << __FUNCTION__ 402 DVLOG(1) << class_name() << "::" << __FUNCTION__
397 << " eos_encountered:" << eos_encountered; 403 << " eos_encountered:" << eos_encountered;
398 404
399 decoder_thread_.Stop(); // synchronous 405 decoder_thread_.Stop(); // synchronous
400 406
401 SetState(kStopped); 407 SetState(kStopped);
402 completed_ = (eos_encountered && !drain_decoder_); 408 completed_ = (eos_encountered && !drain_decoder_);
403 409
410 key_request_posted_ = false;
411
404 // If the stream is completed during preroll we need to report it since 412 // 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. 413 // another stream might be running and the player waits for two callbacks.
406 if (completed_ && !preroll_done_cb_.is_null()) { 414 if (completed_ && !preroll_done_cb_.is_null()) {
407 preroll_timestamp_ = base::TimeDelta(); 415 preroll_timestamp_ = base::TimeDelta();
408 media_task_runner_->PostTask(FROM_HERE, 416 media_task_runner_->PostTask(FROM_HERE,
409 base::ResetAndReturn(&preroll_done_cb_)); 417 base::ResetAndReturn(&preroll_done_cb_));
410 } 418 }
411 419
412 if (eos_encountered && drain_decoder_) { 420 if (eos_encountered && drain_decoder_) {
413 drain_decoder_ = false; 421 drain_decoder_ = false;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 DVLOG(1) << class_name() << "::" << __FUNCTION__; 499 DVLOG(1) << class_name() << "::" << __FUNCTION__;
492 500
493 // After this method returns, decoder thread will not be running. 501 // After this method returns, decoder thread will not be running.
494 502
495 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). 503 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
496 SetState(kInEmergencyStop); 504 SetState(kInEmergencyStop);
497 505
498 decoder_thread_.Stop(); // synchronous 506 decoder_thread_.Stop(); // synchronous
499 507
500 SetState(kStopped); 508 SetState(kStopped);
509
510 key_request_posted_ = false;
501 } 511 }
502 512
503 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, 513 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered,
504 bool has_delayed_tasks) { 514 bool has_delayed_tasks) {
505 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 515 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
506 516
507 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; 517 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks;
508 518
509 if (last_frame_when_stopping || eos_encountered) { 519 if (last_frame_when_stopping || eos_encountered) {
510 media_task_runner_->PostTask( 520 media_task_runner_->PostTask(
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 621 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
612 622
613 DVLOG(2) << class_name() << "::" << __FUNCTION__; 623 DVLOG(2) << class_name() << "::" << __FUNCTION__;
614 624
615 if (eos_enqueued_) { 625 if (eos_enqueued_) {
616 DVLOG(1) << class_name() << "::" << __FUNCTION__ 626 DVLOG(1) << class_name() << "::" << __FUNCTION__
617 << ": eos_enqueued, returning"; 627 << ": eos_enqueued, returning";
618 return true; // Nothing to do 628 return true; // Nothing to do
619 } 629 }
620 630
631 if (key_request_posted_) {
632 DVLOG(1) << class_name() << "::" << __FUNCTION__
633 << ": key_request_posted, returning";
634 return true; // Nothing to do
635 }
636
621 // Keep the number pending video frames low, ideally maintaining 637 // Keep the number pending video frames low, ideally maintaining
622 // the same audio and video duration after stop request 638 // the same audio and video duration after stop request
623 if (NumDelayedRenderTasks() > 1) { 639 if (NumDelayedRenderTasks() > 1) {
624 DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers (" 640 DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers ("
625 << NumDelayedRenderTasks() << ") exceeds 1, returning"; 641 << NumDelayedRenderTasks() << ") exceeds 1, returning";
626 return true; // Nothing to do 642 return true; // Nothing to do
627 } 643 }
628 644
629 // Get the next frame from the queue. As we go, request more data and 645 // Get the next frame from the queue. As we go, request more data and
630 // consume |kConfigChanged| units. 646 // consume |kConfigChanged| units.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 704
689 if (drain_decoder_ || unit->is_end_of_stream) { 705 if (drain_decoder_ || unit->is_end_of_stream) {
690 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS"; 706 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS";
691 media_codec_bridge_->QueueEOS(index); 707 media_codec_bridge_->QueueEOS(index);
692 eos_enqueued_ = true; 708 eos_enqueued_ = true;
693 return true; 709 return true;
694 } 710 }
695 711
696 DCHECK(unit); 712 DCHECK(unit);
697 713
698 DVLOG(2) << class_name() << "::" << __FUNCTION__ 714 if (unit->key_id.empty() || unit->iv.empty()) {
699 << ": QueueInputBuffer pts:" << unit->timestamp; 715 DVLOG(2) << class_name() << "::" << __FUNCTION__
716 << ": QueueInputBuffer pts:" << unit->timestamp;
700 717
701 status = media_codec_bridge_->QueueInputBuffer( 718 status = media_codec_bridge_->QueueInputBuffer(
702 index, &unit->data[0], unit->data.size(), unit->timestamp); 719 index, &unit->data[0], unit->data.size(), unit->timestamp);
720 } else {
721 DVLOG(2) << class_name() << "::" << __FUNCTION__
722 << ": QueueSecureInputBuffer pts:" << unit->timestamp
723 << " key_id size:" << unit->key_id.size()
724 << " iv size:" << unit->iv.size()
725 << " subsamples size:" << unit->subsamples.size();
703 726
704 if (status == MEDIA_CODEC_ERROR) { 727 status = media_codec_bridge_->QueueSecureInputBuffer(
705 DVLOG(0) << class_name() << "::" << __FUNCTION__ 728 index, &unit->data[0], unit->data.size(),
706 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed"; 729 reinterpret_cast<const uint8_t*>(&unit->key_id[0]), unit->key_id.size(),
707 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 730 reinterpret_cast<const uint8_t*>(&unit->iv[0]), unit->iv.size(),
708 return false; 731 unit->subsamples.empty() ? nullptr : &unit->subsamples[0],
732 unit->subsamples.size(), unit->timestamp);
733 }
734
735 switch (status) {
736 case MEDIA_CODEC_OK:
737 break;
738
739 case MEDIA_CODEC_ERROR:
740 DVLOG(0) << class_name() << "::" << __FUNCTION__
741 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed";
742 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
743 return false;
744
745 case MEDIA_CODEC_NO_KEY:
746 DVLOG(1) << class_name() << "::" << __FUNCTION__
747 << ": MEDIA_CODEC_NO_KEY";
748 media_task_runner_->PostTask(FROM_HERE, key_required_cb_);
749
750 // In response to the |key_required_cb_| the player will request to stop
751 // decoder. We need to keep running to properly perform the stop, but
752 // prevent enqueuing the same frame over and over again so we won't
753 // generate more |key_required_cb_|.
754 key_request_posted_ = true;
755 return true;
756
757 default:
758 NOTREACHED() << class_name() << "::" << __FUNCTION__
759 << ": unexpected error code " << status;
760 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
761 return false;
709 } 762 }
710 763
711 // Have successfully queued input buffer, go to next access unit. 764 // Have successfully queued input buffer, go to next access unit.
712 au_queue_.Advance(); 765 au_queue_.Advance();
713 return true; 766 return true;
714 } 767 }
715 768
716 AccessUnitQueue::Info MediaCodecDecoder::AdvanceAccessUnitQueue( 769 AccessUnitQueue::Info MediaCodecDecoder::AdvanceAccessUnitQueue(
717 bool* drain_decoder) { 770 bool* drain_decoder) {
718 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 771 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 RETURN_STRING(kStopping); 949 RETURN_STRING(kStopping);
897 RETURN_STRING(kInEmergencyStop); 950 RETURN_STRING(kInEmergencyStop);
898 RETURN_STRING(kError); 951 RETURN_STRING(kError);
899 } 952 }
900 return nullptr; // crash early 953 return nullptr; // crash early
901 } 954 }
902 955
903 #undef RETURN_STRING 956 #undef RETURN_STRING
904 957
905 } // namespace media 958 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698