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

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

Issue 254473010: Refactor MSE implementation on Android to simplify the logic and improve the performance (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressing comments on unit tests Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
(...skipping 17 matching lines...) Expand all
28 MediaPlayerManager* manager, 28 MediaPlayerManager* manager,
29 const RequestMediaResourcesCB& request_media_resources_cb, 29 const RequestMediaResourcesCB& request_media_resources_cb,
30 const ReleaseMediaResourcesCB& release_media_resources_cb, 30 const ReleaseMediaResourcesCB& release_media_resources_cb,
31 scoped_ptr<DemuxerAndroid> demuxer) 31 scoped_ptr<DemuxerAndroid> demuxer)
32 : MediaPlayerAndroid(player_id, 32 : MediaPlayerAndroid(player_id,
33 manager, 33 manager,
34 request_media_resources_cb, 34 request_media_resources_cb,
35 release_media_resources_cb), 35 release_media_resources_cb),
36 demuxer_(demuxer.Pass()), 36 demuxer_(demuxer.Pass()),
37 pending_event_(NO_EVENT_PENDING), 37 pending_event_(NO_EVENT_PENDING),
38 width_(0),
39 height_(0),
40 audio_codec_(kUnknownAudioCodec),
41 video_codec_(kUnknownVideoCodec),
42 num_channels_(0),
43 sampling_rate_(0),
44 reached_audio_eos_(false),
45 reached_video_eos_(false),
46 playing_(false), 38 playing_(false),
47 is_audio_encrypted_(false),
48 is_video_encrypted_(false),
49 volume_(-1.0),
50 clock_(&default_tick_clock_), 39 clock_(&default_tick_clock_),
51 next_video_data_is_iframe_(true),
52 doing_browser_seek_(false), 40 doing_browser_seek_(false),
53 pending_seek_(false), 41 pending_seek_(false),
54 reconfig_audio_decoder_(false),
55 reconfig_video_decoder_(false),
56 drm_bridge_(NULL), 42 drm_bridge_(NULL),
57 cdm_registration_id_(0), 43 cdm_registration_id_(0),
58 is_waiting_for_key_(false), 44 is_waiting_for_key_(false),
59 has_pending_audio_data_request_(false), 45 is_waiting_for_audio_decoder_(false),
60 has_pending_video_data_request_(false), 46 is_waiting_for_video_decoder_(false),
61 weak_factory_(this) { 47 weak_factory_(this) {
48 audio_decoder_job_.reset(new AudioDecoderJob(
49 base::Bind(&DemuxerAndroid::RequestDemuxerData,
50 base::Unretained(demuxer_.get()),
51 DemuxerStream::AUDIO),
52 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged,
53 weak_factory_.GetWeakPtr())));
54 video_decoder_job_.reset(new VideoDecoderJob(
55 base::Bind(&DemuxerAndroid::RequestDemuxerData,
56 base::Unretained(demuxer_.get()),
57 DemuxerStream::VIDEO),
58 base::Bind(request_media_resources_cb_, player_id),
59 base::Bind(release_media_resources_cb_, player_id),
60 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged,
61 weak_factory_.GetWeakPtr())));
62 demuxer_->Initialize(this); 62 demuxer_->Initialize(this);
63 clock_.SetMaxTime(base::TimeDelta()); 63 clock_.SetMaxTime(base::TimeDelta());
64 weak_this_ = weak_factory_.GetWeakPtr(); 64 weak_this_ = weak_factory_.GetWeakPtr();
65 } 65 }
66 66
67 MediaSourcePlayer::~MediaSourcePlayer() { 67 MediaSourcePlayer::~MediaSourcePlayer() {
68 Release(); 68 Release();
69 DCHECK_EQ(!drm_bridge_, !cdm_registration_id_); 69 DCHECK_EQ(!drm_bridge_, !cdm_registration_id_);
70 if (drm_bridge_) { 70 if (drm_bridge_) {
71 drm_bridge_->UnregisterPlayer(cdm_registration_id_); 71 drm_bridge_->UnregisterPlayer(cdm_registration_id_);
72 cdm_registration_id_ = 0; 72 cdm_registration_id_ = 0;
73 } 73 }
74 } 74 }
75 75
76 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { 76 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) {
77 // For an empty surface, always pass it to the decoder job so that it 77 DVLOG(1) << __FUNCTION__;
78 // can detach from the current one. Otherwise, don't pass an unprotected 78 if (!video_decoder_job_->SetVideoSurface(surface.Pass()))
79 // surface if the video content requires a protected one.
80 if (!surface.IsEmpty() &&
81 IsProtectedSurfaceRequired() && !surface.is_protected()) {
82 return; 79 return;
83 } 80 // Retry video decoder creation.
84 81 RetryDecoderCreation(false, true);
85 surface_ = surface.Pass();
86 is_surface_in_use_ = true;
87
88 // If there is a pending surface change event, just wait for it to be
89 // processed.
90 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING))
91 return;
92
93 // Eventual processing of surface change will take care of feeding the new
94 // video decoder initially with I-frame. See b/8950387.
95 SetPendingEvent(SURFACE_CHANGE_EVENT_PENDING);
96
97 // If seek is already pending, processing of the pending surface change
98 // event will occur in OnDemuxerSeekDone().
99 if (IsEventPending(SEEK_EVENT_PENDING))
100 return;
101
102 // If video config change is already pending, processing of the pending
103 // surface change event will occur in OnDemuxerConfigsAvailable().
104 if (reconfig_video_decoder_ && IsEventPending(CONFIG_CHANGE_EVENT_PENDING))
105 return;
106
107 // Otherwise we need to trigger pending event processing now.
108 ProcessPendingEvents();
109 } 82 }
110 83
111 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( 84 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding(
112 base::TimeDelta seek_time) { 85 base::TimeDelta seek_time) {
113 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; 86 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")";
114 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); 87 DCHECK(!IsEventPending(SEEK_EVENT_PENDING));
115 88
116 pending_seek_ = false; 89 pending_seek_ = false;
117 90
118 clock_.SetTime(seek_time, seek_time); 91 clock_.SetTime(seek_time, seek_time);
119 92
120 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) 93 if (audio_decoder_job_->is_decoding())
121 audio_decoder_job_->StopDecode(); 94 audio_decoder_job_->StopDecode();
122 if (video_decoder_job_ && video_decoder_job_->is_decoding()) 95 if (video_decoder_job_->is_decoding())
123 video_decoder_job_->StopDecode(); 96 video_decoder_job_->StopDecode();
124 97
125 SetPendingEvent(SEEK_EVENT_PENDING); 98 SetPendingEvent(SEEK_EVENT_PENDING);
126 ProcessPendingEvents(); 99 ProcessPendingEvents();
127 } 100 }
128 101
129 void MediaSourcePlayer::BrowserSeekToCurrentTime() { 102 void MediaSourcePlayer::BrowserSeekToCurrentTime() {
130 DVLOG(1) << __FUNCTION__; 103 DVLOG(1) << __FUNCTION__;
131 104
132 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); 105 DCHECK(!IsEventPending(SEEK_EVENT_PENDING));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 // MediaDecoderCallback() is called. 137 // MediaDecoderCallback() is called.
165 playing_ = false; 138 playing_ = false;
166 start_time_ticks_ = base::TimeTicks(); 139 start_time_ticks_ = base::TimeTicks();
167 } 140 }
168 141
169 bool MediaSourcePlayer::IsPlaying() { 142 bool MediaSourcePlayer::IsPlaying() {
170 return playing_; 143 return playing_;
171 } 144 }
172 145
173 int MediaSourcePlayer::GetVideoWidth() { 146 int MediaSourcePlayer::GetVideoWidth() {
174 return width_; 147 return video_decoder_job_->width();
175 } 148 }
176 149
177 int MediaSourcePlayer::GetVideoHeight() { 150 int MediaSourcePlayer::GetVideoHeight() {
178 return height_; 151 return video_decoder_job_->height();
179 } 152 }
180 153
181 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) { 154 void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) {
182 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")"; 155 DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")";
183 156
184 if (IsEventPending(SEEK_EVENT_PENDING)) { 157 if (IsEventPending(SEEK_EVENT_PENDING)) {
185 DCHECK(doing_browser_seek_) << "SeekTo while SeekTo in progress"; 158 DCHECK(doing_browser_seek_) << "SeekTo while SeekTo in progress";
186 DCHECK(!pending_seek_) << "SeekTo while SeekTo pending browser seek"; 159 DCHECK(!pending_seek_) << "SeekTo while SeekTo pending browser seek";
187 160
188 // There is a browser seek currently in progress to obtain I-frame to feed 161 // There is a browser seek currently in progress to obtain I-frame to feed
(...skipping 12 matching lines...) Expand all
201 return clock_.Elapsed(); 174 return clock_.Elapsed();
202 } 175 }
203 176
204 base::TimeDelta MediaSourcePlayer::GetDuration() { 177 base::TimeDelta MediaSourcePlayer::GetDuration() {
205 return duration_; 178 return duration_;
206 } 179 }
207 180
208 void MediaSourcePlayer::Release() { 181 void MediaSourcePlayer::Release() {
209 DVLOG(1) << __FUNCTION__; 182 DVLOG(1) << __FUNCTION__;
210 183
211 // Allow pending seeks and config changes to survive this Release().
212 // If previously pending a prefetch done event, or a job was still decoding,
213 // then at end of Release() we need to ProcessPendingEvents() to process any
214 // seek or config change that was blocked by the prefetch or decode.
215 // TODO(qinmin/wolenetz): Maintain channel state to not double-request data
216 // or drop data received across Release()+Start(). See http://crbug.com/306314
217 // and http://crbug.com/304234.
218 bool process_pending_events = false;
219 process_pending_events = IsEventPending(PREFETCH_DONE_EVENT_PENDING) ||
220 (audio_decoder_job_ && audio_decoder_job_->is_decoding()) ||
221 (video_decoder_job_ && video_decoder_job_->is_decoding());
222
223 // Clear all the pending events except seeks and config changes.
224 pending_event_ &= (SEEK_EVENT_PENDING | CONFIG_CHANGE_EVENT_PENDING);
225 is_surface_in_use_ = false; 184 is_surface_in_use_ = false;
226 ResetAudioDecoderJob(); 185 audio_decoder_job_->ReleaseDecoderResources();
227 ResetVideoDecoderJob(); 186 video_decoder_job_->ReleaseDecoderResources();
228
229 // Prevent job re-creation attempts in OnDemuxerConfigsAvailable()
230 reconfig_audio_decoder_ = false;
231 reconfig_video_decoder_ = false;
232 187
233 // Prevent player restart, including job re-creation attempts. 188 // Prevent player restart, including job re-creation attempts.
234 playing_ = false; 189 playing_ = false;
235 190
236 decoder_starvation_callback_.Cancel(); 191 decoder_starvation_callback_.Cancel();
237 surface_ = gfx::ScopedJavaSurface();
238 if (process_pending_events) {
239 DVLOG(1) << __FUNCTION__ << " : Resuming seek or config change processing";
240 ProcessPendingEvents();
241 }
242 } 192 }
243 193
244 void MediaSourcePlayer::SetVolume(double volume) { 194 void MediaSourcePlayer::SetVolume(double volume) {
245 volume_ = volume; 195 audio_decoder_job_->SetVolume(volume);
246 SetVolumeInternal();
247 } 196 }
248 197
249 bool MediaSourcePlayer::IsSurfaceInUse() const { 198 bool MediaSourcePlayer::IsSurfaceInUse() const {
250 return is_surface_in_use_; 199 return is_surface_in_use_;
251 } 200 }
252 201
253 bool MediaSourcePlayer::CanPause() { 202 bool MediaSourcePlayer::CanPause() {
254 return Seekable(); 203 return Seekable();
255 } 204 }
256 205
(...skipping 13 matching lines...) Expand all
270 DVLOG(1) << __FUNCTION__; 219 DVLOG(1) << __FUNCTION__;
271 // If there are pending events, wait for them finish. 220 // If there are pending events, wait for them finish.
272 if (pending_event_ != NO_EVENT_PENDING) 221 if (pending_event_ != NO_EVENT_PENDING)
273 return; 222 return;
274 223
275 // When we start, we'll have new demuxed data coming in. This new data could 224 // When we start, we'll have new demuxed data coming in. This new data could
276 // be clear (not encrypted) or encrypted with different keys. So 225 // be clear (not encrypted) or encrypted with different keys. So
277 // |is_waiting_for_key_| condition may not be true anymore. 226 // |is_waiting_for_key_| condition may not be true anymore.
278 is_waiting_for_key_ = false; 227 is_waiting_for_key_ = false;
279 228
280 // Create decoder jobs if they are not created
281 ConfigureAudioDecoderJob();
282 ConfigureVideoDecoderJob();
283
284 // If one of the decoder job is not ready, do nothing.
285 if ((HasAudio() && !audio_decoder_job_) ||
286 (HasVideo() && !video_decoder_job_)) {
287 return;
288 }
289
290 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 229 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
291 ProcessPendingEvents(); 230 ProcessPendingEvents();
292 } 231 }
293 232
294 void MediaSourcePlayer::OnDemuxerConfigsAvailable( 233 void MediaSourcePlayer::OnDemuxerConfigsAvailable(
295 const DemuxerConfigs& configs) { 234 const DemuxerConfigs& configs) {
296 DVLOG(1) << __FUNCTION__; 235 DVLOG(1) << __FUNCTION__;
297 DCHECK(!HasAudio() && !HasVideo()); 236 DCHECK(!HasAudio() && !HasVideo());
298 duration_ = configs.duration; 237 duration_ = configs.duration;
299 clock_.SetDuration(duration_); 238 clock_.SetDuration(duration_);
300 239
301 SetDemuxerConfigs(configs, true); 240 audio_decoder_job_->SetDemuxerConfigs(configs);
302 SetDemuxerConfigs(configs, false); 241 video_decoder_job_->SetDemuxerConfigs(configs);
303 242 OnDemuxerConfigsChanged();
304 manager()->OnMediaMetadataChanged(
305 player_id(), duration_, width_, height_, true);
306 } 243 }
307 244
308 void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) { 245 void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) {
309 DVLOG(1) << __FUNCTION__ << "(" << data.type << ")"; 246 DVLOG(1) << __FUNCTION__ << "(" << data.type << ")";
310 DCHECK_LT(0u, data.access_units.size()); 247 DCHECK_LT(0u, data.access_units.size());
311 CHECK_GE(1u, data.demuxer_configs.size()); 248 CHECK_GE(1u, data.demuxer_configs.size());
312 249
313 if (has_pending_audio_data_request_ && data.type == DemuxerStream::AUDIO) { 250 if (data.type == DemuxerStream::AUDIO)
314 has_pending_audio_data_request_ = false;
315 ProcessPendingEvents();
316 return;
317 }
318
319 if (has_pending_video_data_request_ && data.type == DemuxerStream::VIDEO) {
320 next_video_data_is_iframe_ = false;
321 has_pending_video_data_request_ = false;
322 ProcessPendingEvents();
323 return;
324 }
325
326 if (data.type == DemuxerStream::AUDIO && audio_decoder_job_) {
327 audio_decoder_job_->OnDataReceived(data); 251 audio_decoder_job_->OnDataReceived(data);
328 } else if (data.type == DemuxerStream::VIDEO) { 252 else if (data.type == DemuxerStream::VIDEO)
329 next_video_data_is_iframe_ = false; 253 video_decoder_job_->OnDataReceived(data);
330 if (video_decoder_job_)
331 video_decoder_job_->OnDataReceived(data);
332 }
333 } 254 }
334 255
335 void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) { 256 void MediaSourcePlayer::OnDemuxerDurationChanged(base::TimeDelta duration) {
336 duration_ = duration; 257 duration_ = duration;
337 clock_.SetDuration(duration_); 258 clock_.SetDuration(duration_);
338 } 259 }
339 260
340 base::android::ScopedJavaLocalRef<jobject> MediaSourcePlayer::GetMediaCrypto() {
341 base::android::ScopedJavaLocalRef<jobject> media_crypto;
342 if (drm_bridge_)
343 media_crypto = drm_bridge_->GetMediaCrypto();
344 return media_crypto;
345 }
346
347 void MediaSourcePlayer::OnMediaCryptoReady() { 261 void MediaSourcePlayer::OnMediaCryptoReady() {
348 DCHECK(!drm_bridge_->GetMediaCrypto().is_null()); 262 DCHECK(!drm_bridge_->GetMediaCrypto().is_null());
349 drm_bridge_->SetMediaCryptoReadyCB(base::Closure()); 263 drm_bridge_->SetMediaCryptoReadyCB(base::Closure());
350 264
351 if (playing_) 265 // Retry decoder creation if the decoders are waiting for MediaCrypto.
352 StartInternal(); 266 RetryDecoderCreation(true, true);
353 } 267 }
354 268
355 void MediaSourcePlayer::SetCdm(BrowserCdm* cdm) { 269 void MediaSourcePlayer::SetCdm(BrowserCdm* cdm) {
356 // Currently we don't support DRM change during the middle of playback, even 270 // Currently we don't support DRM change during the middle of playback, even
357 // if the player is paused. 271 // if the player is paused.
358 // TODO(qinmin): support DRM change after playback has started. 272 // TODO(qinmin): support DRM change after playback has started.
359 // http://crbug.com/253792. 273 // http://crbug.com/253792.
360 if (GetCurrentTime() > base::TimeDelta()) { 274 if (GetCurrentTime() > base::TimeDelta()) {
361 VLOG(0) << "Setting DRM bridge after playback has started. " 275 VLOG(0) << "Setting DRM bridge after playback has started. "
362 << "This is not well supported!"; 276 << "This is not well supported!";
363 } 277 }
364 278
365 if (drm_bridge_) { 279 if (drm_bridge_) {
366 NOTREACHED() << "Currently we do not support resetting CDM."; 280 NOTREACHED() << "Currently we do not support resetting CDM.";
367 return; 281 return;
368 } 282 }
369 283
370 // Only MediaDrmBridge will be set on MediaSourcePlayer. 284 // Only MediaDrmBridge will be set on MediaSourcePlayer.
371 drm_bridge_ = static_cast<MediaDrmBridge*>(cdm); 285 drm_bridge_ = static_cast<MediaDrmBridge*>(cdm);
372 286
373 cdm_registration_id_ = drm_bridge_->RegisterPlayer( 287 cdm_registration_id_ = drm_bridge_->RegisterPlayer(
374 base::Bind(&MediaSourcePlayer::OnKeyAdded, weak_this_), 288 base::Bind(&MediaSourcePlayer::OnKeyAdded, weak_this_),
375 base::Bind(&MediaSourcePlayer::OnCdmUnset, weak_this_)); 289 base::Bind(&MediaSourcePlayer::OnCdmUnset, weak_this_));
376 290
291 audio_decoder_job_->SetDrmBridge(drm_bridge_);
wolenetz 2014/06/04 21:42:24 Should these two be done prior to registering the
qinmin 2014/06/04 22:34:03 This won't happen. RegisterPlayer() is a simple fu
292 video_decoder_job_->SetDrmBridge(drm_bridge_);
293
377 if (drm_bridge_->GetMediaCrypto().is_null()) { 294 if (drm_bridge_->GetMediaCrypto().is_null()) {
378 drm_bridge_->SetMediaCryptoReadyCB( 295 drm_bridge_->SetMediaCryptoReadyCB(
379 base::Bind(&MediaSourcePlayer::OnMediaCryptoReady, weak_this_)); 296 base::Bind(&MediaSourcePlayer::OnMediaCryptoReady, weak_this_));
380 return; 297 return;
381 } 298 }
382 299
383 if (playing_) 300 // If the player is previously waiting for CDM, retry decoder creation.
384 StartInternal(); 301 RetryDecoderCreation(true, true);
385 } 302 }
386 303
387 void MediaSourcePlayer::OnDemuxerSeekDone( 304 void MediaSourcePlayer::OnDemuxerSeekDone(
388 base::TimeDelta actual_browser_seek_time) { 305 base::TimeDelta actual_browser_seek_time) {
389 DVLOG(1) << __FUNCTION__; 306 DVLOG(1) << __FUNCTION__;
390 307
391 ClearPendingEvent(SEEK_EVENT_PENDING); 308 ClearPendingEvent(SEEK_EVENT_PENDING);
392 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) 309 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING))
393 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 310 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
394 311
395 next_video_data_is_iframe_ = true;
396
397 if (pending_seek_) { 312 if (pending_seek_) {
398 DVLOG(1) << __FUNCTION__ << "processing pending seek"; 313 DVLOG(1) << __FUNCTION__ << "processing pending seek";
399 DCHECK(doing_browser_seek_); 314 DCHECK(doing_browser_seek_);
400 pending_seek_ = false; 315 pending_seek_ = false;
401 SeekTo(pending_seek_time_); 316 SeekTo(pending_seek_time_);
402 return; 317 return;
403 } 318 }
404 319
405 // It is possible that a browser seek to I-frame had to seek to a buffered 320 // It is possible that a browser seek to I-frame had to seek to a buffered
406 // I-frame later than the requested one due to data removal or GC. Update 321 // I-frame later than the requested one due to data removal or GC. Update
407 // player clock to the actual seek target. 322 // player clock to the actual seek target.
408 if (doing_browser_seek_) { 323 if (doing_browser_seek_) {
409 DCHECK(actual_browser_seek_time != kNoTimestamp()); 324 DCHECK(actual_browser_seek_time != kNoTimestamp());
410 base::TimeDelta seek_time = actual_browser_seek_time; 325 base::TimeDelta seek_time = actual_browser_seek_time;
411 // A browser seek must not jump into the past. Ideally, it seeks to the 326 // A browser seek must not jump into the past. Ideally, it seeks to the
412 // requested time, but it might jump into the future. 327 // requested time, but it might jump into the future.
413 DCHECK(seek_time >= GetCurrentTime()); 328 DCHECK(seek_time >= GetCurrentTime());
414 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " 329 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: "
415 << seek_time.InSecondsF(); 330 << seek_time.InSecondsF();
416 clock_.SetTime(seek_time, seek_time); 331 clock_.SetTime(seek_time, seek_time);
417 if (audio_decoder_job_) 332 audio_decoder_job_->SetBaseTimestamp(seek_time);
418 audio_decoder_job_->SetBaseTimestamp(seek_time);
419 } else { 333 } else {
420 DCHECK(actual_browser_seek_time == kNoTimestamp()); 334 DCHECK(actual_browser_seek_time == kNoTimestamp());
421 } 335 }
422 336
423 reached_audio_eos_ = false;
424 reached_video_eos_ = false;
425
426 base::TimeDelta current_time = GetCurrentTime(); 337 base::TimeDelta current_time = GetCurrentTime();
427 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| 338 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_|
428 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| 339 // to preroll media decoder jobs. Currently |start_presentation_timestamp_|
429 // is calculated from decoder output, while preroll relies on the access 340 // is calculated from decoder output, while preroll relies on the access
430 // unit's timestamp. There are some differences between the two. 341 // unit's timestamp. There are some differences between the two.
431 preroll_timestamp_ = current_time; 342 preroll_timestamp_ = current_time;
432 if (audio_decoder_job_) 343 if (HasAudio())
433 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); 344 audio_decoder_job_->BeginPrerolling(preroll_timestamp_);
434 if (video_decoder_job_) 345 if (HasVideo())
435 video_decoder_job_->BeginPrerolling(preroll_timestamp_); 346 video_decoder_job_->BeginPrerolling(preroll_timestamp_);
436 347
437 if (!doing_browser_seek_) 348 if (!doing_browser_seek_)
438 manager()->OnSeekComplete(player_id(), current_time); 349 manager()->OnSeekComplete(player_id(), current_time);
439 350
440 ProcessPendingEvents(); 351 ProcessPendingEvents();
441 } 352 }
442 353
443 void MediaSourcePlayer::UpdateTimestamps( 354 void MediaSourcePlayer::UpdateTimestamps(
444 base::TimeDelta current_presentation_timestamp, 355 base::TimeDelta current_presentation_timestamp,
445 base::TimeDelta max_presentation_timestamp) { 356 base::TimeDelta max_presentation_timestamp) {
446 clock_.SetTime(current_presentation_timestamp, max_presentation_timestamp); 357 clock_.SetTime(current_presentation_timestamp, max_presentation_timestamp);
447
448 manager()->OnTimeUpdate(player_id(), GetCurrentTime()); 358 manager()->OnTimeUpdate(player_id(), GetCurrentTime());
449 } 359 }
450 360
451 void MediaSourcePlayer::ProcessPendingEvents() { 361 void MediaSourcePlayer::ProcessPendingEvents() {
452 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_; 362 DVLOG(1) << __FUNCTION__ << " : 0x" << std::hex << pending_event_;
453 // Wait for all the decoding jobs to finish before processing pending tasks. 363 // Wait for all the decoding jobs to finish before processing pending tasks.
454 if (video_decoder_job_ && video_decoder_job_->is_decoding()) { 364 if (video_decoder_job_->is_decoding()) {
455 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding."; 365 DVLOG(1) << __FUNCTION__ << " : A video job is still decoding.";
456 return; 366 return;
457 } 367 }
458 368
459 if (audio_decoder_job_ && audio_decoder_job_->is_decoding()) { 369 if (audio_decoder_job_->is_decoding()) {
460 DVLOG(1) << __FUNCTION__ << " : An audio job is still decoding."; 370 DVLOG(1) << __FUNCTION__ << " : An audio job is still decoding.";
461 return; 371 return;
462 } 372 }
463 373
464 if (has_pending_audio_data_request_ || has_pending_video_data_request_) {
465 DVLOG(1) << __FUNCTION__ << " : has pending data request.";
466 return;
467 }
468
469 if (IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { 374 if (IsEventPending(PREFETCH_DONE_EVENT_PENDING)) {
470 DVLOG(1) << __FUNCTION__ << " : PREFETCH_DONE still pending."; 375 DVLOG(1) << __FUNCTION__ << " : PREFETCH_DONE still pending.";
471 return; 376 return;
472 } 377 }
473 378
474 if (IsEventPending(SEEK_EVENT_PENDING)) { 379 if (IsEventPending(SEEK_EVENT_PENDING)) {
475 DVLOG(1) << __FUNCTION__ << " : Handling SEEK_EVENT"; 380 DVLOG(1) << __FUNCTION__ << " : Handling SEEK_EVENT";
476 ClearDecodingData(); 381 ClearDecodingData();
477 if (audio_decoder_job_) 382 audio_decoder_job_->SetBaseTimestamp(GetCurrentTime());
478 audio_decoder_job_->SetBaseTimestamp(GetCurrentTime());
479 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_); 383 demuxer_->RequestDemuxerSeek(GetCurrentTime(), doing_browser_seek_);
480 return; 384 return;
481 } 385 }
482 386
483 start_time_ticks_ = base::TimeTicks(); 387 if (IsEventPending(DECODER_CREATION_EVENT_PENDING)) {
484 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { 388 // Don't continue if one of the decoder is not created.
485 DVLOG(1) << __FUNCTION__ << " : Handling CONFIG_CHANGE_EVENT."; 389 if (is_waiting_for_audio_decoder_ || is_waiting_for_video_decoder_)
486 DCHECK(reconfig_audio_decoder_ || reconfig_video_decoder_);
487 manager()->OnMediaMetadataChanged(
488 player_id(), duration_, width_, height_, true);
489
490 if (reconfig_audio_decoder_)
491 ConfigureAudioDecoderJob();
492
493 if (reconfig_video_decoder_)
494 ConfigureVideoDecoderJob();
495
496 ClearPendingEvent(CONFIG_CHANGE_EVENT_PENDING);
497 }
498
499 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING)) {
500 DVLOG(1) << __FUNCTION__ << " : Handling SURFACE_CHANGE_EVENT.";
501 // Setting a new surface will require a new MediaCodec to be created.
502 ResetVideoDecoderJob();
503 ConfigureVideoDecoderJob();
504
505 // Return early if we can't successfully configure a new video decoder job
506 // yet.
507 if (HasVideo() && !video_decoder_job_)
508 return; 390 return;
391 ClearPendingEvent(DECODER_CREATION_EVENT_PENDING);
509 } 392 }
510 393
511 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { 394 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) {
512 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; 395 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT.";
513 // If one of the decoder is not initialized, cancel this event as it will be
514 // called later when Start() is called again.
515 if ((HasVideo() && !video_decoder_job_) ||
516 (HasAudio() && !audio_decoder_job_)) {
517 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
518 return;
519 }
520
521 DCHECK(audio_decoder_job_ || AudioFinished());
522 DCHECK(video_decoder_job_ || VideoFinished());
523 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); 396 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1);
524 397
525 // It is possible that all streams have finished decode, yet starvation 398 // It is possible that all streams have finished decode, yet starvation
526 // occurred during the last stream's EOS decode. In this case, prefetch is a 399 // occurred during the last stream's EOS decode. In this case, prefetch is a
527 // no-op. 400 // no-op.
528 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 401 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
529 if (count == 0) 402 if (count == 0)
530 return; 403 return;
531 404
532 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING); 405 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); 463 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING));
591 464
592 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of 465 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of
593 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process 466 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process
594 // any other pending events only after handling EOS detection. 467 // any other pending events only after handling EOS detection.
595 if (IsEventPending(SEEK_EVENT_PENDING)) { 468 if (IsEventPending(SEEK_EVENT_PENDING)) {
596 ProcessPendingEvents(); 469 ProcessPendingEvents();
597 return; 470 return;
598 } 471 }
599 472
600 if (status == MEDIA_CODEC_OK && is_clock_manager && 473 if ((status == MEDIA_CODEC_OK || status == MEDIA_CODEC_INPUT_END_OF_STREAM) &&
601 current_presentation_timestamp != kNoTimestamp()) { 474 is_clock_manager && current_presentation_timestamp != kNoTimestamp()) {
602 UpdateTimestamps( 475 UpdateTimestamps(current_presentation_timestamp,
603 current_presentation_timestamp, max_presentation_timestamp); 476 max_presentation_timestamp);
604 } 477 }
605 478
606 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) 479 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM)
607 PlaybackCompleted(is_audio); 480 PlaybackCompleted(is_audio);
608 481
609 if (pending_event_ != NO_EVENT_PENDING) { 482 if (pending_event_ != NO_EVENT_PENDING) {
610 ProcessPendingEvents(); 483 ProcessPendingEvents();
611 return; 484 return;
612 } 485 }
613 486
(...skipping 25 matching lines...) Expand all
639 StartStarvationCallback(current_presentation_timestamp, 512 StartStarvationCallback(current_presentation_timestamp,
640 max_presentation_timestamp); 513 max_presentation_timestamp);
641 else 514 else
642 start_time_ticks_ = base::TimeTicks::Now(); 515 start_time_ticks_ = base::TimeTicks::Now();
643 } 516 }
644 517
645 if (is_audio) 518 if (is_audio)
646 DecodeMoreAudio(); 519 DecodeMoreAudio();
647 else 520 else
648 DecodeMoreVideo(); 521 DecodeMoreVideo();
649
650 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING))
651 ProcessPendingEvents();
652 } 522 }
653 523
654 void MediaSourcePlayer::DecodeMoreAudio() { 524 void MediaSourcePlayer::DecodeMoreAudio() {
655 DVLOG(1) << __FUNCTION__; 525 DVLOG(1) << __FUNCTION__;
656 DCHECK(!audio_decoder_job_->is_decoding()); 526 DCHECK(!audio_decoder_job_->is_decoding());
657 DCHECK(!AudioFinished()); 527 DCHECK(!AudioFinished());
658 528
659 scoped_ptr<DemuxerConfigs> configs(audio_decoder_job_->Decode( 529 if (audio_decoder_job_->Decode(
660 start_time_ticks_, 530 start_time_ticks_,
661 start_presentation_timestamp_, 531 start_presentation_timestamp_,
662 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, weak_this_, true))); 532 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, weak_this_, true))) {
663 if (!configs) {
664 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", 533 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio",
665 audio_decoder_job_.get()); 534 audio_decoder_job_.get());
666 return; 535 return;
667 } 536 }
668 537
669 // Failed to start the next decode. 538 is_waiting_for_audio_decoder_ = true;
670 DCHECK(!reconfig_audio_decoder_); 539 if (!IsEventPending(DECODER_CREATION_EVENT_PENDING))
671 reconfig_audio_decoder_ = true; 540 SetPendingEvent(DECODER_CREATION_EVENT_PENDING);
672 SetDemuxerConfigs(*configs, true);
673
674 // Config change may have just been detected on the other stream. If so,
675 // don't send a duplicate demuxer config request.
676 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) {
677 DCHECK(reconfig_video_decoder_);
678 return;
679 }
680
681 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING);
682 } 541 }
683 542
684 void MediaSourcePlayer::DecodeMoreVideo() { 543 void MediaSourcePlayer::DecodeMoreVideo() {
685 DVLOG(1) << __FUNCTION__; 544 DVLOG(1) << __FUNCTION__;
686 DCHECK(!video_decoder_job_->is_decoding()); 545 DCHECK(!video_decoder_job_->is_decoding());
687 DCHECK(!VideoFinished()); 546 DCHECK(!VideoFinished());
688 547
689 scoped_ptr<DemuxerConfigs> configs(video_decoder_job_->Decode( 548 if (video_decoder_job_->Decode(
690 start_time_ticks_, 549 start_time_ticks_,
691 start_presentation_timestamp_, 550 start_presentation_timestamp_,
692 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, weak_this_, false))); 551 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, weak_this_,
693 if (!configs) { 552 false))) {
694 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", 553 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo",
695 video_decoder_job_.get()); 554 video_decoder_job_.get());
696 return; 555 return;
697 } 556 }
698 557
699 // Failed to start the next decode. 558 // If the decoder is waiting for iframe, trigger a browser seek.
700 // After this detection of video config change, next video data received 559 if (!video_decoder_job_->next_video_data_is_iframe()) {
701 // will begin with I-frame. 560 BrowserSeekToCurrentTime();
702 next_video_data_is_iframe_ = true;
703
704 DCHECK(!reconfig_video_decoder_);
705 reconfig_video_decoder_ = true;
706 SetDemuxerConfigs(*configs, false);
707
708 // Config change may have just been detected on the other stream. If so,
709 // don't send a duplicate demuxer config request.
710 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) {
711 DCHECK(reconfig_audio_decoder_);
712 return; 561 return;
713 } 562 }
714 563
715 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); 564 is_waiting_for_video_decoder_ = true;
565 if (!IsEventPending(DECODER_CREATION_EVENT_PENDING))
566 SetPendingEvent(DECODER_CREATION_EVENT_PENDING);
716 } 567 }
717 568
718 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { 569 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) {
719 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; 570 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")";
720 if (is_audio)
721 reached_audio_eos_ = true;
722 else
723 reached_video_eos_ = true;
724 571
725 if (AudioFinished() && VideoFinished()) { 572 if (AudioFinished() && VideoFinished()) {
726 playing_ = false; 573 playing_ = false;
727 clock_.Pause(); 574 clock_.Pause();
728 start_time_ticks_ = base::TimeTicks(); 575 start_time_ticks_ = base::TimeTicks();
729 manager()->OnPlaybackComplete(player_id()); 576 manager()->OnPlaybackComplete(player_id());
730 } 577 }
731 } 578 }
732 579
733 void MediaSourcePlayer::ClearDecodingData() { 580 void MediaSourcePlayer::ClearDecodingData() {
734 DVLOG(1) << __FUNCTION__; 581 DVLOG(1) << __FUNCTION__;
735 if (audio_decoder_job_) 582 audio_decoder_job_->Flush();
736 audio_decoder_job_->Flush(); 583 video_decoder_job_->Flush();
737 if (video_decoder_job_)
738 video_decoder_job_->Flush();
739 start_time_ticks_ = base::TimeTicks(); 584 start_time_ticks_ = base::TimeTicks();
740 } 585 }
741 586
742 bool MediaSourcePlayer::HasVideo() { 587 bool MediaSourcePlayer::HasVideo() {
743 return kUnknownVideoCodec != video_codec_; 588 return video_decoder_job_->HasStream();
744 } 589 }
745 590
746 bool MediaSourcePlayer::HasAudio() { 591 bool MediaSourcePlayer::HasAudio() {
747 return kUnknownAudioCodec != audio_codec_; 592 return audio_decoder_job_->HasStream();
748 } 593 }
749 594
750 bool MediaSourcePlayer::AudioFinished() { 595 bool MediaSourcePlayer::AudioFinished() {
751 return reached_audio_eos_ || !HasAudio(); 596 return audio_decoder_job_->OutputEOSReached() || !HasAudio();
752 } 597 }
753 598
754 bool MediaSourcePlayer::VideoFinished() { 599 bool MediaSourcePlayer::VideoFinished() {
755 return reached_video_eos_ || !HasVideo(); 600 return video_decoder_job_->OutputEOSReached() || !HasVideo();
756 }
757
758 void MediaSourcePlayer::ConfigureAudioDecoderJob() {
759 if (!HasAudio()) {
760 ResetAudioDecoderJob();
761 return;
762 }
763
764 // Create audio decoder job only if config changes.
765 if (audio_decoder_job_ && !reconfig_audio_decoder_)
766 return;
767
768 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto();
769 if (is_audio_encrypted_ && media_crypto.is_null())
770 return;
771
772 DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding());
773
774 ResetAudioDecoderJob();
775 DVLOG(1) << __FUNCTION__ << " : creating new audio decoder job";
776 audio_decoder_job_.reset(AudioDecoderJob::Create(
777 audio_codec_, sampling_rate_, num_channels_, &audio_extra_data_[0],
778 audio_extra_data_.size(), media_crypto.obj(),
779 base::Bind(&DemuxerAndroid::RequestDemuxerData,
780 base::Unretained(demuxer_.get()), DemuxerStream::AUDIO)));
781
782 if (audio_decoder_job_) {
783 SetVolumeInternal();
784 // Need to reset the base timestamp in |audio_decoder_job_|.
785 // TODO(qinmin): When reconfiguring the |audio_decoder_job_|, there might
786 // still be some audio frames in the decoder or in AudioTrack. Therefore,
787 // we are losing some time here. http://crbug.com/357726.
788 base::TimeDelta current_time = GetCurrentTime();
789 audio_decoder_job_->SetBaseTimestamp(current_time);
790 clock_.SetTime(current_time, current_time);
791 audio_decoder_job_->BeginPrerolling(preroll_timestamp_);
792 reconfig_audio_decoder_ = false;
793 }
794 }
795
796 void MediaSourcePlayer::ResetVideoDecoderJob() {
797 if (video_decoder_job_) {
798 has_pending_video_data_request_ =
799 video_decoder_job_->is_requesting_demuxer_data();
800 }
801 video_decoder_job_.reset();
802
803 // Any eventual video decoder job re-creation will use the current |surface_|.
804 if (IsEventPending(SURFACE_CHANGE_EVENT_PENDING))
805 ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING);
806 }
807
808 void MediaSourcePlayer::ResetAudioDecoderJob() {
809 if (audio_decoder_job_) {
810 has_pending_audio_data_request_ =
811 audio_decoder_job_->is_requesting_demuxer_data();
812 }
813 audio_decoder_job_.reset();
814 }
815
816 void MediaSourcePlayer::ConfigureVideoDecoderJob() {
817 if (!HasVideo() || surface_.IsEmpty()) {
818 ResetVideoDecoderJob();
819 return;
820 }
821
822 // Create video decoder job only if config changes or we don't have a job.
823 if (video_decoder_job_ && !reconfig_video_decoder_) {
824 DCHECK(!IsEventPending(SURFACE_CHANGE_EVENT_PENDING));
825 return;
826 }
827
828 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding());
829
830 if (reconfig_video_decoder_) {
831 // No hack browser seek should be required. I-Frame must be next.
832 DCHECK(next_video_data_is_iframe_) << "Received video data between "
833 << "detecting video config change and reconfiguring video decoder";
834 }
835
836 // If uncertain that video I-frame data is next and there is no seek already
837 // in process, request browser demuxer seek so the new decoder will decode
838 // an I-frame first. Otherwise, the new MediaCodec might crash. See b/8950387.
839 // Eventual OnDemuxerSeekDone() will trigger ProcessPendingEvents() and
840 // continue from here.
841 // TODO(wolenetz): Instead of doing hack browser seek, replay cached data
842 // since last keyframe. See http://crbug.com/304234.
843 if (!next_video_data_is_iframe_ && !IsEventPending(SEEK_EVENT_PENDING)) {
844 BrowserSeekToCurrentTime();
845 return;
846 }
847
848 // Release the old VideoDecoderJob first so the surface can get released.
849 // Android does not allow 2 MediaCodec instances use the same surface.
850 ResetVideoDecoderJob();
851
852 base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto();
853 if (is_video_encrypted_ && media_crypto.is_null())
854 return;
855
856 DVLOG(1) << __FUNCTION__ << " : creating new video decoder job";
857
858 // Create the new VideoDecoderJob.
859 bool is_secure = IsProtectedSurfaceRequired();
860 video_decoder_job_.reset(
861 VideoDecoderJob::Create(
862 video_codec_,
863 is_secure,
864 gfx::Size(width_, height_),
865 surface_.j_surface().obj(),
866 media_crypto.obj(),
867 base::Bind(&DemuxerAndroid::RequestDemuxerData,
868 base::Unretained(demuxer_.get()),
869 DemuxerStream::VIDEO),
870 base::Bind(request_media_resources_cb_, player_id()),
871 base::Bind(release_media_resources_cb_, player_id())));
872 if (!video_decoder_job_)
873 return;
874
875 video_decoder_job_->BeginPrerolling(preroll_timestamp_);
876 reconfig_video_decoder_ = false;
877
878 // Inform the fullscreen view the player is ready.
879 // TODO(qinmin): refactor MediaPlayerBridge so that we have a better way
880 // to inform ContentVideoView.
881 manager()->OnMediaMetadataChanged(
882 player_id(), duration_, width_, height_, true);
883 } 601 }
884 602
885 void MediaSourcePlayer::OnDecoderStarved() { 603 void MediaSourcePlayer::OnDecoderStarved() {
886 DVLOG(1) << __FUNCTION__; 604 DVLOG(1) << __FUNCTION__;
887 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 605 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
888 ProcessPendingEvents(); 606 ProcessPendingEvents();
889 } 607 }
890 608
891 void MediaSourcePlayer::StartStarvationCallback( 609 void MediaSourcePlayer::StartStarvationCallback(
892 base::TimeDelta current_presentation_timestamp, 610 base::TimeDelta current_presentation_timestamp,
(...skipping 20 matching lines...) Expand all
913 } 631 }
914 632
915 timeout = std::max(timeout, kMinStarvationTimeout); 633 timeout = std::max(timeout, kMinStarvationTimeout);
916 634
917 decoder_starvation_callback_.Reset( 635 decoder_starvation_callback_.Reset(
918 base::Bind(&MediaSourcePlayer::OnDecoderStarved, weak_this_)); 636 base::Bind(&MediaSourcePlayer::OnDecoderStarved, weak_this_));
919 base::MessageLoop::current()->PostDelayedTask( 637 base::MessageLoop::current()->PostDelayedTask(
920 FROM_HERE, decoder_starvation_callback_.callback(), timeout); 638 FROM_HERE, decoder_starvation_callback_.callback(), timeout);
921 } 639 }
922 640
923 void MediaSourcePlayer::SetVolumeInternal() {
924 if (audio_decoder_job_ && volume_ >= 0)
925 audio_decoder_job_->SetVolume(volume_);
926 }
927
928 bool MediaSourcePlayer::IsProtectedSurfaceRequired() { 641 bool MediaSourcePlayer::IsProtectedSurfaceRequired() {
929 return is_video_encrypted_ && 642 return video_decoder_job_->is_content_encrypted() &&
930 drm_bridge_ && drm_bridge_->IsProtectedSurfaceRequired(); 643 drm_bridge_ && drm_bridge_->IsProtectedSurfaceRequired();
931 } 644 }
932 645
933 void MediaSourcePlayer::OnPrefetchDone() { 646 void MediaSourcePlayer::OnPrefetchDone() {
934 DVLOG(1) << __FUNCTION__; 647 DVLOG(1) << __FUNCTION__;
935 DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding()); 648 DCHECK(!audio_decoder_job_->is_decoding());
936 DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding()); 649 DCHECK(!video_decoder_job_->is_decoding());
937 650
938 // A previously posted OnPrefetchDone() could race against a Release(). If 651 // A previously posted OnPrefetchDone() could race against a Release(). If
939 // Release() won the race, we should no longer have decoder jobs. 652 // Release() won the race, we should no longer have decoder jobs.
940 // TODO(qinmin/wolenetz): Maintain channel state to not double-request data 653 // TODO(qinmin/wolenetz): Maintain channel state to not double-request data
941 // or drop data received across Release()+Start(). See http://crbug.com/306314 654 // or drop data received across Release()+Start(). See http://crbug.com/306314
942 // and http://crbug.com/304234. 655 // and http://crbug.com/304234.
943 if (!IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { 656 if (!IsEventPending(PREFETCH_DONE_EVENT_PENDING)) {
944 DVLOG(1) << __FUNCTION__ << " : aborting"; 657 DVLOG(1) << __FUNCTION__ << " : aborting";
945 DCHECK(!audio_decoder_job_ && !video_decoder_job_);
946 return; 658 return;
947 } 659 }
948 660
949 ClearPendingEvent(PREFETCH_DONE_EVENT_PENDING); 661 ClearPendingEvent(PREFETCH_DONE_EVENT_PENDING);
950 662
951 if (pending_event_ != NO_EVENT_PENDING) { 663 if (pending_event_ != NO_EVENT_PENDING) {
952 ProcessPendingEvents(); 664 ProcessPendingEvents();
953 return; 665 return;
954 } 666 }
955 667
668 if (!playing_)
669 return;
670
956 start_time_ticks_ = base::TimeTicks::Now(); 671 start_time_ticks_ = base::TimeTicks::Now();
957 start_presentation_timestamp_ = GetCurrentTime(); 672 start_presentation_timestamp_ = GetCurrentTime();
958 if (!clock_.IsPlaying()) 673 if (!clock_.IsPlaying())
959 clock_.Play(); 674 clock_.Play();
960 675
961 if (!AudioFinished()) 676 if (!AudioFinished())
962 DecodeMoreAudio(); 677 DecodeMoreAudio();
963 678
964 if (!VideoFinished()) 679 if (!VideoFinished())
965 DecodeMoreVideo(); 680 DecodeMoreVideo();
681 }
966 682
967 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) 683 void MediaSourcePlayer::OnDemuxerConfigsChanged() {
968 ProcessPendingEvents(); 684 manager()->OnMediaMetadataChanged(
685 player_id(), duration_, GetVideoWidth(), GetVideoHeight(), true);
969 } 686 }
970 687
971 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) { 688 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) {
689 // Please keep this in sync with PendingEventFlags.
972 static const char* kPendingEventNames[] = { 690 static const char* kPendingEventNames[] = {
691 "PREFETCH_DONE",
973 "SEEK", 692 "SEEK",
974 "SURFACE_CHANGE", 693 "DECODER_CREATION",
975 "CONFIG_CHANGE",
976 "PREFETCH_REQUEST", 694 "PREFETCH_REQUEST",
977 "PREFETCH_DONE",
978 }; 695 };
979 696
980 int mask = 1; 697 int mask = 1;
981 for (size_t i = 0; i < arraysize(kPendingEventNames); ++i, mask <<= 1) { 698 for (size_t i = 0; i < arraysize(kPendingEventNames); ++i, mask <<= 1) {
982 if (event & mask) 699 if (event & mask)
983 return kPendingEventNames[i]; 700 return kPendingEventNames[i];
984 } 701 }
985 702
986 return "UNKNOWN"; 703 return "UNKNOWN";
987 } 704 }
(...skipping 11 matching lines...) Expand all
999 } 716 }
1000 717
1001 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { 718 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) {
1002 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; 719 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")";
1003 DCHECK_NE(event, NO_EVENT_PENDING); 720 DCHECK_NE(event, NO_EVENT_PENDING);
1004 DCHECK(IsEventPending(event)) << GetEventName(event); 721 DCHECK(IsEventPending(event)) << GetEventName(event);
1005 722
1006 pending_event_ &= ~event; 723 pending_event_ &= ~event;
1007 } 724 }
1008 725
1009 void MediaSourcePlayer::SetDemuxerConfigs(const DemuxerConfigs& configs, 726 void MediaSourcePlayer::RetryDecoderCreation(bool audio, bool video) {
1010 bool is_audio) { 727 if (audio)
1011 if (is_audio) { 728 is_waiting_for_audio_decoder_ = false;
1012 audio_codec_ = configs.audio_codec; 729 if (video)
1013 num_channels_ = configs.audio_channels; 730 is_waiting_for_video_decoder_ = false;
1014 sampling_rate_ = configs.audio_sampling_rate; 731 if (IsEventPending(DECODER_CREATION_EVENT_PENDING))
1015 is_audio_encrypted_ = configs.is_audio_encrypted; 732 ProcessPendingEvents();
1016 audio_extra_data_ = configs.audio_extra_data;
1017 } else {
1018 video_codec_ = configs.video_codec;
1019 width_ = configs.video_size.width();
1020 height_ = configs.video_size.height();
1021 is_video_encrypted_ = configs.is_video_encrypted;
1022 }
1023 } 733 }
1024 734
1025 void MediaSourcePlayer::OnKeyAdded() { 735 void MediaSourcePlayer::OnKeyAdded() {
1026 DVLOG(1) << __FUNCTION__; 736 DVLOG(1) << __FUNCTION__;
1027 if (!is_waiting_for_key_) 737 if (!is_waiting_for_key_)
1028 return; 738 return;
1029 739
1030 is_waiting_for_key_ = false; 740 is_waiting_for_key_ = false;
1031 if (playing_) 741 if (playing_)
1032 StartInternal(); 742 StartInternal();
1033 } 743 }
1034 744
1035 void MediaSourcePlayer::OnCdmUnset() { 745 void MediaSourcePlayer::OnCdmUnset() {
1036 DVLOG(1) << __FUNCTION__; 746 DVLOG(1) << __FUNCTION__;
1037 DCHECK(drm_bridge_); 747 DCHECK(drm_bridge_);
1038 // TODO(xhwang): Support detachment of CDM. This will be needed when we start 748 // TODO(xhwang): Support detachment of CDM. This will be needed when we start
1039 // to support setMediaKeys(0), or when we release MediaDrm when the video is 749 // to support setMediaKeys(0), or when we release MediaDrm when the video is
1040 // paused, or when the device goes to sleep. See http://crbug.com/272421 750 // paused, or when the device goes to sleep. See http://crbug.com/272421
1041 DVLOG(1) << "CDM detachment not supported."; 751 DVLOG(1) << "CDM detachment not supported.";
1042 } 752 }
1043 753
1044 } // namespace media 754 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698