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

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

Issue 23620012: Fix MediaSourcePlayer unittests and minor code cleanup. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 3 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
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 "base/android/jni_android.h" 7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h" 8 #include "base/android/jni_string.h"
9 #include "base/barrier_closure.h" 9 #include "base/barrier_closure.h"
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 base::TimeDelta MediaSourcePlayer::GetCurrentTime() { 145 base::TimeDelta MediaSourcePlayer::GetCurrentTime() {
146 return clock_.Elapsed(); 146 return clock_.Elapsed();
147 } 147 }
148 148
149 base::TimeDelta MediaSourcePlayer::GetDuration() { 149 base::TimeDelta MediaSourcePlayer::GetDuration() {
150 return duration_; 150 return duration_;
151 } 151 }
152 152
153 void MediaSourcePlayer::Release() { 153 void MediaSourcePlayer::Release() {
154 DVLOG(1) << __FUNCTION__; 154 DVLOG(1) << __FUNCTION__;
155 ClearDecodingData();
acolwell GONE FROM CHROMIUM 2013/08/30 18:27:38 Not needed since the jobs are getting Release()'ed
156 audio_decoder_job_.reset(); 155 audio_decoder_job_.reset();
157 video_decoder_job_.reset(); 156 video_decoder_job_.reset();
158 reconfig_audio_decoder_ = false; 157 reconfig_audio_decoder_ = false;
159 reconfig_video_decoder_ = false; 158 reconfig_video_decoder_ = false;
160 playing_ = false; 159 playing_ = false;
161 pending_event_ = NO_EVENT_PENDING; 160 pending_event_ = NO_EVENT_PENDING;
162 surface_ = gfx::ScopedJavaSurface(); 161 surface_ = gfx::ScopedJavaSurface();
163 ReleaseMediaResourcesFromManager(); 162 ReleaseMediaResourcesFromManager();
164 } 163 }
165 164
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 return; 309 return;
311 310
312 ClearPendingEvent(SEEK_EVENT_PENDING); 311 ClearPendingEvent(SEEK_EVENT_PENDING);
313 312
314 OnSeekComplete(); 313 OnSeekComplete();
315 ProcessPendingEvents(); 314 ProcessPendingEvents();
316 } 315 }
317 316
318 void MediaSourcePlayer::UpdateTimestamps( 317 void MediaSourcePlayer::UpdateTimestamps(
319 const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) { 318 const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) {
319 base::TimeDelta new_max_time = presentation_timestamp;
320
320 if (audio_output_bytes > 0) { 321 if (audio_output_bytes > 0) {
321 audio_timestamp_helper_->AddFrames( 322 audio_timestamp_helper_->AddFrames(
322 audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_)); 323 audio_output_bytes / (kBytesPerAudioOutputSample * num_channels_));
323 clock_.SetMaxTime(audio_timestamp_helper_->GetTimestamp()); 324 new_max_time = audio_timestamp_helper_->GetTimestamp();
324 } else {
325 clock_.SetMaxTime(presentation_timestamp);
326 } 325 }
327 326
327 clock_.SetMaxTime(new_max_time);
328 OnTimeUpdated(); 328 OnTimeUpdated();
329 } 329 }
330 330
331 void MediaSourcePlayer::ProcessPendingEvents() { 331 void MediaSourcePlayer::ProcessPendingEvents() {
332 DVLOG(1) << __FUNCTION__ << " : 0x" 332 DVLOG(1) << __FUNCTION__ << " : 0x"
333 << std::hex << pending_event_; 333 << std::hex << pending_event_;
334 // Wait for all the decoding jobs to finish before processing pending tasks. 334 // Wait for all the decoding jobs to finish before processing pending tasks.
335 if ((audio_decoder_job_ && audio_decoder_job_->is_decoding()) || 335 if ((audio_decoder_job_ && audio_decoder_job_->is_decoding()) ||
336 (video_decoder_job_ && video_decoder_job_->is_decoding())) { 336 (video_decoder_job_ && video_decoder_job_->is_decoding())) {
337 DVLOG(1) << __FUNCTION__ << " : A job is still decoding."; 337 DVLOG(1) << __FUNCTION__ << " : A job is still decoding.";
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 // Now that all pending events have been handled, resume decoding if we are 389 // Now that all pending events have been handled, resume decoding if we are
390 // still playing. 390 // still playing.
391 if (playing_) 391 if (playing_)
392 StartInternal(); 392 StartInternal();
393 } 393 }
394 394
395 void MediaSourcePlayer::MediaDecoderCallback( 395 void MediaSourcePlayer::MediaDecoderCallback(
396 bool is_audio, MediaDecoderJob::DecodeStatus decode_status, 396 bool is_audio, MediaDecoderJob::DecodeStatus decode_status,
397 const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) { 397 const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) {
398 DVLOG(1) << __FUNCTION__; 398 DVLOG(1) << __FUNCTION__;
399 if (is_audio) 399
400 bool is_clock_manager = is_audio || !HasAudio();
401
402 if (is_clock_manager)
acolwell GONE FROM CHROMIUM 2013/08/30 18:27:38 The starvation callback gets scheduled in the vide
400 decoder_starvation_callback_.Cancel(); 403 decoder_starvation_callback_.Cancel();
401 404
402 if (decode_status == MediaDecoderJob::DECODE_FAILED) { 405 if (decode_status == MediaDecoderJob::DECODE_FAILED) {
403 Release(); 406 Release();
404 OnMediaError(MEDIA_ERROR_DECODE); 407 OnMediaError(MEDIA_ERROR_DECODE);
405 return; 408 return;
406 } 409 }
407 410
408 if (pending_event_ != NO_EVENT_PENDING) { 411 if (pending_event_ != NO_EVENT_PENDING) {
409 ProcessPendingEvents(); 412 ProcessPendingEvents();
410 return; 413 return;
411 } 414 }
412 415
413 if (decode_status == MediaDecoderJob::DECODE_SUCCEEDED &&
qinmin 2013/08/30 22:27:43 why changing the order of these 2 if statement? F
acolwell GONE FROM CHROMIUM 2013/09/06 00:34:55 The blocks are mutually exclusive. decode status c
qinmin 2013/09/06 00:56:33 Looks like this is a bug. When decode status is DE
414 (is_audio || !HasAudio())) {
415 UpdateTimestamps(presentation_timestamp, audio_output_bytes);
416 }
417
418 if (decode_status == MediaDecoderJob::DECODE_OUTPUT_END_OF_STREAM) { 416 if (decode_status == MediaDecoderJob::DECODE_OUTPUT_END_OF_STREAM) {
419 PlaybackCompleted(is_audio); 417 PlaybackCompleted(is_audio);
420 return; 418 return;
421 } 419 }
422 420
421 if (decode_status == MediaDecoderJob::DECODE_SUCCEEDED && is_clock_manager)
422 UpdateTimestamps(presentation_timestamp, audio_output_bytes);
423
423 if (!playing_) { 424 if (!playing_) {
424 if (is_audio || !HasAudio()) 425 if (is_clock_manager)
425 clock_.Pause(); 426 clock_.Pause();
426 return; 427 return;
427 } 428 }
428 429
429 base::TimeDelta current_timestamp = GetCurrentTime(); 430 if (is_clock_manager && decode_status == MediaDecoderJob::DECODE_SUCCEEDED)
431 StartStarvationCallback(presentation_timestamp);
432
430 if (is_audio) { 433 if (is_audio) {
431 if (decode_status == MediaDecoderJob::DECODE_SUCCEEDED) { 434 DecodeMoreAudio();
432 base::TimeDelta timeout =
433 audio_timestamp_helper_->GetTimestamp() - current_timestamp;
434 StartStarvationCallback(timeout);
435 }
436 DecodeMoreAudio();
437 return; 435 return;
438 } 436 }
439 437
440 if (!HasAudio() && decode_status == MediaDecoderJob::DECODE_SUCCEEDED) {
441 DCHECK(current_timestamp <= presentation_timestamp);
442 // For video only streams, fps can be estimated from the difference
443 // between the previous and current presentation timestamps. The
444 // previous presentation timestamp is equal to current_timestamp.
445 // TODO(qinmin): determine whether 2 is a good coefficient for estimating
446 // video frame timeout.
447 StartStarvationCallback(2 * (presentation_timestamp - current_timestamp));
448 }
449
450 DecodeMoreVideo(); 438 DecodeMoreVideo();
451 } 439 }
452 440
453 void MediaSourcePlayer::DecodeMoreAudio() { 441 void MediaSourcePlayer::DecodeMoreAudio() {
454 DVLOG(1) << __FUNCTION__; 442 DVLOG(1) << __FUNCTION__;
455 DCHECK(!audio_decoder_job_->is_decoding()); 443 DCHECK(!audio_decoder_job_->is_decoding());
456 444
457 if (audio_decoder_job_->Decode( 445 if (audio_decoder_job_->Decode(
458 start_time_ticks_, start_presentation_timestamp_, base::Bind( 446 start_time_ticks_, start_presentation_timestamp_, base::Bind(
459 &MediaSourcePlayer::MediaDecoderCallback, 447 &MediaSourcePlayer::MediaDecoderCallback,
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 OnMediaMetadataChanged(duration_, width_, height_, true); 571 OnMediaMetadataChanged(duration_, width_, height_, true);
584 } 572 }
585 573
586 void MediaSourcePlayer::OnDecoderStarved() { 574 void MediaSourcePlayer::OnDecoderStarved() {
587 DVLOG(1) << __FUNCTION__; 575 DVLOG(1) << __FUNCTION__;
588 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); 576 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING);
589 ProcessPendingEvents(); 577 ProcessPendingEvents();
590 } 578 }
591 579
592 void MediaSourcePlayer::StartStarvationCallback( 580 void MediaSourcePlayer::StartStarvationCallback(
593 const base::TimeDelta& timeout) { 581 const base::TimeDelta& presentation_timestamp) {
594 DVLOG(1) << __FUNCTION__ << "(" << timeout.InSecondsF() << ")"; 582 // 20ms was chosen because it is the typical size of a compressed audio frame.
583 // Anything smaller than this would likely cause unnecessary cycling in and
584 // out of the prefetch state.
585 const base::TimeDelta kMinStarvationTimeout =
586 base::TimeDelta::FromMilliseconds(20);
587
588 base::TimeDelta current_timestamp = GetCurrentTime();
589 base::TimeDelta timeout;
590 if (HasAudio()) {
591 timeout = audio_timestamp_helper_->GetTimestamp() - current_timestamp;
592 } else {
593 DCHECK(current_timestamp <= presentation_timestamp);
594
595 // For video only streams, fps can be estimated from the difference
596 // between the previous and current presentation timestamps. The
597 // previous presentation timestamp is equal to current_timestamp.
598 // TODO(qinmin): determine whether 2 is a good coefficient for estimating
599 // video frame timeout.
600 timeout = 2 * (presentation_timestamp - current_timestamp);
601 }
602
603 timeout = std::max(timeout, kMinStarvationTimeout);
acolwell GONE FROM CHROMIUM 2013/08/30 18:27:38 This fixes a bug that was in the code where it wou
595 604
596 decoder_starvation_callback_.Reset( 605 decoder_starvation_callback_.Reset(
597 base::Bind(&MediaSourcePlayer::OnDecoderStarved, 606 base::Bind(&MediaSourcePlayer::OnDecoderStarved,
598 weak_this_.GetWeakPtr())); 607 weak_this_.GetWeakPtr()));
599 base::MessageLoop::current()->PostDelayedTask( 608 base::MessageLoop::current()->PostDelayedTask(
600 FROM_HERE, decoder_starvation_callback_.callback(), timeout); 609 FROM_HERE, decoder_starvation_callback_.callback(), timeout);
601 } 610 }
602 611
603 void MediaSourcePlayer::SetVolumeInternal() { 612 void MediaSourcePlayer::SetVolumeInternal() {
604 if (audio_decoder_job_ && volume_ >= 0) 613 if (audio_decoder_job_ && volume_ >= 0)
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 675
667 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { 676 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) {
668 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; 677 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")";
669 DCHECK_NE(event, NO_EVENT_PENDING); 678 DCHECK_NE(event, NO_EVENT_PENDING);
670 DCHECK(IsEventPending(event)); 679 DCHECK(IsEventPending(event));
671 680
672 pending_event_ &= ~event; 681 pending_event_ &= ~event;
673 } 682 }
674 683
675 } // namespace media 684 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698