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 |append_mode_| if possible. | |
127 // Returns if the mode was set. Returns false if the mode could not be updated | |
acolwell GONE FROM CHROMIUM
2014/01/10 23:10:37
s/Returns if/Returns true if/
wolenetz
2014/01/11 00:55:44
Done.
| |
128 // at this time. | |
129 bool SetAppendMode(ChunkDemuxer::AppendMode mode); | |
acolwell GONE FROM CHROMIUM
2014/01/10 23:10:37
How about SetSequenceMode(bool is_sequence_mode) s
wolenetz
2014/01/11 00:55:44
Done.
| |
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 // The mode by which appended media is processed. | |
226 // TODO(wolenetz): Enable |kSequence| mode logic. See http://crbug.com/249422 | |
227 // and http://crbug.com/333437. | |
228 ChunkDemuxer::AppendMode append_mode_; | |
229 | |
220 TimeDelta append_window_start_; | 230 TimeDelta append_window_start_; |
221 TimeDelta append_window_end_; | 231 TimeDelta append_window_end_; |
222 | 232 |
223 // Set to true if the next buffers appended within the append window | 233 // 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 | 234 // 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 | 235 // triggers a call to |new_segment_cb_| when the new buffers are |
226 // appended. The flag is set on actual media segment boundaries and | 236 // appended. The flag is set on actual media segment boundaries and |
227 // when the "append window" filtering causes discontinuities in the | 237 // when the "append window" filtering causes discontinuities in the |
228 // appended data. | 238 // appended data. |
229 bool new_media_segment_; | 239 bool new_media_segment_; |
230 | 240 |
231 // Keeps track of whether |timestamp_offset_| can be modified. | 241 // Keeps track of whether |timestamp_offset_| or |append_mode_| can be |
232 bool can_update_offset_; | 242 // set. These cannot be set if media segment is currently being parsed. |
243 bool parsing_media_segment_; | |
233 | 244 |
234 // The object used to parse appended data. | 245 // The object used to parse appended data. |
235 scoped_ptr<StreamParser> stream_parser_; | 246 scoped_ptr<StreamParser> stream_parser_; |
236 | 247 |
237 ChunkDemuxerStream* audio_; | 248 ChunkDemuxerStream* audio_; |
238 bool audio_needs_keyframe_; | 249 bool audio_needs_keyframe_; |
239 | 250 |
240 ChunkDemuxerStream* video_; | 251 ChunkDemuxerStream* video_; |
241 bool video_needs_keyframe_; | 252 bool video_needs_keyframe_; |
242 | 253 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
349 | 360 |
350 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); | 361 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); |
351 }; | 362 }; |
352 | 363 |
353 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, | 364 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, |
354 const LogCB& log_cb, | 365 const LogCB& log_cb, |
355 const CreateDemuxerStreamCB& create_demuxer_stream_cb, | 366 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
356 const IncreaseDurationCB& increase_duration_cb) | 367 const IncreaseDurationCB& increase_duration_cb) |
357 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 368 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
358 increase_duration_cb_(increase_duration_cb), | 369 increase_duration_cb_(increase_duration_cb), |
370 append_mode_(ChunkDemuxer::kSegments), | |
359 append_window_end_(kInfiniteDuration()), | 371 append_window_end_(kInfiniteDuration()), |
360 new_media_segment_(false), | 372 new_media_segment_(false), |
361 can_update_offset_(true), | 373 parsing_media_segment_(false), |
362 stream_parser_(stream_parser.release()), | 374 stream_parser_(stream_parser.release()), |
363 audio_(NULL), | 375 audio_(NULL), |
364 audio_needs_keyframe_(true), | 376 audio_needs_keyframe_(true), |
365 video_(NULL), | 377 video_(NULL), |
366 video_needs_keyframe_(true), | 378 video_needs_keyframe_(true), |
367 log_cb_(log_cb) { | 379 log_cb_(log_cb) { |
368 DCHECK(!create_demuxer_stream_cb_.is_null()); | 380 DCHECK(!create_demuxer_stream_cb_.is_null()); |
369 DCHECK(!increase_duration_cb_.is_null()); | 381 DCHECK(!increase_duration_cb_.is_null()); |
370 } | 382 } |
371 | 383 |
(...skipping 27 matching lines...) Expand all Loading... | |
399 new_text_buffers_cb, | 411 new_text_buffers_cb, |
400 need_key_cb, | 412 need_key_cb, |
401 base::Bind(&SourceState::OnNewMediaSegment, | 413 base::Bind(&SourceState::OnNewMediaSegment, |
402 base::Unretained(this)), | 414 base::Unretained(this)), |
403 base::Bind(&SourceState::OnEndOfMediaSegment, | 415 base::Bind(&SourceState::OnEndOfMediaSegment, |
404 base::Unretained(this)), | 416 base::Unretained(this)), |
405 log_cb_); | 417 log_cb_); |
406 } | 418 } |
407 | 419 |
408 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) { | 420 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) { |
409 if (!can_update_offset_) | 421 if (parsing_media_segment_) |
410 return false; | 422 return false; |
411 | 423 |
412 timestamp_offset_ = timestamp_offset; | 424 timestamp_offset_ = timestamp_offset; |
413 return true; | 425 return true; |
414 } | 426 } |
415 | 427 |
428 bool SourceState::SetAppendMode(ChunkDemuxer::AppendMode mode) { | |
429 if (parsing_media_segment_) | |
430 return false; | |
431 | |
432 append_mode_ = mode; | |
433 return true; | |
434 } | |
435 | |
436 | |
416 bool SourceState::Append(const uint8* data, size_t length) { | 437 bool SourceState::Append(const uint8* data, size_t length) { |
417 return stream_parser_->Parse(data, length); | 438 return stream_parser_->Parse(data, length); |
418 } | 439 } |
419 | 440 |
420 void SourceState::Abort() { | 441 void SourceState::Abort() { |
421 stream_parser_->Flush(); | 442 stream_parser_->Flush(); |
422 audio_needs_keyframe_ = true; | 443 audio_needs_keyframe_ = true; |
423 video_needs_keyframe_ = true; | 444 video_needs_keyframe_ = true; |
424 can_update_offset_ = true; | 445 parsing_media_segment_ = false; |
425 } | 446 } |
426 | 447 |
427 void SourceState::Remove(TimeDelta start, TimeDelta end, TimeDelta duration) { | 448 void SourceState::Remove(TimeDelta start, TimeDelta end, TimeDelta duration) { |
428 if (audio_) | 449 if (audio_) |
429 audio_->Remove(start, end, duration); | 450 audio_->Remove(start, end, duration); |
430 | 451 |
431 if (video_) | 452 if (video_) |
432 video_->Remove(start, end, duration); | 453 video_->Remove(start, end, duration); |
433 | 454 |
434 for (TextStreamMap::iterator itr = text_stream_map_.begin(); | 455 for (TextStreamMap::iterator itr = text_stream_map_.begin(); |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
737 } | 758 } |
738 } | 759 } |
739 } | 760 } |
740 | 761 |
741 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); | 762 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); |
742 return success; | 763 return success; |
743 } | 764 } |
744 | 765 |
745 void SourceState::OnNewMediaSegment() { | 766 void SourceState::OnNewMediaSegment() { |
746 DVLOG(2) << "OnNewMediaSegment()"; | 767 DVLOG(2) << "OnNewMediaSegment()"; |
747 can_update_offset_ = false; | 768 parsing_media_segment_ = true; |
748 new_media_segment_ = true; | 769 new_media_segment_ = true; |
749 } | 770 } |
750 | 771 |
751 void SourceState::OnEndOfMediaSegment() { | 772 void SourceState::OnEndOfMediaSegment() { |
752 DVLOG(2) << "OnEndOfMediaSegment()"; | 773 DVLOG(2) << "OnEndOfMediaSegment()"; |
753 can_update_offset_ = true; | 774 parsing_media_segment_ = false; |
754 new_media_segment_ = false; | 775 new_media_segment_ = false; |
755 } | 776 } |
756 | 777 |
757 bool SourceState::OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, | 778 bool SourceState::OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, |
758 const StreamParser::BufferQueue& video_buffers) { | 779 const StreamParser::BufferQueue& video_buffers) { |
759 DCHECK(!audio_buffers.empty() || !video_buffers.empty()); | 780 DCHECK(!audio_buffers.empty() || !video_buffers.empty()); |
760 AdjustBufferTimestamps(audio_buffers); | 781 AdjustBufferTimestamps(audio_buffers); |
761 AdjustBufferTimestamps(video_buffers); | 782 AdjustBufferTimestamps(video_buffers); |
762 | 783 |
763 StreamParser::BufferQueue filtered_audio; | 784 StreamParser::BufferQueue filtered_audio; |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1517 } | 1538 } |
1518 | 1539 |
1519 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { | 1540 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { |
1520 base::AutoLock auto_lock(lock_); | 1541 base::AutoLock auto_lock(lock_); |
1521 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; | 1542 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; |
1522 CHECK(IsValidId(id)); | 1543 CHECK(IsValidId(id)); |
1523 | 1544 |
1524 return source_state_map_[id]->SetTimestampOffset(offset); | 1545 return source_state_map_[id]->SetTimestampOffset(offset); |
1525 } | 1546 } |
1526 | 1547 |
1548 bool ChunkDemuxer::SetAppendMode(const std::string& id, AppendMode mode) { | |
1549 base::AutoLock auto_lock(lock_); | |
1550 DVLOG(1) << "SetAppendMode(" << id << ", " << mode << ")"; | |
1551 CHECK(IsValidId(id)); | |
1552 DCHECK_NE(state_, ENDED); | |
1553 | |
1554 return source_state_map_[id]->SetAppendMode(mode); | |
1555 } | |
1556 | |
1527 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { | 1557 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { |
1528 DVLOG(1) << "MarkEndOfStream(" << status << ")"; | 1558 DVLOG(1) << "MarkEndOfStream(" << status << ")"; |
1529 base::AutoLock auto_lock(lock_); | 1559 base::AutoLock auto_lock(lock_); |
1530 DCHECK_NE(state_, WAITING_FOR_INIT); | 1560 DCHECK_NE(state_, WAITING_FOR_INIT); |
1531 DCHECK_NE(state_, ENDED); | 1561 DCHECK_NE(state_, ENDED); |
1532 | 1562 |
1533 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) | 1563 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) |
1534 return; | 1564 return; |
1535 | 1565 |
1536 if (state_ == INITIALIZING) { | 1566 if (state_ == INITIALIZING) { |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1820 } | 1850 } |
1821 | 1851 |
1822 void ChunkDemuxer::ShutdownAllStreams() { | 1852 void ChunkDemuxer::ShutdownAllStreams() { |
1823 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1853 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1824 itr != source_state_map_.end(); ++itr) { | 1854 itr != source_state_map_.end(); ++itr) { |
1825 itr->second->Shutdown(); | 1855 itr->second->Shutdown(); |
1826 } | 1856 } |
1827 } | 1857 } |
1828 | 1858 |
1829 } // namespace media | 1859 } // namespace media |
OLD | NEW |