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