OLD | NEW |
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_player.h" | 5 #include "media/base/android/media_codec_player.h" |
6 | 6 |
7 #include "base/barrier_closure.h" | 7 #include "base/barrier_closure.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/thread_task_runner_handle.h" | 11 #include "base/thread_task_runner_handle.h" |
12 #include "base/threading/thread.h" | 12 #include "base/threading/thread.h" |
13 #include "media/base/android/media_codec_audio_decoder.h" | 13 #include "media/base/android/media_codec_audio_decoder.h" |
14 #include "media/base/android/media_codec_video_decoder.h" | 14 #include "media/base/android/media_codec_video_decoder.h" |
| 15 #include "media/base/android/media_drm_bridge.h" |
15 #include "media/base/android/media_player_manager.h" | 16 #include "media/base/android/media_player_manager.h" |
16 #include "media/base/timestamp_constants.h" | 17 #include "media/base/timestamp_constants.h" |
17 | 18 |
18 #define RUN_ON_MEDIA_THREAD(METHOD, ...) \ | 19 #define RUN_ON_MEDIA_THREAD(METHOD, ...) \ |
19 do { \ | 20 do { \ |
20 if (!GetMediaTaskRunner()->BelongsToCurrentThread()) { \ | 21 if (!GetMediaTaskRunner()->BelongsToCurrentThread()) { \ |
21 DCHECK(ui_task_runner_->BelongsToCurrentThread()); \ | 22 DCHECK(ui_task_runner_->BelongsToCurrentThread()); \ |
22 GetMediaTaskRunner()->PostTask( \ | 23 GetMediaTaskRunner()->PostTask( \ |
23 FROM_HERE, base::Bind(&MediaCodecPlayer::METHOD, media_weak_this_, \ | 24 FROM_HERE, base::Bind(&MediaCodecPlayer::METHOD, media_weak_this_, \ |
24 ##__VA_ARGS__)); \ | 25 ##__VA_ARGS__)); \ |
(...skipping 30 matching lines...) Expand all Loading... |
55 : MediaPlayerAndroid(player_id, | 56 : MediaPlayerAndroid(player_id, |
56 manager.get(), | 57 manager.get(), |
57 request_media_resources_cb, | 58 request_media_resources_cb, |
58 frame_url), | 59 frame_url), |
59 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 60 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
60 demuxer_(demuxer.Pass()), | 61 demuxer_(demuxer.Pass()), |
61 state_(kStatePaused), | 62 state_(kStatePaused), |
62 interpolator_(&default_tick_clock_), | 63 interpolator_(&default_tick_clock_), |
63 pending_start_(false), | 64 pending_start_(false), |
64 pending_seek_(kNoTimestamp()), | 65 pending_seek_(kNoTimestamp()), |
| 66 drm_bridge_(nullptr), |
| 67 cdm_registration_id_(0), |
| 68 is_protected_surface_required_(false), |
| 69 key_is_required_(false), |
| 70 key_is_added_(false), |
65 media_weak_factory_(this) { | 71 media_weak_factory_(this) { |
66 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 72 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
67 | 73 |
68 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; | 74 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; |
69 | 75 |
70 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); | 76 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); |
71 | 77 |
72 completion_cb_ = | 78 completion_cb_ = |
73 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); | 79 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); |
| 80 key_required_cb_ = base::Bind(&MediaPlayerManager::OnWaitingForDecryptionKey, |
| 81 manager, player_id); |
74 seek_done_cb_ = | 82 seek_done_cb_ = |
75 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); | 83 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); |
76 error_cb_ = base::Bind(&MediaPlayerManager::OnError, manager, player_id); | 84 error_cb_ = base::Bind(&MediaPlayerManager::OnError, manager, player_id); |
77 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, | 85 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, |
78 WeakPtrForUIThread(), nullptr); | 86 WeakPtrForUIThread(), nullptr); |
79 detach_listener_cb_ = | 87 detach_listener_cb_ = |
80 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); | 88 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); |
81 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, | 89 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, |
82 WeakPtrForUIThread()); | 90 WeakPtrForUIThread()); |
83 time_update_cb_ = | 91 time_update_cb_ = |
(...skipping 13 matching lines...) Expand all Loading... |
97 | 105 |
98 // Currently the unit tests wait for the MediaCodecPlayer destruction by | 106 // Currently the unit tests wait for the MediaCodecPlayer destruction by |
99 // watching the demuxer, which is destroyed as one of the member variables. | 107 // watching the demuxer, which is destroyed as one of the member variables. |
100 // Release the codecs here, before any member variable is destroyed to make | 108 // Release the codecs here, before any member variable is destroyed to make |
101 // the unit tests happy. | 109 // the unit tests happy. |
102 | 110 |
103 if (video_decoder_) | 111 if (video_decoder_) |
104 video_decoder_->ReleaseDecoderResources(); | 112 video_decoder_->ReleaseDecoderResources(); |
105 if (audio_decoder_) | 113 if (audio_decoder_) |
106 audio_decoder_->ReleaseDecoderResources(); | 114 audio_decoder_->ReleaseDecoderResources(); |
| 115 |
| 116 if (drm_bridge_) { |
| 117 DCHECK(cdm_registration_id_); |
| 118 drm_bridge_->UnregisterPlayer(cdm_registration_id_); |
| 119 } |
107 } | 120 } |
108 | 121 |
109 void MediaCodecPlayer::Initialize() { | 122 void MediaCodecPlayer::Initialize() { |
110 DVLOG(1) << __FUNCTION__; | 123 DVLOG(1) << __FUNCTION__; |
111 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 124 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
112 | 125 |
113 interpolator_.SetUpperBound(base::TimeDelta()); | 126 interpolator_.SetUpperBound(base::TimeDelta()); |
114 | 127 |
115 CreateDecoders(); | 128 CreateDecoders(); |
116 | 129 |
(...skipping 27 matching lines...) Expand all Loading... |
144 // Save the empty-ness before we pass the surface to the decoder. | 157 // Save the empty-ness before we pass the surface to the decoder. |
145 bool surface_is_empty = surface.IsEmpty(); | 158 bool surface_is_empty = surface.IsEmpty(); |
146 | 159 |
147 // Apparently RemoveVideoSurface() can be called several times in a row, | 160 // Apparently RemoveVideoSurface() can be called several times in a row, |
148 // ignore the second and subsequent calls. | 161 // ignore the second and subsequent calls. |
149 if (surface_is_empty && !video_decoder_->HasVideoSurface()) { | 162 if (surface_is_empty && !video_decoder_->HasVideoSurface()) { |
150 DVLOG(1) << __FUNCTION__ << ": surface already removed, ignoring"; | 163 DVLOG(1) << __FUNCTION__ << ": surface already removed, ignoring"; |
151 return; | 164 return; |
152 } | 165 } |
153 | 166 |
| 167 // Do not set unprotected surface if we know that we need a protected one. |
| 168 // Empty surface means the surface removal and we always allow for it. |
| 169 if (!surface_is_empty && is_protected_surface_required_ && |
| 170 !surface.is_protected()) { |
| 171 DVLOG(0) << __FUNCTION__ << ": surface is not protected, ignoring"; |
| 172 return; |
| 173 } |
| 174 |
154 video_decoder_->SetVideoSurface(surface.Pass()); | 175 video_decoder_->SetVideoSurface(surface.Pass()); |
155 | 176 |
156 if (surface_is_empty) { | 177 if (surface_is_empty) { |
157 // Remove video surface. | 178 // Remove video surface. |
158 switch (state_) { | 179 switch (state_) { |
159 case kStatePlaying: | 180 case kStatePlaying: |
160 if (VideoFinished()) | 181 if (VideoFinished()) |
161 break; | 182 break; |
162 | 183 |
163 DVLOG(1) << __FUNCTION__ << ": stopping and restarting"; | 184 DVLOG(1) << __FUNCTION__ << ": stopping and restarting"; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 } | 237 } |
217 break; | 238 break; |
218 case kStateStopping: | 239 case kStateStopping: |
219 case kStateWaitingForSeek: | 240 case kStateWaitingForSeek: |
220 SetPendingStart(true); | 241 SetPendingStart(true); |
221 break; | 242 break; |
222 case kStateWaitingForConfig: | 243 case kStateWaitingForConfig: |
223 case kStatePrefetching: | 244 case kStatePrefetching: |
224 case kStatePlaying: | 245 case kStatePlaying: |
225 case kStateWaitingForSurface: | 246 case kStateWaitingForSurface: |
| 247 case kStateWaitingForKey: |
| 248 case kStateWaitingForCrypto: |
226 case kStateError: | 249 case kStateError: |
227 break; // Ignore | 250 break; // Ignore |
228 default: | 251 default: |
229 NOTREACHED(); | 252 NOTREACHED(); |
230 break; | 253 break; |
231 } | 254 } |
232 } | 255 } |
233 | 256 |
234 void MediaCodecPlayer::Pause(bool is_media_related_action) { | 257 void MediaCodecPlayer::Pause(bool is_media_related_action) { |
235 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); | 258 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); |
236 | 259 |
237 DVLOG(1) << __FUNCTION__; | 260 DVLOG(1) << __FUNCTION__; |
238 | 261 |
239 SetPendingStart(false); | 262 SetPendingStart(false); |
240 | 263 |
241 switch (state_) { | 264 switch (state_) { |
242 case kStateWaitingForConfig: | 265 case kStateWaitingForConfig: |
243 case kStatePrefetching: | 266 case kStatePrefetching: |
244 case kStateWaitingForSurface: | 267 case kStateWaitingForSurface: |
| 268 case kStateWaitingForKey: |
| 269 case kStateWaitingForCrypto: |
245 SetState(kStatePaused); | 270 SetState(kStatePaused); |
246 StopDecoders(); | 271 StopDecoders(); |
247 break; | 272 break; |
248 case kStatePlaying: | 273 case kStatePlaying: |
249 SetState(kStateStopping); | 274 SetState(kStateStopping); |
250 RequestToStopDecoders(); | 275 RequestToStopDecoders(); |
251 break; | 276 break; |
252 case kStatePaused: | 277 case kStatePaused: |
253 case kStateStopping: | 278 case kStateStopping: |
254 case kStateWaitingForSeek: | 279 case kStateWaitingForSeek: |
(...skipping 11 matching lines...) Expand all Loading... |
266 DVLOG(1) << __FUNCTION__ << " " << timestamp; | 291 DVLOG(1) << __FUNCTION__ << " " << timestamp; |
267 | 292 |
268 switch (state_) { | 293 switch (state_) { |
269 case kStatePaused: | 294 case kStatePaused: |
270 SetState(kStateWaitingForSeek); | 295 SetState(kStateWaitingForSeek); |
271 RequestDemuxerSeek(timestamp); | 296 RequestDemuxerSeek(timestamp); |
272 break; | 297 break; |
273 case kStateWaitingForConfig: | 298 case kStateWaitingForConfig: |
274 case kStatePrefetching: | 299 case kStatePrefetching: |
275 case kStateWaitingForSurface: | 300 case kStateWaitingForSurface: |
| 301 case kStateWaitingForKey: |
| 302 case kStateWaitingForCrypto: |
276 SetState(kStateWaitingForSeek); | 303 SetState(kStateWaitingForSeek); |
277 StopDecoders(); | 304 StopDecoders(); |
278 SetPendingStart(true); | 305 SetPendingStart(true); |
279 RequestDemuxerSeek(timestamp); | 306 RequestDemuxerSeek(timestamp); |
280 break; | 307 break; |
281 case kStatePlaying: | 308 case kStatePlaying: |
282 SetState(kStateStopping); | 309 SetState(kStateStopping); |
283 RequestToStopDecoders(); | 310 RequestToStopDecoders(); |
284 SetPendingStart(true); | 311 SetPendingStart(true); |
285 SetPendingSeek(timestamp); | 312 SetPendingSeek(timestamp); |
(...skipping 20 matching lines...) Expand all Loading... |
306 // Stop decoding threads and delete MediaCodecs, but keep IPC between browser | 333 // Stop decoding threads and delete MediaCodecs, but keep IPC between browser |
307 // and renderer processes going. Seek should work across and after Release(). | 334 // and renderer processes going. Seek should work across and after Release(). |
308 | 335 |
309 ReleaseDecoderResources(); | 336 ReleaseDecoderResources(); |
310 | 337 |
311 SetPendingStart(false); | 338 SetPendingStart(false); |
312 | 339 |
313 if (state_ != kStateWaitingForSeek) | 340 if (state_ != kStateWaitingForSeek) |
314 SetState(kStatePaused); | 341 SetState(kStatePaused); |
315 | 342 |
| 343 // Crear encryption key related flags. |
| 344 key_is_required_ = false; |
| 345 key_is_added_ = false; |
| 346 |
316 base::TimeDelta pending_seek_time = GetPendingSeek(); | 347 base::TimeDelta pending_seek_time = GetPendingSeek(); |
317 if (pending_seek_time != kNoTimestamp()) { | 348 if (pending_seek_time != kNoTimestamp()) { |
318 SetPendingSeek(kNoTimestamp()); | 349 SetPendingSeek(kNoTimestamp()); |
319 SetState(kStateWaitingForSeek); | 350 SetState(kStateWaitingForSeek); |
320 RequestDemuxerSeek(pending_seek_time); | 351 RequestDemuxerSeek(pending_seek_time); |
321 } | 352 } |
322 } | 353 } |
323 | 354 |
324 void MediaCodecPlayer::SetVolume(double volume) { | 355 void MediaCodecPlayer::SetVolume(double volume) { |
325 RUN_ON_MEDIA_THREAD(SetVolume, volume); | 356 RUN_ON_MEDIA_THREAD(SetVolume, volume); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 } | 406 } |
376 | 407 |
377 bool MediaCodecPlayer::IsPlayerReady() { | 408 bool MediaCodecPlayer::IsPlayerReady() { |
378 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 409 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
379 // This method is called to check whether it's safe to release the player when | 410 // This method is called to check whether it's safe to release the player when |
380 // the OS needs more resources. This class can be released at any time. | 411 // the OS needs more resources. This class can be released at any time. |
381 return true; | 412 return true; |
382 } | 413 } |
383 | 414 |
384 void MediaCodecPlayer::SetCdm(BrowserCdm* cdm) { | 415 void MediaCodecPlayer::SetCdm(BrowserCdm* cdm) { |
385 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 416 RUN_ON_MEDIA_THREAD(SetCdm, cdm); |
386 NOTIMPLEMENTED(); | 417 |
| 418 DVLOG(1) << __FUNCTION__; |
| 419 |
| 420 // Currently we don't support DRM change during the middle of playback, even |
| 421 // if the player is paused. There is no current plan to support it, see |
| 422 // http://crbug.com/253792. |
| 423 if (state_ != kStatePaused || GetInterpolatedTime() > base::TimeDelta()) { |
| 424 VLOG(0) << "Setting DRM bridge after playback has started is not supported"; |
| 425 return; |
| 426 } |
| 427 |
| 428 if (drm_bridge_) { |
| 429 NOTREACHED() << "Currently we do not support resetting CDM."; |
| 430 return; |
| 431 } |
| 432 |
| 433 DCHECK(cdm); |
| 434 drm_bridge_ = static_cast<MediaDrmBridge*>(cdm); |
| 435 |
| 436 DCHECK(drm_bridge_); |
| 437 |
| 438 cdm_registration_id_ = drm_bridge_->RegisterPlayer( |
| 439 base::Bind(&MediaCodecPlayer::OnKeyAdded, media_weak_this_), |
| 440 base::Bind(&MediaCodecPlayer::OnCdmUnset, media_weak_this_)); |
| 441 |
| 442 // We assume this property never changes so we can ask it here and use later. |
| 443 // TODO(timav): This value can be passed with MediaCryptoReadyCB. |
| 444 is_protected_surface_required_ = drm_bridge_->IsProtectedSurfaceRequired(); |
| 445 |
| 446 // If the crypto is ready by this time, OnMediaCryptoReady will be posted |
| 447 // right away. |
| 448 // drm_bridge_->SetMediaCryptoReadyCB( |
| 449 // base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_)); |
| 450 |
| 451 MediaDrmBridge::MediaCryptoReadyCB cb = |
| 452 base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_); |
| 453 |
| 454 // Post back to UI thread? |
| 455 // TODO(timav): We need weak ptr for UI thread. |
| 456 ui_task_runner_->PostTask(FROM_HERE, |
| 457 base::Bind(&MediaDrmBridge::SetMediaCryptoReadyCB, |
| 458 base::Unretained(drm_bridge_), cb)); |
387 } | 459 } |
388 | 460 |
389 // Callbacks from Demuxer. | 461 // Callbacks from Demuxer. |
390 | 462 |
391 void MediaCodecPlayer::OnDemuxerConfigsAvailable( | 463 void MediaCodecPlayer::OnDemuxerConfigsAvailable( |
392 const DemuxerConfigs& configs) { | 464 const DemuxerConfigs& configs) { |
393 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 465 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
394 | 466 |
395 DVLOG(1) << __FUNCTION__; | 467 DVLOG(1) << __FUNCTION__; |
396 | 468 |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 DCHECK(!internal_error_cb_.is_null()); | 669 DCHECK(!internal_error_cb_.is_null()); |
598 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); | 670 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |
599 return; | 671 return; |
600 } | 672 } |
601 | 673 |
602 if (HasVideo() && !video_decoder_->HasVideoSurface()) { | 674 if (HasVideo() && !video_decoder_->HasVideoSurface()) { |
603 SetState(kStateWaitingForSurface); | 675 SetState(kStateWaitingForSurface); |
604 return; | 676 return; |
605 } | 677 } |
606 | 678 |
| 679 if (key_is_required_ && !key_is_added_) { |
| 680 SetState(kStateWaitingForKey); |
| 681 ui_task_runner_->PostTask(FROM_HERE, key_required_cb_); |
| 682 return; |
| 683 } |
| 684 |
607 SetState(kStatePlaying); | 685 SetState(kStatePlaying); |
608 StartPlaybackOrBrowserSeek(); | 686 StartPlaybackOrBrowserSeek(); |
609 } | 687 } |
610 | 688 |
611 void MediaCodecPlayer::OnPrerollDone() { | 689 void MediaCodecPlayer::OnPrerollDone() { |
612 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 690 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
613 | 691 |
614 if (state_ != kStatePlaying) { | 692 if (state_ != kStatePlaying) { |
615 DVLOG(1) << __FUNCTION__ << ": in state " << AsString(state_) | 693 DVLOG(1) << __FUNCTION__ << ": in state " << AsString(state_) |
616 << ", ignoring"; | 694 << ", ignoring"; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 return; | 788 return; |
711 } | 789 } |
712 | 790 |
713 // DetachListener to UI thread | 791 // DetachListener to UI thread |
714 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); | 792 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); |
715 | 793 |
716 if (AudioFinished() && VideoFinished()) | 794 if (AudioFinished() && VideoFinished()) |
717 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); | 795 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); |
718 } | 796 } |
719 | 797 |
| 798 void MediaCodecPlayer::OnKeyRequired(DemuxerStream::Type type) { |
| 799 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 800 DVLOG(1) << __FUNCTION__ << " " << type; |
| 801 |
| 802 // Request stop and restart to pick up the key. |
| 803 key_is_required_ = true; |
| 804 |
| 805 if (state_ == kStatePlaying) { |
| 806 SetState(kStateStopping); |
| 807 RequestToStopDecoders(); |
| 808 SetPendingStart(true); |
| 809 } |
| 810 } |
| 811 |
720 void MediaCodecPlayer::OnError() { | 812 void MediaCodecPlayer::OnError() { |
721 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 813 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
722 DVLOG(1) << __FUNCTION__; | 814 DVLOG(1) << __FUNCTION__; |
723 | 815 |
724 // kStateError blocks all events | 816 // kStateError blocks all events |
725 SetState(kStateError); | 817 SetState(kStateError); |
726 | 818 |
727 ReleaseDecoderResources(); | 819 ReleaseDecoderResources(); |
728 | 820 |
729 ui_task_runner_->PostTask(FROM_HERE, | 821 ui_task_runner_->PostTask(FROM_HERE, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 void MediaCodecPlayer::OnVideoResolutionChanged(const gfx::Size& size) { | 885 void MediaCodecPlayer::OnVideoResolutionChanged(const gfx::Size& size) { |
794 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 886 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
795 | 887 |
796 DVLOG(1) << __FUNCTION__ << " " << size.width() << "x" << size.height(); | 888 DVLOG(1) << __FUNCTION__ << " " << size.width() << "x" << size.height(); |
797 | 889 |
798 // Update cache and notify manager on UI thread | 890 // Update cache and notify manager on UI thread |
799 ui_task_runner_->PostTask( | 891 ui_task_runner_->PostTask( |
800 FROM_HERE, base::Bind(metadata_changed_cb_, kNoTimestamp(), size)); | 892 FROM_HERE, base::Bind(metadata_changed_cb_, kNoTimestamp(), size)); |
801 } | 893 } |
802 | 894 |
| 895 // Callbacks from DRM |
| 896 |
| 897 void MediaCodecPlayer::OnMediaCryptoReady( |
| 898 MediaDrmBridge::JavaObjectPtr media_crypto) { |
| 899 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 900 DVLOG(1) << __FUNCTION__; |
| 901 |
| 902 // We receive the MediaCrypto global reference with this callback and use it |
| 903 // later for all subsequent configurations. This is possible only if the |
| 904 // MediaCrypto object remains valid until new SetCdm() is called. |
| 905 |
| 906 DCHECK(media_crypto); |
| 907 DCHECK(!media_crypto->is_null()); |
| 908 |
| 909 media_crypto_ = media_crypto.Pass(); |
| 910 |
| 911 if (audio_decoder_) { |
| 912 audio_decoder_->SetNeedsReconfigure(); |
| 913 } |
| 914 |
| 915 if (video_decoder_) { |
| 916 video_decoder_->SetNeedsReconfigure(); |
| 917 video_decoder_->SetProtectedSurfaceRequired(is_protected_surface_required_); |
| 918 } |
| 919 |
| 920 if (state_ == kStateWaitingForCrypto) { |
| 921 // Resume start sequence (configure, etc.) |
| 922 SetState(kStatePlaying); |
| 923 StartPlaybackOrBrowserSeek(); |
| 924 } |
| 925 |
| 926 DVLOG(1) << __FUNCTION__ << " end"; |
| 927 } |
| 928 |
| 929 void MediaCodecPlayer::OnKeyAdded() { |
| 930 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 931 DVLOG(1) << __FUNCTION__; |
| 932 |
| 933 key_is_added_ = true; |
| 934 |
| 935 if (state_ == kStateWaitingForKey) { |
| 936 SetState(kStatePlaying); |
| 937 StartPlaybackOrBrowserSeek(); |
| 938 } |
| 939 } |
| 940 |
| 941 void MediaCodecPlayer::OnCdmUnset() { |
| 942 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 943 DVLOG(1) << __FUNCTION__; |
| 944 |
| 945 // This comment is copied from MediaSourcePlayer::OnCdmUnset(). |
| 946 // TODO(xhwang): Currently this is only called during teardown. Support full |
| 947 // detachment of CDM during playback. This will be needed when we start to |
| 948 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release |
| 949 // MediaDrm when the video is paused, or when the device goes to sleep (see |
| 950 // http://crbug.com/272421). |
| 951 |
| 952 if (audio_decoder_) { |
| 953 audio_decoder_->SetNeedsReconfigure(); |
| 954 } |
| 955 |
| 956 if (video_decoder_) { |
| 957 video_decoder_->SetProtectedSurfaceRequired(false); |
| 958 video_decoder_->SetNeedsReconfigure(); |
| 959 } |
| 960 |
| 961 cdm_registration_id_ = 0; |
| 962 is_protected_surface_required_ = false; |
| 963 drm_bridge_ = nullptr; |
| 964 media_crypto_.reset(); |
| 965 } |
| 966 |
803 // State machine operations, called on Media thread | 967 // State machine operations, called on Media thread |
804 | 968 |
805 void MediaCodecPlayer::SetState(PlayerState new_state) { | 969 void MediaCodecPlayer::SetState(PlayerState new_state) { |
806 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 970 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
807 | 971 |
808 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); | 972 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); |
809 state_ = new_state; | 973 state_ = new_state; |
810 } | 974 } |
811 | 975 |
812 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { | 976 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 video_decoder_->Prefetch(prefetch_cb); | 1056 video_decoder_->Prefetch(prefetch_cb); |
893 } | 1057 } |
894 | 1058 |
895 void MediaCodecPlayer::StartPlaybackOrBrowserSeek() { | 1059 void MediaCodecPlayer::StartPlaybackOrBrowserSeek() { |
896 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1060 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
897 DVLOG(1) << __FUNCTION__; | 1061 DVLOG(1) << __FUNCTION__; |
898 | 1062 |
899 // TODO(timav): consider replacing this method with posting a | 1063 // TODO(timav): consider replacing this method with posting a |
900 // browser seek task (i.e. generate an event) from StartPlaybackDecoders(). | 1064 // browser seek task (i.e. generate an event) from StartPlaybackDecoders(). |
901 | 1065 |
| 1066 // Clear encryption key related flags. |
| 1067 key_is_required_ = false; |
| 1068 key_is_added_ = false; |
| 1069 |
902 StartStatus status = StartPlaybackDecoders(); | 1070 StartStatus status = StartPlaybackDecoders(); |
903 | 1071 |
904 switch (status) { | 1072 switch (status) { |
905 case kStartBrowserSeekRequired: | 1073 case kStartBrowserSeekRequired: |
906 // Browser seek | 1074 // Browser seek |
907 SetState(kStateWaitingForSeek); | 1075 SetState(kStateWaitingForSeek); |
908 SetPendingStart(true); | 1076 SetPendingStart(true); |
909 StopDecoders(); | 1077 StopDecoders(); |
910 RequestDemuxerSeek(GetInterpolatedTime(), true); | 1078 RequestDemuxerSeek(GetInterpolatedTime(), true); |
911 break; | 1079 break; |
| 1080 case kStartCryptoRequired: |
| 1081 SetState(kStateWaitingForCrypto); |
| 1082 break; |
912 case kStartFailed: | 1083 case kStartFailed: |
913 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); | 1084 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |
914 break; | 1085 break; |
915 case kStartOk: | 1086 case kStartOk: |
916 break; | 1087 break; |
917 } | 1088 } |
918 } | 1089 } |
919 | 1090 |
920 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { | 1091 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { |
921 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1092 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
(...skipping 17 matching lines...) Expand all Loading... |
939 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1110 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
940 DVLOG(1) << __FUNCTION__; | 1111 DVLOG(1) << __FUNCTION__; |
941 | 1112 |
942 const bool do_audio = !AudioFinished(); | 1113 const bool do_audio = !AudioFinished(); |
943 const bool do_video = !VideoFinished(); | 1114 const bool do_video = !VideoFinished(); |
944 | 1115 |
945 // If there is nothing to play, the state machine should determine this at the | 1116 // If there is nothing to play, the state machine should determine this at the |
946 // prefetch state and never call this method. | 1117 // prefetch state and never call this method. |
947 DCHECK(do_audio || do_video); | 1118 DCHECK(do_audio || do_video); |
948 | 1119 |
949 // Start with video: if browser seek is required it would | 1120 bool need_crypto = (do_audio && audio_decoder_->IsContentEncrypted()) || |
950 // not make sense to configure audio. | 1121 (do_video && video_decoder_->IsContentEncrypted()); |
951 | 1122 |
952 if (do_video) { | 1123 // Do we need to create a local ref from the global ref? |
953 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure(); | 1124 jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr; |
954 switch (status) { | 1125 |
955 case MediaCodecDecoder::kConfigOk: | 1126 if (need_crypto) { |
956 break; | 1127 DVLOG(1) << (audio_decoder_->IsContentEncrypted() ? " audio" : "") |
957 case MediaCodecDecoder::kConfigKeyFrameRequired: | 1128 << (video_decoder_->IsContentEncrypted() ? " video" : "") |
958 // TODO(timav): post a task or return the status? | 1129 << " need(s) encryption"; |
959 return kStartBrowserSeekRequired; | 1130 if (!media_crypto) { |
960 case MediaCodecDecoder::kConfigFailure: | 1131 DVLOG(1) << __FUNCTION__ << ": MediaCrypto is not found, returning"; |
961 return kStartFailed; | 1132 return kStartCryptoRequired; |
962 } | 1133 } |
963 } | 1134 } |
964 | 1135 |
965 if (do_audio) { | 1136 // Start with video: if browser seek is required it would not make sense to |
966 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); | 1137 // configure audio. |
967 if (status != MediaCodecDecoder::kConfigOk) { | 1138 |
| 1139 MediaCodecDecoder::ConfigStatus status = MediaCodecDecoder::kConfigOk; |
| 1140 if (do_video) |
| 1141 status = video_decoder_->Configure(media_crypto); |
| 1142 |
| 1143 if (status == MediaCodecDecoder::kConfigOk && do_audio) |
| 1144 status = audio_decoder_->Configure(media_crypto); |
| 1145 |
| 1146 switch (status) { |
| 1147 case MediaCodecDecoder::kConfigOk: |
| 1148 break; |
| 1149 case MediaCodecDecoder::kConfigKeyFrameRequired: |
| 1150 return kStartBrowserSeekRequired; |
| 1151 case MediaCodecDecoder::kConfigNoCrypto: // TODO: delete this |
| 1152 return kStartCryptoRequired; |
| 1153 case MediaCodecDecoder::kConfigFailure: |
968 return kStartFailed; | 1154 return kStartFailed; |
969 } | |
970 } | 1155 } |
971 | |
972 return kStartOk; | 1156 return kStartOk; |
973 } | 1157 } |
974 | 1158 |
975 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( | 1159 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( |
976 bool* preroll_required) { | 1160 bool* preroll_required) { |
977 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1161 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
978 | 1162 |
979 DVLOG(1) << __FUNCTION__ << " current_time:" << GetInterpolatedTime(); | 1163 DVLOG(1) << __FUNCTION__ << " current_time:" << GetInterpolatedTime(); |
980 | 1164 |
981 // If requested, preroll is always done in the beginning of the playback, | 1165 // If requested, preroll is always done in the beginning of the playback, |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1120 | 1304 |
1121 audio_decoder_.reset(new MediaCodecAudioDecoder( | 1305 audio_decoder_.reset(new MediaCodecAudioDecoder( |
1122 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 1306 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |
1123 media_weak_this_, DemuxerStream::AUDIO), | 1307 media_weak_this_, DemuxerStream::AUDIO), |
1124 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 1308 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
1125 DemuxerStream::AUDIO), | 1309 DemuxerStream::AUDIO), |
1126 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, | 1310 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, |
1127 DemuxerStream::AUDIO), | 1311 DemuxerStream::AUDIO), |
1128 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, | 1312 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, |
1129 DemuxerStream::AUDIO), | 1313 DemuxerStream::AUDIO), |
| 1314 base::Bind(&MediaCodecPlayer::OnKeyRequired, media_weak_this_, |
| 1315 DemuxerStream::AUDIO), |
1130 internal_error_cb_, | 1316 internal_error_cb_, |
1131 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 1317 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
1132 DemuxerStream::AUDIO))); | 1318 DemuxerStream::AUDIO))); |
1133 | 1319 |
1134 video_decoder_.reset(new MediaCodecVideoDecoder( | 1320 video_decoder_.reset(new MediaCodecVideoDecoder( |
1135 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 1321 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |
1136 media_weak_this_, DemuxerStream::VIDEO), | 1322 media_weak_this_, DemuxerStream::VIDEO), |
1137 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 1323 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
1138 DemuxerStream::VIDEO), | 1324 DemuxerStream::VIDEO), |
1139 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, | 1325 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, |
1140 DemuxerStream::VIDEO), | 1326 DemuxerStream::VIDEO), |
1141 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, | 1327 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, |
1142 DemuxerStream::VIDEO), | 1328 DemuxerStream::VIDEO), |
| 1329 base::Bind(&MediaCodecPlayer::OnKeyRequired, media_weak_this_, |
| 1330 DemuxerStream::VIDEO), |
1143 internal_error_cb_, | 1331 internal_error_cb_, |
1144 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 1332 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
1145 DemuxerStream::VIDEO), | 1333 DemuxerStream::VIDEO), |
1146 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), | 1334 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), |
1147 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); | 1335 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); |
1148 } | 1336 } |
1149 | 1337 |
1150 bool MediaCodecPlayer::AudioFinished() const { | 1338 bool MediaCodecPlayer::AudioFinished() const { |
1151 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); | 1339 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); |
1152 } | 1340 } |
(...skipping 15 matching lines...) Expand all Loading... |
1168 return #x; | 1356 return #x; |
1169 | 1357 |
1170 const char* MediaCodecPlayer::AsString(PlayerState state) { | 1358 const char* MediaCodecPlayer::AsString(PlayerState state) { |
1171 switch (state) { | 1359 switch (state) { |
1172 RETURN_STRING(kStatePaused); | 1360 RETURN_STRING(kStatePaused); |
1173 RETURN_STRING(kStateWaitingForConfig); | 1361 RETURN_STRING(kStateWaitingForConfig); |
1174 RETURN_STRING(kStatePrefetching); | 1362 RETURN_STRING(kStatePrefetching); |
1175 RETURN_STRING(kStatePlaying); | 1363 RETURN_STRING(kStatePlaying); |
1176 RETURN_STRING(kStateStopping); | 1364 RETURN_STRING(kStateStopping); |
1177 RETURN_STRING(kStateWaitingForSurface); | 1365 RETURN_STRING(kStateWaitingForSurface); |
| 1366 RETURN_STRING(kStateWaitingForKey); |
| 1367 RETURN_STRING(kStateWaitingForCrypto); |
1178 RETURN_STRING(kStateWaitingForSeek); | 1368 RETURN_STRING(kStateWaitingForSeek); |
1179 RETURN_STRING(kStateError); | 1369 RETURN_STRING(kStateError); |
1180 } | 1370 } |
1181 return nullptr; // crash early | 1371 return nullptr; // crash early |
1182 } | 1372 } |
1183 | 1373 |
1184 #undef RETURN_STRING | 1374 #undef RETURN_STRING |
1185 | 1375 |
1186 } // namespace media | 1376 } // namespace media |
OLD | NEW |