summaryrefslogtreecommitdiffstats
path: root/webkit/glue/media/buffered_data_source.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/glue/media/buffered_data_source.cc')
-rw-r--r--webkit/glue/media/buffered_data_source.cc102
1 files changed, 35 insertions, 67 deletions
diff --git a/webkit/glue/media/buffered_data_source.cc b/webkit/glue/media/buffered_data_source.cc
index 36e43d0..6efaa8c 100644
--- a/webkit/glue/media/buffered_data_source.cc
+++ b/webkit/glue/media/buffered_data_source.cc
@@ -72,6 +72,7 @@ BufferedResourceLoader::BufferedResourceLoader(
deferred_(false),
completed_(false),
range_requested_(false),
+ partial_response_(false),
bridge_factory_(bridge_factory),
url_(url),
first_byte_position_(first_byte_position),
@@ -235,14 +236,19 @@ void BufferedResourceLoader::OnReceivedResponse(
// We expect to receive headers because this is a HTTP or HTTPS protocol,
// if not report failure.
error = net::ERR_INVALID_RESPONSE;
- } else if (range_requested_) {
- // If we have verified the partial response and it is correct, we will
- // return net::OK.
- if (!VerifyPartialResponse(info))
- error = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
- } else if (info.headers->response_code() != kHttpOK) {
- // We didn't request a range but server didn't reply with "200 OK".
- error = net::ERR_FAILED;
+ } else {
+ if (info.headers->response_code() == kHttpPartialContent)
+ partial_response_ = true;
+
+ if (range_requested_ && partial_response_) {
+ // If we have verified the partial response and it is correct, we will
+ // return net::OK.
+ if (!VerifyPartialResponse(info))
+ error = net::ERR_INVALID_RESPONSE;
+ } else if (info.headers->response_code() != kHttpOK) {
+ // We didn't request a range but server didn't reply with "200 OK".
+ error = net::ERR_FAILED;
+ }
}
if (error != net::OK) {
@@ -250,6 +256,10 @@ void BufferedResourceLoader::OnReceivedResponse(
Stop();
return;
}
+ } else {
+ // For any protocol other than HTTP and HTTPS, assume range request is
+ // always fulfilled.
+ partial_response_ = range_requested_;
}
// |info.content_length| can be -1, in that case |content_length_| is
@@ -258,7 +268,7 @@ void BufferedResourceLoader::OnReceivedResponse(
// If we have not requested a range, then the size of the instance is equal
// to the content length.
- if (!range_requested_)
+ if (!partial_response_)
instance_size_ = content_length_;
// Calls with a successful response.
@@ -418,9 +428,6 @@ void BufferedResourceLoader::DoneStart(int error) {
bool BufferedResourceLoader::VerifyPartialResponse(
const ResourceLoaderBridge::ResponseInfo& info) {
- if (info.headers->response_code() != kHttpPartialContent)
- return false;
-
int64 first_byte_position, last_byte_position, instance_size;
if (!info.headers->GetContentRange(&first_byte_position,
&last_byte_position,
@@ -455,8 +462,6 @@ BufferedDataSource::BufferedDataSource(
read_position_(0),
read_size_(0),
read_buffer_(NULL),
- initial_response_received_(false),
- probe_response_received_(false),
intermediate_read_buffer_(new uint8[kInitialReadBufferSize]),
intermediate_read_buffer_size_(kInitialReadBufferSize),
render_loop_(render_loop),
@@ -551,7 +556,6 @@ bool BufferedDataSource::IsStreaming() {
void BufferedDataSource::InitializeTask() {
DCHECK(MessageLoop::current() == render_loop_);
DCHECK(!loader_.get());
- DCHECK(!probe_loader_.get());
// Kick starts the watch dog task that will handle connection timeout.
// We run the watch dog 2 times faster the actual timeout so as to catch
@@ -561,18 +565,13 @@ void BufferedDataSource::InitializeTask() {
this,
&BufferedDataSource::WatchDogTask);
- // Creates a new resource loader with the full range and a probe resource
- // loader. Creates a probe resource loader to make sure the server supports
- // partial range request.
- // TODO(hclam): Only request 1 byte for this probe request, it may be useful
- // that we perform a suffix range request and fetch the index. That way we
- // can minimize the number of requests made.
- loader_ = CreateLoader(-1, -1);
- probe_loader_ = CreateLoader(1, 1);
-
+ // Fetch only first 1024 bytes as this usually covers the header portion
+ // of a media file that gives enough information about the codecs, etc.
+ // This also serve as a probe to determine server capability to serve
+ // range request.
+ // TODO(hclam): Do some experiments for the best approach.
+ loader_ = CreateLoader(0, 1024);
loader_->Start(NewCallback(this, &BufferedDataSource::InitialStartCallback));
- probe_loader_->Start(
- NewCallback(this, &BufferedDataSource::ProbeStartCallback));
}
void BufferedDataSource::ReadTask(
@@ -612,10 +611,6 @@ void BufferedDataSource::StopTask() {
if (loader_.get())
loader_->Stop();
- // If the probe request is still active, stop it too.
- if (probe_loader_.get())
- probe_loader_->Stop();
-
// Reset the parameters of the current read request.
read_callback_.reset();
read_position_ = 0;
@@ -731,21 +726,21 @@ void BufferedDataSource::InitialStartCallback(int error) {
// TODO(hclam): In case of failure, we can retry several times.
host()->SetError(media::PIPELINE_ERROR_NETWORK);
DCHECK(loader_.get());
- DCHECK(probe_loader_.get());
loader_->Stop();
- probe_loader_->Stop();
DoneInitialization();
return;
}
+ // TODO(hclam): Needs more thinking about supporting servers without range
+ // request or their partial response is not complete.
total_bytes_ = loader_->instance_size();
- if (total_bytes_ >= 0) {
+ if (total_bytes_ >= 0 && loader_->partial_response()) {
// This value governs the range that we can seek to.
// TODO(hclam): Report the correct value of buffered bytes.
host()->SetTotalBytes(total_bytes_);
host()->SetBufferedBytes(total_bytes_);
} else {
- // If the server didn't reply with a content length, it is likely this
+ // If the server didn't reply with an instance size, it is likely this
// is a streaming response.
streaming_ = true;
host()->SetStreaming(true);
@@ -753,45 +748,18 @@ void BufferedDataSource::InitialStartCallback(int error) {
// Currently, only files can be used reliably w/o a network.
host()->SetLoaded(url_.SchemeIsFile());
-
- initial_response_received_ = true;
- if (probe_response_received_)
- DoneInitialization();
-}
-
-void BufferedDataSource::ProbeStartCallback(int error) {
- DCHECK(MessageLoop::current() == render_loop_);
-
- // We need to prevent calling to filter host and running the callback if
- // we have received the stop signal. We need to lock down the whole callback
- // method to prevent bad things from happening. The reason behind this is
- // that we cannot guarantee tasks on render thread have completely stopped
- // when we receive the Stop() method call. The only way to solve this is to
- // let tasks on render thread to run but make sure they don't call outside
- // this object when Stop() method is ever called. Locking this method is safe
- // because |lock_| is only acquired in tasks on render thread.
- AutoLock auto_lock(lock_);
- if (stopped_)
- return;
-
- if (error != net::OK) {
- streaming_ = true;
- host()->SetStreaming(true);
- }
-
- DCHECK(probe_loader_.get());
- probe_loader_->Stop();
- probe_response_received_ = true;
- if (initial_response_received_)
- DoneInitialization();
+ DoneInitialization();
}
void BufferedDataSource::PartialReadStartCallback(int error) {
DCHECK(MessageLoop::current() == render_loop_);
DCHECK(loader_.get());
- if (error == net::OK) {
- // Once the range request has start successfully, we can proceed with
+ // This callback method is invoked after we have verified the server has
+ // range request capability, so as a safety guard verify again the response
+ // is partial.
+ if (error == net::OK && loader_->partial_response()) {
+ // Once the range request has started successfully, we can proceed with
// reading from it.
ReadInternal();
} else {