diff options
Diffstat (limited to 'content/renderer')
51 files changed, 39 insertions, 7651 deletions
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index e59e108..1f0e307 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn @@ -29,6 +29,7 @@ source_set("renderer") { "//gin", "//jingle:jingle_glue", "//media", + "//media/blink", "//mojo/bindings/js", "//mojo/environment:chromium", "//mojo/public/js/bindings", @@ -71,7 +72,6 @@ source_set("renderer") { sources -= [ "accessibility/renderer_accessibility_focus_only.cc", "media/audio_decoder.cc", - "media/webmediaplayer_impl.cc", ] sources += [ "external_popup_menu.cc", diff --git a/content/renderer/media/active_loader.cc b/content/renderer/media/active_loader.cc deleted file mode 100644 index 6951514..0000000 --- a/content/renderer/media/active_loader.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/active_loader.h" - -#include "content/renderer/media/buffered_resource_loader.h" -#include "third_party/WebKit/public/platform/WebURLLoader.h" - -namespace content { - -ActiveLoader::ActiveLoader(scoped_ptr<blink::WebURLLoader> loader) - : loader_(loader.Pass()), - deferred_(false) { -} - -ActiveLoader::~ActiveLoader() { - loader_->cancel(); -} - -void ActiveLoader::SetDeferred(bool deferred) { - deferred_ = deferred; - loader_->setDefersLoading(deferred); -} - -} // namespace content diff --git a/content/renderer/media/active_loader.h b/content/renderer/media/active_loader.h deleted file mode 100644 index 1c30214..0000000 --- a/content/renderer/media/active_loader.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_ACTIVE_LOADER_H_ -#define CONTENT_RENDERER_MEDIA_ACTIVE_LOADER_H_ - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" - -namespace blink { -class WebURLLoader; -} - -namespace content { - -// Wraps an active WebURLLoader with some additional state. -// -// Handles deferring and deletion of loaders. -class ActiveLoader { - public: - // Creates an ActiveLoader with the given loader. It is assumed that the - // initial state of |loader| is loading and not deferred. - explicit ActiveLoader(scoped_ptr<blink::WebURLLoader> loader); - ~ActiveLoader(); - - // Starts or stops deferring the resource load. - void SetDeferred(bool deferred); - bool deferred() { return deferred_; } - - private: - friend class BufferedDataSourceTest; - - scoped_ptr<blink::WebURLLoader> loader_; - bool deferred_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(ActiveLoader); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_ACTIVE_LOADER_H_ diff --git a/content/renderer/media/android/media_info_loader.cc b/content/renderer/media/android/media_info_loader.cc index ce3a299..95fed0b 100644 --- a/content/renderer/media/android/media_info_loader.cc +++ b/content/renderer/media/android/media_info_loader.cc @@ -83,7 +83,7 @@ void MediaInfoLoader::Start(blink::WebFrame* frame) { // Start the resource loading. loader->loadAsynchronously(request, this); - active_loader_.reset(new ActiveLoader(loader.Pass())); + active_loader_.reset(new media::ActiveLoader(loader.Pass())); } ///////////////////////////////////////////////////////////////////////////// diff --git a/content/renderer/media/android/media_info_loader.h b/content/renderer/media/android/media_info_loader.h index caefc9d..b421fb3 100644 --- a/content/renderer/media/android/media_info_loader.h +++ b/content/renderer/media/android/media_info_loader.h @@ -11,7 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "content/common/content_export.h" -#include "content/renderer/media/active_loader.h" +#include "media/blink/active_loader.h" #include "third_party/WebKit/public/platform/WebMediaPlayer.h" #include "third_party/WebKit/public/platform/WebURLLoaderClient.h" #include "third_party/WebKit/public/web/WebDocument.h" @@ -113,7 +113,7 @@ class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient { scoped_ptr<blink::WebURLLoader> test_loader_; // Keeps track of an active WebURLLoader and associated state. - scoped_ptr<ActiveLoader> active_loader_; + scoped_ptr<media::ActiveLoader> active_loader_; bool loader_failed_; GURL url_; diff --git a/content/renderer/media/android/media_source_delegate.cc b/content/renderer/media/android/media_source_delegate.cc index 9e6d954..6b1f206 100644 --- a/content/renderer/media/android/media_source_delegate.cc +++ b/content/renderer/media/android/media_source_delegate.cc @@ -11,12 +11,12 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/strings/string_number_conversions.h" #include "content/renderer/media/android/renderer_demuxer_android.h" -#include "content/renderer/media/webmediaplayer_util.h" -#include "content/renderer/media/webmediasource_impl.h" #include "media/base/android/demuxer_stream_player_params.h" #include "media/base/bind_to_current_loop.h" #include "media/base/demuxer_stream.h" #include "media/base/media_log.h" +#include "media/blink/webmediaplayer_util.h" +#include "media/blink/webmediasource_impl.h" #include "media/filters/chunk_demuxer.h" #include "media/filters/decrypting_demuxer_stream.h" #include "third_party/WebKit/public/platform/WebString.h" @@ -189,7 +189,7 @@ void MediaSourceDelegate::InitializeDemuxer() { } blink::WebTimeRanges MediaSourceDelegate::Buffered() const { - return ConvertToWebTimeRanges(buffered_time_ranges_); + return media::ConvertToWebTimeRanges(buffered_time_ranges_); } size_t MediaSourceDelegate::DecodedFrameCount() const { @@ -662,7 +662,7 @@ base::TimeDelta MediaSourceDelegate::GetDuration() const { if (duration == std::numeric_limits<double>::infinity()) return media::kInfiniteDuration(); - return ConvertSecondsToTimestamp(duration); + return media::ConvertSecondsToTimestamp(duration); } void MediaSourceDelegate::OnDemuxerOpened() { @@ -670,7 +670,7 @@ void MediaSourceDelegate::OnDemuxerOpened() { if (media_source_opened_cb_.is_null()) return; - media_source_opened_cb_.Run(new WebMediaSourceImpl( + media_source_opened_cb_.Run(new media::WebMediaSourceImpl( chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_))); } diff --git a/content/renderer/media/android/webmediaplayer_android.cc b/content/renderer/media/android/webmediaplayer_android.cc index 6b3a589..67aa9b0 100644 --- a/content/renderer/media/android/webmediaplayer_android.cc +++ b/content/renderer/media/android/webmediaplayer_android.cc @@ -26,8 +26,6 @@ #include "content/renderer/media/crypto/key_systems.h" #include "content/renderer/media/crypto/renderer_cdm_manager.h" #include "content/renderer/media/webcontentdecryptionmodule_impl.h" -#include "content/renderer/media/webmediaplayer_delegate.h" -#include "content/renderer/media/webmediaplayer_util.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" #include "gpu/GLES2/gl2extchromium.h" @@ -40,6 +38,8 @@ #include "media/base/media_log.h" #include "media/base/media_switches.h" #include "media/base/video_frame.h" +#include "media/blink/webmediaplayer_delegate.h" +#include "media/blink/webmediaplayer_util.h" #include "net/base/mime_util.h" #include "third_party/WebKit/public/platform/Platform.h" #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" @@ -111,7 +111,7 @@ namespace content { WebMediaPlayerAndroid::WebMediaPlayerAndroid( blink::WebFrame* frame, blink::WebMediaPlayerClient* client, - base::WeakPtr<WebMediaPlayerDelegate> delegate, + base::WeakPtr<media::WebMediaPlayerDelegate> delegate, RendererMediaPlayerManager* player_manager, RendererCdmManager* cdm_manager, scoped_refptr<StreamTextureFactory> factory, @@ -200,7 +200,7 @@ void WebMediaPlayerAndroid::load(LoadType load_type, const blink::WebURL& url, CORSMode cors_mode) { DCHECK(main_thread_checker_.CalledOnValidThread()); - ReportMediaSchemeUma(GURL(url)); + media::ReportMediaSchemeUma(GURL(url)); switch (load_type) { case LoadTypeURL: @@ -331,7 +331,7 @@ void WebMediaPlayerAndroid::seek(double seconds) { DCHECK(main_thread_checker_.CalledOnValidThread()); DVLOG(1) << __FUNCTION__ << "(" << seconds << ")"; - base::TimeDelta new_seek_time = ConvertSecondsToTimestamp(seconds); + base::TimeDelta new_seek_time = media::ConvertSecondsToTimestamp(seconds); if (seeking_) { if (new_seek_time == seek_time_) { @@ -672,7 +672,7 @@ bool WebMediaPlayerAndroid::didPassCORSAccessCheck() const { } double WebMediaPlayerAndroid::mediaTimeForTimeValue(double timeValue) const { - return ConvertSecondsToTimestamp(timeValue).InSecondsF(); + return media::ConvertSecondsToTimestamp(timeValue).InSecondsF(); } unsigned WebMediaPlayerAndroid::decodedFrameCount() const { diff --git a/content/renderer/media/android/webmediaplayer_android.h b/content/renderer/media/android/webmediaplayer_android.h index b3864e6..bf290b7 100644 --- a/content/renderer/media/android/webmediaplayer_android.h +++ b/content/renderer/media/android/webmediaplayer_android.h @@ -56,13 +56,13 @@ struct MailboxHolder; namespace media { class MediaLog; +class WebMediaPlayerDelegate; } namespace content { class RendererCdmManager; class RendererMediaPlayerManager; class WebContentDecryptionModuleImpl; -class WebMediaPlayerDelegate; // This class implements blink::WebMediaPlayer by keeping the android // media player in the browser process. It listens to all the status changes @@ -81,7 +81,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer, WebMediaPlayerAndroid( blink::WebFrame* frame, blink::WebMediaPlayerClient* client, - base::WeakPtr<WebMediaPlayerDelegate> delegate, + base::WeakPtr<media::WebMediaPlayerDelegate> delegate, RendererMediaPlayerManager* player_manager, RendererCdmManager* cdm_manager, scoped_refptr<StreamTextureFactory> factory, @@ -331,7 +331,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer, // TODO(qinmin): Currently android mediaplayer takes care of the screen // lock. So this is only used for media source. Will apply this to regular // media tag once http://crbug.com/247892 is fixed. - base::WeakPtr<WebMediaPlayerDelegate> delegate_; + base::WeakPtr<media::WebMediaPlayerDelegate> delegate_; // Save the list of buffered time ranges. blink::WebTimeRanges buffered_; diff --git a/content/renderer/media/buffered_data_source.cc b/content/renderer/media/buffered_data_source.cc deleted file mode 100644 index 5fc0c59..0000000 --- a/content/renderer/media/buffered_data_source.cc +++ /dev/null @@ -1,536 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/buffered_data_source.h" - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/single_thread_task_runner.h" -#include "content/public/common/url_constants.h" -#include "media/base/media_log.h" -#include "net/base/net_errors.h" - -using blink::WebFrame; - -namespace { - -// BufferedDataSource has an intermediate buffer, this value governs the initial -// size of that buffer. It is set to 32KB because this is a typical read size -// of FFmpeg. -const int kInitialReadBufferSize = 32768; - -// Number of cache misses we allow for a single Read() before signaling an -// error. -const int kNumCacheMissRetries = 3; - -} // namespace - -namespace content { - -class BufferedDataSource::ReadOperation { - public: - ReadOperation(int64 position, int size, uint8* data, - const media::DataSource::ReadCB& callback); - ~ReadOperation(); - - // Runs |callback_| with the given |result|, deleting the operation - // afterwards. - static void Run(scoped_ptr<ReadOperation> read_op, int result); - - // State for the number of times this read operation has been retried. - int retries() { return retries_; } - void IncrementRetries() { ++retries_; } - - int64 position() { return position_; } - int size() { return size_; } - uint8* data() { return data_; } - - private: - int retries_; - - const int64 position_; - const int size_; - uint8* data_; - media::DataSource::ReadCB callback_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(ReadOperation); -}; - -BufferedDataSource::ReadOperation::ReadOperation( - int64 position, int size, uint8* data, - const media::DataSource::ReadCB& callback) - : retries_(0), - position_(position), - size_(size), - data_(data), - callback_(callback) { - DCHECK(!callback_.is_null()); -} - -BufferedDataSource::ReadOperation::~ReadOperation() { - DCHECK(callback_.is_null()); -} - -// static -void BufferedDataSource::ReadOperation::Run( - scoped_ptr<ReadOperation> read_op, int result) { - base::ResetAndReturn(&read_op->callback_).Run(result); -} - -BufferedDataSource::BufferedDataSource( - const GURL& url, - BufferedResourceLoader::CORSMode cors_mode, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - WebFrame* frame, - media::MediaLog* media_log, - BufferedDataSourceHost* host, - const DownloadingCB& downloading_cb) - : url_(url), - cors_mode_(cors_mode), - total_bytes_(kPositionNotSpecified), - streaming_(false), - frame_(frame), - intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), - intermediate_read_buffer_size_(kInitialReadBufferSize), - render_task_runner_(task_runner), - stop_signal_received_(false), - media_has_played_(false), - preload_(AUTO), - bitrate_(0), - playback_rate_(0.0), - media_log_(media_log), - host_(host), - downloading_cb_(downloading_cb), - weak_factory_(this) { - DCHECK(host_); - DCHECK(!downloading_cb_.is_null()); -} - -BufferedDataSource::~BufferedDataSource() {} - -// A factory method to create BufferedResourceLoader using the read parameters. -// This method can be overridden to inject mock BufferedResourceLoader object -// for testing purpose. -BufferedResourceLoader* BufferedDataSource::CreateResourceLoader( - int64 first_byte_position, int64 last_byte_position) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - - BufferedResourceLoader::DeferStrategy strategy = preload_ == METADATA ? - BufferedResourceLoader::kReadThenDefer : - BufferedResourceLoader::kCapacityDefer; - - return new BufferedResourceLoader(url_, - cors_mode_, - first_byte_position, - last_byte_position, - strategy, - bitrate_, - playback_rate_, - media_log_.get()); -} - -void BufferedDataSource::Initialize(const InitializeCB& init_cb) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - DCHECK(!init_cb.is_null()); - DCHECK(!loader_.get()); - - init_cb_ = init_cb; - - if (url_.SchemeIsHTTPOrHTTPS()) { - // Do an unbounded range request starting at the beginning. If the server - // responds with 200 instead of 206 we'll fall back into a streaming mode. - loader_.reset(CreateResourceLoader(0, kPositionNotSpecified)); - } else { - // For all other protocols, assume they support range request. We fetch - // the full range of the resource to obtain the instance size because - // we won't be served HTTP headers. - loader_.reset(CreateResourceLoader(kPositionNotSpecified, - kPositionNotSpecified)); - } - - base::WeakPtr<BufferedDataSource> weak_this = weak_factory_.GetWeakPtr(); - loader_->Start( - base::Bind(&BufferedDataSource::StartCallback, weak_this), - base::Bind(&BufferedDataSource::LoadingStateChangedCallback, weak_this), - base::Bind(&BufferedDataSource::ProgressCallback, weak_this), - frame_); -} - -void BufferedDataSource::SetPreload(Preload preload) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - preload_ = preload; -} - -bool BufferedDataSource::HasSingleOrigin() { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - DCHECK(init_cb_.is_null() && loader_.get()) - << "Initialize() must complete before calling HasSingleOrigin()"; - return loader_->HasSingleOrigin(); -} - -bool BufferedDataSource::DidPassCORSAccessCheck() const { - return loader_.get() && loader_->DidPassCORSAccessCheck(); -} - -void BufferedDataSource::Abort() { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - { - base::AutoLock auto_lock(lock_); - StopInternal_Locked(); - } - StopLoader(); - frame_ = NULL; -} - -void BufferedDataSource::MediaPlaybackRateChanged(float playback_rate) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - DCHECK(loader_.get()); - - if (playback_rate < 0.0f) - return; - - playback_rate_ = playback_rate; - loader_->SetPlaybackRate(playback_rate); -} - -void BufferedDataSource::MediaIsPlaying() { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - media_has_played_ = true; - UpdateDeferStrategy(false); -} - -void BufferedDataSource::MediaIsPaused() { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - UpdateDeferStrategy(true); -} - -///////////////////////////////////////////////////////////////////////////// -// media::DataSource implementation. -void BufferedDataSource::Stop() { - { - base::AutoLock auto_lock(lock_); - StopInternal_Locked(); - } - - render_task_runner_->PostTask( - FROM_HERE, - base::Bind(&BufferedDataSource::StopLoader, weak_factory_.GetWeakPtr())); -} - -void BufferedDataSource::SetBitrate(int bitrate) { - render_task_runner_->PostTask(FROM_HERE, - base::Bind(&BufferedDataSource::SetBitrateTask, - weak_factory_.GetWeakPtr(), - bitrate)); -} - -void BufferedDataSource::Read( - int64 position, int size, uint8* data, - const media::DataSource::ReadCB& read_cb) { - DVLOG(1) << "Read: " << position << " offset, " << size << " bytes"; - DCHECK(!read_cb.is_null()); - - { - base::AutoLock auto_lock(lock_); - DCHECK(!read_op_); - - if (stop_signal_received_) { - read_cb.Run(kReadError); - return; - } - - read_op_.reset(new ReadOperation(position, size, data, read_cb)); - } - - render_task_runner_->PostTask( - FROM_HERE, - base::Bind(&BufferedDataSource::ReadTask, weak_factory_.GetWeakPtr())); -} - -bool BufferedDataSource::GetSize(int64* size_out) { - if (total_bytes_ != kPositionNotSpecified) { - *size_out = total_bytes_; - return true; - } - *size_out = 0; - return false; -} - -bool BufferedDataSource::IsStreaming() { - return streaming_; -} - -///////////////////////////////////////////////////////////////////////////// -// Render thread tasks. -void BufferedDataSource::ReadTask() { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - ReadInternal(); -} - -void BufferedDataSource::StopInternal_Locked() { - lock_.AssertAcquired(); - if (stop_signal_received_) - return; - - stop_signal_received_ = true; - - // Initialize() isn't part of the DataSource interface so don't call it in - // response to Stop(). - init_cb_.Reset(); - - if (read_op_) - ReadOperation::Run(read_op_.Pass(), kReadError); -} - -void BufferedDataSource::StopLoader() { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - - if (loader_) - loader_->Stop(); -} - -void BufferedDataSource::SetBitrateTask(int bitrate) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - DCHECK(loader_.get()); - - bitrate_ = bitrate; - loader_->SetBitrate(bitrate); -} - -// This method is the place where actual read happens, |loader_| must be valid -// prior to make this method call. -void BufferedDataSource::ReadInternal() { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - int64 position = 0; - int size = 0; - { - base::AutoLock auto_lock(lock_); - if (stop_signal_received_) - return; - - position = read_op_->position(); - size = read_op_->size(); - } - - // First we prepare the intermediate read buffer for BufferedResourceLoader - // to write to. - if (size > intermediate_read_buffer_size_) { - intermediate_read_buffer_.reset(new uint8[size]); - } - - // Perform the actual read with BufferedResourceLoader. - loader_->Read(position, - size, - intermediate_read_buffer_.get(), - base::Bind(&BufferedDataSource::ReadCallback, - weak_factory_.GetWeakPtr())); -} - - -///////////////////////////////////////////////////////////////////////////// -// BufferedResourceLoader callback methods. -void BufferedDataSource::StartCallback( - BufferedResourceLoader::Status status) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - DCHECK(loader_.get()); - - bool init_cb_is_null = false; - { - base::AutoLock auto_lock(lock_); - init_cb_is_null = init_cb_.is_null(); - } - if (init_cb_is_null) { - loader_->Stop(); - return; - } - - // All responses must be successful. Resources that are assumed to be fully - // buffered must have a known content length. - bool success = status == BufferedResourceLoader::kOk && - (!assume_fully_buffered() || - loader_->instance_size() != kPositionNotSpecified); - - if (success) { - total_bytes_ = loader_->instance_size(); - streaming_ = - !assume_fully_buffered() && - (total_bytes_ == kPositionNotSpecified || !loader_->range_supported()); - - media_log_->SetDoubleProperty("total_bytes", - static_cast<double>(total_bytes_)); - media_log_->SetBooleanProperty("streaming", streaming_); - } else { - loader_->Stop(); - } - - // TODO(scherkus): we shouldn't have to lock to signal host(), see - // http://crbug.com/113712 for details. - base::AutoLock auto_lock(lock_); - if (stop_signal_received_) - return; - - if (success) { - if (total_bytes_ != kPositionNotSpecified) { - host_->SetTotalBytes(total_bytes_); - if (assume_fully_buffered()) - host_->AddBufferedByteRange(0, total_bytes_); - } - - media_log_->SetBooleanProperty("single_origin", loader_->HasSingleOrigin()); - media_log_->SetBooleanProperty("passed_cors_access_check", - loader_->DidPassCORSAccessCheck()); - media_log_->SetBooleanProperty("range_header_supported", - loader_->range_supported()); - } - - base::ResetAndReturn(&init_cb_).Run(success); -} - -void BufferedDataSource::PartialReadStartCallback( - BufferedResourceLoader::Status status) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - DCHECK(loader_.get()); - - if (status == BufferedResourceLoader::kOk) { - // Once the request has started successfully, we can proceed with - // reading from it. - ReadInternal(); - return; - } - - // Stop the resource loader since we have received an error. - loader_->Stop(); - - // TODO(scherkus): we shouldn't have to lock to signal host(), see - // http://crbug.com/113712 for details. - base::AutoLock auto_lock(lock_); - if (stop_signal_received_) - return; - ReadOperation::Run(read_op_.Pass(), kReadError); -} - -void BufferedDataSource::ReadCallback( - BufferedResourceLoader::Status status, - int bytes_read) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - - // TODO(scherkus): we shouldn't have to lock to signal host(), see - // http://crbug.com/113712 for details. - base::AutoLock auto_lock(lock_); - if (stop_signal_received_) - return; - - if (status != BufferedResourceLoader::kOk) { - // Stop the resource load if it failed. - loader_->Stop(); - - if (status == BufferedResourceLoader::kCacheMiss && - read_op_->retries() < kNumCacheMissRetries) { - read_op_->IncrementRetries(); - - // Recreate a loader starting from where we last left off until the - // end of the resource. - loader_.reset(CreateResourceLoader( - read_op_->position(), kPositionNotSpecified)); - - base::WeakPtr<BufferedDataSource> weak_this = weak_factory_.GetWeakPtr(); - loader_->Start( - base::Bind(&BufferedDataSource::PartialReadStartCallback, weak_this), - base::Bind(&BufferedDataSource::LoadingStateChangedCallback, - weak_this), - base::Bind(&BufferedDataSource::ProgressCallback, weak_this), - frame_); - return; - } - - ReadOperation::Run(read_op_.Pass(), kReadError); - return; - } - - if (bytes_read > 0) { - memcpy(read_op_->data(), intermediate_read_buffer_.get(), bytes_read); - } else if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) { - // We've reached the end of the file and we didn't know the total size - // before. Update the total size so Read()s past the end of the file will - // fail like they would if we had known the file size at the beginning. - total_bytes_ = loader_->instance_size(); - - if (total_bytes_ != kPositionNotSpecified) { - host_->SetTotalBytes(total_bytes_); - host_->AddBufferedByteRange(loader_->first_byte_position(), - total_bytes_); - } - } - ReadOperation::Run(read_op_.Pass(), bytes_read); -} - -void BufferedDataSource::LoadingStateChangedCallback( - BufferedResourceLoader::LoadingState state) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - - if (assume_fully_buffered()) - return; - - bool is_downloading_data; - switch (state) { - case BufferedResourceLoader::kLoading: - is_downloading_data = true; - break; - case BufferedResourceLoader::kLoadingDeferred: - case BufferedResourceLoader::kLoadingFinished: - is_downloading_data = false; - break; - - // TODO(scherkus): we don't signal network activity changes when loads - // fail to preserve existing behaviour when deferring is toggled, however - // we should consider changing DownloadingCB to also propagate loading - // state. For example there isn't any signal today to notify the client that - // loading has failed (we only get errors on subsequent reads). - case BufferedResourceLoader::kLoadingFailed: - return; - } - - downloading_cb_.Run(is_downloading_data); -} - -void BufferedDataSource::ProgressCallback(int64 position) { - DCHECK(render_task_runner_->BelongsToCurrentThread()); - - if (assume_fully_buffered()) - return; - - // TODO(scherkus): we shouldn't have to lock to signal host(), see - // http://crbug.com/113712 for details. - base::AutoLock auto_lock(lock_); - if (stop_signal_received_) - return; - - host_->AddBufferedByteRange(loader_->first_byte_position(), position); -} - -void BufferedDataSource::UpdateDeferStrategy(bool paused) { - // No need to aggressively buffer when we are assuming the resource is fully - // buffered. - if (assume_fully_buffered()) { - loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); - return; - } - - // If the playback has started (at which point the preload value is ignored) - // and we're paused, then try to load as much as possible (the loader will - // fall back to kCapacityDefer if it knows the current response won't be - // useful from the cache in the future). - if (media_has_played_ && paused && loader_->range_supported()) { - loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); - return; - } - - // If media is currently playing or the page indicated preload=auto or the - // the server does not support the byte range request or we do not want to go - // too far ahead of the read head, use threshold strategy to enable/disable - // deferring when the buffer is full/depleted. - loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); -} - -} // namespace content diff --git a/content/renderer/media/buffered_data_source.h b/content/renderer/media/buffered_data_source.h deleted file mode 100644 index c2fd174..0000000 --- a/content/renderer/media/buffered_data_source.h +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_H_ -#define CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_H_ - -#include <string> - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" -#include "content/common/content_export.h" -#include "content/renderer/media/buffered_resource_loader.h" -#include "media/base/data_source.h" -#include "media/base/ranges.h" -#include "url/gurl.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace media { -class MediaLog; -} - -namespace content { - -class CONTENT_EXPORT BufferedDataSourceHost { - public: - // Notify the host of the total size of the media file. - virtual void SetTotalBytes(int64 total_bytes) = 0; - - // Notify the host that byte range [start,end] has been buffered. - // TODO(fischman): remove this method when demuxing is push-based instead of - // pull-based. http://crbug.com/131444 - virtual void AddBufferedByteRange(int64 start, int64 end) = 0; - - protected: - virtual ~BufferedDataSourceHost() {}; -}; - -// A data source capable of loading URLs and buffering the data using an -// in-memory sliding window. -// -// BufferedDataSource must be created and initialized on the render thread -// before being passed to other threads. It may be deleted on any thread. -class CONTENT_EXPORT BufferedDataSource : public media::DataSource { - public: - // Used to specify video preload states. They are "hints" to the browser about - // how aggressively the browser should load and buffer data. - // Please see the HTML5 spec for the descriptions of these values: - // http://www.w3.org/TR/html5/video.html#attr-media-preload - // - // Enum values must match the values in blink::WebMediaPlayer::Preload and - // there will be assertions at compile time if they do not match. - enum Preload { - NONE, - METADATA, - AUTO, - }; - typedef base::Callback<void(bool)> DownloadingCB; - - // |url| and |cors_mode| are passed to the object. Buffered byte range changes - // will be reported to |host|. |downloading_cb| will be called whenever the - // downloading/paused state of the source changes. - BufferedDataSource( - const GURL& url, - BufferedResourceLoader::CORSMode cors_mode, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - blink::WebFrame* frame, - media::MediaLog* media_log, - BufferedDataSourceHost* host, - const DownloadingCB& downloading_cb); - virtual ~BufferedDataSource(); - - // Executes |init_cb| with the result of initialization when it has completed. - // - // Method called on the render thread. - typedef base::Callback<void(bool)> InitializeCB; - void Initialize(const InitializeCB& init_cb); - - // Adjusts the buffering algorithm based on the given preload value. - void SetPreload(Preload preload); - - // Returns true if the media resource has a single origin, false otherwise. - // Only valid to call after Initialize() has completed. - // - // Method called on the render thread. - bool HasSingleOrigin(); - - // Returns true if the media resource passed a CORS access control check. - bool DidPassCORSAccessCheck() const; - - // Cancels initialization, any pending loaders, and any pending read calls - // from the demuxer. The caller is expected to release its reference to this - // object and never call it again. - // - // Method called on the render thread. - void Abort(); - - // Notifies changes in playback state for controlling media buffering - // behavior. - void MediaPlaybackRateChanged(float playback_rate); - void MediaIsPlaying(); - void MediaIsPaused(); - - // Returns true if the resource is local. - bool assume_fully_buffered() { return !url_.SchemeIsHTTPOrHTTPS(); } - - // media::DataSource implementation. - // Called from demuxer thread. - virtual void Stop() OVERRIDE; - - virtual void Read(int64 position, int size, uint8* data, - const media::DataSource::ReadCB& read_cb) OVERRIDE; - virtual bool GetSize(int64* size_out) OVERRIDE; - virtual bool IsStreaming() OVERRIDE; - virtual void SetBitrate(int bitrate) OVERRIDE; - - protected: - // A factory method to create a BufferedResourceLoader based on the read - // parameters. We can override this file to object a mock - // BufferedResourceLoader for testing. - virtual BufferedResourceLoader* CreateResourceLoader( - int64 first_byte_position, int64 last_byte_position); - - private: - friend class BufferedDataSourceTest; - - // Task posted to perform actual reading on the render thread. - void ReadTask(); - - // Cancels oustanding callbacks and sets |stop_signal_received_|. Safe to call - // from any thread. - void StopInternal_Locked(); - - // Stops |loader_| if present. Used by Abort() and Stop(). - void StopLoader(); - - // Tells |loader_| the bitrate of the media. - void SetBitrateTask(int bitrate); - - // The method that performs actual read. This method can only be executed on - // the render thread. - void ReadInternal(); - - // BufferedResourceLoader::Start() callback for initial load. - void StartCallback(BufferedResourceLoader::Status status); - - // BufferedResourceLoader::Start() callback for subsequent loads (i.e., - // when accessing ranges that are outside initial buffered region). - void PartialReadStartCallback(BufferedResourceLoader::Status status); - - // BufferedResourceLoader callbacks. - void ReadCallback(BufferedResourceLoader::Status status, int bytes_read); - void LoadingStateChangedCallback(BufferedResourceLoader::LoadingState state); - void ProgressCallback(int64 position); - - // Update |loader_|'s deferring strategy in response to a play/pause, or - // change in playback rate. - void UpdateDeferStrategy(bool paused); - - // URL of the resource requested. - GURL url_; - // crossorigin attribute on the corresponding HTML media element, if any. - BufferedResourceLoader::CORSMode cors_mode_; - - // The total size of the resource. Set during StartCallback() if the size is - // known, otherwise it will remain kPositionNotSpecified until the size is - // determined by reaching EOF. - int64 total_bytes_; - - // This value will be true if this data source can only support streaming. - // i.e. range request is not supported. - bool streaming_; - - // A webframe for loading. - blink::WebFrame* frame_; - - // A resource loader for the media resource. - scoped_ptr<BufferedResourceLoader> loader_; - - // Callback method from the pipeline for initialization. - InitializeCB init_cb_; - - // Read parameters received from the Read() method call. Must be accessed - // under |lock_|. - class ReadOperation; - scoped_ptr<ReadOperation> read_op_; - - // This buffer is intermediate, we use it for BufferedResourceLoader to write - // to. And when read in BufferedResourceLoader is done, we copy data from - // this buffer to |read_buffer_|. The reason for an additional copy is that - // we don't own |read_buffer_|. But since the read operation is asynchronous, - // |read_buffer| can be destroyed at any time, so we only copy into - // |read_buffer| in the final step when it is safe. - // Memory is allocated for this member during initialization of this object - // because we want buffer to be passed into BufferedResourceLoader to be - // always non-null. And by initializing this member with a default size we can - // avoid creating zero-sized buffered if the first read has zero size. - scoped_ptr<uint8[]> intermediate_read_buffer_; - int intermediate_read_buffer_size_; - - // The task runner of the render thread. - const scoped_refptr<base::SingleThreadTaskRunner> render_task_runner_; - - // Protects |stop_signal_received_| and |read_op_|. - base::Lock lock_; - - // Whether we've been told to stop via Abort() or Stop(). - bool stop_signal_received_; - - // This variable is true when the user has requested the video to play at - // least once. - bool media_has_played_; - - // This variable holds the value of the preload attribute for the video - // element. - Preload preload_; - - // Bitrate of the content, 0 if unknown. - int bitrate_; - - // Current playback rate. - float playback_rate_; - - scoped_refptr<media::MediaLog> media_log_; - - // Host object to report buffered byte range changes to. - BufferedDataSourceHost* host_; - - DownloadingCB downloading_cb_; - - // NOTE: Weak pointers must be invalidated before all other member variables. - base::WeakPtrFactory<BufferedDataSource> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(BufferedDataSource); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_H_ diff --git a/content/renderer/media/buffered_data_source_host_impl.cc b/content/renderer/media/buffered_data_source_host_impl.cc deleted file mode 100644 index 3ffee07..0000000 --- a/content/renderer/media/buffered_data_source_host_impl.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/buffered_data_source_host_impl.h" - -namespace content { - -BufferedDataSourceHostImpl::BufferedDataSourceHostImpl() - : total_bytes_(0), - did_loading_progress_(false) { } - -BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() { } - -void BufferedDataSourceHostImpl::SetTotalBytes(int64 total_bytes) { - total_bytes_ = total_bytes; -} - -void BufferedDataSourceHostImpl::AddBufferedByteRange(int64 start, int64 end) { - buffered_byte_ranges_.Add(start, end); - did_loading_progress_ = true; -} - -static base::TimeDelta TimeForByteOffset( - int64 byte_offset, int64 total_bytes, base::TimeDelta duration) { - double position = static_cast<double>(byte_offset) / total_bytes; - // Snap to the beginning/end where the approximation can look especially bad. - if (position < 0.01) - return base::TimeDelta(); - if (position > 0.99) - return duration; - return base::TimeDelta::FromMilliseconds( - static_cast<int64>(position * duration.InMilliseconds())); -} - -void BufferedDataSourceHostImpl::AddBufferedTimeRanges( - media::Ranges<base::TimeDelta>* buffered_time_ranges, - base::TimeDelta media_duration) const { - DCHECK(media_duration != media::kNoTimestamp()); - DCHECK(media_duration != media::kInfiniteDuration()); - if (total_bytes_ && buffered_byte_ranges_.size()) { - for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i) { - int64 start = buffered_byte_ranges_.start(i); - int64 end = buffered_byte_ranges_.end(i); - buffered_time_ranges->Add( - TimeForByteOffset(start, total_bytes_, media_duration), - TimeForByteOffset(end, total_bytes_, media_duration)); - } - } -} - -bool BufferedDataSourceHostImpl::DidLoadingProgress() { - bool ret = did_loading_progress_; - did_loading_progress_ = false; - return ret; -} - -} // namespace content diff --git a/content/renderer/media/buffered_data_source_host_impl.h b/content/renderer/media/buffered_data_source_host_impl.h deleted file mode 100644 index d04d467..0000000 --- a/content/renderer/media/buffered_data_source_host_impl.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_HOST_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_HOST_IMPL_H_ - -#include "base/time/time.h" -#include "content/common/content_export.h" -#include "content/renderer/media/buffered_data_source.h" -#include "media/base/ranges.h" - -namespace content { - -// Provides an implementation of BufferedDataSourceHost that translates the -// buffered byte ranges into estimated time ranges. -class CONTENT_EXPORT BufferedDataSourceHostImpl - : public BufferedDataSourceHost { - public: - BufferedDataSourceHostImpl(); - virtual ~BufferedDataSourceHostImpl(); - - // BufferedDataSourceHost implementation. - virtual void SetTotalBytes(int64 total_bytes) OVERRIDE; - virtual void AddBufferedByteRange(int64 start, int64 end) OVERRIDE; - - // Translate the byte ranges to time ranges and append them to the list. - // TODO(sandersd): This is a confusing name, find something better. - void AddBufferedTimeRanges( - media::Ranges<base::TimeDelta>* buffered_time_ranges, - base::TimeDelta media_duration) const; - - bool DidLoadingProgress(); - - private: - // Total size of the data source. - int64 total_bytes_; - - // List of buffered byte ranges for estimating buffered time. - media::Ranges<int64> buffered_byte_ranges_; - - // True when AddBufferedByteRange() has been called more recently than - // DidLoadingProgress(). - bool did_loading_progress_; - - DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceHostImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_HOST_IMPL_H_ diff --git a/content/renderer/media/buffered_data_source_host_impl_unittest.cc b/content/renderer/media/buffered_data_source_host_impl_unittest.cc deleted file mode 100644 index 6b5a5ec..0000000 --- a/content/renderer/media/buffered_data_source_host_impl_unittest.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/buffered_data_source_host_impl.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { - -class BufferedDataSourceHostImplTest : public testing::Test { - public: - BufferedDataSourceHostImplTest() {} - - void Add() { - host_.AddBufferedTimeRanges(&ranges_, base::TimeDelta::FromSeconds(10)); - } - - protected: - BufferedDataSourceHostImpl host_; - media::Ranges<base::TimeDelta> ranges_; - - DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceHostImplTest); -}; - -TEST_F(BufferedDataSourceHostImplTest, Empty) { - EXPECT_FALSE(host_.DidLoadingProgress()); - Add(); - EXPECT_EQ(0u, ranges_.size()); -} - -TEST_F(BufferedDataSourceHostImplTest, AddBufferedTimeRanges) { - host_.AddBufferedByteRange(10, 20); - host_.SetTotalBytes(100); - Add(); - EXPECT_EQ(1u, ranges_.size()); - EXPECT_EQ(base::TimeDelta::FromSeconds(1), ranges_.start(0)); - EXPECT_EQ(base::TimeDelta::FromSeconds(2), ranges_.end(0)); -} - -TEST_F(BufferedDataSourceHostImplTest, AddBufferedTimeRanges_Merges) { - ranges_.Add(base::TimeDelta::FromSeconds(0), base::TimeDelta::FromSeconds(1)); - host_.AddBufferedByteRange(10, 20); - host_.SetTotalBytes(100); - Add(); - EXPECT_EQ(1u, ranges_.size()); - EXPECT_EQ(base::TimeDelta::FromSeconds(0), ranges_.start(0)); - EXPECT_EQ(base::TimeDelta::FromSeconds(2), ranges_.end(0)); -} - -TEST_F(BufferedDataSourceHostImplTest, AddBufferedTimeRanges_Snaps) { - host_.AddBufferedByteRange(5, 995); - host_.SetTotalBytes(1000); - Add(); - EXPECT_EQ(1u, ranges_.size()); - EXPECT_EQ(base::TimeDelta::FromSeconds(0), ranges_.start(0)); - EXPECT_EQ(base::TimeDelta::FromSeconds(10), ranges_.end(0)); -} - -TEST_F(BufferedDataSourceHostImplTest, SetTotalBytes) { - host_.AddBufferedByteRange(10, 20); - Add(); - EXPECT_EQ(0u, ranges_.size()); - - host_.SetTotalBytes(100); - Add(); - EXPECT_EQ(1u, ranges_.size()); -} - -TEST_F(BufferedDataSourceHostImplTest, DidLoadingProgress) { - host_.AddBufferedByteRange(10, 20); - EXPECT_TRUE(host_.DidLoadingProgress()); - EXPECT_FALSE(host_.DidLoadingProgress()); -} - -} // namespace content diff --git a/content/renderer/media/buffered_data_source_unittest.cc b/content/renderer/media/buffered_data_source_unittest.cc deleted file mode 100644 index 9749991..0000000 --- a/content/renderer/media/buffered_data_source_unittest.cc +++ /dev/null @@ -1,780 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/message_loop/message_loop.h" -#include "content/public/common/url_constants.h" -#include "content/renderer/media/buffered_data_source.h" -#include "content/renderer/media/test_response_generator.h" -#include "content/test/mock_webframeclient.h" -#include "content/test/mock_weburlloader.h" -#include "media/base/media_log.h" -#include "media/base/mock_filters.h" -#include "media/base/test_helpers.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebView.h" - -using ::testing::_; -using ::testing::Assign; -using ::testing::Invoke; -using ::testing::InSequence; -using ::testing::NiceMock; -using ::testing::StrictMock; - -using blink::WebLocalFrame; -using blink::WebString; -using blink::WebURLLoader; -using blink::WebURLResponse; -using blink::WebView; - -namespace content { - -class MockBufferedDataSourceHost : public BufferedDataSourceHost { - public: - MockBufferedDataSourceHost() {} - virtual ~MockBufferedDataSourceHost() {} - - MOCK_METHOD1(SetTotalBytes, void(int64 total_bytes)); - MOCK_METHOD2(AddBufferedByteRange, void(int64 start, int64 end)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSourceHost); -}; - -// Overrides CreateResourceLoader() to permit injecting a MockWebURLLoader. -// Also keeps track of whether said MockWebURLLoader is actively loading. -class MockBufferedDataSource : public BufferedDataSource { - public: - MockBufferedDataSource( - const GURL& url, - const scoped_refptr<base::MessageLoopProxy>& message_loop, - WebLocalFrame* frame, - BufferedDataSourceHost* host) - : BufferedDataSource(url, - BufferedResourceLoader::kUnspecified, - message_loop, - frame, - new media::MediaLog(), - host, - base::Bind(&MockBufferedDataSource::set_downloading, - base::Unretained(this))), - downloading_(false), - loading_(false) {} - virtual ~MockBufferedDataSource() {} - - MOCK_METHOD2(CreateResourceLoader, BufferedResourceLoader*(int64, int64)); - BufferedResourceLoader* CreateMockResourceLoader(int64 first_byte_position, - int64 last_byte_position) { - CHECK(!loading_) << "Previous resource load wasn't cancelled"; - - BufferedResourceLoader* loader = - BufferedDataSource::CreateResourceLoader(first_byte_position, - last_byte_position); - - // Keep track of active loading state via loadAsynchronously() and cancel(). - NiceMock<MockWebURLLoader>* url_loader = new NiceMock<MockWebURLLoader>(); - ON_CALL(*url_loader, loadAsynchronously(_, _)) - .WillByDefault(Assign(&loading_, true)); - ON_CALL(*url_loader, cancel()) - .WillByDefault(Assign(&loading_, false)); - - // |test_loader_| will be used when Start() is called. - loader->test_loader_ = scoped_ptr<WebURLLoader>(url_loader); - return loader; - } - - bool loading() { return loading_; } - void set_loading(bool loading) { loading_ = loading; } - bool downloading() { return downloading_; } - void set_downloading(bool downloading) { downloading_ = downloading; } - - private: - // Whether the resource is downloading or deferred. - bool downloading_; - - // Whether the resource load has starting loading but yet to been cancelled. - bool loading_; - - DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource); -}; - -static const int64 kFileSize = 5000000; -static const int64 kFarReadPosition = 4000000; -static const int kDataSize = 1024; - -static const char kHttpUrl[] = "http://localhost/foo.webm"; -static const char kFileUrl[] = "file:///tmp/bar.webm"; - -class BufferedDataSourceTest : public testing::Test { - public: - BufferedDataSourceTest() - : view_(WebView::create(NULL)), - frame_(WebLocalFrame::create(&client_)), - preload_(BufferedDataSource::AUTO) { - view_->setMainFrame(frame_); - } - - virtual ~BufferedDataSourceTest() { - view_->close(); - frame_->close(); - } - - MOCK_METHOD1(OnInitialize, void(bool)); - - void Initialize(const char* url, bool expected) { - GURL gurl(url); - data_source_.reset( - new MockBufferedDataSource(gurl, - message_loop_.message_loop_proxy(), - view_->mainFrame()->toWebLocalFrame(), - &host_)); - data_source_->SetPreload(preload_); - - response_generator_.reset(new TestResponseGenerator(gurl, kFileSize)); - ExpectCreateResourceLoader(); - EXPECT_CALL(*this, OnInitialize(expected)); - data_source_->Initialize(base::Bind(&BufferedDataSourceTest::OnInitialize, - base::Unretained(this))); - message_loop_.RunUntilIdle(); - - bool is_http = gurl.SchemeIsHTTPOrHTTPS(); - EXPECT_EQ(data_source_->downloading(), is_http); - } - - // Helper to initialize tests with a valid 200 response. - void InitializeWith200Response() { - Initialize(kHttpUrl, true); - - EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length())); - Respond(response_generator_->Generate200()); - } - - // Helper to initialize tests with a valid 206 response. - void InitializeWith206Response() { - Initialize(kHttpUrl, true); - - EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length())); - Respond(response_generator_->Generate206(0)); - } - - // Helper to initialize tests with a valid file:// response. - void InitializeWithFileResponse() { - Initialize(kFileUrl, true); - - EXPECT_CALL(host_, SetTotalBytes(kFileSize)); - EXPECT_CALL(host_, AddBufferedByteRange(0, kFileSize)); - Respond(response_generator_->GenerateFileResponse(0)); - } - - // Stops any active loaders and shuts down the data source. - // - // This typically happens when the page is closed and for our purposes is - // appropriate to do when tearing down a test. - void Stop() { - if (data_source_->loading()) { - loader()->didFail(url_loader(), response_generator_->GenerateError()); - message_loop_.RunUntilIdle(); - } - - data_source_->Stop(); - message_loop_.RunUntilIdle(); - } - - void ExpectCreateResourceLoader() { - EXPECT_CALL(*data_source_, CreateResourceLoader(_, _)) - .WillOnce(Invoke(data_source_.get(), - &MockBufferedDataSource::CreateMockResourceLoader)); - message_loop_.RunUntilIdle(); - } - - void Respond(const WebURLResponse& response) { - loader()->didReceiveResponse(url_loader(), response); - message_loop_.RunUntilIdle(); - } - - void ReceiveData(int size) { - scoped_ptr<char[]> data(new char[size]); - memset(data.get(), 0xA5, size); // Arbitrary non-zero value. - - loader()->didReceiveData(url_loader(), data.get(), size, size); - message_loop_.RunUntilIdle(); - } - - void FinishLoading() { - data_source_->set_loading(false); - loader()->didFinishLoading(url_loader(), 0, -1); - message_loop_.RunUntilIdle(); - } - - MOCK_METHOD1(ReadCallback, void(int size)); - - void ReadAt(int64 position) { - data_source_->Read(position, kDataSize, buffer_, - base::Bind(&BufferedDataSourceTest::ReadCallback, - base::Unretained(this))); - message_loop_.RunUntilIdle(); - } - - // Accessors for private variables on |data_source_|. - BufferedResourceLoader* loader() { - return data_source_->loader_.get(); - } - WebURLLoader* url_loader() { - return loader()->active_loader_->loader_.get(); - } - - BufferedDataSource::Preload preload() { return data_source_->preload_; } - void set_preload(BufferedDataSource::Preload preload) { preload_ = preload; } - BufferedResourceLoader::DeferStrategy defer_strategy() { - return loader()->defer_strategy_; - } - int data_source_bitrate() { return data_source_->bitrate_; } - int data_source_playback_rate() { return data_source_->playback_rate_; } - int loader_bitrate() { return loader()->bitrate_; } - int loader_playback_rate() { return loader()->playback_rate_; } - bool is_local_source() { return data_source_->assume_fully_buffered(); } - void set_might_be_reused_from_cache_in_future(bool value) { - loader()->might_be_reused_from_cache_in_future_ = value; - } - - scoped_ptr<MockBufferedDataSource> data_source_; - - scoped_ptr<TestResponseGenerator> response_generator_; - MockWebFrameClient client_; - WebView* view_; - WebLocalFrame* frame_; - - StrictMock<MockBufferedDataSourceHost> host_; - base::MessageLoop message_loop_; - - private: - // Used for calling BufferedDataSource::Read(). - uint8 buffer_[kDataSize]; - - BufferedDataSource::Preload preload_; - - DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest); -}; - -TEST_F(BufferedDataSourceTest, Range_Supported) { - InitializeWith206Response(); - - EXPECT_TRUE(data_source_->loading()); - EXPECT_FALSE(data_source_->IsStreaming()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Range_InstanceSizeUnknown) { - Initialize(kHttpUrl, true); - - Respond(response_generator_->Generate206( - 0, TestResponseGenerator::kNoContentRangeInstanceSize)); - - EXPECT_TRUE(data_source_->loading()); - EXPECT_TRUE(data_source_->IsStreaming()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Range_NotFound) { - Initialize(kHttpUrl, false); - Respond(response_generator_->Generate404()); - - EXPECT_FALSE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Range_NotSupported) { - InitializeWith200Response(); - - EXPECT_TRUE(data_source_->loading()); - EXPECT_TRUE(data_source_->IsStreaming()); - Stop(); -} - -// Special carve-out for Apache versions that choose to return a 200 for -// Range:0- ("because it's more efficient" than a 206) -TEST_F(BufferedDataSourceTest, Range_SupportedButReturned200) { - Initialize(kHttpUrl, true); - EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length())); - WebURLResponse response = response_generator_->Generate200(); - response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"), - WebString::fromUTF8("bytes")); - Respond(response); - - EXPECT_TRUE(data_source_->loading()); - EXPECT_FALSE(data_source_->IsStreaming()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Range_MissingContentRange) { - Initialize(kHttpUrl, false); - Respond(response_generator_->Generate206( - 0, TestResponseGenerator::kNoContentRange)); - - EXPECT_FALSE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Range_MissingContentLength) { - Initialize(kHttpUrl, true); - - // It'll manage without a Content-Length response. - EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length())); - Respond(response_generator_->Generate206( - 0, TestResponseGenerator::kNoContentLength)); - - EXPECT_TRUE(data_source_->loading()); - EXPECT_FALSE(data_source_->IsStreaming()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Range_WrongContentRange) { - Initialize(kHttpUrl, false); - - // Now it's done and will fail. - Respond(response_generator_->Generate206(1337)); - - EXPECT_FALSE(data_source_->loading()); - Stop(); -} - -// Test the case where the initial response from the server indicates that -// Range requests are supported, but a later request prove otherwise. -TEST_F(BufferedDataSourceTest, Range_ServerLied) { - InitializeWith206Response(); - - // Read causing a new request to be made -- we'll expect it to error. - ExpectCreateResourceLoader(); - ReadAt(kFarReadPosition); - - // Return a 200 in response to a range request. - EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); - Respond(response_generator_->Generate200()); - - EXPECT_FALSE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Http_AbortWhileReading) { - InitializeWith206Response(); - - // Make sure there's a pending read -- we'll expect it to error. - ReadAt(0); - - // Abort!!! - EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); - data_source_->Abort(); - message_loop_.RunUntilIdle(); - - EXPECT_FALSE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, File_AbortWhileReading) { - InitializeWithFileResponse(); - - // Make sure there's a pending read -- we'll expect it to error. - ReadAt(0); - - // Abort!!! - EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); - data_source_->Abort(); - message_loop_.RunUntilIdle(); - - EXPECT_FALSE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Http_Retry) { - InitializeWith206Response(); - - // Read to advance our position. - EXPECT_CALL(*this, ReadCallback(kDataSize)); - EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1)); - ReadAt(0); - ReceiveData(kDataSize); - - // Issue a pending read but terminate the connection to force a retry. - ReadAt(kDataSize); - ExpectCreateResourceLoader(); - FinishLoading(); - Respond(response_generator_->Generate206(kDataSize)); - - // Complete the read. - EXPECT_CALL(*this, ReadCallback(kDataSize)); - EXPECT_CALL(host_, AddBufferedByteRange(kDataSize, (kDataSize * 2) - 1)); - ReceiveData(kDataSize); - - EXPECT_TRUE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, File_Retry) { - InitializeWithFileResponse(); - - // Read to advance our position. - EXPECT_CALL(*this, ReadCallback(kDataSize)); - ReadAt(0); - ReceiveData(kDataSize); - - // Issue a pending read but terminate the connection to force a retry. - ReadAt(kDataSize); - ExpectCreateResourceLoader(); - FinishLoading(); - Respond(response_generator_->GenerateFileResponse(kDataSize)); - - // Complete the read. - EXPECT_CALL(*this, ReadCallback(kDataSize)); - ReceiveData(kDataSize); - - EXPECT_TRUE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Http_TooManyRetries) { - InitializeWith206Response(); - - // Make sure there's a pending read -- we'll expect it to error. - ReadAt(0); - - // It'll try three times. - ExpectCreateResourceLoader(); - FinishLoading(); - Respond(response_generator_->Generate206(0)); - - ExpectCreateResourceLoader(); - FinishLoading(); - Respond(response_generator_->Generate206(0)); - - ExpectCreateResourceLoader(); - FinishLoading(); - Respond(response_generator_->Generate206(0)); - - // It'll error after this. - EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); - FinishLoading(); - - EXPECT_FALSE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, File_TooManyRetries) { - InitializeWithFileResponse(); - - // Make sure there's a pending read -- we'll expect it to error. - ReadAt(0); - - // It'll try three times. - ExpectCreateResourceLoader(); - FinishLoading(); - Respond(response_generator_->GenerateFileResponse(0)); - - ExpectCreateResourceLoader(); - FinishLoading(); - Respond(response_generator_->GenerateFileResponse(0)); - - ExpectCreateResourceLoader(); - FinishLoading(); - Respond(response_generator_->GenerateFileResponse(0)); - - // It'll error after this. - EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); - FinishLoading(); - - EXPECT_FALSE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, File_InstanceSizeUnknown) { - Initialize(kFileUrl, false); - EXPECT_FALSE(data_source_->downloading()); - - Respond(response_generator_->GenerateFileResponse(-1)); - - EXPECT_FALSE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, File_Successful) { - InitializeWithFileResponse(); - - EXPECT_TRUE(data_source_->loading()); - EXPECT_FALSE(data_source_->IsStreaming()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, StopDuringRead) { - InitializeWith206Response(); - - uint8 buffer[256]; - data_source_->Read(0, arraysize(buffer), buffer, base::Bind( - &BufferedDataSourceTest::ReadCallback, base::Unretained(this))); - - // The outstanding read should fail before the stop callback runs. - { - InSequence s; - EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); - data_source_->Stop(); - } - message_loop_.RunUntilIdle(); -} - -TEST_F(BufferedDataSourceTest, DefaultValues) { - InitializeWith206Response(); - - // Ensure we have sane values for default loading scenario. - EXPECT_EQ(BufferedDataSource::AUTO, preload()); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - EXPECT_EQ(0, data_source_bitrate()); - EXPECT_EQ(0.0f, data_source_playback_rate()); - EXPECT_EQ(0, loader_bitrate()); - EXPECT_EQ(0.0f, loader_playback_rate()); - - EXPECT_TRUE(data_source_->loading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, SetBitrate) { - InitializeWith206Response(); - - data_source_->SetBitrate(1234); - message_loop_.RunUntilIdle(); - EXPECT_EQ(1234, data_source_bitrate()); - EXPECT_EQ(1234, loader_bitrate()); - - // Read so far ahead to cause the loader to get recreated. - BufferedResourceLoader* old_loader = loader(); - ExpectCreateResourceLoader(); - ReadAt(kFarReadPosition); - Respond(response_generator_->Generate206(kFarReadPosition)); - - // Verify loader changed but still has same bitrate. - EXPECT_NE(old_loader, loader()); - EXPECT_EQ(1234, loader_bitrate()); - - EXPECT_TRUE(data_source_->loading()); - EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); - Stop(); -} - -TEST_F(BufferedDataSourceTest, MediaPlaybackRateChanged) { - InitializeWith206Response(); - - data_source_->MediaPlaybackRateChanged(2.0f); - message_loop_.RunUntilIdle(); - EXPECT_EQ(2.0f, data_source_playback_rate()); - EXPECT_EQ(2.0f, loader_playback_rate()); - - // Read so far ahead to cause the loader to get recreated. - BufferedResourceLoader* old_loader = loader(); - ExpectCreateResourceLoader(); - ReadAt(kFarReadPosition); - Respond(response_generator_->Generate206(kFarReadPosition)); - - // Verify loader changed but still has same playback rate. - EXPECT_NE(old_loader, loader()); - - EXPECT_TRUE(data_source_->loading()); - EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError)); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Http_Read) { - InitializeWith206Response(); - - ReadAt(0); - - // Receive first half of the read. - EXPECT_CALL(host_, AddBufferedByteRange(0, (kDataSize / 2) - 1)); - ReceiveData(kDataSize / 2); - - // Receive last half of the read. - EXPECT_CALL(*this, ReadCallback(kDataSize)); - EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1)); - ReceiveData(kDataSize / 2); - - EXPECT_TRUE(data_source_->downloading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, Http_Read_Seek) { - InitializeWith206Response(); - - // Read a bit from the beginning. - ReadAt(0); - EXPECT_CALL(*this, ReadCallback(kDataSize)); - EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1)); - ReceiveData(kDataSize); - - // Simulate a seek by reading a bit beyond kDataSize. - ReadAt(kDataSize * 2); - - // We receive data leading up to but not including our read. - EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2 - 1)); - ReceiveData(kDataSize); - - // We now receive the rest of the data for our read. - EXPECT_CALL(*this, ReadCallback(kDataSize)); - EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3 - 1)); - ReceiveData(kDataSize); - - EXPECT_TRUE(data_source_->downloading()); - Stop(); -} - -TEST_F(BufferedDataSourceTest, File_Read) { - InitializeWithFileResponse(); - - ReadAt(0); - - // Receive first half of the read but no buffering update. - ReceiveData(kDataSize / 2); - - // Receive last half of the read but no buffering update. - EXPECT_CALL(*this, ReadCallback(kDataSize)); - ReceiveData(kDataSize / 2); - - Stop(); -} - -TEST_F(BufferedDataSourceTest, Http_FinishLoading) { - InitializeWith206Response(); - - EXPECT_TRUE(data_source_->downloading()); - FinishLoading(); - EXPECT_FALSE(data_source_->downloading()); - - Stop(); -} - -TEST_F(BufferedDataSourceTest, File_FinishLoading) { - InitializeWithFileResponse(); - - EXPECT_FALSE(data_source_->downloading()); - FinishLoading(); - EXPECT_FALSE(data_source_->downloading()); - - Stop(); -} - -TEST_F(BufferedDataSourceTest, LocalResource_DeferStrategy) { - InitializeWithFileResponse(); - - EXPECT_EQ(BufferedDataSource::AUTO, preload()); - EXPECT_TRUE(is_local_source()); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - data_source_->MediaIsPlaying(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - data_source_->MediaIsPaused(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - Stop(); -} - -TEST_F(BufferedDataSourceTest, LocalResource_PreloadMetadata_DeferStrategy) { - set_preload(BufferedDataSource::METADATA); - InitializeWithFileResponse(); - - EXPECT_EQ(BufferedDataSource::METADATA, preload()); - EXPECT_TRUE(is_local_source()); - EXPECT_EQ(BufferedResourceLoader::kReadThenDefer, defer_strategy()); - - data_source_->MediaIsPlaying(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - data_source_->MediaIsPaused(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - Stop(); -} - -TEST_F(BufferedDataSourceTest, ExternalResource_Reponse200_DeferStrategy) { - InitializeWith200Response(); - - EXPECT_EQ(BufferedDataSource::AUTO, preload()); - EXPECT_FALSE(is_local_source()); - EXPECT_FALSE(loader()->range_supported()); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - data_source_->MediaIsPlaying(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - data_source_->MediaIsPaused(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - Stop(); -} - -TEST_F(BufferedDataSourceTest, - ExternalResource_Response200_PreloadMetadata_DeferStrategy) { - set_preload(BufferedDataSource::METADATA); - InitializeWith200Response(); - - EXPECT_EQ(BufferedDataSource::METADATA, preload()); - EXPECT_FALSE(is_local_source()); - EXPECT_FALSE(loader()->range_supported()); - EXPECT_EQ(BufferedResourceLoader::kReadThenDefer, defer_strategy()); - - data_source_->MediaIsPlaying(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - data_source_->MediaIsPaused(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - Stop(); -} - -TEST_F(BufferedDataSourceTest, ExternalResource_Reponse206_DeferStrategy) { - InitializeWith206Response(); - - EXPECT_EQ(BufferedDataSource::AUTO, preload()); - EXPECT_FALSE(is_local_source()); - EXPECT_TRUE(loader()->range_supported()); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - data_source_->MediaIsPlaying(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - set_might_be_reused_from_cache_in_future(true); - data_source_->MediaIsPaused(); - EXPECT_EQ(BufferedResourceLoader::kNeverDefer, defer_strategy()); - - data_source_->MediaIsPlaying(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - set_might_be_reused_from_cache_in_future(false); - data_source_->MediaIsPaused(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - Stop(); -} - -TEST_F(BufferedDataSourceTest, - ExternalResource_Response206_PreloadMetadata_DeferStrategy) { - set_preload(BufferedDataSource::METADATA); - InitializeWith206Response(); - - EXPECT_EQ(BufferedDataSource::METADATA, preload()); - EXPECT_FALSE(is_local_source()); - EXPECT_TRUE(loader()->range_supported()); - EXPECT_EQ(BufferedResourceLoader::kReadThenDefer, defer_strategy()); - - data_source_->MediaIsPlaying(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - set_might_be_reused_from_cache_in_future(true); - data_source_->MediaIsPaused(); - EXPECT_EQ(BufferedResourceLoader::kNeverDefer, defer_strategy()); - - data_source_->MediaIsPlaying(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - set_might_be_reused_from_cache_in_future(false); - data_source_->MediaIsPaused(); - EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy()); - - Stop(); -} - -} // namespace content diff --git a/content/renderer/media/buffered_resource_loader.cc b/content/renderer/media/buffered_resource_loader.cc deleted file mode 100644 index b43359c..0000000 --- a/content/renderer/media/buffered_resource_loader.cc +++ /dev/null @@ -1,787 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/buffered_resource_loader.h" - -#include "base/bits.h" -#include "base/callback_helpers.h" -#include "base/metrics/histogram.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "content/public/common/url_constants.h" -#include "content/renderer/media/cache_util.h" -#include "media/base/media_log.h" -#include "net/http/http_byte_range.h" -#include "net/http/http_request_headers.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/platform/WebURLError.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" -#include "third_party/WebKit/public/web/WebKit.h" -#include "third_party/WebKit/public/web/WebURLLoaderOptions.h" - -using blink::WebFrame; -using blink::WebString; -using blink::WebURLError; -using blink::WebURLLoader; -using blink::WebURLLoaderOptions; -using blink::WebURLRequest; -using blink::WebURLResponse; - -namespace content { - -static const int kHttpOK = 200; -static const int kHttpPartialContent = 206; - -// Define the number of bytes in a megabyte. -static const int kMegabyte = 1024 * 1024; - -// Minimum capacity of the buffer in forward or backward direction. -// -// 2MB is an arbitrary limit; it just seems to be "good enough" in practice. -static const int kMinBufferCapacity = 2 * kMegabyte; - -// Maximum capacity of the buffer in forward or backward direction. This is -// effectively the largest single read the code path can handle. -// 20MB is an arbitrary limit; it just seems to be "good enough" in practice. -static const int kMaxBufferCapacity = 20 * kMegabyte; - -// Maximum number of bytes outside the buffer we will wait for in order to -// fulfill a read. If a read starts more than 2MB away from the data we -// currently have in the buffer, we will not wait for buffer to reach the read's -// location and will instead reset the request. -static const int kForwardWaitThreshold = 2 * kMegabyte; - -// Computes the suggested backward and forward capacity for the buffer -// if one wants to play at |playback_rate| * the natural playback speed. -// Use a value of 0 for |bitrate| if it is unknown. -static void ComputeTargetBufferWindow(float playback_rate, int bitrate, - int* out_backward_capacity, - int* out_forward_capacity) { - static const int kDefaultBitrate = 200 * 1024 * 8; // 200 Kbps. - static const int kMaxBitrate = 20 * kMegabyte * 8; // 20 Mbps. - static const float kMaxPlaybackRate = 25.0; - static const int kTargetSecondsBufferedAhead = 10; - static const int kTargetSecondsBufferedBehind = 2; - - // Use a default bit rate if unknown and clamp to prevent overflow. - if (bitrate <= 0) - bitrate = kDefaultBitrate; - bitrate = std::min(bitrate, kMaxBitrate); - - // Only scale the buffer window for playback rates greater than 1.0 in - // magnitude and clamp to prevent overflow. - bool backward_playback = false; - if (playback_rate < 0.0f) { - backward_playback = true; - playback_rate *= -1.0f; - } - - playback_rate = std::max(playback_rate, 1.0f); - playback_rate = std::min(playback_rate, kMaxPlaybackRate); - - int bytes_per_second = (bitrate / 8.0) * playback_rate; - - // Clamp between kMinBufferCapacity and kMaxBufferCapacity. - *out_forward_capacity = std::max( - kTargetSecondsBufferedAhead * bytes_per_second, kMinBufferCapacity); - *out_backward_capacity = std::max( - kTargetSecondsBufferedBehind * bytes_per_second, kMinBufferCapacity); - - *out_forward_capacity = std::min(*out_forward_capacity, kMaxBufferCapacity); - *out_backward_capacity = std::min(*out_backward_capacity, kMaxBufferCapacity); - - if (backward_playback) - std::swap(*out_forward_capacity, *out_backward_capacity); -} - -BufferedResourceLoader::BufferedResourceLoader( - const GURL& url, - CORSMode cors_mode, - int64 first_byte_position, - int64 last_byte_position, - DeferStrategy strategy, - int bitrate, - float playback_rate, - media::MediaLog* media_log) - : buffer_(kMinBufferCapacity, kMinBufferCapacity), - loader_failed_(false), - defer_strategy_(strategy), - might_be_reused_from_cache_in_future_(true), - range_supported_(false), - saved_forward_capacity_(0), - url_(url), - cors_mode_(cors_mode), - first_byte_position_(first_byte_position), - last_byte_position_(last_byte_position), - single_origin_(true), - offset_(0), - content_length_(kPositionNotSpecified), - instance_size_(kPositionNotSpecified), - read_position_(0), - read_size_(0), - read_buffer_(NULL), - first_offset_(0), - last_offset_(0), - bitrate_(bitrate), - playback_rate_(playback_rate), - media_log_(media_log) { - - // Set the initial capacity of |buffer_| based on |bitrate_| and - // |playback_rate_|. - UpdateBufferWindow(); -} - -BufferedResourceLoader::~BufferedResourceLoader() {} - -void BufferedResourceLoader::Start( - const StartCB& start_cb, - const LoadingStateChangedCB& loading_cb, - const ProgressCB& progress_cb, - WebFrame* frame) { - // Make sure we have not started. - DCHECK(start_cb_.is_null()); - DCHECK(loading_cb_.is_null()); - DCHECK(progress_cb_.is_null()); - DCHECK(!start_cb.is_null()); - DCHECK(!loading_cb.is_null()); - DCHECK(!progress_cb.is_null()); - CHECK(frame); - - start_cb_ = start_cb; - loading_cb_ = loading_cb; - progress_cb_ = progress_cb; - - if (first_byte_position_ != kPositionNotSpecified) { - // TODO(hclam): server may not support range request so |offset_| may not - // equal to |first_byte_position_|. - offset_ = first_byte_position_; - } - - // Prepare the request. - WebURLRequest request(url_); - // TODO(mkwst): Split this into video/audio. - request.setRequestContext(WebURLRequest::RequestContextVideo); - - if (IsRangeRequest()) { - request.setHTTPHeaderField( - WebString::fromUTF8(net::HttpRequestHeaders::kRange), - WebString::fromUTF8(net::HttpByteRange::Bounded( - first_byte_position_, last_byte_position_).GetHeaderValue())); - } - - frame->setReferrerForRequest(request, blink::WebURL()); - - // Disable compression, compression for audio/video doesn't make sense... - request.setHTTPHeaderField( - WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding), - WebString::fromUTF8("identity;q=1, *;q=0")); - - // Check for our test WebURLLoader. - scoped_ptr<WebURLLoader> loader; - if (test_loader_) { - loader = test_loader_.Pass(); - } else { - WebURLLoaderOptions options; - if (cors_mode_ == kUnspecified) { - options.allowCredentials = true; - options.crossOriginRequestPolicy = - WebURLLoaderOptions::CrossOriginRequestPolicyAllow; - } else { - options.exposeAllResponseHeaders = true; - // The author header set is empty, no preflight should go ahead. - options.preflightPolicy = WebURLLoaderOptions::PreventPreflight; - options.crossOriginRequestPolicy = - WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; - if (cors_mode_ == kUseCredentials) - options.allowCredentials = true; - } - loader.reset(frame->createAssociatedURLLoader(options)); - } - - // Start the resource loading. - loader->loadAsynchronously(request, this); - active_loader_.reset(new ActiveLoader(loader.Pass())); - loading_cb_.Run(kLoading); -} - -void BufferedResourceLoader::Stop() { - // Reset callbacks. - start_cb_.Reset(); - loading_cb_.Reset(); - progress_cb_.Reset(); - read_cb_.Reset(); - - // Cancel and reset any active loaders. - active_loader_.reset(); -} - -void BufferedResourceLoader::Read( - int64 position, - int read_size, - uint8* buffer, - const ReadCB& read_cb) { - DCHECK(start_cb_.is_null()); - DCHECK(read_cb_.is_null()); - DCHECK(!read_cb.is_null()); - DCHECK(buffer); - DCHECK_GT(read_size, 0); - - // Save the parameter of reading. - read_cb_ = read_cb; - read_position_ = position; - read_size_ = read_size; - read_buffer_ = buffer; - - // Reads should immediately fail if the loader also failed. - if (loader_failed_) { - DoneRead(kFailed, 0); - return; - } - - // If we're attempting to read past the end of the file, return a zero - // indicating EOF. - // - // This can happen with callees that read in fixed-sized amounts for parsing - // or at the end of chunked 200 responses when we discover the actual length - // of the file. - if (instance_size_ != kPositionNotSpecified && - instance_size_ <= read_position_) { - DVLOG(1) << "Appear to have seeked beyond EOS; returning 0."; - DoneRead(kOk, 0); - return; - } - - // Make sure |offset_| and |read_position_| does not differ by a large - // amount. - if (read_position_ > offset_ + kint32max || - read_position_ < offset_ + kint32min) { - DoneRead(kCacheMiss, 0); - return; - } - - // Make sure |read_size_| is not too large for the buffer to ever be able to - // fulfill the read request. - if (read_size_ > kMaxBufferCapacity) { - DoneRead(kFailed, 0); - return; - } - - // Prepare the parameters. - first_offset_ = read_position_ - offset_; - last_offset_ = first_offset_ + read_size_; - - // If we can serve the request now, do the actual read. - if (CanFulfillRead()) { - ReadInternal(); - UpdateDeferBehavior(); - return; - } - - // If we expect the read request to be fulfilled later, expand capacity as - // necessary and disable deferring. - if (WillFulfillRead()) { - // Advance offset as much as possible to create additional capacity. - int advance = std::min(first_offset_, buffer_.forward_bytes()); - bool ret = buffer_.Seek(advance); - DCHECK(ret); - - offset_ += advance; - first_offset_ -= advance; - last_offset_ -= advance; - - // Expand capacity to accomodate a read that extends past the normal - // capacity. - // - // This can happen when reading in a large seek index or when the - // first byte of a read request falls within kForwardWaitThreshold. - if (last_offset_ > buffer_.forward_capacity()) { - saved_forward_capacity_ = buffer_.forward_capacity(); - buffer_.set_forward_capacity(last_offset_); - } - - // Make sure we stop deferring now that there's additional capacity. - DCHECK(!ShouldDefer()) - << "Capacity was not adjusted properly to prevent deferring."; - UpdateDeferBehavior(); - - return; - } - - // Make a callback to report failure. - DoneRead(kCacheMiss, 0); -} - -int64 BufferedResourceLoader::content_length() { - return content_length_; -} - -int64 BufferedResourceLoader::instance_size() { - return instance_size_; -} - -bool BufferedResourceLoader::range_supported() { - return range_supported_; -} - -///////////////////////////////////////////////////////////////////////////// -// blink::WebURLLoaderClient implementation. -void BufferedResourceLoader::willSendRequest( - WebURLLoader* loader, - WebURLRequest& newRequest, - const WebURLResponse& redirectResponse) { - - // The load may have been stopped and |start_cb| is destroyed. - // In this case we shouldn't do anything. - if (start_cb_.is_null()) { - // Set the url in the request to an invalid value (empty url). - newRequest.setURL(blink::WebURL()); - return; - } - - // Only allow |single_origin_| if we haven't seen a different origin yet. - if (single_origin_) - single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin(); - - url_ = newRequest.url(); -} - -void BufferedResourceLoader::didSendData( - WebURLLoader* loader, - unsigned long long bytes_sent, - unsigned long long total_bytes_to_be_sent) { - NOTIMPLEMENTED(); -} - -void BufferedResourceLoader::didReceiveResponse( - WebURLLoader* loader, - const WebURLResponse& response) { - DVLOG(1) << "didReceiveResponse: HTTP/" - << (response.httpVersion() == WebURLResponse::HTTP_0_9 ? "0.9" : - response.httpVersion() == WebURLResponse::HTTP_1_0 ? "1.0" : - response.httpVersion() == WebURLResponse::HTTP_1_1 ? "1.1" : - "Unknown") - << " " << response.httpStatusCode(); - DCHECK(active_loader_.get()); - - // The loader may have been stopped and |start_cb| is destroyed. - // In this case we shouldn't do anything. - if (start_cb_.is_null()) - return; - - uint32 reasons = GetReasonsForUncacheability(response); - might_be_reused_from_cache_in_future_ = reasons == 0; - UMA_HISTOGRAM_BOOLEAN("Media.CacheUseful", reasons == 0); - int shift = 0; - int max_enum = base::bits::Log2Ceiling(kMaxReason); - while (reasons) { - DCHECK_LT(shift, max_enum); // Sanity check. - if (reasons & 0x1) - UMA_HISTOGRAM_ENUMERATION("Media.UncacheableReason", shift, max_enum); - reasons >>= 1; - ++shift; - } - - // Expected content length can be |kPositionNotSpecified|, in that case - // |content_length_| is not specified and this is a streaming response. - content_length_ = response.expectedContentLength(); - - // We make a strong assumption that when we reach here we have either - // received a response from HTTP/HTTPS protocol or the request was - // successful (in particular range request). So we only verify the partial - // response for HTTP and HTTPS protocol. - if (url_.SchemeIsHTTPOrHTTPS()) { - bool partial_response = (response.httpStatusCode() == kHttpPartialContent); - bool ok_response = (response.httpStatusCode() == kHttpOK); - - if (IsRangeRequest()) { - // Check to see whether the server supports byte ranges. - std::string accept_ranges = - response.httpHeaderField("Accept-Ranges").utf8(); - range_supported_ = (accept_ranges.find("bytes") != std::string::npos); - - // If we have verified the partial response and it is correct, we will - // return kOk. It's also possible for a server to support range requests - // without advertising "Accept-Ranges: bytes". - if (partial_response && VerifyPartialResponse(response)) { - range_supported_ = true; - } else if (ok_response && first_byte_position_ == 0 && - last_byte_position_ == kPositionNotSpecified) { - // We accept a 200 response for a Range:0- request, trusting the - // Accept-Ranges header, because Apache thinks that's a reasonable thing - // to return. - instance_size_ = content_length_; - } else { - DoneStart(kFailed); - return; - } - } else { - instance_size_ = content_length_; - if (response.httpStatusCode() != kHttpOK) { - // We didn't request a range but server didn't reply with "200 OK". - DoneStart(kFailed); - return; - } - } - - } else { - CHECK_EQ(instance_size_, kPositionNotSpecified); - if (content_length_ != kPositionNotSpecified) { - if (first_byte_position_ == kPositionNotSpecified) - instance_size_ = content_length_; - else if (last_byte_position_ == kPositionNotSpecified) - instance_size_ = content_length_ + first_byte_position_; - } - } - - // Calls with a successful response. - DoneStart(kOk); -} - -void BufferedResourceLoader::didReceiveData( - WebURLLoader* loader, - const char* data, - int data_length, - int encoded_data_length) { - DVLOG(1) << "didReceiveData: " << data_length << " bytes"; - DCHECK(active_loader_.get()); - DCHECK_GT(data_length, 0); - - buffer_.Append(reinterpret_cast<const uint8*>(data), data_length); - - // If there is an active read request, try to fulfill the request. - if (HasPendingRead() && CanFulfillRead()) - ReadInternal(); - - // At last see if the buffer is full and we need to defer the downloading. - UpdateDeferBehavior(); - - // Consume excess bytes from our in-memory buffer if necessary. - if (buffer_.forward_bytes() > buffer_.forward_capacity()) { - int excess = buffer_.forward_bytes() - buffer_.forward_capacity(); - bool success = buffer_.Seek(excess); - DCHECK(success); - offset_ += first_offset_ + excess; - } - - // Notify latest progress and buffered offset. - progress_cb_.Run(offset_ + buffer_.forward_bytes() - 1); - Log(); -} - -void BufferedResourceLoader::didDownloadData( - blink::WebURLLoader* loader, - int dataLength, - int encoded_data_length) { - NOTIMPLEMENTED(); -} - -void BufferedResourceLoader::didReceiveCachedMetadata( - WebURLLoader* loader, - const char* data, - int data_length) { - NOTIMPLEMENTED(); -} - -void BufferedResourceLoader::didFinishLoading( - WebURLLoader* loader, - double finishTime, - int64_t total_encoded_data_length) { - DVLOG(1) << "didFinishLoading"; - DCHECK(active_loader_.get()); - - // We're done with the loader. - active_loader_.reset(); - loading_cb_.Run(kLoadingFinished); - - // If we didn't know the |instance_size_| we do now. - if (instance_size_ == kPositionNotSpecified) { - instance_size_ = offset_ + buffer_.forward_bytes(); - } - - // If there is a start callback, run it. - if (!start_cb_.is_null()) { - DCHECK(read_cb_.is_null()) - << "Shouldn't have a read callback during start"; - DoneStart(kOk); - return; - } - - // Don't leave read callbacks hanging around. - if (HasPendingRead()) { - // Try to fulfill with what is in the buffer. - if (CanFulfillRead()) - ReadInternal(); - else - DoneRead(kCacheMiss, 0); - } -} - -void BufferedResourceLoader::didFail( - WebURLLoader* loader, - const WebURLError& error) { - DVLOG(1) << "didFail: reason=" << error.reason - << ", isCancellation=" << error.isCancellation - << ", domain=" << error.domain.utf8().data() - << ", localizedDescription=" - << error.localizedDescription.utf8().data(); - DCHECK(active_loader_.get()); - - // We don't need to continue loading after failure. - // - // Keep it alive until we exit this method so that |error| remains valid. - scoped_ptr<ActiveLoader> active_loader = active_loader_.Pass(); - loader_failed_ = true; - loading_cb_.Run(kLoadingFailed); - - // Don't leave start callbacks hanging around. - if (!start_cb_.is_null()) { - DCHECK(read_cb_.is_null()) - << "Shouldn't have a read callback during start"; - DoneStart(kFailed); - return; - } - - // Don't leave read callbacks hanging around. - if (HasPendingRead()) { - DoneRead(kFailed, 0); - } -} - -bool BufferedResourceLoader::HasSingleOrigin() const { - DCHECK(start_cb_.is_null()) - << "Start() must complete before calling HasSingleOrigin()"; - return single_origin_; -} - -bool BufferedResourceLoader::DidPassCORSAccessCheck() const { - DCHECK(start_cb_.is_null()) - << "Start() must complete before calling DidPassCORSAccessCheck()"; - return !loader_failed_ && cors_mode_ != kUnspecified; -} - -void BufferedResourceLoader::UpdateDeferStrategy(DeferStrategy strategy) { - if (!might_be_reused_from_cache_in_future_ && strategy == kNeverDefer) - strategy = kCapacityDefer; - defer_strategy_ = strategy; - UpdateDeferBehavior(); -} - -void BufferedResourceLoader::SetPlaybackRate(float playback_rate) { - playback_rate_ = playback_rate; - - // This is a pause so don't bother updating the buffer window as we'll likely - // get unpaused in the future. - if (playback_rate_ == 0.0) - return; - - UpdateBufferWindow(); -} - -void BufferedResourceLoader::SetBitrate(int bitrate) { - DCHECK(bitrate >= 0); - bitrate_ = bitrate; - UpdateBufferWindow(); -} - -///////////////////////////////////////////////////////////////////////////// -// Helper methods. - -void BufferedResourceLoader::UpdateBufferWindow() { - int backward_capacity; - int forward_capacity; - ComputeTargetBufferWindow( - playback_rate_, bitrate_, &backward_capacity, &forward_capacity); - - // This does not evict data from the buffer if the new capacities are less - // than the current capacities; the new limits will be enforced after the - // existing excess buffered data is consumed. - buffer_.set_backward_capacity(backward_capacity); - buffer_.set_forward_capacity(forward_capacity); -} - -void BufferedResourceLoader::UpdateDeferBehavior() { - if (!active_loader_) - return; - - SetDeferred(ShouldDefer()); -} - -void BufferedResourceLoader::SetDeferred(bool deferred) { - if (active_loader_->deferred() == deferred) - return; - - active_loader_->SetDeferred(deferred); - loading_cb_.Run(deferred ? kLoadingDeferred : kLoading); -} - -bool BufferedResourceLoader::ShouldDefer() const { - switch(defer_strategy_) { - case kNeverDefer: - return false; - - case kReadThenDefer: - DCHECK(read_cb_.is_null() || last_offset_ > buffer_.forward_bytes()) - << "We shouldn't stop deferring if we can fulfill the read"; - return read_cb_.is_null(); - - case kCapacityDefer: - return buffer_.forward_bytes() >= buffer_.forward_capacity(); - } - NOTREACHED(); - return false; -} - -bool BufferedResourceLoader::CanFulfillRead() const { - // If we are reading too far in the backward direction. - if (first_offset_ < 0 && (first_offset_ + buffer_.backward_bytes()) < 0) - return false; - - // If the start offset is too far ahead. - if (first_offset_ >= buffer_.forward_bytes()) - return false; - - // At the point, we verified that first byte requested is within the buffer. - // If the request has completed, then just returns with what we have now. - if (!active_loader_) - return true; - - // If the resource request is still active, make sure the whole requested - // range is covered. - if (last_offset_ > buffer_.forward_bytes()) - return false; - - return true; -} - -bool BufferedResourceLoader::WillFulfillRead() const { - // Trying to read too far behind. - if (first_offset_ < 0 && (first_offset_ + buffer_.backward_bytes()) < 0) - return false; - - // Trying to read too far ahead. - if ((first_offset_ - buffer_.forward_bytes()) >= kForwardWaitThreshold) - return false; - - // The resource request has completed, there's no way we can fulfill the - // read request. - if (!active_loader_) - return false; - - return true; -} - -void BufferedResourceLoader::ReadInternal() { - // Seek to the first byte requested. - bool ret = buffer_.Seek(first_offset_); - DCHECK(ret); - - // Then do the read. - int read = buffer_.Read(read_buffer_, read_size_); - offset_ += first_offset_ + read; - - // And report with what we have read. - DoneRead(kOk, read); -} - -int64 BufferedResourceLoader::first_byte_position() const { - return first_byte_position_; -} - -// static -bool BufferedResourceLoader::ParseContentRange( - const std::string& content_range_str, int64* first_byte_position, - int64* last_byte_position, int64* instance_size) { - const std::string kUpThroughBytesUnit = "bytes "; - if (content_range_str.find(kUpThroughBytesUnit) != 0) - return false; - std::string range_spec = - content_range_str.substr(kUpThroughBytesUnit.length()); - size_t dash_offset = range_spec.find("-"); - size_t slash_offset = range_spec.find("/"); - - if (dash_offset == std::string::npos || slash_offset == std::string::npos || - slash_offset < dash_offset || slash_offset + 1 == range_spec.length()) { - return false; - } - if (!base::StringToInt64(range_spec.substr(0, dash_offset), - first_byte_position) || - !base::StringToInt64(range_spec.substr(dash_offset + 1, - slash_offset - dash_offset - 1), - last_byte_position)) { - return false; - } - if (slash_offset == range_spec.length() - 2 && - range_spec[slash_offset + 1] == '*') { - *instance_size = kPositionNotSpecified; - } else { - if (!base::StringToInt64(range_spec.substr(slash_offset + 1), - instance_size)) { - return false; - } - } - if (*last_byte_position < *first_byte_position || - (*instance_size != kPositionNotSpecified && - *last_byte_position >= *instance_size)) { - return false; - } - - return true; -} - -bool BufferedResourceLoader::VerifyPartialResponse( - const WebURLResponse& response) { - int64 first_byte_position, last_byte_position, instance_size; - if (!ParseContentRange(response.httpHeaderField("Content-Range").utf8(), - &first_byte_position, &last_byte_position, - &instance_size)) { - return false; - } - - if (instance_size != kPositionNotSpecified) { - instance_size_ = instance_size; - } - - if (first_byte_position_ != kPositionNotSpecified && - first_byte_position_ != first_byte_position) { - return false; - } - - // TODO(hclam): I should also check |last_byte_position|, but since - // we will never make such a request that it is ok to leave it unimplemented. - return true; -} - -void BufferedResourceLoader::DoneRead(Status status, int bytes_read) { - if (saved_forward_capacity_) { - buffer_.set_forward_capacity(saved_forward_capacity_); - saved_forward_capacity_ = 0; - } - read_position_ = 0; - read_size_ = 0; - read_buffer_ = NULL; - first_offset_ = 0; - last_offset_ = 0; - Log(); - - base::ResetAndReturn(&read_cb_).Run(status, bytes_read); -} - - -void BufferedResourceLoader::DoneStart(Status status) { - base::ResetAndReturn(&start_cb_).Run(status); -} - -bool BufferedResourceLoader::IsRangeRequest() const { - return first_byte_position_ != kPositionNotSpecified; -} - -void BufferedResourceLoader::Log() { - media_log_->AddEvent( - media_log_->CreateBufferedExtentsChangedEvent( - offset_ - buffer_.backward_bytes(), - offset_, - offset_ + buffer_.forward_bytes())); -} - -} // namespace content diff --git a/content/renderer/media/buffered_resource_loader.h b/content/renderer/media/buffered_resource_loader.h deleted file mode 100644 index 3bdf138..0000000 --- a/content/renderer/media/buffered_resource_loader.h +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_BUFFERED_RESOURCE_LOADER_H_ -#define CONTENT_RENDERER_MEDIA_BUFFERED_RESOURCE_LOADER_H_ - -#include <string> - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "base/timer/timer.h" -#include "content/common/content_export.h" -#include "content/renderer/media/active_loader.h" -#include "media/base/seekable_buffer.h" -#include "third_party/WebKit/public/platform/WebURLLoader.h" -#include "third_party/WebKit/public/platform/WebURLLoaderClient.h" -#include "third_party/WebKit/public/platform/WebURLRequest.h" -#include "third_party/WebKit/public/web/WebFrame.h" -#include "url/gurl.h" - -namespace media { -class MediaLog; -class SeekableBuffer; -} - -namespace content { - -const int64 kPositionNotSpecified = -1; - -// BufferedResourceLoader is single threaded and must be accessed on the -// render thread. It wraps a WebURLLoader and does in-memory buffering, -// pausing resource loading when the in-memory buffer is full and resuming -// resource loading when there is available capacity. -class CONTENT_EXPORT BufferedResourceLoader - : NON_EXPORTED_BASE(public blink::WebURLLoaderClient) { - public: - // kNeverDefer - Aggresively buffer; never defer loading while paused. - // kReadThenDefer - Request only enough data to fulfill read requests. - // kCapacityDefer - Try to keep amount of buffered data at capacity. - enum DeferStrategy { - kNeverDefer, - kReadThenDefer, - kCapacityDefer, - }; - - // Status codes for start/read operations on BufferedResourceLoader. - enum Status { - // Everything went as planned. - kOk, - - // The operation failed, which may have been due to: - // - Page navigation - // - Server replied 4xx/5xx - // - The response was invalid - // - Connection was terminated - // - // At this point you should delete the loader. - kFailed, - - // The loader will never be able to satisfy the read request. Please stop, - // delete, create a new loader, and try again. - kCacheMiss, - }; - - // Keep in sync with WebMediaPlayer::CORSMode. - enum CORSMode { kUnspecified, kAnonymous, kUseCredentials }; - - enum LoadingState { - kLoading, // Actively attempting to download data. - kLoadingDeferred, // Loading intentionally deferred. - kLoadingFinished, // Loading finished normally; no more data will arrive. - kLoadingFailed, // Loading finished abnormally; no more data will arrive. - }; - - // |url| - URL for the resource to be loaded. - // |cors_mode| - HTML media element's crossorigin attribute. - // |first_byte_position| - First byte to start loading from, - // |kPositionNotSpecified| for not specified. - // |last_byte_position| - Last byte to be loaded, - // |kPositionNotSpecified| for not specified. - // |strategy| is the initial loading strategy to use. - // |bitrate| is the bitrate of the media, 0 if unknown. - // |playback_rate| is the current playback rate of the media. - BufferedResourceLoader( - const GURL& url, - CORSMode cors_mode, - int64 first_byte_position, - int64 last_byte_position, - DeferStrategy strategy, - int bitrate, - float playback_rate, - media::MediaLog* media_log); - virtual ~BufferedResourceLoader(); - - // Start the resource loading with the specified URL and range. - // - // |loading_cb| is executed when the loading state has changed. - // |progress_cb| is executed when additional data has arrived. - typedef base::Callback<void(Status)> StartCB; - typedef base::Callback<void(LoadingState)> LoadingStateChangedCB; - typedef base::Callback<void(int64)> ProgressCB; - void Start(const StartCB& start_cb, - const LoadingStateChangedCB& loading_cb, - const ProgressCB& progress_cb, - blink::WebFrame* frame); - - // Stops everything associated with this loader, including active URL loads - // and pending callbacks. - // - // It is safe to delete a BufferedResourceLoader after calling Stop(). - void Stop(); - - // Copies |read_size| bytes from |position| into |buffer|, executing |read_cb| - // when the operation has completed. - // - // The callback will contain the number of bytes read iff the status is kOk, - // zero otherwise. - // - // If necessary will temporarily increase forward capacity of buffer to - // accomodate an unusually large read. - typedef base::Callback<void(Status, int)> ReadCB; - void Read(int64 position, int read_size, - uint8* buffer, const ReadCB& read_cb); - - // Gets the content length in bytes of the instance after this loader has been - // started. If this value is |kPositionNotSpecified|, then content length is - // unknown. - int64 content_length(); - - // Gets the original size of the file requested. If this value is - // |kPositionNotSpecified|, then the size is unknown. - int64 instance_size(); - - // Returns true if the server supports byte range requests. - bool range_supported(); - - // blink::WebURLLoaderClient implementation. - virtual void willSendRequest( - blink::WebURLLoader* loader, - blink::WebURLRequest& newRequest, - const blink::WebURLResponse& redirectResponse); - virtual void didSendData( - blink::WebURLLoader* loader, - unsigned long long bytesSent, - unsigned long long totalBytesToBeSent); - virtual void didReceiveResponse( - blink::WebURLLoader* loader, - const blink::WebURLResponse& response); - virtual void didDownloadData( - blink::WebURLLoader* loader, - int data_length, - int encoded_data_length); - virtual void didReceiveData( - blink::WebURLLoader* loader, - const char* data, - int data_length, - int encoded_data_length); - virtual void didReceiveCachedMetadata( - blink::WebURLLoader* loader, - const char* data, int dataLength); - virtual void didFinishLoading( - blink::WebURLLoader* loader, - double finishTime, - int64_t total_encoded_data_length); - virtual void didFail( - blink::WebURLLoader* loader, - const blink::WebURLError&); - - // Returns true if the media resource has a single origin, false otherwise. - // Only valid to call after Start() has completed. - bool HasSingleOrigin() const; - - // Returns true if the media resource passed a CORS access control check. - // Only valid to call after Start() has completed. - bool DidPassCORSAccessCheck() const; - - // Sets the defer strategy to the given value unless it seems unwise. - // Specifically downgrade kNeverDefer to kCapacityDefer if we know the - // current response will not be used to satisfy future requests (the cache - // won't help us). - void UpdateDeferStrategy(DeferStrategy strategy); - - // Sets the playback rate to the given value and updates buffer window - // accordingly. - void SetPlaybackRate(float playback_rate); - - // Sets the bitrate to the given value and updates buffer window - // accordingly. - void SetBitrate(int bitrate); - - // Return the |first_byte_position| passed into the ctor. - int64 first_byte_position() const; - - // Parse a Content-Range header into its component pieces and return true if - // each of the expected elements was found & parsed correctly. - // |*instance_size| may be set to kPositionNotSpecified if the range ends in - // "/*". - // NOTE: only public for testing! This is an implementation detail of - // VerifyPartialResponse (a private method). - static bool ParseContentRange( - const std::string& content_range_str, int64* first_byte_position, - int64* last_byte_position, int64* instance_size); - - private: - friend class BufferedDataSourceTest; - friend class BufferedResourceLoaderTest; - friend class MockBufferedDataSource; - - // Updates the |buffer_|'s forward and backward capacities. - void UpdateBufferWindow(); - - // Updates deferring behavior based on current buffering scheme. - void UpdateDeferBehavior(); - - // Sets |active_loader_|'s defer state and fires |loading_cb_| if the state - // changed. - void SetDeferred(bool deferred); - - // Returns true if we should defer resource loading based on the current - // buffering scheme. - bool ShouldDefer() const; - - // Returns true if the current read request can be fulfilled by what is in - // the buffer. - bool CanFulfillRead() const; - - // Returns true if the current read request will be fulfilled in the future. - bool WillFulfillRead() const; - - // Method that does the actual read and calls the |read_cb_|, assuming the - // request range is in |buffer_|. - void ReadInternal(); - - // If we have made a range request, verify the response from the server. - bool VerifyPartialResponse(const blink::WebURLResponse& response); - - // Done with read. Invokes the read callback and reset parameters for the - // read request. - void DoneRead(Status status, int bytes_read); - - // Done with start. Invokes the start callback and reset it. - void DoneStart(Status status); - - bool HasPendingRead() { return !read_cb_.is_null(); } - - // Helper function that returns true if a range request was specified. - bool IsRangeRequest() const; - - // Log everything interesting to |media_log_|. - void Log(); - - // A sliding window of buffer. - media::SeekableBuffer buffer_; - - // Keeps track of an active WebURLLoader and associated state. - scoped_ptr<ActiveLoader> active_loader_; - - // Tracks if |active_loader_| failed. If so, then all calls to Read() will - // fail. - bool loader_failed_; - - // Current buffering algorithm in place for resource loading. - DeferStrategy defer_strategy_; - - // True if the currently-reading response might be used to satisfy a future - // request from the cache. - bool might_be_reused_from_cache_in_future_; - - // True if Range header is supported. - bool range_supported_; - - // Forward capacity to reset to after an extension. - size_t saved_forward_capacity_; - - GURL url_; - CORSMode cors_mode_; - const int64 first_byte_position_; - const int64 last_byte_position_; - bool single_origin_; - - // Executed whenever the state of resource loading has changed. - LoadingStateChangedCB loading_cb_; - - // Executed whenever additional data has been downloaded and reports the - // zero-indexed file offset of the furthest buffered byte. - ProgressCB progress_cb_; - - // Members used during request start. - StartCB start_cb_; - int64 offset_; - int64 content_length_; - int64 instance_size_; - - // Members used during a read operation. They should be reset after each - // read has completed or failed. - ReadCB read_cb_; - int64 read_position_; - int read_size_; - uint8* read_buffer_; - - // Offsets of the requested first byte and last byte in |buffer_|. They are - // written by Read(). - int first_offset_; - int last_offset_; - - // Injected WebURLLoader instance for testing purposes. - scoped_ptr<blink::WebURLLoader> test_loader_; - - // Bitrate of the media. Set to 0 if unknown. - int bitrate_; - - // Playback rate of the media. - float playback_rate_; - - scoped_refptr<media::MediaLog> media_log_; - - DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoader); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_BUFFERED_RESOURCE_LOADER_H_ diff --git a/content/renderer/media/buffered_resource_loader_unittest.cc b/content/renderer/media/buffered_resource_loader_unittest.cc deleted file mode 100644 index 7bd23de..0000000 --- a/content/renderer/media/buffered_resource_loader_unittest.cc +++ /dev/null @@ -1,1131 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <algorithm> -#include <string> - -#include "base/bind.h" -#include "base/format_macros.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/stringprintf.h" -#include "content/renderer/media/buffered_resource_loader.h" -#include "content/test/mock_webframeclient.h" -#include "content/test/mock_weburlloader.h" -#include "media/base/media_log.h" -#include "media/base/seekable_buffer.h" -#include "net/base/net_errors.h" -#include "net/http/http_request_headers.h" -#include "net/http/http_util.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/platform/WebURLError.h" -#include "third_party/WebKit/public/platform/WebURLRequest.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebView.h" - -using ::testing::_; -using ::testing::InSequence; -using ::testing::Return; -using ::testing::Truly; -using ::testing::NiceMock; - -using blink::WebLocalFrame; -using blink::WebString; -using blink::WebURLError; -using blink::WebURLResponse; -using blink::WebView; - -namespace content { - -static const char* kHttpUrl = "http://test"; -static const char kHttpRedirectToSameDomainUrl1[] = "http://test/ing"; -static const char kHttpRedirectToSameDomainUrl2[] = "http://test/ing2"; -static const char kHttpRedirectToDifferentDomainUrl1[] = "http://test2"; - -static const int kDataSize = 1024; -static const int kHttpOK = 200; -static const int kHttpPartialContent = 206; - -enum NetworkState { - NONE, - LOADED, - LOADING -}; - -// Predicate that tests that request disallows compressed data. -static bool CorrectAcceptEncoding(const blink::WebURLRequest &request) { - std::string value = request.httpHeaderField( - WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding)).utf8(); - return (value.find("identity;q=1") != std::string::npos) && - (value.find("*;q=0") != std::string::npos); -} - -class BufferedResourceLoaderTest : public testing::Test { - public: - BufferedResourceLoaderTest() - : view_(WebView::create(NULL)), frame_(WebLocalFrame::create(&client_)) { - view_->setMainFrame(frame_); - - for (int i = 0; i < kDataSize; ++i) { - data_[i] = i; - } - } - - virtual ~BufferedResourceLoaderTest() { - view_->close(); - frame_->close(); - } - - void Initialize(const char* url, int first_position, int last_position) { - gurl_ = GURL(url); - first_position_ = first_position; - last_position_ = last_position; - - loader_.reset(new BufferedResourceLoader( - gurl_, BufferedResourceLoader::kUnspecified, - first_position_, last_position_, - BufferedResourceLoader::kCapacityDefer, 0, 0, - new media::MediaLog())); - - // |test_loader_| will be used when Start() is called. - url_loader_ = new NiceMock<MockWebURLLoader>(); - loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_); - } - - void SetLoaderBuffer(int forward_capacity, int backward_capacity) { - loader_->buffer_.set_forward_capacity(forward_capacity); - loader_->buffer_.set_backward_capacity(backward_capacity); - loader_->buffer_.Clear(); - } - - void Start() { - InSequence s; - EXPECT_CALL(*url_loader_, loadAsynchronously(Truly(CorrectAcceptEncoding), - loader_.get())); - - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - loader_->Start( - base::Bind(&BufferedResourceLoaderTest::StartCallback, - base::Unretained(this)), - base::Bind(&BufferedResourceLoaderTest::LoadingCallback, - base::Unretained(this)), - base::Bind(&BufferedResourceLoaderTest::ProgressCallback, - base::Unretained(this)), - view_->mainFrame()); - } - - void FullResponse(int64 instance_size) { - FullResponse(instance_size, BufferedResourceLoader::kOk); - } - - void FullResponse(int64 instance_size, - BufferedResourceLoader::Status status) { - EXPECT_CALL(*this, StartCallback(status)); - - WebURLResponse response(gurl_); - response.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), - WebString::fromUTF8(base::StringPrintf("%" - PRId64, instance_size))); - response.setExpectedContentLength(instance_size); - response.setHTTPStatusCode(kHttpOK); - loader_->didReceiveResponse(url_loader_, response); - - if (status == BufferedResourceLoader::kOk) { - EXPECT_EQ(instance_size, loader_->content_length()); - EXPECT_EQ(instance_size, loader_->instance_size()); - } - - EXPECT_FALSE(loader_->range_supported()); - } - - void PartialResponse(int64 first_position, int64 last_position, - int64 instance_size) { - PartialResponse(first_position, last_position, instance_size, false, true); - } - - void PartialResponse(int64 first_position, int64 last_position, - int64 instance_size, bool chunked, bool accept_ranges) { - EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kOk)); - - WebURLResponse response(gurl_); - response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"), - WebString::fromUTF8(base::StringPrintf("bytes " - "%" PRId64 "-%" PRId64 "/%" PRId64, - first_position, - last_position, - instance_size))); - - // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked. - int64 content_length = -1; - if (chunked) { - response.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"), - WebString::fromUTF8("chunked")); - } else { - content_length = last_position - first_position + 1; - } - response.setExpectedContentLength(content_length); - - // A server isn't required to return Accept-Ranges even though it might. - if (accept_ranges) { - response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"), - WebString::fromUTF8("bytes")); - } - - response.setHTTPStatusCode(kHttpPartialContent); - loader_->didReceiveResponse(url_loader_, response); - - // XXX: what's the difference between these two? For example in the chunked - // range request case, Content-Length is unspecified (because it's chunked) - // but Content-Range: a-b/c can be returned, where c == Content-Length - // - // Can we eliminate one? - EXPECT_EQ(content_length, loader_->content_length()); - EXPECT_EQ(instance_size, loader_->instance_size()); - - // A valid partial response should always result in this being true. - EXPECT_TRUE(loader_->range_supported()); - } - - void Redirect(const char* url) { - GURL redirectUrl(url); - blink::WebURLRequest newRequest(redirectUrl); - blink::WebURLResponse redirectResponse(gurl_); - - loader_->willSendRequest(url_loader_, newRequest, redirectResponse); - - base::MessageLoop::current()->RunUntilIdle(); - } - - void StopWhenLoad() { - InSequence s; - EXPECT_CALL(*url_loader_, cancel()); - loader_->Stop(); - loader_.reset(); - } - - // Helper method to write to |loader_| from |data_|. - void WriteLoader(int position, int size) { - EXPECT_CALL(*this, ProgressCallback(position + size - 1)); - loader_->didReceiveData(url_loader_, - reinterpret_cast<char*>(data_ + position), - size, - size); - } - - void WriteData(int size) { - EXPECT_CALL(*this, ProgressCallback(_)); - - scoped_ptr<char[]> data(new char[size]); - loader_->didReceiveData(url_loader_, data.get(), size, size); - } - - void WriteUntilThreshold() { - int buffered = loader_->buffer_.forward_bytes(); - int capacity = loader_->buffer_.forward_capacity(); - CHECK_LT(buffered, capacity); - - EXPECT_CALL(*this, LoadingCallback( - BufferedResourceLoader::kLoadingDeferred)); - WriteData(capacity - buffered); - } - - // Helper method to read from |loader_|. - void ReadLoader(int64 position, int size, uint8* buffer) { - loader_->Read(position, size, buffer, - base::Bind(&BufferedResourceLoaderTest::ReadCallback, - base::Unretained(this))); - } - - // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size]. - void VerifyBuffer(uint8* buffer, int pos, int size) { - EXPECT_EQ(0, memcmp(buffer, data_ + pos, size)); - } - - void ConfirmLoaderOffsets(int64 expected_offset, - int expected_first_offset, - int expected_last_offset) { - EXPECT_EQ(loader_->offset_, expected_offset); - EXPECT_EQ(loader_->first_offset_, expected_first_offset); - EXPECT_EQ(loader_->last_offset_, expected_last_offset); - } - - void ConfirmBufferState(int backward_bytes, - int backward_capacity, - int forward_bytes, - int forward_capacity) { - EXPECT_EQ(backward_bytes, loader_->buffer_.backward_bytes()); - EXPECT_EQ(backward_capacity, loader_->buffer_.backward_capacity()); - EXPECT_EQ(forward_bytes, loader_->buffer_.forward_bytes()); - EXPECT_EQ(forward_capacity, loader_->buffer_.forward_capacity()); - } - - void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity) { - EXPECT_EQ(loader_->buffer_.backward_capacity(), - expected_backward_capacity); - } - - void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity) { - EXPECT_EQ(loader_->buffer_.forward_capacity(), expected_forward_capacity); - } - - // Makes sure the |loader_| buffer window is in a reasonable range. - void CheckBufferWindowBounds() { - // Corresponds to value defined in buffered_resource_loader.cc. - static const int kMinBufferCapacity = 2 * 1024 * 1024; - EXPECT_GE(loader_->buffer_.forward_capacity(), kMinBufferCapacity); - EXPECT_GE(loader_->buffer_.backward_capacity(), kMinBufferCapacity); - - // Corresponds to value defined in buffered_resource_loader.cc. - static const int kMaxBufferCapacity = 20 * 1024 * 1024; - EXPECT_LE(loader_->buffer_.forward_capacity(), kMaxBufferCapacity); - EXPECT_LE(loader_->buffer_.backward_capacity(), kMaxBufferCapacity); - } - - MOCK_METHOD1(StartCallback, void(BufferedResourceLoader::Status)); - MOCK_METHOD2(ReadCallback, void(BufferedResourceLoader::Status, int)); - MOCK_METHOD1(LoadingCallback, void(BufferedResourceLoader::LoadingState)); - MOCK_METHOD1(ProgressCallback, void(int64)); - - protected: - GURL gurl_; - int64 first_position_; - int64 last_position_; - - scoped_ptr<BufferedResourceLoader> loader_; - NiceMock<MockWebURLLoader>* url_loader_; - - MockWebFrameClient client_; - WebView* view_; - WebLocalFrame* frame_; - - base::MessageLoop message_loop_; - - uint8 data_[kDataSize]; - - private: - DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest); -}; - -TEST_F(BufferedResourceLoaderTest, StartStop) { - Initialize(kHttpUrl, -1, -1); - Start(); - StopWhenLoad(); -} - -// Tests that a bad HTTP response is recived, e.g. file not found. -TEST_F(BufferedResourceLoaderTest, BadHttpResponse) { - Initialize(kHttpUrl, -1, -1); - Start(); - - EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed)); - - WebURLResponse response(gurl_); - response.setHTTPStatusCode(404); - response.setHTTPStatusText("Not Found\n"); - loader_->didReceiveResponse(url_loader_, response); - StopWhenLoad(); -} - -// Tests that partial content is requested but not fulfilled. -TEST_F(BufferedResourceLoaderTest, NotPartialResponse) { - Initialize(kHttpUrl, 100, -1); - Start(); - FullResponse(1024, BufferedResourceLoader::kFailed); - StopWhenLoad(); -} - -// Tests that a 200 response is received. -TEST_F(BufferedResourceLoaderTest, FullResponse) { - Initialize(kHttpUrl, -1, -1); - Start(); - FullResponse(1024); - StopWhenLoad(); -} - -// Tests that a partial content response is received. -TEST_F(BufferedResourceLoaderTest, PartialResponse) { - Initialize(kHttpUrl, 100, 200); - Start(); - PartialResponse(100, 200, 1024); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, PartialResponse_Chunked) { - Initialize(kHttpUrl, 100, 200); - Start(); - PartialResponse(100, 200, 1024, true, true); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, PartialResponse_NoAcceptRanges) { - Initialize(kHttpUrl, 100, 200); - Start(); - PartialResponse(100, 200, 1024, false, false); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, PartialResponse_ChunkedNoAcceptRanges) { - Initialize(kHttpUrl, 100, 200); - Start(); - PartialResponse(100, 200, 1024, true, false); - StopWhenLoad(); -} - -// Tests that an invalid partial response is received. -TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) { - Initialize(kHttpUrl, 0, 10); - Start(); - - EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed)); - - WebURLResponse response(gurl_); - response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"), - WebString::fromUTF8(base::StringPrintf("bytes " - "%d-%d/%d", 1, 10, 1024))); - response.setExpectedContentLength(10); - response.setHTTPStatusCode(kHttpPartialContent); - loader_->didReceiveResponse(url_loader_, response); - StopWhenLoad(); -} - -// Tests the logic of sliding window for data buffering and reading. -TEST_F(BufferedResourceLoaderTest, BufferAndRead) { - Initialize(kHttpUrl, 10, 29); - loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); - Start(); - PartialResponse(10, 29, 30); - - uint8 buffer[10]; - InSequence s; - - // Writes 10 bytes and read them back. - WriteLoader(10, 10); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); - ReadLoader(10, 10, buffer); - VerifyBuffer(buffer, 10, 10); - - // Writes 10 bytes and read 2 times. - WriteLoader(20, 10); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5)); - ReadLoader(20, 5, buffer); - VerifyBuffer(buffer, 20, 5); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5)); - ReadLoader(25, 5, buffer); - VerifyBuffer(buffer, 25, 5); - - // Read backward within buffer. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); - ReadLoader(10, 10, buffer); - VerifyBuffer(buffer, 10, 10); - - // Read backward outside buffer. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); - ReadLoader(9, 10, buffer); - - // Response has completed. - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished)); - loader_->didFinishLoading(url_loader_, 0, -1); - - // Try to read 10 from position 25 will just return with 5 bytes. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5)); - ReadLoader(25, 10, buffer); - VerifyBuffer(buffer, 25, 5); - - // Try to read outside buffered range after request has completed. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); - ReadLoader(5, 10, buffer); - - // Try to read beyond the instance size. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 0)); - ReadLoader(30, 10, buffer); -} - -// Tests the logic of expanding the data buffer for large reads. -TEST_F(BufferedResourceLoaderTest, ReadExtendBuffer) { - Initialize(kHttpUrl, 10, 0x014FFFFFF); - SetLoaderBuffer(10, 20); - Start(); - PartialResponse(10, 0x014FFFFFF, 0x015000000); - - uint8 buffer[20]; - InSequence s; - - // Write more than forward capacity and read it back. Ensure forward capacity - // gets reset after reading. - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); - WriteLoader(10, 20); - - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20)); - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - ReadLoader(10, 20, buffer); - - VerifyBuffer(buffer, 10, 20); - ConfirmLoaderBufferForwardCapacity(10); - - // Make and outstanding read request larger than forward capacity. Ensure - // forward capacity gets extended. - ReadLoader(30, 20, buffer); - ConfirmLoaderBufferForwardCapacity(20); - - // Fulfill outstanding request. Ensure forward capacity gets reset. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20)); - WriteLoader(30, 20); - - VerifyBuffer(buffer, 30, 20); - ConfirmLoaderBufferForwardCapacity(10); - - // Try to read further ahead than kForwardWaitThreshold allows. Ensure - // forward capacity is not changed. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); - ReadLoader(0x00300000, 1, buffer); - - ConfirmLoaderBufferForwardCapacity(10); - - // Try to read more than maximum forward capacity. Ensure forward capacity is - // not changed. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0)); - ReadLoader(30, 0x01400001, buffer); - - ConfirmLoaderBufferForwardCapacity(10); - - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) { - Initialize(kHttpUrl, 10, 0x00FFFFFF); - Start(); - PartialResponse(10, 0x00FFFFFF, 0x01000000); - - uint8 buffer[10]; - InSequence s; - - // Read very far ahead will get a cache miss. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); - ReadLoader(0x00FFFFFF, 1, buffer); - - // The following call will not call ReadCallback() because it is waiting for - // data to arrive. - ReadLoader(10, 10, buffer); - - // Writing to loader will fulfill the read request. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); - WriteLoader(10, 20); - VerifyBuffer(buffer, 10, 10); - - // The following call cannot be fulfilled now. - ReadLoader(25, 10, buffer); - - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished)); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5)); - loader_->didFinishLoading(url_loader_, 0, -1); -} - -TEST_F(BufferedResourceLoaderTest, RequestFailedWhenRead) { - Initialize(kHttpUrl, 10, 29); - Start(); - PartialResponse(10, 29, 30); - - uint8 buffer[10]; - InSequence s; - - // We should convert any error we receive to BufferedResourceLoader::kFailed. - ReadLoader(10, 10, buffer); - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed)); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0)); - WebURLError error; - error.reason = net::ERR_TIMED_OUT; - error.isCancellation = false; - loader_->didFail(url_loader_, error); -} - -TEST_F(BufferedResourceLoaderTest, RequestFailedWithNoPendingReads) { - Initialize(kHttpUrl, 10, 29); - Start(); - PartialResponse(10, 29, 30); - - uint8 buffer[10]; - InSequence s; - - // Write enough data so that a read would technically complete had the request - // not failed. - WriteLoader(10, 20); - - // Fail without a pending read. - WebURLError error; - error.reason = net::ERR_TIMED_OUT; - error.isCancellation = false; - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed)); - loader_->didFail(url_loader_, error); - - // Now we should immediately fail any read even if we have data buffered. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0)); - ReadLoader(10, 10, buffer); -} - -TEST_F(BufferedResourceLoaderTest, RequestCancelledWhenRead) { - Initialize(kHttpUrl, 10, 29); - Start(); - PartialResponse(10, 29, 30); - - uint8 buffer[10]; - InSequence s; - - // We should convert any error we receive to BufferedResourceLoader::kFailed. - ReadLoader(10, 10, buffer); - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed)); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0)); - WebURLError error; - error.reason = 0; - error.isCancellation = true; - loader_->didFail(url_loader_, error); -} - -// Tests the data buffering logic of NeverDefer strategy. -TEST_F(BufferedResourceLoaderTest, NeverDeferStrategy) { - Initialize(kHttpUrl, 10, 99); - SetLoaderBuffer(10, 20); - loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); - Start(); - PartialResponse(10, 99, 100); - - uint8 buffer[10]; - - // Read past the buffer size; should not defer regardless. - WriteLoader(10, 10); - WriteLoader(20, 50); - - // Should move past window. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); - ReadLoader(10, 10, buffer); - - StopWhenLoad(); -} - -// Tests the data buffering logic of ReadThenDefer strategy. -TEST_F(BufferedResourceLoaderTest, ReadThenDeferStrategy) { - Initialize(kHttpUrl, 10, 99); - SetLoaderBuffer(10, 20); - loader_->UpdateDeferStrategy(BufferedResourceLoader::kReadThenDefer); - Start(); - PartialResponse(10, 99, 100); - - uint8 buffer[10]; - - // Make an outstanding read request. - ReadLoader(10, 10, buffer); - - // Receive almost enough data to cover, shouldn't defer. - WriteLoader(10, 9); - - // As soon as we have received enough data to fulfill the read, defer. - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); - WriteLoader(19, 1); - - VerifyBuffer(buffer, 10, 10); - - // Read again which should disable deferring since there should be nothing - // left in our internal buffer. - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - ReadLoader(20, 10, buffer); - - // Over-fulfill requested bytes, then deferring should be enabled again. - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); - WriteLoader(20, 40); - - VerifyBuffer(buffer, 20, 10); - - // Read far ahead, which should disable deferring. In this case we still have - // bytes in our internal buffer. - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - ReadLoader(80, 10, buffer); - - // Fulfill requested bytes, then deferring should be enabled again. - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); - WriteLoader(60, 40); - - VerifyBuffer(buffer, 80, 10); - - StopWhenLoad(); -} - -// Tests the data buffering logic of kCapacityDefer strategy. -TEST_F(BufferedResourceLoaderTest, ThresholdDeferStrategy) { - Initialize(kHttpUrl, 10, 99); - SetLoaderBuffer(10, 20); - Start(); - PartialResponse(10, 99, 100); - - uint8 buffer[10]; - InSequence s; - - // Write half of capacity: keep not deferring. - WriteData(5); - - // Write rest of space until capacity: start deferring. - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); - WriteData(5); - - // Read a byte from the buffer: stop deferring. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1)); - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - ReadLoader(10, 1, buffer); - - // Write a byte to hit capacity: start deferring. - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred)); - WriteData(6); - - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, Tricky_ReadForwardsPastBuffered) { - Initialize(kHttpUrl, 10, 99); - SetLoaderBuffer(10, 10); - Start(); - PartialResponse(10, 99, 100); - - uint8 buffer[256]; - InSequence s; - - // PRECONDITION - WriteUntilThreshold(); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1)); - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - ReadLoader(10, 1, buffer); - ConfirmBufferState(1, 10, 9, 10); - ConfirmLoaderOffsets(11, 0, 0); - - // *** TRICKY BUSINESS, PT. I *** - // Read past buffered: stop deferring. - // - // In order for the read to complete we must: - // 1) Stop deferring to receive more data. - // - // BEFORE - // offset=11 [xxxxxxxxx_] - // ^ ^^^ requested 4 bytes @ offset 20 - // AFTER - // offset=24 [__________] - // - ReadLoader(20, 4, buffer); - - // Write a little, make sure we didn't start deferring. - WriteData(2); - - // Write the rest, read should complete. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4)); - WriteData(2); - - // POSTCONDITION - ConfirmBufferState(4, 10, 0, 10); - ConfirmLoaderOffsets(24, 0, 0); - - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, Tricky_ReadBackwardsPastBuffered) { - Initialize(kHttpUrl, 10, 99); - SetLoaderBuffer(10, 10); - Start(); - PartialResponse(10, 99, 100); - - uint8 buffer[256]; - InSequence s; - - // PRECONDITION - WriteUntilThreshold(); - ConfirmBufferState(0, 10, 10, 10); - ConfirmLoaderOffsets(10, 0, 0); - - // *** TRICKY BUSINESS, PT. II *** - // Read backwards a little too much: cache miss. - // - // BEFORE - // offset=10 [__________|xxxxxxxxxx] - // ^ ^^^ requested 10 bytes @ offset 9 - // AFTER - // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!! - // - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); - ReadLoader(9, 4, buffer); - - // POSTCONDITION - ConfirmBufferState(0, 10, 10, 10); - ConfirmLoaderOffsets(10, 0, 0); - - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, Tricky_SmallReadWithinThreshold) { - Initialize(kHttpUrl, 10, 99); - SetLoaderBuffer(10, 10); - Start(); - PartialResponse(10, 99, 100); - - uint8 buffer[256]; - InSequence s; - - // PRECONDITION - WriteUntilThreshold(); - ConfirmBufferState(0, 10, 10, 10); - ConfirmLoaderOffsets(10, 0, 0); - - // *** TRICKY BUSINESS, PT. III *** - // Read past forward capacity but within capacity: stop deferring. - // - // In order for the read to complete we must: - // 1) Adjust offset forward to create capacity. - // 2) Stop deferring to receive more data. - // - // BEFORE - // offset=10 [xxxxxxxxxx] - // ^^^^ requested 4 bytes @ offset 24 - // ADJUSTED OFFSET - // offset=20 [__________] - // ^^^^ requested 4 bytes @ offset 24 - // AFTER - // offset=28 [__________] - // - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - ReadLoader(24, 4, buffer); - ConfirmLoaderOffsets(20, 4, 8); - - // Write a little, make sure we didn't start deferring. - WriteData(4); - - // Write the rest, read should complete. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4)); - WriteData(4); - - // POSTCONDITION - ConfirmBufferState(8, 10, 0, 10); - ConfirmLoaderOffsets(28, 0, 0); - - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadWithinThreshold) { - Initialize(kHttpUrl, 10, 99); - SetLoaderBuffer(10, 10); - Start(); - PartialResponse(10, 99, 100); - - uint8 buffer[256]; - InSequence s; - - // PRECONDITION - WriteUntilThreshold(); - ConfirmBufferState(0, 10, 10, 10); - ConfirmLoaderOffsets(10, 0, 0); - - // *** TRICKY BUSINESS, PT. IV *** - // Read a large amount past forward capacity but within - // capacity: stop deferring. - // - // In order for the read to complete we must: - // 1) Adjust offset forward to create capacity. - // 2) Expand capacity to make sure we don't defer as data arrives. - // 3) Stop deferring to receive more data. - // - // BEFORE - // offset=10 [xxxxxxxxxx] - // ^^^^^^^^^^^^ requested 12 bytes @ offset 24 - // ADJUSTED OFFSET - // offset=20 [__________] - // ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24 - // ADJUSTED CAPACITY - // offset=20 [________________] - // ^^^^^^^^^^^^ requested 12 bytes @ offset 24 - // AFTER - // offset=36 [__________] - // - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - ReadLoader(24, 12, buffer); - ConfirmLoaderOffsets(20, 4, 16); - ConfirmBufferState(10, 10, 0, 16); - - // Write a little, make sure we didn't start deferring. - WriteData(10); - - // Write the rest, read should complete and capacity should go back to normal. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 12)); - WriteData(6); - ConfirmLoaderBufferForwardCapacity(10); - - // POSTCONDITION - ConfirmBufferState(6, 10, 0, 10); - ConfirmLoaderOffsets(36, 0, 0); - - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadBackwards) { - Initialize(kHttpUrl, 10, 99); - SetLoaderBuffer(10, 10); - Start(); - PartialResponse(10, 99, 100); - - uint8 buffer[256]; - InSequence s; - - // PRECONDITION - WriteUntilThreshold(); - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10)); - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - ReadLoader(10, 10, buffer); - WriteUntilThreshold(); - ConfirmBufferState(10, 10, 10, 10); - ConfirmLoaderOffsets(20, 0, 0); - - // *** TRICKY BUSINESS, PT. V *** - // Read a large amount that involves backwards data: stop deferring. - // - // In order for the read to complete we must: - // 1) Adjust offset *backwards* to create capacity. - // 2) Expand capacity to make sure we don't defer as data arrives. - // 3) Stop deferring to receive more data. - // - // BEFORE - // offset=20 [xxxxxxxxxx|xxxxxxxxxx] - // ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16 - // ADJUSTED OFFSET - // offset=16 [____xxxxxx|xxxxxxxxxx]xxxx - // ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16 - // ADJUSTED CAPACITY - // offset=16 [____xxxxxx|xxxxxxxxxxxxxx____] - // ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16 - // AFTER - // offset=34 [xxxxxxxxxx|__________] - // - EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading)); - ReadLoader(16, 18, buffer); - ConfirmLoaderOffsets(16, 0, 18); - ConfirmBufferState(6, 10, 14, 18); - - // Write a little, make sure we didn't start deferring. - WriteData(2); - - // Write the rest, read should complete and capacity should go back to normal. - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 18)); - WriteData(2); - ConfirmLoaderBufferForwardCapacity(10); - - // POSTCONDITION - ConfirmBufferState(4, 10, 0, 10); - ConfirmLoaderOffsets(34, 0, 0); - - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, Tricky_ReadPastThreshold) { - const int kSize = 5 * 1024 * 1024; - const int kThreshold = 2 * 1024 * 1024; - - Initialize(kHttpUrl, 10, kSize); - SetLoaderBuffer(10, 10); - Start(); - PartialResponse(10, kSize - 1, kSize); - - uint8 buffer[256]; - InSequence s; - - // PRECONDITION - WriteUntilThreshold(); - ConfirmBufferState(0, 10, 10, 10); - ConfirmLoaderOffsets(10, 0, 0); - - // *** TRICKY BUSINESS, PT. VI *** - // Read past the forward wait threshold: cache miss. - // - // BEFORE - // offset=10 [xxxxxxxxxx] ... - // ^^^^ requested 10 bytes @ threshold - // AFTER - // offset=10 [xxxxxxxxxx] !!! cache miss !!! - // - EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0)); - ReadLoader(kThreshold + 20, 10, buffer); - - // POSTCONDITION - ConfirmBufferState(0, 10, 10, 10); - ConfirmLoaderOffsets(10, 0, 0); - - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, HasSingleOrigin) { - // Make sure no redirect case works as expected. - Initialize(kHttpUrl, -1, -1); - Start(); - FullResponse(1024); - EXPECT_TRUE(loader_->HasSingleOrigin()); - StopWhenLoad(); - - // Test redirect to the same domain. - Initialize(kHttpUrl, -1, -1); - Start(); - Redirect(kHttpRedirectToSameDomainUrl1); - FullResponse(1024); - EXPECT_TRUE(loader_->HasSingleOrigin()); - StopWhenLoad(); - - // Test redirect twice to the same domain. - Initialize(kHttpUrl, -1, -1); - Start(); - Redirect(kHttpRedirectToSameDomainUrl1); - Redirect(kHttpRedirectToSameDomainUrl2); - FullResponse(1024); - EXPECT_TRUE(loader_->HasSingleOrigin()); - StopWhenLoad(); - - // Test redirect to a different domain. - Initialize(kHttpUrl, -1, -1); - Start(); - Redirect(kHttpRedirectToDifferentDomainUrl1); - FullResponse(1024); - EXPECT_FALSE(loader_->HasSingleOrigin()); - StopWhenLoad(); - - // Test redirect to the same domain and then to a different domain. - Initialize(kHttpUrl, -1, -1); - Start(); - Redirect(kHttpRedirectToSameDomainUrl1); - Redirect(kHttpRedirectToDifferentDomainUrl1); - FullResponse(1024); - EXPECT_FALSE(loader_->HasSingleOrigin()); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_Default) { - Initialize(kHttpUrl, -1, -1); - Start(); - - // Test ensures that default construction of a BufferedResourceLoader has sane - // values. - // - // Please do not change these values in order to make a test pass! Instead, - // start a conversation on what the default buffer window capacities should - // be. - ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024); - ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024); - - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_Unknown) { - Initialize(kHttpUrl, -1, -1); - Start(); - loader_->SetBitrate(0); - CheckBufferWindowBounds(); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_BelowLowerBound) { - Initialize(kHttpUrl, -1, -1); - Start(); - loader_->SetBitrate(1024 * 8); // 1 Kbps. - CheckBufferWindowBounds(); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_WithinBounds) { - Initialize(kHttpUrl, -1, -1); - Start(); - loader_->SetBitrate(2 * 1024 * 1024 * 8); // 2 Mbps. - CheckBufferWindowBounds(); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_AboveUpperBound) { - Initialize(kHttpUrl, -1, -1); - Start(); - loader_->SetBitrate(100 * 1024 * 1024 * 8); // 100 Mbps. - CheckBufferWindowBounds(); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Negative) { - Initialize(kHttpUrl, -1, -1); - Start(); - loader_->SetPlaybackRate(-10); - CheckBufferWindowBounds(); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Zero) { - Initialize(kHttpUrl, -1, -1); - Start(); - loader_->SetPlaybackRate(0); - CheckBufferWindowBounds(); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_BelowLowerBound) { - Initialize(kHttpUrl, -1, -1); - Start(); - loader_->SetPlaybackRate(0.1f); - CheckBufferWindowBounds(); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_WithinBounds) { - Initialize(kHttpUrl, -1, -1); - Start(); - loader_->SetPlaybackRate(10); - CheckBufferWindowBounds(); - StopWhenLoad(); -} - -TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_AboveUpperBound) { - Initialize(kHttpUrl, -1, -1); - Start(); - loader_->SetPlaybackRate(100); - CheckBufferWindowBounds(); - StopWhenLoad(); -} - -static void ExpectContentRange( - const std::string& str, bool expect_success, - int64 expected_first, int64 expected_last, int64 expected_size) { - int64 first, last, size; - ASSERT_EQ(expect_success, BufferedResourceLoader::ParseContentRange( - str, &first, &last, &size)) << str; - if (!expect_success) - return; - EXPECT_EQ(first, expected_first); - EXPECT_EQ(last, expected_last); - EXPECT_EQ(size, expected_size); -} - -static void ExpectContentRangeFailure(const std::string& str) { - ExpectContentRange(str, false, 0, 0, 0); -} - -static void ExpectContentRangeSuccess( - const std::string& str, - int64 expected_first, int64 expected_last, int64 expected_size) { - ExpectContentRange(str, true, expected_first, expected_last, expected_size); -} - -TEST(BufferedResourceLoaderStandaloneTest, ParseContentRange) { - ExpectContentRangeFailure("cytes 0-499/500"); - ExpectContentRangeFailure("bytes 0499/500"); - ExpectContentRangeFailure("bytes 0-499500"); - ExpectContentRangeFailure("bytes 0-499/500-blorg"); - ExpectContentRangeFailure("bytes 0-499/500-1"); - ExpectContentRangeFailure("bytes 0-499/400"); - ExpectContentRangeFailure("bytes 0-/400"); - ExpectContentRangeFailure("bytes -300/400"); - ExpectContentRangeFailure("bytes 20-10/400"); - - ExpectContentRangeSuccess("bytes 0-499/500", 0, 499, 500); - ExpectContentRangeSuccess("bytes 0-0/500", 0, 0, 500); - ExpectContentRangeSuccess("bytes 10-11/50", 10, 11, 50); - ExpectContentRangeSuccess("bytes 10-11/*", 10, 11, - kPositionNotSpecified); -} - -} // namespace content diff --git a/content/renderer/media/cache_util.cc b/content/renderer/media/cache_util.cc deleted file mode 100644 index d79e692..0000000 --- a/content/renderer/media/cache_util.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/cache_util.h" - -#include <string> - -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/time/time.h" -#include "net/http/http_util.h" -#include "net/http/http_version.h" -#include "third_party/WebKit/public/platform/WebCString.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" - -using base::Time; -using base::TimeDelta; -using net::HttpVersion; -using blink::WebURLResponse; - -namespace content { - -enum { kHttpOK = 200, kHttpPartialContent = 206 }; - -uint32 GetReasonsForUncacheability(const WebURLResponse& response) { - uint32 reasons = 0; - const int code = response.httpStatusCode(); - const int version = response.httpVersion(); - const HttpVersion http_version = - version == WebURLResponse::HTTP_1_1 ? HttpVersion(1, 1) : - version == WebURLResponse::HTTP_1_0 ? HttpVersion(1, 0) : - version == WebURLResponse::HTTP_0_9 ? HttpVersion(0, 9) : - HttpVersion(); - if (code != kHttpOK && code != kHttpPartialContent) - reasons |= kNoData; - if (http_version < HttpVersion(1, 1) && code == kHttpPartialContent) - reasons |= kPre11PartialResponse; - if (code == kHttpPartialContent && - !net::HttpUtil::HasStrongValidators( - http_version, - response.httpHeaderField("etag").utf8(), - response.httpHeaderField("Last-Modified").utf8(), - response.httpHeaderField("Date").utf8())) { - reasons |= kNoStrongValidatorOnPartialResponse; - } - - std::string cache_control_header = - response.httpHeaderField("cache-control").utf8(); - base::StringToLowerASCII(&cache_control_header); - if (cache_control_header.find("no-cache") != std::string::npos) - reasons |= kNoCache; - if (cache_control_header.find("no-store") != std::string::npos) - reasons |= kNoStore; - if (cache_control_header.find("must-revalidate") != std::string::npos) - reasons |= kHasMustRevalidate; - - const TimeDelta kMinimumAgeForUsefulness = - TimeDelta::FromSeconds(3600); // Arbitrary value. - - const char kMaxAgePrefix[] = "max-age="; - const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1; - if (cache_control_header.substr(0, kMaxAgePrefixLen) == kMaxAgePrefix) { - int64 max_age_seconds; - base::StringToInt64( - base::StringPiece(cache_control_header.begin() + kMaxAgePrefixLen, - cache_control_header.end()), - &max_age_seconds); - if (TimeDelta::FromSeconds(max_age_seconds) < kMinimumAgeForUsefulness) - reasons |= kShortMaxAge; - } - - Time date; - Time expires; - if (Time::FromString(response.httpHeaderField("Date").utf8().data(), &date) && - Time::FromString(response.httpHeaderField("Expires").utf8().data(), - &expires) && - date > Time() && expires > Time() && - (expires - date) < kMinimumAgeForUsefulness) { - reasons |= kExpiresTooSoon; - } - - return reasons; -} - -} // namespace content diff --git a/content/renderer/media/cache_util.h b/content/renderer/media/cache_util.h deleted file mode 100644 index aca8d8a..0000000 --- a/content/renderer/media/cache_util.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_CACHE_UTIL_H_ -#define CONTENT_RENDERER_MEDIA_CACHE_UTIL_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "content/common/content_export.h" - -namespace blink { -class WebURLResponse; -} - -namespace content { - -// Reasons that a cached WebURLResponse will *not* prevent a future request to -// the server. Reported via UMA, so don't change/reuse previously-existing -// values. -enum UncacheableReason { - kNoData = 1 << 0, // Not 200 or 206. - kPre11PartialResponse = 1 << 1, // 206 but HTTP version < 1.1. - kNoStrongValidatorOnPartialResponse = 1 << 2, // 206, no strong validator. - kShortMaxAge = 1 << 3, // Max age less than 1h (arbitrary value). - kExpiresTooSoon = 1 << 4, // Expires in less than 1h (arbitrary value). - kHasMustRevalidate = 1 << 5, // Response asks for revalidation. - kNoCache = 1 << 6, // Response included a no-cache header. - kNoStore = 1 << 7, // Response included a no-store header. - kMaxReason // Needs to be one more than max legitimate reason. -}; - -// Return the logical OR of the reasons "response" cannot be used for a future -// request (using the disk cache), or 0 if it might be useful. -uint32 CONTENT_EXPORT GetReasonsForUncacheability( - const blink::WebURLResponse& response); - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_CACHE_UTIL_H_ diff --git a/content/renderer/media/cache_util_unittest.cc b/content/renderer/media/cache_util_unittest.cc deleted file mode 100644 index 2db66b9..0000000 --- a/content/renderer/media/cache_util_unittest.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/cache_util.h" - -#include <string> - -#include "base/format_macros.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" - -using blink::WebString; -using blink::WebURLResponse; - -namespace content { - -// Inputs & expected output for GetReasonsForUncacheability. -struct GRFUTestCase { - WebURLResponse::HTTPVersion version; - int status_code; - const char* headers; - uint32 expected_reasons; -}; - -// Create a new WebURLResponse object. -static WebURLResponse CreateResponse(const GRFUTestCase& test) { - WebURLResponse response; - response.initialize(); - response.setHTTPVersion(test.version); - response.setHTTPStatusCode(test.status_code); - std::vector<std::string> lines; - Tokenize(test.headers, "\n", &lines); - for (size_t i = 0; i < lines.size(); ++i) { - size_t colon = lines[i].find(": "); - response.addHTTPHeaderField( - WebString::fromUTF8(lines[i].substr(0, colon)), - WebString::fromUTF8(lines[i].substr(colon + 2))); - } - return response; -} - -TEST(CacheUtilTest, GetReasonsForUncacheability) { - enum { kNoReasons = 0 }; - - const GRFUTestCase tests[] = { - { - WebURLResponse::HTTP_1_1, 206, "ETag: 'fooblort'", kNoReasons - }, - { - WebURLResponse::HTTP_1_1, 206, "", kNoStrongValidatorOnPartialResponse - }, - { - WebURLResponse::HTTP_1_0, 206, "", - kPre11PartialResponse | kNoStrongValidatorOnPartialResponse - }, - { - WebURLResponse::HTTP_1_1, 200, "cache-control: max-Age=42", kShortMaxAge - }, - { - WebURLResponse::HTTP_1_1, 200, "cache-control: max-Age=4200", kNoReasons - }, - { - WebURLResponse::HTTP_1_1, 200, - "Date: Tue, 22 May 2012 23:46:08 GMT\n" - "Expires: Tue, 22 May 2012 23:56:08 GMT", kExpiresTooSoon - }, - { - WebURLResponse::HTTP_1_1, 200, "cache-control: must-revalidate", - kHasMustRevalidate - }, - { - WebURLResponse::HTTP_1_1, 200, "cache-control: no-cache", kNoCache - }, - { - WebURLResponse::HTTP_1_1, 200, "cache-control: no-store", kNoStore - }, - { - WebURLResponse::HTTP_1_1, 200, - "cache-control: no-cache\ncache-control: no-store", kNoCache | kNoStore - }, - }; - for (size_t i = 0; i < arraysize(tests); ++i) { - SCOPED_TRACE(base::StringPrintf("case: %" PRIuS - ", version: %d, code: %d, headers: %s", - i, tests[i].version, tests[i].status_code, - tests[i].headers)); - EXPECT_EQ(GetReasonsForUncacheability(CreateResponse(tests[i])), - tests[i].expected_reasons); - } -} - -} // namespace content diff --git a/content/renderer/media/crypto/encrypted_media_player_support.cc b/content/renderer/media/crypto/encrypted_media_player_support.cc deleted file mode 100644 index 0414496..0000000 --- a/content/renderer/media/crypto/encrypted_media_player_support.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/crypto/encrypted_media_player_support.h" - -namespace content { - -EncryptedMediaPlayerSupport::EncryptedMediaPlayerSupport() { -} - -EncryptedMediaPlayerSupport::~EncryptedMediaPlayerSupport() { -} - -} diff --git a/content/renderer/media/crypto/encrypted_media_player_support.h b/content/renderer/media/crypto/encrypted_media_player_support.h deleted file mode 100644 index 59a4e24..0000000 --- a/content/renderer/media/crypto/encrypted_media_player_support.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_ -#define CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_ - -#include "media/base/decryptor.h" -#include "media/base/demuxer.h" -#include "third_party/WebKit/public/platform/WebMediaPlayer.h" - -namespace blink { -class WebContentDecryptionModule; -class WebContentDecryptionModuleResult; -class WebLocalFrame; -class WebMediaPlayerClient; -class WebString; -} - -namespace content { - -class EncryptedMediaPlayerSupport { - public: - EncryptedMediaPlayerSupport(); - virtual ~EncryptedMediaPlayerSupport(); - - // Prefixed API methods. - virtual blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest( - blink::WebLocalFrame* frame, - const blink::WebString& key_system, - const unsigned char* init_data, - unsigned init_data_length) = 0; - - virtual blink::WebMediaPlayer::MediaKeyException AddKey( - const blink::WebString& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const blink::WebString& session_id) = 0; - - virtual blink::WebMediaPlayer::MediaKeyException CancelKeyRequest( - const blink::WebString& key_system, - const blink::WebString& session_id) = 0; - - - // Unprefixed API methods. - virtual void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) = 0; - virtual void SetContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) = 0; - virtual void SetContentDecryptionModuleSync( - blink::WebContentDecryptionModule* cdm) = 0; - - - // Callback factory and notification methods used by WebMediaPlayerImpl. - - // Creates a callback that Demuxers can use to signal that the content - // requires a key. This method make sure the callback returned can be safely - // invoked from any thread. - virtual media::Demuxer::NeedKeyCB CreateNeedKeyCB() = 0; - - // Creates a callback that renderers can use to set decryptor - // ready callback. This method make sure the callback returned can be safely - // invoked from any thread. - virtual media::SetDecryptorReadyCB CreateSetDecryptorReadyCB() = 0; - - // Called to inform this object that the media pipeline encountered - // and handled a decryption error. - virtual void OnPipelineDecryptError() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(EncryptedMediaPlayerSupport); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_H_ diff --git a/content/renderer/media/crypto/encrypted_media_player_support_impl.cc b/content/renderer/media/crypto/encrypted_media_player_support_impl.cc index b15cd81..c884cd6 100644 --- a/content/renderer/media/crypto/encrypted_media_player_support_impl.cc +++ b/content/renderer/media/crypto/encrypted_media_player_support_impl.cc @@ -16,6 +16,7 @@ #include "content/renderer/media/webcontentdecryptionmodule_impl.h" #include "content/renderer/pepper/pepper_webplugin_impl.h" #include "media/base/bind_to_current_loop.h" +#include "media/blink/encrypted_media_player_support.h" #include "third_party/WebKit/public/platform/WebContentDecryptionModule.h" #include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" @@ -123,8 +124,8 @@ static std::string GuessInitDataType(const unsigned char* init_data, return "video/mp4"; } -scoped_ptr<EncryptedMediaPlayerSupport> EncryptedMediaPlayerSupportImpl::Create( - blink::WebMediaPlayerClient* client) { +scoped_ptr<media::EncryptedMediaPlayerSupport> +EncryptedMediaPlayerSupportImpl::Create(blink::WebMediaPlayerClient* client) { return scoped_ptr<EncryptedMediaPlayerSupport>( new EncryptedMediaPlayerSupportImpl(client)); } diff --git a/content/renderer/media/crypto/encrypted_media_player_support_impl.h b/content/renderer/media/crypto/encrypted_media_player_support_impl.h index 76063e6..f0299d8 100644 --- a/content/renderer/media/crypto/encrypted_media_player_support_impl.h +++ b/content/renderer/media/crypto/encrypted_media_player_support_impl.h @@ -9,8 +9,8 @@ #include <vector> #include "base/memory/weak_ptr.h" -#include "content/renderer/media/crypto/encrypted_media_player_support.h" #include "content/renderer/media/crypto/proxy_decryptor.h" +#include "media/blink/encrypted_media_player_support.h" namespace blink { class WebMediaPlayerClient; @@ -21,7 +21,7 @@ namespace content { class WebContentDecryptionModuleImpl; class EncryptedMediaPlayerSupportImpl - : public EncryptedMediaPlayerSupport, + : public media::EncryptedMediaPlayerSupport, public base::SupportsWeakPtr<EncryptedMediaPlayerSupportImpl> { public: static scoped_ptr<EncryptedMediaPlayerSupport> Create( diff --git a/content/renderer/media/test_response_generator.cc b/content/renderer/media/test_response_generator.cc deleted file mode 100644 index 64f82e7..0000000 --- a/content/renderer/media/test_response_generator.cc +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/test_response_generator.h" - -#include "base/format_macros.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "net/base/net_errors.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" - -using blink::WebString; -using blink::WebURLError; -using blink::WebURLResponse; - -namespace content { - -TestResponseGenerator::TestResponseGenerator(const GURL& gurl, - int64 content_length) - : gurl_(gurl), - content_length_(content_length) { -} - -WebURLError TestResponseGenerator::GenerateError() { - WebURLError error; - error.reason = net::ERR_ABORTED; - error.domain = WebString::fromUTF8(net::kErrorDomain); - return error; -} - -WebURLResponse TestResponseGenerator::Generate200() { - WebURLResponse response(gurl_); - response.setHTTPStatusCode(200); - - response.setHTTPHeaderField( - WebString::fromUTF8("Content-Length"), - WebString::fromUTF8(base::Int64ToString(content_length_))); - response.setExpectedContentLength(content_length_); - return response; -} - -WebURLResponse TestResponseGenerator::Generate206(int64 first_byte_offset) { - return Generate206(first_byte_offset, kNormal); -} - -WebURLResponse TestResponseGenerator::Generate206(int64 first_byte_offset, - Flags flags) { - int64 range_content_length = content_length_ - first_byte_offset; - int64 last_byte_offset = content_length_ - 1; - - WebURLResponse response(gurl_); - response.setHTTPStatusCode(206); - - if ((flags & kNoAcceptRanges) == 0) { - response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"), - WebString::fromUTF8("bytes")); - } - - if ((flags & kNoContentRange) == 0) { - std::string content_range = base::StringPrintf( - "bytes %" PRId64 "-%" PRId64 "/", - first_byte_offset, last_byte_offset); - if (flags & kNoContentRangeInstanceSize) - content_range += "*"; - else - content_range += base::StringPrintf("%" PRId64, content_length_); - response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"), - WebString::fromUTF8(content_range)); - } - - if ((flags & kNoContentLength) == 0) { - response.setHTTPHeaderField( - WebString::fromUTF8("Content-Length"), - WebString::fromUTF8(base::Int64ToString(range_content_length))); - response.setExpectedContentLength(range_content_length); - } - return response; -} - -WebURLResponse TestResponseGenerator::Generate404() { - WebURLResponse response(gurl_); - response.setHTTPStatusCode(404); - return response; -} - -WebURLResponse TestResponseGenerator::GenerateFileResponse( - int64 first_byte_offset) { - WebURLResponse response(gurl_); - response.setHTTPStatusCode(0); - - if (first_byte_offset >= 0) { - response.setExpectedContentLength(content_length_ - first_byte_offset); - } else { - response.setExpectedContentLength(-1); - } - return response; -} - -} // namespace content diff --git a/content/renderer/media/test_response_generator.h b/content/renderer/media/test_response_generator.h deleted file mode 100644 index dcbcc05..0000000 --- a/content/renderer/media/test_response_generator.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_TEST_RESPONSE_GENERATOR_H_ -#define CONTENT_RENDERER_MEDIA_TEST_RESPONSE_GENERATOR_H_ - -#include "base/basictypes.h" -#include "third_party/WebKit/public/platform/WebURLError.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" -#include "url/gurl.h" - -namespace content { - -// Generates WebURLErrors and WebURLResponses suitable for testing purposes. -class TestResponseGenerator { - public: - enum Flags { - kNormal = 0, - kNoAcceptRanges = 1 << 0, // Don't include Accept-Ranges in 206 response. - kNoContentRange = 1 << 1, // Don't include Content-Range in 206 response. - kNoContentLength = 1 << 2, // Don't include Content-Length in 206 response. - kNoContentRangeInstanceSize = 1 << 3, // Content-Range: N-M/* in 206. - }; - - // Build an HTTP response generator for the given URL. |content_length| is - // used to generate Content-Length and Content-Range headers. - TestResponseGenerator(const GURL& gurl, int64 content_length); - - // Generates a WebURLError object. - blink::WebURLError GenerateError(); - - // Generates a regular HTTP 200 response. - blink::WebURLResponse Generate200(); - - // Generates a regular HTTP 206 response starting from |first_byte_offset| - // until the end of the resource. - blink::WebURLResponse Generate206(int64 first_byte_offset); - - // Generates a custom HTTP 206 response starting from |first_byte_offset| - // until the end of the resource. You can tweak what gets included in the - // headers via |flags|. - blink::WebURLResponse Generate206(int64 first_byte_offset, Flags flags); - - // Generates a regular HTTP 404 response. - blink::WebURLResponse Generate404(); - - // Generates a file:// response starting from |first_byte_offset| until the - // end of the resource. - // - // If |first_byte_offset| is negative a response containing no content length - // will be returned. - blink::WebURLResponse GenerateFileResponse(int64 first_byte_offset); - - int64 content_length() { return content_length_; } - - private: - GURL gurl_; - int64 content_length_; - - DISALLOW_COPY_AND_ASSIGN(TestResponseGenerator); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_TEST_RESPONSE_GENERATOR_H_ diff --git a/content/renderer/media/texttrack_impl.cc b/content/renderer/media/texttrack_impl.cc deleted file mode 100644 index 565689f..0000000 --- a/content/renderer/media/texttrack_impl.cc +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/texttrack_impl.h" - -#include "base/bind.h" -#include "base/location.h" -#include "base/single_thread_task_runner.h" -#include "content/renderer/media/webinbandtexttrack_impl.h" -#include "media/base/bind_to_current_loop.h" -#include "third_party/WebKit/public/platform/WebInbandTextTrackClient.h" -#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" - -namespace content { - -TextTrackImpl::TextTrackImpl( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - blink::WebMediaPlayerClient* client, - scoped_ptr<WebInbandTextTrackImpl> text_track) - : task_runner_(task_runner), - client_(client), - text_track_(text_track.Pass()) { - client_->addTextTrack(text_track_.get()); -} - -TextTrackImpl::~TextTrackImpl() { - task_runner_->PostTask( - FROM_HERE, - base::Bind(&TextTrackImpl::OnRemoveTrack, - client_, - base::Passed(&text_track_))); -} - -void TextTrackImpl::addWebVTTCue(const base::TimeDelta& start, - const base::TimeDelta& end, - const std::string& id, - const std::string& content, - const std::string& settings) { - task_runner_->PostTask( - FROM_HERE, - base::Bind(&TextTrackImpl::OnAddCue, - text_track_.get(), - start, end, - id, content, settings)); -} - -void TextTrackImpl::OnAddCue(WebInbandTextTrackImpl* text_track, - const base::TimeDelta& start, - const base::TimeDelta& end, - const std::string& id, - const std::string& content, - const std::string& settings) { - if (blink::WebInbandTextTrackClient* client = text_track->client()) { - client->addWebVTTCue(start.InSecondsF(), - end.InSecondsF(), - blink::WebString::fromUTF8(id), - blink::WebString::fromUTF8(content), - blink::WebString::fromUTF8(settings)); - } -} - -void TextTrackImpl::OnRemoveTrack( - blink::WebMediaPlayerClient* client, - scoped_ptr<WebInbandTextTrackImpl> text_track) { - if (text_track->client()) - client->removeTextTrack(text_track.get()); -} - -} // namespace content diff --git a/content/renderer/media/texttrack_impl.h b/content/renderer/media/texttrack_impl.h deleted file mode 100644 index 436d4ea..0000000 --- a/content/renderer/media/texttrack_impl.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_TEXTTRACK_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_TEXTTRACK_IMPL_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "media/base/text_track.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace blink { -class WebInbandTextTrackClient; -class WebMediaPlayerClient; -} - -namespace content { - -class WebInbandTextTrackImpl; - -class TextTrackImpl : public media::TextTrack { - public: - // Constructor assumes ownership of the |text_track| object. - TextTrackImpl(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - blink::WebMediaPlayerClient* client, - scoped_ptr<WebInbandTextTrackImpl> text_track); - - virtual ~TextTrackImpl(); - - virtual void addWebVTTCue(const base::TimeDelta& start, - const base::TimeDelta& end, - const std::string& id, - const std::string& content, - const std::string& settings) OVERRIDE; - - private: - static void OnAddCue(WebInbandTextTrackImpl* text_track, - const base::TimeDelta& start, - const base::TimeDelta& end, - const std::string& id, - const std::string& content, - const std::string& settings); - - static void OnRemoveTrack(blink::WebMediaPlayerClient* client, - scoped_ptr<WebInbandTextTrackImpl> text_track); - - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - blink::WebMediaPlayerClient* client_; - scoped_ptr<WebInbandTextTrackImpl> text_track_; - DISALLOW_COPY_AND_ASSIGN(TextTrackImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_TEXTTRACK_IMPL_H_ diff --git a/content/renderer/media/video_frame_compositor.cc b/content/renderer/media/video_frame_compositor.cc deleted file mode 100644 index 50dd8c9..0000000 --- a/content/renderer/media/video_frame_compositor.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/video_frame_compositor.h" - -#include "media/base/video_frame.h" - -namespace content { - -static bool IsOpaque(const scoped_refptr<media::VideoFrame>& frame) { - switch (frame->format()) { - case media::VideoFrame::UNKNOWN: - case media::VideoFrame::YV12: - case media::VideoFrame::YV12J: - case media::VideoFrame::YV16: - case media::VideoFrame::I420: - case media::VideoFrame::YV24: - case media::VideoFrame::NV12: - return true; - - case media::VideoFrame::YV12A: -#if defined(VIDEO_HOLE) - case media::VideoFrame::HOLE: -#endif // defined(VIDEO_HOLE) - case media::VideoFrame::NATIVE_TEXTURE: - break; - } - return false; -} - -VideoFrameCompositor::VideoFrameCompositor( - const base::Callback<void(gfx::Size)>& natural_size_changed_cb, - const base::Callback<void(bool)>& opacity_changed_cb) - : natural_size_changed_cb_(natural_size_changed_cb), - opacity_changed_cb_(opacity_changed_cb), - client_(NULL) { -} - -VideoFrameCompositor::~VideoFrameCompositor() { - if (client_) - client_->StopUsingProvider(); -} - -void VideoFrameCompositor::SetVideoFrameProviderClient( - cc::VideoFrameProvider::Client* client) { - if (client_) - client_->StopUsingProvider(); - client_ = client; -} - -scoped_refptr<media::VideoFrame> VideoFrameCompositor::GetCurrentFrame() { - return current_frame_; -} - -void VideoFrameCompositor::PutCurrentFrame( - const scoped_refptr<media::VideoFrame>& frame) { -} - -void VideoFrameCompositor::UpdateCurrentFrame( - const scoped_refptr<media::VideoFrame>& frame) { - if (current_frame_.get() && - current_frame_->natural_size() != frame->natural_size()) { - natural_size_changed_cb_.Run(frame->natural_size()); - } - - if (!current_frame_.get() || IsOpaque(current_frame_) != IsOpaque(frame)) { - opacity_changed_cb_.Run(IsOpaque(frame)); - } - - current_frame_ = frame; - - if (client_) - client_->DidReceiveFrame(); -} - -} // namespace content diff --git a/content/renderer/media/video_frame_compositor.h b/content/renderer/media/video_frame_compositor.h deleted file mode 100644 index 91e5d0c..0000000 --- a/content/renderer/media/video_frame_compositor.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_VIDEO_FRAME_COMPOSITOR_H_ -#define CONTENT_RENDERER_MEDIA_VIDEO_FRAME_COMPOSITOR_H_ - -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "cc/layers/video_frame_provider.h" -#include "content/common/content_export.h" -#include "ui/gfx/size.h" - -namespace media { -class VideoFrame; -} - -namespace content { - -// VideoFrameCompositor handles incoming frames by notifying the compositor and -// dispatching callbacks when detecting changes in video frames. -// -// Typical usage is to deliver ready-to-be-displayed video frames to -// UpdateCurrentFrame() so that VideoFrameCompositor can take care of tracking -// changes in video frames and firing callbacks as needed. -// -// VideoFrameCompositor must live on the same thread as the compositor. -class CONTENT_EXPORT VideoFrameCompositor - : NON_EXPORTED_BASE(public cc::VideoFrameProvider) { - public: - // |natural_size_changed_cb| is run with the new natural size of the video - // frame whenever a change in natural size is detected. It is not called the - // first time UpdateCurrentFrame() is called. Run on the same thread as the - // caller of UpdateCurrentFrame(). - // - // |opacity_changed_cb| is run when a change in opacity is detected. It *is* - // called the first time UpdateCurrentFrame() is called. Run on the same - // thread as the caller of UpdateCurrentFrame(). - // - // TODO(scherkus): Investigate the inconsistency between the callbacks with - // respect to why we don't call |natural_size_changed_cb| on the first frame. - // I suspect it was for historical reasons that no longer make sense. - VideoFrameCompositor( - const base::Callback<void(gfx::Size)>& natural_size_changed_cb, - const base::Callback<void(bool)>& opacity_changed_cb); - virtual ~VideoFrameCompositor(); - - // cc::VideoFrameProvider implementation. - virtual void SetVideoFrameProviderClient( - cc::VideoFrameProvider::Client* client) OVERRIDE; - virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE; - virtual void PutCurrentFrame( - const scoped_refptr<media::VideoFrame>& frame) OVERRIDE; - - // Updates the current frame and notifies the compositor. - void UpdateCurrentFrame(const scoped_refptr<media::VideoFrame>& frame); - - private: - base::Callback<void(gfx::Size)> natural_size_changed_cb_; - base::Callback<void(bool)> opacity_changed_cb_; - - cc::VideoFrameProvider::Client* client_; - - scoped_refptr<media::VideoFrame> current_frame_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameCompositor); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_VIDEO_FRAME_COMPOSITOR_H_ diff --git a/content/renderer/media/video_frame_compositor_unittest.cc b/content/renderer/media/video_frame_compositor_unittest.cc deleted file mode 100644 index 801c9e3..0000000 --- a/content/renderer/media/video_frame_compositor_unittest.cc +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "cc/layers/video_frame_provider.h" -#include "content/renderer/media/video_frame_compositor.h" -#include "media/base/video_frame.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { - -using media::VideoFrame; - -class VideoFrameCompositorTest : public testing::Test, - public cc::VideoFrameProvider::Client { - public: - VideoFrameCompositorTest() - : compositor_(new VideoFrameCompositor( - base::Bind(&VideoFrameCompositorTest::NaturalSizeChanged, - base::Unretained(this)), - base::Bind(&VideoFrameCompositorTest::OpacityChanged, - base::Unretained(this)))), - did_receive_frame_count_(0), - natural_size_changed_count_(0), - opacity_changed_count_(0), - opaque_(false) { - compositor_->SetVideoFrameProviderClient(this); - } - - virtual ~VideoFrameCompositorTest() { - compositor_->SetVideoFrameProviderClient(NULL); - } - - VideoFrameCompositor* compositor() { return compositor_.get(); } - int did_receive_frame_count() { return did_receive_frame_count_; } - int natural_size_changed_count() { return natural_size_changed_count_; } - gfx::Size natural_size() { return natural_size_; } - - int opacity_changed_count() { return opacity_changed_count_; } - bool opaque() { return opaque_; } - - private: - // cc::VideoFrameProvider::Client implementation. - virtual void StopUsingProvider() OVERRIDE {} - virtual void DidReceiveFrame() OVERRIDE { - ++did_receive_frame_count_; - } - virtual void DidUpdateMatrix(const float* matrix) OVERRIDE {} - - void NaturalSizeChanged(gfx::Size natural_size) { - ++natural_size_changed_count_; - natural_size_ = natural_size; - } - - void OpacityChanged(bool opaque) { - ++opacity_changed_count_; - opaque_ = opaque; - } - - scoped_ptr<VideoFrameCompositor> compositor_; - int did_receive_frame_count_; - int natural_size_changed_count_; - gfx::Size natural_size_; - int opacity_changed_count_; - bool opaque_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameCompositorTest); -}; - -TEST_F(VideoFrameCompositorTest, InitialValues) { - EXPECT_FALSE(compositor()->GetCurrentFrame().get()); -} - -TEST_F(VideoFrameCompositorTest, UpdateCurrentFrame) { - scoped_refptr<VideoFrame> expected = VideoFrame::CreateEOSFrame(); - - // Should notify compositor synchronously. - EXPECT_EQ(0, did_receive_frame_count()); - compositor()->UpdateCurrentFrame(expected); - scoped_refptr<VideoFrame> actual = compositor()->GetCurrentFrame(); - EXPECT_EQ(expected, actual); - EXPECT_EQ(1, did_receive_frame_count()); -} - -TEST_F(VideoFrameCompositorTest, NaturalSizeChanged) { - gfx::Size initial_size(8, 8); - scoped_refptr<VideoFrame> initial_frame = - VideoFrame::CreateBlackFrame(initial_size); - - gfx::Size larger_size(16, 16); - scoped_refptr<VideoFrame> larger_frame = - VideoFrame::CreateBlackFrame(larger_size); - - // Initial expectations. - EXPECT_EQ(0, natural_size().width()); - EXPECT_EQ(0, natural_size().height()); - EXPECT_EQ(0, natural_size_changed_count()); - - // Callback isn't fired for the first frame. - compositor()->UpdateCurrentFrame(initial_frame); - EXPECT_EQ(0, natural_size().width()); - EXPECT_EQ(0, natural_size().height()); - EXPECT_EQ(0, natural_size_changed_count()); - - // Callback should be fired once. - compositor()->UpdateCurrentFrame(larger_frame); - EXPECT_EQ(larger_size.width(), natural_size().width()); - EXPECT_EQ(larger_size.height(), natural_size().height()); - EXPECT_EQ(1, natural_size_changed_count()); - - compositor()->UpdateCurrentFrame(larger_frame); - EXPECT_EQ(larger_size.width(), natural_size().width()); - EXPECT_EQ(larger_size.height(), natural_size().height()); - EXPECT_EQ(1, natural_size_changed_count()); - - // Callback is fired once more when switching back to initial size. - compositor()->UpdateCurrentFrame(initial_frame); - EXPECT_EQ(initial_size.width(), natural_size().width()); - EXPECT_EQ(initial_size.height(), natural_size().height()); - EXPECT_EQ(2, natural_size_changed_count()); - - compositor()->UpdateCurrentFrame(initial_frame); - EXPECT_EQ(initial_size.width(), natural_size().width()); - EXPECT_EQ(initial_size, natural_size()); - EXPECT_EQ(2, natural_size_changed_count()); -} - -TEST_F(VideoFrameCompositorTest, OpacityChanged) { - gfx::Size size(8, 8); - gfx::Rect rect(gfx::Point(0, 0), size); - scoped_refptr<VideoFrame> opaque_frame = VideoFrame::CreateFrame( - VideoFrame::YV12, size, rect, size, base::TimeDelta()); - scoped_refptr<VideoFrame> not_opaque_frame = VideoFrame::CreateFrame( - VideoFrame::YV12A, size, rect, size, base::TimeDelta()); - - // Initial expectations. - EXPECT_FALSE(opaque()); - EXPECT_EQ(0, opacity_changed_count()); - - // Callback is fired for the first frame. - compositor()->UpdateCurrentFrame(not_opaque_frame); - EXPECT_FALSE(opaque()); - EXPECT_EQ(1, opacity_changed_count()); - - // Callback shouldn't be first subsequent times with same opaqueness. - compositor()->UpdateCurrentFrame(not_opaque_frame); - EXPECT_FALSE(opaque()); - EXPECT_EQ(1, opacity_changed_count()); - - // Callback is fired when using opacity changes. - compositor()->UpdateCurrentFrame(opaque_frame); - EXPECT_TRUE(opaque()); - EXPECT_EQ(2, opacity_changed_count()); - - // Callback shouldn't be first subsequent times with same opaqueness. - compositor()->UpdateCurrentFrame(opaque_frame); - EXPECT_TRUE(opaque()); - EXPECT_EQ(2, opacity_changed_count()); -} - -} // namespace content diff --git a/content/renderer/media/webaudiosourceprovider_impl.cc b/content/renderer/media/webaudiosourceprovider_impl.cc deleted file mode 100644 index 4d878ce4..0000000 --- a/content/renderer/media/webaudiosourceprovider_impl.cc +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webaudiosourceprovider_impl.h" - -#include <vector> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/logging.h" -#include "media/base/bind_to_current_loop.h" -#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" - -using blink::WebVector; - -namespace content { - -namespace { - -// Simple helper class for Try() locks. Lock is Try()'d on construction and -// must be checked via the locked() attribute. If acquisition was successful -// the lock will be released upon destruction. -// TODO(dalecurtis): This should probably move to base/ if others start using -// this pattern. -class AutoTryLock { - public: - explicit AutoTryLock(base::Lock& lock) - : lock_(lock), - acquired_(lock_.Try()) {} - - bool locked() const { return acquired_; } - - ~AutoTryLock() { - if (acquired_) { - lock_.AssertAcquired(); - lock_.Release(); - } - } - - private: - base::Lock& lock_; - const bool acquired_; - DISALLOW_COPY_AND_ASSIGN(AutoTryLock); -}; - -} // namespace - -WebAudioSourceProviderImpl::WebAudioSourceProviderImpl( - const scoped_refptr<media::AudioRendererSink>& sink) - : channels_(0), - sample_rate_(0), - volume_(1.0), - state_(kStopped), - renderer_(NULL), - client_(NULL), - sink_(sink), - weak_factory_(this) {} - -WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() { -} - -void WebAudioSourceProviderImpl::setClient( - blink::WebAudioSourceProviderClient* client) { - base::AutoLock auto_lock(sink_lock_); - if (client && client != client_) { - // Detach the audio renderer from normal playback. - sink_->Stop(); - - // The client will now take control by calling provideInput() periodically. - client_ = client; - - set_format_cb_ = media::BindToCurrentLoop(base::Bind( - &WebAudioSourceProviderImpl::OnSetFormat, weak_factory_.GetWeakPtr())); - - // If |renderer_| is set, then run |set_format_cb_| to send |client_| - // the current format info. If |renderer_| is not set, then |set_format_cb_| - // will get called when Initialize() is called. - // Note: Always using |set_format_cb_| ensures we have the same - // locking order when calling into |client_|. - if (renderer_) - base::ResetAndReturn(&set_format_cb_).Run(); - } else if (!client && client_) { - // Restore normal playback. - client_ = NULL; - sink_->SetVolume(volume_); - if (state_ >= kStarted) - sink_->Start(); - if (state_ >= kPlaying) - sink_->Play(); - } -} - -void WebAudioSourceProviderImpl::provideInput( - const WebVector<float*>& audio_data, size_t number_of_frames) { - if (!bus_wrapper_ || - static_cast<size_t>(bus_wrapper_->channels()) != audio_data.size()) { - bus_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size()); - } - - bus_wrapper_->set_frames(number_of_frames); - for (size_t i = 0; i < audio_data.size(); ++i) - bus_wrapper_->SetChannelData(i, audio_data[i]); - - // Use a try lock to avoid contention in the real-time audio thread. - AutoTryLock auto_try_lock(sink_lock_); - if (!auto_try_lock.locked() || state_ != kPlaying) { - // Provide silence if we failed to acquire the lock or the source is not - // running. - bus_wrapper_->Zero(); - return; - } - - DCHECK(renderer_); - DCHECK(client_); - DCHECK_EQ(channels_, bus_wrapper_->channels()); - const size_t frames = renderer_->Render(bus_wrapper_.get(), 0); - if (frames < number_of_frames) - bus_wrapper_->ZeroFramesPartial(frames, number_of_frames - frames); - bus_wrapper_->Scale(volume_); -} - -void WebAudioSourceProviderImpl::Start() { - base::AutoLock auto_lock(sink_lock_); - DCHECK_EQ(state_, kStopped); - state_ = kStarted; - if (!client_) - sink_->Start(); -} - -void WebAudioSourceProviderImpl::Stop() { - base::AutoLock auto_lock(sink_lock_); - state_ = kStopped; - if (!client_) - sink_->Stop(); -} - -void WebAudioSourceProviderImpl::Play() { - base::AutoLock auto_lock(sink_lock_); - DCHECK_EQ(state_, kStarted); - state_ = kPlaying; - if (!client_) - sink_->Play(); -} - -void WebAudioSourceProviderImpl::Pause() { - base::AutoLock auto_lock(sink_lock_); - DCHECK(state_ == kPlaying || state_ == kStarted); - state_ = kStarted; - if (!client_) - sink_->Pause(); -} - -bool WebAudioSourceProviderImpl::SetVolume(double volume) { - base::AutoLock auto_lock(sink_lock_); - volume_ = volume; - if (!client_) - sink_->SetVolume(volume); - return true; -} - -void WebAudioSourceProviderImpl::Initialize( - const media::AudioParameters& params, - RenderCallback* renderer) { - base::AutoLock auto_lock(sink_lock_); - CHECK(!renderer_); - renderer_ = renderer; - - DCHECK_EQ(state_, kStopped); - sink_->Initialize(params, renderer); - - // Keep track of the format in case the client hasn't yet been set. - channels_ = params.channels(); - sample_rate_ = params.sample_rate(); - - if (!set_format_cb_.is_null()) - base::ResetAndReturn(&set_format_cb_).Run(); -} - -void WebAudioSourceProviderImpl::OnSetFormat() { - base::AutoLock auto_lock(sink_lock_); - if (!client_) - return; - - // Inform Blink about the audio stream format. - client_->setFormat(channels_, sample_rate_); -} - -} // namespace content diff --git a/content/renderer/media/webaudiosourceprovider_impl.h b/content/renderer/media/webaudiosourceprovider_impl.h deleted file mode 100644 index aca9d83..0000000 --- a/content/renderer/media/webaudiosourceprovider_impl.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_ - -#include "base/callback.h" -#include "base/memory/weak_ptr.h" -#include "base/synchronization/lock.h" -#include "content/common/content_export.h" -#include "media/base/audio_renderer_sink.h" -#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" -#include "third_party/WebKit/public/platform/WebVector.h" - -namespace blink { -class WebAudioSourceProviderClient; -} - -namespace content { - -// WebAudioSourceProviderImpl provides a bridge between classes: -// blink::WebAudioSourceProvider <---> media::AudioRendererSink -// -// WebAudioSourceProviderImpl wraps an existing audio sink that is used unless -// WebKit has set a client via setClient(). While a client is set WebKit will -// periodically call provideInput() to render a certain number of audio -// sample-frames using the sink's RenderCallback to get the data. -// -// All calls are protected by a lock. -class CONTENT_EXPORT WebAudioSourceProviderImpl - : NON_EXPORTED_BASE(public blink::WebAudioSourceProvider), - NON_EXPORTED_BASE(public media::AudioRendererSink) { - public: - explicit WebAudioSourceProviderImpl( - const scoped_refptr<media::AudioRendererSink>& sink); - - // blink::WebAudioSourceProvider implementation. - virtual void setClient(blink::WebAudioSourceProviderClient* client); - virtual void provideInput(const blink::WebVector<float*>& audio_data, - size_t number_of_frames); - - // media::AudioRendererSink implementation. - virtual void Start() OVERRIDE; - virtual void Stop() OVERRIDE; - virtual void Play() OVERRIDE; - virtual void Pause() OVERRIDE; - virtual bool SetVolume(double volume) OVERRIDE; - virtual void Initialize(const media::AudioParameters& params, - RenderCallback* renderer) OVERRIDE; - - protected: - virtual ~WebAudioSourceProviderImpl(); - - private: - // Calls setFormat() on |client_| from the Blink renderer thread. - void OnSetFormat(); - - // Closure that posts a task to call OnSetFormat() on the renderer thread. - base::Closure set_format_cb_; - - // Set to true when Initialize() is called. - int channels_; - int sample_rate_; - double volume_; - - // Tracks the current playback state. - enum PlaybackState { kStopped, kStarted, kPlaying }; - PlaybackState state_; - - // Where audio comes from. - media::AudioRendererSink::RenderCallback* renderer_; - - // When set via setClient() it overrides |sink_| for consuming audio. - blink::WebAudioSourceProviderClient* client_; - - // Where audio ends up unless overridden by |client_|. - base::Lock sink_lock_; - scoped_refptr<media::AudioRendererSink> sink_; - scoped_ptr<media::AudioBus> bus_wrapper_; - - // NOTE: Weak pointers must be invalidated before all other member variables. - base::WeakPtrFactory<WebAudioSourceProviderImpl> weak_factory_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(WebAudioSourceProviderImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_ diff --git a/content/renderer/media/webaudiosourceprovider_impl_unittest.cc b/content/renderer/media/webaudiosourceprovider_impl_unittest.cc deleted file mode 100644 index 8a59822..0000000 --- a/content/renderer/media/webaudiosourceprovider_impl_unittest.cc +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "content/renderer/media/webaudiosourceprovider_impl.h" -#include "media/audio/audio_parameters.h" -#include "media/base/fake_audio_render_callback.h" -#include "media/base/mock_audio_renderer_sink.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h" - -namespace content { - -namespace { -const float kTestVolume = 0.25; -} // namespace - -class WebAudioSourceProviderImplTest - : public testing::Test, - public blink::WebAudioSourceProviderClient { - public: - WebAudioSourceProviderImplTest() - : params_(media::AudioParameters::AUDIO_PCM_LINEAR, - media::CHANNEL_LAYOUT_STEREO, 48000, 16, 64), - fake_callback_(0.1), - mock_sink_(new media::MockAudioRendererSink()), - wasp_impl_(new WebAudioSourceProviderImpl(mock_sink_)) { - } - - virtual ~WebAudioSourceProviderImplTest() {} - - void CallAllSinkMethodsAndVerify(bool verify) { - testing::InSequence s; - - EXPECT_CALL(*mock_sink_.get(), Start()).Times(verify); - wasp_impl_->Start(); - - EXPECT_CALL(*mock_sink_.get(), Play()).Times(verify); - wasp_impl_->Play(); - - EXPECT_CALL(*mock_sink_.get(), Pause()).Times(verify); - wasp_impl_->Pause(); - - EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)).Times(verify); - wasp_impl_->SetVolume(kTestVolume); - - EXPECT_CALL(*mock_sink_.get(), Stop()).Times(verify); - wasp_impl_->Stop(); - - testing::Mock::VerifyAndClear(mock_sink_.get()); - } - - void SetClient(blink::WebAudioSourceProviderClient* client) { - testing::InSequence s; - - if (client) { - EXPECT_CALL(*mock_sink_.get(), Stop()); - EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); - } - wasp_impl_->setClient(client); - base::RunLoop().RunUntilIdle(); - - testing::Mock::VerifyAndClear(mock_sink_.get()); - testing::Mock::VerifyAndClear(this); - } - - bool CompareBusses(const media::AudioBus* bus1, const media::AudioBus* bus2) { - EXPECT_EQ(bus1->channels(), bus2->channels()); - EXPECT_EQ(bus1->frames(), bus2->frames()); - for (int ch = 0; ch < bus1->channels(); ++ch) { - if (memcmp(bus1->channel(ch), bus2->channel(ch), - sizeof(*bus1->channel(ch)) * bus1->frames()) != 0) { - return false; - } - } - return true; - } - - // blink::WebAudioSourceProviderClient implementation. - MOCK_METHOD2(setFormat, void(size_t numberOfChannels, float sampleRate)); - - protected: - media::AudioParameters params_; - media::FakeAudioRenderCallback fake_callback_; - scoped_refptr<media::MockAudioRendererSink> mock_sink_; - scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_; - base::MessageLoop message_loop_; - - DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest); -}; - -TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) { - // setClient() with a NULL client should do nothing if no client is set. - wasp_impl_->setClient(NULL); - - EXPECT_CALL(*mock_sink_.get(), Stop()); - wasp_impl_->setClient(this); - base::RunLoop().RunUntilIdle(); - - // When Initialize() is called after setClient(), the params should propagate - // to the client via setFormat() during the call. - EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate())); - wasp_impl_->Initialize(params_, &fake_callback_); - base::RunLoop().RunUntilIdle(); - - // setClient() with the same client should do nothing. - wasp_impl_->setClient(this); - base::RunLoop().RunUntilIdle(); -} - -// Verify AudioRendererSink functionality w/ and w/o a client. -TEST_F(WebAudioSourceProviderImplTest, SinkMethods) { - wasp_impl_->Initialize(params_, &fake_callback_); - ASSERT_EQ(mock_sink_->callback(), &fake_callback_); - - // Without a client all WASP calls should fall through to the underlying sink. - CallAllSinkMethodsAndVerify(true); - - // With a client no calls should reach the Stop()'d sink. Also, setClient() - // should propagate the params provided during Initialize() at call time. - SetClient(this); - CallAllSinkMethodsAndVerify(false); - - // Removing the client should cause WASP to revert to the underlying sink. - EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); - SetClient(NULL); - CallAllSinkMethodsAndVerify(true); -} - -// Verify underlying sink state is restored after client removal. -TEST_F(WebAudioSourceProviderImplTest, SinkStateRestored) { - wasp_impl_->Initialize(params_, &fake_callback_); - - // Verify state set before the client is set propagates back afterward. - EXPECT_CALL(*mock_sink_.get(), Start()); - wasp_impl_->Start(); - SetClient(this); - - EXPECT_CALL(*mock_sink_.get(), SetVolume(1.0)); - EXPECT_CALL(*mock_sink_.get(), Start()); - SetClient(NULL); - - // Verify state set while the client was attached propagates back afterward. - SetClient(this); - wasp_impl_->Play(); - wasp_impl_->SetVolume(kTestVolume); - - EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)); - EXPECT_CALL(*mock_sink_.get(), Start()); - EXPECT_CALL(*mock_sink_.get(), Play()); - SetClient(NULL); -} - -// Test the AudioRendererSink state machine and its effects on provideInput(). -TEST_F(WebAudioSourceProviderImplTest, ProvideInput) { - scoped_ptr<media::AudioBus> bus1 = media::AudioBus::Create(params_); - scoped_ptr<media::AudioBus> bus2 = media::AudioBus::Create(params_); - - // Point the WebVector into memory owned by |bus1|. - blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels())); - for (size_t i = 0; i < audio_data.size(); ++i) - audio_data[i] = bus1->channel(i); - - // Verify provideInput() works before Initialize() and returns silence. - bus1->channel(0)[0] = 1; - bus2->Zero(); - wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); - ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); - - wasp_impl_->Initialize(params_, &fake_callback_); - SetClient(this); - - // Verify provideInput() is muted prior to Start() and no calls to the render - // callback have occurred. - bus1->channel(0)[0] = 1; - bus2->Zero(); - wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); - ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); - ASSERT_EQ(fake_callback_.last_audio_delay_milliseconds(), -1); - - wasp_impl_->Start(); - - // Ditto for Play(). - bus1->channel(0)[0] = 1; - wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); - ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); - ASSERT_EQ(fake_callback_.last_audio_delay_milliseconds(), -1); - - wasp_impl_->Play(); - - // Now we should get real audio data. - wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); - ASSERT_FALSE(CompareBusses(bus1.get(), bus2.get())); - - // Ensure volume adjustment is working. - fake_callback_.reset(); - fake_callback_.Render(bus2.get(), 0); - bus2->Scale(kTestVolume); - - fake_callback_.reset(); - wasp_impl_->SetVolume(kTestVolume); - wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); - ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); - - // Pause should return to silence. - wasp_impl_->Pause(); - bus1->channel(0)[0] = 1; - bus2->Zero(); - wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); - ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); - - // Ensure if a renderer properly fill silence for partial Render() calls by - // configuring the fake callback to return half the data. After these calls - // bus1 is full of junk data, and bus2 is partially filled. - wasp_impl_->SetVolume(1); - fake_callback_.Render(bus1.get(), 0); - fake_callback_.reset(); - fake_callback_.Render(bus2.get(), 0); - bus2->ZeroFramesPartial(bus2->frames() / 2, - bus2->frames() - bus2->frames() / 2); - fake_callback_.reset(); - fake_callback_.set_half_fill(true); - wasp_impl_->Play(); - - // Play should return real audio data again, but the last half should be zero. - wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); - ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); - - // Stop() should return silence. - wasp_impl_->Stop(); - bus1->channel(0)[0] = 1; - bus2->Zero(); - wasp_impl_->provideInput(audio_data, params_.frames_per_buffer()); - ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get())); -} - -} // namespace content diff --git a/content/renderer/media/webinbandtexttrack_impl.cc b/content/renderer/media/webinbandtexttrack_impl.cc deleted file mode 100644 index e83af8f..0000000 --- a/content/renderer/media/webinbandtexttrack_impl.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webinbandtexttrack_impl.h" - -#include "base/logging.h" - -namespace content { - -WebInbandTextTrackImpl::WebInbandTextTrackImpl( - Kind kind, - const blink::WebString& label, - const blink::WebString& language, - const blink::WebString& id, - int index) - : client_(NULL), - kind_(kind), - label_(label), - language_(language), - id_(id), - index_(index) { -} - -WebInbandTextTrackImpl::~WebInbandTextTrackImpl() { - DCHECK(!client_); -} - -void WebInbandTextTrackImpl::setClient( - blink::WebInbandTextTrackClient* client) { - client_ = client; -} - -blink::WebInbandTextTrackClient* WebInbandTextTrackImpl::client() { - return client_; -} - -WebInbandTextTrackImpl::Kind WebInbandTextTrackImpl::kind() const { - return kind_; -} - -blink::WebString WebInbandTextTrackImpl::label() const { - return label_; -} - -blink::WebString WebInbandTextTrackImpl::language() const { - return language_; -} - -blink::WebString WebInbandTextTrackImpl::id() const { - return id_; -} - -int WebInbandTextTrackImpl::textTrackIndex() const { - return index_; -} - -} // namespace content diff --git a/content/renderer/media/webinbandtexttrack_impl.h b/content/renderer/media/webinbandtexttrack_impl.h deleted file mode 100644 index 293fbd3..0000000 --- a/content/renderer/media/webinbandtexttrack_impl.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_ - -#include "third_party/WebKit/public/platform/WebInbandTextTrack.h" -#include "third_party/WebKit/public/platform/WebString.h" - -namespace content { - -class WebInbandTextTrackImpl : public blink::WebInbandTextTrack { - public: - WebInbandTextTrackImpl(Kind kind, - const blink::WebString& label, - const blink::WebString& language, - const blink::WebString& id, - int index); - virtual ~WebInbandTextTrackImpl(); - - virtual void setClient(blink::WebInbandTextTrackClient* client); - virtual blink::WebInbandTextTrackClient* client(); - - virtual Kind kind() const; - - virtual blink::WebString label() const; - virtual blink::WebString language() const; - virtual blink::WebString id() const; - - virtual int textTrackIndex() const; - - private: - blink::WebInbandTextTrackClient* client_; - Kind kind_; - blink::WebString label_; - blink::WebString language_; - blink::WebString id_; - int index_; - DISALLOW_COPY_AND_ASSIGN(WebInbandTextTrackImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_ diff --git a/content/renderer/media/webmediaplayer_delegate.h b/content/renderer/media/webmediaplayer_delegate.h deleted file mode 100644 index 868abce..0000000 --- a/content/renderer/media/webmediaplayer_delegate.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_ -#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_ - -namespace blink { -class WebMediaPlayer; -} -namespace content { - -// An interface to allow a WebMediaPlayerImpl to communicate changes of state -// to objects that need to know. -class WebMediaPlayerDelegate { - public: - WebMediaPlayerDelegate() {} - - // The specified player started playing media. - virtual void DidPlay(blink::WebMediaPlayer* player) = 0; - - // The specified player stopped playing media. - virtual void DidPause(blink::WebMediaPlayer* player) = 0; - - // The specified player was destroyed. Do not call any methods on it. - virtual void PlayerGone(blink::WebMediaPlayer* player) = 0; - - protected: - virtual ~WebMediaPlayerDelegate() {} -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_ diff --git a/content/renderer/media/webmediaplayer_impl.cc b/content/renderer/media/webmediaplayer_impl.cc deleted file mode 100644 index 83e6202..0000000 --- a/content/renderer/media/webmediaplayer_impl.cc +++ /dev/null @@ -1,1036 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webmediaplayer_impl.h" - -#include <algorithm> -#include <limits> -#include <string> -#include <vector> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/callback_helpers.h" -#include "base/debug/alias.h" -#include "base/debug/crash_logging.h" -#include "base/debug/trace_event.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/metrics/histogram.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/waitable_event.h" -#include "cc/blink/web_layer_impl.h" -#include "cc/layers/video_layer.h" -#include "content/renderer/media/buffered_data_source.h" -#include "content/renderer/media/crypto/encrypted_media_player_support.h" -#include "content/renderer/media/texttrack_impl.h" -#include "content/renderer/media/webaudiosourceprovider_impl.h" -#include "content/renderer/media/webinbandtexttrack_impl.h" -#include "content/renderer/media/webmediaplayer_delegate.h" -#include "content/renderer/media/webmediaplayer_params.h" -#include "content/renderer/media/webmediaplayer_util.h" -#include "content/renderer/media/webmediasource_impl.h" -#include "gpu/GLES2/gl2extchromium.h" -#include "gpu/command_buffer/common/mailbox_holder.h" -#include "media/audio/null_audio_sink.h" -#include "media/base/audio_hardware_config.h" -#include "media/base/bind_to_current_loop.h" -#include "media/base/limits.h" -#include "media/base/media_log.h" -#include "media/base/pipeline.h" -#include "media/base/text_renderer.h" -#include "media/base/video_frame.h" -#include "media/filters/audio_renderer_impl.h" -#include "media/filters/chunk_demuxer.h" -#include "media/filters/ffmpeg_audio_decoder.h" -#include "media/filters/ffmpeg_demuxer.h" -#include "media/filters/ffmpeg_video_decoder.h" -#include "media/filters/gpu_video_accelerator_factories.h" -#include "media/filters/gpu_video_decoder.h" -#include "media/filters/opus_audio_decoder.h" -#include "media/filters/renderer_impl.h" -#include "media/filters/video_renderer_impl.h" -#include "media/filters/vpx_video_decoder.h" -#include "third_party/WebKit/public/platform/WebMediaSource.h" -#include "third_party/WebKit/public/platform/WebRect.h" -#include "third_party/WebKit/public/platform/WebSize.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/platform/WebURL.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebSecurityOrigin.h" -#include "third_party/WebKit/public/web/WebView.h" - -using blink::WebCanvas; -using blink::WebMediaPlayer; -using blink::WebRect; -using blink::WebSize; -using blink::WebString; -using media::PipelineStatus; - -namespace { - -// Limits the range of playback rate. -// -// TODO(kylep): Revisit these. -// -// Vista has substantially lower performance than XP or Windows7. If you speed -// up a video too much, it can't keep up, and rendering stops updating except on -// the time bar. For really high speeds, audio becomes a bottleneck and we just -// use up the data we have, which may not achieve the speed requested, but will -// not crash the tab. -// -// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems -// like a busy loop). It gets unresponsive, although its not completely dead. -// -// Also our timers are not very accurate (especially for ogg), which becomes -// evident at low speeds and on Vista. Since other speeds are risky and outside -// the norms, we think 1/16x to 16x is a safe and useful range for now. -const double kMinRate = 0.0625; -const double kMaxRate = 16.0; - -class SyncPointClientImpl : public media::VideoFrame::SyncPointClient { - public: - explicit SyncPointClientImpl( - blink::WebGraphicsContext3D* web_graphics_context) - : web_graphics_context_(web_graphics_context) {} - virtual ~SyncPointClientImpl() {} - virtual uint32 InsertSyncPoint() OVERRIDE { - return web_graphics_context_->insertSyncPoint(); - } - virtual void WaitSyncPoint(uint32 sync_point) OVERRIDE { - web_graphics_context_->waitSyncPoint(sync_point); - } - - private: - blink::WebGraphicsContext3D* web_graphics_context_; -}; - -} // namespace - -namespace content { - -class BufferedDataSourceHostImpl; - -#define COMPILE_ASSERT_MATCHING_ENUM(name) \ - COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \ - static_cast<int>(BufferedResourceLoader::k ## name), \ - mismatching_enums) -COMPILE_ASSERT_MATCHING_ENUM(Unspecified); -COMPILE_ASSERT_MATCHING_ENUM(Anonymous); -COMPILE_ASSERT_MATCHING_ENUM(UseCredentials); -#undef COMPILE_ASSERT_MATCHING_ENUM - -#define BIND_TO_RENDER_LOOP(function) \ - (DCHECK(main_task_runner_->BelongsToCurrentThread()), \ - media::BindToCurrentLoop(base::Bind(function, AsWeakPtr()))) - -#define BIND_TO_RENDER_LOOP1(function, arg1) \ - (DCHECK(main_task_runner_->BelongsToCurrentThread()), \ - media::BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1))) - -static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log, - const std::string& error) { - media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error)); -} - -WebMediaPlayerImpl::WebMediaPlayerImpl( - blink::WebLocalFrame* frame, - blink::WebMediaPlayerClient* client, - base::WeakPtr<WebMediaPlayerDelegate> delegate, - const WebMediaPlayerParams& params) - : frame_(frame), - network_state_(WebMediaPlayer::NetworkStateEmpty), - ready_state_(WebMediaPlayer::ReadyStateHaveNothing), - preload_(BufferedDataSource::AUTO), - main_task_runner_(base::MessageLoopProxy::current()), - media_task_runner_(params.media_task_runner()), - media_log_(params.media_log()), - pipeline_(media_task_runner_, media_log_.get()), - load_type_(LoadTypeURL), - opaque_(false), - paused_(true), - seeking_(false), - playback_rate_(0.0f), - ended_(false), - pending_seek_(false), - pending_seek_seconds_(0.0f), - should_notify_time_changed_(false), - client_(client), - delegate_(delegate), - defer_load_cb_(params.defer_load_cb()), - gpu_factories_(params.gpu_factories()), - supports_save_(true), - chunk_demuxer_(NULL), - compositor_task_runner_(params.compositor_task_runner()), - compositor_(new VideoFrameCompositor( - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged), - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))), - text_track_index_(0), - encrypted_media_support_( - params.CreateEncryptedMediaPlayerSupport(client)), - audio_hardware_config_(params.audio_hardware_config()) { - DCHECK(encrypted_media_support_); - - // Threaded compositing isn't enabled universally yet. - if (!compositor_task_runner_.get()) - compositor_task_runner_ = base::MessageLoopProxy::current(); - - media_log_->AddEvent( - media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED)); - - // |gpu_factories_| requires that its entry points be called on its - // |GetTaskRunner()|. Since |pipeline_| will own decoders created from the - // factories, require that their message loops are identical. - DCHECK(!gpu_factories_.get() || - (gpu_factories_->GetTaskRunner() == media_task_runner_.get())); - - // Use the null sink if no sink was provided. - audio_source_provider_ = new WebAudioSourceProviderImpl( - params.audio_renderer_sink().get() - ? params.audio_renderer_sink() - : new media::NullAudioSink(media_task_runner_)); -} - -WebMediaPlayerImpl::~WebMediaPlayerImpl() { - client_->setWebLayer(NULL); - - DCHECK(main_task_runner_->BelongsToCurrentThread()); - media_log_->AddEvent( - media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); - - if (delegate_.get()) - delegate_->PlayerGone(this); - - // Abort any pending IO so stopping the pipeline doesn't get blocked. - if (data_source_) - data_source_->Abort(); - if (chunk_demuxer_) { - chunk_demuxer_->Shutdown(); - chunk_demuxer_ = NULL; - } - - gpu_factories_ = NULL; - - // Make sure to kill the pipeline so there's no more media threads running. - // Note: stopping the pipeline might block for a long time. - base::WaitableEvent waiter(false, false); - pipeline_.Stop( - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter))); - waiter.Wait(); - - compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_); -} - -void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url, - CORSMode cors_mode) { - DVLOG(1) << __FUNCTION__ << "(" << load_type << ", " << url << ", " - << cors_mode << ")"; - if (!defer_load_cb_.is_null()) { - defer_load_cb_.Run(base::Bind( - &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode)); - return; - } - DoLoad(load_type, url, cors_mode); -} - -void WebMediaPlayerImpl::DoLoad(LoadType load_type, - const blink::WebURL& url, - CORSMode cors_mode) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - GURL gurl(url); - ReportMediaSchemeUma(gurl); - - // Set subresource URL for crash reporting. - base::debug::SetCrashKeyValue("subresource_url", gurl.spec()); - - load_type_ = load_type; - - SetNetworkState(WebMediaPlayer::NetworkStateLoading); - SetReadyState(WebMediaPlayer::ReadyStateHaveNothing); - media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec())); - - // Media source pipelines can start immediately. - if (load_type == LoadTypeMediaSource) { - supports_save_ = false; - StartPipeline(); - return; - } - - // Otherwise it's a regular request which requires resolving the URL first. - data_source_.reset(new BufferedDataSource( - url, - static_cast<BufferedResourceLoader::CORSMode>(cors_mode), - main_task_runner_, - frame_, - media_log_.get(), - &buffered_data_source_host_, - base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr()))); - data_source_->Initialize( - base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr())); - data_source_->SetPreload(preload_); -} - -void WebMediaPlayerImpl::play() { - DVLOG(1) << __FUNCTION__; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - paused_ = false; - pipeline_.SetPlaybackRate(playback_rate_); - if (data_source_) - data_source_->MediaIsPlaying(); - - media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY)); - - if (delegate_.get()) - delegate_->DidPlay(this); -} - -void WebMediaPlayerImpl::pause() { - DVLOG(1) << __FUNCTION__; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - paused_ = true; - pipeline_.SetPlaybackRate(0.0f); - if (data_source_) - data_source_->MediaIsPaused(); - paused_time_ = pipeline_.GetMediaTime(); - - media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE)); - - if (delegate_.get()) - delegate_->DidPause(this); -} - -bool WebMediaPlayerImpl::supportsSave() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - return supports_save_; -} - -void WebMediaPlayerImpl::seek(double seconds) { - DVLOG(1) << __FUNCTION__ << "(" << seconds << ")"; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - ended_ = false; - - if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata) - SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); - - base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds); - - if (seeking_) { - pending_seek_ = true; - pending_seek_seconds_ = seconds; - if (chunk_demuxer_) - chunk_demuxer_->CancelPendingSeek(seek_time); - return; - } - - media_log_->AddEvent(media_log_->CreateSeekEvent(seconds)); - - // Update our paused time. - if (paused_) - paused_time_ = seek_time; - - seeking_ = true; - - if (chunk_demuxer_) - chunk_demuxer_->StartWaitingForSeek(seek_time); - - // Kick off the asynchronous seek! - pipeline_.Seek( - seek_time, - BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, true)); -} - -void WebMediaPlayerImpl::setRate(double rate) { - DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - // TODO(kylep): Remove when support for negatives is added. Also, modify the - // following checks so rewind uses reasonable values also. - if (rate < 0.0) - return; - - // Limit rates to reasonable values by clamping. - if (rate != 0.0) { - if (rate < kMinRate) - rate = kMinRate; - else if (rate > kMaxRate) - rate = kMaxRate; - } - - playback_rate_ = rate; - if (!paused_) { - pipeline_.SetPlaybackRate(rate); - if (data_source_) - data_source_->MediaPlaybackRateChanged(rate); - } -} - -void WebMediaPlayerImpl::setVolume(double volume) { - DVLOG(1) << __FUNCTION__ << "(" << volume << ")"; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - pipeline_.SetVolume(volume); -} - -#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \ - COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::webkit_name) == \ - static_cast<int>(BufferedDataSource::chromium_name), \ - mismatching_enums) -COMPILE_ASSERT_MATCHING_ENUM(PreloadNone, NONE); -COMPILE_ASSERT_MATCHING_ENUM(PreloadMetaData, METADATA); -COMPILE_ASSERT_MATCHING_ENUM(PreloadAuto, AUTO); -#undef COMPILE_ASSERT_MATCHING_ENUM - -void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) { - DVLOG(1) << __FUNCTION__ << "(" << preload << ")"; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - preload_ = static_cast<BufferedDataSource::Preload>(preload); - if (data_source_) - data_source_->SetPreload(preload_); -} - -bool WebMediaPlayerImpl::hasVideo() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - return pipeline_metadata_.has_video; -} - -bool WebMediaPlayerImpl::hasAudio() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - return pipeline_metadata_.has_audio; -} - -blink::WebSize WebMediaPlayerImpl::naturalSize() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - return blink::WebSize(pipeline_metadata_.natural_size); -} - -bool WebMediaPlayerImpl::paused() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - return pipeline_.GetPlaybackRate() == 0.0f; -} - -bool WebMediaPlayerImpl::seeking() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) - return false; - - return seeking_; -} - -double WebMediaPlayerImpl::duration() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) - return std::numeric_limits<double>::quiet_NaN(); - - return GetPipelineDuration(); -} - -double WebMediaPlayerImpl::timelineOffset() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - if (pipeline_metadata_.timeline_offset.is_null()) - return std::numeric_limits<double>::quiet_NaN(); - - return pipeline_metadata_.timeline_offset.ToJsTime(); -} - -double WebMediaPlayerImpl::currentTime() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); - - // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement, - // see http://crbug.com/409280 - if (ended_) - return duration(); - - return (paused_ ? paused_time_ : pipeline_.GetMediaTime()).InSecondsF(); -} - -WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - return network_state_; -} - -WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - return ready_state_; -} - -blink::WebTimeRanges WebMediaPlayerImpl::buffered() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - media::Ranges<base::TimeDelta> buffered_time_ranges = - pipeline_.GetBufferedTimeRanges(); - - const base::TimeDelta duration = pipeline_.GetMediaDuration(); - if (duration != media::kInfiniteDuration()) { - buffered_data_source_host_.AddBufferedTimeRanges( - &buffered_time_ranges, duration); - } - return ConvertToWebTimeRanges(buffered_time_ranges); -} - -double WebMediaPlayerImpl::maxTimeSeekable() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - // If we haven't even gotten to ReadyStateHaveMetadata yet then just - // return 0 so that the seekable range is empty. - if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata) - return 0.0; - - // We don't support seeking in streaming media. - if (data_source_ && data_source_->IsStreaming()) - return 0.0; - return duration(); -} - -bool WebMediaPlayerImpl::didLoadingProgress() { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - bool pipeline_progress = pipeline_.DidLoadingProgress(); - bool data_progress = buffered_data_source_host_.DidLoadingProgress(); - return pipeline_progress || data_progress; -} - -void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, - const blink::WebRect& rect, - unsigned char alpha) { - paint(canvas, rect, alpha, SkXfermode::kSrcOver_Mode); -} - -void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, - const blink::WebRect& rect, - unsigned char alpha, - SkXfermode::Mode mode) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); - - // TODO(scherkus): Clarify paint() API contract to better understand when and - // why it's being called. For example, today paint() is called when: - // - We haven't reached HAVE_CURRENT_DATA and need to paint black - // - We're painting to a canvas - // See http://crbug.com/341225 http://crbug.com/342621 for details. - scoped_refptr<media::VideoFrame> video_frame = - GetCurrentFrameFromCompositor(); - - gfx::Rect gfx_rect(rect); - - skcanvas_video_renderer_.Paint(video_frame.get(), - canvas, - gfx_rect, - alpha, - mode, - pipeline_metadata_.video_rotation); -} - -bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const { - if (data_source_) - return data_source_->HasSingleOrigin(); - return true; -} - -bool WebMediaPlayerImpl::didPassCORSAccessCheck() const { - if (data_source_) - return data_source_->DidPassCORSAccessCheck(); - return false; -} - -double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const { - return ConvertSecondsToTimestamp(timeValue).InSecondsF(); -} - -unsigned WebMediaPlayerImpl::decodedFrameCount() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - media::PipelineStatistics stats = pipeline_.GetStatistics(); - return stats.video_frames_decoded; -} - -unsigned WebMediaPlayerImpl::droppedFrameCount() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - media::PipelineStatistics stats = pipeline_.GetStatistics(); - return stats.video_frames_dropped; -} - -unsigned WebMediaPlayerImpl::audioDecodedByteCount() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - media::PipelineStatistics stats = pipeline_.GetStatistics(); - return stats.audio_bytes_decoded; -} - -unsigned WebMediaPlayerImpl::videoDecodedByteCount() const { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - media::PipelineStatistics stats = pipeline_.GetStatistics(); - return stats.video_bytes_decoded; -} - -bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture( - blink::WebGraphicsContext3D* web_graphics_context, - unsigned int texture, - unsigned int level, - unsigned int internal_format, - unsigned int type, - bool premultiply_alpha, - bool flip_y) { - TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture"); - - scoped_refptr<media::VideoFrame> video_frame = - GetCurrentFrameFromCompositor(); - - if (!video_frame.get()) - return false; - if (video_frame->format() != media::VideoFrame::NATIVE_TEXTURE) - return false; - - const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); - if (mailbox_holder->texture_target != GL_TEXTURE_2D) - return false; - - web_graphics_context->waitSyncPoint(mailbox_holder->sync_point); - uint32 source_texture = web_graphics_context->createAndConsumeTextureCHROMIUM( - GL_TEXTURE_2D, mailbox_holder->mailbox.name); - - // The video is stored in a unmultiplied format, so premultiply - // if necessary. - web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, - premultiply_alpha); - // Application itself needs to take care of setting the right flip_y - // value down to get the expected result. - // flip_y==true means to reverse the video orientation while - // flip_y==false means to keep the intrinsic orientation. - web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); - web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D, - source_texture, - texture, - level, - internal_format, - type); - web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false); - web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, - false); - - web_graphics_context->deleteTexture(source_texture); - web_graphics_context->flush(); - - SyncPointClientImpl client(web_graphics_context); - video_frame->UpdateReleaseSyncPoint(&client); - return true; -} - -WebMediaPlayer::MediaKeyException -WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system, - const unsigned char* init_data, - unsigned init_data_length) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - return encrypted_media_support_->GenerateKeyRequest( - frame_, key_system, init_data, init_data_length); -} - -WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey( - const WebString& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const WebString& session_id) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - return encrypted_media_support_->AddKey( - key_system, key, key_length, init_data, init_data_length, session_id); -} - -WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest( - const WebString& key_system, - const WebString& session_id) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - return encrypted_media_support_->CancelKeyRequest(key_system, session_id); -} - -void WebMediaPlayerImpl::setContentDecryptionModule( - blink::WebContentDecryptionModule* cdm) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - encrypted_media_support_->SetContentDecryptionModule(cdm); -} - -void WebMediaPlayerImpl::setContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - encrypted_media_support_->SetContentDecryptionModule(cdm, result); -} - -void WebMediaPlayerImpl::setContentDecryptionModuleSync( - blink::WebContentDecryptionModule* cdm) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - encrypted_media_support_->SetContentDecryptionModuleSync(cdm); -} - -void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, - PipelineStatus status) { - DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")"; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - seeking_ = false; - if (pending_seek_) { - pending_seek_ = false; - seek(pending_seek_seconds_); - return; - } - - if (status != media::PIPELINE_OK) { - OnPipelineError(status); - return; - } - - // Update our paused time. - if (paused_) - paused_time_ = pipeline_.GetMediaTime(); - - should_notify_time_changed_ = time_changed; -} - -void WebMediaPlayerImpl::OnPipelineEnded() { - DVLOG(1) << __FUNCTION__; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - // Ignore state changes until we've completed all outstanding seeks. - if (seeking_ || pending_seek_) - return; - - ended_ = true; - client_->timeChanged(); -} - -void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - DCHECK_NE(error, media::PIPELINE_OK); - - if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) { - // Any error that occurs before reaching ReadyStateHaveMetadata should - // be considered a format error. - SetNetworkState(WebMediaPlayer::NetworkStateFormatError); - return; - } - - SetNetworkState(PipelineErrorToNetworkState(error)); - - if (error == media::PIPELINE_ERROR_DECRYPT) - encrypted_media_support_->OnPipelineDecryptError(); -} - -void WebMediaPlayerImpl::OnPipelineMetadata( - media::PipelineMetadata metadata) { - DVLOG(1) << __FUNCTION__; - - pipeline_metadata_ = metadata; - - UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", - metadata.video_rotation, - media::VIDEO_ROTATION_MAX + 1); - SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); - - if (hasVideo()) { - DCHECK(!video_weblayer_); - scoped_refptr<cc::VideoLayer> layer = - cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation); - - if (pipeline_metadata_.video_rotation == media::VIDEO_ROTATION_90 || - pipeline_metadata_.video_rotation == media::VIDEO_ROTATION_270) { - gfx::Size size = pipeline_metadata_.natural_size; - pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width()); - } - - video_weblayer_.reset(new cc_blink::WebLayerImpl(layer)); - video_weblayer_->setOpaque(opaque_); - client_->setWebLayer(video_weblayer_.get()); - } -} - -void WebMediaPlayerImpl::OnPipelineBufferingStateChanged( - media::BufferingState buffering_state) { - DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")"; - - // Ignore buffering state changes until we've completed all outstanding seeks. - if (seeking_ || pending_seek_) - return; - - // TODO(scherkus): Handle other buffering states when Pipeline starts using - // them and translate them ready state changes http://crbug.com/144683 - DCHECK_EQ(buffering_state, media::BUFFERING_HAVE_ENOUGH); - SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); - - // Blink expects a timeChanged() in response to a seek(). - if (should_notify_time_changed_) - client_->timeChanged(); -} - -void WebMediaPlayerImpl::OnDemuxerOpened() { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - client_->mediaSourceOpened(new WebMediaSourceImpl( - chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_))); -} - -void WebMediaPlayerImpl::OnAddTextTrack( - const media::TextTrackConfig& config, - const media::AddTextTrackDoneCB& done_cb) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - const WebInbandTextTrackImpl::Kind web_kind = - static_cast<WebInbandTextTrackImpl::Kind>(config.kind()); - const blink::WebString web_label = - blink::WebString::fromUTF8(config.label()); - const blink::WebString web_language = - blink::WebString::fromUTF8(config.language()); - const blink::WebString web_id = - blink::WebString::fromUTF8(config.id()); - - scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track( - new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id, - text_track_index_++)); - - scoped_ptr<media::TextTrack> text_track(new TextTrackImpl( - main_task_runner_, client_, web_inband_text_track.Pass())); - - done_cb.Run(text_track.Pass()); -} - -void WebMediaPlayerImpl::DataSourceInitialized(bool success) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - if (!success) { - SetNetworkState(WebMediaPlayer::NetworkStateFormatError); - return; - } - - StartPipeline(); -} - -void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { - if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading) - SetNetworkState(WebMediaPlayer::NetworkStateIdle); - else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle) - SetNetworkState(WebMediaPlayer::NetworkStateLoading); - media_log_->AddEvent( - media_log_->CreateBooleanEvent( - media::MediaLogEvent::NETWORK_ACTIVITY_SET, - "is_downloading_data", is_downloading)); -} - -// TODO(xhwang): Move this to a factory class so that we can create different -// renderers. -scoped_ptr<media::Renderer> WebMediaPlayerImpl::CreateRenderer() { - media::SetDecryptorReadyCB set_decryptor_ready_cb = - encrypted_media_support_->CreateSetDecryptorReadyCB(); - - // Create our audio decoders and renderer. - ScopedVector<media::AudioDecoder> audio_decoders; - - media::LogCB log_cb = base::Bind(&LogMediaSourceError, media_log_); - audio_decoders.push_back(new media::FFmpegAudioDecoder(media_task_runner_, - log_cb)); - audio_decoders.push_back(new media::OpusAudioDecoder(media_task_runner_)); - - scoped_ptr<media::AudioRenderer> audio_renderer(new media::AudioRendererImpl( - media_task_runner_, - audio_source_provider_.get(), - audio_decoders.Pass(), - set_decryptor_ready_cb, - audio_hardware_config_)); - - // Create our video decoders and renderer. - ScopedVector<media::VideoDecoder> video_decoders; - - if (gpu_factories_.get()) { - video_decoders.push_back( - new media::GpuVideoDecoder(gpu_factories_, media_log_)); - } - -#if !defined(MEDIA_DISABLE_LIBVPX) - video_decoders.push_back(new media::VpxVideoDecoder(media_task_runner_)); -#endif // !defined(MEDIA_DISABLE_LIBVPX) - - video_decoders.push_back(new media::FFmpegVideoDecoder(media_task_runner_)); - - scoped_ptr<media::VideoRenderer> video_renderer( - new media::VideoRendererImpl( - media_task_runner_, - video_decoders.Pass(), - set_decryptor_ready_cb, - base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)), - true)); - - // Create renderer. - return scoped_ptr<media::Renderer>(new media::RendererImpl( - media_task_runner_, - demuxer_.get(), - audio_renderer.Pass(), - video_renderer.Pass())); -} - -void WebMediaPlayerImpl::StartPipeline() { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - // Keep track if this is a MSE or non-MSE playback. - UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback", - (load_type_ == LoadTypeMediaSource)); - - media::LogCB mse_log_cb; - media::Demuxer::NeedKeyCB need_key_cb = - encrypted_media_support_->CreateNeedKeyCB(); - - // Figure out which demuxer to use. - if (load_type_ != LoadTypeMediaSource) { - DCHECK(!chunk_demuxer_); - DCHECK(data_source_); - - demuxer_.reset(new media::FFmpegDemuxer( - media_task_runner_, data_source_.get(), - need_key_cb, - media_log_)); - } else { - DCHECK(!chunk_demuxer_); - DCHECK(!data_source_); - - mse_log_cb = base::Bind(&LogMediaSourceError, media_log_); - - chunk_demuxer_ = new media::ChunkDemuxer( - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened), - need_key_cb, - mse_log_cb, - true); - demuxer_.reset(chunk_demuxer_); - } - - // ... and we're ready to go! - seeking_ = true; - pipeline_.Start( - demuxer_.get(), - CreateRenderer(), - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded), - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError), - BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false), - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata), - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged), - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged), - BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack)); -} - -void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { - DVLOG(1) << __FUNCTION__ << "(" << state << ")"; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - network_state_ = state; - // Always notify to ensure client has the latest value. - client_->networkStateChanged(); -} - -void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) { - DVLOG(1) << __FUNCTION__ << "(" << state << ")"; - DCHECK(main_task_runner_->BelongsToCurrentThread()); - - if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ && - data_source_->assume_fully_buffered() && - network_state_ == WebMediaPlayer::NetworkStateLoading) - SetNetworkState(WebMediaPlayer::NetworkStateLoaded); - - ready_state_ = state; - // Always notify to ensure client has the latest value. - client_->readyStateChanged(); -} - -blink::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() { - return audio_source_provider_.get(); -} - -double WebMediaPlayerImpl::GetPipelineDuration() const { - base::TimeDelta duration = pipeline_.GetMediaDuration(); - - // Return positive infinity if the resource is unbounded. - // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration - if (duration == media::kInfiniteDuration()) - return std::numeric_limits<double>::infinity(); - - return duration.InSecondsF(); -} - -void WebMediaPlayerImpl::OnDurationChanged() { - if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) - return; - - client_->durationChanged(); -} - -void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); - TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged"); - - media_log_->AddEvent( - media_log_->CreateVideoSizeSetEvent(size.width(), size.height())); - pipeline_metadata_.natural_size = size; - - client_->sizeChanged(); -} - -void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); - - opaque_ = opaque; - if (video_weblayer_) - video_weblayer_->setOpaque(opaque_); -} - -void WebMediaPlayerImpl::FrameReady( - const scoped_refptr<media::VideoFrame>& frame) { - compositor_task_runner_->PostTask( - FROM_HERE, - base::Bind(&VideoFrameCompositor::UpdateCurrentFrame, - base::Unretained(compositor_), - frame)); -} - -static void GetCurrentFrameAndSignal( - VideoFrameCompositor* compositor, - scoped_refptr<media::VideoFrame>* video_frame_out, - base::WaitableEvent* event) { - TRACE_EVENT0("media", "GetCurrentFrameAndSignal"); - *video_frame_out = compositor->GetCurrentFrame(); - event->Signal(); -} - -scoped_refptr<media::VideoFrame> -WebMediaPlayerImpl::GetCurrentFrameFromCompositor() { - TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor"); - if (compositor_task_runner_->BelongsToCurrentThread()) - return compositor_->GetCurrentFrame(); - - // Use a posted task and waitable event instead of a lock otherwise - // WebGL/Canvas can see different content than what the compositor is seeing. - scoped_refptr<media::VideoFrame> video_frame; - base::WaitableEvent event(false, false); - compositor_task_runner_->PostTask(FROM_HERE, - base::Bind(&GetCurrentFrameAndSignal, - base::Unretained(compositor_), - &video_frame, - &event)); - event.Wait(); - return video_frame; -} - -} // namespace content diff --git a/content/renderer/media/webmediaplayer_impl.h b/content/renderer/media/webmediaplayer_impl.h deleted file mode 100644 index 7c2892b..0000000 --- a/content/renderer/media/webmediaplayer_impl.h +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/thread.h" -#include "content/renderer/media/buffered_data_source_host_impl.h" -#include "content/renderer/media/video_frame_compositor.h" -#include "media/base/audio_renderer_sink.h" -// TODO(xhwang): Remove when we remove prefixed EME implementation. -#include "media/base/media_keys.h" -#include "media/base/pipeline.h" -#include "media/base/text_track.h" -#include "media/filters/skcanvas_video_renderer.h" -#include "skia/ext/platform_canvas.h" -#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h" -#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h" -#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" -#include "third_party/WebKit/public/platform/WebMediaPlayer.h" -#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" -#include "url/gurl.h" - -namespace blink { -class WebLocalFrame; -} - -namespace base { -class SingleThreadTaskRunner; -} - -namespace cc_blink { -class WebLayerImpl; -} - -namespace media { -class AudioHardwareConfig; -class ChunkDemuxer; -class GpuVideoAcceleratorFactories; -class MediaLog; -} - - -namespace content { -class BufferedDataSource; -class EncryptedMediaPlayerSupport; -class VideoFrameCompositor; -class WebAudioSourceProviderImpl; -class WebMediaPlayerDelegate; -class WebMediaPlayerParams; -class WebTextTrackImpl; - -// The canonical implementation of blink::WebMediaPlayer that's backed by -// media::Pipeline. Handles normal resource loading, Media Source, and -// Encrypted Media. -class WebMediaPlayerImpl - : public blink::WebMediaPlayer, - public base::SupportsWeakPtr<WebMediaPlayerImpl> { - public: - // Constructs a WebMediaPlayer implementation using Chromium's media stack. - // |delegate| may be null. - WebMediaPlayerImpl(blink::WebLocalFrame* frame, - blink::WebMediaPlayerClient* client, - base::WeakPtr<WebMediaPlayerDelegate> delegate, - const WebMediaPlayerParams& params); - virtual ~WebMediaPlayerImpl(); - - virtual void load(LoadType load_type, - const blink::WebURL& url, - CORSMode cors_mode); - - // Playback controls. - virtual void play(); - virtual void pause(); - virtual bool supportsSave() const; - virtual void seek(double seconds); - virtual void setRate(double rate); - virtual void setVolume(double volume); - virtual void setPreload(blink::WebMediaPlayer::Preload preload); - virtual blink::WebTimeRanges buffered() const; - virtual double maxTimeSeekable() const; - - // Methods for painting. - virtual void paint(blink::WebCanvas* canvas, - const blink::WebRect& rect, - unsigned char alpha, - SkXfermode::Mode mode); - // TODO(dshwang): remove it because above method replaces. crbug.com/401027 - virtual void paint(blink::WebCanvas* canvas, - const blink::WebRect& rect, - unsigned char alpha); - - // True if the loaded media has a playable video/audio track. - virtual bool hasVideo() const; - virtual bool hasAudio() const; - - // Dimensions of the video. - virtual blink::WebSize naturalSize() const; - - // Getters of playback state. - virtual bool paused() const; - virtual bool seeking() const; - virtual double duration() const; - virtual double timelineOffset() const; - virtual double currentTime() const; - - // Internal states of loading and network. - // TODO(hclam): Ask the pipeline about the state rather than having reading - // them from members which would cause race conditions. - virtual blink::WebMediaPlayer::NetworkState networkState() const; - virtual blink::WebMediaPlayer::ReadyState readyState() const; - - virtual bool didLoadingProgress(); - - virtual bool hasSingleSecurityOrigin() const; - virtual bool didPassCORSAccessCheck() const; - - virtual double mediaTimeForTimeValue(double timeValue) const; - - virtual unsigned decodedFrameCount() const; - virtual unsigned droppedFrameCount() const; - virtual unsigned audioDecodedByteCount() const; - virtual unsigned videoDecodedByteCount() const; - - virtual bool copyVideoTextureToPlatformTexture( - blink::WebGraphicsContext3D* web_graphics_context, - unsigned int texture, - unsigned int level, - unsigned int internal_format, - unsigned int type, - bool premultiply_alpha, - bool flip_y); - - virtual blink::WebAudioSourceProvider* audioSourceProvider(); - - virtual MediaKeyException generateKeyRequest( - const blink::WebString& key_system, - const unsigned char* init_data, - unsigned init_data_length); - - virtual MediaKeyException addKey(const blink::WebString& key_system, - const unsigned char* key, - unsigned key_length, - const unsigned char* init_data, - unsigned init_data_length, - const blink::WebString& session_id); - - virtual MediaKeyException cancelKeyRequest( - const blink::WebString& key_system, - const blink::WebString& session_id); - - // TODO(jrummell): Remove this method once Blink updated to use the other - // two methods. - virtual void setContentDecryptionModule( - blink::WebContentDecryptionModule* cdm); - virtual void setContentDecryptionModule( - blink::WebContentDecryptionModule* cdm, - blink::WebContentDecryptionModuleResult result); - virtual void setContentDecryptionModuleSync( - blink::WebContentDecryptionModule* cdm); - - void OnPipelineSeeked(bool time_changed, media::PipelineStatus status); - void OnPipelineEnded(); - void OnPipelineError(media::PipelineStatus error); - void OnPipelineMetadata(media::PipelineMetadata metadata); - void OnPipelineBufferingStateChanged(media::BufferingState buffering_state); - void OnDemuxerOpened(); - void OnAddTextTrack(const media::TextTrackConfig& config, - const media::AddTextTrackDoneCB& done_cb); - - private: - // Called after |defer_load_cb_| has decided to allow the load. If - // |defer_load_cb_| is null this is called immediately. - void DoLoad(LoadType load_type, - const blink::WebURL& url, - CORSMode cors_mode); - - // Called after asynchronous initialization of a data source completed. - void DataSourceInitialized(bool success); - - // Called when the data source is downloading or paused. - void NotifyDownloading(bool is_downloading); - - // Creates a media::Renderer that will be used by the |pipeline_|. - scoped_ptr<media::Renderer> CreateRenderer(); - - // Finishes starting the pipeline due to a call to load(). - void StartPipeline(); - - // Helpers that set the network/ready state and notifies the client if - // they've changed. - void SetNetworkState(blink::WebMediaPlayer::NetworkState state); - void SetReadyState(blink::WebMediaPlayer::ReadyState state); - - // Gets the duration value reported by the pipeline. - double GetPipelineDuration() const; - - // Callbacks from |pipeline_| that are forwarded to |client_|. - void OnDurationChanged(); - void OnNaturalSizeChanged(gfx::Size size); - void OnOpacityChanged(bool opaque); - - // Called by VideoRendererImpl on its internal thread with the new frame to be - // painted. - void FrameReady(const scoped_refptr<media::VideoFrame>& frame); - - // Returns the current video frame from |compositor_|. Blocks until the - // compositor can return the frame. - scoped_refptr<media::VideoFrame> GetCurrentFrameFromCompositor(); - - blink::WebLocalFrame* frame_; - - // TODO(hclam): get rid of these members and read from the pipeline directly. - blink::WebMediaPlayer::NetworkState network_state_; - blink::WebMediaPlayer::ReadyState ready_state_; - - // Preload state for when |data_source_| is created after setPreload(). - BufferedDataSource::Preload preload_; - - // Task runner for posting tasks on Chrome's main thread. Also used - // for DCHECKs so methods calls won't execute in the wrong thread. - const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; - - scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; - scoped_refptr<media::MediaLog> media_log_; - media::Pipeline pipeline_; - - // The LoadType passed in the |load_type| parameter of the load() call. - LoadType load_type_; - - // Cache of metadata for answering hasAudio(), hasVideo(), and naturalSize(). - media::PipelineMetadata pipeline_metadata_; - - // Whether the video is known to be opaque or not. - bool opaque_; - - // Playback state. - // - // TODO(scherkus): we have these because Pipeline favours the simplicity of a - // single "playback rate" over worrying about paused/stopped etc... It forces - // all clients to manage the pause+playback rate externally, but is that - // really a bad thing? - // - // TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want - // to hang the render thread during pause(), we record the time at the same - // time we pause and then return that value in currentTime(). Otherwise our - // clock can creep forward a little bit while the asynchronous - // SetPlaybackRate(0) is being executed. - bool paused_; - bool seeking_; - double playback_rate_; - base::TimeDelta paused_time_; - - // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement, - // see http://crbug.com/409280 - bool ended_; - - // Seek gets pending if another seek is in progress. Only last pending seek - // will have effect. - bool pending_seek_; - double pending_seek_seconds_; - - // Tracks whether to issue time changed notifications during buffering state - // changes. - bool should_notify_time_changed_; - - blink::WebMediaPlayerClient* client_; - - base::WeakPtr<WebMediaPlayerDelegate> delegate_; - - base::Callback<void(const base::Closure&)> defer_load_cb_; - - // Factories for supporting video accelerators. May be null. - scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_; - - // Routes audio playback to either AudioRendererSink or WebAudio. - scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_; - - bool supports_save_; - - // These two are mutually exclusive: - // |data_source_| is used for regular resource loads. - // |chunk_demuxer_| is used for Media Source resource loads. - // - // |demuxer_| will contain the appropriate demuxer based on which resource - // load strategy we're using. - scoped_ptr<BufferedDataSource> data_source_; - scoped_ptr<media::Demuxer> demuxer_; - media::ChunkDemuxer* chunk_demuxer_; - - BufferedDataSourceHostImpl buffered_data_source_host_; - - // Video rendering members. - scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; - VideoFrameCompositor* compositor_; // Deleted on |compositor_task_runner_|. - media::SkCanvasVideoRenderer skcanvas_video_renderer_; - - // The compositor layer for displaying the video content when using composited - // playback. - scoped_ptr<cc_blink::WebLayerImpl> video_weblayer_; - - // Text track objects get a unique index value when they're created. - int text_track_index_; - - scoped_ptr<EncryptedMediaPlayerSupport> encrypted_media_support_; - - const media::AudioHardwareConfig& audio_hardware_config_; - - DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_ diff --git a/content/renderer/media/webmediaplayer_ms.cc b/content/renderer/media/webmediaplayer_ms.cc index b8ecc14..5aefdd9 100644 --- a/content/renderer/media/webmediaplayer_ms.cc +++ b/content/renderer/media/webmediaplayer_ms.cc @@ -16,13 +16,13 @@ #include "content/renderer/media/media_stream_audio_renderer.h" #include "content/renderer/media/media_stream_renderer_factory.h" #include "content/renderer/media/video_frame_provider.h" -#include "content/renderer/media/webmediaplayer_delegate.h" -#include "content/renderer/media/webmediaplayer_util.h" #include "content/renderer/render_frame_impl.h" #include "media/base/media_log.h" #include "media/base/video_frame.h" #include "media/base/video_rotation.h" #include "media/base/video_util.h" +#include "media/blink/webmediaplayer_delegate.h" +#include "media/blink/webmediaplayer_util.h" #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" #include "third_party/WebKit/public/platform/WebRect.h" #include "third_party/WebKit/public/platform/WebSize.h" @@ -81,7 +81,7 @@ namespace content { WebMediaPlayerMS::WebMediaPlayerMS( blink::WebFrame* frame, blink::WebMediaPlayerClient* client, - base::WeakPtr<WebMediaPlayerDelegate> delegate, + base::WeakPtr<media::WebMediaPlayerDelegate> delegate, media::MediaLog* media_log, scoped_ptr<MediaStreamRendererFactory> factory) : frame_(frame), @@ -358,7 +358,7 @@ bool WebMediaPlayerMS::didPassCORSAccessCheck() const { } double WebMediaPlayerMS::mediaTimeForTimeValue(double timeValue) const { - return ConvertSecondsToTimestamp(timeValue).InSecondsF(); + return media::ConvertSecondsToTimestamp(timeValue).InSecondsF(); } unsigned WebMediaPlayerMS::decodedFrameCount() const { diff --git a/content/renderer/media/webmediaplayer_ms.h b/content/renderer/media/webmediaplayer_ms.h index eea5c03..eb67d3d 100644 --- a/content/renderer/media/webmediaplayer_ms.h +++ b/content/renderer/media/webmediaplayer_ms.h @@ -23,6 +23,7 @@ class WebMediaPlayerClient; namespace media { class MediaLog; +class WebMediaPlayerDelegate; } namespace cc_blink { @@ -33,7 +34,6 @@ namespace content { class MediaStreamAudioRenderer; class MediaStreamRendererFactory; class VideoFrameProvider; -class WebMediaPlayerDelegate; // WebMediaPlayerMS delegates calls from WebCore::MediaPlayerPrivate to // Chrome's media player when "src" is from media stream. @@ -58,7 +58,7 @@ class WebMediaPlayerMS // a MediaStreamClient which provides VideoFrameProvider. WebMediaPlayerMS(blink::WebFrame* frame, blink::WebMediaPlayerClient* client, - base::WeakPtr<WebMediaPlayerDelegate> delegate, + base::WeakPtr<media::WebMediaPlayerDelegate> delegate, media::MediaLog* media_log, scoped_ptr<MediaStreamRendererFactory> factory); virtual ~WebMediaPlayerMS(); @@ -155,7 +155,7 @@ class WebMediaPlayerMS blink::WebMediaPlayerClient* client_; - base::WeakPtr<WebMediaPlayerDelegate> delegate_; + base::WeakPtr<media::WebMediaPlayerDelegate> delegate_; // Specify content:: to disambiguate from cc::. scoped_refptr<content::VideoFrameProvider> video_frame_provider_; diff --git a/content/renderer/media/webmediaplayer_params.cc b/content/renderer/media/webmediaplayer_params.cc deleted file mode 100644 index 5daa7d0..0000000 --- a/content/renderer/media/webmediaplayer_params.cc +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webmediaplayer_params.h" - -#include "base/single_thread_task_runner.h" -#include "media/base/audio_renderer_sink.h" -#include "media/base/media_log.h" -#include "media/filters/gpu_video_accelerator_factories.h" - -namespace content { - -WebMediaPlayerParams::WebMediaPlayerParams( - const base::Callback<void(const base::Closure&)>& defer_load_cb, - const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink, - const media::AudioHardwareConfig& audio_hardware_config, - const scoped_refptr<media::MediaLog>& media_log, - const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories, - const scoped_refptr<base::SingleThreadTaskRunner>& - media_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& - compositor_task_runner, - const EncryptedMediaPlayerSupportCreateCB& - encrypted_media_player_support_cb) - : defer_load_cb_(defer_load_cb), - audio_renderer_sink_(audio_renderer_sink), - audio_hardware_config_(audio_hardware_config), - media_log_(media_log), - gpu_factories_(gpu_factories), - media_task_runner_(media_task_runner), - compositor_task_runner_(compositor_task_runner), - encrypted_media_player_support_cb_(encrypted_media_player_support_cb) { -} - -WebMediaPlayerParams::~WebMediaPlayerParams() {} - -scoped_ptr<EncryptedMediaPlayerSupport> -WebMediaPlayerParams::CreateEncryptedMediaPlayerSupport( - blink::WebMediaPlayerClient* client) const { - return encrypted_media_player_support_cb_.Run(client); -} - -} // namespace content diff --git a/content/renderer/media/webmediaplayer_params.h b/content/renderer/media/webmediaplayer_params.h deleted file mode 100644 index cfaff62..0000000 --- a/content/renderer/media/webmediaplayer_params.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_PARAMS_H_ -#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_PARAMS_H_ - -#include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "content/renderer/media/crypto/encrypted_media_player_support.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace blink { -class WebMediaPlayerClient; -} - -namespace media { -class AudioHardwareConfig; -class AudioRendererSink; -class GpuVideoAcceleratorFactories; -class MediaLog; -} - -namespace content { - -// Holds parameters for constructing WebMediaPlayerImpl without having -// to plumb arguments through various abstraction layers. -class WebMediaPlayerParams { - public: - // Callback used to create EncryptedMediaPlayerSupport instances. This - // callback must always return a valid EncryptedMediaPlayerSupport object. - typedef base::Callback<scoped_ptr<EncryptedMediaPlayerSupport>( - blink::WebMediaPlayerClient*)> EncryptedMediaPlayerSupportCreateCB; - - // |defer_load_cb|, |audio_renderer_sink|, and |compositor_task_runner| may be - // null. - WebMediaPlayerParams( - const base::Callback<void(const base::Closure&)>& defer_load_cb, - const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink, - const media::AudioHardwareConfig& audio_hardware_config, - const scoped_refptr<media::MediaLog>& media_log, - const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories, - const scoped_refptr<base::SingleThreadTaskRunner>& - media_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& - compositor_task_runner, - const EncryptedMediaPlayerSupportCreateCB& - encrypted_media_player_support_cb); - - ~WebMediaPlayerParams(); - - base::Callback<void(const base::Closure&)> defer_load_cb() const { - return defer_load_cb_; - } - - const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink() const { - return audio_renderer_sink_; - } - - const media::AudioHardwareConfig& audio_hardware_config() const { - return audio_hardware_config_; - } - - const scoped_refptr<media::MediaLog>& media_log() const { - return media_log_; - } - - const scoped_refptr<media::GpuVideoAcceleratorFactories>& - gpu_factories() const { - return gpu_factories_; - } - - const scoped_refptr<base::SingleThreadTaskRunner>& - media_task_runner() const { - return media_task_runner_; - } - - const scoped_refptr<base::SingleThreadTaskRunner>& - compositor_task_runner() const { - return compositor_task_runner_; - } - - scoped_ptr<EncryptedMediaPlayerSupport> - CreateEncryptedMediaPlayerSupport(blink::WebMediaPlayerClient* client) const; - - private: - base::Callback<void(const base::Closure&)> defer_load_cb_; - scoped_refptr<media::AudioRendererSink> audio_renderer_sink_; - const media::AudioHardwareConfig& audio_hardware_config_; - scoped_refptr<media::MediaLog> media_log_; - scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_; - scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; - EncryptedMediaPlayerSupportCreateCB encrypted_media_player_support_cb_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(WebMediaPlayerParams); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_PARAMS_H_ diff --git a/content/renderer/media/webmediaplayer_util.cc b/content/renderer/media/webmediaplayer_util.cc deleted file mode 100644 index 6d1b1e2..0000000 --- a/content/renderer/media/webmediaplayer_util.cc +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webmediaplayer_util.h" - -#include <math.h> - -#include "base/metrics/histogram.h" -#include "media/base/media_keys.h" -#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h" - -namespace content { - -// Compile asserts shared by all platforms. - -#define COMPILE_ASSERT_MATCHING_ENUM(name) \ - COMPILE_ASSERT( \ - static_cast<int>(blink::WebMediaPlayerClient::MediaKeyErrorCode ## name) == \ - static_cast<int>(media::MediaKeys::k ## name ## Error), \ - mismatching_enums) -COMPILE_ASSERT_MATCHING_ENUM(Unknown); -COMPILE_ASSERT_MATCHING_ENUM(Client); -#undef COMPILE_ASSERT_MATCHING_ENUM - -base::TimeDelta ConvertSecondsToTimestamp(double seconds) { - double microseconds = seconds * base::Time::kMicrosecondsPerSecond; - return base::TimeDelta::FromMicroseconds( - microseconds > 0 ? microseconds + 0.5 : ceil(microseconds - 0.5)); -} - -blink::WebTimeRanges ConvertToWebTimeRanges( - const media::Ranges<base::TimeDelta>& ranges) { - blink::WebTimeRanges result(ranges.size()); - for (size_t i = 0; i < ranges.size(); ++i) { - result[i].start = ranges.start(i).InSecondsF(); - result[i].end = ranges.end(i).InSecondsF(); - } - return result; -} - -blink::WebMediaPlayer::NetworkState PipelineErrorToNetworkState( - media::PipelineStatus error) { - DCHECK_NE(error, media::PIPELINE_OK); - - switch (error) { - case media::PIPELINE_ERROR_NETWORK: - case media::PIPELINE_ERROR_READ: - return blink::WebMediaPlayer::NetworkStateNetworkError; - - // TODO(vrk): Because OnPipelineInitialize() directly reports the - // NetworkStateFormatError instead of calling OnPipelineError(), I believe - // this block can be deleted. Should look into it! (crbug.com/126070) - case media::PIPELINE_ERROR_INITIALIZATION_FAILED: - case media::PIPELINE_ERROR_COULD_NOT_RENDER: - case media::PIPELINE_ERROR_URL_NOT_FOUND: - case media::DEMUXER_ERROR_COULD_NOT_OPEN: - case media::DEMUXER_ERROR_COULD_NOT_PARSE: - case media::DEMUXER_ERROR_NO_SUPPORTED_STREAMS: - case media::DECODER_ERROR_NOT_SUPPORTED: - return blink::WebMediaPlayer::NetworkStateFormatError; - - case media::PIPELINE_ERROR_DECODE: - case media::PIPELINE_ERROR_ABORT: - case media::PIPELINE_ERROR_OPERATION_PENDING: - case media::PIPELINE_ERROR_INVALID_STATE: - return blink::WebMediaPlayer::NetworkStateDecodeError; - - case media::PIPELINE_ERROR_DECRYPT: - // TODO(xhwang): Change to use NetworkStateDecryptError once it's added in - // Webkit (see http://crbug.com/124486). - return blink::WebMediaPlayer::NetworkStateDecodeError; - - case media::PIPELINE_OK: - NOTREACHED() << "Unexpected status! " << error; - } - return blink::WebMediaPlayer::NetworkStateFormatError; -} - -namespace { - -// Helper enum for reporting scheme histograms. -enum URLSchemeForHistogram { - kUnknownURLScheme, - kMissingURLScheme, - kHttpURLScheme, - kHttpsURLScheme, - kFtpURLScheme, - kChromeExtensionURLScheme, - kJavascriptURLScheme, - kFileURLScheme, - kBlobURLScheme, - kDataURLScheme, - kFileSystemScheme, - kMaxURLScheme = kFileSystemScheme // Must be equal to highest enum value. -}; - -URLSchemeForHistogram URLScheme(const GURL& url) { - if (!url.has_scheme()) return kMissingURLScheme; - if (url.SchemeIs("http")) return kHttpURLScheme; - if (url.SchemeIs("https")) return kHttpsURLScheme; - if (url.SchemeIs("ftp")) return kFtpURLScheme; - if (url.SchemeIs("chrome-extension")) return kChromeExtensionURLScheme; - if (url.SchemeIs("javascript")) return kJavascriptURLScheme; - if (url.SchemeIs("file")) return kFileURLScheme; - if (url.SchemeIs("blob")) return kBlobURLScheme; - if (url.SchemeIs("data")) return kDataURLScheme; - if (url.SchemeIs("filesystem")) return kFileSystemScheme; - - return kUnknownURLScheme; -} - -} // namespace - -void ReportMediaSchemeUma(const GURL& url) { - UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme); -} - -} // namespace content diff --git a/content/renderer/media/webmediaplayer_util.h b/content/renderer/media/webmediaplayer_util.h deleted file mode 100644 index d401c39..0000000 --- a/content/renderer/media/webmediaplayer_util.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_UTIL_H_ -#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_UTIL_H_ - -#include "base/time/time.h" -#include "media/base/pipeline_status.h" -#include "media/base/ranges.h" -#include "third_party/WebKit/public/platform/WebMediaPlayer.h" -#include "third_party/WebKit/public/platform/WebTimeRange.h" -#include "url/gurl.h" - -namespace content { - -// Platform independent method for converting and rounding floating point -// seconds to an int64 timestamp. -// -// Refer to https://bugs.webkit.org/show_bug.cgi?id=52697 for details. -base::TimeDelta ConvertSecondsToTimestamp(double seconds); - -blink::WebTimeRanges ConvertToWebTimeRanges( - const media::Ranges<base::TimeDelta>& ranges); - -blink::WebMediaPlayer::NetworkState PipelineErrorToNetworkState( - media::PipelineStatus error); - -// Report the scheme of Media URIs. -void ReportMediaSchemeUma(const GURL& url); - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_UTIL_H_ diff --git a/content/renderer/media/webmediasource_impl.cc b/content/renderer/media/webmediasource_impl.cc deleted file mode 100644 index b3078f7..0000000 --- a/content/renderer/media/webmediasource_impl.cc +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webmediasource_impl.h" - -#include "base/guid.h" -#include "content/renderer/media/websourcebuffer_impl.h" -#include "media/filters/chunk_demuxer.h" -#include "third_party/WebKit/public/platform/WebCString.h" -#include "third_party/WebKit/public/platform/WebString.h" - -using ::blink::WebString; -using ::blink::WebMediaSource; - -namespace content { - -#define COMPILE_ASSERT_MATCHING_STATUS_ENUM(webkit_name, chromium_name) \ - COMPILE_ASSERT(static_cast<int>(WebMediaSource::webkit_name) == \ - static_cast<int>(media::ChunkDemuxer::chromium_name), \ - mismatching_status_enums) -COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddStatusOk, kOk); -COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddStatusNotSupported, kNotSupported); -COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddStatusReachedIdLimit, kReachedIdLimit); -#undef COMPILE_ASSERT_MATCHING_STATUS_ENUM - -WebMediaSourceImpl::WebMediaSourceImpl( - media::ChunkDemuxer* demuxer, media::LogCB log_cb) - : demuxer_(demuxer), - log_cb_(log_cb) { - DCHECK(demuxer_); -} - -WebMediaSourceImpl::~WebMediaSourceImpl() {} - -WebMediaSource::AddStatus WebMediaSourceImpl::addSourceBuffer( - const blink::WebString& type, - const blink::WebVector<blink::WebString>& codecs, - blink::WebSourceBuffer** source_buffer) { - std::string id = base::GenerateGUID(); - std::vector<std::string> new_codecs(codecs.size()); - for (size_t i = 0; i < codecs.size(); ++i) - new_codecs[i] = codecs[i].utf8().data(); - - WebMediaSource::AddStatus result = - static_cast<WebMediaSource::AddStatus>( - demuxer_->AddId(id, type.utf8().data(), new_codecs)); - - if (result == WebMediaSource::AddStatusOk) - *source_buffer = new WebSourceBufferImpl(id, demuxer_); - - return result; -} - -double WebMediaSourceImpl::duration() { - return demuxer_->GetDuration(); -} - -void WebMediaSourceImpl::setDuration(double new_duration) { - DCHECK_GE(new_duration, 0); - demuxer_->SetDuration(new_duration); -} - -void WebMediaSourceImpl::markEndOfStream( - WebMediaSource::EndOfStreamStatus status) { - media::PipelineStatus pipeline_status = media::PIPELINE_OK; - - switch (status) { - case WebMediaSource::EndOfStreamStatusNoError: - break; - case WebMediaSource::EndOfStreamStatusNetworkError: - pipeline_status = media::PIPELINE_ERROR_NETWORK; - break; - case WebMediaSource::EndOfStreamStatusDecodeError: - pipeline_status = media::PIPELINE_ERROR_DECODE; - break; - } - - demuxer_->MarkEndOfStream(pipeline_status); -} - -void WebMediaSourceImpl::unmarkEndOfStream() { - demuxer_->UnmarkEndOfStream(); -} - -} // namespace content diff --git a/content/renderer/media/webmediasource_impl.h b/content/renderer/media/webmediasource_impl.h deleted file mode 100644 index c788a66..0000000 --- a/content/renderer/media/webmediasource_impl.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBMEDIASOURCE_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_WEBMEDIASOURCE_IMPL_H_ - -#include <string> -#include <vector> - -#include "media/base/media_log.h" -#include "third_party/WebKit/public/platform/WebMediaSource.h" - -namespace media { -class ChunkDemuxer; -} - -namespace content { - -class WebMediaSourceImpl : public blink::WebMediaSource { - public: - WebMediaSourceImpl(media::ChunkDemuxer* demuxer, media::LogCB log_cb); - virtual ~WebMediaSourceImpl(); - - // blink::WebMediaSource implementation. - virtual AddStatus addSourceBuffer( - const blink::WebString& type, - const blink::WebVector<blink::WebString>& codecs, - blink::WebSourceBuffer** source_buffer); - virtual double duration(); - virtual void setDuration(double duration); - virtual void markEndOfStream(EndOfStreamStatus status); - virtual void unmarkEndOfStream(); - - private: - media::ChunkDemuxer* demuxer_; // Owned by WebMediaPlayerImpl. - media::LogCB log_cb_; - - DISALLOW_COPY_AND_ASSIGN(WebMediaSourceImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBMEDIASOURCE_IMPL_H_ diff --git a/content/renderer/media/websourcebuffer_impl.cc b/content/renderer/media/websourcebuffer_impl.cc deleted file mode 100644 index 1b8e4fa..0000000 --- a/content/renderer/media/websourcebuffer_impl.cc +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/websourcebuffer_impl.h" - -#include <limits> - -#include "base/float_util.h" -#include "media/filters/chunk_demuxer.h" - -namespace content { - -static base::TimeDelta DoubleToTimeDelta(double time) { - DCHECK(!base::IsNaN(time)); - DCHECK_NE(time, -std::numeric_limits<double>::infinity()); - - if (time == std::numeric_limits<double>::infinity()) - return media::kInfiniteDuration(); - - // Don't use base::TimeDelta::Max() here, as we want the largest finite time - // delta. - base::TimeDelta max_time = base::TimeDelta::FromInternalValue(kint64max - 1); - double max_time_in_seconds = max_time.InSecondsF(); - - if (time >= max_time_in_seconds) - return max_time; - - return base::TimeDelta::FromMicroseconds( - time * base::Time::kMicrosecondsPerSecond); -} - -WebSourceBufferImpl::WebSourceBufferImpl( - const std::string& id, media::ChunkDemuxer* demuxer) - : id_(id), - demuxer_(demuxer), - append_window_end_(media::kInfiniteDuration()) { - DCHECK(demuxer_); -} - -WebSourceBufferImpl::~WebSourceBufferImpl() { - DCHECK(!demuxer_) << "Object destroyed w/o removedFromMediaSource() call"; -} - -bool WebSourceBufferImpl::setMode(WebSourceBuffer::AppendMode mode) { - if (demuxer_->IsParsingMediaSegment(id_)) - return false; - - switch (mode) { - case WebSourceBuffer::AppendModeSegments: - demuxer_->SetSequenceMode(id_, false); - return true; - case WebSourceBuffer::AppendModeSequence: - demuxer_->SetSequenceMode(id_, true); - return true; - } - - NOTREACHED(); - return false; -} - -blink::WebTimeRanges WebSourceBufferImpl::buffered() { - media::Ranges<base::TimeDelta> ranges = demuxer_->GetBufferedRanges(id_); - blink::WebTimeRanges result(ranges.size()); - for (size_t i = 0; i < ranges.size(); i++) { - result[i].start = ranges.start(i).InSecondsF(); - result[i].end = ranges.end(i).InSecondsF(); - } - return result; -} - -void WebSourceBufferImpl::append( - const unsigned char* data, - unsigned length, - double* timestamp_offset) { - base::TimeDelta old_offset = timestamp_offset_; - demuxer_->AppendData(id_, data, length, - append_window_start_, append_window_end_, - ×tamp_offset_); - - // Coded frame processing may update the timestamp offset. If the caller - // provides a non-NULL |timestamp_offset| and frame processing changes the - // timestamp offset, report the new offset to the caller. Do not update the - // caller's offset otherwise, to preserve any pre-existing value that may have - // more than microsecond precision. - if (timestamp_offset && old_offset != timestamp_offset_) - *timestamp_offset = timestamp_offset_.InSecondsF(); -} - -void WebSourceBufferImpl::abort() { - demuxer_->Abort(id_, - append_window_start_, append_window_end_, - ×tamp_offset_); - - // TODO(wolenetz): abort should be able to modify the caller timestamp offset - // (just like WebSourceBufferImpl::append). - // See http://crbug.com/370229 for further details. -} - -void WebSourceBufferImpl::remove(double start, double end) { - DCHECK_GE(start, 0); - DCHECK_GE(end, 0); - demuxer_->Remove(id_, DoubleToTimeDelta(start), DoubleToTimeDelta(end)); -} - -bool WebSourceBufferImpl::setTimestampOffset(double offset) { - if (demuxer_->IsParsingMediaSegment(id_)) - return false; - - timestamp_offset_ = DoubleToTimeDelta(offset); - - // http://www.w3.org/TR/media-source/#widl-SourceBuffer-timestampOffset - // Step 6: If the mode attribute equals "sequence", then set the group start - // timestamp to new timestamp offset. - demuxer_->SetGroupStartTimestampIfInSequenceMode(id_, timestamp_offset_); - return true; -} - -void WebSourceBufferImpl::setAppendWindowStart(double start) { - DCHECK_GE(start, 0); - append_window_start_ = DoubleToTimeDelta(start); -} - -void WebSourceBufferImpl::setAppendWindowEnd(double end) { - DCHECK_GE(end, 0); - append_window_end_ = DoubleToTimeDelta(end); -} - -void WebSourceBufferImpl::removedFromMediaSource() { - demuxer_->RemoveId(id_); - demuxer_ = NULL; -} - -} // namespace content diff --git a/content/renderer/media/websourcebuffer_impl.h b/content/renderer/media/websourcebuffer_impl.h deleted file mode 100644 index b0e4fa6..0000000 --- a/content/renderer/media/websourcebuffer_impl.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBSOURCEBUFFER_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_WEBSOURCEBUFFER_IMPL_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/time/time.h" -#include "third_party/WebKit/public/platform/WebSourceBuffer.h" - -namespace media { -class ChunkDemuxer; -} - -namespace content { - -class WebSourceBufferImpl : public blink::WebSourceBuffer { - public: - WebSourceBufferImpl(const std::string& id, media::ChunkDemuxer* demuxer); - virtual ~WebSourceBufferImpl(); - - // blink::WebSourceBuffer implementation. - virtual bool setMode(AppendMode mode); - virtual blink::WebTimeRanges buffered(); - virtual void append( - const unsigned char* data, - unsigned length, - double* timestamp_offset); - virtual void abort(); - virtual void remove(double start, double end); - virtual bool setTimestampOffset(double offset); - virtual void setAppendWindowStart(double start); - virtual void setAppendWindowEnd(double end); - virtual void removedFromMediaSource(); - - private: - std::string id_; - media::ChunkDemuxer* demuxer_; // Owned by WebMediaPlayerImpl. - - // Controls the offset applied to timestamps when processing appended media - // segments. It is initially 0, which indicates that no offset is being - // applied. Both setTimestampOffset() and append() may update this value. - base::TimeDelta timestamp_offset_; - - base::TimeDelta append_window_start_; - base::TimeDelta append_window_end_; - - DISALLOW_COPY_AND_ASSIGN(WebSourceBufferImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBSOURCEBUFFER_IMPL_H_ diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 549004c..e2b1bfa 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -74,9 +74,7 @@ #include "content/renderer/media/render_media_log.h" #include "content/renderer/media/user_media_client_impl.h" #include "content/renderer/media/webcontentdecryptionmodule_impl.h" -#include "content/renderer/media/webmediaplayer_impl.h" #include "content/renderer/media/webmediaplayer_ms.h" -#include "content/renderer/media/webmediaplayer_params.h" #include "content/renderer/notification_permission_dispatcher.h" #include "content/renderer/notification_provider.h" #include "content/renderer/npapi/plugin_channel_host.h" @@ -93,6 +91,8 @@ #include "content/renderer/v8_value_converter_impl.h" #include "content/renderer/websharedworker_proxy.h" #include "media/base/audio_renderer_mixer_input.h" +#include "media/blink/webmediaplayer_impl.h" +#include "media/blink/webmediaplayer_params.h" #include "media/filters/gpu_video_accelerator_factories.h" #include "net/base/data_url.h" #include "net/base/net_errors.h" @@ -1602,7 +1602,7 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer( return CreateAndroidWebMediaPlayer(url, client); #else RenderThreadImpl* render_thread = RenderThreadImpl::current(); - WebMediaPlayerParams params( + media::WebMediaPlayerParams params( base::Bind(&ContentRendererClient::DeferMediaLoad, base::Unretained(GetContentClient()->renderer()), static_cast<RenderFrame*>(this)), @@ -1614,8 +1614,10 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer( render_thread->GetMediaThreadTaskRunner(), render_thread->compositor_message_loop_proxy(), base::Bind(&EncryptedMediaPlayerSupportImpl::Create)); - return new WebMediaPlayerImpl(frame, client, weak_factory_.GetWeakPtr(), - params); + return new media::WebMediaPlayerImpl(frame, + client, + weak_factory_.GetWeakPtr(), + params); #endif // defined(OS_ANDROID) } diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 31f05cc..d8cdfc38 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h @@ -19,10 +19,10 @@ #include "content/public/common/javascript_message_type.h" #include "content/public/common/referrer.h" #include "content/public/renderer/render_frame.h" -#include "content/renderer/media/webmediaplayer_delegate.h" #include "content/renderer/render_frame_proxy.h" #include "content/renderer/renderer_webcookiejar_impl.h" #include "ipc/ipc_message.h" +#include "media/blink/webmediaplayer_delegate.h" #include "third_party/WebKit/public/web/WebAXObject.h" #include "third_party/WebKit/public/web/WebDataSource.h" #include "third_party/WebKit/public/web/WebFrameClient.h" @@ -83,7 +83,7 @@ struct CustomContextMenuContext; class CONTENT_EXPORT RenderFrameImpl : public RenderFrame, NON_EXPORTED_BASE(public blink::WebFrameClient), - NON_EXPORTED_BASE(public WebMediaPlayerDelegate) { + NON_EXPORTED_BASE(public media::WebMediaPlayerDelegate) { public: // Creates a new RenderFrame. |render_view| is the RenderView object that this // frame belongs to. |