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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 ~SourceState(); | 101 ~SourceState(); |
102 | 102 |
103 void Init(const StreamParser::InitCB& init_cb, | 103 void Init(const StreamParser::InitCB& init_cb, |
104 bool allow_audio, | 104 bool allow_audio, |
105 bool allow_video, | 105 bool allow_video, |
106 const StreamParser::NeedKeyCB& need_key_cb, | 106 const StreamParser::NeedKeyCB& need_key_cb, |
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. Appending uses cached |timestamp_offset_| and may update |
112 bool Append(const uint8* data, size_t length); | 112 // |*timestamp_offset| if |timestamp_offset| is not NULL. |
| 113 // TODO(wolenetz): Rework so |timestamp_offset_| is only valid during |
| 114 // Append(). See http://crbug.com/347623. |
| 115 bool Append(const uint8* data, size_t length, double* timestamp_offset); |
113 | 116 |
114 // Aborts the current append sequence and resets the parser. | 117 // Aborts the current append sequence and resets the parser. |
115 void Abort(); | 118 void Abort(); |
116 | 119 |
117 // Calls Remove(|start|, |end|, |duration|) on all | 120 // Calls Remove(|start|, |end|, |duration|) on all |
118 // ChunkDemuxerStreams managed by this object. | 121 // ChunkDemuxerStreams managed by this object. |
119 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration); | 122 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration); |
120 | 123 |
121 // Sets |timestamp_offset_| if possible. | 124 // Sets user-specified |timestamp_offset_| if possible. |
122 // Returns if the offset was set. Returns false if the offset could not be | 125 // Returns true if the offset was set. Returns false if the offset could not |
123 // updated at this time. | 126 // be set at this time. |
124 bool SetTimestampOffset(TimeDelta timestamp_offset); | 127 bool SetTimestampOffset(TimeDelta timestamp_offset); |
125 | 128 |
126 // Sets |sequence_mode_| to |sequence_mode| if possible. | 129 // Sets |sequence_mode_| to |sequence_mode| if possible. |
127 // Returns true if the mode update was allowed. Returns false if the mode | 130 // Returns true if the mode update was allowed. Returns false if the mode |
128 // could not be updated at this time. | 131 // could not be updated at this time. |
129 bool SetSequenceMode(bool sequence_mode); | 132 bool SetSequenceMode(bool sequence_mode); |
130 | 133 |
131 TimeDelta timestamp_offset() const { return timestamp_offset_; } | |
132 | |
133 void set_append_window_start(TimeDelta start) { | 134 void set_append_window_start(TimeDelta start) { |
134 append_window_start_ = start; | 135 append_window_start_ = start; |
135 } | 136 } |
136 void set_append_window_end(TimeDelta end) { append_window_end_ = end; } | 137 void set_append_window_end(TimeDelta end) { append_window_end_ = end; } |
137 | 138 |
138 // Returns the range of buffered data in this source, capped at |duration|. | 139 // Returns the range of buffered data in this source, capped at |duration|. |
139 // |ended| - Set to true if end of stream has been signalled and the special | 140 // |ended| - Set to true if end of stream has been signalled and the special |
140 // end of stream range logic needs to be executed. | 141 // end of stream range logic needs to be executed. |
141 Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const; | 142 Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const; |
142 | 143 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 bool* needs_keyframe, | 218 bool* needs_keyframe, |
218 StreamParser::BufferQueue* filtered_buffers); | 219 StreamParser::BufferQueue* filtered_buffers); |
219 | 220 |
220 CreateDemuxerStreamCB create_demuxer_stream_cb_; | 221 CreateDemuxerStreamCB create_demuxer_stream_cb_; |
221 IncreaseDurationCB increase_duration_cb_; | 222 IncreaseDurationCB increase_duration_cb_; |
222 NewTextTrackCB new_text_track_cb_; | 223 NewTextTrackCB new_text_track_cb_; |
223 | 224 |
224 // The offset to apply to media segment timestamps. | 225 // The offset to apply to media segment timestamps. |
225 TimeDelta timestamp_offset_; | 226 TimeDelta timestamp_offset_; |
226 | 227 |
| 228 // Flag that tracks whether or not the current Append() operation changed |
| 229 // |timestamp_offset_|. |
| 230 bool timestamp_offset_updated_by_append_; |
| 231 |
227 // Tracks the mode by which appended media is processed. If true, then | 232 // Tracks the mode by which appended media is processed. If true, then |
228 // appended media is processed using "sequence" mode. Otherwise, appended | 233 // appended media is processed using "sequence" mode. Otherwise, appended |
229 // media is processed using "segments" mode. | 234 // media is processed using "segments" mode. |
230 // TODO(wolenetz): Enable "sequence" mode logic. See http://crbug.com/249422 | 235 // TODO(wolenetz): Enable "sequence" mode logic. See http://crbug.com/249422 |
231 // and http://crbug.com/333437. | 236 // and http://crbug.com/333437. |
232 bool sequence_mode_; | 237 bool sequence_mode_; |
233 | 238 |
234 TimeDelta append_window_start_; | 239 TimeDelta append_window_start_; |
235 TimeDelta append_window_end_; | 240 TimeDelta append_window_end_; |
236 | 241 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 | 363 |
359 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); | 364 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); |
360 }; | 365 }; |
361 | 366 |
362 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, | 367 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, |
363 const LogCB& log_cb, | 368 const LogCB& log_cb, |
364 const CreateDemuxerStreamCB& create_demuxer_stream_cb, | 369 const CreateDemuxerStreamCB& create_demuxer_stream_cb, |
365 const IncreaseDurationCB& increase_duration_cb) | 370 const IncreaseDurationCB& increase_duration_cb) |
366 : create_demuxer_stream_cb_(create_demuxer_stream_cb), | 371 : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
367 increase_duration_cb_(increase_duration_cb), | 372 increase_duration_cb_(increase_duration_cb), |
| 373 timestamp_offset_updated_by_append_(false), |
368 sequence_mode_(false), | 374 sequence_mode_(false), |
369 append_window_end_(kInfiniteDuration()), | 375 append_window_end_(kInfiniteDuration()), |
370 new_media_segment_(false), | 376 new_media_segment_(false), |
371 parsing_media_segment_(false), | 377 parsing_media_segment_(false), |
372 stream_parser_(stream_parser.release()), | 378 stream_parser_(stream_parser.release()), |
373 audio_(NULL), | 379 audio_(NULL), |
374 audio_needs_keyframe_(true), | 380 audio_needs_keyframe_(true), |
375 video_(NULL), | 381 video_(NULL), |
376 video_needs_keyframe_(true), | 382 video_needs_keyframe_(true), |
377 log_cb_(log_cb) { | 383 log_cb_(log_cb) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 } | 423 } |
418 | 424 |
419 bool SourceState::SetSequenceMode(bool sequence_mode) { | 425 bool SourceState::SetSequenceMode(bool sequence_mode) { |
420 if (parsing_media_segment_) | 426 if (parsing_media_segment_) |
421 return false; | 427 return false; |
422 | 428 |
423 sequence_mode_ = sequence_mode; | 429 sequence_mode_ = sequence_mode; |
424 return true; | 430 return true; |
425 } | 431 } |
426 | 432 |
| 433 bool SourceState::Append(const uint8* data, size_t length, |
| 434 double* timestamp_offset) { |
| 435 timestamp_offset_updated_by_append_ = false; |
| 436 bool err = stream_parser_->Parse(data, length); |
427 | 437 |
428 bool SourceState::Append(const uint8* data, size_t length) { | 438 if (timestamp_offset_updated_by_append_ && timestamp_offset) |
429 return stream_parser_->Parse(data, length); | 439 *timestamp_offset = timestamp_offset_.InSecondsF(); |
| 440 |
| 441 return err; |
430 } | 442 } |
431 | 443 |
432 void SourceState::Abort() { | 444 void SourceState::Abort() { |
433 stream_parser_->Flush(); | 445 stream_parser_->Flush(); |
434 audio_needs_keyframe_ = true; | 446 audio_needs_keyframe_ = true; |
435 video_needs_keyframe_ = true; | 447 video_needs_keyframe_ = true; |
436 parsing_media_segment_ = false; | 448 parsing_media_segment_ = false; |
437 } | 449 } |
438 | 450 |
439 void SourceState::Remove(TimeDelta start, TimeDelta end, TimeDelta duration) { | 451 void SourceState::Remove(TimeDelta start, TimeDelta end, TimeDelta duration) { |
(...skipping 961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1401 base::AutoLock auto_lock(lock_); | 1413 base::AutoLock auto_lock(lock_); |
1402 DCHECK(!id.empty()); | 1414 DCHECK(!id.empty()); |
1403 | 1415 |
1404 SourceStateMap::const_iterator itr = source_state_map_.find(id); | 1416 SourceStateMap::const_iterator itr = source_state_map_.find(id); |
1405 | 1417 |
1406 DCHECK(itr != source_state_map_.end()); | 1418 DCHECK(itr != source_state_map_.end()); |
1407 return itr->second->GetBufferedRanges(duration_, state_ == ENDED); | 1419 return itr->second->GetBufferedRanges(duration_, state_ == ENDED); |
1408 } | 1420 } |
1409 | 1421 |
1410 void ChunkDemuxer::AppendData(const std::string& id, | 1422 void ChunkDemuxer::AppendData(const std::string& id, |
1411 const uint8* data, | 1423 const uint8* data, size_t length, |
1412 size_t length) { | 1424 double* timestamp_offset) { |
1413 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; | 1425 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; |
1414 | 1426 |
1415 DCHECK(!id.empty()); | 1427 DCHECK(!id.empty()); |
1416 | 1428 |
1417 Ranges<TimeDelta> ranges; | 1429 Ranges<TimeDelta> ranges; |
1418 | 1430 |
1419 { | 1431 { |
1420 base::AutoLock auto_lock(lock_); | 1432 base::AutoLock auto_lock(lock_); |
1421 DCHECK_NE(state_, ENDED); | 1433 DCHECK_NE(state_, ENDED); |
1422 | 1434 |
1423 // Capture if any of the SourceBuffers are waiting for data before we start | 1435 // Capture if any of the SourceBuffers are waiting for data before we start |
1424 // parsing. | 1436 // parsing. |
1425 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); | 1437 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); |
1426 | 1438 |
1427 if (length == 0u) | 1439 if (length == 0u) |
1428 return; | 1440 return; |
1429 | 1441 |
1430 DCHECK(data); | 1442 DCHECK(data); |
1431 | 1443 |
1432 switch (state_) { | 1444 switch (state_) { |
1433 case INITIALIZING: | 1445 case INITIALIZING: |
1434 DCHECK(IsValidId(id)); | 1446 DCHECK(IsValidId(id)); |
1435 if (!source_state_map_[id]->Append(data, length)) { | 1447 if (!source_state_map_[id]->Append(data, length, |
| 1448 timestamp_offset)) { |
1436 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); | 1449 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
1437 return; | 1450 return; |
1438 } | 1451 } |
1439 break; | 1452 break; |
1440 | 1453 |
1441 case INITIALIZED: { | 1454 case INITIALIZED: { |
1442 DCHECK(IsValidId(id)); | 1455 DCHECK(IsValidId(id)); |
1443 if (!source_state_map_[id]->Append(data, length)) { | 1456 if (!source_state_map_[id]->Append(data, length, |
| 1457 timestamp_offset)) { |
1444 ReportError_Locked(PIPELINE_ERROR_DECODE); | 1458 ReportError_Locked(PIPELINE_ERROR_DECODE); |
1445 return; | 1459 return; |
1446 } | 1460 } |
1447 } break; | 1461 } break; |
1448 | 1462 |
1449 case PARSE_ERROR: | 1463 case PARSE_ERROR: |
1450 DVLOG(1) << "AppendData(): Ignoring data after a parse error."; | 1464 DVLOG(1) << "AppendData(): Ignoring data after a parse error."; |
1451 return; | 1465 return; |
1452 | 1466 |
1453 case WAITING_FOR_INIT: | 1467 case WAITING_FOR_INIT: |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1865 } | 1879 } |
1866 | 1880 |
1867 void ChunkDemuxer::ShutdownAllStreams() { | 1881 void ChunkDemuxer::ShutdownAllStreams() { |
1868 for (SourceStateMap::iterator itr = source_state_map_.begin(); | 1882 for (SourceStateMap::iterator itr = source_state_map_.begin(); |
1869 itr != source_state_map_.end(); ++itr) { | 1883 itr != source_state_map_.end(); ++itr) { |
1870 itr->second->Shutdown(); | 1884 itr->second->Shutdown(); |
1871 } | 1885 } |
1872 } | 1886 } |
1873 | 1887 |
1874 } // namespace media | 1888 } // namespace media |
OLD | NEW |