| OLD | NEW | 
 | (Empty) | 
|    1 // Copyright 2013 The Chromium Authors. All rights reserved. |  | 
|    2 // Use of this source code is governed by a BSD-style license that can be |  | 
|    3 // found in the LICENSE file. |  | 
|    4  |  | 
|    5 #include "content/renderer/media/buffered_data_source.h" |  | 
|    6  |  | 
|    7 #include "base/bind.h" |  | 
|    8 #include "base/callback_helpers.h" |  | 
|    9 #include "base/single_thread_task_runner.h" |  | 
|   10 #include "content/public/common/url_constants.h" |  | 
|   11 #include "media/base/media_log.h" |  | 
|   12 #include "net/base/net_errors.h" |  | 
|   13  |  | 
|   14 using blink::WebFrame; |  | 
|   15  |  | 
|   16 namespace { |  | 
|   17  |  | 
|   18 // BufferedDataSource has an intermediate buffer, this value governs the initial |  | 
|   19 // size of that buffer. It is set to 32KB because this is a typical read size |  | 
|   20 // of FFmpeg. |  | 
|   21 const int kInitialReadBufferSize = 32768; |  | 
|   22  |  | 
|   23 // Number of cache misses we allow for a single Read() before signaling an |  | 
|   24 // error. |  | 
|   25 const int kNumCacheMissRetries = 3; |  | 
|   26  |  | 
|   27 }  // namespace |  | 
|   28  |  | 
|   29 namespace content { |  | 
|   30  |  | 
|   31 class BufferedDataSource::ReadOperation { |  | 
|   32  public: |  | 
|   33   ReadOperation(int64 position, int size, uint8* data, |  | 
|   34                 const media::DataSource::ReadCB& callback); |  | 
|   35   ~ReadOperation(); |  | 
|   36  |  | 
|   37   // Runs |callback_| with the given |result|, deleting the operation |  | 
|   38   // afterwards. |  | 
|   39   static void Run(scoped_ptr<ReadOperation> read_op, int result); |  | 
|   40  |  | 
|   41   // State for the number of times this read operation has been retried. |  | 
|   42   int retries() { return retries_; } |  | 
|   43   void IncrementRetries() { ++retries_; } |  | 
|   44  |  | 
|   45   int64 position() { return position_; } |  | 
|   46   int size() { return size_; } |  | 
|   47   uint8* data() { return data_; } |  | 
|   48  |  | 
|   49  private: |  | 
|   50   int retries_; |  | 
|   51  |  | 
|   52   const int64 position_; |  | 
|   53   const int size_; |  | 
|   54   uint8* data_; |  | 
|   55   media::DataSource::ReadCB callback_; |  | 
|   56  |  | 
|   57   DISALLOW_IMPLICIT_CONSTRUCTORS(ReadOperation); |  | 
|   58 }; |  | 
|   59  |  | 
|   60 BufferedDataSource::ReadOperation::ReadOperation( |  | 
|   61     int64 position, int size, uint8* data, |  | 
|   62     const media::DataSource::ReadCB& callback) |  | 
|   63     : retries_(0), |  | 
|   64       position_(position), |  | 
|   65       size_(size), |  | 
|   66       data_(data), |  | 
|   67       callback_(callback) { |  | 
|   68   DCHECK(!callback_.is_null()); |  | 
|   69 } |  | 
|   70  |  | 
|   71 BufferedDataSource::ReadOperation::~ReadOperation() { |  | 
|   72   DCHECK(callback_.is_null()); |  | 
|   73 } |  | 
|   74  |  | 
|   75 // static |  | 
|   76 void BufferedDataSource::ReadOperation::Run( |  | 
|   77     scoped_ptr<ReadOperation> read_op, int result) { |  | 
|   78   base::ResetAndReturn(&read_op->callback_).Run(result); |  | 
|   79 } |  | 
|   80  |  | 
|   81 BufferedDataSource::BufferedDataSource( |  | 
|   82     const GURL& url, |  | 
|   83     BufferedResourceLoader::CORSMode cors_mode, |  | 
|   84     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |  | 
|   85     WebFrame* frame, |  | 
|   86     media::MediaLog* media_log, |  | 
|   87     BufferedDataSourceHost* host, |  | 
|   88     const DownloadingCB& downloading_cb) |  | 
|   89     : url_(url), |  | 
|   90       cors_mode_(cors_mode), |  | 
|   91       total_bytes_(kPositionNotSpecified), |  | 
|   92       streaming_(false), |  | 
|   93       frame_(frame), |  | 
|   94       intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), |  | 
|   95       intermediate_read_buffer_size_(kInitialReadBufferSize), |  | 
|   96       render_task_runner_(task_runner), |  | 
|   97       stop_signal_received_(false), |  | 
|   98       media_has_played_(false), |  | 
|   99       preload_(AUTO), |  | 
|  100       bitrate_(0), |  | 
|  101       playback_rate_(0.0), |  | 
|  102       media_log_(media_log), |  | 
|  103       host_(host), |  | 
|  104       downloading_cb_(downloading_cb), |  | 
|  105       weak_factory_(this) { |  | 
|  106   DCHECK(host_); |  | 
|  107   DCHECK(!downloading_cb_.is_null()); |  | 
|  108 } |  | 
|  109  |  | 
|  110 BufferedDataSource::~BufferedDataSource() {} |  | 
|  111  |  | 
|  112 // A factory method to create BufferedResourceLoader using the read parameters. |  | 
|  113 // This method can be overridden to inject mock BufferedResourceLoader object |  | 
|  114 // for testing purpose. |  | 
|  115 BufferedResourceLoader* BufferedDataSource::CreateResourceLoader( |  | 
|  116     int64 first_byte_position, int64 last_byte_position) { |  | 
|  117   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  118  |  | 
|  119   BufferedResourceLoader::DeferStrategy strategy = preload_ == METADATA ? |  | 
|  120       BufferedResourceLoader::kReadThenDefer : |  | 
|  121       BufferedResourceLoader::kCapacityDefer; |  | 
|  122  |  | 
|  123   return new BufferedResourceLoader(url_, |  | 
|  124                                     cors_mode_, |  | 
|  125                                     first_byte_position, |  | 
|  126                                     last_byte_position, |  | 
|  127                                     strategy, |  | 
|  128                                     bitrate_, |  | 
|  129                                     playback_rate_, |  | 
|  130                                     media_log_.get()); |  | 
|  131 } |  | 
|  132  |  | 
|  133 void BufferedDataSource::Initialize(const InitializeCB& init_cb) { |  | 
|  134   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  135   DCHECK(!init_cb.is_null()); |  | 
|  136   DCHECK(!loader_.get()); |  | 
|  137  |  | 
|  138   init_cb_ = init_cb; |  | 
|  139  |  | 
|  140   if (url_.SchemeIsHTTPOrHTTPS()) { |  | 
|  141     // Do an unbounded range request starting at the beginning.  If the server |  | 
|  142     // responds with 200 instead of 206 we'll fall back into a streaming mode. |  | 
|  143     loader_.reset(CreateResourceLoader(0, kPositionNotSpecified)); |  | 
|  144   } else { |  | 
|  145     // For all other protocols, assume they support range request. We fetch |  | 
|  146     // the full range of the resource to obtain the instance size because |  | 
|  147     // we won't be served HTTP headers. |  | 
|  148     loader_.reset(CreateResourceLoader(kPositionNotSpecified, |  | 
|  149                                        kPositionNotSpecified)); |  | 
|  150   } |  | 
|  151  |  | 
|  152   base::WeakPtr<BufferedDataSource> weak_this = weak_factory_.GetWeakPtr(); |  | 
|  153   loader_->Start( |  | 
|  154       base::Bind(&BufferedDataSource::StartCallback, weak_this), |  | 
|  155       base::Bind(&BufferedDataSource::LoadingStateChangedCallback, weak_this), |  | 
|  156       base::Bind(&BufferedDataSource::ProgressCallback, weak_this), |  | 
|  157       frame_); |  | 
|  158 } |  | 
|  159  |  | 
|  160 void BufferedDataSource::SetPreload(Preload preload) { |  | 
|  161   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  162   preload_ = preload; |  | 
|  163 } |  | 
|  164  |  | 
|  165 bool BufferedDataSource::HasSingleOrigin() { |  | 
|  166   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  167   DCHECK(init_cb_.is_null() && loader_.get()) |  | 
|  168       << "Initialize() must complete before calling HasSingleOrigin()"; |  | 
|  169   return loader_->HasSingleOrigin(); |  | 
|  170 } |  | 
|  171  |  | 
|  172 bool BufferedDataSource::DidPassCORSAccessCheck() const { |  | 
|  173   return loader_.get() && loader_->DidPassCORSAccessCheck(); |  | 
|  174 } |  | 
|  175  |  | 
|  176 void BufferedDataSource::Abort() { |  | 
|  177   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  178   { |  | 
|  179     base::AutoLock auto_lock(lock_); |  | 
|  180     StopInternal_Locked(); |  | 
|  181   } |  | 
|  182   StopLoader(); |  | 
|  183   frame_ = NULL; |  | 
|  184 } |  | 
|  185  |  | 
|  186 void BufferedDataSource::MediaPlaybackRateChanged(float playback_rate) { |  | 
|  187   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  188   DCHECK(loader_.get()); |  | 
|  189  |  | 
|  190   if (playback_rate < 0.0f) |  | 
|  191     return; |  | 
|  192  |  | 
|  193   playback_rate_ = playback_rate; |  | 
|  194   loader_->SetPlaybackRate(playback_rate); |  | 
|  195 } |  | 
|  196  |  | 
|  197 void BufferedDataSource::MediaIsPlaying() { |  | 
|  198   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  199   media_has_played_ = true; |  | 
|  200   UpdateDeferStrategy(false); |  | 
|  201 } |  | 
|  202  |  | 
|  203 void BufferedDataSource::MediaIsPaused() { |  | 
|  204   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  205   UpdateDeferStrategy(true); |  | 
|  206 } |  | 
|  207  |  | 
|  208 ///////////////////////////////////////////////////////////////////////////// |  | 
|  209 // media::DataSource implementation. |  | 
|  210 void BufferedDataSource::Stop() { |  | 
|  211   { |  | 
|  212     base::AutoLock auto_lock(lock_); |  | 
|  213     StopInternal_Locked(); |  | 
|  214   } |  | 
|  215  |  | 
|  216   render_task_runner_->PostTask( |  | 
|  217       FROM_HERE, |  | 
|  218       base::Bind(&BufferedDataSource::StopLoader, weak_factory_.GetWeakPtr())); |  | 
|  219 } |  | 
|  220  |  | 
|  221 void BufferedDataSource::SetBitrate(int bitrate) { |  | 
|  222   render_task_runner_->PostTask(FROM_HERE, |  | 
|  223                          base::Bind(&BufferedDataSource::SetBitrateTask, |  | 
|  224                                     weak_factory_.GetWeakPtr(), |  | 
|  225                                     bitrate)); |  | 
|  226 } |  | 
|  227  |  | 
|  228 void BufferedDataSource::Read( |  | 
|  229     int64 position, int size, uint8* data, |  | 
|  230     const media::DataSource::ReadCB& read_cb) { |  | 
|  231   DVLOG(1) << "Read: " << position << " offset, " << size << " bytes"; |  | 
|  232   DCHECK(!read_cb.is_null()); |  | 
|  233  |  | 
|  234   { |  | 
|  235     base::AutoLock auto_lock(lock_); |  | 
|  236     DCHECK(!read_op_); |  | 
|  237  |  | 
|  238     if (stop_signal_received_) { |  | 
|  239       read_cb.Run(kReadError); |  | 
|  240       return; |  | 
|  241     } |  | 
|  242  |  | 
|  243     read_op_.reset(new ReadOperation(position, size, data, read_cb)); |  | 
|  244   } |  | 
|  245  |  | 
|  246   render_task_runner_->PostTask( |  | 
|  247       FROM_HERE, |  | 
|  248       base::Bind(&BufferedDataSource::ReadTask, weak_factory_.GetWeakPtr())); |  | 
|  249 } |  | 
|  250  |  | 
|  251 bool BufferedDataSource::GetSize(int64* size_out) { |  | 
|  252   if (total_bytes_ != kPositionNotSpecified) { |  | 
|  253     *size_out = total_bytes_; |  | 
|  254     return true; |  | 
|  255   } |  | 
|  256   *size_out = 0; |  | 
|  257   return false; |  | 
|  258 } |  | 
|  259  |  | 
|  260 bool BufferedDataSource::IsStreaming() { |  | 
|  261   return streaming_; |  | 
|  262 } |  | 
|  263  |  | 
|  264 ///////////////////////////////////////////////////////////////////////////// |  | 
|  265 // Render thread tasks. |  | 
|  266 void BufferedDataSource::ReadTask() { |  | 
|  267   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  268   ReadInternal(); |  | 
|  269 } |  | 
|  270  |  | 
|  271 void BufferedDataSource::StopInternal_Locked() { |  | 
|  272   lock_.AssertAcquired(); |  | 
|  273   if (stop_signal_received_) |  | 
|  274     return; |  | 
|  275  |  | 
|  276   stop_signal_received_ = true; |  | 
|  277  |  | 
|  278   // Initialize() isn't part of the DataSource interface so don't call it in |  | 
|  279   // response to Stop(). |  | 
|  280   init_cb_.Reset(); |  | 
|  281  |  | 
|  282   if (read_op_) |  | 
|  283     ReadOperation::Run(read_op_.Pass(), kReadError); |  | 
|  284 } |  | 
|  285  |  | 
|  286 void BufferedDataSource::StopLoader() { |  | 
|  287   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  288  |  | 
|  289   if (loader_) |  | 
|  290     loader_->Stop(); |  | 
|  291 } |  | 
|  292  |  | 
|  293 void BufferedDataSource::SetBitrateTask(int bitrate) { |  | 
|  294   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  295   DCHECK(loader_.get()); |  | 
|  296  |  | 
|  297   bitrate_ = bitrate; |  | 
|  298   loader_->SetBitrate(bitrate); |  | 
|  299 } |  | 
|  300  |  | 
|  301 // This method is the place where actual read happens, |loader_| must be valid |  | 
|  302 // prior to make this method call. |  | 
|  303 void BufferedDataSource::ReadInternal() { |  | 
|  304   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  305   int64 position = 0; |  | 
|  306   int size = 0; |  | 
|  307   { |  | 
|  308     base::AutoLock auto_lock(lock_); |  | 
|  309     if (stop_signal_received_) |  | 
|  310       return; |  | 
|  311  |  | 
|  312     position = read_op_->position(); |  | 
|  313     size = read_op_->size(); |  | 
|  314   } |  | 
|  315  |  | 
|  316   // First we prepare the intermediate read buffer for BufferedResourceLoader |  | 
|  317   // to write to. |  | 
|  318   if (size > intermediate_read_buffer_size_) { |  | 
|  319     intermediate_read_buffer_.reset(new uint8[size]); |  | 
|  320   } |  | 
|  321  |  | 
|  322   // Perform the actual read with BufferedResourceLoader. |  | 
|  323   loader_->Read(position, |  | 
|  324                 size, |  | 
|  325                 intermediate_read_buffer_.get(), |  | 
|  326                 base::Bind(&BufferedDataSource::ReadCallback, |  | 
|  327                            weak_factory_.GetWeakPtr())); |  | 
|  328 } |  | 
|  329  |  | 
|  330  |  | 
|  331 ///////////////////////////////////////////////////////////////////////////// |  | 
|  332 // BufferedResourceLoader callback methods. |  | 
|  333 void BufferedDataSource::StartCallback( |  | 
|  334     BufferedResourceLoader::Status status) { |  | 
|  335   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  336   DCHECK(loader_.get()); |  | 
|  337  |  | 
|  338   bool init_cb_is_null = false; |  | 
|  339   { |  | 
|  340     base::AutoLock auto_lock(lock_); |  | 
|  341     init_cb_is_null = init_cb_.is_null(); |  | 
|  342   } |  | 
|  343   if (init_cb_is_null) { |  | 
|  344     loader_->Stop(); |  | 
|  345     return; |  | 
|  346   } |  | 
|  347  |  | 
|  348   // All responses must be successful. Resources that are assumed to be fully |  | 
|  349   // buffered must have a known content length. |  | 
|  350   bool success = status == BufferedResourceLoader::kOk && |  | 
|  351                  (!assume_fully_buffered() || |  | 
|  352                   loader_->instance_size() != kPositionNotSpecified); |  | 
|  353  |  | 
|  354   if (success) { |  | 
|  355     total_bytes_ = loader_->instance_size(); |  | 
|  356     streaming_ = |  | 
|  357         !assume_fully_buffered() && |  | 
|  358         (total_bytes_ == kPositionNotSpecified || !loader_->range_supported()); |  | 
|  359  |  | 
|  360     media_log_->SetDoubleProperty("total_bytes", |  | 
|  361                                   static_cast<double>(total_bytes_)); |  | 
|  362     media_log_->SetBooleanProperty("streaming", streaming_); |  | 
|  363   } else { |  | 
|  364     loader_->Stop(); |  | 
|  365   } |  | 
|  366  |  | 
|  367   // TODO(scherkus): we shouldn't have to lock to signal host(), see |  | 
|  368   // http://crbug.com/113712 for details. |  | 
|  369   base::AutoLock auto_lock(lock_); |  | 
|  370   if (stop_signal_received_) |  | 
|  371     return; |  | 
|  372  |  | 
|  373   if (success) { |  | 
|  374     if (total_bytes_ != kPositionNotSpecified) { |  | 
|  375       host_->SetTotalBytes(total_bytes_); |  | 
|  376       if (assume_fully_buffered()) |  | 
|  377         host_->AddBufferedByteRange(0, total_bytes_); |  | 
|  378     } |  | 
|  379  |  | 
|  380     media_log_->SetBooleanProperty("single_origin", loader_->HasSingleOrigin()); |  | 
|  381     media_log_->SetBooleanProperty("passed_cors_access_check", |  | 
|  382                                    loader_->DidPassCORSAccessCheck()); |  | 
|  383     media_log_->SetBooleanProperty("range_header_supported", |  | 
|  384                                    loader_->range_supported()); |  | 
|  385   } |  | 
|  386  |  | 
|  387   base::ResetAndReturn(&init_cb_).Run(success); |  | 
|  388 } |  | 
|  389  |  | 
|  390 void BufferedDataSource::PartialReadStartCallback( |  | 
|  391     BufferedResourceLoader::Status status) { |  | 
|  392   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  393   DCHECK(loader_.get()); |  | 
|  394  |  | 
|  395   if (status == BufferedResourceLoader::kOk) { |  | 
|  396     // Once the request has started successfully, we can proceed with |  | 
|  397     // reading from it. |  | 
|  398     ReadInternal(); |  | 
|  399     return; |  | 
|  400   } |  | 
|  401  |  | 
|  402   // Stop the resource loader since we have received an error. |  | 
|  403   loader_->Stop(); |  | 
|  404  |  | 
|  405   // TODO(scherkus): we shouldn't have to lock to signal host(), see |  | 
|  406   // http://crbug.com/113712 for details. |  | 
|  407   base::AutoLock auto_lock(lock_); |  | 
|  408   if (stop_signal_received_) |  | 
|  409     return; |  | 
|  410   ReadOperation::Run(read_op_.Pass(), kReadError); |  | 
|  411 } |  | 
|  412  |  | 
|  413 void BufferedDataSource::ReadCallback( |  | 
|  414     BufferedResourceLoader::Status status, |  | 
|  415     int bytes_read) { |  | 
|  416   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  417  |  | 
|  418   // TODO(scherkus): we shouldn't have to lock to signal host(), see |  | 
|  419   // http://crbug.com/113712 for details. |  | 
|  420   base::AutoLock auto_lock(lock_); |  | 
|  421   if (stop_signal_received_) |  | 
|  422     return; |  | 
|  423  |  | 
|  424   if (status != BufferedResourceLoader::kOk) { |  | 
|  425     // Stop the resource load if it failed. |  | 
|  426     loader_->Stop(); |  | 
|  427  |  | 
|  428     if (status == BufferedResourceLoader::kCacheMiss && |  | 
|  429         read_op_->retries() < kNumCacheMissRetries) { |  | 
|  430       read_op_->IncrementRetries(); |  | 
|  431  |  | 
|  432       // Recreate a loader starting from where we last left off until the |  | 
|  433       // end of the resource. |  | 
|  434       loader_.reset(CreateResourceLoader( |  | 
|  435           read_op_->position(), kPositionNotSpecified)); |  | 
|  436  |  | 
|  437       base::WeakPtr<BufferedDataSource> weak_this = weak_factory_.GetWeakPtr(); |  | 
|  438       loader_->Start( |  | 
|  439           base::Bind(&BufferedDataSource::PartialReadStartCallback, weak_this), |  | 
|  440           base::Bind(&BufferedDataSource::LoadingStateChangedCallback, |  | 
|  441                      weak_this), |  | 
|  442           base::Bind(&BufferedDataSource::ProgressCallback, weak_this), |  | 
|  443           frame_); |  | 
|  444       return; |  | 
|  445     } |  | 
|  446  |  | 
|  447     ReadOperation::Run(read_op_.Pass(), kReadError); |  | 
|  448     return; |  | 
|  449   } |  | 
|  450  |  | 
|  451   if (bytes_read > 0) { |  | 
|  452     memcpy(read_op_->data(), intermediate_read_buffer_.get(), bytes_read); |  | 
|  453   } else if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) { |  | 
|  454     // We've reached the end of the file and we didn't know the total size |  | 
|  455     // before. Update the total size so Read()s past the end of the file will |  | 
|  456     // fail like they would if we had known the file size at the beginning. |  | 
|  457     total_bytes_ = loader_->instance_size(); |  | 
|  458  |  | 
|  459     if (total_bytes_ != kPositionNotSpecified) { |  | 
|  460       host_->SetTotalBytes(total_bytes_); |  | 
|  461       host_->AddBufferedByteRange(loader_->first_byte_position(), |  | 
|  462                                   total_bytes_); |  | 
|  463     } |  | 
|  464   } |  | 
|  465   ReadOperation::Run(read_op_.Pass(), bytes_read); |  | 
|  466 } |  | 
|  467  |  | 
|  468 void BufferedDataSource::LoadingStateChangedCallback( |  | 
|  469     BufferedResourceLoader::LoadingState state) { |  | 
|  470   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  471  |  | 
|  472   if (assume_fully_buffered()) |  | 
|  473     return; |  | 
|  474  |  | 
|  475   bool is_downloading_data; |  | 
|  476   switch (state) { |  | 
|  477     case BufferedResourceLoader::kLoading: |  | 
|  478       is_downloading_data = true; |  | 
|  479       break; |  | 
|  480     case BufferedResourceLoader::kLoadingDeferred: |  | 
|  481     case BufferedResourceLoader::kLoadingFinished: |  | 
|  482       is_downloading_data = false; |  | 
|  483       break; |  | 
|  484  |  | 
|  485     // TODO(scherkus): we don't signal network activity changes when loads |  | 
|  486     // fail to preserve existing behaviour when deferring is toggled, however |  | 
|  487     // we should consider changing DownloadingCB to also propagate loading |  | 
|  488     // state. For example there isn't any signal today to notify the client that |  | 
|  489     // loading has failed (we only get errors on subsequent reads). |  | 
|  490     case BufferedResourceLoader::kLoadingFailed: |  | 
|  491       return; |  | 
|  492   } |  | 
|  493  |  | 
|  494   downloading_cb_.Run(is_downloading_data); |  | 
|  495 } |  | 
|  496  |  | 
|  497 void BufferedDataSource::ProgressCallback(int64 position) { |  | 
|  498   DCHECK(render_task_runner_->BelongsToCurrentThread()); |  | 
|  499  |  | 
|  500   if (assume_fully_buffered()) |  | 
|  501     return; |  | 
|  502  |  | 
|  503   // TODO(scherkus): we shouldn't have to lock to signal host(), see |  | 
|  504   // http://crbug.com/113712 for details. |  | 
|  505   base::AutoLock auto_lock(lock_); |  | 
|  506   if (stop_signal_received_) |  | 
|  507     return; |  | 
|  508  |  | 
|  509   host_->AddBufferedByteRange(loader_->first_byte_position(), position); |  | 
|  510 } |  | 
|  511  |  | 
|  512 void BufferedDataSource::UpdateDeferStrategy(bool paused) { |  | 
|  513   // No need to aggressively buffer when we are assuming the resource is fully |  | 
|  514   // buffered. |  | 
|  515   if (assume_fully_buffered()) { |  | 
|  516     loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); |  | 
|  517     return; |  | 
|  518   } |  | 
|  519  |  | 
|  520   // If the playback has started (at which point the preload value is ignored) |  | 
|  521   // and we're paused, then try to load as much as possible (the loader will |  | 
|  522   // fall back to kCapacityDefer if it knows the current response won't be |  | 
|  523   // useful from the cache in the future). |  | 
|  524   if (media_has_played_ && paused && loader_->range_supported()) { |  | 
|  525     loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer); |  | 
|  526     return; |  | 
|  527   } |  | 
|  528  |  | 
|  529   // If media is currently playing or the page indicated preload=auto or the |  | 
|  530   // the server does not support the byte range request or we do not want to go |  | 
|  531   // too far ahead of the read head, use threshold strategy to enable/disable |  | 
|  532   // deferring when the buffer is full/depleted. |  | 
|  533   loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer); |  | 
|  534 } |  | 
|  535  |  | 
|  536 }  // namespace content |  | 
| OLD | NEW |