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/android/media_task_runner.h" | 17 #include "media/base/android/media_task_runner.h" |
| 18 #include "media/base/bind_to_current_loop.h" |
17 #include "media/base/timestamp_constants.h" | 19 #include "media/base/timestamp_constants.h" |
18 | 20 |
19 #define RUN_ON_MEDIA_THREAD(METHOD, ...) \ | 21 #define RUN_ON_MEDIA_THREAD(METHOD, ...) \ |
20 do { \ | 22 do { \ |
21 if (!GetMediaTaskRunner()->BelongsToCurrentThread()) { \ | 23 if (!GetMediaTaskRunner()->BelongsToCurrentThread()) { \ |
22 DCHECK(ui_task_runner_->BelongsToCurrentThread()); \ | 24 DCHECK(ui_task_runner_->BelongsToCurrentThread()); \ |
23 GetMediaTaskRunner()->PostTask( \ | 25 GetMediaTaskRunner()->PostTask( \ |
24 FROM_HERE, base::Bind(&MediaCodecPlayer::METHOD, media_weak_this_, \ | 26 FROM_HERE, base::Bind(&MediaCodecPlayer::METHOD, media_weak_this_, \ |
25 ##__VA_ARGS__)); \ | 27 ##__VA_ARGS__)); \ |
26 return; \ | 28 return; \ |
(...skipping 13 matching lines...) Expand all Loading... |
40 : MediaPlayerAndroid(player_id, | 42 : MediaPlayerAndroid(player_id, |
41 manager.get(), | 43 manager.get(), |
42 request_media_resources_cb, | 44 request_media_resources_cb, |
43 frame_url), | 45 frame_url), |
44 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 46 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
45 demuxer_(demuxer.Pass()), | 47 demuxer_(demuxer.Pass()), |
46 state_(kStatePaused), | 48 state_(kStatePaused), |
47 interpolator_(&default_tick_clock_), | 49 interpolator_(&default_tick_clock_), |
48 pending_start_(false), | 50 pending_start_(false), |
49 pending_seek_(kNoTimestamp()), | 51 pending_seek_(kNoTimestamp()), |
| 52 drm_bridge_(nullptr), |
| 53 cdm_registration_id_(0), |
| 54 key_is_required_(false), |
| 55 key_is_added_(false), |
50 media_weak_factory_(this) { | 56 media_weak_factory_(this) { |
51 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 57 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
52 | 58 |
53 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; | 59 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; |
54 | 60 |
55 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); | 61 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); |
56 | 62 |
57 completion_cb_ = | 63 completion_cb_ = |
58 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); | 64 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); |
| 65 waiting_for_decryption_key_cb_ = base::Bind( |
| 66 &MediaPlayerManager::OnWaitingForDecryptionKey, manager, player_id); |
59 seek_done_cb_ = | 67 seek_done_cb_ = |
60 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); | 68 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); |
61 error_cb_ = base::Bind(&MediaPlayerManager::OnError, manager, player_id); | 69 error_cb_ = base::Bind(&MediaPlayerManager::OnError, manager, player_id); |
62 | 70 |
63 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, | 71 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, |
64 WeakPtrForUIThread(), nullptr); | 72 WeakPtrForUIThread(), nullptr); |
65 detach_listener_cb_ = | 73 detach_listener_cb_ = |
66 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); | 74 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); |
67 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, | 75 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, |
68 WeakPtrForUIThread()); | 76 WeakPtrForUIThread()); |
(...skipping 14 matching lines...) Expand all Loading... |
83 | 91 |
84 // Currently the unit tests wait for the MediaCodecPlayer destruction by | 92 // Currently the unit tests wait for the MediaCodecPlayer destruction by |
85 // watching the demuxer, which is destroyed as one of the member variables. | 93 // watching the demuxer, which is destroyed as one of the member variables. |
86 // Release the codecs here, before any member variable is destroyed to make | 94 // Release the codecs here, before any member variable is destroyed to make |
87 // the unit tests happy. | 95 // the unit tests happy. |
88 | 96 |
89 if (video_decoder_) | 97 if (video_decoder_) |
90 video_decoder_->ReleaseDecoderResources(); | 98 video_decoder_->ReleaseDecoderResources(); |
91 if (audio_decoder_) | 99 if (audio_decoder_) |
92 audio_decoder_->ReleaseDecoderResources(); | 100 audio_decoder_->ReleaseDecoderResources(); |
| 101 |
| 102 if (drm_bridge_) { |
| 103 DCHECK(cdm_registration_id_); |
| 104 drm_bridge_->UnregisterPlayer(cdm_registration_id_); |
| 105 } |
93 } | 106 } |
94 | 107 |
95 void MediaCodecPlayer::Initialize() { | 108 void MediaCodecPlayer::Initialize() { |
96 DVLOG(1) << __FUNCTION__; | 109 DVLOG(1) << __FUNCTION__; |
97 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 110 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
98 | 111 |
99 interpolator_.SetUpperBound(base::TimeDelta()); | 112 interpolator_.SetUpperBound(base::TimeDelta()); |
100 | 113 |
101 CreateDecoders(); | 114 CreateDecoders(); |
102 | 115 |
(...skipping 27 matching lines...) Expand all Loading... |
130 // Save the empty-ness before we pass the surface to the decoder. | 143 // Save the empty-ness before we pass the surface to the decoder. |
131 bool surface_is_empty = surface.IsEmpty(); | 144 bool surface_is_empty = surface.IsEmpty(); |
132 | 145 |
133 // Apparently RemoveVideoSurface() can be called several times in a row, | 146 // Apparently RemoveVideoSurface() can be called several times in a row, |
134 // ignore the second and subsequent calls. | 147 // ignore the second and subsequent calls. |
135 if (surface_is_empty && !video_decoder_->HasVideoSurface()) { | 148 if (surface_is_empty && !video_decoder_->HasVideoSurface()) { |
136 DVLOG(1) << __FUNCTION__ << ": surface already removed, ignoring"; | 149 DVLOG(1) << __FUNCTION__ << ": surface already removed, ignoring"; |
137 return; | 150 return; |
138 } | 151 } |
139 | 152 |
| 153 // Do not set unprotected surface if we know that we need a protected one. |
| 154 // Empty surface means the surface removal and we always allow for it. |
| 155 if (!surface_is_empty && video_decoder_->IsProtectedSurfaceRequired() && |
| 156 !surface.is_protected()) { |
| 157 DVLOG(0) << __FUNCTION__ << ": surface is not protected, ignoring"; |
| 158 return; |
| 159 } |
| 160 |
140 video_decoder_->SetVideoSurface(surface.Pass()); | 161 video_decoder_->SetVideoSurface(surface.Pass()); |
141 | 162 |
142 if (surface_is_empty) { | 163 if (surface_is_empty) { |
143 // Remove video surface. | 164 // Remove video surface. |
144 switch (state_) { | 165 switch (state_) { |
145 case kStatePlaying: | 166 case kStatePlaying: |
146 if (VideoFinished()) | 167 if (VideoFinished()) |
147 break; | 168 break; |
148 | 169 |
149 DVLOG(1) << __FUNCTION__ << ": stopping and restarting"; | 170 DVLOG(1) << __FUNCTION__ << ": stopping and restarting"; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 break; | 224 break; |
204 case kStateStopping: | 225 case kStateStopping: |
205 case kStateWaitingForSeek: | 226 case kStateWaitingForSeek: |
206 SetPendingStart(true); | 227 SetPendingStart(true); |
207 break; | 228 break; |
208 case kStateWaitingForConfig: | 229 case kStateWaitingForConfig: |
209 case kStateWaitingForPermission: | 230 case kStateWaitingForPermission: |
210 case kStatePrefetching: | 231 case kStatePrefetching: |
211 case kStatePlaying: | 232 case kStatePlaying: |
212 case kStateWaitingForSurface: | 233 case kStateWaitingForSurface: |
| 234 case kStateWaitingForKey: |
| 235 case kStateWaitingForMediaCrypto: |
213 case kStateError: | 236 case kStateError: |
214 break; // Ignore | 237 break; // Ignore |
215 default: | 238 default: |
216 NOTREACHED(); | 239 NOTREACHED(); |
217 break; | 240 break; |
218 } | 241 } |
219 } | 242 } |
220 | 243 |
221 void MediaCodecPlayer::Pause(bool is_media_related_action) { | 244 void MediaCodecPlayer::Pause(bool is_media_related_action) { |
222 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); | 245 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); |
223 | 246 |
224 DVLOG(1) << __FUNCTION__; | 247 DVLOG(1) << __FUNCTION__; |
225 | 248 |
226 SetPendingStart(false); | 249 SetPendingStart(false); |
227 | 250 |
228 switch (state_) { | 251 switch (state_) { |
229 case kStateWaitingForConfig: | 252 case kStateWaitingForConfig: |
230 case kStateWaitingForPermission: | 253 case kStateWaitingForPermission: |
231 case kStatePrefetching: | 254 case kStatePrefetching: |
232 case kStateWaitingForSurface: | 255 case kStateWaitingForSurface: |
| 256 case kStateWaitingForKey: |
| 257 case kStateWaitingForMediaCrypto: |
233 SetState(kStatePaused); | 258 SetState(kStatePaused); |
234 StopDecoders(); | 259 StopDecoders(); |
235 break; | 260 break; |
236 case kStatePlaying: | 261 case kStatePlaying: |
237 SetState(kStateStopping); | 262 SetState(kStateStopping); |
238 RequestToStopDecoders(); | 263 RequestToStopDecoders(); |
239 break; | 264 break; |
240 case kStatePaused: | 265 case kStatePaused: |
241 case kStateStopping: | 266 case kStateStopping: |
242 case kStateWaitingForSeek: | 267 case kStateWaitingForSeek: |
(...skipping 12 matching lines...) Expand all Loading... |
255 | 280 |
256 switch (state_) { | 281 switch (state_) { |
257 case kStatePaused: | 282 case kStatePaused: |
258 SetState(kStateWaitingForSeek); | 283 SetState(kStateWaitingForSeek); |
259 RequestDemuxerSeek(timestamp); | 284 RequestDemuxerSeek(timestamp); |
260 break; | 285 break; |
261 case kStateWaitingForConfig: | 286 case kStateWaitingForConfig: |
262 case kStateWaitingForPermission: | 287 case kStateWaitingForPermission: |
263 case kStatePrefetching: | 288 case kStatePrefetching: |
264 case kStateWaitingForSurface: | 289 case kStateWaitingForSurface: |
| 290 case kStateWaitingForKey: |
| 291 case kStateWaitingForMediaCrypto: |
265 SetState(kStateWaitingForSeek); | 292 SetState(kStateWaitingForSeek); |
266 StopDecoders(); | 293 StopDecoders(); |
267 SetPendingStart(true); | 294 SetPendingStart(true); |
268 RequestDemuxerSeek(timestamp); | 295 RequestDemuxerSeek(timestamp); |
269 break; | 296 break; |
270 case kStatePlaying: | 297 case kStatePlaying: |
271 SetState(kStateStopping); | 298 SetState(kStateStopping); |
272 RequestToStopDecoders(); | 299 RequestToStopDecoders(); |
273 SetPendingStart(true); | 300 SetPendingStart(true); |
274 SetPendingSeek(timestamp); | 301 SetPendingSeek(timestamp); |
(...skipping 20 matching lines...) Expand all Loading... |
295 // Stop decoding threads and delete MediaCodecs, but keep IPC between browser | 322 // Stop decoding threads and delete MediaCodecs, but keep IPC between browser |
296 // and renderer processes going. Seek should work across and after Release(). | 323 // and renderer processes going. Seek should work across and after Release(). |
297 | 324 |
298 ReleaseDecoderResources(); | 325 ReleaseDecoderResources(); |
299 | 326 |
300 SetPendingStart(false); | 327 SetPendingStart(false); |
301 | 328 |
302 if (state_ != kStateWaitingForSeek) | 329 if (state_ != kStateWaitingForSeek) |
303 SetState(kStatePaused); | 330 SetState(kStatePaused); |
304 | 331 |
| 332 // Crear encryption key related flags. |
| 333 key_is_required_ = false; |
| 334 key_is_added_ = false; |
| 335 |
305 base::TimeDelta pending_seek_time = GetPendingSeek(); | 336 base::TimeDelta pending_seek_time = GetPendingSeek(); |
306 if (pending_seek_time != kNoTimestamp()) { | 337 if (pending_seek_time != kNoTimestamp()) { |
307 SetPendingSeek(kNoTimestamp()); | 338 SetPendingSeek(kNoTimestamp()); |
308 SetState(kStateWaitingForSeek); | 339 SetState(kStateWaitingForSeek); |
309 RequestDemuxerSeek(pending_seek_time); | 340 RequestDemuxerSeek(pending_seek_time); |
310 } | 341 } |
311 } | 342 } |
312 | 343 |
313 void MediaCodecPlayer::SetVolume(double volume) { | 344 void MediaCodecPlayer::SetVolume(double volume) { |
314 RUN_ON_MEDIA_THREAD(SetVolume, volume); | 345 RUN_ON_MEDIA_THREAD(SetVolume, volume); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 } | 395 } |
365 | 396 |
366 bool MediaCodecPlayer::IsPlayerReady() { | 397 bool MediaCodecPlayer::IsPlayerReady() { |
367 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 398 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
368 // This method is called to check whether it's safe to release the player when | 399 // This method is called to check whether it's safe to release the player when |
369 // the OS needs more resources. This class can be released at any time. | 400 // the OS needs more resources. This class can be released at any time. |
370 return true; | 401 return true; |
371 } | 402 } |
372 | 403 |
373 void MediaCodecPlayer::SetCdm(BrowserCdm* cdm) { | 404 void MediaCodecPlayer::SetCdm(BrowserCdm* cdm) { |
374 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 405 RUN_ON_MEDIA_THREAD(SetCdm, cdm); |
375 NOTIMPLEMENTED(); | 406 |
| 407 DVLOG(1) << __FUNCTION__; |
| 408 |
| 409 // Currently we don't support DRM change during the middle of playback, even |
| 410 // if the player is paused. There is no current plan to support it, see |
| 411 // http://crbug.com/253792. |
| 412 if (state_ != kStatePaused || GetInterpolatedTime() > base::TimeDelta()) { |
| 413 VLOG(0) << "Setting DRM bridge after playback has started is not supported"; |
| 414 return; |
| 415 } |
| 416 |
| 417 if (drm_bridge_) { |
| 418 NOTREACHED() << "Currently we do not support resetting CDM."; |
| 419 return; |
| 420 } |
| 421 |
| 422 DCHECK(cdm); |
| 423 drm_bridge_ = static_cast<MediaDrmBridge*>(cdm); |
| 424 |
| 425 DCHECK(drm_bridge_); |
| 426 |
| 427 cdm_registration_id_ = drm_bridge_->RegisterPlayer( |
| 428 base::Bind(&MediaCodecPlayer::OnKeyAdded, media_weak_this_), |
| 429 base::Bind(&MediaCodecPlayer::OnCdmUnset, media_weak_this_)); |
| 430 |
| 431 MediaDrmBridge::MediaCryptoReadyCB cb = BindToCurrentLoop( |
| 432 base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_)); |
| 433 |
| 434 // Post back to UI thread. |
| 435 ui_task_runner_->PostTask(FROM_HERE, |
| 436 base::Bind(&MediaDrmBridge::SetMediaCryptoReadyCB, |
| 437 drm_bridge_->WeakPtrForUIThread(), cb)); |
376 } | 438 } |
377 | 439 |
378 // Callbacks from Demuxer. | 440 // Callbacks from Demuxer. |
379 | 441 |
380 void MediaCodecPlayer::OnDemuxerConfigsAvailable( | 442 void MediaCodecPlayer::OnDemuxerConfigsAvailable( |
381 const DemuxerConfigs& configs) { | 443 const DemuxerConfigs& configs) { |
382 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 444 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
383 | 445 |
384 DVLOG(1) << __FUNCTION__; | 446 DVLOG(1) << __FUNCTION__; |
385 | 447 |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 DCHECK(!internal_error_cb_.is_null()); | 688 DCHECK(!internal_error_cb_.is_null()); |
627 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); | 689 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |
628 return; | 690 return; |
629 } | 691 } |
630 | 692 |
631 if (HasVideo() && !video_decoder_->HasVideoSurface()) { | 693 if (HasVideo() && !video_decoder_->HasVideoSurface()) { |
632 SetState(kStateWaitingForSurface); | 694 SetState(kStateWaitingForSurface); |
633 return; | 695 return; |
634 } | 696 } |
635 | 697 |
| 698 if (key_is_required_ && !key_is_added_) { |
| 699 SetState(kStateWaitingForKey); |
| 700 ui_task_runner_->PostTask(FROM_HERE, waiting_for_decryption_key_cb_); |
| 701 return; |
| 702 } |
| 703 |
636 SetState(kStatePlaying); | 704 SetState(kStatePlaying); |
637 StartPlaybackOrBrowserSeek(); | 705 StartPlaybackOrBrowserSeek(); |
638 } | 706 } |
639 | 707 |
640 void MediaCodecPlayer::OnPrerollDone() { | 708 void MediaCodecPlayer::OnPrerollDone() { |
641 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 709 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
642 | 710 |
643 if (state_ != kStatePlaying) { | 711 if (state_ != kStatePlaying) { |
644 DVLOG(1) << __FUNCTION__ << ": in state " << AsString(state_) | 712 DVLOG(1) << __FUNCTION__ << ": in state " << AsString(state_) |
645 << ", ignoring"; | 713 << ", ignoring"; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 return; | 807 return; |
740 } | 808 } |
741 | 809 |
742 // DetachListener to UI thread | 810 // DetachListener to UI thread |
743 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); | 811 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); |
744 | 812 |
745 if (AudioFinished() && VideoFinished()) | 813 if (AudioFinished() && VideoFinished()) |
746 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); | 814 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); |
747 } | 815 } |
748 | 816 |
| 817 void MediaCodecPlayer::OnMissingKeyReported(DemuxerStream::Type type) { |
| 818 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 819 DVLOG(1) << __FUNCTION__ << " " << type; |
| 820 |
| 821 // Request stop and restart to pick up the key. |
| 822 key_is_required_ = true; |
| 823 |
| 824 if (state_ == kStatePlaying) { |
| 825 SetState(kStateStopping); |
| 826 RequestToStopDecoders(); |
| 827 SetPendingStart(true); |
| 828 } |
| 829 } |
| 830 |
749 void MediaCodecPlayer::OnError() { | 831 void MediaCodecPlayer::OnError() { |
750 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 832 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
751 DVLOG(1) << __FUNCTION__; | 833 DVLOG(1) << __FUNCTION__; |
752 | 834 |
753 // kStateError blocks all events | 835 // kStateError blocks all events |
754 SetState(kStateError); | 836 SetState(kStateError); |
755 | 837 |
756 ReleaseDecoderResources(); | 838 ReleaseDecoderResources(); |
757 | 839 |
758 ui_task_runner_->PostTask(FROM_HERE, | 840 ui_task_runner_->PostTask(FROM_HERE, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 void MediaCodecPlayer::OnVideoResolutionChanged(const gfx::Size& size) { | 904 void MediaCodecPlayer::OnVideoResolutionChanged(const gfx::Size& size) { |
823 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 905 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
824 | 906 |
825 DVLOG(1) << __FUNCTION__ << " " << size.width() << "x" << size.height(); | 907 DVLOG(1) << __FUNCTION__ << " " << size.width() << "x" << size.height(); |
826 | 908 |
827 // Update cache and notify manager on UI thread | 909 // Update cache and notify manager on UI thread |
828 ui_task_runner_->PostTask( | 910 ui_task_runner_->PostTask( |
829 FROM_HERE, base::Bind(metadata_changed_cb_, kNoTimestamp(), size)); | 911 FROM_HERE, base::Bind(metadata_changed_cb_, kNoTimestamp(), size)); |
830 } | 912 } |
831 | 913 |
| 914 // Callbacks from MediaDrmBridge. |
| 915 |
| 916 void MediaCodecPlayer::OnMediaCryptoReady( |
| 917 MediaDrmBridge::JavaObjectPtr media_crypto, |
| 918 bool needs_protected_surface) { |
| 919 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 920 DVLOG(1) << __FUNCTION__ << " protected surface is " |
| 921 << (needs_protected_surface ? "required" : "not required"); |
| 922 |
| 923 // We use the parameters that come with this callback every time we call |
| 924 // Configure(). This is possible only if the MediaCrypto object remains valid |
| 925 // and the surface requirement does not change until new SetCdm() is called. |
| 926 |
| 927 DCHECK(media_crypto); |
| 928 DCHECK(!media_crypto->is_null()); |
| 929 |
| 930 media_crypto_ = media_crypto.Pass(); |
| 931 |
| 932 if (audio_decoder_) { |
| 933 audio_decoder_->SetNeedsReconfigure(); |
| 934 } |
| 935 |
| 936 if (video_decoder_) { |
| 937 video_decoder_->SetNeedsReconfigure(); |
| 938 video_decoder_->SetProtectedSurfaceRequired(needs_protected_surface); |
| 939 } |
| 940 |
| 941 if (state_ == kStateWaitingForMediaCrypto) { |
| 942 // Resume start sequence (configure, etc.) |
| 943 SetState(kStatePlaying); |
| 944 StartPlaybackOrBrowserSeek(); |
| 945 } |
| 946 |
| 947 DVLOG(1) << __FUNCTION__ << " end"; |
| 948 } |
| 949 |
| 950 void MediaCodecPlayer::OnKeyAdded() { |
| 951 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 952 DVLOG(1) << __FUNCTION__; |
| 953 |
| 954 key_is_added_ = true; |
| 955 |
| 956 if (state_ == kStateWaitingForKey) { |
| 957 SetState(kStatePlaying); |
| 958 StartPlaybackOrBrowserSeek(); |
| 959 } |
| 960 } |
| 961 |
| 962 void MediaCodecPlayer::OnCdmUnset() { |
| 963 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 964 DVLOG(1) << __FUNCTION__; |
| 965 |
| 966 // This comment is copied from MediaSourcePlayer::OnCdmUnset(). |
| 967 // TODO(xhwang): Currently this is only called during teardown. Support full |
| 968 // detachment of CDM during playback. This will be needed when we start to |
| 969 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release |
| 970 // MediaDrm when the video is paused, or when the device goes to sleep (see |
| 971 // http://crbug.com/272421). |
| 972 |
| 973 if (audio_decoder_) { |
| 974 audio_decoder_->SetNeedsReconfigure(); |
| 975 } |
| 976 |
| 977 if (video_decoder_) { |
| 978 video_decoder_->SetProtectedSurfaceRequired(false); |
| 979 video_decoder_->SetNeedsReconfigure(); |
| 980 } |
| 981 |
| 982 cdm_registration_id_ = 0; |
| 983 drm_bridge_ = nullptr; |
| 984 media_crypto_.reset(); |
| 985 } |
| 986 |
832 // State machine operations, called on Media thread | 987 // State machine operations, called on Media thread |
833 | 988 |
834 void MediaCodecPlayer::SetState(PlayerState new_state) { | 989 void MediaCodecPlayer::SetState(PlayerState new_state) { |
835 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 990 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
836 | 991 |
837 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); | 992 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); |
838 state_ = new_state; | 993 state_ = new_state; |
839 } | 994 } |
840 | 995 |
841 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { | 996 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
933 video_decoder_->Prefetch(prefetch_cb); | 1088 video_decoder_->Prefetch(prefetch_cb); |
934 } | 1089 } |
935 | 1090 |
936 void MediaCodecPlayer::StartPlaybackOrBrowserSeek() { | 1091 void MediaCodecPlayer::StartPlaybackOrBrowserSeek() { |
937 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1092 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
938 DVLOG(1) << __FUNCTION__; | 1093 DVLOG(1) << __FUNCTION__; |
939 | 1094 |
940 // TODO(timav): consider replacing this method with posting a | 1095 // TODO(timav): consider replacing this method with posting a |
941 // browser seek task (i.e. generate an event) from StartPlaybackDecoders(). | 1096 // browser seek task (i.e. generate an event) from StartPlaybackDecoders(). |
942 | 1097 |
| 1098 // Clear encryption key related flags. |
| 1099 key_is_required_ = false; |
| 1100 key_is_added_ = false; |
| 1101 |
943 StartStatus status = StartPlaybackDecoders(); | 1102 StartStatus status = StartPlaybackDecoders(); |
944 | 1103 |
945 switch (status) { | 1104 switch (status) { |
946 case kStartBrowserSeekRequired: | 1105 case kStartBrowserSeekRequired: |
947 // Browser seek | 1106 // Browser seek |
948 SetState(kStateWaitingForSeek); | 1107 SetState(kStateWaitingForSeek); |
949 SetPendingStart(true); | 1108 SetPendingStart(true); |
950 StopDecoders(); | 1109 StopDecoders(); |
951 RequestDemuxerSeek(GetInterpolatedTime(), true); | 1110 RequestDemuxerSeek(GetInterpolatedTime(), true); |
952 break; | 1111 break; |
| 1112 case kStartCryptoRequired: |
| 1113 SetState(kStateWaitingForMediaCrypto); |
| 1114 break; |
953 case kStartFailed: | 1115 case kStartFailed: |
954 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); | 1116 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |
955 break; | 1117 break; |
956 case kStartOk: | 1118 case kStartOk: |
957 break; | 1119 break; |
958 } | 1120 } |
959 } | 1121 } |
960 | 1122 |
961 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { | 1123 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { |
962 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1124 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
(...skipping 17 matching lines...) Expand all Loading... |
980 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1142 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
981 DVLOG(1) << __FUNCTION__; | 1143 DVLOG(1) << __FUNCTION__; |
982 | 1144 |
983 const bool do_audio = !AudioFinished(); | 1145 const bool do_audio = !AudioFinished(); |
984 const bool do_video = !VideoFinished(); | 1146 const bool do_video = !VideoFinished(); |
985 | 1147 |
986 // If there is nothing to play, the state machine should determine this at the | 1148 // If there is nothing to play, the state machine should determine this at the |
987 // prefetch state and never call this method. | 1149 // prefetch state and never call this method. |
988 DCHECK(do_audio || do_video); | 1150 DCHECK(do_audio || do_video); |
989 | 1151 |
990 // Start with video: if browser seek is required it would | 1152 const bool need_audio_crypto = |
991 // not make sense to configure audio. | 1153 do_audio && audio_decoder_->IsContentEncrypted(); |
| 1154 const bool need_video_crypto = |
| 1155 do_video && video_decoder_->IsContentEncrypted(); |
992 | 1156 |
993 if (do_video) { | 1157 // Do we need to create a local ref from the global ref? |
994 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure(); | 1158 jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr; |
995 switch (status) { | 1159 |
996 case MediaCodecDecoder::kConfigOk: | 1160 if (need_audio_crypto || need_video_crypto) { |
997 break; | 1161 DVLOG(1) << (need_audio_crypto ? " audio" : "") |
998 case MediaCodecDecoder::kConfigKeyFrameRequired: | 1162 << (need_video_crypto ? " video" : "") << " need(s) encryption"; |
999 // TODO(timav): post a task or return the status? | 1163 if (!media_crypto) { |
1000 return kStartBrowserSeekRequired; | 1164 DVLOG(1) << __FUNCTION__ << ": MediaCrypto is not found, returning"; |
1001 case MediaCodecDecoder::kConfigFailure: | 1165 return kStartCryptoRequired; |
1002 return kStartFailed; | |
1003 } | 1166 } |
1004 } | 1167 } |
1005 | 1168 |
1006 if (do_audio) { | 1169 // Start with video: if browser seek is required it would not make sense to |
1007 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); | 1170 // configure audio. |
1008 if (status != MediaCodecDecoder::kConfigOk) { | 1171 |
| 1172 MediaCodecDecoder::ConfigStatus status = MediaCodecDecoder::kConfigOk; |
| 1173 if (do_video) |
| 1174 status = video_decoder_->Configure(media_crypto); |
| 1175 |
| 1176 if (status == MediaCodecDecoder::kConfigOk && do_audio) |
| 1177 status = audio_decoder_->Configure(media_crypto); |
| 1178 |
| 1179 switch (status) { |
| 1180 case MediaCodecDecoder::kConfigOk: |
| 1181 break; |
| 1182 case MediaCodecDecoder::kConfigKeyFrameRequired: |
| 1183 return kStartBrowserSeekRequired; |
| 1184 case MediaCodecDecoder::kConfigFailure: |
1009 return kStartFailed; | 1185 return kStartFailed; |
1010 } | |
1011 } | 1186 } |
1012 | |
1013 return kStartOk; | 1187 return kStartOk; |
1014 } | 1188 } |
1015 | 1189 |
1016 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( | 1190 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( |
1017 bool* preroll_required) { | 1191 bool* preroll_required) { |
1018 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1192 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
1019 | 1193 |
1020 DVLOG(1) << __FUNCTION__ << " current_time:" << GetInterpolatedTime(); | 1194 DVLOG(1) << __FUNCTION__ << " current_time:" << GetInterpolatedTime(); |
1021 | 1195 |
1022 // If requested, preroll is always done in the beginning of the playback, | 1196 // 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... |
1161 | 1335 |
1162 audio_decoder_.reset(new MediaCodecAudioDecoder( | 1336 audio_decoder_.reset(new MediaCodecAudioDecoder( |
1163 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 1337 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |
1164 media_weak_this_, DemuxerStream::AUDIO), | 1338 media_weak_this_, DemuxerStream::AUDIO), |
1165 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 1339 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
1166 DemuxerStream::AUDIO), | 1340 DemuxerStream::AUDIO), |
1167 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, | 1341 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, |
1168 DemuxerStream::AUDIO), | 1342 DemuxerStream::AUDIO), |
1169 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, | 1343 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, |
1170 DemuxerStream::AUDIO), | 1344 DemuxerStream::AUDIO), |
| 1345 base::Bind(&MediaCodecPlayer::OnMissingKeyReported, media_weak_this_, |
| 1346 DemuxerStream::AUDIO), |
1171 internal_error_cb_, | 1347 internal_error_cb_, |
1172 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 1348 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
1173 DemuxerStream::AUDIO))); | 1349 DemuxerStream::AUDIO))); |
1174 | 1350 |
1175 video_decoder_.reset(new MediaCodecVideoDecoder( | 1351 video_decoder_.reset(new MediaCodecVideoDecoder( |
1176 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 1352 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |
1177 media_weak_this_, DemuxerStream::VIDEO), | 1353 media_weak_this_, DemuxerStream::VIDEO), |
1178 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 1354 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
1179 DemuxerStream::VIDEO), | 1355 DemuxerStream::VIDEO), |
1180 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, | 1356 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, |
1181 DemuxerStream::VIDEO), | 1357 DemuxerStream::VIDEO), |
1182 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, | 1358 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, |
1183 DemuxerStream::VIDEO), | 1359 DemuxerStream::VIDEO), |
| 1360 base::Bind(&MediaCodecPlayer::OnMissingKeyReported, media_weak_this_, |
| 1361 DemuxerStream::VIDEO), |
1184 internal_error_cb_, | 1362 internal_error_cb_, |
1185 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 1363 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
1186 DemuxerStream::VIDEO), | 1364 DemuxerStream::VIDEO), |
1187 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), | 1365 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), |
1188 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); | 1366 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); |
1189 } | 1367 } |
1190 | 1368 |
1191 bool MediaCodecPlayer::AudioFinished() const { | 1369 bool MediaCodecPlayer::AudioFinished() const { |
1192 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); | 1370 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); |
1193 } | 1371 } |
(...skipping 16 matching lines...) Expand all Loading... |
1210 | 1388 |
1211 const char* MediaCodecPlayer::AsString(PlayerState state) { | 1389 const char* MediaCodecPlayer::AsString(PlayerState state) { |
1212 switch (state) { | 1390 switch (state) { |
1213 RETURN_STRING(kStatePaused); | 1391 RETURN_STRING(kStatePaused); |
1214 RETURN_STRING(kStateWaitingForConfig); | 1392 RETURN_STRING(kStateWaitingForConfig); |
1215 RETURN_STRING(kStateWaitingForPermission); | 1393 RETURN_STRING(kStateWaitingForPermission); |
1216 RETURN_STRING(kStatePrefetching); | 1394 RETURN_STRING(kStatePrefetching); |
1217 RETURN_STRING(kStatePlaying); | 1395 RETURN_STRING(kStatePlaying); |
1218 RETURN_STRING(kStateStopping); | 1396 RETURN_STRING(kStateStopping); |
1219 RETURN_STRING(kStateWaitingForSurface); | 1397 RETURN_STRING(kStateWaitingForSurface); |
| 1398 RETURN_STRING(kStateWaitingForKey); |
| 1399 RETURN_STRING(kStateWaitingForMediaCrypto); |
1220 RETURN_STRING(kStateWaitingForSeek); | 1400 RETURN_STRING(kStateWaitingForSeek); |
1221 RETURN_STRING(kStateError); | 1401 RETURN_STRING(kStateError); |
1222 } | 1402 } |
1223 return nullptr; // crash early | 1403 return nullptr; // crash early |
1224 } | 1404 } |
1225 | 1405 |
1226 #undef RETURN_STRING | 1406 #undef RETURN_STRING |
1227 | 1407 |
1228 } // namespace media | 1408 } // namespace media |
OLD | NEW |