#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "content/public/common/url_constants.h"
#include "media/base/media_log.h"
#include "net/base/net_errors.h"
-using WebKit::WebFrame;
+using blink::WebFrame;
namespace {
}
BufferedDataSource::BufferedDataSource(
+ const GURL& url,
+ BufferedResourceLoader::CORSMode cors_mode,
const scoped_refptr<base::MessageLoopProxy>& render_loop,
WebFrame* frame,
media::MediaLog* media_log,
+ BufferedDataSourceHost* host,
const DownloadingCB& downloading_cb)
- : weak_factory_(this),
- weak_this_(weak_factory_.GetWeakPtr()),
- cors_mode_(BufferedResourceLoader::kUnspecified),
+ : url_(url),
+ cors_mode_(cors_mode),
total_bytes_(kPositionNotSpecified),
- assume_fully_buffered_(false),
streaming_(false),
frame_(frame),
intermediate_read_buffer_(new uint8[kInitialReadBufferSize]),
bitrate_(0),
playback_rate_(0.0),
media_log_(media_log),
- downloading_cb_(downloading_cb) {
+ host_(host),
+ downloading_cb_(downloading_cb),
+ weak_factory_(this) {
+ DCHECK(host_);
DCHECK(!downloading_cb_.is_null());
}
media_log_.get());
}
-void BufferedDataSource::set_host(media::DataSourceHost* host) {
- DataSource::set_host(host);
-
- if (loader_) {
- base::AutoLock auto_lock(lock_);
- UpdateHostState_Locked();
- }
-}
-
-void BufferedDataSource::Initialize(
- const GURL& url,
- BufferedResourceLoader::CORSMode cors_mode,
- const InitializeCB& init_cb) {
+void BufferedDataSource::Initialize(const InitializeCB& init_cb) {
DCHECK(render_loop_->BelongsToCurrentThread());
DCHECK(!init_cb.is_null());
DCHECK(!loader_.get());
- url_ = url;
- cors_mode_ = cors_mode;
init_cb_ = init_cb;
- if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) {
+ 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));
// we won't be served HTTP headers.
loader_.reset(CreateResourceLoader(kPositionNotSpecified,
kPositionNotSpecified));
- assume_fully_buffered_ = true;
}
+ 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_),
+ base::Bind(&BufferedDataSource::StartCallback, weak_this),
+ base::Bind(&BufferedDataSource::LoadingStateChangedCallback, weak_this),
+ base::Bind(&BufferedDataSource::ProgressCallback, weak_this),
frame_);
}
/////////////////////////////////////////////////////////////////////////////
// media::DataSource implementation.
-void BufferedDataSource::Stop(const base::Closure& closure) {
+void BufferedDataSource::Stop() {
{
base::AutoLock auto_lock(lock_);
StopInternal_Locked();
}
- closure.Run();
- render_loop_->PostTask(FROM_HERE,
- base::Bind(&BufferedDataSource::StopLoader, weak_this_));
+ render_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&BufferedDataSource::StopLoader, weak_factory_.GetWeakPtr()));
}
void BufferedDataSource::SetBitrate(int bitrate) {
- render_loop_->PostTask(FROM_HERE, base::Bind(
- &BufferedDataSource::SetBitrateTask, weak_this_, bitrate));
+ render_loop_->PostTask(FROM_HERE,
+ base::Bind(&BufferedDataSource::SetBitrateTask,
+ weak_factory_.GetWeakPtr(),
+ bitrate));
}
void BufferedDataSource::Read(
read_op_.reset(new ReadOperation(position, size, data, read_cb));
}
- render_loop_->PostTask(FROM_HERE, base::Bind(
- &BufferedDataSource::ReadTask, weak_this_));
+ render_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&BufferedDataSource::ReadTask, weak_factory_.GetWeakPtr()));
}
bool BufferedDataSource::GetSize(int64* size_out) {
}
// Perform the actual read with BufferedResourceLoader.
- loader_->Read(
- position, size, intermediate_read_buffer_.get(),
- base::Bind(&BufferedDataSource::ReadCallback, weak_this_));
+ loader_->Read(position,
+ size,
+ intermediate_read_buffer_.get(),
+ base::Bind(&BufferedDataSource::ReadCallback,
+ weak_factory_.GetWeakPtr()));
}
// 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);
+ (!assume_fully_buffered() ||
+ loader_->instance_size() != kPositionNotSpecified);
if (success) {
total_bytes_ = loader_->instance_size();
- streaming_ = !assume_fully_buffered_ &&
+ streaming_ =
+ !assume_fully_buffered() &&
(total_bytes_ == kPositionNotSpecified || !loader_->range_supported());
media_log_->SetDoubleProperty("total_bytes",
return;
if (success) {
- UpdateHostState_Locked();
+ 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());
// 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::PartialReadStartCallback, weak_this),
base::Bind(&BufferedDataSource::LoadingStateChangedCallback,
- weak_this_),
- base::Bind(&BufferedDataSource::ProgressCallback, weak_this_),
+ weak_this),
+ base::Bind(&BufferedDataSource::ProgressCallback, weak_this),
frame_);
return;
}
// fail like they would if we had known the file size at the beginning.
total_bytes_ = loader_->instance_size();
- if (host() && total_bytes_ != kPositionNotSpecified) {
- host()->SetTotalBytes(total_bytes_);
- host()->AddBufferedByteRange(loader_->first_byte_position(),
- total_bytes_);
+ if (total_bytes_ != kPositionNotSpecified) {
+ host_->SetTotalBytes(total_bytes_);
+ host_->AddBufferedByteRange(loader_->first_byte_position(),
+ total_bytes_);
}
}
ReadOperation::Run(read_op_.Pass(), bytes_read);
BufferedResourceLoader::LoadingState state) {
DCHECK(render_loop_->BelongsToCurrentThread());
- if (assume_fully_buffered_)
+ if (assume_fully_buffered())
return;
bool is_downloading_data;
void BufferedDataSource::ProgressCallback(int64 position) {
DCHECK(render_loop_->BelongsToCurrentThread());
- if (assume_fully_buffered_)
+ if (assume_fully_buffered())
return;
// TODO(scherkus): we shouldn't have to lock to signal host(), see
if (stop_signal_received_)
return;
- ReportOrQueueBufferedBytes(loader_->first_byte_position(), position);
-}
-
-void BufferedDataSource::ReportOrQueueBufferedBytes(int64 start, int64 end) {
- if (host())
- host()->AddBufferedByteRange(start, end);
- else
- queued_buffered_byte_ranges_.Add(start, end);
-}
-
-void BufferedDataSource::UpdateHostState_Locked() {
- lock_.AssertAcquired();
-
- if (!host())
- return;
-
- for (size_t i = 0; i < queued_buffered_byte_ranges_.size(); ++i) {
- host()->AddBufferedByteRange(queued_buffered_byte_ranges_.start(i),
- queued_buffered_byte_ranges_.end(i));
- }
- queued_buffered_byte_ranges_.clear();
-
- if (total_bytes_ == kPositionNotSpecified)
- return;
-
- host()->SetTotalBytes(total_bytes_);
-
- if (assume_fully_buffered_)
- host()->AddBufferedByteRange(0, total_bytes_);
+ host_->AddBufferedByteRange(loader_->first_byte_position(), position);
}
void BufferedDataSource::UpdateDeferStrategy(bool paused) {
- // 200 responses end up not being reused to satisfy future range requests,
- // and we don't want to get too far ahead of the read-head (and thus require
- // a restart), so keep to the thresholds.
- if (!loader_->range_supported()) {
+ // No need to aggressively buffer when we are assuming the resource is fully
+ // buffered.
+ if (assume_fully_buffered()) {
loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
return;
}
// 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) {
+ if (media_has_played_ && paused && loader_->range_supported()) {
loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer);
return;
}
- // If media is currently playing or the page indicated preload=auto,
- // use threshold strategy to enable/disable deferring when the buffer
- // is full/depleted.
+ // 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);
}