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

Side by Side Diff: media/filters/chunk_demuxer.cc

Issue 16867010: Move pending seek cancellation logic from ChunkDemuxerStream to ChunkDemuxer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address CR comments Created 7 years, 6 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
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/chunk_demuxer.h" 5 #include "media/filters/chunk_demuxer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <deque> 8 #include <deque>
9 #include <limits> 9 #include <limits>
10 10
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 198 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
199 typedef std::deque<ReadCB> ReadCBQueue; 199 typedef std::deque<ReadCB> ReadCBQueue;
200 typedef std::deque<base::Closure> ClosureQueue; 200 typedef std::deque<base::Closure> ClosureQueue;
201 201
202 ChunkDemuxerStream(const AudioDecoderConfig& audio_config, 202 ChunkDemuxerStream(const AudioDecoderConfig& audio_config,
203 const LogCB& log_cb); 203 const LogCB& log_cb);
204 ChunkDemuxerStream(const VideoDecoderConfig& video_config, 204 ChunkDemuxerStream(const VideoDecoderConfig& video_config,
205 const LogCB& log_cb); 205 const LogCB& log_cb);
206 virtual ~ChunkDemuxerStream(); 206 virtual ~ChunkDemuxerStream();
207 207
208 void StartWaitingForSeek(); 208 void AbortReads();
209 void Seek(TimeDelta time); 209 void Seek(TimeDelta time);
210 void CancelPendingSeek();
211 bool IsSeekWaitingForData() const; 210 bool IsSeekWaitingForData() const;
212 211
213 // Add buffers to this stream. Buffers are stored in SourceBufferStreams, 212 // Add buffers to this stream. Buffers are stored in SourceBufferStreams,
214 // which handle ordering and overlap resolution. 213 // which handle ordering and overlap resolution.
215 // Returns true if buffers were successfully added. 214 // Returns true if buffers were successfully added.
216 bool Append(const StreamParser::BufferQueue& buffers); 215 bool Append(const StreamParser::BufferQueue& buffers);
217 216
218 // Signal to the stream that duration has changed to |duration|. 217 // Signal to the stream that duration has changed to |duration|.
219 void OnSetDuration(TimeDelta duration); 218 void OnSetDuration(TimeDelta duration);
220 219
(...skipping 17 matching lines...) Expand all
238 237
239 // DemuxerStream methods. 238 // DemuxerStream methods.
240 virtual void Read(const ReadCB& read_cb) OVERRIDE; 239 virtual void Read(const ReadCB& read_cb) OVERRIDE;
241 virtual Type type() OVERRIDE; 240 virtual Type type() OVERRIDE;
242 virtual void EnableBitstreamConverter() OVERRIDE; 241 virtual void EnableBitstreamConverter() OVERRIDE;
243 virtual AudioDecoderConfig audio_decoder_config() OVERRIDE; 242 virtual AudioDecoderConfig audio_decoder_config() OVERRIDE;
244 virtual VideoDecoderConfig video_decoder_config() OVERRIDE; 243 virtual VideoDecoderConfig video_decoder_config() OVERRIDE;
245 244
246 private: 245 private:
247 enum State { 246 enum State {
247 UNINITIALIZED,
248 RETURNING_DATA_FOR_READS, 248 RETURNING_DATA_FOR_READS,
249 WAITING_FOR_SEEK, 249 RETURNING_ABORT_FOR_READS,
250 CANCELED,
251 SHUTDOWN, 250 SHUTDOWN,
252 }; 251 };
253 252
254 // Assigns |state_| to |state| 253 // Assigns |state_| to |state|
255 void ChangeState_Locked(State state); 254 void ChangeState_Locked(State state);
256 255
257 // Adds the callback to |read_cbs_| so it can be called later when we 256 // Adds the callback to |read_cbs_| so it can be called later when we
258 // have data. 257 // have data.
259 void DeferRead_Locked(const ReadCB& read_cb); 258 void DeferRead_Locked(const ReadCB& read_cb);
260 259
(...skipping 15 matching lines...) Expand all
276 mutable base::Lock lock_; 275 mutable base::Lock lock_;
277 State state_; 276 State state_;
278 ReadCBQueue read_cbs_; 277 ReadCBQueue read_cbs_;
279 278
280 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); 279 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream);
281 }; 280 };
282 281
283 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config, 282 ChunkDemuxerStream::ChunkDemuxerStream(const AudioDecoderConfig& audio_config,
284 const LogCB& log_cb) 283 const LogCB& log_cb)
285 : type_(AUDIO), 284 : type_(AUDIO),
286 state_(RETURNING_DATA_FOR_READS) { 285 state_(UNINITIALIZED) {
287 stream_.reset(new SourceBufferStream(audio_config, log_cb)); 286 stream_.reset(new SourceBufferStream(audio_config, log_cb));
288 } 287 }
289 288
290 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config, 289 ChunkDemuxerStream::ChunkDemuxerStream(const VideoDecoderConfig& video_config,
291 const LogCB& log_cb) 290 const LogCB& log_cb)
292 : type_(VIDEO), 291 : type_(VIDEO),
293 state_(RETURNING_DATA_FOR_READS) { 292 state_(UNINITIALIZED) {
294 stream_.reset(new SourceBufferStream(video_config, log_cb)); 293 stream_.reset(new SourceBufferStream(video_config, log_cb));
295 } 294 }
296 295
297 void ChunkDemuxerStream::StartWaitingForSeek() { 296 void ChunkDemuxerStream::AbortReads() {
298 DVLOG(1) << "ChunkDemuxerStream::StartWaitingForSeek()"; 297 DVLOG(1) << "ChunkDemuxerStream::AbortReads()";
299 ReadCBQueue read_cbs; 298 ReadCBQueue read_cbs;
300 { 299 {
301 base::AutoLock auto_lock(lock_); 300 base::AutoLock auto_lock(lock_);
302 ChangeState_Locked(WAITING_FOR_SEEK); 301 ChangeState_Locked(RETURNING_ABORT_FOR_READS);
303 std::swap(read_cbs_, read_cbs); 302 std::swap(read_cbs_, read_cbs);
304 } 303 }
305 304
306 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it) 305 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it)
307 it->Run(kAborted, NULL); 306 it->Run(kAborted, NULL);
308 } 307 }
309 308
310 void ChunkDemuxerStream::Seek(TimeDelta time) { 309 void ChunkDemuxerStream::Seek(TimeDelta time) {
311 base::AutoLock auto_lock(lock_); 310 base::AutoLock auto_lock(lock_);
312
313 DCHECK(read_cbs_.empty()); 311 DCHECK(read_cbs_.empty());
314 312 DCHECK(state_ == UNINITIALIZED || state_ == RETURNING_ABORT_FOR_READS);
315 // Ignore seek requests when canceled.
316 if (state_ == CANCELED)
317 return;
318 313
319 stream_->Seek(time); 314 stream_->Seek(time);
320 315 ChangeState_Locked(RETURNING_DATA_FOR_READS);
321 if (state_ == WAITING_FOR_SEEK)
322 ChangeState_Locked(RETURNING_DATA_FOR_READS);
323 }
324
325 void ChunkDemuxerStream::CancelPendingSeek() {
326 DVLOG(1) << "ChunkDemuxerStream::CancelPendingSeek()";
327 ReadCBQueue read_cbs;
328 {
329 base::AutoLock auto_lock(lock_);
330 ChangeState_Locked(CANCELED);
331 std::swap(read_cbs_, read_cbs);
332 }
333
334 for (ReadCBQueue::iterator it = read_cbs.begin(); it != read_cbs.end(); ++it)
335 it->Run(kAborted, NULL);
336 } 316 }
337 317
338 bool ChunkDemuxerStream::IsSeekWaitingForData() const { 318 bool ChunkDemuxerStream::IsSeekWaitingForData() const {
339 base::AutoLock auto_lock(lock_); 319 base::AutoLock auto_lock(lock_);
340 return stream_->IsSeekPending(); 320 return stream_->IsSeekPending();
341 } 321 }
342 322
343 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) { 323 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) {
344 base::AutoLock auto_lock(lock_); 324 base::AutoLock auto_lock(lock_);
345 stream_->OnNewMediaSegment(start_timestamp); 325 stream_->OnNewMediaSegment(start_timestamp);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 message_loop_proxy->PostTask(FROM_HERE, base::Bind( 422 message_loop_proxy->PostTask(FROM_HERE, base::Bind(
443 &RunOnMessageLoop, read_cb, message_loop_proxy, status, buffer)); 423 &RunOnMessageLoop, read_cb, message_loop_proxy, status, buffer));
444 return; 424 return;
445 } 425 }
446 426
447 read_cb.Run(status, buffer); 427 read_cb.Run(status, buffer);
448 } 428 }
449 429
450 // DemuxerStream methods. 430 // DemuxerStream methods.
451 void ChunkDemuxerStream::Read(const ReadCB& read_cb) { 431 void ChunkDemuxerStream::Read(const ReadCB& read_cb) {
432 base::AutoLock auto_lock(lock_);
433 DCHECK_NE(state_, UNINITIALIZED);
434
452 DemuxerStream::Status status = kOk; 435 DemuxerStream::Status status = kOk;
453 scoped_refptr<StreamParserBuffer> buffer; 436 scoped_refptr<StreamParserBuffer> buffer;
454 { 437
455 base::AutoLock auto_lock(lock_); 438 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&status, &buffer)) {
456 if (!read_cbs_.empty() || !GetNextBuffer_Locked(&status, &buffer)) { 439 DeferRead_Locked(read_cb);
457 DeferRead_Locked(read_cb); 440 return;
458 return;
459 }
460 } 441 }
461 442
462 base::MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind( 443 base::MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind(
463 read_cb, status, buffer)); 444 read_cb, status, buffer));
464 } 445 }
465 446
466 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; } 447 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; }
467 448
468 void ChunkDemuxerStream::EnableBitstreamConverter() {} 449 void ChunkDemuxerStream::EnableBitstreamConverter() {}
469 450
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 read_cbs_.pop_front(); 494 read_cbs_.pop_front();
514 } 495 }
515 } 496 }
516 497
517 bool ChunkDemuxerStream::GetNextBuffer_Locked( 498 bool ChunkDemuxerStream::GetNextBuffer_Locked(
518 DemuxerStream::Status* status, 499 DemuxerStream::Status* status,
519 scoped_refptr<StreamParserBuffer>* buffer) { 500 scoped_refptr<StreamParserBuffer>* buffer) {
520 lock_.AssertAcquired(); 501 lock_.AssertAcquired();
521 502
522 switch (state_) { 503 switch (state_) {
504 case UNINITIALIZED:
505 NOTREACHED();
506 return false;
523 case RETURNING_DATA_FOR_READS: 507 case RETURNING_DATA_FOR_READS:
524 switch (stream_->GetNextBuffer(buffer)) { 508 switch (stream_->GetNextBuffer(buffer)) {
525 case SourceBufferStream::kSuccess: 509 case SourceBufferStream::kSuccess:
526 *status = DemuxerStream::kOk; 510 *status = DemuxerStream::kOk;
527 return true; 511 return true;
528 case SourceBufferStream::kNeedBuffer: 512 case SourceBufferStream::kNeedBuffer:
529 return false; 513 return false;
530 case SourceBufferStream::kEndOfStream: 514 case SourceBufferStream::kEndOfStream:
531 *status = DemuxerStream::kOk; 515 *status = DemuxerStream::kOk;
532 *buffer = StreamParserBuffer::CreateEOSBuffer(); 516 *buffer = StreamParserBuffer::CreateEOSBuffer();
533 return true; 517 return true;
534 case SourceBufferStream::kConfigChange: 518 case SourceBufferStream::kConfigChange:
535 DVLOG(2) << "Config change reported to ChunkDemuxerStream."; 519 DVLOG(2) << "Config change reported to ChunkDemuxerStream.";
536 *status = kConfigChanged; 520 *status = kConfigChanged;
537 *buffer = NULL; 521 *buffer = NULL;
538 return true; 522 return true;
539 } 523 }
540 break; 524 break;
541 case CANCELED: 525 case RETURNING_ABORT_FOR_READS:
542 case WAITING_FOR_SEEK:
543 // Null buffers should be returned in this state since we are waiting 526 // Null buffers should be returned in this state since we are waiting
544 // for a seek. Any buffers in the SourceBuffer should NOT be returned 527 // for a seek. Any buffers in the SourceBuffer should NOT be returned
545 // because they are associated with the seek. 528 // because they are associated with the seek.
546 DCHECK(read_cbs_.empty()); 529 DCHECK(read_cbs_.empty());
547 *status = DemuxerStream::kAborted; 530 *status = DemuxerStream::kAborted;
548 *buffer = NULL; 531 *buffer = NULL;
549 return true; 532 return true;
550 case SHUTDOWN: 533 case SHUTDOWN:
551 DCHECK(read_cbs_.empty()); 534 DCHECK(read_cbs_.empty());
552 *status = DemuxerStream::kOk; 535 *status = DemuxerStream::kOk;
553 *buffer = StreamParserBuffer::CreateEOSBuffer(); 536 *buffer = StreamParserBuffer::CreateEOSBuffer();
554 return true; 537 return true;
555 } 538 }
556 539
557 NOTREACHED(); 540 NOTREACHED();
558 return false; 541 return false;
559 } 542 }
560 543
561 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb, 544 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb,
562 const NeedKeyCB& need_key_cb, 545 const NeedKeyCB& need_key_cb,
563 const AddTextTrackCB& add_text_track_cb, 546 const AddTextTrackCB& add_text_track_cb,
564 const LogCB& log_cb) 547 const LogCB& log_cb)
565 : state_(WAITING_FOR_INIT), 548 : state_(WAITING_FOR_INIT),
549 cancel_next_seek_(false),
566 host_(NULL), 550 host_(NULL),
567 open_cb_(open_cb), 551 open_cb_(open_cb),
568 need_key_cb_(need_key_cb), 552 need_key_cb_(need_key_cb),
569 add_text_track_cb_(add_text_track_cb), 553 add_text_track_cb_(add_text_track_cb),
570 log_cb_(log_cb), 554 log_cb_(log_cb),
571 duration_(kNoTimestamp()), 555 duration_(kNoTimestamp()),
572 user_specified_duration_(-1) { 556 user_specified_duration_(-1) {
573 DCHECK(!open_cb_.is_null()); 557 DCHECK(!open_cb_.is_null());
574 DCHECK(!need_key_cb_.is_null()); 558 DCHECK(!need_key_cb_.is_null());
575 } 559 }
(...skipping 18 matching lines...) Expand all
594 578
595 void ChunkDemuxer::Stop(const base::Closure& callback) { 579 void ChunkDemuxer::Stop(const base::Closure& callback) {
596 DVLOG(1) << "Stop()"; 580 DVLOG(1) << "Stop()";
597 Shutdown(); 581 Shutdown();
598 callback.Run(); 582 callback.Run();
599 } 583 }
600 584
601 void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) { 585 void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) {
602 DVLOG(1) << "Seek(" << time.InSecondsF() << ")"; 586 DVLOG(1) << "Seek(" << time.InSecondsF() << ")";
603 DCHECK(time >= TimeDelta()); 587 DCHECK(time >= TimeDelta());
588
589 base::AutoLock auto_lock(lock_);
604 DCHECK(seek_cb_.is_null()); 590 DCHECK(seek_cb_.is_null());
605 591
606 PipelineStatus status = PIPELINE_ERROR_INVALID_STATE;
607 base::AutoLock auto_lock(lock_);
608
609 seek_cb_ = BindToCurrentLoop(cb); 592 seek_cb_ = BindToCurrentLoop(cb);
610 if (state_ == INITIALIZED || state_ == ENDED) { 593 if (state_ != INITIALIZED && state_ != ENDED) {
611 if (audio_) 594 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_INVALID_STATE);
612 audio_->Seek(time); 595 return;
613
614 if (video_)
615 video_->Seek(time);
616
617 if (IsSeekWaitingForData_Locked()) {
618 DVLOG(1) << "Seek() : waiting for more data to arrive.";
619 return;
620 }
621
622 status = PIPELINE_OK;
623 } 596 }
624 597
625 base::ResetAndReturn(&seek_cb_).Run(status); 598 if (cancel_next_seek_) {
599 cancel_next_seek_ = false;
600 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
601 return;
602 }
603
604 if (audio_)
605 audio_->Seek(time);
606
607 if (video_)
608 video_->Seek(time);
609
610 if (IsSeekWaitingForData_Locked()) {
611 DVLOG(1) << "Seek() : waiting for more data to arrive.";
612 return;
613 }
614
615 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
626 } 616 }
627 617
628 void ChunkDemuxer::OnAudioRendererDisabled() { 618 void ChunkDemuxer::OnAudioRendererDisabled() {
629 base::AutoLock auto_lock(lock_); 619 base::AutoLock auto_lock(lock_);
630 audio_->Shutdown(); 620 audio_->Shutdown();
631 disabled_audio_ = audio_.Pass(); 621 disabled_audio_ = audio_.Pass();
632 } 622 }
633 623
634 // Demuxer implementation. 624 // Demuxer implementation.
635 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) { 625 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) {
636 base::AutoLock auto_lock(lock_); 626 base::AutoLock auto_lock(lock_);
637 if (type == DemuxerStream::VIDEO) 627 if (type == DemuxerStream::VIDEO)
638 return video_.get(); 628 return video_.get();
639 629
640 if (type == DemuxerStream::AUDIO) 630 if (type == DemuxerStream::AUDIO)
641 return audio_.get(); 631 return audio_.get();
642 632
643 return NULL; 633 return NULL;
644 } 634 }
645 635
646 TimeDelta ChunkDemuxer::GetStartTime() const { 636 TimeDelta ChunkDemuxer::GetStartTime() const {
647 return TimeDelta(); 637 return TimeDelta();
648 } 638 }
649 639
650 void ChunkDemuxer::StartWaitingForSeek() { 640 void ChunkDemuxer::StartWaitingForSeek() {
651 DVLOG(1) << "StartWaitingForSeek()"; 641 DVLOG(1) << "StartWaitingForSeek()";
652 base::AutoLock auto_lock(lock_); 642 base::AutoLock auto_lock(lock_);
653 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN); 643 DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN);
644 DCHECK(seek_cb_.is_null());
654 645
655 if (state_ == SHUTDOWN) 646 if (state_ == SHUTDOWN)
656 return; 647 return;
657 648
658 if (audio_) 649 if (audio_)
659 audio_->StartWaitingForSeek(); 650 audio_->AbortReads();
660 651
661 if (video_) 652 if (video_)
662 video_->StartWaitingForSeek(); 653 video_->AbortReads();
654
655 // Cancel state set in CancelPendingSeek() since we want to
656 // accept the next Seek().
657 cancel_next_seek_ = false;
663 } 658 }
664 659
665 void ChunkDemuxer::CancelPendingSeek() { 660 void ChunkDemuxer::CancelPendingSeek() {
666 base::AutoLock auto_lock(lock_); 661 base::AutoLock auto_lock(lock_);
667 DCHECK(seek_cb_.is_null() != IsSeekWaitingForData_Locked()); 662 DCHECK_NE(state_, INITIALIZING);
663 DCHECK(seek_cb_.is_null() || IsSeekWaitingForData_Locked());
664
665 if (cancel_next_seek_)
666 return;
668 667
669 if (audio_) 668 if (audio_)
670 audio_->CancelPendingSeek(); 669 audio_->AbortReads();
671 670
672 if (video_) 671 if (video_)
673 video_->CancelPendingSeek(); 672 video_->AbortReads();
674 673
675 if (!seek_cb_.is_null()) 674 if (seek_cb_.is_null()) {
676 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); 675 cancel_next_seek_ = true;
676 return;
677 }
678
679 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
677 } 680 }
678 681
679 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, 682 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
680 const std::string& type, 683 const std::string& type,
681 std::vector<std::string>& codecs) { 684 std::vector<std::string>& codecs) {
682 DCHECK_GT(codecs.size(), 0u); 685 DCHECK_GT(codecs.size(), 0u);
683 base::AutoLock auto_lock(lock_); 686 base::AutoLock auto_lock(lock_);
684 687
685 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id)) 688 if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id))
686 return kReachedIdLimit; 689 return kReachedIdLimit;
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 } 1080 }
1078 1081
1079 if (duration != TimeDelta() && duration_ == kNoTimestamp()) 1082 if (duration != TimeDelta() && duration_ == kNoTimestamp())
1080 UpdateDuration(duration); 1083 UpdateDuration(duration);
1081 1084
1082 // Wait until all streams have initialized. 1085 // Wait until all streams have initialized.
1083 if ((!source_id_audio_.empty() && !audio_) || 1086 if ((!source_id_audio_.empty() && !audio_) ||
1084 (!source_id_video_.empty() && !video_)) 1087 (!source_id_video_.empty() && !video_))
1085 return; 1088 return;
1086 1089
1090 TimeDelta start_time = GetStartTime();
1087 if (audio_) 1091 if (audio_)
1088 audio_->Seek(TimeDelta()); 1092 audio_->Seek(start_time);
1089 1093
1090 if (video_) 1094 if (video_)
1091 video_->Seek(TimeDelta()); 1095 video_->Seek(start_time);
1092 1096
1093 if (duration_ == kNoTimestamp()) 1097 if (duration_ == kNoTimestamp())
1094 duration_ = kInfiniteDuration(); 1098 duration_ = kInfiniteDuration();
1095 1099
1096 // The demuxer is now initialized after the |start_timestamp_| was set. 1100 // The demuxer is now initialized after the |start_timestamp_| was set.
1097 ChangeState_Locked(INITIALIZED); 1101 ChangeState_Locked(INITIALIZED);
1098 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 1102 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
1099 } 1103 }
1100 1104
1101 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video, 1105 bool ChunkDemuxer::OnNewConfigs(bool has_audio, bool has_video,
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1276 1280
1277 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const { 1281 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const {
1278 if (audio_ && !video_) 1282 if (audio_ && !video_)
1279 return audio_->GetBufferedRanges(duration_); 1283 return audio_->GetBufferedRanges(duration_);
1280 else if (!audio_ && video_) 1284 else if (!audio_ && video_)
1281 return video_->GetBufferedRanges(duration_); 1285 return video_->GetBufferedRanges(duration_);
1282 return ComputeIntersection(); 1286 return ComputeIntersection();
1283 } 1287 }
1284 1288
1285 } // namespace media 1289 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698