OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_source_player.h" | 5 #include "media/base/android/media_source_player.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
10 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
11 #include "base/barrier_closure.h" | 11 #include "base/barrier_closure.h" |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/bind_helpers.h" |
14 #include "base/callback_helpers.h" | 15 #include "base/callback_helpers.h" |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
17 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
18 #include "media/base/android/audio_decoder_job.h" | 19 #include "media/base/android/audio_decoder_job.h" |
19 #include "media/base/android/media_player_manager.h" | 20 #include "media/base/android/media_player_manager.h" |
20 #include "media/base/android/video_decoder_job.h" | 21 #include "media/base/android/video_decoder_job.h" |
21 #include "media/base/bind_to_current_loop.h" | 22 #include "media/base/bind_to_current_loop.h" |
22 #include "media/base/timestamp_constants.h" | 23 #include "media/base/timestamp_constants.h" |
23 | 24 |
24 namespace media { | 25 namespace media { |
25 | 26 |
26 MediaSourcePlayer::MediaSourcePlayer( | 27 MediaSourcePlayer::MediaSourcePlayer( |
27 int player_id, | 28 int player_id, |
28 MediaPlayerManager* manager, | 29 MediaPlayerManager* manager, |
29 const OnDecoderResourcesReleasedCB& on_decoder_resources_released_cb, | 30 const OnDecoderResourcesReleasedCB& on_decoder_resources_released_cb, |
30 scoped_ptr<DemuxerAndroid> demuxer, | 31 scoped_ptr<DemuxerAndroid> demuxer, |
31 const GURL& frame_url) | 32 const GURL& frame_url) |
32 : MediaPlayerAndroid(player_id, | 33 : MediaPlayerAndroid(player_id, |
33 manager, | 34 manager, |
34 on_decoder_resources_released_cb, | 35 on_decoder_resources_released_cb, |
35 frame_url), | 36 frame_url), |
36 demuxer_(demuxer.Pass()), | 37 demuxer_(demuxer.Pass()), |
37 pending_event_(NO_EVENT_PENDING), | 38 pending_event_(NO_EVENT_PENDING), |
38 playing_(false), | 39 playing_(false), |
39 interpolator_(&default_tick_clock_), | 40 interpolator_(&default_tick_clock_), |
40 doing_browser_seek_(false), | 41 doing_browser_seek_(false), |
41 pending_seek_(false), | 42 pending_seek_(false), |
42 drm_bridge_(NULL), | |
43 cdm_registration_id_(0), | 43 cdm_registration_id_(0), |
44 is_waiting_for_key_(false), | 44 is_waiting_for_key_(false), |
45 key_added_while_decode_pending_(false), | 45 key_added_while_decode_pending_(false), |
46 is_waiting_for_audio_decoder_(false), | 46 is_waiting_for_audio_decoder_(false), |
47 is_waiting_for_video_decoder_(false), | 47 is_waiting_for_video_decoder_(false), |
48 prerolling_(true), | 48 prerolling_(true), |
49 weak_factory_(this) { | 49 weak_factory_(this) { |
50 media_stat_.reset(new MediaStatistics()); | 50 media_stat_.reset(new MediaStatistics()); |
51 | 51 |
52 audio_decoder_job_.reset(new AudioDecoderJob( | 52 audio_decoder_job_.reset(new AudioDecoderJob( |
53 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 53 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
54 base::Unretained(demuxer_.get()), | 54 base::Unretained(demuxer_.get()), |
55 DemuxerStream::AUDIO), | 55 DemuxerStream::AUDIO), |
56 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, | 56 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, |
57 weak_factory_.GetWeakPtr()))); | 57 weak_factory_.GetWeakPtr()))); |
58 video_decoder_job_.reset(new VideoDecoderJob( | 58 video_decoder_job_.reset(new VideoDecoderJob( |
59 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 59 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
60 base::Unretained(demuxer_.get()), | 60 base::Unretained(demuxer_.get()), |
61 DemuxerStream::VIDEO), | 61 DemuxerStream::VIDEO), |
62 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, | 62 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, |
63 weak_factory_.GetWeakPtr()))); | 63 weak_factory_.GetWeakPtr()))); |
64 | 64 |
65 demuxer_->Initialize(this); | 65 demuxer_->Initialize(this); |
66 interpolator_.SetUpperBound(base::TimeDelta()); | 66 interpolator_.SetUpperBound(base::TimeDelta()); |
67 weak_this_ = weak_factory_.GetWeakPtr(); | 67 weak_this_ = weak_factory_.GetWeakPtr(); |
68 } | 68 } |
69 | 69 |
70 MediaSourcePlayer::~MediaSourcePlayer() { | 70 MediaSourcePlayer::~MediaSourcePlayer() { |
71 Release(); | 71 Release(); |
72 DCHECK_EQ(!drm_bridge_, !cdm_registration_id_); | 72 DCHECK_EQ(!cdm_, !cdm_registration_id_); |
73 if (drm_bridge_) { | 73 if (cdm_) { |
74 drm_bridge_->UnregisterPlayer(cdm_registration_id_); | 74 static_cast<MediaDrmBridge*>(cdm_.get()) |
| 75 ->UnregisterPlayer(cdm_registration_id_); |
75 cdm_registration_id_ = 0; | 76 cdm_registration_id_ = 0; |
76 } | 77 } |
77 } | 78 } |
78 | 79 |
79 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { | 80 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
80 DVLOG(1) << __FUNCTION__; | 81 DVLOG(1) << __FUNCTION__; |
81 if (!video_decoder_job_->SetVideoSurface(surface.Pass())) | 82 if (!video_decoder_job_->SetVideoSurface(surface.Pass())) |
82 return; | 83 return; |
83 // Retry video decoder creation. | 84 // Retry video decoder creation. |
84 RetryDecoderCreation(false, true); | 85 RetryDecoderCreation(false, true); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 | 261 |
261 void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) { | 262 void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) { |
262 duration_ = duration; | 263 duration_ = duration; |
263 } | 264 } |
264 | 265 |
265 void MediaSourcePlayer::OnMediaCryptoReady( | 266 void MediaSourcePlayer::OnMediaCryptoReady( |
266 MediaDrmBridge::JavaObjectPtr /* media_crypto */, | 267 MediaDrmBridge::JavaObjectPtr /* media_crypto */, |
267 bool /* needs_protected_surface */) { | 268 bool /* needs_protected_surface */) { |
268 // Callback parameters are ignored in this player. They are intended for | 269 // Callback parameters are ignored in this player. They are intended for |
269 // MediaCodecPlayer which uses a different threading scheme. | 270 // MediaCodecPlayer which uses a different threading scheme. |
270 DCHECK(!drm_bridge_->GetMediaCrypto().is_null()); | 271 DCHECK(!static_cast<MediaDrmBridge*>(cdm_.get())->GetMediaCrypto().is_null()); |
271 | 272 |
272 // Retry decoder creation if the decoders are waiting for MediaCrypto. | 273 // Retry decoder creation if the decoders are waiting for MediaCrypto. |
273 RetryDecoderCreation(true, true); | 274 RetryDecoderCreation(true, true); |
274 } | 275 } |
275 | 276 |
276 void MediaSourcePlayer::SetCdm(BrowserCdm* cdm) { | 277 void MediaSourcePlayer::SetCdm(const scoped_refptr<MediaKeys>& cdm) { |
| 278 DCHECK(cdm); |
| 279 |
277 // Currently we don't support DRM change during the middle of playback, even | 280 // Currently we don't support DRM change during the middle of playback, even |
278 // if the player is paused. | 281 // if the player is paused. |
279 // TODO(qinmin): support DRM change after playback has started. | 282 // TODO(qinmin): support DRM change after playback has started. |
280 // http://crbug.com/253792. | 283 // http://crbug.com/253792. |
281 if (GetCurrentTime() > base::TimeDelta()) { | 284 if (GetCurrentTime() > base::TimeDelta()) { |
282 VLOG(0) << "Setting DRM bridge after playback has started. " | 285 VLOG(0) << "Setting DRM bridge after playback has started. " |
283 << "This is not well supported!"; | 286 << "This is not well supported!"; |
284 } | 287 } |
285 | 288 |
286 if (drm_bridge_) { | 289 if (cdm_) { |
287 NOTREACHED() << "Currently we do not support resetting CDM."; | 290 NOTREACHED() << "Currently we do not support resetting CDM."; |
288 return; | 291 return; |
289 } | 292 } |
290 | 293 |
| 294 cdm_ = cdm; |
| 295 |
291 // Only MediaDrmBridge will be set on MediaSourcePlayer. | 296 // Only MediaDrmBridge will be set on MediaSourcePlayer. |
292 drm_bridge_ = static_cast<MediaDrmBridge*>(cdm); | 297 MediaDrmBridge* drm_bridge = static_cast<MediaDrmBridge*>(cdm_.get()); |
293 | 298 |
294 cdm_registration_id_ = drm_bridge_->RegisterPlayer( | 299 // No need to set |cdm_unset_cb| since |this| holds a reference to the |cdm_|. |
| 300 cdm_registration_id_ = drm_bridge->RegisterPlayer( |
295 base::Bind(&MediaSourcePlayer::OnKeyAdded, weak_this_), | 301 base::Bind(&MediaSourcePlayer::OnKeyAdded, weak_this_), |
296 base::Bind(&MediaSourcePlayer::OnCdmUnset, weak_this_)); | 302 base::Bind(&base::DoNothing)); |
297 | 303 |
298 audio_decoder_job_->SetDrmBridge(drm_bridge_); | 304 audio_decoder_job_->SetDrmBridge(drm_bridge); |
299 video_decoder_job_->SetDrmBridge(drm_bridge_); | 305 video_decoder_job_->SetDrmBridge(drm_bridge); |
300 | 306 |
301 if (drm_bridge_->GetMediaCrypto().is_null()) { | 307 if (drm_bridge->GetMediaCrypto().is_null()) { |
| 308 // Use BindToCurrentLoop to avoid reentrancy. |
302 MediaDrmBridge::MediaCryptoReadyCB cb = BindToCurrentLoop( | 309 MediaDrmBridge::MediaCryptoReadyCB cb = BindToCurrentLoop( |
303 base::Bind(&MediaSourcePlayer::OnMediaCryptoReady, weak_this_)); | 310 base::Bind(&MediaSourcePlayer::OnMediaCryptoReady, weak_this_)); |
304 drm_bridge_->SetMediaCryptoReadyCB(cb); | 311 drm_bridge->SetMediaCryptoReadyCB(cb); |
305 return; | 312 return; |
306 } | 313 } |
307 | 314 |
308 // If the player is previously waiting for CDM, retry decoder creation. | 315 // If the player is previously waiting for CDM, retry decoder creation. |
309 RetryDecoderCreation(true, true); | 316 RetryDecoderCreation(true, true); |
310 } | 317 } |
311 | 318 |
312 void MediaSourcePlayer::OnDemuxerSeekDone( | 319 void MediaSourcePlayer::OnDemuxerSeekDone( |
313 base::TimeDelta actual_browser_seek_time) { | 320 base::TimeDelta actual_browser_seek_time) { |
314 DVLOG(1) << __FUNCTION__; | 321 DVLOG(1) << __FUNCTION__; |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 | 835 |
829 is_waiting_for_key_ = false; | 836 is_waiting_for_key_ = false; |
830 key_added_while_decode_pending_ = false; | 837 key_added_while_decode_pending_ = false; |
831 | 838 |
832 // StartInternal() will trigger a prefetch, where in most cases we'll just | 839 // StartInternal() will trigger a prefetch, where in most cases we'll just |
833 // use previously received data. | 840 // use previously received data. |
834 if (playing_) | 841 if (playing_) |
835 StartInternal(); | 842 StartInternal(); |
836 } | 843 } |
837 | 844 |
838 void MediaSourcePlayer::OnCdmUnset() { | |
839 DVLOG(1) << __FUNCTION__; | |
840 DCHECK(drm_bridge_); | |
841 // TODO(xhwang): Currently this is only called during teardown. Support full | |
842 // detachment of CDM during playback. This will be needed when we start to | |
843 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release | |
844 // MediaDrm when the video is paused, or when the device goes to sleep (see | |
845 // http://crbug.com/272421). | |
846 audio_decoder_job_->SetDrmBridge(NULL); | |
847 video_decoder_job_->SetDrmBridge(NULL); | |
848 cdm_registration_id_ = 0; | |
849 drm_bridge_ = NULL; | |
850 } | |
851 | |
852 } // namespace media | 845 } // namespace media |
OLD | NEW |