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

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

Issue 160076: BufferedDataSource to support server without range request support... (Closed) Base URL: svn://chrome-svn/chrome/trunk/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
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 kDataTransferTimeoutSeconds = 5; 47 const int kDataTransferTimeoutSeconds = 5;
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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 513
494 bool BufferedDataSource::GetSize(int64* size_out) { 514 bool BufferedDataSource::GetSize(int64* size_out) {
495 if (total_bytes_ != kPositionNotSpecified) { 515 if (total_bytes_ != kPositionNotSpecified) {
496 *size_out = total_bytes_; 516 *size_out = total_bytes_;
497 return true; 517 return true;
498 } 518 }
499 *size_out = 0; 519 *size_out = 0;
500 return false; 520 return false;
501 } 521 }
502 522
503 bool BufferedDataSource::IsSeekable() { 523 bool BufferedDataSource::IsStreaming() {
504 return total_bytes_ != kPositionNotSpecified; 524 return streaming_;
505 } 525 }
506 526
507 ///////////////////////////////////////////////////////////////////////////// 527 /////////////////////////////////////////////////////////////////////////////
508 // BufferedDataSource, render thread tasks 528 // BufferedDataSource, render thread tasks
509 void BufferedDataSource::InitializeTask() { 529 void BufferedDataSource::InitializeTask() {
510 DCHECK(MessageLoop::current() == render_loop_); 530 DCHECK(MessageLoop::current() == render_loop_);
511 DCHECK(!loader_.get()); 531 DCHECK(!loader_.get());
532 DCHECK(!probe_loader_.get());
512 533
513 // Creates a new resource loader with the full range. 534 // Creates a new resource loader with the full range and a probe resource
535 // loader. Creates a probe resource loader to make sure the server supports
536 // partial range request.
537 // TODO(hclam): Only request 1 byte for this probe request, it may be useful
538 // that we perform a suffix range request and fetch the index. That way we
539 // can minimize the number of requests made.
514 loader_.reset(CreateLoader(-1, -1)); 540 loader_.reset(CreateLoader(-1, -1));
541 probe_loader_.reset(CreateLoader(1, 1));
515 542
516 // And then start the resource request. 543 loader_->Start(NewCallback(this, &BufferedDataSource::InitialStartCallback));
517 loader_->Start(NewCallback(this, 544 probe_loader_->Start(
518 &BufferedDataSource::InitializeStartCallback)); 545 NewCallback(this, &BufferedDataSource::ProbeStartCallback));
519 } 546 }
520 547
521 void BufferedDataSource::ReadTask( 548 void BufferedDataSource::ReadTask(
522 int64 position, int read_size, uint8* buffer, 549 int64 position, int read_size, uint8* buffer,
523 media::DataSource::ReadCallback* read_callback) { 550 media::DataSource::ReadCallback* read_callback) {
524 DCHECK(MessageLoop::current() == render_loop_); 551 DCHECK(MessageLoop::current() == render_loop_);
525 DCHECK(!read_callback_.get()); 552 DCHECK(!read_callback_.get());
526 DCHECK(read_callback); 553 DCHECK(read_callback);
527 554
528 // Saves the read parameters. 555 // Saves the read parameters.
529 read_position_ = position; 556 read_position_ = position;
530 read_size_ = read_size; 557 read_size_ = read_size;
531 read_callback_.reset(read_callback); 558 read_callback_.reset(read_callback);
532 read_buffer_ = buffer; 559 read_buffer_ = buffer;
533 560
534 // Call to read internal to perform the actual read. 561 // Call to read internal to perform the actual read.
535 ReadInternal(); 562 ReadInternal();
536 } 563 }
537 564
538 void BufferedDataSource::StopTask() { 565 void BufferedDataSource::StopTask() {
539 DCHECK(MessageLoop::current() == render_loop_); 566 DCHECK(MessageLoop::current() == render_loop_);
540 567
541 // We just need to stop the loader, so it stops activity. 568 // We just need to stop the loader, so it stops activity.
542 if (loader_.get()) { 569 if (loader_.get())
543 loader_->Stop(); 570 loader_->Stop();
544 loader_.reset(); 571
545 } 572 // If the probe request is still active, stop it too.
573 if (probe_loader_.get())
574 probe_loader_->Stop();
546 } 575 }
547 576
548 void BufferedDataSource::SwapLoaderTask(BufferedResourceLoader* loader) { 577 void BufferedDataSource::SwapLoaderTask(BufferedResourceLoader* loader) {
549 DCHECK(MessageLoop::current() == render_loop_); 578 DCHECK(MessageLoop::current() == render_loop_);
550 DCHECK(loader); 579 DCHECK(loader);
551 580
552 loader_.reset(loader); 581 loader_.reset(loader);
553 loader_->Start(NewCallback(this, 582 loader_->Start(NewCallback(this,
554 &BufferedDataSource::PartialReadStartCallback)); 583 &BufferedDataSource::PartialReadStartCallback));
555 } 584 }
556 585
557 // This method is the place where actual read happens, |loader_| must be valid 586 // This method is the place where actual read happens, |loader_| must be valid
558 // prior to make this method call. 587 // prior to make this method call.
559 void BufferedDataSource::ReadInternal() { 588 void BufferedDataSource::ReadInternal() {
560 DCHECK(MessageLoop::current() == render_loop_); 589 DCHECK(MessageLoop::current() == render_loop_);
561 DCHECK(loader_.get()); 590 DCHECK(loader_.get());
562 591
563 // First we prepare the intermediate read buffer for BufferedResourceLoader 592 // First we prepare the intermediate read buffer for BufferedResourceLoader
564 // to write to. 593 // to write to.
565 if (read_size_ > intermediate_read_buffer_size_) { 594 if (read_size_ > intermediate_read_buffer_size_) {
566 intermediate_read_buffer_.reset(new uint8[read_size_]); 595 intermediate_read_buffer_.reset(new uint8[read_size_]);
567 } 596 }
568 597
569 // Perform the actual read with BufferedResourceLoader. 598 // Perform the actual read with BufferedResourceLoader.
570 loader_->Read(read_position_, read_size_, 599 loader_->Read(read_position_, read_size_, intermediate_read_buffer_.get(),
571 intermediate_read_buffer_.get(),
572 NewCallback(this, &BufferedDataSource::ReadCallback)); 600 NewCallback(this, &BufferedDataSource::ReadCallback));
573 } 601 }
574 602
575 // Method to report the results of the current read request. Also reset all 603 // Method to report the results of the current read request. Also reset all
576 // the read parameters. 604 // the read parameters.
577 void BufferedDataSource::DoneRead(int error) { 605 void BufferedDataSource::DoneRead(int error) {
578 DCHECK(MessageLoop::current() == render_loop_); 606 DCHECK(MessageLoop::current() == render_loop_);
579 lock_.AssertAcquired(); 607 lock_.AssertAcquired();
580 608
581 if (error >= 0) { 609 if (error >= 0) {
(...skipping 14 matching lines...) Expand all
596 lock_.AssertAcquired(); 624 lock_.AssertAcquired();
597 625
598 initialize_callback_->Run(); 626 initialize_callback_->Run();
599 initialize_callback_.reset(); 627 initialize_callback_.reset();
600 } 628 }
601 629
602 ///////////////////////////////////////////////////////////////////////////// 630 /////////////////////////////////////////////////////////////////////////////
603 // BufferedDataSource, callback methods. 631 // BufferedDataSource, callback methods.
604 // These methods are called on the render thread for the events reported by 632 // These methods are called on the render thread for the events reported by
605 // BufferedResourceLoader. 633 // BufferedResourceLoader.
606 void BufferedDataSource::InitializeStartCallback(int error) { 634 void BufferedDataSource::InitialStartCallback(int error) {
607 DCHECK(MessageLoop::current() == render_loop_); 635 DCHECK(MessageLoop::current() == render_loop_);
608 636
609 // We need to prevent calling to filter host and running the callback if 637 // We need to prevent calling to filter host and running the callback if
610 // we have received the stop signal. We need to lock down the whole callback 638 // we have received the stop signal. We need to lock down the whole callback
611 // method to prevent bad things from happening. The reason behind this is 639 // method to prevent bad things from happening. The reason behind this is
612 // that we cannot guarantee tasks on render thread have completely stopped 640 // that we cannot guarantee tasks on render thread have completely stopped
613 // when we receive the Stop() method call. The only way to solve this is to 641 // when we receive the Stop() method call. The only way to solve this is to
614 // let tasks on render thread to run but make sure they don't call outside 642 // let tasks on render thread to run but make sure they don't call outside
615 // this object when Stop() method is ever called. Locking this method is safe 643 // this object when Stop() method is ever called. Locking this method is safe
616 // because |lock_| is only acquired in tasks on render thread. 644 // because |lock_| is only acquired in tasks on render thread.
617 AutoLock auto_lock(lock_); 645 AutoLock auto_lock(lock_);
618 if (stopped_) 646 if (stopped_)
619 return; 647 return;
620 648
621 DCHECK(loader_.get()); 649 if (error != net::OK) {
622
623 if (error == net::OK) {
624 total_bytes_ = loader_->content_length();
625 // TODO(hclam): Figure out what to do when total bytes is not known.
626 if (total_bytes_ >= 0) {
627 host()->SetTotalBytes(total_bytes_);
628
629 // This value governs the range that we can seek to.
630 // TODO(hclam): Report the correct value of buffered bytes.
631 host()->SetBufferedBytes(total_bytes_);
632 }
633 } else {
634 // TODO(hclam): In case of failure, we can retry several times. 650 // TODO(hclam): In case of failure, we can retry several times.
635 // Also it might be bad to access host() here.
636 host()->SetError(media::PIPELINE_ERROR_NETWORK); 651 host()->SetError(media::PIPELINE_ERROR_NETWORK);
637 652 DCHECK(loader_.get());
638 // Stops the loader, just to be safe. 653 DCHECK(probe_loader_.get());
639 loader_->Stop(); 654 loader_->Stop();
655 probe_loader_->Stop();
656 DoneInitialization();
657 return;
640 } 658 }
641 659
642 DoneInitialization(); 660 total_bytes_ = loader_->instance_size();
661 if (total_bytes_ >= 0) {
662 // This value governs the range that we can seek to.
663 // TODO(hclam): Report the correct value of buffered bytes.
664 host()->SetTotalBytes(total_bytes_);
665 host()->SetBufferedBytes(total_bytes_);
666 } else {
667 // If the server didn't reply with a content length, it is likely this
668 // is a streaming response.
669 streaming_ = true;
670 host()->SetStreaming(true);
671 }
672
673 initial_response_received_ = true;
674 if (probe_response_received_)
675 DoneInitialization();
676 }
677
678 void BufferedDataSource::ProbeStartCallback(int error) {
679 DCHECK(MessageLoop::current() == render_loop_);
680
681 // We need to prevent calling to filter host and running the callback if
682 // we have received the stop signal. We need to lock down the whole callback
683 // method to prevent bad things from happening. The reason behind this is
684 // that we cannot guarantee tasks on render thread have completely stopped
685 // when we receive the Stop() method call. The only way to solve this is to
686 // let tasks on render thread to run but make sure they don't call outside
687 // this object when Stop() method is ever called. Locking this method is safe
688 // because |lock_| is only acquired in tasks on render thread.
689 AutoLock auto_lock(lock_);
690 if (stopped_)
691 return;
692
693 if (error != net::OK) {
694 streaming_ = true;
695 host()->SetStreaming(true);
696 }
697
698 DCHECK(probe_loader_.get());
699 probe_loader_->Stop();
700 probe_response_received_ = true;
701 if (initial_response_received_)
702 DoneInitialization();
643 } 703 }
644 704
645 void BufferedDataSource::PartialReadStartCallback(int error) { 705 void BufferedDataSource::PartialReadStartCallback(int error) {
646 DCHECK(MessageLoop::current() == render_loop_); 706 DCHECK(MessageLoop::current() == render_loop_);
647 DCHECK(loader_.get()); 707 DCHECK(loader_.get());
648 708
649 if (error == net::OK) { 709 if (error == net::OK) {
650 // Once the range request has start successfully, we can proceed with 710 // Once the range request has start successfully, we can proceed with
651 // reading from it. 711 // reading from it.
652 ReadInternal(); 712 ReadInternal();
653 } else { 713 } else {
714 loader_->Stop();
715
654 // We need to prevent calling to filter host and running the callback if 716 // We need to prevent calling to filter host and running the callback if
655 // we have received the stop signal. We need to lock down the whole callback 717 // we have received the stop signal. We need to lock down the whole callback
656 // method to prevent bad things from happening. The reason behind this is 718 // method to prevent bad things from happening. The reason behind this is
657 // that we cannot guarantee tasks on render thread have completely stopped 719 // that we cannot guarantee tasks on render thread have completely stopped
658 // when we receive the Stop() method call. So only way to solve this is to 720 // when we receive the Stop() method call. So only way to solve this is to
659 // let tasks on render thread to run but make sure they don't call outside 721 // let tasks on render thread to run but make sure they don't call outside
660 // this object when Stop() method is ever called. Locking this method is 722 // this object when Stop() method is ever called. Locking this method is
661 // safe because |lock_| is only acquired in tasks on render thread. 723 // safe because |lock_| is only acquired in tasks on render thread.
662 AutoLock auto_lock(lock_); 724 AutoLock auto_lock(lock_);
663 if (stopped_) 725 if (stopped_)
664 return; 726 return;
665 727 DoneRead(net::ERR_INVALID_RESPONSE);
666 // TODO(hclam): It may be bad to access host() here.
667 host()->SetError(media::PIPELINE_ERROR_NETWORK);
668
669 // Kill the loader just to be safe.
670 loader_->Stop();
671 } 728 }
672 } 729 }
673 730
674 void BufferedDataSource::ReadCallback(int error) { 731 void BufferedDataSource::ReadCallback(int error) {
675 DCHECK(MessageLoop::current() == render_loop_); 732 DCHECK(MessageLoop::current() == render_loop_);
676 733
677 // We need to prevent calling to filter host and running the callback if 734 // We need to prevent calling to filter host and running the callback if
678 // we have received the stop signal. We need to lock down the whole callback 735 // we have received the stop signal. We need to lock down the whole callback
679 // method to prevent bad things from happening. The reason behind this is 736 // method to prevent bad things from happening. The reason behind this is
680 // that we cannot guarantee tasks on render thread have completely stopped 737 // that we cannot guarantee tasks on render thread have completely stopped
681 // when we receive the Stop() method call. So only way to solve this is to 738 // when we receive the Stop() method call. So only way to solve this is to
682 // let tasks on render thread to run but make sure they don't call outside 739 // let tasks on render thread to run but make sure they don't call outside
683 // this object when Stop() method is ever called. Locking this method is safe 740 // this object when Stop() method is ever called. Locking this method is safe
684 // because |lock_| is only acquired in tasks on render thread. 741 // because |lock_| is only acquired in tasks on render thread.
685 AutoLock auto_lock(lock_); 742 AutoLock auto_lock(lock_);
686 if (stopped_) 743 if (stopped_)
687 return; 744 return;
688 745
689 DCHECK(loader_.get()); 746 DCHECK(loader_.get());
690 DCHECK(read_callback_.get()); 747 DCHECK(read_callback_.get());
691 748
692 if (error >= 0) { 749 if (error >= 0) {
693 // If a position error code is received, read was successful. So copy 750 // If a position error code is received, read was successful. So copy
694 // from intermediate read buffer to the target read buffer. 751 // from intermediate read buffer to the target read buffer.
695 memcpy(read_buffer_, intermediate_read_buffer_.get(), error); 752 memcpy(read_buffer_, intermediate_read_buffer_.get(), error);
696
697 DoneRead(error); 753 DoneRead(error);
698 } else if (error == net::ERR_CACHE_MISS) { 754 } else if (error == net::ERR_CACHE_MISS) {
699 // If the current loader cannot serve this read request, we need to create 755 // If the current loader cannot serve this read request, we need to create
700 // a new one. 756 // a new one.
701 // We have the following conditions:
702 // 1. Read is beyond the content length of the file (if known).
703 // 2. We have tried too many times (TODO here).
704 if (read_position_ >= total_bytes_) {
705 DoneRead(0);
706 return;
707 }
708
709 // TODO(hclam): we need to count how many times it failed to prevent 757 // TODO(hclam): we need to count how many times it failed to prevent
710 // excessive trials. 758 // excessive trials.
711 759
712 // Stops the current resource loader. 760 // Stops the current resource loader.
713 loader_->Stop(); 761 loader_->Stop();
714 762
715 // Since this method is called from the current buffered resource loader, 763 // Since this method is called from the current buffered resource loader,
716 // we cannot delete it. So we need to post a task to swap in a new 764 // we cannot delete it. So we need to post a task to swap in a new
717 // resource loader and starts it. 765 // resource loader and starts it.
718 render_loop_->PostTask(FROM_HERE, 766 render_loop_->PostTask(FROM_HERE,
719 NewRunnableMethod(this, 767 NewRunnableMethod(this, &BufferedDataSource::SwapLoaderTask,
720 &BufferedDataSource::SwapLoaderTask,
721 CreateLoader(read_position_, -1))); 768 CreateLoader(read_position_, -1)));
722 } else { 769 } else {
723 // The read has finished with error. 770 loader_->Stop();
724 DoneRead(error); 771 DoneRead(error);
725
726 // TODO(hclam): It may be bad to access host() here.
727 host()->SetError(media::PIPELINE_ERROR_NETWORK);
728
729 // Stops the laoder.
730 loader_->Stop();
731 } 772 }
732 } 773 }
733 774
734 } // namespace webkit_glue 775 } // 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