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 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
177 base::AutoLock auto_lock(lock_); | 177 base::AutoLock auto_lock(lock_); |
178 return has_video_; | 178 return has_video_; |
179 } | 179 } |
180 | 180 |
181 float PipelineImpl::GetPlaybackRate() const { | 181 float PipelineImpl::GetPlaybackRate() const { |
182 base::AutoLock auto_lock(lock_); | 182 base::AutoLock auto_lock(lock_); |
183 return playback_rate_; | 183 return playback_rate_; |
184 } | 184 } |
185 | 185 |
186 void PipelineImpl::SetPlaybackRate(float playback_rate) { | 186 void PipelineImpl::SetPlaybackRate(float playback_rate) { |
187 if (playback_rate < 0.0f) { | 187 if (playback_rate < 0.0f) |
188 return; | 188 return; |
189 } | |
190 | 189 |
191 base::AutoLock auto_lock(lock_); | 190 base::AutoLock auto_lock(lock_); |
192 playback_rate_ = playback_rate; | 191 playback_rate_ = playback_rate; |
193 if (running_ && !tearing_down_) { | 192 if (running_ && !tearing_down_) { |
194 message_loop_->PostTask(FROM_HERE, base::Bind( | 193 message_loop_->PostTask(FROM_HERE, base::Bind( |
195 &PipelineImpl::PlaybackRateChangedTask, this, playback_rate)); | 194 &PipelineImpl::PlaybackRateChangedTask, this, playback_rate)); |
196 } | 195 } |
197 } | 196 } |
198 | 197 |
199 float PipelineImpl::GetVolume() const { | 198 float PipelineImpl::GetVolume() const { |
200 base::AutoLock auto_lock(lock_); | 199 base::AutoLock auto_lock(lock_); |
201 return volume_; | 200 return volume_; |
202 } | 201 } |
203 | 202 |
204 void PipelineImpl::SetVolume(float volume) { | 203 void PipelineImpl::SetVolume(float volume) { |
205 if (volume < 0.0f || volume > 1.0f) { | 204 if (volume < 0.0f || volume > 1.0f) |
206 return; | 205 return; |
207 } | |
208 | 206 |
209 base::AutoLock auto_lock(lock_); | 207 base::AutoLock auto_lock(lock_); |
210 volume_ = volume; | 208 volume_ = volume; |
211 if (running_ && !tearing_down_) { | 209 if (running_ && !tearing_down_) { |
212 message_loop_->PostTask(FROM_HERE, base::Bind( | 210 message_loop_->PostTask(FROM_HERE, base::Bind( |
213 &PipelineImpl::VolumeChangedTask, this, volume)); | 211 &PipelineImpl::VolumeChangedTask, this, volume)); |
214 } | 212 } |
215 } | 213 } |
216 | 214 |
217 Preload PipelineImpl::GetPreload() const { | 215 Preload PipelineImpl::GetPreload() const { |
(...skipping 12 matching lines...) Expand all Loading... | |
230 | 228 |
231 base::TimeDelta PipelineImpl::GetCurrentTime() const { | 229 base::TimeDelta PipelineImpl::GetCurrentTime() const { |
232 // TODO(scherkus): perhaps replace checking state_ == kEnded with a bool that | 230 // TODO(scherkus): perhaps replace checking state_ == kEnded with a bool that |
233 // is set/get under the lock, because this is breaching the contract that | 231 // is set/get under the lock, because this is breaching the contract that |
234 // |state_| is only accessed on |message_loop_|. | 232 // |state_| is only accessed on |message_loop_|. |
235 base::AutoLock auto_lock(lock_); | 233 base::AutoLock auto_lock(lock_); |
236 return GetCurrentTime_Locked(); | 234 return GetCurrentTime_Locked(); |
237 } | 235 } |
238 | 236 |
239 base::TimeDelta PipelineImpl::GetCurrentTime_Locked() const { | 237 base::TimeDelta PipelineImpl::GetCurrentTime_Locked() const { |
238 lock_.AssertAcquired(); | |
240 base::TimeDelta elapsed = clock_->Elapsed(); | 239 base::TimeDelta elapsed = clock_->Elapsed(); |
241 if (state_ == kEnded || elapsed > duration_) { | 240 if (state_ == kEnded || elapsed > duration_) { |
242 return duration_; | 241 return duration_; |
243 } | 242 } |
244 return elapsed; | 243 return elapsed; |
245 } | 244 } |
246 | 245 |
247 base::TimeDelta PipelineImpl::GetBufferedTime() { | 246 base::TimeDelta PipelineImpl::GetBufferedTime() { |
248 base::AutoLock auto_lock(lock_); | 247 base::AutoLock auto_lock(lock_); |
248 return GetBufferedTime_Locked(); | |
249 } | |
249 | 250 |
251 base::TimeDelta PipelineImpl::GetBufferedTime_Locked() { | |
252 lock_.AssertAcquired(); | |
250 // If media is fully loaded, then return duration. | 253 // If media is fully loaded, then return duration. |
251 if (loaded_ || total_bytes_ == buffered_bytes_) { | 254 if (loaded_ || total_bytes_ == buffered_bytes_) { |
252 max_buffered_time_ = duration_; | 255 max_buffered_time_ = duration_; |
253 return duration_; | 256 return duration_; |
254 } | 257 } |
255 | 258 |
256 base::TimeDelta current_time = GetCurrentTime_Locked(); | 259 base::TimeDelta current_time = GetCurrentTime_Locked(); |
257 | 260 |
258 // If buffered time was set, we report that value directly. | 261 // If buffered time was set, we report that value directly. |
259 if (buffered_time_.ToInternalValue() > 0) { | 262 if (buffered_time_.ToInternalValue() > 0) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 volume_ = 1.0f; | 365 volume_ = 1.0f; |
363 preload_ = AUTO; | 366 preload_ = AUTO; |
364 playback_rate_ = 0.0f; | 367 playback_rate_ = 0.0f; |
365 pending_playback_rate_ = 0.0f; | 368 pending_playback_rate_ = 0.0f; |
366 status_ = PIPELINE_OK; | 369 status_ = PIPELINE_OK; |
367 has_audio_ = false; | 370 has_audio_ = false; |
368 has_video_ = false; | 371 has_video_ = false; |
369 waiting_for_clock_update_ = false; | 372 waiting_for_clock_update_ = false; |
370 audio_disabled_ = false; | 373 audio_disabled_ = false; |
371 clock_->SetTime(kZero); | 374 clock_->SetTime(kZero); |
375 starting_bytes_loaded_ = 0; | |
376 starting_time_ = base::Time(); | |
377 has_notified_can_play_through_ = false; | |
378 is_downloading_data_ = false; | |
379 last_approximate_download_rate_ = -1; | |
372 } | 380 } |
373 | 381 |
374 void PipelineImpl::SetState(State next_state) { | 382 void PipelineImpl::SetState(State next_state) { |
375 state_ = next_state; | 383 state_ = next_state; |
376 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); | 384 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(next_state)); |
377 } | 385 } |
378 | 386 |
379 bool PipelineImpl::IsPipelineOk() { | 387 bool PipelineImpl::IsPipelineOk() { |
380 base::AutoLock auto_lock(lock_); | 388 base::AutoLock auto_lock(lock_); |
381 return status_ == PIPELINE_OK; | 389 return status_ == PIPELINE_OK; |
(...skipping 25 matching lines...) Expand all Loading... | |
407 } | 415 } |
408 | 416 |
409 void PipelineImpl::FinishInitialization() { | 417 void PipelineImpl::FinishInitialization() { |
410 DCHECK_EQ(MessageLoop::current(), message_loop_); | 418 DCHECK_EQ(MessageLoop::current(), message_loop_); |
411 // Execute the seek callback, if present. Note that this might be the | 419 // Execute the seek callback, if present. Note that this might be the |
412 // initial callback passed into Start(). | 420 // initial callback passed into Start(). |
413 if (!seek_callback_.is_null()) { | 421 if (!seek_callback_.is_null()) { |
414 seek_callback_.Run(status_); | 422 seek_callback_.Run(status_); |
415 seek_callback_.Reset(); | 423 seek_callback_.Reset(); |
416 } | 424 } |
425 is_downloading_data_ = true; | |
426 starting_time_ = base::Time::Now(); | |
427 NotifyCanPlayThroughIfNeeded(); | |
417 } | 428 } |
418 | 429 |
419 // static | 430 // static |
420 bool PipelineImpl::TransientState(State state) { | 431 bool PipelineImpl::TransientState(State state) { |
421 return state == kPausing || | 432 return state == kPausing || |
422 state == kFlushing || | 433 state == kFlushing || |
423 state == kSeeking || | 434 state == kSeeking || |
424 state == kStarting || | 435 state == kStarting || |
425 state == kStopping; | 436 state == kStopping; |
426 } | 437 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
507 media_log_->AddEvent( | 518 media_log_->AddEvent( |
508 media_log_->CreateIntegerEvent( | 519 media_log_->CreateIntegerEvent( |
509 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes)); | 520 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes)); |
510 | 521 |
511 base::AutoLock auto_lock(lock_); | 522 base::AutoLock auto_lock(lock_); |
512 total_bytes_ = total_bytes; | 523 total_bytes_ = total_bytes; |
513 } | 524 } |
514 | 525 |
515 void PipelineImpl::SetBufferedBytes(int64 buffered_bytes) { | 526 void PipelineImpl::SetBufferedBytes(int64 buffered_bytes) { |
516 DCHECK(IsRunning()); | 527 DCHECK(IsRunning()); |
517 base::AutoLock auto_lock(lock_); | 528 { |
518 | 529 base::AutoLock auto_lock(lock_); |
519 // See comments in SetCurrentReadPosition() about capping. | 530 // See comments in SetCurrentReadPosition() about capping. |
520 if (buffered_bytes < current_bytes_) | 531 if (buffered_bytes < current_bytes_) |
521 current_bytes_ = buffered_bytes; | 532 current_bytes_ = buffered_bytes; |
522 buffered_bytes_ = buffered_bytes; | 533 buffered_bytes_ = buffered_bytes; |
534 } | |
535 NotifyCanPlayThroughIfNeeded(); | |
523 } | 536 } |
524 | 537 |
525 void PipelineImpl::SetNaturalVideoSize(const gfx::Size& size) { | 538 void PipelineImpl::SetNaturalVideoSize(const gfx::Size& size) { |
526 DCHECK(IsRunning()); | 539 DCHECK(IsRunning()); |
527 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( | 540 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( |
528 size.width(), size.height())); | 541 size.width(), size.height())); |
529 | 542 |
530 base::AutoLock auto_lock(lock_); | 543 base::AutoLock auto_lock(lock_); |
531 natural_size_ = size; | 544 natural_size_ = size; |
532 } | 545 } |
533 | 546 |
534 void PipelineImpl::SetStreaming(bool streaming) { | 547 void PipelineImpl::SetStreaming(bool streaming) { |
535 DCHECK(IsRunning()); | 548 DCHECK(IsRunning()); |
536 media_log_->AddEvent( | 549 media_log_->AddEvent( |
537 media_log_->CreateBooleanEvent( | 550 media_log_->CreateBooleanEvent( |
538 MediaLogEvent::STREAMING_SET, "streaming", streaming)); | 551 MediaLogEvent::STREAMING_SET, "streaming", streaming)); |
539 | 552 |
540 base::AutoLock auto_lock(lock_); | 553 base::AutoLock auto_lock(lock_); |
541 streaming_ = streaming; | 554 streaming_ = streaming; |
542 } | 555 } |
543 | 556 |
544 void PipelineImpl::NotifyEnded() { | 557 void PipelineImpl::NotifyEnded() { |
545 DCHECK(IsRunning()); | 558 DCHECK(IsRunning()); |
546 message_loop_->PostTask(FROM_HERE, | 559 message_loop_->PostTask(FROM_HERE, |
547 base::Bind(&PipelineImpl::NotifyEndedTask, this)); | 560 base::Bind(&PipelineImpl::NotifyEndedTask, this)); |
548 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); | 561 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); |
562 NotifyCanPlayThroughIfNeeded(); | |
549 } | 563 } |
550 | 564 |
551 void PipelineImpl::SetLoaded(bool loaded) { | 565 void PipelineImpl::SetLoaded(bool loaded) { |
552 DCHECK(IsRunning()); | 566 DCHECK(IsRunning()); |
553 media_log_->AddEvent( | 567 media_log_->AddEvent( |
554 media_log_->CreateBooleanEvent( | 568 media_log_->CreateBooleanEvent( |
555 MediaLogEvent::LOADED_SET, "loaded", loaded)); | 569 MediaLogEvent::LOADED_SET, "loaded", loaded)); |
556 | 570 |
557 base::AutoLock auto_lock(lock_); | 571 base::AutoLock auto_lock(lock_); |
558 loaded_ = loaded; | 572 loaded_ = loaded; |
559 } | 573 } |
560 | 574 |
561 void PipelineImpl::SetNetworkActivity(bool is_downloading_data) { | 575 void PipelineImpl::SetNetworkActivity(bool is_downloading_data) { |
562 DCHECK(IsRunning()); | 576 DCHECK(IsRunning()); |
577 | |
578 base::AutoLock auto_lock(lock_); | |
acolwell GONE FROM CHROMIUM
2011/10/28 18:24:13
Why are we doing these operations here instead of
vrk (LEFT CHROMIUM)
2011/11/01 21:57:34
Hmm, no real reason; I guess I was doing this here
| |
579 if (is_downloading_data_ == is_downloading_data) | |
580 return; | |
581 | |
582 is_downloading_data_ = is_downloading_data; | |
583 NetworkEvent type = DOWNLOAD_PAUSED; | |
584 if (is_downloading_data) { | |
585 type = DOWNLOAD_CONTINUED; | |
586 // Reset CanPlayThrough-related state when downloading continues. | |
587 starting_bytes_loaded_ = buffered_bytes_; | |
588 starting_time_ = base::Time::Now(); | |
589 } | |
563 message_loop_->PostTask(FROM_HERE, | 590 message_loop_->PostTask(FROM_HERE, |
564 base::Bind( | 591 base::Bind( |
565 &PipelineImpl::NotifyNetworkEventTask, this, is_downloading_data)); | 592 &PipelineImpl::NotifyNetworkEventTask, this, type)); |
566 media_log_->AddEvent( | 593 media_log_->AddEvent( |
567 media_log_->CreateBooleanEvent( | 594 media_log_->CreateBooleanEvent( |
568 MediaLogEvent::NETWORK_ACTIVITY_SET, | 595 MediaLogEvent::NETWORK_ACTIVITY_SET, |
569 "is_downloading_data", is_downloading_data)); | 596 "is_downloading_data", is_downloading_data)); |
570 } | 597 } |
571 | 598 |
572 void PipelineImpl::DisableAudioRenderer() { | 599 void PipelineImpl::DisableAudioRenderer() { |
573 DCHECK(IsRunning()); | 600 DCHECK(IsRunning()); |
574 | 601 |
575 // Disable renderer on the message loop. | 602 // Disable renderer on the message loop. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
661 // If we have received the stop or error signal, return immediately. | 688 // If we have received the stop or error signal, return immediately. |
662 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) | 689 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) |
663 return; | 690 return; |
664 | 691 |
665 DCHECK(state_ == kInitDemuxer || | 692 DCHECK(state_ == kInitDemuxer || |
666 state_ == kInitAudioDecoder || | 693 state_ == kInitAudioDecoder || |
667 state_ == kInitAudioRenderer || | 694 state_ == kInitAudioRenderer || |
668 state_ == kInitVideoDecoder || | 695 state_ == kInitVideoDecoder || |
669 state_ == kInitVideoRenderer); | 696 state_ == kInitVideoRenderer); |
670 | 697 |
671 | |
672 // Demuxer created, create audio decoder. | 698 // Demuxer created, create audio decoder. |
673 if (state_ == kInitDemuxer) { | 699 if (state_ == kInitDemuxer) { |
674 SetState(kInitAudioDecoder); | 700 SetState(kInitAudioDecoder); |
675 // If this method returns false, then there's no audio stream. | 701 // If this method returns false, then there's no audio stream. |
676 if (InitializeAudioDecoder(demuxer_)) | 702 if (InitializeAudioDecoder(demuxer_)) |
677 return; | 703 return; |
678 } | 704 } |
679 | 705 |
680 // Assuming audio decoder was created, create audio renderer. | 706 // Assuming audio decoder was created, create audio renderer. |
681 if (state_ == kInitAudioDecoder) { | 707 if (state_ == kInitAudioDecoder) { |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
919 return; | 945 return; |
920 } | 946 } |
921 | 947 |
922 // Transition to ended, executing the callback if present. | 948 // Transition to ended, executing the callback if present. |
923 SetState(kEnded); | 949 SetState(kEnded); |
924 if (!ended_callback_.is_null()) { | 950 if (!ended_callback_.is_null()) { |
925 ended_callback_.Run(status_); | 951 ended_callback_.Run(status_); |
926 } | 952 } |
927 } | 953 } |
928 | 954 |
929 void PipelineImpl::NotifyNetworkEventTask(bool is_downloading_data) { | 955 void PipelineImpl::NotifyNetworkEventTask(NetworkEvent type) { |
930 DCHECK_EQ(MessageLoop::current(), message_loop_); | 956 DCHECK_EQ(MessageLoop::current(), message_loop_); |
931 if (!network_callback_.is_null()) | 957 if (!network_callback_.is_null()) |
932 network_callback_.Run(is_downloading_data); | 958 network_callback_.Run(type); |
933 } | 959 } |
934 | 960 |
935 void PipelineImpl::DisableAudioRendererTask() { | 961 void PipelineImpl::DisableAudioRendererTask() { |
936 DCHECK_EQ(MessageLoop::current(), message_loop_); | 962 DCHECK_EQ(MessageLoop::current(), message_loop_); |
937 | 963 |
938 base::AutoLock auto_lock(lock_); | 964 base::AutoLock auto_lock(lock_); |
939 has_audio_ = false; | 965 has_audio_ = false; |
940 audio_disabled_ = true; | 966 audio_disabled_ = true; |
941 | 967 |
942 // Notify all filters of disabled audio renderer. If the filter isn't | 968 // Notify all filters of disabled audio renderer. If the filter isn't |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1368 base::Bind(&PipelineImpl::OnFilterStateTransitionWithStatus, this); | 1394 base::Bind(&PipelineImpl::OnFilterStateTransitionWithStatus, this); |
1369 | 1395 |
1370 if (status == PIPELINE_OK && pipeline_filter_) { | 1396 if (status == PIPELINE_OK && pipeline_filter_) { |
1371 pipeline_filter_->Seek(seek_timestamp, done_cb); | 1397 pipeline_filter_->Seek(seek_timestamp, done_cb); |
1372 return; | 1398 return; |
1373 } | 1399 } |
1374 | 1400 |
1375 done_cb.Run(status); | 1401 done_cb.Run(status); |
1376 } | 1402 } |
1377 | 1403 |
1404 void PipelineImpl::NotifyCanPlayThroughIfNeeded() { | |
1405 if (!IsRunning() || !IsInitialized()) | |
1406 return; | |
1407 | |
1408 base::AutoLock auto_lock(lock_); | |
1409 if (!ShouldNotifyCanPlayThrough_Locked()) | |
1410 return; | |
1411 | |
1412 has_notified_can_play_through_ = true; | |
1413 message_loop_->PostTask(FROM_HERE, | |
acolwell GONE FROM CHROMIUM
2011/10/28 18:24:13
Do we need this PostTask? Aren't we always on the
vrk (LEFT CHROMIUM)
2011/11/01 21:57:34
I believe we are not on this thread for 2 out of 3
| |
1414 base::Bind( | |
1415 &PipelineImpl::NotifyNetworkEventTask, this, CAN_PLAY_THROUGH)); | |
1416 } | |
1417 | |
1418 int PipelineImpl::ApproximateDownloadRate_Locked() { | |
1419 lock_.AssertAcquired(); | |
1420 | |
1421 // Playback hasn't started yet. | |
1422 if (starting_time_.is_null()) | |
1423 return -1; | |
1424 | |
1425 float seconds_elapsed = (base::Time::Now() - starting_time_).InSecondsF(); | |
1426 DCHECK(seconds_elapsed >= 0); | |
1427 // Update approximation if pipeline is downloading data and has been | |
1428 // downloading data long enough to get an accurate estimate. | |
1429 // XXX: How many seconds should we wait to get an accurate reading? | |
1430 if (is_downloading_data_ && seconds_elapsed > 1) { | |
acolwell GONE FROM CHROMIUM
2011/10/28 18:24:13
Make the time elapsed threshold a constant and let
vrk (LEFT CHROMIUM)
2011/11/01 21:57:34
Done.
| |
1431 int bytes_downloaded = buffered_bytes_ - starting_bytes_loaded_; | |
1432 DCHECK(bytes_downloaded > 0); | |
acolwell GONE FROM CHROMIUM
2011/10/28 18:24:13
Should this really be a DCHECK? Shouldn't we just
vrk (LEFT CHROMIUM)
2011/11/01 21:57:34
Oops, the ">" was meant to be a ">=". Am fine with
| |
1433 last_approximate_download_rate_ = bytes_downloaded / seconds_elapsed; | |
1434 } | |
1435 return last_approximate_download_rate_; | |
1436 } | |
1437 | |
1438 bool PipelineImpl::ShouldNotifyCanPlayThrough_Locked() { | |
1439 lock_.AssertAcquired(); | |
1440 if (has_notified_can_play_through_ || total_bytes_ == 0) | |
acolwell GONE FROM CHROMIUM
2011/10/28 18:24:13
Might want to add a comment explaining what total_
vrk (LEFT CHROMIUM)
2011/11/01 21:57:34
Done.
| |
1441 return false; | |
1442 if (loaded_ || buffered_bytes_ == total_bytes_) | |
1443 return true; | |
1444 | |
1445 int download_rate = ApproximateDownloadRate_Locked(); | |
1446 // If download rate is unknown, cannot approximate when the media can play | |
1447 // through. | |
1448 if (download_rate == -1) | |
1449 return false; | |
1450 | |
1451 // If we are downloading at or faster than the media's bitrate, then we can | |
1452 // play through to the end of the media without stopping to buffer. | |
1453 int bitrate = demuxer_->GetBitrate(); | |
1454 if (download_rate > bitrate * 8) | |
acolwell GONE FROM CHROMIUM
2011/10/28 18:24:13
Shouldn't this be (8 * download_rate > bitrate) or
vrk (LEFT CHROMIUM)
2011/11/01 21:57:34
D'OH! Yes, absolutely. Done.
| |
1455 return true; | |
1456 | |
1457 // If the rate of downloading the media is slower than the rate at which the | |
1458 // media is being played back, see if there's enough data buffered to let the | |
1459 // media play through until the end without buffering. | |
1460 base::TimeDelta current_time = GetCurrentTime_Locked(); | |
1461 base::TimeDelta buffered_time = GetBufferedTime_Locked(); | |
1462 DCHECK(buffered_time >= current_time); | |
1463 float seconds_buffered = (buffered_time - current_time).InSecondsF(); | |
acolwell GONE FROM CHROMIUM
2011/10/28 18:24:13
std::max(..., 0) to protect the computation in rel
vrk (LEFT CHROMIUM)
2011/11/01 21:57:34
Done.
| |
1464 int bytes_downloaded_after_buffer_is_consumed = | |
acolwell GONE FROM CHROMIUM
2011/10/28 18:24:13
s/after/while/ ?
vrk (LEFT CHROMIUM)
2011/11/01 21:57:34
Done.
| |
1465 static_cast<int>(seconds_buffered * download_rate); | |
1466 int bytes_left_to_download = total_bytes_ - buffered_bytes_; | |
1467 | |
1468 return bytes_downloaded_after_buffer_is_consumed >= bytes_left_to_download; | |
1469 } | |
1470 | |
1378 } // namespace media | 1471 } // namespace media |
OLD | NEW |