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