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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 | 116 |
117 // Calls Remove(|start|, |end|, |duration|) on all | 117 // Calls Remove(|start|, |end|, |duration|) on all |
118 // ChunkDemuxerStreams managed by this object. | 118 // ChunkDemuxerStreams managed by this object. |
119 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration); | 119 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration); |
120 | 120 |
121 // Sets |timestamp_offset_| if possible. | 121 // Sets |timestamp_offset_| if possible. |
122 // 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 |
123 // updated at this time. | 123 // updated at this time. |
124 bool SetTimestampOffset(TimeDelta timestamp_offset); | 124 bool SetTimestampOffset(TimeDelta timestamp_offset); |
125 | 125 |
| 126 // Sets |sequence_mode_| to |sequence_mode| if possible. |
| 127 // Returns true if the mode update was allowed. Returns false if the mode |
| 128 // could not be updated at this time. |
| 129 bool SetSequenceMode(bool sequence_mode); |
| 130 |
126 TimeDelta timestamp_offset() const { return timestamp_offset_; } | 131 TimeDelta timestamp_offset() const { return timestamp_offset_; } |
127 | 132 |
128 void set_append_window_start(TimeDelta start) { | 133 void set_append_window_start(TimeDelta start) { |
129 append_window_start_ = start; | 134 append_window_start_ = start; |
130 } | 135 } |
131 void set_append_window_end(TimeDelta end) { append_window_end_ = end; } | 136 void set_append_window_end(TimeDelta end) { append_window_end_ = end; } |
132 | 137 |
133 // Returns the range of buffered data in this source, capped at |duration|. | 138 // Returns the range of buffered data in this source, capped at |duration|. |
134 // |ended| - Set to true if end of stream has been signalled and the special | 139 // |ended| - Set to true if end of stream has been signalled and the special |
135 // end of stream range logic needs to be executed. | 140 // end of stream range logic needs to be executed. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 bool* needs_keyframe, | 215 bool* needs_keyframe, |
211 StreamParser::BufferQueue* filtered_buffers); | 216 StreamParser::BufferQueue* filtered_buffers); |
212 | 217 |
213 CreateDemuxerStreamCB create_demuxer_stream_cb_; | 218 CreateDemuxerStreamCB create_demuxer_stream_cb_; |
214 IncreaseDurationCB increase_duration_cb_; | 219 IncreaseDurationCB increase_duration_cb_; |
215 NewTextTrackCB new_text_track_cb_; | 220 NewTextTrackCB new_text_track_cb_; |
216 | 221 |
217 // The offset to apply to media segment timestamps. | 222 // The offset to apply to media segment timestamps. |
218 TimeDelta timestamp_offset_; | 223 TimeDelta timestamp_offset_; |
219 | 224 |
| 225 // Tracks the mode by which appended media is processed. If true, then |
| 226 // appended media is processed using "sequence" mode. Otherwise, appended |
| 227 // media is processed using "segments" mode. |
| 228 // TODO(wolenetz): Enable "sequence" mode logic. See http://crbug.com/249422 |
| 229 // and http://crbug.com/333437. |
| 230 bool sequence_mode_; |
| 231 |
220 TimeDelta append_window_start_; | 232 TimeDelta append_window_start_; |
221 TimeDelta append_window_end_; | 233 TimeDelta append_window_end_; |
222 | 234 |
223 // Set to true if the next buffers appended within the append window | 235 // Set to true if the next buffers appended within the append window |
224 // represent the start of a new media segment. This flag being set | 236 // represent the start of a new media segment. This flag being set |
225 // triggers a call to |new_segment_cb_| when the new buffers are | 237 // triggers a call to |new_segment_cb_| when the new buffers are |
226 // appended. The flag is set on actual media segment boundaries and | 238 // appended. The flag is set on actual media segment boundaries and |
227 // when the "append window" filtering causes discontinuities in the | 239 // when the "append window" filtering causes discontinuities in the |
228 // appended data. | 240 // appended data. |
229 bool new_media_segment_; | 241 bool new_media_segment_; |
230 | 242 |
231 // Keeps track of whether |timestamp_offset_| can be modified. | 243 // Keeps track of whether |timestamp_offset_| or |sequence_mode_| can be |
232 bool can_update_offset_; | 244 // updated. These cannot be updated if a media segment is being parsed. |
| 245 bool parsing_media_segment_; |
233 | 246 |
234 // The object used to parse appended data. | 247 // The object used to parse appended data. |
235 scoped_ptr<StreamParser> stream_parser_; | 248 scoped_ptr<StreamParser> stream_parser_; |
236 | 249 |
237 ChunkDemuxerStream* audio_; | 250 ChunkDemuxerStream* audio_; |
238 bool audio_needs_keyframe_; | 251 bool audio_needs_keyframe_; |
239 | 252 |
240 ChunkDemuxerStream* video_; | 253 ChunkDemuxerStream* video_; |
241 bool video_needs_keyframe_; | 254 bool video_needs_keyframe_; |
242 | 255 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 | 362 |
350 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); | 363 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); |
351 }; | 364 }; |
352 | 365 |
353 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, | 366 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, |
354 const LogCB& log_cb, | 367 const LogCB& log_cb, |
355 const CreateDemuxerStreamCB& create_demuxer_stream_cb, | 368 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
356 const IncreaseDurationCB& increase_duration_cb) | 369 const IncreaseDurationCB& increase_duration_cb) |
357 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 370 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
358 increase_duration_cb_(increase_duration_cb), | 371 increase_duration_cb_(increase_duration_cb), |
| 372 sequence_mode_(false), |
359 append_window_end_(kInfiniteDuration()), | 373 append_window_end_(kInfiniteDuration()), |
360 new_media_segment_(false), | 374 new_media_segment_(false), |
361 can_update_offset_(true), | 375 parsing_media_segment_(false), |
362 stream_parser_(stream_parser.release()), | 376 stream_parser_(stream_parser.release()), |
363 audio_(NULL), | 377 audio_(NULL), |
364 audio_needs_keyframe_(true), | 378 audio_needs_keyframe_(true), |
365 video_(NULL), | 379 video_(NULL), |
366 video_needs_keyframe_(true), | 380 video_needs_keyframe_(true), |
367 log_cb_(log_cb) { | 381 log_cb_(log_cb) { |
368 DCHECK(!create_demuxer_stream_cb_.is_null()); | 382 DCHECK(!create_demuxer_stream_cb_.is_null()); |
369 DCHECK(!increase_duration_cb_.is_null()); | 383 DCHECK(!increase_duration_cb_.is_null()); |
370 } | 384 } |
371 | 385 |
(...skipping 27 matching lines...) Expand all Loading... |
399 new_text_buffers_cb, | 413 new_text_buffers_cb, |
400 need_key_cb, | 414 need_key_cb, |
401 base::Bind(&SourceState::OnNewMediaSegment, | 415 base::Bind(&SourceState::OnNewMediaSegment, |
402 base::Unretained(this)), | 416 base::Unretained(this)), |
403 base::Bind(&SourceState::OnEndOfMediaSegment, | 417 base::Bind(&SourceState::OnEndOfMediaSegment, |
404 base::Unretained(this)), | 418 base::Unretained(this)), |
405 log_cb_); | 419 log_cb_); |
406 } | 420 } |
407 | 421 |
408 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) { | 422 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) { |
409 if (!can_update_offset_) | 423 if (parsing_media_segment_) |
410 return false; | 424 return false; |
411 | 425 |
412 timestamp_offset_ = timestamp_offset; | 426 timestamp_offset_ = timestamp_offset; |
413 return true; | 427 return true; |
414 } | 428 } |
415 | 429 |
| 430 bool SourceState::SetSequenceMode(bool sequence_mode) { |
| 431 if (parsing_media_segment_) |
| 432 return false; |
| 433 |
| 434 sequence_mode_ = sequence_mode; |
| 435 return true; |
| 436 } |
| 437 |
| 438 |
416 bool SourceState::Append(const uint8* data, size_t length) { | 439 bool SourceState::Append(const uint8* data, size_t length) { |
417 return stream_parser_->Parse(data, length); | 440 return stream_parser_->Parse(data, length); |
418 } | 441 } |
419 | 442 |
420 void SourceState::Abort() { | 443 void SourceState::Abort() { |
421 stream_parser_->Flush(); | 444 stream_parser_->Flush(); |
422 audio_needs_keyframe_ = true; | 445 audio_needs_keyframe_ = true; |
423 video_needs_keyframe_ = true; | 446 video_needs_keyframe_ = true; |
424 can_update_offset_ = true; | 447 parsing_media_segment_ = false; |
425 } | 448 } |
426 | 449 |
427 void SourceState::Remove(TimeDelta start, TimeDelta end, TimeDelta duration) { | 450 void SourceState::Remove(TimeDelta start, TimeDelta end, TimeDelta duration) { |
428 if (audio_) | 451 if (audio_) |
429 audio_->Remove(start, end, duration); | 452 audio_->Remove(start, end, duration); |
430 | 453 |
431 if (video_) | 454 if (video_) |
432 video_->Remove(start, end, duration); | 455 video_->Remove(start, end, duration); |
433 | 456 |
434 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | 457 for (TextStreamMap::iterator itr = text_stream_map_.begin(); |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 } | 760 } |
738 } | 761 } |
739 } | 762 } |
740 | 763 |
741 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); | 764 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); |
742 return success; | 765 return success; |
743 } | 766 } |
744 | 767 |
745 void SourceState::OnNewMediaSegment() { | 768 void SourceState::OnNewMediaSegment() { |
746 DVLOG(2) << "OnNewMediaSegment()"; | 769 DVLOG(2) << "OnNewMediaSegment()"; |
747 can_update_offset_ = false; | 770 parsing_media_segment_ = true; |
748 new_media_segment_ = true; | 771 new_media_segment_ = true; |
749 } | 772 } |
750 | 773 |
751 void SourceState::OnEndOfMediaSegment() { | 774 void SourceState::OnEndOfMediaSegment() { |
752 DVLOG(2) << "OnEndOfMediaSegment()"; | 775 DVLOG(2) << "OnEndOfMediaSegment()"; |
753 can_update_offset_ = true; | 776 parsing_media_segment_ = false; |
754 new_media_segment_ = false; | 777 new_media_segment_ = false; |
755 } | 778 } |
756 | 779 |
757 bool SourceState::OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, | 780 bool SourceState::OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, |
758 const StreamParser::BufferQueue& video_buffers) { | 781 const StreamParser::BufferQueue& video_buffers) { |
759 DCHECK(!audio_buffers.empty() || !video_buffers.empty()); | 782 DCHECK(!audio_buffers.empty() || !video_buffers.empty()); |
760 AdjustBufferTimestamps(audio_buffers); | 783 AdjustBufferTimestamps(audio_buffers); |
761 AdjustBufferTimestamps(video_buffers); | 784 AdjustBufferTimestamps(video_buffers); |
762 | 785 |
763 StreamParser::BufferQueue filtered_audio; | 786 StreamParser::BufferQueue filtered_audio; |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1517 } | 1540 } |
1518 | 1541 |
1519 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { | 1542 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { |
1520 base::AutoLock auto_lock(lock_); | 1543 base::AutoLock auto_lock(lock_); |
1521 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; | 1544 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; |
1522 CHECK(IsValidId(id)); | 1545 CHECK(IsValidId(id)); |
1523 | 1546 |
1524 return source_state_map_[id]->SetTimestampOffset(offset); | 1547 return source_state_map_[id]->SetTimestampOffset(offset); |
1525 } | 1548 } |
1526 | 1549 |
| 1550 bool ChunkDemuxer::SetSequenceMode(const std::string& id, |
| 1551 bool sequence_mode) { |
| 1552 base::AutoLock auto_lock(lock_); |
| 1553 DVLOG(1) << "SetSequenceMode(" << id << ", " << sequence_mode << ")"; |
| 1554 CHECK(IsValidId(id)); |
| 1555 DCHECK_NE(state_, ENDED); |
| 1556 |
| 1557 return source_state_map_[id]->SetSequenceMode(sequence_mode); |
| 1558 } |
| 1559 |
1527 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { | 1560 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { |
1528 DVLOG(1) << "MarkEndOfStream(" << status << ")"; | 1561 DVLOG(1) << "MarkEndOfStream(" << status << ")"; |
1529 base::AutoLock auto_lock(lock_); | 1562 base::AutoLock auto_lock(lock_); |
1530 DCHECK_NE(state_, WAITING_FOR_INIT); | 1563 DCHECK_NE(state_, WAITING_FOR_INIT); |
1531 DCHECK_NE(state_, ENDED); | 1564 DCHECK_NE(state_, ENDED); |
1532 | 1565 |
1533 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) | 1566 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) |
1534 return; | 1567 return; |
1535 | 1568 |
1536 if (state_ == INITIALIZING) { | 1569 if (state_ == INITIALIZING) { |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1820 } | 1853 } |
1821 | 1854 |
1822 void ChunkDemuxer::ShutdownAllStreams() { | 1855 void ChunkDemuxer::ShutdownAllStreams() { |
1823 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1856 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1824 itr != source_state_map_.end(); ++itr) { | 1857 itr != source_state_map_.end(); ++itr) { |
1825 itr->second->Shutdown(); | 1858 itr->second->Shutdown(); |
1826 } | 1859 } |
1827 } | 1860 } |
1828 | 1861 |
1829 } // namespace media | 1862 } // namespace media |
OLD | NEW |