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

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

Issue 110693007: Fix various operations in ChunkDemuxer that were not being applied to text tracks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address CR comment and added tests Created 6 years, 11 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) 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 #include <list> 10 #include <list>
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 const NewTextTrackCB& new_text_track_cb); 107 const NewTextTrackCB& new_text_track_cb);
108 108
109 // Appends new data to the StreamParser. 109 // Appends new data to the StreamParser.
110 // Returns true if the data was successfully appended. Returns false if an 110 // Returns true if the data was successfully appended. Returns false if an
111 // error occurred. 111 // error occurred.
112 bool Append(const uint8* data, size_t length); 112 bool Append(const uint8* data, size_t length);
113 113
114 // Aborts the current append sequence and resets the parser. 114 // Aborts the current append sequence and resets the parser.
115 void Abort(); 115 void Abort();
116 116
117 // Calls Remove(|start|, |end|, |duration|) on all
118 // ChunkDemuxerStreams managed by this object.
119 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration);
120
117 // Sets |timestamp_offset_| if possible. 121 // Sets |timestamp_offset_| if possible.
118 // Returns if the offset was set. Returns false if the offset could not be 122 // Returns if the offset was set. Returns false if the offset could not be
119 // updated at this time. 123 // updated at this time.
120 bool SetTimestampOffset(TimeDelta timestamp_offset); 124 bool SetTimestampOffset(TimeDelta timestamp_offset);
121 125
122 TimeDelta timestamp_offset() const { return timestamp_offset_; } 126 TimeDelta timestamp_offset() const { return timestamp_offset_; }
123 127
124 void set_append_window_start(TimeDelta start) { 128 void set_append_window_start(TimeDelta start) {
125 append_window_start_ = start; 129 append_window_start_ = start;
126 } 130 }
(...skipping 11 matching lines...) Expand all
138 142
139 // Helper methods that call methods with similar names on all the 143 // Helper methods that call methods with similar names on all the
140 // ChunkDemuxerStreams managed by this object. 144 // ChunkDemuxerStreams managed by this object.
141 void StartReturningData(); 145 void StartReturningData();
142 void AbortReads(); 146 void AbortReads();
143 void Seek(TimeDelta seek_time); 147 void Seek(TimeDelta seek_time);
144 void CompletePendingReadIfPossible(); 148 void CompletePendingReadIfPossible();
145 void OnSetDuration(TimeDelta duration); 149 void OnSetDuration(TimeDelta duration);
146 void MarkEndOfStream(); 150 void MarkEndOfStream();
147 void UnmarkEndOfStream(); 151 void UnmarkEndOfStream();
152 void Shutdown();
153 // Sets the memory limit on each stream. |memory_limit| is the
154 // maximum number of bytes each stream is allowed to hold in its buffer.
155 void SetMemoryLimitsForTesting(int memory_limit);
156 bool IsSeekWaitingForData() const;
148 157
149 private: 158 private:
150 // Called by the |stream_parser_| when a new initialization segment is 159 // Called by the |stream_parser_| when a new initialization segment is
151 // encountered. 160 // encountered.
152 // Returns true on a successful call. Returns false if an error occured while 161 // Returns true on a successful call. Returns false if an error occured while
153 // processing decoder configurations. 162 // processing decoder configurations.
154 bool OnNewConfigs(bool allow_audio, bool allow_video, 163 bool OnNewConfigs(bool allow_audio, bool allow_video,
155 const AudioDecoderConfig& audio_config, 164 const AudioDecoderConfig& audio_config,
156 const VideoDecoderConfig& video_config, 165 const VideoDecoderConfig& video_config,
157 const StreamParser::TextTrackConfigMap& text_configs); 166 const StreamParser::TextTrackConfigMap& text_configs);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 virtual void Read(const ReadCB& read_cb) OVERRIDE; 307 virtual void Read(const ReadCB& read_cb) OVERRIDE;
299 virtual Type type() OVERRIDE; 308 virtual Type type() OVERRIDE;
300 virtual void EnableBitstreamConverter() OVERRIDE; 309 virtual void EnableBitstreamConverter() OVERRIDE;
301 virtual AudioDecoderConfig audio_decoder_config() OVERRIDE; 310 virtual AudioDecoderConfig audio_decoder_config() OVERRIDE;
302 virtual VideoDecoderConfig video_decoder_config() OVERRIDE; 311 virtual VideoDecoderConfig video_decoder_config() OVERRIDE;
303 312
304 // Returns the text track configuration. It is an error to call this method 313 // Returns the text track configuration. It is an error to call this method
305 // if type() != TEXT. 314 // if type() != TEXT.
306 TextTrackConfig text_track_config(); 315 TextTrackConfig text_track_config();
307 316
317 // Sets the memory limit, in bytes, on the SourceBufferStream.
308 void set_memory_limit_for_testing(int memory_limit) { 318 void set_memory_limit_for_testing(int memory_limit) {
309 stream_->set_memory_limit_for_testing(memory_limit); 319 stream_->set_memory_limit_for_testing(memory_limit);
310 } 320 }
311 321
312 private: 322 private:
313 enum State { 323 enum State {
314 UNINITIALIZED, 324 UNINITIALIZED,
315 RETURNING_DATA_FOR_READS, 325 RETURNING_DATA_FOR_READS,
316 RETURNING_ABORT_FOR_READS, 326 RETURNING_ABORT_FOR_READS,
317 SHUTDOWN, 327 SHUTDOWN,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 audio_(NULL), 363 audio_(NULL),
354 audio_needs_keyframe_(true), 364 audio_needs_keyframe_(true),
355 video_(NULL), 365 video_(NULL),
356 video_needs_keyframe_(true), 366 video_needs_keyframe_(true),
357 log_cb_(log_cb) { 367 log_cb_(log_cb) {
358 DCHECK(!create_demuxer_stream_cb_.is_null()); 368 DCHECK(!create_demuxer_stream_cb_.is_null());
359 DCHECK(!increase_duration_cb_.is_null()); 369 DCHECK(!increase_duration_cb_.is_null());
360 } 370 }
361 371
362 SourceState::~SourceState() { 372 SourceState::~SourceState() {
363 if (audio_) 373 Shutdown();
364 audio_->Shutdown();
365 374
366 if (video_) 375 STLDeleteValues(&text_stream_map_);
367 video_->Shutdown();
368
369 for (TextStreamMap::iterator itr = text_stream_map_.begin();
370 itr != text_stream_map_.end(); ++itr) {
371 itr->second->Shutdown();
372 delete itr->second;
373 }
374 } 376 }
375 377
376 void SourceState::Init(const StreamParser::InitCB& init_cb, 378 void SourceState::Init(const StreamParser::InitCB& init_cb,
377 bool allow_audio, 379 bool allow_audio,
378 bool allow_video, 380 bool allow_video,
379 const StreamParser::NeedKeyCB& need_key_cb, 381 const StreamParser::NeedKeyCB& need_key_cb,
380 const NewTextTrackCB& new_text_track_cb) { 382 const NewTextTrackCB& new_text_track_cb) {
381 new_text_track_cb_ = new_text_track_cb; 383 new_text_track_cb_ = new_text_track_cb;
382 384
383 StreamParser::NewTextBuffersCB new_text_buffers_cb; 385 StreamParser::NewTextBuffersCB new_text_buffers_cb;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 return stream_parser_->Parse(data, length); 417 return stream_parser_->Parse(data, length);
416 } 418 }
417 419
418 void SourceState::Abort() { 420 void SourceState::Abort() {
419 stream_parser_->Flush(); 421 stream_parser_->Flush();
420 audio_needs_keyframe_ = true; 422 audio_needs_keyframe_ = true;
421 video_needs_keyframe_ = true; 423 video_needs_keyframe_ = true;
422 can_update_offset_ = true; 424 can_update_offset_ = true;
423 } 425 }
424 426
427 void SourceState::Remove(TimeDelta start, TimeDelta end, TimeDelta duration) {
428 if (audio_)
429 audio_->Remove(start, end, duration);
430
431 if (video_)
432 video_->Remove(start, end, duration);
433
434 for (TextStreamMap::iterator itr = text_stream_map_.begin();
435 itr != text_stream_map_.end(); ++itr) {
436 itr->second->Remove(start, end, duration);
437 }
438 }
439
425 Ranges<TimeDelta> SourceState::GetBufferedRanges(TimeDelta duration, 440 Ranges<TimeDelta> SourceState::GetBufferedRanges(TimeDelta duration,
426 bool ended) const { 441 bool ended) const {
427 // TODO(acolwell): When we start allowing disabled tracks we'll need to update 442 // TODO(acolwell): When we start allowing disabled tracks we'll need to update
428 // this code to only add ranges from active tracks. 443 // this code to only add ranges from active tracks.
429 RangesList ranges_list; 444 RangesList ranges_list;
430 if (audio_) 445 if (audio_)
431 ranges_list.push_back(audio_->GetBufferedRanges(duration)); 446 ranges_list.push_back(audio_->GetBufferedRanges(duration));
432 447
433 if (video_) 448 if (video_)
434 ranges_list.push_back(video_->GetBufferedRanges(duration)); 449 ranges_list.push_back(video_->GetBufferedRanges(duration));
435 450
436 for (TextStreamMap::const_iterator itr = text_stream_map_.begin(); 451 for (TextStreamMap::const_iterator itr = text_stream_map_.begin();
437 itr != text_stream_map_.end(); ++itr) { 452 itr != text_stream_map_.end(); ++itr) {
438 ranges_list.push_back(itr->second->GetBufferedRanges(duration)); 453 ranges_list.push_back(itr->second->GetBufferedRanges(duration));
439 } 454 }
440 455
441 return ComputeIntersection(ranges_list, ended); 456 return ComputeIntersection(ranges_list, ended);
442 } 457 }
443 458
444 TimeDelta SourceState::GetMaxBufferedDuration() const { 459 TimeDelta SourceState::GetMaxBufferedDuration() const {
445 TimeDelta max_duration; 460 TimeDelta max_duration;
446 461
447 if (audio_) 462 if (audio_)
448 max_duration = std::max(max_duration, audio_->GetBufferedDuration()); 463 max_duration = std::max(max_duration, audio_->GetBufferedDuration());
449 464
450 if (video_) 465 if (video_)
451 max_duration = std::max(max_duration, video_->GetBufferedDuration()); 466 max_duration = std::max(max_duration, video_->GetBufferedDuration());
452 467
453 468
xhwang 2014/01/08 19:03:26 nit: drop an extra empty line?
acolwell GONE FROM CHROMIUM 2014/01/09 00:21:13 Done.
454 for (TextStreamMap::const_iterator itr = text_stream_map_.begin(); 469 for (TextStreamMap::const_iterator itr = text_stream_map_.begin();
455 itr != text_stream_map_.end(); ++itr) { 470 itr != text_stream_map_.end(); ++itr) {
456 max_duration = std::max(max_duration, itr->second->GetBufferedDuration()); 471 max_duration = std::max(max_duration, itr->second->GetBufferedDuration());
457 } 472 }
458 473
459 return max_duration; 474 return max_duration;
460 } 475 }
461 476
462 void SourceState::StartReturningData() { 477 void SourceState::StartReturningData() {
463 if (audio_) 478 if (audio_)
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 558
544 if (video_) 559 if (video_)
545 video_->UnmarkEndOfStream(); 560 video_->UnmarkEndOfStream();
546 561
547 for (TextStreamMap::iterator itr = text_stream_map_.begin(); 562 for (TextStreamMap::iterator itr = text_stream_map_.begin();
548 itr != text_stream_map_.end(); ++itr) { 563 itr != text_stream_map_.end(); ++itr) {
549 itr->second->UnmarkEndOfStream(); 564 itr->second->UnmarkEndOfStream();
550 } 565 }
551 } 566 }
552 567
568 void SourceState::Shutdown() {
569 if (audio_)
570 audio_->Shutdown();
571
572 if (video_)
573 video_->Shutdown();
574
575 for (TextStreamMap::iterator itr = text_stream_map_.begin();
576 itr != text_stream_map_.end(); ++itr) {
577 itr->second->Shutdown();
578 }
579 }
580
581 void SourceState::SetMemoryLimitsForTesting(int memory_limit) {
582 if (audio_)
583 audio_->set_memory_limit_for_testing(memory_limit);
584
585 if (video_)
586 video_->set_memory_limit_for_testing(memory_limit);
587
588 for (TextStreamMap::iterator itr = text_stream_map_.begin();
589 itr != text_stream_map_.end(); ++itr) {
590 itr->second->set_memory_limit_for_testing(memory_limit);
591 }
592 }
593
594 bool SourceState::IsSeekWaitingForData() const {
595 if (audio_ && audio_->IsSeekWaitingForData())
596 return true;
597
598 if (video_ && video_->IsSeekWaitingForData())
599 return true;
600
601 // NOTE: We are intentionally not checking the text tracks
602 // because text tracks are discontinuous and may not have data
603 // for the seek position. This is ok and playback should not be
604 // stalled because we don't have cues. If cues, with timestamps after
605 // the seek time, eventually arrive they will be delivered properly
606 // in response to ChunkDemuxerStream::Read() calls.
607
608 return false;
609 }
610
553 void SourceState::AdjustBufferTimestamps( 611 void SourceState::AdjustBufferTimestamps(
554 const StreamParser::BufferQueue& buffers) { 612 const StreamParser::BufferQueue& buffers) {
555 if (timestamp_offset_ == TimeDelta()) 613 if (timestamp_offset_ == TimeDelta())
556 return; 614 return;
557 615
558 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); 616 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
559 itr != buffers.end(); ++itr) { 617 itr != buffers.end(); ++itr) {
560 (*itr)->SetDecodeTimestamp( 618 (*itr)->SetDecodeTimestamp(
561 (*itr)->GetDecodeTimestamp() + timestamp_offset_); 619 (*itr)->GetDecodeTimestamp() + timestamp_offset_);
562 (*itr)->set_timestamp((*itr)->timestamp() + timestamp_offset_); 620 (*itr)->set_timestamp((*itr)->timestamp() + timestamp_offset_);
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 // Pass an end of stream buffer to the pending callback to signal that no more 935 // Pass an end of stream buffer to the pending callback to signal that no more
878 // data will be sent. 936 // data will be sent.
879 if (!read_cb_.is_null()) { 937 if (!read_cb_.is_null()) {
880 base::ResetAndReturn(&read_cb_).Run(DemuxerStream::kOk, 938 base::ResetAndReturn(&read_cb_).Run(DemuxerStream::kOk,
881 StreamParserBuffer::CreateEOSBuffer()); 939 StreamParserBuffer::CreateEOSBuffer());
882 } 940 }
883 } 941 }
884 942
885 bool ChunkDemuxerStream::IsSeekWaitingForData() const { 943 bool ChunkDemuxerStream::IsSeekWaitingForData() const {
886 base::AutoLock auto_lock(lock_); 944 base::AutoLock auto_lock(lock_);
945
946 // This method should not be called for text tracks. See the note in
947 // SourceState::IsSeekWaitingForData().
948 DCHECK_NE(type_, DemuxerStream::TEXT);
949
887 return stream_->IsSeekPending(); 950 return stream_->IsSeekPending();
888 } 951 }
889 952
890 void ChunkDemuxerStream::Seek(TimeDelta time) { 953 void ChunkDemuxerStream::Seek(TimeDelta time) {
891 DVLOG(1) << "ChunkDemuxerStream::Seek(" << time.InSecondsF() << ")"; 954 DVLOG(1) << "ChunkDemuxerStream::Seek(" << time.InSecondsF() << ")";
892 base::AutoLock auto_lock(lock_); 955 base::AutoLock auto_lock(lock_);
893 DCHECK(read_cb_.is_null()); 956 DCHECK(read_cb_.is_null());
894 DCHECK(state_ == UNINITIALIZED || state_ == RETURNING_ABORT_FOR_READS) 957 DCHECK(state_ == UNINITIALIZED || state_ == RETURNING_ABORT_FOR_READS)
895 << state_; 958 << state_;
896 959
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
1375 } 1438 }
1376 1439
1377 void ChunkDemuxer::Abort(const std::string& id) { 1440 void ChunkDemuxer::Abort(const std::string& id) {
1378 DVLOG(1) << "Abort(" << id << ")"; 1441 DVLOG(1) << "Abort(" << id << ")";
1379 base::AutoLock auto_lock(lock_); 1442 base::AutoLock auto_lock(lock_);
1380 DCHECK(!id.empty()); 1443 DCHECK(!id.empty());
1381 CHECK(IsValidId(id)); 1444 CHECK(IsValidId(id));
1382 source_state_map_[id]->Abort(); 1445 source_state_map_[id]->Abort();
1383 } 1446 }
1384 1447
1385 void ChunkDemuxer::Remove(const std::string& id, base::TimeDelta start, 1448 void ChunkDemuxer::Remove(const std::string& id, TimeDelta start,
1386 base::TimeDelta end) { 1449 TimeDelta end) {
1387 DVLOG(1) << "Remove(" << id << ", " << start.InSecondsF() 1450 DVLOG(1) << "Remove(" << id << ", " << start.InSecondsF()
1388 << ", " << end.InSecondsF() << ")"; 1451 << ", " << end.InSecondsF() << ")";
1389 base::AutoLock auto_lock(lock_); 1452 base::AutoLock auto_lock(lock_);
1390 1453
1391 if (id == source_id_audio_ && audio_) 1454 DCHECK(!id.empty());
1392 audio_->Remove(start, end, duration_); 1455 CHECK(IsValidId(id));
1393 1456 source_state_map_[id]->Remove(start, end, duration_);
1394 if (id == source_id_video_ && video_)
1395 video_->Remove(start, end, duration_);
1396 } 1457 }
1397 1458
1398 double ChunkDemuxer::GetDuration() { 1459 double ChunkDemuxer::GetDuration() {
1399 base::AutoLock auto_lock(lock_); 1460 base::AutoLock auto_lock(lock_);
1400 return GetDuration_Locked(); 1461 return GetDuration_Locked();
1401 } 1462 }
1402 1463
1403 double ChunkDemuxer::GetDuration_Locked() { 1464 double ChunkDemuxer::GetDuration_Locked() {
1404 lock_.AssertAcquired(); 1465 lock_.AssertAcquired();
1405 if (duration_ == kNoTimestamp()) 1466 if (duration_ == kNoTimestamp())
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 source_state_map_[id]->set_append_window_end(end); 1591 source_state_map_[id]->set_append_window_end(end);
1531 } 1592 }
1532 1593
1533 void ChunkDemuxer::Shutdown() { 1594 void ChunkDemuxer::Shutdown() {
1534 DVLOG(1) << "Shutdown()"; 1595 DVLOG(1) << "Shutdown()";
1535 base::AutoLock auto_lock(lock_); 1596 base::AutoLock auto_lock(lock_);
1536 1597
1537 if (state_ == SHUTDOWN) 1598 if (state_ == SHUTDOWN)
1538 return; 1599 return;
1539 1600
1540 if (audio_) 1601 ShutdownAllStreams();
1541 audio_->Shutdown();
1542
1543 if (video_)
1544 video_->Shutdown();
1545 1602
1546 ChangeState_Locked(SHUTDOWN); 1603 ChangeState_Locked(SHUTDOWN);
1547 1604
1548 if(!seek_cb_.is_null()) 1605 if(!seek_cb_.is_null())
1549 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_ABORT); 1606 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_ABORT);
1550 } 1607 }
1551 1608
1552 void ChunkDemuxer::SetMemoryLimitsForTesting(int memory_limit) { 1609 void ChunkDemuxer::SetMemoryLimitsForTesting(int memory_limit) {
1553 if (audio_) 1610 for (SourceStateMap::iterator itr = source_state_map_.begin();
1554 audio_->set_memory_limit_for_testing(memory_limit); 1611 itr != source_state_map_.end(); ++itr) {
1555 1612 itr->second->SetMemoryLimitsForTesting(memory_limit);
1556 if (video_) 1613 }
1557 video_->set_memory_limit_for_testing(memory_limit);
1558 } 1614 }
1559 1615
1560 void ChunkDemuxer::ChangeState_Locked(State new_state) { 1616 void ChunkDemuxer::ChangeState_Locked(State new_state) {
1561 lock_.AssertAcquired(); 1617 lock_.AssertAcquired();
1562 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : " 1618 DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : "
1563 << state_ << " -> " << new_state; 1619 << state_ << " -> " << new_state;
1564 state_ = new_state; 1620 state_ = new_state;
1565 } 1621 }
1566 1622
1567 ChunkDemuxer::~ChunkDemuxer() { 1623 ChunkDemuxer::~ChunkDemuxer() {
1568 DCHECK_NE(state_, INITIALIZED); 1624 DCHECK_NE(state_, INITIALIZED);
1569 for (SourceStateMap::iterator it = source_state_map_.begin(); 1625
1570 it != source_state_map_.end(); ++it) { 1626 STLDeleteValues(&source_state_map_);
1571 delete it->second;
1572 }
1573 source_state_map_.clear();
1574 } 1627 }
1575 1628
1576 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { 1629 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) {
1577 DVLOG(1) << "ReportError_Locked(" << error << ")"; 1630 DVLOG(1) << "ReportError_Locked(" << error << ")";
1578 lock_.AssertAcquired(); 1631 lock_.AssertAcquired();
1579 DCHECK_NE(error, PIPELINE_OK); 1632 DCHECK_NE(error, PIPELINE_OK);
1580 1633
1581 ChangeState_Locked(PARSE_ERROR); 1634 ChangeState_Locked(PARSE_ERROR);
1582 1635
1583 PipelineStatusCB cb; 1636 PipelineStatusCB cb;
1584 1637
1585 if (!init_cb_.is_null()) { 1638 if (!init_cb_.is_null()) {
1586 std::swap(cb, init_cb_); 1639 std::swap(cb, init_cb_);
1587 } else { 1640 } else {
1588 if (!seek_cb_.is_null()) 1641 if (!seek_cb_.is_null())
1589 std::swap(cb, seek_cb_); 1642 std::swap(cb, seek_cb_);
1590 1643
1591 if (audio_) 1644 ShutdownAllStreams();
1592 audio_->Shutdown();
1593
1594 if (video_)
1595 video_->Shutdown();
1596 } 1645 }
1597 1646
1598 if (!cb.is_null()) { 1647 if (!cb.is_null()) {
1599 cb.Run(error); 1648 cb.Run(error);
1600 return; 1649 return;
1601 } 1650 }
1602 1651
1603 base::AutoUnlock auto_unlock(lock_); 1652 base::AutoUnlock auto_unlock(lock_);
1604 host_->OnDemuxerError(error); 1653 host_->OnDemuxerError(error);
1605 } 1654 }
1606 1655
1607 bool ChunkDemuxer::IsSeekWaitingForData_Locked() const { 1656 bool ChunkDemuxer::IsSeekWaitingForData_Locked() const {
1608 lock_.AssertAcquired(); 1657 lock_.AssertAcquired();
1609 bool waiting_for_data = false; 1658 for (SourceStateMap::const_iterator itr = source_state_map_.begin();
1659 itr != source_state_map_.end(); ++itr) {
1660 if (itr->second->IsSeekWaitingForData())
1661 return true;
1662 }
1610 1663
1611 if (audio_) 1664 return false;
1612 waiting_for_data = audio_->IsSeekWaitingForData();
1613
1614 if (!waiting_for_data && video_)
1615 waiting_for_data = video_->IsSeekWaitingForData();
1616
1617 return waiting_for_data;
1618 } 1665 }
1619 1666
1620 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) { 1667 void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) {
1621 DVLOG(1) << "OnSourceInitDone(" << success << ", " 1668 DVLOG(1) << "OnSourceInitDone(" << success << ", "
1622 << duration.InSecondsF() << ")"; 1669 << duration.InSecondsF() << ")";
1623 lock_.AssertAcquired(); 1670 lock_.AssertAcquired();
1624 DCHECK_EQ(state_, INITIALIZING); 1671 DCHECK_EQ(state_, INITIALIZING);
1625 if (!success || (!audio_ && !video_)) { 1672 if (!success || (!audio_ && !video_)) {
1626 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1673 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
1627 return; 1674 return;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1766 } 1813 }
1767 } 1814 }
1768 1815
1769 void ChunkDemuxer::CompletePendingReadsIfPossible() { 1816 void ChunkDemuxer::CompletePendingReadsIfPossible() {
1770 for (SourceStateMap::iterator itr = source_state_map_.begin(); 1817 for (SourceStateMap::iterator itr = source_state_map_.begin();
1771 itr != source_state_map_.end(); ++itr) { 1818 itr != source_state_map_.end(); ++itr) {
1772 itr->second->CompletePendingReadIfPossible(); 1819 itr->second->CompletePendingReadIfPossible();
1773 } 1820 }
1774 } 1821 }
1775 1822
1823 void ChunkDemuxer::ShutdownAllStreams() {
1824 for (SourceStateMap::iterator itr = source_state_map_.begin();
1825 itr != source_state_map_.end(); ++itr) {
1826 itr->second->Shutdown();
1827 }
1828 }
1829
1776 } // namespace media 1830 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698