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 "webkit/media/webmediaplayer_impl.h" | 5 #include "webkit/media/webmediaplayer_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 // the time bar. For really high speeds, audio becomes a bottleneck and we just | 74 // the time bar. For really high speeds, audio becomes a bottleneck and we just |
75 // use up the data we have, which may not achieve the speed requested, but will | 75 // use up the data we have, which may not achieve the speed requested, but will |
76 // not crash the tab. | 76 // not crash the tab. |
77 // | 77 // |
78 // A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems | 78 // A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems |
79 // like a busy loop). It gets unresponsive, although its not completely dead. | 79 // like a busy loop). It gets unresponsive, although its not completely dead. |
80 // | 80 // |
81 // Also our timers are not very accurate (especially for ogg), which becomes | 81 // Also our timers are not very accurate (especially for ogg), which becomes |
82 // evident at low speeds and on Vista. Since other speeds are risky and outside | 82 // evident at low speeds and on Vista. Since other speeds are risky and outside |
83 // the norms, we think 1/16x to 16x is a safe and useful range for now. | 83 // the norms, we think 1/16x to 16x is a safe and useful range for now. |
84 const float kMinRate = 0.0625f; | 84 const double kMinRate = 0.0625; |
85 const float kMaxRate = 16.0f; | 85 const double kMaxRate = 16.0; |
86 | 86 |
87 // Prefix for histograms related to Encrypted Media Extensions. | 87 // Prefix for histograms related to Encrypted Media Extensions. |
88 const char* kMediaEme = "Media.EME."; | 88 const char* kMediaEme = "Media.EME."; |
89 } // namespace | 89 } // namespace |
90 | 90 |
91 namespace webkit_media { | 91 namespace webkit_media { |
92 | 92 |
93 #define COMPILE_ASSERT_MATCHING_ENUM(name) \ | 93 #define COMPILE_ASSERT_MATCHING_ENUM(name) \ |
94 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \ | 94 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \ |
95 static_cast<int>(BufferedResourceLoader::k ## name), \ | 95 static_cast<int>(BufferedResourceLoader::k ## name), \ |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 | 368 |
369 bool WebMediaPlayerImpl::supportsSave() const { | 369 bool WebMediaPlayerImpl::supportsSave() const { |
370 DCHECK(main_loop_->BelongsToCurrentThread()); | 370 DCHECK(main_loop_->BelongsToCurrentThread()); |
371 return supports_save_; | 371 return supports_save_; |
372 } | 372 } |
373 | 373 |
374 void WebMediaPlayerImpl::seekFloat(float seconds) { | 374 void WebMediaPlayerImpl::seekFloat(float seconds) { |
375 seek(seconds); | 375 seek(seconds); |
376 } | 376 } |
377 | 377 |
378 void WebMediaPlayerImpl::seek(float seconds) { | 378 void WebMediaPlayerImpl::seek(double seconds) { |
379 DCHECK(main_loop_->BelongsToCurrentThread()); | 379 DCHECK(main_loop_->BelongsToCurrentThread()); |
380 | 380 |
381 if (starting_ || seeking_) { | 381 if (starting_ || seeking_) { |
382 pending_seek_ = true; | 382 pending_seek_ = true; |
383 pending_seek_seconds_ = seconds; | 383 pending_seek_seconds_ = seconds; |
384 if (chunk_demuxer_) | 384 if (chunk_demuxer_) |
385 chunk_demuxer_->CancelPendingSeek(); | 385 chunk_demuxer_->CancelPendingSeek(); |
386 return; | 386 return; |
387 } | 387 } |
388 | 388 |
(...skipping 13 matching lines...) Expand all Loading... |
402 // Kick off the asynchronous seek! | 402 // Kick off the asynchronous seek! |
403 pipeline_->Seek( | 403 pipeline_->Seek( |
404 seek_time, | 404 seek_time, |
405 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek)); | 405 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek)); |
406 } | 406 } |
407 | 407 |
408 void WebMediaPlayerImpl::setEndTimeFloat(float seconds) { | 408 void WebMediaPlayerImpl::setEndTimeFloat(float seconds) { |
409 setEndTime(seconds); | 409 setEndTime(seconds); |
410 } | 410 } |
411 | 411 |
412 void WebMediaPlayerImpl::setEndTime(float seconds) { | 412 void WebMediaPlayerImpl::setEndTime(double seconds) { |
413 DCHECK(main_loop_->BelongsToCurrentThread()); | 413 DCHECK(main_loop_->BelongsToCurrentThread()); |
414 | 414 |
415 // TODO(hclam): add method call when it has been implemented. | 415 // TODO(hclam): add method call when it has been implemented. |
416 return; | 416 return; |
417 } | 417 } |
418 | 418 |
419 void WebMediaPlayerImpl::setRateFloat(float rate) { | 419 void WebMediaPlayerImpl::setRateFloat(float rate) { |
420 setRate(rate); | 420 setRate(rate); |
421 } | 421 } |
422 | 422 |
423 void WebMediaPlayerImpl::setRate(float rate) { | 423 void WebMediaPlayerImpl::setRate(double rate) { |
424 DCHECK(main_loop_->BelongsToCurrentThread()); | 424 DCHECK(main_loop_->BelongsToCurrentThread()); |
425 | 425 |
426 // TODO(kylep): Remove when support for negatives is added. Also, modify the | 426 // TODO(kylep): Remove when support for negatives is added. Also, modify the |
427 // following checks so rewind uses reasonable values also. | 427 // following checks so rewind uses reasonable values also. |
428 if (rate < 0.0f) | 428 if (rate < 0.0) |
429 return; | 429 return; |
430 | 430 |
431 // Limit rates to reasonable values by clamping. | 431 // Limit rates to reasonable values by clamping. |
432 if (rate != 0.0f) { | 432 if (rate != 0.0) { |
433 if (rate < kMinRate) | 433 if (rate < kMinRate) |
434 rate = kMinRate; | 434 rate = kMinRate; |
435 else if (rate > kMaxRate) | 435 else if (rate > kMaxRate) |
436 rate = kMaxRate; | 436 rate = kMaxRate; |
437 } | 437 } |
438 | 438 |
439 playback_rate_ = rate; | 439 playback_rate_ = rate; |
440 if (!paused_) { | 440 if (!paused_) { |
441 pipeline_->SetPlaybackRate(rate); | 441 pipeline_->SetPlaybackRate(rate); |
442 } | 442 } |
443 } | 443 } |
444 | 444 |
445 void WebMediaPlayerImpl::setVolumeFloat(float volume) { | 445 void WebMediaPlayerImpl::setVolumeFloat(float volume) { |
446 setVolume(volume); | 446 setVolume(volume); |
447 } | 447 } |
448 | 448 |
449 void WebMediaPlayerImpl::setVolume(float volume) { | 449 void WebMediaPlayerImpl::setVolume(double volume) { |
450 DCHECK(main_loop_->BelongsToCurrentThread()); | 450 DCHECK(main_loop_->BelongsToCurrentThread()); |
451 | 451 |
452 pipeline_->SetVolume(volume); | 452 pipeline_->SetVolume(volume); |
453 } | 453 } |
454 | 454 |
455 void WebMediaPlayerImpl::setVisible(bool visible) { | 455 void WebMediaPlayerImpl::setVisible(bool visible) { |
456 DCHECK(main_loop_->BelongsToCurrentThread()); | 456 DCHECK(main_loop_->BelongsToCurrentThread()); |
457 | 457 |
458 // TODO(hclam): add appropriate method call when pipeline has it implemented. | 458 // TODO(hclam): add appropriate method call when pipeline has it implemented. |
459 return; | 459 return; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 bool WebMediaPlayerImpl::seeking() const { | 510 bool WebMediaPlayerImpl::seeking() const { |
511 DCHECK(main_loop_->BelongsToCurrentThread()); | 511 DCHECK(main_loop_->BelongsToCurrentThread()); |
512 | 512 |
513 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) | 513 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) |
514 return false; | 514 return false; |
515 | 515 |
516 return seeking_; | 516 return seeking_; |
517 } | 517 } |
518 | 518 |
519 float WebMediaPlayerImpl::durationFloat() const { | 519 float WebMediaPlayerImpl::durationFloat() const { |
520 return duration(); | |
521 } | |
522 | |
523 float WebMediaPlayerImpl::duration() const { | |
524 DCHECK(main_loop_->BelongsToCurrentThread()); | |
525 | |
526 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) | 520 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) |
527 return std::numeric_limits<float>::quiet_NaN(); | 521 return std::numeric_limits<float>::quiet_NaN(); |
528 | 522 |
529 double duration; | 523 double result = duration(); |
530 if (chunk_demuxer_) { | |
531 duration = chunk_demuxer_->GetDuration(); | |
532 } else { | |
533 duration = GetPipelineDuration(); | |
534 } | |
535 | 524 |
536 // Make sure super small durations don't get truncated to 0 and | 525 // Make sure super small durations don't get truncated to 0 and |
537 // large durations don't get converted to infinity by the double -> float | 526 // large durations don't get converted to infinity by the double -> float |
538 // conversion. | 527 // conversion. |
539 // | 528 // |
540 // TODO(acolwell): Remove when WebKit is changed to report duration as a | 529 // TODO(acolwell): Remove when WebKit is changed to report duration as a |
541 // double. | 530 // double. |
542 if (duration > 0.0 && duration < std::numeric_limits<double>::infinity()) { | 531 if (result > 0.0 && result < std::numeric_limits<double>::infinity()) { |
543 duration = std::max(duration, | 532 result = std::max(result, |
544 static_cast<double>(std::numeric_limits<float>::min())); | 533 static_cast<double>(std::numeric_limits<float>::min())); |
545 duration = std::min(duration, | 534 result = std::min(result, |
546 static_cast<double>(std::numeric_limits<float>::max())); | 535 static_cast<double>(std::numeric_limits<float>::max())); |
547 } | 536 } |
548 | 537 |
549 return static_cast<float>(duration); | 538 return static_cast<float>(result); |
| 539 |
| 540 } |
| 541 |
| 542 double WebMediaPlayerImpl::duration() const { |
| 543 DCHECK(main_loop_->BelongsToCurrentThread()); |
| 544 |
| 545 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) |
| 546 return std::numeric_limits<double>::quiet_NaN(); |
| 547 |
| 548 if (chunk_demuxer_) |
| 549 return chunk_demuxer_->GetDuration(); |
| 550 |
| 551 return GetPipelineDuration(); |
550 } | 552 } |
551 | 553 |
552 float WebMediaPlayerImpl::currentTimeFloat() const { | 554 float WebMediaPlayerImpl::currentTimeFloat() const { |
553 return currentTime(); | 555 return static_cast<float>(currentTime()); |
554 } | 556 } |
555 | 557 |
556 float WebMediaPlayerImpl::currentTime() const { | 558 double WebMediaPlayerImpl::currentTime() const { |
557 DCHECK(main_loop_->BelongsToCurrentThread()); | 559 DCHECK(main_loop_->BelongsToCurrentThread()); |
558 if (paused_) | 560 return (paused_ ? paused_time_ : pipeline_->GetMediaTime()).InSecondsF(); |
559 return static_cast<float>(paused_time_.InSecondsF()); | |
560 return static_cast<float>(pipeline_->GetMediaTime().InSecondsF()); | |
561 } | 561 } |
562 | 562 |
563 int WebMediaPlayerImpl::dataRate() const { | 563 int WebMediaPlayerImpl::dataRate() const { |
564 DCHECK(main_loop_->BelongsToCurrentThread()); | 564 DCHECK(main_loop_->BelongsToCurrentThread()); |
565 | 565 |
566 // TODO(hclam): Add this method call if pipeline has it in the interface. | 566 // TODO(hclam): Add this method call if pipeline has it in the interface. |
567 return 0; | 567 return 0; |
568 } | 568 } |
569 | 569 |
570 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const { | 570 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const { |
571 DCHECK(main_loop_->BelongsToCurrentThread()); | 571 DCHECK(main_loop_->BelongsToCurrentThread()); |
572 return network_state_; | 572 return network_state_; |
573 } | 573 } |
574 | 574 |
575 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const { | 575 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const { |
576 DCHECK(main_loop_->BelongsToCurrentThread()); | 576 DCHECK(main_loop_->BelongsToCurrentThread()); |
577 return ready_state_; | 577 return ready_state_; |
578 } | 578 } |
579 | 579 |
580 const WebKit::WebTimeRanges& WebMediaPlayerImpl::buffered() { | 580 const WebKit::WebTimeRanges& WebMediaPlayerImpl::buffered() { |
581 DCHECK(main_loop_->BelongsToCurrentThread()); | 581 DCHECK(main_loop_->BelongsToCurrentThread()); |
582 WebKit::WebTimeRanges web_ranges( | 582 WebKit::WebTimeRanges web_ranges( |
583 ConvertToWebTimeRanges(pipeline_->GetBufferedTimeRanges())); | 583 ConvertToWebTimeRanges(pipeline_->GetBufferedTimeRanges())); |
584 buffered_.swap(web_ranges); | 584 buffered_.swap(web_ranges); |
585 return buffered_; | 585 return buffered_; |
586 } | 586 } |
587 | 587 |
588 float WebMediaPlayerImpl::maxTimeSeekableFloat() const { | 588 float WebMediaPlayerImpl::maxTimeSeekableFloat() const { |
589 return maxTimeSeekable(); | |
590 } | |
591 | |
592 float WebMediaPlayerImpl::maxTimeSeekable() const { | |
593 DCHECK(main_loop_->BelongsToCurrentThread()); | 589 DCHECK(main_loop_->BelongsToCurrentThread()); |
594 | 590 |
595 // If we haven't even gotten to ReadyStateHaveMetadata yet then just | 591 // If we haven't even gotten to ReadyStateHaveMetadata yet then just |
596 // return 0 so that the seekable range is empty. | 592 // return 0 so that the seekable range is empty. |
597 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata) | 593 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata) |
598 return 0.0f; | 594 return 0.0f; |
599 | 595 |
600 // We don't support seeking in streaming media. | 596 // We don't support seeking in streaming media. |
601 if (data_source_ && data_source_->IsStreaming()) | 597 if (data_source_ && data_source_->IsStreaming()) |
602 return 0.0f; | 598 return 0.0f; |
| 599 return durationFloat(); |
| 600 } |
| 601 |
| 602 double WebMediaPlayerImpl::maxTimeSeekable() const { |
| 603 DCHECK(main_loop_->BelongsToCurrentThread()); |
| 604 |
| 605 // If we haven't even gotten to ReadyStateHaveMetadata yet then just |
| 606 // return 0 so that the seekable range is empty. |
| 607 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata) |
| 608 return 0.0; |
| 609 |
| 610 // We don't support seeking in streaming media. |
| 611 if (data_source_ && data_source_->IsStreaming()) |
| 612 return 0.0; |
603 return duration(); | 613 return duration(); |
604 } | 614 } |
605 | 615 |
606 bool WebMediaPlayerImpl::didLoadingProgress() const { | 616 bool WebMediaPlayerImpl::didLoadingProgress() const { |
607 DCHECK(main_loop_->BelongsToCurrentThread()); | 617 DCHECK(main_loop_->BelongsToCurrentThread()); |
608 return pipeline_->DidLoadingProgress(); | 618 return pipeline_->DidLoadingProgress(); |
609 } | 619 } |
610 | 620 |
611 unsigned long long WebMediaPlayerImpl::totalBytes() const { | 621 unsigned long long WebMediaPlayerImpl::totalBytes() const { |
612 DCHECK(main_loop_->BelongsToCurrentThread()); | 622 DCHECK(main_loop_->BelongsToCurrentThread()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 // Disable seeking while streaming. | 674 // Disable seeking while streaming. |
665 if (data_source_ && data_source_->IsStreaming()) | 675 if (data_source_ && data_source_->IsStreaming()) |
666 return WebMediaPlayer::MovieLoadTypeLiveStream; | 676 return WebMediaPlayer::MovieLoadTypeLiveStream; |
667 return WebMediaPlayer::MovieLoadTypeUnknown; | 677 return WebMediaPlayer::MovieLoadTypeUnknown; |
668 } | 678 } |
669 | 679 |
670 float WebMediaPlayerImpl::mediaTimeForTimeValueFloat(float timeValue) const { | 680 float WebMediaPlayerImpl::mediaTimeForTimeValueFloat(float timeValue) const { |
671 return mediaTimeForTimeValue(timeValue); | 681 return mediaTimeForTimeValue(timeValue); |
672 } | 682 } |
673 | 683 |
674 float WebMediaPlayerImpl::mediaTimeForTimeValue(float timeValue) const { | 684 double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const { |
675 return ConvertSecondsToTimestamp(timeValue).InSecondsF(); | 685 return ConvertSecondsToTimestamp(timeValue).InSecondsF(); |
676 } | 686 } |
677 | 687 |
678 unsigned WebMediaPlayerImpl::decodedFrameCount() const { | 688 unsigned WebMediaPlayerImpl::decodedFrameCount() const { |
679 DCHECK(main_loop_->BelongsToCurrentThread()); | 689 DCHECK(main_loop_->BelongsToCurrentThread()); |
680 | 690 |
681 media::PipelineStatistics stats = pipeline_->GetStatistics(); | 691 media::PipelineStatistics stats = pipeline_->GetStatistics(); |
682 return stats.video_frames_decoded; | 692 return stats.video_frames_decoded; |
683 } | 693 } |
684 | 694 |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 | 1280 |
1271 if (pending_repaint_) | 1281 if (pending_repaint_) |
1272 return; | 1282 return; |
1273 | 1283 |
1274 pending_repaint_ = true; | 1284 pending_repaint_ = true; |
1275 main_loop_->PostTask(FROM_HERE, base::Bind( | 1285 main_loop_->PostTask(FROM_HERE, base::Bind( |
1276 &WebMediaPlayerImpl::Repaint, AsWeakPtr())); | 1286 &WebMediaPlayerImpl::Repaint, AsWeakPtr())); |
1277 } | 1287 } |
1278 | 1288 |
1279 } // namespace webkit_media | 1289 } // namespace webkit_media |
OLD | NEW |