| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/pipeline.h" | 5 #include "media/base/pipeline.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 scoped_refptr<CompositeFilter> composite; | 64 scoped_refptr<CompositeFilter> composite; |
| 65 }; | 65 }; |
| 66 | 66 |
| 67 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) | 67 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
| 68 : message_loop_(message_loop->message_loop_proxy()), | 68 : message_loop_(message_loop->message_loop_proxy()), |
| 69 media_log_(media_log), | 69 media_log_(media_log), |
| 70 clock_(new Clock(&base::Time::Now)), | 70 clock_(new Clock(&base::Time::Now)), |
| 71 waiting_for_clock_update_(false), | 71 waiting_for_clock_update_(false), |
| 72 state_(kCreated), | 72 state_(kCreated), |
| 73 current_bytes_(0), | 73 current_bytes_(0), |
| 74 creation_time_(base::Time::Now()), | 74 creation_time_(base::Time::Now()) { |
| 75 is_downloading_data_(false) { | |
| 76 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 75 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
| 77 ResetState(); | 76 ResetState(); |
| 78 media_log_->AddEvent( | 77 media_log_->AddEvent( |
| 79 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); | 78 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); |
| 80 } | 79 } |
| 81 | 80 |
| 82 Pipeline::~Pipeline() { | 81 Pipeline::~Pipeline() { |
| 83 base::AutoLock auto_lock(lock_); | 82 base::AutoLock auto_lock(lock_); |
| 84 DCHECK(!running_) << "Stop() must complete before destroying object"; | 83 DCHECK(!running_) << "Stop() must complete before destroying object"; |
| 85 DCHECK(!stop_pending_); | 84 DCHECK(!stop_pending_); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 110 // Stop the pipeline, which will set |running_| to false on our behalf. | 109 // Stop the pipeline, which will set |running_| to false on our behalf. |
| 111 message_loop_->PostTask(FROM_HERE, base::Bind( | 110 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 112 &Pipeline::StopTask, this, stop_cb)); | 111 &Pipeline::StopTask, this, stop_cb)); |
| 113 } | 112 } |
| 114 | 113 |
| 115 void Pipeline::Seek(base::TimeDelta time, | 114 void Pipeline::Seek(base::TimeDelta time, |
| 116 const PipelineStatusCB& seek_cb) { | 115 const PipelineStatusCB& seek_cb) { |
| 117 base::AutoLock auto_lock(lock_); | 116 base::AutoLock auto_lock(lock_); |
| 118 CHECK(running_) << "Media pipeline isn't running"; | 117 CHECK(running_) << "Media pipeline isn't running"; |
| 119 | 118 |
| 120 download_rate_monitor_.Stop(); | |
| 121 | |
| 122 message_loop_->PostTask(FROM_HERE, base::Bind( | 119 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 123 &Pipeline::SeekTask, this, time, seek_cb)); | 120 &Pipeline::SeekTask, this, time, seek_cb)); |
| 124 } | 121 } |
| 125 | 122 |
| 126 bool Pipeline::IsRunning() const { | 123 bool Pipeline::IsRunning() const { |
| 127 base::AutoLock auto_lock(lock_); | 124 base::AutoLock auto_lock(lock_); |
| 128 return running_; | 125 return running_; |
| 129 } | 126 } |
| 130 | 127 |
| 131 bool Pipeline::IsInitialized() const { | 128 bool Pipeline::IsInitialized() const { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 } | 218 } |
| 222 | 219 |
| 223 void Pipeline::GetNaturalVideoSize(gfx::Size* out_size) const { | 220 void Pipeline::GetNaturalVideoSize(gfx::Size* out_size) const { |
| 224 CHECK(out_size); | 221 CHECK(out_size); |
| 225 base::AutoLock auto_lock(lock_); | 222 base::AutoLock auto_lock(lock_); |
| 226 *out_size = natural_size_; | 223 *out_size = natural_size_; |
| 227 } | 224 } |
| 228 | 225 |
| 229 bool Pipeline::IsStreaming() const { | 226 bool Pipeline::IsStreaming() const { |
| 230 base::AutoLock auto_lock(lock_); | 227 base::AutoLock auto_lock(lock_); |
| 231 return streaming_; | 228 return demuxer_ && !demuxer_->IsSeekable(); |
| 232 } | 229 } |
| 233 | 230 |
| 234 bool Pipeline::IsLocalSource() const { | 231 bool Pipeline::IsLocalSource() const { |
| 235 base::AutoLock auto_lock(lock_); | 232 base::AutoLock auto_lock(lock_); |
| 236 return local_source_; | 233 return demuxer_ && demuxer_->IsLocalSource(); |
| 237 } | 234 } |
| 238 | 235 |
| 239 PipelineStatistics Pipeline::GetStatistics() const { | 236 PipelineStatistics Pipeline::GetStatistics() const { |
| 240 base::AutoLock auto_lock(lock_); | 237 base::AutoLock auto_lock(lock_); |
| 241 return statistics_; | 238 return statistics_; |
| 242 } | 239 } |
| 243 | 240 |
| 244 void Pipeline::SetClockForTesting(Clock* clock) { | 241 void Pipeline::SetClockForTesting(Clock* clock) { |
| 245 clock_.reset(clock); | 242 clock_.reset(clock); |
| 246 } | 243 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 263 base::AutoLock auto_lock(lock_); | 260 base::AutoLock auto_lock(lock_); |
| 264 const base::TimeDelta kZero; | 261 const base::TimeDelta kZero; |
| 265 running_ = false; | 262 running_ = false; |
| 266 stop_pending_ = false; | 263 stop_pending_ = false; |
| 267 seek_pending_ = false; | 264 seek_pending_ = false; |
| 268 tearing_down_ = false; | 265 tearing_down_ = false; |
| 269 error_caused_teardown_ = false; | 266 error_caused_teardown_ = false; |
| 270 playback_rate_change_pending_ = false; | 267 playback_rate_change_pending_ = false; |
| 271 buffered_bytes_ = 0; | 268 buffered_bytes_ = 0; |
| 272 buffered_time_ranges_.clear(); | 269 buffered_time_ranges_.clear(); |
| 273 streaming_ = false; | |
| 274 local_source_ = false; | |
| 275 total_bytes_ = 0; | 270 total_bytes_ = 0; |
| 276 natural_size_.SetSize(0, 0); | 271 natural_size_.SetSize(0, 0); |
| 277 volume_ = 1.0f; | 272 volume_ = 1.0f; |
| 278 playback_rate_ = 0.0f; | 273 playback_rate_ = 0.0f; |
| 279 pending_playback_rate_ = 0.0f; | 274 pending_playback_rate_ = 0.0f; |
| 280 status_ = PIPELINE_OK; | 275 status_ = PIPELINE_OK; |
| 281 has_audio_ = false; | 276 has_audio_ = false; |
| 282 has_video_ = false; | 277 has_video_ = false; |
| 283 waiting_for_clock_update_ = false; | 278 waiting_for_clock_update_ = false; |
| 284 audio_disabled_ = false; | 279 audio_disabled_ = false; |
| 285 clock_->Reset(); | 280 clock_->Reset(); |
| 286 download_rate_monitor_.Reset(); | |
| 287 } | 281 } |
| 288 | 282 |
| 289 void Pipeline::SetState(State next_state) { | 283 void Pipeline::SetState(State next_state) { |
| 290 if (state_ != kStarted && next_state == kStarted && | 284 if (state_ != kStarted && next_state == kStarted && |
| 291 !creation_time_.is_null()) { | 285 !creation_time_.is_null()) { |
| 292 UMA_HISTOGRAM_TIMES( | 286 UMA_HISTOGRAM_TIMES( |
| 293 "Media.TimeToPipelineStarted", base::Time::Now() - creation_time_); | 287 "Media.TimeToPipelineStarted", base::Time::Now() - creation_time_); |
| 294 creation_time_ = base::Time(); | 288 creation_time_ = base::Time(); |
| 295 } | 289 } |
| 296 state_ = next_state; | 290 state_ = next_state; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 media_log_->CreateIntegerEvent( | 439 media_log_->CreateIntegerEvent( |
| 446 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes)); | 440 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes)); |
| 447 int64 total_mbytes = total_bytes >> 20; | 441 int64 total_mbytes = total_bytes >> 20; |
| 448 if (total_mbytes > kint32max) | 442 if (total_mbytes > kint32max) |
| 449 total_mbytes = kint32max; | 443 total_mbytes = kint32max; |
| 450 UMA_HISTOGRAM_CUSTOM_COUNTS( | 444 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 451 "Media.TotalMBytes", static_cast<int32>(total_mbytes), 1, kint32max, 50); | 445 "Media.TotalMBytes", static_cast<int32>(total_mbytes), 1, kint32max, 50); |
| 452 | 446 |
| 453 base::AutoLock auto_lock(lock_); | 447 base::AutoLock auto_lock(lock_); |
| 454 total_bytes_ = total_bytes; | 448 total_bytes_ = total_bytes; |
| 455 download_rate_monitor_.set_total_bytes(total_bytes_); | |
| 456 } | 449 } |
| 457 | 450 |
| 458 void Pipeline::SetBufferedBytes(int64 buffered_bytes) { | 451 void Pipeline::SetBufferedBytes(int64 buffered_bytes) { |
| 459 DCHECK(IsRunning()); | 452 DCHECK(IsRunning()); |
| 460 base::AutoLock auto_lock(lock_); | 453 base::AutoLock auto_lock(lock_); |
| 461 // See comments in SetCurrentReadPosition() about capping. | 454 // See comments in SetCurrentReadPosition() about capping. |
| 462 if (buffered_bytes < current_bytes_) | 455 if (buffered_bytes < current_bytes_) |
| 463 current_bytes_ = buffered_bytes; | 456 current_bytes_ = buffered_bytes; |
| 464 buffered_bytes_ = buffered_bytes; | 457 buffered_bytes_ = buffered_bytes; |
| 465 download_rate_monitor_.SetBufferedBytes(buffered_bytes, base::Time::Now()); | |
| 466 UpdateBufferedTimeRanges_Locked(); | 458 UpdateBufferedTimeRanges_Locked(); |
| 467 } | 459 } |
| 468 | 460 |
| 469 void Pipeline::UpdateBufferedTimeRanges_Locked() { | 461 void Pipeline::UpdateBufferedTimeRanges_Locked() { |
| 470 lock_.AssertAcquired(); | 462 lock_.AssertAcquired(); |
| 471 if (total_bytes_ == 0) | 463 if (total_bytes_ == 0) |
| 472 return; | 464 return; |
| 473 base::TimeDelta buffered_time = | 465 base::TimeDelta buffered_time = |
| 474 clock_->Duration() * buffered_bytes_ / total_bytes_; | 466 clock_->Duration() * buffered_bytes_ / total_bytes_; |
| 475 // Cap approximated buffered time at the length of the video. | 467 // Cap approximated buffered time at the length of the video. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 497 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); | 489 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); |
| 498 } | 490 } |
| 499 | 491 |
| 500 void Pipeline::SetNetworkActivity(bool is_downloading_data) { | 492 void Pipeline::SetNetworkActivity(bool is_downloading_data) { |
| 501 DCHECK(IsRunning()); | 493 DCHECK(IsRunning()); |
| 502 | 494 |
| 503 NetworkEvent type = DOWNLOAD_PAUSED; | 495 NetworkEvent type = DOWNLOAD_PAUSED; |
| 504 if (is_downloading_data) | 496 if (is_downloading_data) |
| 505 type = DOWNLOAD_CONTINUED; | 497 type = DOWNLOAD_CONTINUED; |
| 506 | 498 |
| 507 { | |
| 508 base::AutoLock auto_lock(lock_); | |
| 509 download_rate_monitor_.SetNetworkActivity(is_downloading_data); | |
| 510 } | |
| 511 | |
| 512 message_loop_->PostTask(FROM_HERE, base::Bind( | 499 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 513 &Pipeline::NotifyNetworkEventTask, this, type)); | 500 &Pipeline::NotifyNetworkEventTask, this, type)); |
| 514 media_log_->AddEvent( | 501 media_log_->AddEvent( |
| 515 media_log_->CreateBooleanEvent( | 502 media_log_->CreateBooleanEvent( |
| 516 MediaLogEvent::NETWORK_ACTIVITY_SET, | 503 MediaLogEvent::NETWORK_ACTIVITY_SET, |
| 517 "is_downloading_data", is_downloading_data)); | 504 "is_downloading_data", is_downloading_data)); |
| 518 } | 505 } |
| 519 | 506 |
| 520 void Pipeline::DisableAudioRenderer() { | 507 void Pipeline::DisableAudioRenderer() { |
| 521 DCHECK(IsRunning()); | 508 DCHECK(IsRunning()); |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 | 953 |
| 967 base::AutoLock auto_lock(lock_); | 954 base::AutoLock auto_lock(lock_); |
| 968 // We use audio stream to update the clock. So if there is such a stream, | 955 // We use audio stream to update the clock. So if there is such a stream, |
| 969 // we pause the clock until we receive a valid timestamp. | 956 // we pause the clock until we receive a valid timestamp. |
| 970 waiting_for_clock_update_ = true; | 957 waiting_for_clock_update_ = true; |
| 971 if (!has_audio_) { | 958 if (!has_audio_) { |
| 972 clock_->SetMaxTime(clock_->Duration()); | 959 clock_->SetMaxTime(clock_->Duration()); |
| 973 StartClockIfWaitingForTimeUpdate_Locked(); | 960 StartClockIfWaitingForTimeUpdate_Locked(); |
| 974 } | 961 } |
| 975 | 962 |
| 976 // Start monitoring rate of downloading. | |
| 977 int bitrate = 0; | |
| 978 if (demuxer_) { | |
| 979 bitrate = demuxer_->GetBitrate(); | |
| 980 local_source_ = demuxer_->IsLocalSource(); | |
| 981 streaming_ = !demuxer_->IsSeekable(); | |
| 982 } | |
| 983 // Needs to be locked because most other calls to |download_rate_monitor_| | |
| 984 // occur on the renderer thread. | |
| 985 download_rate_monitor_.Start( | |
| 986 base::Bind(&Pipeline::OnCanPlayThrough, this), | |
| 987 bitrate, streaming_, local_source_); | |
| 988 download_rate_monitor_.SetBufferedBytes(buffered_bytes_, base::Time::Now()); | |
| 989 | |
| 990 if (IsPipelineStopPending()) { | 963 if (IsPipelineStopPending()) { |
| 991 // We had a pending stop request need to be honored right now. | 964 // We had a pending stop request need to be honored right now. |
| 992 TearDownPipeline(); | 965 TearDownPipeline(); |
| 993 } | 966 } |
| 994 } else { | 967 } else { |
| 995 NOTREACHED() << "Unexpected state: " << state_; | 968 NOTREACHED() << "Unexpected state: " << state_; |
| 996 } | 969 } |
| 997 } | 970 } |
| 998 | 971 |
| 999 void Pipeline::TeardownStateTransitionTask() { | 972 void Pipeline::TeardownStateTransitionTask() { |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1326 return; | 1299 return; |
| 1327 } | 1300 } |
| 1328 | 1301 |
| 1329 if (state_ != kStarted) | 1302 if (state_ != kStarted) |
| 1330 return; | 1303 return; |
| 1331 | 1304 |
| 1332 if (audio_renderer_) | 1305 if (audio_renderer_) |
| 1333 audio_renderer_->ResumeAfterUnderflow(true); | 1306 audio_renderer_->ResumeAfterUnderflow(true); |
| 1334 } | 1307 } |
| 1335 | 1308 |
| 1336 void Pipeline::OnCanPlayThrough() { | |
| 1337 message_loop_->PostTask(FROM_HERE, base::Bind( | |
| 1338 &Pipeline::NotifyCanPlayThrough, this)); | |
| 1339 } | |
| 1340 | |
| 1341 void Pipeline::NotifyCanPlayThrough() { | |
| 1342 DCHECK(message_loop_->BelongsToCurrentThread()); | |
| 1343 NotifyNetworkEventTask(CAN_PLAY_THROUGH); | |
| 1344 } | |
| 1345 | |
| 1346 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1309 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
| 1347 lock_.AssertAcquired(); | 1310 lock_.AssertAcquired(); |
| 1348 if (!waiting_for_clock_update_) | 1311 if (!waiting_for_clock_update_) |
| 1349 return; | 1312 return; |
| 1350 | 1313 |
| 1351 waiting_for_clock_update_ = false; | 1314 waiting_for_clock_update_ = false; |
| 1352 clock_->Play(); | 1315 clock_->Play(); |
| 1353 } | 1316 } |
| 1354 | 1317 |
| 1355 } // namespace media | 1318 } // namespace media |
| OLD | NEW |