diff options
Diffstat (limited to 'webkit/glue/media/buffered_data_source.cc')
-rw-r--r-- | webkit/glue/media/buffered_data_source.cc | 102 |
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 { |