Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Side by Side Diff: webkit/glue/media/buffered_data_source.cc

Issue 165176: Merge 21999 - BufferedDataSource to support server without range request supp... (Closed) Base URL: svn://chrome-svn/chrome/branches/195/src/
Patch Set: Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Modified: svn:mergeinfo
Merged /trunk/src/webkit/glue/media/buffered_data_source.cc:r21999
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the 2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file. 3 // LICENSE file.
4 4
5 #include "base/compiler_specific.h" 5 #include "base/compiler_specific.h"
6 #include "base/message_loop.h" 6 #include "base/message_loop.h"
7 #include "base/process_util.h" 7 #include "base/process_util.h"
8 #include "base/stl_util-inl.h" 8 #include "base/stl_util-inl.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "chrome/common/extensions/url_pattern.h" 10 #include "chrome/common/extensions/url_pattern.h"
(...skipping 14 matching lines...) Expand all
25 25
26 // Define the number of bytes in a megabyte. 26 // Define the number of bytes in a megabyte.
27 const size_t kMegabyte = 1024 * 1024; 27 const size_t kMegabyte = 1024 * 1024;
28 28
29 // Backward capacity of the buffer, by default 2MB. 29 // Backward capacity of the buffer, by default 2MB.
30 const size_t kBackwardCapcity = 2 * kMegabyte; 30 const size_t kBackwardCapcity = 2 * kMegabyte;
31 31
32 // Forward capacity of the buffer, by default 10MB. 32 // Forward capacity of the buffer, by default 10MB.
33 const size_t kForwardCapacity = 10 * kMegabyte; 33 const size_t kForwardCapacity = 10 * kMegabyte;
34 34
35 // The maximum offset to seek to, this value limits the range of seek to
36 // prevent corruption of calculations. The buffer has a maximum size of 12MB
37 // so this is enough to contain every valid operations.
38 const int kMaxSeek = 100 * kMegabyte;
39
40 // The threshold of bytes that we should wait until the data arrives in the 35 // The threshold of bytes that we should wait until the data arrives in the
41 // future instead of restarting a new connection. This number is defined in the 36 // future instead of restarting a new connection. This number is defined in the
42 // number of bytes, we should determine this value from typical connection speed 37 // number of bytes, we should determine this value from typical connection speed
43 // and amount of time for a suitable wait. Now I just make a guess for this 38 // and amount of time for a suitable wait. Now I just make a guess for this
44 // number to be 2MB. 39 // number to be 2MB.
45 // TODO(hclam): determine a better value for this. 40 // TODO(hclam): determine a better value for this.
46 const int kForwardWaitThreshold = 2 * kMegabyte; 41 const int kForwardWaitThreshold = 2 * kMegabyte;
47 42
48 // Defines how long we should wait for more data before we declare a connection 43 // Defines how long we should wait for more data before we declare a connection
49 // timeout and start a new request. 44 // timeout and start a new request.
50 // TODO(hclam): Use this value when retry is implemented. 45 // TODO(hclam): Use this value when retry is implemented.
51 // TODO(hclam): Set it to 5s, calibrate this value later. 46 // TODO(hclam): Set it to 5s, calibrate this value later.
52 const int kTimeoutMilliseconds = 5000; 47 const int kTimeoutMilliseconds = 5000;
53 48
54 // Defines how many times we should try to read from a buffered resource loader 49 // Defines how many times we should try to read from a buffered resource loader
55 // before we declare a read error. After each failure of read from a buffered 50 // before we declare a read error. After each failure of read from a buffered
56 // resource loader, a new one is created to be read. 51 // resource loader, a new one is created to be read.
57 // TODO(hclam): Use this value when retry is implemented. 52 // TODO(hclam): Use this value when retry is implemented.
58 const int kReadTrials = 3; 53 const int kReadTrials = 3;
59 54
60 // BufferedDataSource has an intermediate buffer, this value governs the initial 55 // BufferedDataSource has an intermediate buffer, this value governs the initial
61 // size of that buffer. It is set to 32KB because this is a typical read size 56 // size of that buffer. It is set to 32KB because this is a typical read size
62 // of FFmpeg. 57 // of FFmpeg.
63 const int kInitialReadBufferSize = 32768; 58 const int kInitialReadBufferSize = 32768;
64 59
65 // A helper method that accepts only HTTP, HTTPS and FILE protocol. 60 // A helper method that accepts only HTTP, HTTPS and FILE protocol.
61 // TODO(hclam): Support also FTP protocol.
66 bool IsSchemeSupported(const GURL& url) { 62 bool IsSchemeSupported(const GURL& url) {
67 return url.SchemeIs(kHttpScheme) || 63 return url.SchemeIs(kHttpScheme) ||
68 url.SchemeIs(kHttpsScheme) || 64 url.SchemeIs(kHttpsScheme) ||
69 url.SchemeIsFile(); 65 url.SchemeIsFile();
70 } 66 }
71 67
72 } // namespace 68 } // namespace
73 69
74 namespace webkit_glue { 70 namespace webkit_glue {
75 71
76 ///////////////////////////////////////////////////////////////////////////// 72 /////////////////////////////////////////////////////////////////////////////
77 // BufferedResourceLoader 73 // BufferedResourceLoader
78 BufferedResourceLoader::BufferedResourceLoader( 74 BufferedResourceLoader::BufferedResourceLoader(
79 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory, 75 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory,
80 const GURL& url, 76 const GURL& url,
81 int64 first_byte_position, 77 int64 first_byte_position,
82 int64 last_byte_position) 78 int64 last_byte_position)
83 : buffer_(new media::SeekableBuffer(kBackwardCapcity, kForwardCapacity)), 79 : buffer_(new media::SeekableBuffer(kBackwardCapcity, kForwardCapacity)),
84 deferred_(false), 80 deferred_(false),
85 completed_(false), 81 completed_(false),
86 range_requested_(false), 82 range_requested_(false),
87 bridge_factory_(bridge_factory), 83 bridge_factory_(bridge_factory),
88 url_(url), 84 url_(url),
89 first_byte_position_(first_byte_position), 85 first_byte_position_(first_byte_position),
90 last_byte_position_(last_byte_position), 86 last_byte_position_(last_byte_position),
91 start_callback_(NULL), 87 start_callback_(NULL),
92 bridge_(NULL), 88 bridge_(NULL),
93 offset_(0), 89 offset_(0),
94 content_length_(kPositionNotSpecified), 90 content_length_(kPositionNotSpecified),
91 instance_size_(kPositionNotSpecified),
95 read_callback_(NULL), 92 read_callback_(NULL),
96 read_position_(0), 93 read_position_(0),
97 read_size_(0), 94 read_size_(0),
98 read_buffer_(NULL), 95 read_buffer_(NULL),
99 first_offset_(0), 96 first_offset_(0),
100 last_offset_(0) { 97 last_offset_(0) {
101 } 98 }
102 99
103 BufferedResourceLoader::~BufferedResourceLoader() { 100 BufferedResourceLoader::~BufferedResourceLoader() {
104 } 101 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 DCHECK(buffer_.get()); 149 DCHECK(buffer_.get());
153 DCHECK(read_callback); 150 DCHECK(read_callback);
154 DCHECK(buffer); 151 DCHECK(buffer);
155 152
156 // Saves the parameter of reading. 153 // Saves the parameter of reading.
157 read_callback_.reset(read_callback); 154 read_callback_.reset(read_callback);
158 read_position_ = position; 155 read_position_ = position;
159 read_size_ = read_size; 156 read_size_ = read_size;
160 read_buffer_ = buffer; 157 read_buffer_ = buffer;
161 158
162 // Check that the read parameters are within the range that we can handle. 159 // If read position is beyond the instance size, we cannot read there.
163 // If the read request is made too far from the current offset, report that 160 if (instance_size_ != kPositionNotSpecified &&
164 // we cannot serve the request. 161 instance_size_ <= read_position_) {
165 if (VerifyRead()) { 162 DoneRead(0);
166 // If we can serve the request now, do the actual read. 163 return;
167 if (CanFulfillRead()) { 164 }
168 ReadInternal();
169 DisableDeferIfNeeded();
170 return;
171 }
172 165
173 // If we expected the read request to be fulfilled later, returns 166 // Make sure |offset_| and |read_position_| does not differ by a large
174 // immediately and let more data to flow in. 167 // amount.
175 if (WillFulfillRead()) 168 if (read_position_ > offset_ + kint32max ||
176 return; 169 read_position_ < offset_ + kint32min) {
177
178 // Make a callback to report failure.
179 DoneRead(net::ERR_CACHE_MISS); 170 DoneRead(net::ERR_CACHE_MISS);
180 return; 171 return;
181 } 172 }
182 173
183 // TODO(hclam): We should report a better error code than just 0. 174 // Prepare the parameters.
184 DoneRead(0); 175 first_offset_ = static_cast<int>(read_position_ - offset_);
176 last_offset_ = first_offset_ + read_size_;
177
178 // If we can serve the request now, do the actual read.
179 if (CanFulfillRead()) {
180 ReadInternal();
181 DisableDeferIfNeeded();
182 return;
183 }
184
185 // If we expected the read request to be fulfilled later, returns
186 // immediately and let more data to flow in.
187 if (WillFulfillRead())
188 return;
189
190 // Make a callback to report failure.
191 DoneRead(net::ERR_CACHE_MISS);
185 } 192 }
186 193
187 ///////////////////////////////////////////////////////////////////////////// 194 /////////////////////////////////////////////////////////////////////////////
188 // BufferedResourceLoader, 195 // BufferedResourceLoader,
189 // webkit_glue::ResourceLoaderBridge::Peer implementations 196 // webkit_glue::ResourceLoaderBridge::Peer implementations
190 void BufferedResourceLoader::OnReceivedRedirect(const GURL& new_url) { 197 void BufferedResourceLoader::OnReceivedRedirect(const GURL& new_url) {
191 DCHECK(bridge_.get()); 198 DCHECK(bridge_.get());
192 DCHECK(start_callback_.get()); 199 DCHECK(start_callback_.get());
193 200
194 // Saves the new URL. 201 // Saves the new URL.
(...skipping 18 matching lines...) Expand all
213 220
214 // The file:// protocol should be able to serve any request we want, so we 221 // The file:// protocol should be able to serve any request we want, so we
215 // take an exception for file protocol. 222 // take an exception for file protocol.
216 if (!url_.SchemeIsFile()) { 223 if (!url_.SchemeIsFile()) {
217 int error = net::OK; 224 int error = net::OK;
218 if (!info.headers) { 225 if (!info.headers) {
219 // We expect to receive headers because this is a HTTP or HTTPS protocol, 226 // We expect to receive headers because this is a HTTP or HTTPS protocol,
220 // if not report failure. 227 // if not report failure.
221 error = net::ERR_INVALID_RESPONSE; 228 error = net::ERR_INVALID_RESPONSE;
222 } else if (range_requested_) { 229 } else if (range_requested_) {
223 if (info.headers->response_code() != kHttpPartialContent || 230 // If we have verified the partial response and it is correct, we will
224 !info.headers->GetContentRange(&first_byte_position, 231 // return net::OK.
225 &last_byte_position, 232 if (!VerifyPartialResponse(info))
226 &instance_size)) { 233 error = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
227 // We requested a range, but server didn't reply with partial content or
228 // the "Content-Range" header is corrupted.
229 // TODO(hclam): should also make sure this is the range we requested.
230 error = net::ERR_INVALID_RESPONSE;
231 }
232 } else if (info.headers->response_code() != kHttpOK) { 234 } else if (info.headers->response_code() != kHttpOK) {
233 // We didn't request a range but server didn't reply with "200 OK". 235 // We didn't request a range but server didn't reply with "200 OK".
234 error = net::ERR_FAILED; 236 error = net::ERR_FAILED;
235 } 237 }
236 238
237 if (error != net::OK) { 239 if (error != net::OK) {
238 DoneStart(error); 240 DoneStart(error);
239 Stop(); 241 Stop();
240 return; 242 return;
241 } 243 }
242 } 244 }
243 245
244 // |info.content_length| can be -1, in that case |content_length_| is 246 // |info.content_length| can be -1, in that case |content_length_| is
245 // not specified and this is a streaming response. 247 // not specified and this is a streaming response.
246 content_length_ = info.content_length; 248 content_length_ = info.content_length;
247 249
250 // If we have not requested a range, then the size of the instance is equal
251 // to the content length.
252 if (!range_requested_)
253 instance_size_ = content_length_;
254
248 // We only care about the first byte position if it's given by the server. 255 // We only care about the first byte position if it's given by the server.
249 // TODO(hclam): If server replies with a different offset, consider failing 256 // TODO(hclam): If server replies with a different offset, consider failing
250 // here. 257 // here.
251 if (first_byte_position != kPositionNotSpecified) 258 if (first_byte_position != kPositionNotSpecified)
252 offset_ = first_byte_position; 259 offset_ = first_byte_position;
253 260
254 // Calls with a successful response. 261 // Calls with a successful response.
255 DoneStart(net::OK); 262 DoneStart(net::OK);
256 } 263 }
257 264
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 return false; 370 return false;
364 371
365 // The resource request has completed, there's no way we can fulfill the 372 // The resource request has completed, there's no way we can fulfill the
366 // read request. 373 // read request.
367 if (completed_) 374 if (completed_)
368 return false; 375 return false;
369 376
370 return true; 377 return true;
371 } 378 }
372 379
373 bool BufferedResourceLoader::VerifyRead() {
374 // Make sure |offset_| and |read_position_| does not differ by a large
375 // amount
376 if (read_position_ > offset_ + kMaxSeek)
377 return false;
378 else if (read_position_ < offset_ - kMaxSeek)
379 return false;
380
381 // If we can manage the read request with int32 math, then prepare the
382 // parameters.
383 first_offset_ = static_cast<int>(read_position_ - offset_);
384 last_offset_ = first_offset_ + read_size_;
385 return true;
386 }
387
388 void BufferedResourceLoader::ReadInternal() { 380 void BufferedResourceLoader::ReadInternal() {
389 // Seek to the first byte requested. 381 // Seek to the first byte requested.
390 bool ret = buffer_->Seek(first_offset_); 382 bool ret = buffer_->Seek(first_offset_);
391 DCHECK(ret); 383 DCHECK(ret);
392 384
393 // Then do the read. 385 // Then do the read.
394 int read = static_cast<int>(buffer_->Read(read_size_, read_buffer_)); 386 int read = static_cast<int>(buffer_->Read(read_size_, read_buffer_));
395 offset_ += first_offset_ + read; 387 offset_ += first_offset_ + read;
396 388
397 // And report with what we have read. 389 // And report with what we have read.
398 DoneRead(read); 390 DoneRead(read);
399 } 391 }
400 392
401 void BufferedResourceLoader::DoneRead(int error) { 393 void BufferedResourceLoader::DoneRead(int error) {
402 read_callback_->RunWithParams(Tuple1<int>(error)); 394 read_callback_->RunWithParams(Tuple1<int>(error));
403 read_callback_.reset(); 395 read_callback_.reset();
404 read_position_ = 0; 396 read_position_ = 0;
405 read_size_ = 0; 397 read_size_ = 0;
406 read_buffer_ = NULL; 398 read_buffer_ = NULL;
407 first_offset_ = 0; 399 first_offset_ = 0;
408 last_offset_ = 0; 400 last_offset_ = 0;
409 } 401 }
410 402
411 void BufferedResourceLoader::DoneStart(int error) { 403 void BufferedResourceLoader::DoneStart(int error) {
412 start_callback_->RunWithParams(Tuple1<int>(error)); 404 start_callback_->RunWithParams(Tuple1<int>(error));
413 start_callback_.reset(); 405 start_callback_.reset();
414 } 406 }
415 407
408 bool BufferedResourceLoader::VerifyPartialResponse(
409 const ResourceLoaderBridge::ResponseInfo& info) {
410 if (info.headers->response_code() != kHttpPartialContent)
411 return false;
412
413 int64 first_byte_position, last_byte_position, instance_size;
414 if (!info.headers->GetContentRange(&first_byte_position,
415 &last_byte_position,
416 &instance_size)) {
417 return false;
418 }
419
420 if (instance_size != kPositionNotSpecified)
421 instance_size_ = instance_size;
422
423 if (first_byte_position_ != -1 &&
424 first_byte_position_ != first_byte_position) {
425 return false;
426 }
427
428 // TODO(hclam): I should also check |last_byte_position|, but since
429 // we will never make such a request that it is ok to leave it unimplemented.
430 return true;
431 }
432
416 ////////////////////////////////////////////////////////////////////////////// 433 //////////////////////////////////////////////////////////////////////////////
417 // BufferedDataSource, protected 434 // BufferedDataSource, protected
418 BufferedDataSource::BufferedDataSource( 435 BufferedDataSource::BufferedDataSource(
419 MessageLoop* render_loop, 436 MessageLoop* render_loop,
420 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory) 437 webkit_glue::MediaResourceLoaderBridgeFactory* bridge_factory)
421 : total_bytes_(kPositionNotSpecified), 438 : total_bytes_(kPositionNotSpecified),
439 streaming_(false),
422 bridge_factory_(bridge_factory), 440 bridge_factory_(bridge_factory),
423 loader_(NULL), 441 loader_(NULL),
442 initialize_callback_(NULL),
424 read_callback_(NULL), 443 read_callback_(NULL),
425 read_position_(0), 444 read_position_(0),
426 read_size_(0), 445 read_size_(0),
427 read_buffer_(NULL), 446 read_buffer_(NULL),
447 initial_response_received_(false),
448 probe_response_received_(false),
428 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), 449 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]),
429 intermediate_read_buffer_size_(kInitialReadBufferSize), 450 intermediate_read_buffer_size_(kInitialReadBufferSize),
430 render_loop_(render_loop), 451 render_loop_(render_loop),
431 initialize_callback_(NULL),
432 stopped_(false) { 452 stopped_(false) {
433 } 453 }
434 454
435 BufferedDataSource::~BufferedDataSource() { 455 BufferedDataSource::~BufferedDataSource() {
436 } 456 }
437 457
438 // A factory method to create BufferedResourceLoader using the read parameters. 458 // A factory method to create BufferedResourceLoader using the read parameters.
439 // This method can be overrided to inject mock BufferedResourceLoader object 459 // This method can be overrided to inject mock BufferedResourceLoader object
440 // for testing purpose. 460 // for testing purpose.
441 BufferedResourceLoader* BufferedDataSource::CreateLoader( 461 BufferedResourceLoader* BufferedDataSource::CreateLoader(
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 520
501 bool BufferedDataSource::GetSize(int64* size_out) { 521 bool BufferedDataSource::GetSize(int64* size_out) {
502 if (total_bytes_ != kPositionNotSpecified) { 522 if (total_bytes_ != kPositionNotSpecified) {
503 *size_out = total_bytes_; 523 *size_out = total_bytes_;
504 return true; 524 return true;
505 } 525 }
506 *size_out = 0; 526 *size_out = 0;
507 return false; 527 return false;
508 } 528 }
509 529
510 bool BufferedDataSource::IsSeekable() { 530 bool BufferedDataSource::IsStreaming() {
511 return total_bytes_ != kPositionNotSpecified; 531 return streaming_;
512 } 532 }
513 533
514 ///////////////////////////////////////////////////////////////////////////// 534 /////////////////////////////////////////////////////////////////////////////
515 // BufferedDataSource, render thread tasks 535 // BufferedDataSource, render thread tasks
516 void BufferedDataSource::InitializeTask() { 536 void BufferedDataSource::InitializeTask() {
517 DCHECK(MessageLoop::current() == render_loop_); 537 DCHECK(MessageLoop::current() == render_loop_);
518 DCHECK(!loader_.get()); 538 DCHECK(!loader_.get());
539 DCHECK(!probe_loader_.get());
519 540
520 // Kick starts the watch dog task that will handle connection timeout. 541 // Kick starts the watch dog task that will handle connection timeout.
521 // We run the watch dog 2 times faster the actual timeout so as to catch 542 // We run the watch dog 2 times faster the actual timeout so as to catch
522 // the timeout more accurately. 543 // the timeout more accurately.
523 watch_dog_timer_.Start( 544 watch_dog_timer_.Start(
524 GetTimeoutMilliseconds() / 2, 545 GetTimeoutMilliseconds() / 2,
525 this, 546 this,
526 &BufferedDataSource::WatchDogTask); 547 &BufferedDataSource::WatchDogTask);
527 548
528 // Creates a new resource loader with the full range. 549 // Creates a new resource loader with the full range and a probe resource
550 // loader. Creates a probe resource loader to make sure the server supports
551 // partial range request.
552 // TODO(hclam): Only request 1 byte for this probe request, it may be useful
553 // that we perform a suffix range request and fetch the index. That way we
554 // can minimize the number of requests made.
529 loader_.reset(CreateLoader(-1, -1)); 555 loader_.reset(CreateLoader(-1, -1));
556 probe_loader_.reset(CreateLoader(1, 1));
530 557
531 // And then start the resource request. 558 loader_->Start(NewCallback(this, &BufferedDataSource::InitialStartCallback));
532 loader_->Start(NewCallback(this, 559 probe_loader_->Start(
533 &BufferedDataSource::InitializeStartCallback)); 560 NewCallback(this, &BufferedDataSource::ProbeStartCallback));
534 } 561 }
535 562
536 void BufferedDataSource::ReadTask( 563 void BufferedDataSource::ReadTask(
537 int64 position, int read_size, uint8* buffer, 564 int64 position, int read_size, uint8* buffer,
538 media::DataSource::ReadCallback* read_callback) { 565 media::DataSource::ReadCallback* read_callback) {
539 DCHECK(MessageLoop::current() == render_loop_); 566 DCHECK(MessageLoop::current() == render_loop_);
540 DCHECK(!read_callback_.get()); 567 DCHECK(!read_callback_.get());
541 DCHECK(read_callback); 568 DCHECK(read_callback);
542 569
543 // Saves the read parameters. 570 // Saves the read parameters.
544 read_position_ = position; 571 read_position_ = position;
545 read_size_ = read_size; 572 read_size_ = read_size;
546 read_callback_.reset(read_callback); 573 read_callback_.reset(read_callback);
547 read_buffer_ = buffer; 574 read_buffer_ = buffer;
548 read_submitted_time_ = base::Time::Now(); 575 read_submitted_time_ = base::Time::Now();
549 read_attempts_ = 0; 576 read_attempts_ = 0;
550 577
551 // Call to read internal to perform the actual read. 578 // Call to read internal to perform the actual read.
552 ReadInternal(); 579 ReadInternal();
553 } 580 }
554 581
555 void BufferedDataSource::StopTask() { 582 void BufferedDataSource::StopTask() {
556 DCHECK(MessageLoop::current() == render_loop_); 583 DCHECK(MessageLoop::current() == render_loop_);
557 584
558 // Stop the watch dog. 585 // Stop the watch dog.
559 watch_dog_timer_.Stop(); 586 watch_dog_timer_.Stop();
560 587
561 // We just need to stop the loader, so it stops activity. 588 // We just need to stop the loader, so it stops activity.
562 if (loader_.get()) { 589 if (loader_.get())
563 loader_->Stop(); 590 loader_->Stop();
564 loader_.reset(); 591
565 } 592 // If the probe request is still active, stop it too.
593 if (probe_loader_.get())
594 probe_loader_->Stop();
566 595
567 // Reset the parameters of the current read request. 596 // Reset the parameters of the current read request.
568 read_callback_.reset(); 597 read_callback_.reset();
569 read_position_ = 0; 598 read_position_ = 0;
570 read_size_ = 0; 599 read_size_ = 0;
571 read_buffer_ = 0; 600 read_buffer_ = 0;
572 read_submitted_time_ = base::Time(); 601 read_submitted_time_ = base::Time();
573 read_attempts_ = 0; 602 read_attempts_ = 0;
574 } 603 }
575 604
(...skipping 10 matching lines...) Expand all
586 DCHECK(MessageLoop::current() == render_loop_); 615 DCHECK(MessageLoop::current() == render_loop_);
587 616
588 // We only care if there is an active read request. 617 // We only care if there is an active read request.
589 if (!read_callback_.get()) 618 if (!read_callback_.get())
590 return; 619 return;
591 620
592 DCHECK(loader_.get()); 621 DCHECK(loader_.get());
593 base::TimeDelta delta = base::Time::Now() - read_submitted_time_; 622 base::TimeDelta delta = base::Time::Now() - read_submitted_time_;
594 if (delta < GetTimeoutMilliseconds()) 623 if (delta < GetTimeoutMilliseconds())
595 return; 624 return;
596 625
597 // TODO(hclam): Maybe raise an error here. But if an error is reported 626 // TODO(hclam): Maybe raise an error here. But if an error is reported
598 // the whole pipeline may get destroyed... 627 // the whole pipeline may get destroyed...
599 if (read_attempts_ >= kReadTrials) 628 if (read_attempts_ >= kReadTrials)
600 return; 629 return;
601 630
602 ++read_attempts_; 631 ++read_attempts_;
603 read_submitted_time_ = base::Time::Now(); 632 read_submitted_time_ = base::Time::Now();
604 633
605 // Stops the current loader and swap in a new resource loader and 634 // Stops the current loader and swap in a new resource loader and
606 // retry the request. 635 // retry the request.
607 loader_->Stop(); 636 loader_->Stop();
608 SwapLoaderTask(CreateLoader(read_position_, -1)); 637 SwapLoaderTask(CreateLoader(read_position_, -1));
609 } 638 }
610 639
611 // This method is the place where actual read happens, |loader_| must be valid 640 // This method is the place where actual read happens, |loader_| must be valid
612 // prior to make this method call. 641 // prior to make this method call.
613 void BufferedDataSource::ReadInternal() { 642 void BufferedDataSource::ReadInternal() {
614 DCHECK(MessageLoop::current() == render_loop_); 643 DCHECK(MessageLoop::current() == render_loop_);
615 DCHECK(loader_.get()); 644 DCHECK(loader_.get());
616 645
617 // First we prepare the intermediate read buffer for BufferedResourceLoader 646 // First we prepare the intermediate read buffer for BufferedResourceLoader
618 // to write to. 647 // to write to.
619 if (read_size_ > intermediate_read_buffer_size_) { 648 if (read_size_ > intermediate_read_buffer_size_) {
620 intermediate_read_buffer_.reset(new uint8[read_size_]); 649 intermediate_read_buffer_.reset(new uint8[read_size_]);
621 } 650 }
622 651
623 // Perform the actual read with BufferedResourceLoader. 652 // Perform the actual read with BufferedResourceLoader.
624 loader_->Read(read_position_, read_size_, 653 loader_->Read(read_position_, read_size_, intermediate_read_buffer_.get(),
625 intermediate_read_buffer_.get(),
626 NewCallback(this, &BufferedDataSource::ReadCallback)); 654 NewCallback(this, &BufferedDataSource::ReadCallback));
627 } 655 }
628 656
629 // Method to report the results of the current read request. Also reset all 657 // Method to report the results of the current read request. Also reset all
630 // the read parameters. 658 // the read parameters.
631 void BufferedDataSource::DoneRead(int error) { 659 void BufferedDataSource::DoneRead(int error) {
632 DCHECK(MessageLoop::current() == render_loop_); 660 DCHECK(MessageLoop::current() == render_loop_);
633 lock_.AssertAcquired(); 661 lock_.AssertAcquired();
634 662
635 if (error >= 0) { 663 if (error >= 0) {
(...skipping 14 matching lines...) Expand all
650 lock_.AssertAcquired(); 678 lock_.AssertAcquired();
651 679
652 initialize_callback_->Run(); 680 initialize_callback_->Run();
653 initialize_callback_.reset(); 681 initialize_callback_.reset();
654 } 682 }
655 683
656 ///////////////////////////////////////////////////////////////////////////// 684 /////////////////////////////////////////////////////////////////////////////
657 // BufferedDataSource, callback methods. 685 // BufferedDataSource, callback methods.
658 // These methods are called on the render thread for the events reported by 686 // These methods are called on the render thread for the events reported by
659 // BufferedResourceLoader. 687 // BufferedResourceLoader.
660 void BufferedDataSource::InitializeStartCallback(int error) { 688 void BufferedDataSource::InitialStartCallback(int error) {
661 DCHECK(MessageLoop::current() == render_loop_); 689 DCHECK(MessageLoop::current() == render_loop_);
662 690
663 // We need to prevent calling to filter host and running the callback if 691 // We need to prevent calling to filter host and running the callback if
664 // we have received the stop signal. We need to lock down the whole callback 692 // we have received the stop signal. We need to lock down the whole callback
665 // method to prevent bad things from happening. The reason behind this is 693 // method to prevent bad things from happening. The reason behind this is
666 // that we cannot guarantee tasks on render thread have completely stopped 694 // that we cannot guarantee tasks on render thread have completely stopped
667 // when we receive the Stop() method call. The only way to solve this is to 695 // when we receive the Stop() method call. The only way to solve this is to
668 // let tasks on render thread to run but make sure they don't call outside 696 // let tasks on render thread to run but make sure they don't call outside
669 // this object when Stop() method is ever called. Locking this method is safe 697 // this object when Stop() method is ever called. Locking this method is safe
670 // because |lock_| is only acquired in tasks on render thread. 698 // because |lock_| is only acquired in tasks on render thread.
671 AutoLock auto_lock(lock_); 699 AutoLock auto_lock(lock_);
672 if (stopped_) 700 if (stopped_)
673 return; 701 return;
674 702
675 DCHECK(loader_.get()); 703 if (error != net::OK) {
676
677 if (error == net::OK) {
678 total_bytes_ = loader_->content_length();
679 // TODO(hclam): Figure out what to do when total bytes is not known.
680 if (total_bytes_ >= 0) {
681 host()->SetTotalBytes(total_bytes_);
682
683 // This value governs the range that we can seek to.
684 // TODO(hclam): Report the correct value of buffered bytes.
685 host()->SetBufferedBytes(total_bytes_);
686 }
687 } else {
688 // TODO(hclam): In case of failure, we can retry several times. 704 // TODO(hclam): In case of failure, we can retry several times.
689 // Also it might be bad to access host() here.
690 host()->SetError(media::PIPELINE_ERROR_NETWORK); 705 host()->SetError(media::PIPELINE_ERROR_NETWORK);
691 706 DCHECK(loader_.get());
692 // Stops the loader, just to be safe. 707 DCHECK(probe_loader_.get());
693 loader_->Stop(); 708 loader_->Stop();
709 probe_loader_->Stop();
710 DoneInitialization();
711 return;
694 } 712 }
695 713
696 DoneInitialization(); 714 total_bytes_ = loader_->instance_size();
715 if (total_bytes_ >= 0) {
716 // This value governs the range that we can seek to.
717 // TODO(hclam): Report the correct value of buffered bytes.
718 host()->SetTotalBytes(total_bytes_);
719 host()->SetBufferedBytes(total_bytes_);
720 } else {
721 // If the server didn't reply with a content length, it is likely this
722 // is a streaming response.
723 streaming_ = true;
724 host()->SetStreaming(true);
725 }
726
727 initial_response_received_ = true;
728 if (probe_response_received_)
729 DoneInitialization();
730 }
731
732 void BufferedDataSource::ProbeStartCallback(int error) {
733 DCHECK(MessageLoop::current() == render_loop_);
734
735 // We need to prevent calling to filter host and running the callback if
736 // we have received the stop signal. We need to lock down the whole callback
737 // method to prevent bad things from happening. The reason behind this is
738 // that we cannot guarantee tasks on render thread have completely stopped
739 // when we receive the Stop() method call. The only way to solve this is to
740 // let tasks on render thread to run but make sure they don't call outside
741 // this object when Stop() method is ever called. Locking this method is safe
742 // because |lock_| is only acquired in tasks on render thread.
743 AutoLock auto_lock(lock_);
744 if (stopped_)
745 return;
746
747 if (error != net::OK) {
748 streaming_ = true;
749 host()->SetStreaming(true);
750 }
751
752 DCHECK(probe_loader_.get());
753 probe_loader_->Stop();
754 probe_response_received_ = true;
755 if (initial_response_received_)
756 DoneInitialization();
697 } 757 }
698 758
699 void BufferedDataSource::PartialReadStartCallback(int error) { 759 void BufferedDataSource::PartialReadStartCallback(int error) {
700 DCHECK(MessageLoop::current() == render_loop_); 760 DCHECK(MessageLoop::current() == render_loop_);
701 DCHECK(loader_.get()); 761 DCHECK(loader_.get());
702 762
703 if (error == net::OK) { 763 if (error == net::OK) {
704 // Once the range request has start successfully, we can proceed with 764 // Once the range request has start successfully, we can proceed with
705 // reading from it. 765 // reading from it.
706 ReadInternal(); 766 ReadInternal();
707 } else { 767 } else {
768 loader_->Stop();
769
708 // We need to prevent calling to filter host and running the callback if 770 // We need to prevent calling to filter host and running the callback if
709 // we have received the stop signal. We need to lock down the whole callback 771 // we have received the stop signal. We need to lock down the whole callback
710 // method to prevent bad things from happening. The reason behind this is 772 // method to prevent bad things from happening. The reason behind this is
711 // that we cannot guarantee tasks on render thread have completely stopped 773 // that we cannot guarantee tasks on render thread have completely stopped
712 // when we receive the Stop() method call. So only way to solve this is to 774 // when we receive the Stop() method call. So only way to solve this is to
713 // let tasks on render thread to run but make sure they don't call outside 775 // let tasks on render thread to run but make sure they don't call outside
714 // this object when Stop() method is ever called. Locking this method is 776 // this object when Stop() method is ever called. Locking this method is
715 // safe because |lock_| is only acquired in tasks on render thread. 777 // safe because |lock_| is only acquired in tasks on render thread.
716 AutoLock auto_lock(lock_); 778 AutoLock auto_lock(lock_);
717 if (stopped_) 779 if (stopped_)
718 return; 780 return;
719 781 DoneRead(net::ERR_INVALID_RESPONSE);
720 // TODO(hclam): It may be bad to access host() here.
721 host()->SetError(media::PIPELINE_ERROR_NETWORK);
722
723 // Kill the loader just to be safe.
724 loader_->Stop();
725 } 782 }
726 } 783 }
727 784
728 void BufferedDataSource::ReadCallback(int error) { 785 void BufferedDataSource::ReadCallback(int error) {
729 DCHECK(MessageLoop::current() == render_loop_); 786 DCHECK(MessageLoop::current() == render_loop_);
730 787
731 // We need to prevent calling to filter host and running the callback if 788 // We need to prevent calling to filter host and running the callback if
732 // we have received the stop signal. We need to lock down the whole callback 789 // we have received the stop signal. We need to lock down the whole callback
733 // method to prevent bad things from happening. The reason behind this is 790 // method to prevent bad things from happening. The reason behind this is
734 // that we cannot guarantee tasks on render thread have completely stopped 791 // that we cannot guarantee tasks on render thread have completely stopped
735 // when we receive the Stop() method call. So only way to solve this is to 792 // when we receive the Stop() method call. So only way to solve this is to
736 // let tasks on render thread to run but make sure they don't call outside 793 // let tasks on render thread to run but make sure they don't call outside
737 // this object when Stop() method is ever called. Locking this method is safe 794 // this object when Stop() method is ever called. Locking this method is safe
738 // because |lock_| is only acquired in tasks on render thread. 795 // because |lock_| is only acquired in tasks on render thread.
739 AutoLock auto_lock(lock_); 796 AutoLock auto_lock(lock_);
740 if (stopped_) 797 if (stopped_)
741 return; 798 return;
742 799
743 DCHECK(loader_.get()); 800 DCHECK(loader_.get());
744 DCHECK(read_callback_.get()); 801 DCHECK(read_callback_.get());
745 802
746 if (error >= 0) { 803 if (error >= 0) {
747 // If a position error code is received, read was successful. So copy 804 // If a position error code is received, read was successful. So copy
748 // from intermediate read buffer to the target read buffer. 805 // from intermediate read buffer to the target read buffer.
749 memcpy(read_buffer_, intermediate_read_buffer_.get(), error); 806 memcpy(read_buffer_, intermediate_read_buffer_.get(), error);
750
751 DoneRead(error); 807 DoneRead(error);
752 } else if (error == net::ERR_CACHE_MISS) { 808 } else if (error == net::ERR_CACHE_MISS) {
753 // If the current loader cannot serve this read request, we need to create 809 // If the current loader cannot serve this read request, we need to create
754 // a new one. 810 // a new one.
755 // We have the following conditions:
756 // 1. Read is beyond the content length of the file (if known).
757 // 2. We have tried too many times (TODO here).
758 if (read_position_ >= total_bytes_) {
759 DoneRead(0);
760 return;
761 }
762
763 // TODO(hclam): we need to count how many times it failed to prevent 811 // TODO(hclam): we need to count how many times it failed to prevent
764 // excessive trials. 812 // excessive trials.
765 813
766 // Stops the current resource loader. 814 // Stops the current resource loader.
767 loader_->Stop(); 815 loader_->Stop();
768 816
769 // Since this method is called from the current buffered resource loader, 817 // Since this method is called from the current buffered resource loader,
770 // we cannot delete it. So we need to post a task to swap in a new 818 // we cannot delete it. So we need to post a task to swap in a new
771 // resource loader and starts it. 819 // resource loader and starts it.
772 render_loop_->PostTask(FROM_HERE, 820 render_loop_->PostTask(FROM_HERE,
773 NewRunnableMethod(this, 821 NewRunnableMethod(this, &BufferedDataSource::SwapLoaderTask,
774 &BufferedDataSource::SwapLoaderTask,
775 CreateLoader(read_position_, -1))); 822 CreateLoader(read_position_, -1)));
776 } else { 823 } else {
777 // The read has finished with error. 824 loader_->Stop();
778 DoneRead(error); 825 DoneRead(error);
779
780 // TODO(hclam): It may be bad to access host() here.
781 host()->SetError(media::PIPELINE_ERROR_NETWORK);
782
783 // Stops the laoder.
784 loader_->Stop();
785 } 826 }
786 } 827 }
787 828
788 } // namespace webkit_glue 829 } // namespace webkit_glue
OLDNEW
« no previous file with comments | « webkit/glue/media/buffered_data_source.h ('k') | webkit/glue/media/buffered_data_source_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698