Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, | 5 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, | 
| 6 // potential deadlocks, etc... | 6 // potential deadlocks, etc... | 
| 7 | 7 | 
| 8 #include "media/base/pipeline_impl.h" | 8 #include "media/base/pipeline_impl.h" | 
| 9 | 9 | 
| 10 #include <algorithm> | 10 #include <algorithm> | 
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 179 base::AutoLock auto_lock(lock_); | 179 base::AutoLock auto_lock(lock_); | 
| 180 return has_video_; | 180 return has_video_; | 
| 181 } | 181 } | 
| 182 | 182 | 
| 183 float PipelineImpl::GetPlaybackRate() const { | 183 float PipelineImpl::GetPlaybackRate() const { | 
| 184 base::AutoLock auto_lock(lock_); | 184 base::AutoLock auto_lock(lock_); | 
| 185 return playback_rate_; | 185 return playback_rate_; | 
| 186 } | 186 } | 
| 187 | 187 | 
| 188 void PipelineImpl::SetPlaybackRate(float playback_rate) { | 188 void PipelineImpl::SetPlaybackRate(float playback_rate) { | 
| 189 if (playback_rate < 0.0f) { | 189 if (playback_rate < 0.0f) | 
| 190 return; | 190 return; | 
| 191 } | |
| 192 | 191 | 
| 193 base::AutoLock auto_lock(lock_); | 192 base::AutoLock auto_lock(lock_); | 
| 194 playback_rate_ = playback_rate; | 193 playback_rate_ = playback_rate; | 
| 195 if (running_ && !tearing_down_) { | 194 if (running_ && !tearing_down_) { | 
| 196 message_loop_->PostTask(FROM_HERE, base::Bind( | 195 message_loop_->PostTask(FROM_HERE, base::Bind( | 
| 197 &PipelineImpl::PlaybackRateChangedTask, this, playback_rate)); | 196 &PipelineImpl::PlaybackRateChangedTask, this, playback_rate)); | 
| 198 } | 197 } | 
| 199 } | 198 } | 
| 200 | 199 | 
| 201 float PipelineImpl::GetVolume() const { | 200 float PipelineImpl::GetVolume() const { | 
| 202 base::AutoLock auto_lock(lock_); | 201 base::AutoLock auto_lock(lock_); | 
| 203 return volume_; | 202 return volume_; | 
| 204 } | 203 } | 
| 205 | 204 | 
| 206 void PipelineImpl::SetVolume(float volume) { | 205 void PipelineImpl::SetVolume(float volume) { | 
| 207 if (volume < 0.0f || volume > 1.0f) { | 206 if (volume < 0.0f || volume > 1.0f) | 
| 208 return; | 207 return; | 
| 209 } | |
| 210 | 208 | 
| 211 base::AutoLock auto_lock(lock_); | 209 base::AutoLock auto_lock(lock_); | 
| 212 volume_ = volume; | 210 volume_ = volume; | 
| 213 if (running_ && !tearing_down_) { | 211 if (running_ && !tearing_down_) { | 
| 214 message_loop_->PostTask(FROM_HERE, base::Bind( | 212 message_loop_->PostTask(FROM_HERE, base::Bind( | 
| 215 &PipelineImpl::VolumeChangedTask, this, volume)); | 213 &PipelineImpl::VolumeChangedTask, this, volume)); | 
| 216 } | 214 } | 
| 217 } | 215 } | 
| 218 | 216 | 
| 219 Preload PipelineImpl::GetPreload() const { | 217 Preload PipelineImpl::GetPreload() const { | 
| (...skipping 12 matching lines...) Expand all Loading... | |
| 232 | 230 | 
| 233 base::TimeDelta PipelineImpl::GetCurrentTime() const { | 231 base::TimeDelta PipelineImpl::GetCurrentTime() const { | 
| 234 // TODO(scherkus): perhaps replace checking state_ == kEnded with a bool that | 232 // TODO(scherkus): perhaps replace checking state_ == kEnded with a bool that | 
| 235 // is set/get under the lock, because this is breaching the contract that | 233 // is set/get under the lock, because this is breaching the contract that | 
| 236 // |state_| is only accessed on |message_loop_|. | 234 // |state_| is only accessed on |message_loop_|. | 
| 237 base::AutoLock auto_lock(lock_); | 235 base::AutoLock auto_lock(lock_); | 
| 238 return GetCurrentTime_Locked(); | 236 return GetCurrentTime_Locked(); | 
| 239 } | 237 } | 
| 240 | 238 | 
| 241 base::TimeDelta PipelineImpl::GetCurrentTime_Locked() const { | 239 base::TimeDelta PipelineImpl::GetCurrentTime_Locked() const { | 
| 240 lock_.AssertAcquired(); | |
| 242 base::TimeDelta elapsed = clock_->Elapsed(); | 241 base::TimeDelta elapsed = clock_->Elapsed(); | 
| 243 if (state_ == kEnded || elapsed > duration_) { | 242 if (state_ == kEnded || elapsed > duration_) { | 
| 244 return duration_; | 243 return duration_; | 
| 245 } | 244 } | 
| 246 return elapsed; | 245 return elapsed; | 
| 247 } | 246 } | 
| 248 | 247 | 
| 249 base::TimeDelta PipelineImpl::GetBufferedTime() { | 248 base::TimeDelta PipelineImpl::GetBufferedTime() { | 
| 250 base::AutoLock auto_lock(lock_); | 249 base::AutoLock auto_lock(lock_); | 
| 251 | 250 | 
| 252 // If media is fully loaded, then return duration. | 251 // If media is fully loaded, then return duration. | 
| 253 if (loaded_ || total_bytes_ == buffered_bytes_) { | 252 if (loaded_ || total_bytes_ == buffered_bytes_) { | 
| 254 max_buffered_time_ = duration_; | 253 max_buffered_time_ = duration_; | 
| 255 return duration_; | 254 return duration_; | 
| 256 } | 255 } | 
| 257 | 256 | 
| 258 base::TimeDelta current_time = GetCurrentTime_Locked(); | 257 base::TimeDelta current_time = GetCurrentTime_Locked(); | 
| 259 | 258 | 
| 260 // If buffered time was set, we report that value directly. | 259 // If buffered time was set, we report that value directly. | 
| 261 if (buffered_time_.ToInternalValue() > 0) { | 260 if (buffered_time_.ToInternalValue() > 0) | 
| 262 return std::max(buffered_time_, current_time); | 261 return std::max(buffered_time_, current_time); | 
| 263 } | |
| 264 | 262 | 
| 265 if (total_bytes_ == 0) | 263 if (total_bytes_ == 0) | 
| 266 return base::TimeDelta(); | 264 return base::TimeDelta(); | 
| 267 | 265 | 
| 268 // If buffered time was not set, we use current time, current bytes, and | 266 // If buffered time was not set, we use current time, current bytes, and | 
| 269 // buffered bytes to estimate the buffered time. | 267 // buffered bytes to estimate the buffered time. | 
| 270 double estimated_rate = duration_.InMillisecondsF() / total_bytes_; | 268 double estimated_rate = duration_.InMillisecondsF() / total_bytes_; | 
| 271 double estimated_current_time = estimated_rate * current_bytes_; | 269 double estimated_current_time = estimated_rate * current_bytes_; | 
| 272 DCHECK_GE(buffered_bytes_, current_bytes_); | 270 DCHECK_GE(buffered_bytes_, current_bytes_); | 
| 273 base::TimeDelta buffered_time = base::TimeDelta::FromMilliseconds( | 271 base::TimeDelta buffered_time = base::TimeDelta::FromMilliseconds( | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 volume_ = 1.0f; | 362 volume_ = 1.0f; | 
| 365 preload_ = AUTO; | 363 preload_ = AUTO; | 
| 366 playback_rate_ = 0.0f; | 364 playback_rate_ = 0.0f; | 
| 367 pending_playback_rate_ = 0.0f; | 365 pending_playback_rate_ = 0.0f; | 
| 368 status_ = PIPELINE_OK; | 366 status_ = PIPELINE_OK; | 
| 369 has_audio_ = false; | 367 has_audio_ = false; | 
| 370 has_video_ = false; | 368 has_video_ = false; | 
| 371 waiting_for_clock_update_ = false; | 369 waiting_for_clock_update_ = false; | 
| 372 audio_disabled_ = false; | 370 audio_disabled_ = false; | 
| 373 clock_->SetTime(kZero); | 371 clock_->SetTime(kZero); | 
| 372 is_downloading_data_ = false; | |
| 
 
acolwell GONE FROM CHROMIUM
2011/11/09 00:50:22
Does download_rate_monitor_ need to be reset here?
 
vrk (LEFT CHROMIUM)
2011/11/11 02:51:06
Yes, done.
 
 | |
| 374 } | 373 } | 
| 375 | 374 | 
| 376 void PipelineImpl::SetState(State next_state) { | 375 void PipelineImpl::SetState(State next_state) { | 
| 377 if (state_ != kStarted && next_state == kStarted && | 376 if (state_ != kStarted && next_state == kStarted && | 
| 378 !creation_time_.is_null()) { | 377 !creation_time_.is_null()) { | 
| 379 UMA_HISTOGRAM_TIMES( | 378 UMA_HISTOGRAM_TIMES( | 
| 380 "Media.TimeToPipelineStarted", base::Time::Now() - creation_time_); | 379 "Media.TimeToPipelineStarted", base::Time::Now() - creation_time_); | 
| 381 creation_time_ = base::Time(); | 380 creation_time_ = base::Time(); | 
| 382 } | 381 } | 
| 383 state_ = next_state; | 382 state_ = next_state; | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 415 } | 414 } | 
| 416 | 415 | 
| 417 void PipelineImpl::FinishInitialization() { | 416 void PipelineImpl::FinishInitialization() { | 
| 418 DCHECK_EQ(MessageLoop::current(), message_loop_); | 417 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 419 // Execute the seek callback, if present. Note that this might be the | 418 // Execute the seek callback, if present. Note that this might be the | 
| 420 // initial callback passed into Start(). | 419 // initial callback passed into Start(). | 
| 421 if (!seek_callback_.is_null()) { | 420 if (!seek_callback_.is_null()) { | 
| 422 seek_callback_.Run(status_); | 421 seek_callback_.Run(status_); | 
| 423 seek_callback_.Reset(); | 422 seek_callback_.Reset(); | 
| 424 } | 423 } | 
| 424 | |
| 425 base::AutoLock auto_lock(lock_); | |
| 
 
acolwell GONE FROM CHROMIUM
2011/11/09 00:50:22
This is neaded because the SetXXXBytes() calls are
 
vrk (LEFT CHROMIUM)
2011/11/11 02:51:06
Actually the SetXXXBytes method calls (and SetLoad
 
 | |
| 426 int bitrate = 0; | |
| 427 if (demuxer_.get()) | |
| 428 bitrate = demuxer_->GetBitrate(); | |
| 429 download_rate_monitor_.Start( | |
| 430 base::Bind(&PipelineImpl::OnCanPlayThrough, this), bitrate); | |
| 425 } | 431 } | 
| 426 | 432 | 
| 427 // static | 433 // static | 
| 428 bool PipelineImpl::TransientState(State state) { | 434 bool PipelineImpl::TransientState(State state) { | 
| 429 return state == kPausing || | 435 return state == kPausing || | 
| 430 state == kFlushing || | 436 state == kFlushing || | 
| 431 state == kSeeking || | 437 state == kSeeking || | 
| 432 state == kStarting || | 438 state == kStarting || | 
| 433 state == kStopping; | 439 state == kStopping; | 
| 434 } | 440 } | 
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 media_log_->CreateIntegerEvent( | 523 media_log_->CreateIntegerEvent( | 
| 518 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes)); | 524 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes)); | 
| 519 int64 total_mbytes = total_bytes >> 20; | 525 int64 total_mbytes = total_bytes >> 20; | 
| 520 if (total_mbytes > kint32max) | 526 if (total_mbytes > kint32max) | 
| 521 total_mbytes = kint32max; | 527 total_mbytes = kint32max; | 
| 522 UMA_HISTOGRAM_CUSTOM_COUNTS( | 528 UMA_HISTOGRAM_CUSTOM_COUNTS( | 
| 523 "Media.TotalMBytes", static_cast<int32>(total_mbytes), 1, kint32max, 50); | 529 "Media.TotalMBytes", static_cast<int32>(total_mbytes), 1, kint32max, 50); | 
| 524 | 530 | 
| 525 base::AutoLock auto_lock(lock_); | 531 base::AutoLock auto_lock(lock_); | 
| 526 total_bytes_ = total_bytes; | 532 total_bytes_ = total_bytes; | 
| 533 download_rate_monitor_.SetTotalBytes(total_bytes_); | |
| 527 } | 534 } | 
| 528 | 535 | 
| 529 void PipelineImpl::SetBufferedBytes(int64 buffered_bytes) { | 536 void PipelineImpl::SetBufferedBytes(int64 buffered_bytes) { | 
| 530 DCHECK(IsRunning()); | 537 DCHECK(IsRunning()); | 
| 531 base::AutoLock auto_lock(lock_); | 538 base::AutoLock auto_lock(lock_); | 
| 532 | |
| 533 // See comments in SetCurrentReadPosition() about capping. | 539 // See comments in SetCurrentReadPosition() about capping. | 
| 534 if (buffered_bytes < current_bytes_) | 540 if (buffered_bytes < current_bytes_) | 
| 535 current_bytes_ = buffered_bytes; | 541 current_bytes_ = buffered_bytes; | 
| 536 buffered_bytes_ = buffered_bytes; | 542 buffered_bytes_ = buffered_bytes; | 
| 543 download_rate_monitor_.SetBufferedBytes(buffered_bytes, base::Time::Now()); | |
| 537 } | 544 } | 
| 538 | 545 | 
| 539 void PipelineImpl::SetNaturalVideoSize(const gfx::Size& size) { | 546 void PipelineImpl::SetNaturalVideoSize(const gfx::Size& size) { | 
| 540 DCHECK(IsRunning()); | 547 DCHECK(IsRunning()); | 
| 541 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( | 548 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( | 
| 542 size.width(), size.height())); | 549 size.width(), size.height())); | 
| 543 | 550 | 
| 544 base::AutoLock auto_lock(lock_); | 551 base::AutoLock auto_lock(lock_); | 
| 545 natural_size_ = size; | 552 natural_size_ = size; | 
| 546 } | 553 } | 
| (...skipping 16 matching lines...) Expand all Loading... | |
| 563 } | 570 } | 
| 564 | 571 | 
| 565 void PipelineImpl::SetLoaded(bool loaded) { | 572 void PipelineImpl::SetLoaded(bool loaded) { | 
| 566 DCHECK(IsRunning()); | 573 DCHECK(IsRunning()); | 
| 567 media_log_->AddEvent( | 574 media_log_->AddEvent( | 
| 568 media_log_->CreateBooleanEvent( | 575 media_log_->CreateBooleanEvent( | 
| 569 MediaLogEvent::LOADED_SET, "loaded", loaded)); | 576 MediaLogEvent::LOADED_SET, "loaded", loaded)); | 
| 570 | 577 | 
| 571 base::AutoLock auto_lock(lock_); | 578 base::AutoLock auto_lock(lock_); | 
| 572 loaded_ = loaded; | 579 loaded_ = loaded; | 
| 580 download_rate_monitor_.SetLoaded(loaded_); | |
| 573 } | 581 } | 
| 574 | 582 | 
| 575 void PipelineImpl::SetNetworkActivity(bool is_downloading_data) { | 583 void PipelineImpl::SetNetworkActivity(bool is_downloading_data) { | 
| 576 DCHECK(IsRunning()); | 584 DCHECK(IsRunning()); | 
| 585 | |
| 586 NetworkEvent type = DOWNLOAD_PAUSED; | |
| 587 if (is_downloading_data) | |
| 588 type = DOWNLOAD_CONTINUED; | |
| 589 | |
| 590 { | |
| 591 base::AutoLock auto_lock(lock_); | |
| 592 download_rate_monitor_.SetNetworkActivity(is_downloading_data); | |
| 593 } | |
| 594 | |
| 577 message_loop_->PostTask(FROM_HERE, | 595 message_loop_->PostTask(FROM_HERE, | 
| 578 base::Bind( | 596 base::Bind( | 
| 579 &PipelineImpl::NotifyNetworkEventTask, this, is_downloading_data)); | 597 &PipelineImpl::NotifyNetworkEventTask, this, type, | 
| 598 is_downloading_data)); | |
| 
 
acolwell GONE FROM CHROMIUM
2011/11/09 00:50:22
Is is_downloading_data still needed given that it'
 
vrk (LEFT CHROMIUM)
2011/11/11 02:51:06
AH oops, you're right! It served a purpose when th
 
 | |
| 580 media_log_->AddEvent( | 599 media_log_->AddEvent( | 
| 581 media_log_->CreateBooleanEvent( | 600 media_log_->CreateBooleanEvent( | 
| 582 MediaLogEvent::NETWORK_ACTIVITY_SET, | 601 MediaLogEvent::NETWORK_ACTIVITY_SET, | 
| 583 "is_downloading_data", is_downloading_data)); | 602 "is_downloading_data", is_downloading_data)); | 
| 584 } | 603 } | 
| 585 | 604 | 
| 586 void PipelineImpl::DisableAudioRenderer() { | 605 void PipelineImpl::DisableAudioRenderer() { | 
| 587 DCHECK(IsRunning()); | 606 DCHECK(IsRunning()); | 
| 588 | 607 | 
| 589 // Disable renderer on the message loop. | 608 // Disable renderer on the message loop. | 
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 675 // If we have received the stop or error signal, return immediately. | 694 // If we have received the stop or error signal, return immediately. | 
| 676 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 695 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 
| 677 return; | 696 return; | 
| 678 | 697 | 
| 679 DCHECK(state_ == kInitDemuxer || | 698 DCHECK(state_ == kInitDemuxer || | 
| 680 state_ == kInitAudioDecoder || | 699 state_ == kInitAudioDecoder || | 
| 681 state_ == kInitAudioRenderer || | 700 state_ == kInitAudioRenderer || | 
| 682 state_ == kInitVideoDecoder || | 701 state_ == kInitVideoDecoder || | 
| 683 state_ == kInitVideoRenderer); | 702 state_ == kInitVideoRenderer); | 
| 684 | 703 | 
| 685 | |
| 686 // Demuxer created, create audio decoder. | 704 // Demuxer created, create audio decoder. | 
| 687 if (state_ == kInitDemuxer) { | 705 if (state_ == kInitDemuxer) { | 
| 688 SetState(kInitAudioDecoder); | 706 SetState(kInitAudioDecoder); | 
| 689 // If this method returns false, then there's no audio stream. | 707 // If this method returns false, then there's no audio stream. | 
| 690 if (InitializeAudioDecoder(demuxer_)) | 708 if (InitializeAudioDecoder(demuxer_)) | 
| 691 return; | 709 return; | 
| 692 } | 710 } | 
| 693 | 711 | 
| 694 // Assuming audio decoder was created, create audio renderer. | 712 // Assuming audio decoder was created, create audio renderer. | 
| 695 if (state_ == kInitAudioDecoder) { | 713 if (state_ == kInitAudioDecoder) { | 
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 933 return; | 951 return; | 
| 934 } | 952 } | 
| 935 | 953 | 
| 936 // Transition to ended, executing the callback if present. | 954 // Transition to ended, executing the callback if present. | 
| 937 SetState(kEnded); | 955 SetState(kEnded); | 
| 938 if (!ended_callback_.is_null()) { | 956 if (!ended_callback_.is_null()) { | 
| 939 ended_callback_.Run(status_); | 957 ended_callback_.Run(status_); | 
| 940 } | 958 } | 
| 941 } | 959 } | 
| 942 | 960 | 
| 943 void PipelineImpl::NotifyNetworkEventTask(bool is_downloading_data) { | 961 void PipelineImpl::NotifyNetworkEventTask(NetworkEvent type, | 
| 962 bool is_downloading_data) { | |
| 944 DCHECK_EQ(MessageLoop::current(), message_loop_); | 963 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 964 is_downloading_data_ = is_downloading_data; | |
| 945 if (!network_callback_.is_null()) | 965 if (!network_callback_.is_null()) | 
| 946 network_callback_.Run(is_downloading_data); | 966 network_callback_.Run(type); | 
| 947 } | 967 } | 
| 948 | 968 | 
| 949 void PipelineImpl::DisableAudioRendererTask() { | 969 void PipelineImpl::DisableAudioRendererTask() { | 
| 950 DCHECK_EQ(MessageLoop::current(), message_loop_); | 970 DCHECK_EQ(MessageLoop::current(), message_loop_); | 
| 951 | 971 | 
| 952 base::AutoLock auto_lock(lock_); | 972 base::AutoLock auto_lock(lock_); | 
| 953 has_audio_ = false; | 973 has_audio_ = false; | 
| 954 audio_disabled_ = true; | 974 audio_disabled_ = true; | 
| 955 | 975 | 
| 956 // Notify all filters of disabled audio renderer. If the filter isn't | 976 // Notify all filters of disabled audio renderer. If the filter isn't | 
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1398 return; | 1418 return; | 
| 1399 } | 1419 } | 
| 1400 | 1420 | 
| 1401 if (state_ != kStarted) | 1421 if (state_ != kStarted) | 
| 1402 return; | 1422 return; | 
| 1403 | 1423 | 
| 1404 if (audio_renderer_) | 1424 if (audio_renderer_) | 
| 1405 audio_renderer_->ResumeAfterUnderflow(true); | 1425 audio_renderer_->ResumeAfterUnderflow(true); | 
| 1406 } | 1426 } | 
| 1407 | 1427 | 
| 1428 void PipelineImpl::OnCanPlayThrough() { | |
| 1429 message_loop_->PostTask(FROM_HERE, | |
| 1430 base::Bind( | |
| 1431 &PipelineImpl::NotifyCanPlayThrough, this)); | |
| 
 
scherkus (not reviewing)
2011/11/09 02:55:15
nit: can put this on previous line
 
vrk (LEFT CHROMIUM)
2011/11/11 02:51:06
Done.
 
 | |
| 1432 } | |
| 1433 | |
| 1434 void PipelineImpl::NotifyCanPlayThrough() { | |
| 1435 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
| 1436 NotifyNetworkEventTask(CAN_PLAY_THROUGH, is_downloading_data_); | |
| 1437 } | |
| 1438 | |
| 1408 } // namespace media | 1439 } // namespace media | 
| OLD | NEW |