OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |