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

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

Issue 1341883003: Prepare MediaDrmBridge to work with MediaCodecPlayer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bug526755
Patch Set: 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
187 void MediaCodecDecoder::SetDrmBridge(MediaDrmBridge* drm_bridge) {
188 DCHECK(media_task_runner_->BelongsToCurrentThread());
189
190 DVLOG(1) << class_name() << "::" << __FUNCTION__;
191
192 drm_bridge_ = drm_bridge;
193
194 needs_reconfigure_ = true;
195 }
196
182 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() { 197 base::android::ScopedJavaLocalRef<jobject> MediaCodecDecoder::GetMediaCrypto() {
183 base::android::ScopedJavaLocalRef<jobject> media_crypto; 198 base::android::ScopedJavaLocalRef<jobject> media_crypto;
184 199 if (drm_bridge_)
185 // TODO(timav): implement DRM. 200 media_crypto = drm_bridge_->GetMediaCrypto();
186 // drm_bridge_ is not implemented
187 // if (drm_bridge_)
188 // media_crypto = drm_bridge_->GetMediaCrypto();
189 return media_crypto; 201 return media_crypto;
190 } 202 }
191 203
192 void MediaCodecDecoder::Prefetch(const base::Closure& prefetch_done_cb) { 204 void MediaCodecDecoder::Prefetch(const base::Closure& prefetch_done_cb) {
193 DCHECK(media_task_runner_->BelongsToCurrentThread()); 205 DCHECK(media_task_runner_->BelongsToCurrentThread());
194 206
195 DVLOG(1) << class_name() << "::" << __FUNCTION__; 207 DVLOG(1) << class_name() << "::" << __FUNCTION__;
196 208
197 DCHECK(GetState() == kStopped); 209 DCHECK(GetState() == kStopped);
198 210
(...skipping 19 matching lines...) Expand all
218 needs_reconfigure_ = false; 230 needs_reconfigure_ = false;
219 ReleaseMediaCodec(); 231 ReleaseMediaCodec();
220 } 232 }
221 233
222 if (media_codec_bridge_) { 234 if (media_codec_bridge_) {
223 DVLOG(1) << class_name() << "::" << __FUNCTION__ 235 DVLOG(1) << class_name() << "::" << __FUNCTION__
224 << ": reconfiguration is not required, ignoring"; 236 << ": reconfiguration is not required, ignoring";
225 return kConfigOk; 237 return kConfigOk;
226 } 238 }
227 239
240 if (IsContentEncrypted() && GetMediaCrypto().is_null()) {
241 DVLOG(1) << class_name() << "::" << __FUNCTION__
242 << ": MediaCrypto is missing";
243 return kConfigNoCrypto;
244 }
245
228 // Read all |kConfigChanged| units preceding the data one. 246 // Read all |kConfigChanged| units preceding the data one.
229 AccessUnitQueue::Info au_info = au_queue_.GetInfo(); 247 AccessUnitQueue::Info au_info = au_queue_.GetInfo();
230 while (au_info.configs) { 248 while (au_info.configs) {
231 SetDemuxerConfigs(*au_info.configs); 249 SetDemuxerConfigs(*au_info.configs);
232 au_queue_.Advance(); 250 au_queue_.Advance();
233 au_info = au_queue_.GetInfo(); 251 au_info = au_queue_.GetInfo();
234 } 252 }
235 253
236 MediaCodecDecoder::ConfigStatus result = ConfigureInternal(); 254 MediaCodecDecoder::ConfigStatus result = ConfigureInternal();
237 255
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 DCHECK(media_task_runner_->BelongsToCurrentThread()); 412 DCHECK(media_task_runner_->BelongsToCurrentThread());
395 413
396 DVLOG(1) << class_name() << "::" << __FUNCTION__ 414 DVLOG(1) << class_name() << "::" << __FUNCTION__
397 << " eos_encountered:" << eos_encountered; 415 << " eos_encountered:" << eos_encountered;
398 416
399 decoder_thread_.Stop(); // synchronous 417 decoder_thread_.Stop(); // synchronous
400 418
401 SetState(kStopped); 419 SetState(kStopped);
402 completed_ = (eos_encountered && !drain_decoder_); 420 completed_ = (eos_encountered && !drain_decoder_);
403 421
422 key_request_posted_ = false;
423
404 // If the stream is completed during preroll we need to report it since 424 // 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. 425 // another stream might be running and the player waits for two callbacks.
406 if (completed_ && !preroll_done_cb_.is_null()) { 426 if (completed_ && !preroll_done_cb_.is_null()) {
407 preroll_timestamp_ = base::TimeDelta(); 427 preroll_timestamp_ = base::TimeDelta();
408 media_task_runner_->PostTask(FROM_HERE, 428 media_task_runner_->PostTask(FROM_HERE,
409 base::ResetAndReturn(&preroll_done_cb_)); 429 base::ResetAndReturn(&preroll_done_cb_));
410 } 430 }
411 431
412 if (eos_encountered && drain_decoder_) { 432 if (eos_encountered && drain_decoder_) {
413 drain_decoder_ = false; 433 drain_decoder_ = false;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 DVLOG(1) << class_name() << "::" << __FUNCTION__; 511 DVLOG(1) << class_name() << "::" << __FUNCTION__;
492 512
493 // After this method returns, decoder thread will not be running. 513 // After this method returns, decoder thread will not be running.
494 514
495 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame(). 515 // Set [kInEmergencyStop| state to block already posted ProcessNextFrame().
496 SetState(kInEmergencyStop); 516 SetState(kInEmergencyStop);
497 517
498 decoder_thread_.Stop(); // synchronous 518 decoder_thread_.Stop(); // synchronous
499 519
500 SetState(kStopped); 520 SetState(kStopped);
521
522 key_request_posted_ = false;
501 } 523 }
502 524
503 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered, 525 void MediaCodecDecoder::CheckLastFrame(bool eos_encountered,
504 bool has_delayed_tasks) { 526 bool has_delayed_tasks) {
505 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 527 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
506 528
507 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks; 529 bool last_frame_when_stopping = GetState() == kStopping && !has_delayed_tasks;
508 530
509 if (last_frame_when_stopping || eos_encountered) { 531 if (last_frame_when_stopping || eos_encountered) {
510 media_task_runner_->PostTask( 532 media_task_runner_->PostTask(
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 633 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
612 634
613 DVLOG(2) << class_name() << "::" << __FUNCTION__; 635 DVLOG(2) << class_name() << "::" << __FUNCTION__;
614 636
615 if (eos_enqueued_) { 637 if (eos_enqueued_) {
616 DVLOG(1) << class_name() << "::" << __FUNCTION__ 638 DVLOG(1) << class_name() << "::" << __FUNCTION__
617 << ": eos_enqueued, returning"; 639 << ": eos_enqueued, returning";
618 return true; // Nothing to do 640 return true; // Nothing to do
619 } 641 }
620 642
643 if (key_request_posted_) {
644 DVLOG(1) << class_name() << "::" << __FUNCTION__
645 << ": key_request_posted, returning";
646 return true; // Nothing to do
647 }
648
621 // Keep the number pending video frames low, ideally maintaining 649 // Keep the number pending video frames low, ideally maintaining
622 // the same audio and video duration after stop request 650 // the same audio and video duration after stop request
623 if (NumDelayedRenderTasks() > 1) { 651 if (NumDelayedRenderTasks() > 1) {
624 DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers (" 652 DVLOG(2) << class_name() << "::" << __FUNCTION__ << ": # delayed buffers ("
625 << NumDelayedRenderTasks() << ") exceeds 1, returning"; 653 << NumDelayedRenderTasks() << ") exceeds 1, returning";
626 return true; // Nothing to do 654 return true; // Nothing to do
627 } 655 }
628 656
629 // Get the next frame from the queue. As we go, request more data and 657 // Get the next frame from the queue. As we go, request more data and
630 // consume |kConfigChanged| units. 658 // consume |kConfigChanged| units.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 716
689 if (drain_decoder_ || unit->is_end_of_stream) { 717 if (drain_decoder_ || unit->is_end_of_stream) {
690 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS"; 718 DVLOG(1) << class_name() << "::" << __FUNCTION__ << ": QueueEOS";
691 media_codec_bridge_->QueueEOS(index); 719 media_codec_bridge_->QueueEOS(index);
692 eos_enqueued_ = true; 720 eos_enqueued_ = true;
693 return true; 721 return true;
694 } 722 }
695 723
696 DCHECK(unit); 724 DCHECK(unit);
697 725
698 DVLOG(2) << class_name() << "::" << __FUNCTION__ 726 if (unit->key_id.empty() || unit->iv.empty()) {
699 << ": QueueInputBuffer pts:" << unit->timestamp; 727 DVLOG(2) << class_name() << "::" << __FUNCTION__
728 << ": QueueInputBuffer pts:" << unit->timestamp;
700 729
701 status = media_codec_bridge_->QueueInputBuffer( 730 status = media_codec_bridge_->QueueInputBuffer(
702 index, &unit->data[0], unit->data.size(), unit->timestamp); 731 index, &unit->data[0], unit->data.size(), unit->timestamp);
732 } else {
733 DVLOG(2) << class_name() << "::" << __FUNCTION__
734 << ": QueueSecureInputBuffer pts:" << unit->timestamp
735 << " key_id size:" << unit->key_id.size()
736 << " iv size:" << unit->iv.size()
737 << " subsamples size:" << unit->subsamples.size();
703 738
704 if (status == MEDIA_CODEC_ERROR) { 739 status = media_codec_bridge_->QueueSecureInputBuffer(
705 DVLOG(0) << class_name() << "::" << __FUNCTION__ 740 index, &unit->data[0], unit->data.size(),
706 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed"; 741 reinterpret_cast<const uint8_t*>(&unit->key_id[0]), unit->key_id.size(),
707 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_); 742 reinterpret_cast<const uint8_t*>(&unit->iv[0]), unit->iv.size(),
708 return false; 743 unit->subsamples.empty() ? nullptr : &unit->subsamples[0],
744 unit->subsamples.size(), unit->timestamp);
745 }
746
747 switch (status) {
748 case MEDIA_CODEC_OK:
749 break;
750
751 case MEDIA_CODEC_ERROR:
752 DVLOG(0) << class_name() << "::" << __FUNCTION__
753 << ": MEDIA_CODEC_ERROR: QueueInputBuffer failed";
754 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
755 return false;
756
757 case MEDIA_CODEC_NO_KEY:
758 DVLOG(1) << class_name() << "::" << __FUNCTION__
759 << ": MEDIA_CODEC_NO_KEY";
760 media_task_runner_->PostTask(FROM_HERE, key_required_cb_);
761
762 // In response to the |key_required_cb_| the player will request to stop
763 // decoder. We need to keep running to properly perform the stop, but
764 // prevent enqueuing the same frame over and over again so we won't
765 // generate more |key_required_cb_|.
766 key_request_posted_ = true;
767 return true;
768
769 default:
770 NOTREACHED() << class_name() << "::" << __FUNCTION__
771 << ": unexpected error code " << status;
772 media_task_runner_->PostTask(FROM_HERE, internal_error_cb_);
773 return false;
709 } 774 }
710 775
711 // Have successfully queued input buffer, go to next access unit. 776 // Have successfully queued input buffer, go to next access unit.
712 au_queue_.Advance(); 777 au_queue_.Advance();
713 return true; 778 return true;
714 } 779 }
715 780
716 AccessUnitQueue::Info MediaCodecDecoder::AdvanceAccessUnitQueue( 781 AccessUnitQueue::Info MediaCodecDecoder::AdvanceAccessUnitQueue(
717 bool* drain_decoder) { 782 bool* drain_decoder) {
718 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); 783 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread());
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 RETURN_STRING(kStopping); 961 RETURN_STRING(kStopping);
897 RETURN_STRING(kInEmergencyStop); 962 RETURN_STRING(kInEmergencyStop);
898 RETURN_STRING(kError); 963 RETURN_STRING(kError);
899 } 964 }
900 return nullptr; // crash early 965 return nullptr; // crash early
901 } 966 }
902 967
903 #undef RETURN_STRING 968 #undef RETURN_STRING
904 969
905 } // namespace media 970 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698