Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: media/filters/chunk_demuxer.cc

Issue 180153003: Implement core of compliant MediaSource coded frame processing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: A couple nits, still not ready for review. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <limits> 8 #include <limits>
9 #include <list> 9 #include <list>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback_helpers.h" 12 #include "base/callback_helpers.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/message_loop/message_loop_proxy.h" 14 #include "base/message_loop/message_loop_proxy.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "media/base/audio_decoder_config.h" 16 #include "media/base/audio_decoder_config.h"
17 #include "media/base/bind_to_current_loop.h" 17 #include "media/base/bind_to_current_loop.h"
18 #include "media/base/stream_parser_buffer.h" 18 #include "media/base/stream_parser_buffer.h"
19 #include "media/base/video_decoder_config.h" 19 #include "media/base/video_decoder_config.h"
20 #include "media/filters/frame_processor.h"
20 #include "media/filters/legacy_frame_processor.h" 21 #include "media/filters/legacy_frame_processor.h"
21 #include "media/filters/stream_parser_factory.h" 22 #include "media/filters/stream_parser_factory.h"
22 23
23 using base::TimeDelta; 24 using base::TimeDelta;
24 25
25 namespace media { 26 namespace media {
26 27
27 static TimeDelta EndTimestamp(const StreamParser::BufferQueue& queue) { 28 static TimeDelta EndTimestamp(const StreamParser::BufferQueue& queue) {
28 return queue.back()->timestamp() + queue.back()->duration(); 29 return queue.back()->timestamp() + queue.back()->duration();
29 } 30 }
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 // Calls Remove(|start|, |end|, |duration|) on all 131 // Calls Remove(|start|, |end|, |duration|) on all
131 // ChunkDemuxerStreams managed by this object. 132 // ChunkDemuxerStreams managed by this object.
132 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration); 133 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration);
133 134
134 // Returns true if currently parsing a media segment, or false otherwise. 135 // Returns true if currently parsing a media segment, or false otherwise.
135 bool parsing_media_segment() const { return parsing_media_segment_; } 136 bool parsing_media_segment() const { return parsing_media_segment_; }
136 137
137 // Sets |frame_processor_|'s sequence mode to |sequence_mode|. 138 // Sets |frame_processor_|'s sequence mode to |sequence_mode|.
138 void SetSequenceMode(bool sequence_mode); 139 void SetSequenceMode(bool sequence_mode);
139 140
141 // Signals the coded frame processor to update its group start timestamp to be
142 // |timestamp_offset| if it is in sequence append mode.
143 void SetGroupStartTimestampIfInSequenceMode(base::TimeDelta timestamp_offset);
144
140 // Returns the range of buffered data in this source, capped at |duration|. 145 // Returns the range of buffered data in this source, capped at |duration|.
141 // |ended| - Set to true if end of stream has been signalled and the special 146 // |ended| - Set to true if end of stream has been signaled and the special
142 // end of stream range logic needs to be executed. 147 // end of stream range logic needs to be executed.
143 Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const; 148 Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const;
144 149
145 // Returns the highest buffered duration across all streams managed 150 // Returns the highest buffered duration across all streams managed
146 // by this object. 151 // by this object.
147 // Returns TimeDelta() if none of the streams contain buffered data. 152 // Returns TimeDelta() if none of the streams contain buffered data.
148 TimeDelta GetMaxBufferedDuration() const; 153 TimeDelta GetMaxBufferedDuration() const;
149 154
150 // Helper methods that call methods with similar names on all the 155 // Helper methods that call methods with similar names on all the
151 // ChunkDemuxerStreams managed by this object. 156 // ChunkDemuxerStreams managed by this object.
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 base::Bind(&SourceState::OnEndOfMediaSegment, base::Unretained(this)), 290 base::Bind(&SourceState::OnEndOfMediaSegment, base::Unretained(this)),
286 log_cb_); 291 log_cb_);
287 } 292 }
288 293
289 void SourceState::SetSequenceMode(bool sequence_mode) { 294 void SourceState::SetSequenceMode(bool sequence_mode) {
290 DCHECK(!parsing_media_segment_); 295 DCHECK(!parsing_media_segment_);
291 296
292 frame_processor_->SetSequenceMode(sequence_mode); 297 frame_processor_->SetSequenceMode(sequence_mode);
293 } 298 }
294 299
300 void SourceState::SetGroupStartTimestampIfInSequenceMode(
301 base::TimeDelta timestamp_offset) {
302 DCHECK(!parsing_media_segment_);
303
304 frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset);
305 }
306
295 bool SourceState::Append(const uint8* data, size_t length, 307 bool SourceState::Append(const uint8* data, size_t length,
296 TimeDelta append_window_start, 308 TimeDelta append_window_start,
297 TimeDelta append_window_end, 309 TimeDelta append_window_end,
298 TimeDelta* timestamp_offset) { 310 TimeDelta* timestamp_offset) {
299 DCHECK(timestamp_offset); 311 DCHECK(timestamp_offset);
300 DCHECK(!timestamp_offset_during_append_); 312 DCHECK(!timestamp_offset_during_append_);
301 timestamp_offset_during_append_ = timestamp_offset;
302 append_window_start_during_append_ = append_window_start; 313 append_window_start_during_append_ = append_window_start;
303 append_window_end_during_append_ = append_window_end; 314 append_window_end_during_append_ = append_window_end;
315 timestamp_offset_during_append_ = timestamp_offset;
304 316
305 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with 317 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with
306 // append window and timestamp offset pointer. See http://crbug.com/351454. 318 // append window and timestamp offset pointer. See http://crbug.com/351454.
307 bool err = stream_parser_->Parse(data, length); 319 bool err = stream_parser_->Parse(data, length);
308 timestamp_offset_during_append_ = NULL; 320 timestamp_offset_during_append_ = NULL;
309 return err; 321 return err;
310 } 322 }
311 323
312 void SourceState::Abort() { 324 void SourceState::Abort() {
313 stream_parser_->Flush(); 325 stream_parser_->Flush();
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 if (has_audio) 1136 if (has_audio)
1125 source_id_audio_ = id; 1137 source_id_audio_ = id;
1126 1138
1127 if (has_video) 1139 if (has_video)
1128 source_id_video_ = id; 1140 source_id_video_ = id;
1129 1141
1130 scoped_ptr<FrameProcessorBase> frame_processor(new LegacyFrameProcessor( 1142 scoped_ptr<FrameProcessorBase> frame_processor(new LegacyFrameProcessor(
1131 base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary, 1143 base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary,
1132 base::Unretained(this)))); 1144 base::Unretained(this))));
1133 1145
1146 // BIG TODO remove!
1147 frame_processor.reset(new FrameProcessor(
1148 base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary,
1149 base::Unretained(this))));
1150
1134 scoped_ptr<SourceState> source_state( 1151 scoped_ptr<SourceState> source_state(
1135 new SourceState(stream_parser.Pass(), 1152 new SourceState(stream_parser.Pass(),
1136 frame_processor.Pass(), log_cb_, 1153 frame_processor.Pass(), log_cb_,
1137 base::Bind(&ChunkDemuxer::CreateDemuxerStream, 1154 base::Bind(&ChunkDemuxer::CreateDemuxerStream,
1138 base::Unretained(this)))); 1155 base::Unretained(this))));
1139 1156
1140 SourceState::NewTextTrackCB new_text_track_cb; 1157 SourceState::NewTextTrackCB new_text_track_cb;
1141 1158
1142 if (enable_text_) { 1159 if (enable_text_) {
1143 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack, 1160 new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack,
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1344 void ChunkDemuxer::SetSequenceMode(const std::string& id, 1361 void ChunkDemuxer::SetSequenceMode(const std::string& id,
1345 bool sequence_mode) { 1362 bool sequence_mode) {
1346 base::AutoLock auto_lock(lock_); 1363 base::AutoLock auto_lock(lock_);
1347 DVLOG(1) << "SetSequenceMode(" << id << ", " << sequence_mode << ")"; 1364 DVLOG(1) << "SetSequenceMode(" << id << ", " << sequence_mode << ")";
1348 CHECK(IsValidId(id)); 1365 CHECK(IsValidId(id));
1349 DCHECK_NE(state_, ENDED); 1366 DCHECK_NE(state_, ENDED);
1350 1367
1351 source_state_map_[id]->SetSequenceMode(sequence_mode); 1368 source_state_map_[id]->SetSequenceMode(sequence_mode);
1352 } 1369 }
1353 1370
1371 void ChunkDemuxer::SetGroupStartTimestampIfInSequenceMode(
1372 const std::string& id,
1373 base::TimeDelta timestamp_offset) {
1374 base::AutoLock auto_lock(lock_);
1375 DVLOG(1) << "SetGroupStartTimestampIfInSequenceMode(" << id << ", "
1376 << timestamp_offset.InSecondsF() << ")";
1377 CHECK(IsValidId(id));
1378 DCHECK_NE(state_, ENDED);
1379
1380 source_state_map_[id]->SetGroupStartTimestampIfInSequenceMode(
1381 timestamp_offset);
1382 }
1383
1384
1354 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { 1385 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) {
1355 DVLOG(1) << "MarkEndOfStream(" << status << ")"; 1386 DVLOG(1) << "MarkEndOfStream(" << status << ")";
1356 base::AutoLock auto_lock(lock_); 1387 base::AutoLock auto_lock(lock_);
1357 DCHECK_NE(state_, WAITING_FOR_INIT); 1388 DCHECK_NE(state_, WAITING_FOR_INIT);
1358 DCHECK_NE(state_, ENDED); 1389 DCHECK_NE(state_, ENDED);
1359 1390
1360 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) 1391 if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
1361 return; 1392 return;
1362 1393
1363 if (state_ == INITIALIZING) { 1394 if (state_ == INITIALIZING) {
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
1545 1576
1546 void ChunkDemuxer::UpdateDuration(TimeDelta new_duration) { 1577 void ChunkDemuxer::UpdateDuration(TimeDelta new_duration) {
1547 DCHECK(duration_ != new_duration); 1578 DCHECK(duration_ != new_duration);
1548 user_specified_duration_ = -1; 1579 user_specified_duration_ = -1;
1549 duration_ = new_duration; 1580 duration_ = new_duration;
1550 host_->SetDuration(new_duration); 1581 host_->SetDuration(new_duration);
1551 } 1582 }
1552 1583
1553 void ChunkDemuxer::IncreaseDurationIfNecessary(TimeDelta new_duration) { 1584 void ChunkDemuxer::IncreaseDurationIfNecessary(TimeDelta new_duration) {
1554 DCHECK(new_duration != kNoTimestamp()); 1585 DCHECK(new_duration != kNoTimestamp());
1586 DCHECK(new_duration != kInfiniteDuration());
1587
1588 // http://www.w3.org/TR/media-source/#sourcebuffer-coded-frame-processing
1589 // TODO(acolwell): Adjust the MSE spec text for this step to be like:
1590 // 5. If highest presentation end timestamp is beyond the current duration,
1591 // then run the duration change algorithm with new duration set to highest
1592 // presentation end timestamp.
1555 1593
1556 if (new_duration <= duration_) 1594 if (new_duration <= duration_)
1557 return; 1595 return;
1558 1596
1559 DVLOG(2) << __FUNCTION__ << ": Increasing duration: " 1597 DVLOG(2) << __FUNCTION__ << ": Increasing duration: "
1560 << duration_.InSecondsF() << " -> " << new_duration.InSecondsF(); 1598 << duration_.InSecondsF() << " -> " << new_duration.InSecondsF();
1561 1599
1562 UpdateDuration(new_duration); 1600 UpdateDuration(new_duration);
1563 } 1601 }
1564 1602
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 } 1667 }
1630 1668
1631 void ChunkDemuxer::ShutdownAllStreams() { 1669 void ChunkDemuxer::ShutdownAllStreams() {
1632 for (SourceStateMap::iterator itr = source_state_map_.begin(); 1670 for (SourceStateMap::iterator itr = source_state_map_.begin();
1633 itr != source_state_map_.end(); ++itr) { 1671 itr != source_state_map_.end(); ++itr) {
1634 itr->second->Shutdown(); 1672 itr->second->Shutdown();
1635 } 1673 }
1636 } 1674 }
1637 1675
1638 } // namespace media 1676 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698