1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/blink/buffered_data_source.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/single_thread_task_runner.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_log.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebFrame;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BufferedDataSource has an intermediate buffer, this value governs the initial
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// size of that buffer. It is set to 32KB because this is a typical read size
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of FFmpeg.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInitialReadBufferSize = 32768;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Number of cache misses we allow for a single Read() before signaling an
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// error.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNumCacheMissRetries = 3;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace media {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class BufferedDataSource::ReadOperation {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReadOperation(int64 position, int size, uint8* data,
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                const DataSource::ReadCB& callback);
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~ReadOperation();
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Runs |callback_| with the given |result|, deleting the operation
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // afterwards.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void Run(scoped_ptr<ReadOperation> read_op, int result);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // State for the number of times this read operation has been retried.
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int retries() { return retries_; }
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void IncrementRetries() { ++retries_; }
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 position() { return position_; }
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int size() { return size_; }
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8* data() { return data_; }
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int retries_;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int64 position_;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int size_;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8* data_;
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DataSource::ReadCB callback_;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(ReadOperation);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BufferedDataSource::ReadOperation::ReadOperation(
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 position, int size, uint8* data,
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DataSource::ReadCB& callback)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : retries_(0),
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      position_(position),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      size_(size),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      data_(data),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_(callback) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback_.is_null());
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BufferedDataSource::ReadOperation::~ReadOperation() {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(callback_.is_null());
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferedDataSource::ReadOperation::Run(
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<ReadOperation> read_op, int result) {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ResetAndReturn(&read_op->callback_).Run(result);
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferedDataSource::BufferedDataSource(
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const GURL& url,
8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    BufferedResourceLoader::CORSMode cors_mode,
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebFrame* frame,
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    MediaLog* media_log,
86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    BufferedDataSourceHost* host,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DownloadingCB& downloading_cb)
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : url_(url),
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      cors_mode_(cors_mode),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      total_bytes_(kPositionNotSpecified),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      streaming_(false),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame_(frame),
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      intermediate_read_buffer_(kInitialReadBufferSize),
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      render_task_runner_(task_runner),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stop_signal_received_(false),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      media_has_played_(false),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      preload_(AUTO),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bitrate_(0),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      playback_rate_(0.0),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      media_log_(media_log),
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      host_(host),
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      downloading_cb_(downloading_cb),
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      weak_factory_(this) {
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(host_);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!downloading_cb_.is_null());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferedDataSource::~BufferedDataSource() {}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A factory method to create BufferedResourceLoader using the read parameters.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method can be overridden to inject mock BufferedResourceLoader object
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for testing purpose.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferedResourceLoader* BufferedDataSource::CreateResourceLoader(
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 first_byte_position, int64 last_byte_position) {
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BufferedResourceLoader::DeferStrategy strategy = preload_ == METADATA ?
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BufferedResourceLoader::kReadThenDefer :
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BufferedResourceLoader::kCapacityDefer;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new BufferedResourceLoader(url_,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    cors_mode_,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    first_byte_position,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    last_byte_position,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    strategy,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bitrate_,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    playback_rate_,
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    media_log_.get());
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BufferedDataSource::Initialize(const InitializeCB& init_cb) {
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!init_cb.is_null());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!loader_.get());
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_cb_ = init_cb;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (url_.SchemeIsHTTPOrHTTPS()) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do an unbounded range request starting at the beginning.  If the server
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // responds with 200 instead of 206 we'll fall back into a streaming mode.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loader_.reset(CreateResourceLoader(0, kPositionNotSpecified));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For all other protocols, assume they support range request. We fetch
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the full range of the resource to obtain the instance size because
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we won't be served HTTP headers.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loader_.reset(CreateResourceLoader(kPositionNotSpecified,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       kPositionNotSpecified));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::WeakPtr<BufferedDataSource> weak_this = weak_factory_.GetWeakPtr();
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loader_->Start(
15223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::Bind(&BufferedDataSource::StartCallback, weak_this),
15323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::Bind(&BufferedDataSource::LoadingStateChangedCallback, weak_this),
15423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::Bind(&BufferedDataSource::ProgressCallback, weak_this),
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame_);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::SetPreload(Preload preload) {
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  preload_ = preload;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedDataSource::HasSingleOrigin() {
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(init_cb_.is_null() && loader_.get())
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Initialize() must complete before calling HasSingleOrigin()";
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return loader_->HasSingleOrigin();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedDataSource::DidPassCORSAccessCheck() const {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return loader_.get() && loader_->DidPassCORSAccessCheck();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::Abort() {
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoLock auto_lock(lock_);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StopInternal_Locked();
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StopLoader();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame_ = NULL;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void BufferedDataSource::MediaPlaybackRateChanged(float playback_rate) {
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(loader_.get());
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (playback_rate < 0.0f)
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  playback_rate_ = playback_rate;
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  loader_->SetPlaybackRate(playback_rate);
1938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void BufferedDataSource::MediaIsPlaying() {
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  media_has_played_ = true;
1988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  UpdateDeferStrategy(false);
1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void BufferedDataSource::MediaIsPaused() {
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
2038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  UpdateDeferStrategy(true);
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// DataSource implementation.
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void BufferedDataSource::Stop() {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StopInternal_Locked();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_task_runner_->PostTask(
21523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      FROM_HERE,
21623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::Bind(&BufferedDataSource::StopLoader, weak_factory_.GetWeakPtr()));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::SetBitrate(int bitrate) {
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_task_runner_->PostTask(FROM_HERE,
22123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                         base::Bind(&BufferedDataSource::SetBitrateTask,
22223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                    weak_factory_.GetWeakPtr(),
22323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                    bitrate));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::Read(
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 position, int size, uint8* data,
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DataSource::ReadCB& read_cb) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Read: " << position << " offset, " << size << " bytes";
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!read_cb.is_null());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!read_op_);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (stop_signal_received_) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_cb.Run(kReadError);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    read_op_.reset(new ReadOperation(position, size, data, read_cb));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  render_task_runner_->PostTask(
24523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      FROM_HERE,
24623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::Bind(&BufferedDataSource::ReadTask, weak_factory_.GetWeakPtr()));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedDataSource::GetSize(int64* size_out) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (total_bytes_ != kPositionNotSpecified) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *size_out = total_bytes_;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *size_out = 0;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedDataSource::IsStreaming() {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return streaming_;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Render thread tasks.
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferedDataSource::ReadTask() {
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadInternal();
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferedDataSource::StopInternal_Locked() {
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  lock_.AssertAcquired();
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (stop_signal_received_)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stop_signal_received_ = true;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initialize() isn't part of the DataSource interface so don't call it in
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // response to Stop().
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  init_cb_.Reset();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (read_op_)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ReadOperation::Run(read_op_.Pass(), kReadError);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BufferedDataSource::StopLoader() {
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (loader_)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loader_->Stop();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::SetBitrateTask(int bitrate) {
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loader_.get());
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitrate_ = bitrate;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loader_->SetBitrate(bitrate);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is the place where actual read happens, |loader_| must be valid
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prior to make this method call.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::ReadInternal() {
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 position = 0;
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int size = 0;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoLock auto_lock(lock_);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (stop_signal_received_)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    position = read_op_->position();
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size = read_op_->size();
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First we prepare the intermediate read buffer for BufferedResourceLoader
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to write to.
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (static_cast<int>(intermediate_read_buffer_.size()) < size)
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    intermediate_read_buffer_.resize(size);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Perform the actual read with BufferedResourceLoader.
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!intermediate_read_buffer_.empty());
32123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  loader_->Read(position,
32223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                size,
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                &intermediate_read_buffer_[0],
32423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                base::Bind(&BufferedDataSource::ReadCallback,
32523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                           weak_factory_.GetWeakPtr()));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BufferedResourceLoader callback methods.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::StartCallback(
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BufferedResourceLoader::Status status) {
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loader_.get());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool init_cb_is_null = false;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    init_cb_is_null = init_cb_.is_null();
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (init_cb_is_null) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loader_->Stop();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All responses must be successful. Resources that are assumed to be fully
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // buffered must have a known content length.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = status == BufferedResourceLoader::kOk &&
34946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 (!assume_fully_buffered() ||
35046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                  loader_->instance_size() != kPositionNotSpecified);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_bytes_ = loader_->instance_size();
35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    streaming_ =
35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        !assume_fully_buffered() &&
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (total_bytes_ == kPositionNotSpecified || !loader_->range_supported());
35758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    media_log_->SetDoubleProperty("total_bytes",
35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  static_cast<double>(total_bytes_));
36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    media_log_->SetBooleanProperty("streaming", streaming_);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loader_->Stop();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(scherkus): we shouldn't have to lock to signal host(), see
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/113712 for details.
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (stop_signal_received_)
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (success) {
372c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (total_bytes_ != kPositionNotSpecified) {
373c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      host_->SetTotalBytes(total_bytes_);
37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (assume_fully_buffered())
375c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        host_->AddBufferedByteRange(0, total_bytes_);
376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    media_log_->SetBooleanProperty("single_origin", loader_->HasSingleOrigin());
37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    media_log_->SetBooleanProperty("passed_cors_access_check",
38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   loader_->DidPassCORSAccessCheck());
38158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    media_log_->SetBooleanProperty("range_header_supported",
38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                   loader_->range_supported());
38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ResetAndReturn(&init_cb_).Run(success);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::PartialReadStartCallback(
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BufferedResourceLoader::Status status) {
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loader_.get());
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status == BufferedResourceLoader::kOk) {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Once the request has started successfully, we can proceed with
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // reading from it.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadInternal();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop the resource loader since we have received an error.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loader_->Stop();
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(scherkus): we shouldn't have to lock to signal host(), see
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/113712 for details.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stop_signal_received_)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReadOperation::Run(read_op_.Pass(), kReadError);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::ReadCallback(
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BufferedResourceLoader::Status status,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int bytes_read) {
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(scherkus): we shouldn't have to lock to signal host(), see
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // http://crbug.com/113712 for details.
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (stop_signal_received_)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status != BufferedResourceLoader::kOk) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Stop the resource load if it failed.
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    loader_->Stop();
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (status == BufferedResourceLoader::kCacheMiss &&
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        read_op_->retries() < kNumCacheMissRetries) {
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      read_op_->IncrementRetries();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Recreate a loader starting from where we last left off until the
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // end of the resource.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loader_.reset(CreateResourceLoader(
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          read_op_->position(), kPositionNotSpecified));
43423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
43523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      base::WeakPtr<BufferedDataSource> weak_this = weak_factory_.GetWeakPtr();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loader_->Start(
43723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          base::Bind(&BufferedDataSource::PartialReadStartCallback, weak_this),
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&BufferedDataSource::LoadingStateChangedCallback,
43923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                     weak_this),
44023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          base::Bind(&BufferedDataSource::ProgressCallback, weak_this),
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          frame_);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ReadOperation::Run(read_op_.Pass(), kReadError);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bytes_read > 0) {
4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(!intermediate_read_buffer_.empty());
4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    memcpy(read_op_->data(), &intermediate_read_buffer_[0], bytes_read);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We've reached the end of the file and we didn't know the total size
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before. Update the total size so Read()s past the end of the file will
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // fail like they would if we had known the file size at the beginning.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total_bytes_ = loader_->instance_size();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
458c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (total_bytes_ != kPositionNotSpecified) {
459c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      host_->SetTotalBytes(total_bytes_);
460c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      host_->AddBufferedByteRange(loader_->first_byte_position(),
461c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                  total_bytes_);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReadOperation::Run(read_op_.Pass(), bytes_read);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::LoadingStateChangedCallback(
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BufferedResourceLoader::LoadingState state) {
4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (assume_fully_buffered())
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_downloading_data;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BufferedResourceLoader::kLoading:
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_downloading_data = true;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BufferedResourceLoader::kLoadingDeferred:
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BufferedResourceLoader::kLoadingFinished:
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_downloading_data = false;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(scherkus): we don't signal network activity changes when loads
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // fail to preserve existing behaviour when deferring is toggled, however
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we should consider changing DownloadingCB to also propagate loading
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // state. For example there isn't any signal today to notify the client that
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // loading has failed (we only get errors on subsequent reads).
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BufferedResourceLoader::kLoadingFailed:
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  downloading_cb_.Run(is_downloading_data);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedDataSource::ProgressCallback(int64 position) {
4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(render_task_runner_->BelongsToCurrentThread());
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (assume_fully_buffered())
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(scherkus): we shouldn't have to lock to signal host(), see
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://crbug.com/113712 for details.
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (stop_signal_received_)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
508c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  host_->AddBufferedByteRange(loader_->first_byte_position(), position);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void BufferedDataSource::UpdateDeferStrategy(bool paused) {
512f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // No need to aggressively buffer when we are assuming the resource is fully
513f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // buffered.
514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (assume_fully_buffered()) {
5158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
5168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
5178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // If the playback has started (at which point the preload value is ignored)
5208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // and we're paused, then try to load as much as possible (the loader will
5218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // fall back to kCapacityDefer if it knows the current response won't be
5228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // useful from the cache in the future).
523f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (media_has_played_ && paused && loader_->range_supported()) {
5248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer);
5258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
5268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If media is currently playing or the page indicated preload=auto or the
529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // the server does not support the byte range request or we do not want to go
530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // too far ahead of the read head, use threshold strategy to enable/disable
531f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // deferring when the buffer is full/depleted.
5328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
5338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace media
536