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

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

Issue 196173002: MSE: Lift timestampOffset and appendWindow[Start,End] storage to WebSourceBufferImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address PS1 nit 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
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <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
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. Appending uses cached |timestamp_offset_| and may update 111 // error occurred. |*timestamp_offset| is used and possibly updated by the
112 // |*timestamp_offset| if |timestamp_offset| is not NULL. 112 // append. |append_window_start| and |append_window_end| correspond to the MSE
113 // TODO(wolenetz): Rework so |timestamp_offset_| is only valid during 113 // spec's similarly named source buffer attributes that are used in coded
114 // Append(). See http://crbug.com/347623. 114 // frame processing.
115 bool Append(const uint8* data, size_t length, double* timestamp_offset); 115 bool Append(const uint8* data, size_t length,
116 TimeDelta append_window_start_,
117 TimeDelta append_window_end_,
118 TimeDelta* timestamp_offset);
116 119
117 // Aborts the current append sequence and resets the parser. 120 // Aborts the current append sequence and resets the parser.
118 void Abort(); 121 void Abort();
119 122
120 // Calls Remove(|start|, |end|, |duration|) on all 123 // Calls Remove(|start|, |end|, |duration|) on all
121 // ChunkDemuxerStreams managed by this object. 124 // ChunkDemuxerStreams managed by this object.
122 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration); 125 void Remove(TimeDelta start, TimeDelta end, TimeDelta duration);
123 126
124 // Sets user-specified |timestamp_offset_| if possible. 127 // Returns true if currently parsing a media segment, or false otherwise.
125 // Returns true if the offset was set. Returns false if the offset could not 128 bool parsing_media_segment() const { return parsing_media_segment_; }
126 // be set at this time.
127 bool SetTimestampOffset(TimeDelta timestamp_offset);
128 129
129 // Sets |sequence_mode_| to |sequence_mode| if possible. 130 // Sets |sequence_mode_| to |sequence_mode|.
130 // Returns true if the mode update was allowed. Returns false if the mode 131 void SetSequenceMode(bool sequence_mode);
131 // could not be updated at this time.
132 bool SetSequenceMode(bool sequence_mode);
133
134 void set_append_window_start(TimeDelta start) {
135 append_window_start_ = start;
136 }
137 void set_append_window_end(TimeDelta end) { append_window_end_ = end; }
138 132
139 // Returns the range of buffered data in this source, capped at |duration|. 133 // Returns the range of buffered data in this source, capped at |duration|.
140 // |ended| - Set to true if end of stream has been signalled and the special 134 // |ended| - Set to true if end of stream has been signalled and the special
141 // end of stream range logic needs to be executed. 135 // end of stream range logic needs to be executed.
142 Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const; 136 Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const;
143 137
144 // Returns the highest buffered duration across all streams managed 138 // Returns the highest buffered duration across all streams managed
145 // by this object. 139 // by this object.
146 // Returns TimeDelta() if none of the streams contain buffered data. 140 // Returns TimeDelta() if none of the streams contain buffered data.
147 TimeDelta GetMaxBufferedDuration() const; 141 TimeDelta GetMaxBufferedDuration() const;
(...skipping 23 matching lines...) Expand all
171 const VideoDecoderConfig& video_config, 165 const VideoDecoderConfig& video_config,
172 const StreamParser::TextTrackConfigMap& text_configs); 166 const StreamParser::TextTrackConfigMap& text_configs);
173 167
174 // Called by the |stream_parser_| at the beginning of a new media segment. 168 // Called by the |stream_parser_| at the beginning of a new media segment.
175 void OnNewMediaSegment(); 169 void OnNewMediaSegment();
176 170
177 // Called by the |stream_parser_| at the end of a media segment. 171 // Called by the |stream_parser_| at the end of a media segment.
178 void OnEndOfMediaSegment(); 172 void OnEndOfMediaSegment();
179 173
180 // Called by the |stream_parser_| when new buffers have been parsed. It 174 // Called by the |stream_parser_| when new buffers have been parsed. It
181 // applies |timestamp_offset_| to all buffers in |audio_buffers|, 175 // applies |*timestamp_offset_during_append_| to all buffers in
182 // |video_buffers| and |text_map| and then calls Append() with the modified 176 // |audio_buffers|, |video_buffers| and |text_map|, filters buffers against
183 // buffers on |audio_|, |video_| and/or the text demuxer streams associated 177 // |append_window_[start,end]_during_append_| and then calls Append()
184 // with the track numbers in |text_map|. 178 // with the surviving modified buffers on |audio_|, |video_| and/or the text
179 // demuxer streams associated with the track numbers in |text_map|.
185 // Returns true on a successful call. Returns false if an error occurred while 180 // Returns true on a successful call. Returns false if an error occurred while
186 // processing the buffers. 181 // processing the buffers.
187 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, 182 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers,
188 const StreamParser::BufferQueue& video_buffers, 183 const StreamParser::BufferQueue& video_buffers,
189 const StreamParser::TextBufferQueueMap& text_map); 184 const StreamParser::TextBufferQueueMap& text_map);
190 185
191 // Helper function for OnNewBuffers() when new text buffers have been parsed. 186 // Helper function for OnNewBuffers() when new text buffers have been parsed.
192 // It applies |timestamp_offset_| to all buffers in |buffers| and then appends 187 // It applies |*timestamp_offset_during_append_| to all buffers in |buffers|,
193 // the (modified) buffers to the demuxer stream associated with 188 // filters the buffers against |append_window_[start,end]_during_append_| and
189 // then appends the (modified) buffers to the demuxer stream associated with
194 // the track having |text_track_id|. 190 // the track having |text_track_id|.
195 // Returns true on a successful call. Returns false if an error occurred while 191 // Returns true on a successful call. Returns false if an error occurred while
196 // processing the buffers. 192 // processing the buffers.
197 bool OnTextBuffers(StreamParser::TrackId text_track_id, 193 bool OnTextBuffers(StreamParser::TrackId text_track_id,
198 const StreamParser::BufferQueue& buffers); 194 const StreamParser::BufferQueue& buffers);
199 195
200 // Helper function that appends |buffers| to |stream| and calls 196 // Helper function that appends |buffers| to |stream| and calls
201 // |increase_duration_cb_| to potentially update the duration. 197 // |increase_duration_cb_| to potentially update the duration.
202 // Returns true if the append was successful. Returns false if 198 // Returns true if the append was successful. Returns false if
203 // |stream| is NULL or something in |buffers| caused the append to fail. 199 // |stream| is NULL or something in |buffers| caused the append to fail.
204 bool AppendAndUpdateDuration(ChunkDemuxerStream* stream, 200 bool AppendAndUpdateDuration(ChunkDemuxerStream* stream,
205 const StreamParser::BufferQueue& buffers); 201 const StreamParser::BufferQueue& buffers);
206 202
207 // Helper function that adds |timestamp_offset_| to each buffer in |buffers|. 203 // Helper function that adds |*timestamp_offset_during_append_| to each buffer
204 // in |buffers|.
208 void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers); 205 void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers);
209 206
210 // Filters out buffers that are outside of the append window 207 // Filters out buffers that are outside of the append window
211 // [|append_window_start_|, |append_window_end_|). 208 // [|append_window_start_during_append_|, |append_window_end_during_append_|).
212 // |needs_keyframe| is a pointer to the |xxx_need_keyframe_| flag 209 // |needs_keyframe| is a pointer to the |xxx_need_keyframe_| flag
213 // associated with the |buffers|. Its state is read an updated as 210 // associated with the |buffers|. Its state is read an updated as
214 // this method filters |buffers|. 211 // this method filters |buffers|.
215 // Buffers that are inside the append window are appended to the end 212 // Buffers that are inside the append window are appended to the end
216 // of |filtered_buffers|. 213 // of |filtered_buffers|.
217 void FilterWithAppendWindow(const StreamParser::BufferQueue& buffers, 214 void FilterWithAppendWindow(const StreamParser::BufferQueue& buffers,
218 bool* needs_keyframe, 215 bool* needs_keyframe,
219 StreamParser::BufferQueue* filtered_buffers); 216 StreamParser::BufferQueue* filtered_buffers);
220 217
221 CreateDemuxerStreamCB create_demuxer_stream_cb_; 218 CreateDemuxerStreamCB create_demuxer_stream_cb_;
222 IncreaseDurationCB increase_duration_cb_; 219 IncreaseDurationCB increase_duration_cb_;
223 NewTextTrackCB new_text_track_cb_; 220 NewTextTrackCB new_text_track_cb_;
224 221
225 // The offset to apply to media segment timestamps. 222 // During Append(), if OnNewBuffers() coded frame processing updates the
226 TimeDelta timestamp_offset_; 223 // timestamp offset then |*timestamp_offset_during_append_| is also updated
224 // so Append()'s caller can know the new offset. This pointer is only non-NULL
225 // during the lifetime of an Append() call.
226 TimeDelta* timestamp_offset_during_append_;
227 227
228 // Flag that tracks whether or not the current Append() operation changed 228 // During Append(), coded frame processing triggered by OnNewBuffers()
229 // |timestamp_offset_|. 229 // requires these two attributes. These are only valid during the lifetime of
230 bool timestamp_offset_updated_by_append_; 230 // an Append() call.
231 TimeDelta append_window_start_during_append_;
232 TimeDelta append_window_end_during_append_;
231 233
232 // Tracks the mode by which appended media is processed. If true, then 234 // Tracks the mode by which appended media is processed. If true, then
233 // appended media is processed using "sequence" mode. Otherwise, appended 235 // appended media is processed using "sequence" mode. Otherwise, appended
234 // media is processed using "segments" mode. 236 // media is processed using "segments" mode.
235 // TODO(wolenetz): Enable "sequence" mode logic. See http://crbug.com/249422 237 // TODO(wolenetz): Enable "sequence" mode logic. See http://crbug.com/249422
236 // and http://crbug.com/333437. 238 // and http://crbug.com/333437.
237 bool sequence_mode_; 239 bool sequence_mode_;
238 240
239 TimeDelta append_window_start_;
240 TimeDelta append_window_end_;
241
242 // Set to true if the next buffers appended within the append window 241 // Set to true if the next buffers appended within the append window
243 // represent the start of a new media segment. This flag being set 242 // represent the start of a new media segment. This flag being set
244 // triggers a call to |new_segment_cb_| when the new buffers are 243 // triggers a call to |new_segment_cb_| when the new buffers are
245 // appended. The flag is set on actual media segment boundaries and 244 // appended. The flag is set on actual media segment boundaries and
246 // when the "append window" filtering causes discontinuities in the 245 // when the "append window" filtering causes discontinuities in the
247 // appended data. 246 // appended data.
247 // TODO(wolenetz/acolwell): Investigate if we need this, or if coded frame
248 // processing's discontinuity logic is enough. See http://crbug.com/351489.
248 bool new_media_segment_; 249 bool new_media_segment_;
249 250
250 // Keeps track of whether |timestamp_offset_| or |sequence_mode_| can be 251 // Keeps track of whether a media segment is being parsed.
251 // updated. These cannot be updated if a media segment is being parsed.
252 bool parsing_media_segment_; 252 bool parsing_media_segment_;
253 253
254 // The object used to parse appended data. 254 // The object used to parse appended data.
255 scoped_ptr<StreamParser> stream_parser_; 255 scoped_ptr<StreamParser> stream_parser_;
256 256
257 ChunkDemuxerStream* audio_; 257 ChunkDemuxerStream* audio_; // Not owned by |this|.
258 bool audio_needs_keyframe_; 258 bool audio_needs_keyframe_;
259 259
260 ChunkDemuxerStream* video_; 260 ChunkDemuxerStream* video_; // Not owned by |this|.
261 bool video_needs_keyframe_; 261 bool video_needs_keyframe_;
262 262
263 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; 263 typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap;
264 TextStreamMap text_stream_map_; 264 TextStreamMap text_stream_map_; // |this| owns the map's stream pointers.
265 265
266 LogCB log_cb_; 266 LogCB log_cb_;
267 267
268 DISALLOW_COPY_AND_ASSIGN(SourceState); 268 DISALLOW_COPY_AND_ASSIGN(SourceState);
269 }; 269 };
270 270
271 class ChunkDemuxerStream : public DemuxerStream { 271 class ChunkDemuxerStream : public DemuxerStream {
272 public: 272 public:
273 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 273 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
274 274
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 363
364 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); 364 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream);
365 }; 365 };
366 366
367 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, 367 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser,
368 const LogCB& log_cb, 368 const LogCB& log_cb,
369 const CreateDemuxerStreamCB& create_demuxer_stream_cb, 369 const CreateDemuxerStreamCB& create_demuxer_stream_cb,
370 const IncreaseDurationCB& increase_duration_cb) 370 const IncreaseDurationCB& increase_duration_cb)
371 : create_demuxer_stream_cb_(create_demuxer_stream_cb), 371 : create_demuxer_stream_cb_(create_demuxer_stream_cb),
372 increase_duration_cb_(increase_duration_cb), 372 increase_duration_cb_(increase_duration_cb),
373 timestamp_offset_updated_by_append_(false), 373 timestamp_offset_during_append_(NULL),
374 sequence_mode_(false), 374 sequence_mode_(false),
375 append_window_end_(kInfiniteDuration()),
376 new_media_segment_(false), 375 new_media_segment_(false),
377 parsing_media_segment_(false), 376 parsing_media_segment_(false),
378 stream_parser_(stream_parser.release()), 377 stream_parser_(stream_parser.release()),
379 audio_(NULL), 378 audio_(NULL),
380 audio_needs_keyframe_(true), 379 audio_needs_keyframe_(true),
381 video_(NULL), 380 video_(NULL),
382 video_needs_keyframe_(true), 381 video_needs_keyframe_(true),
383 log_cb_(log_cb) { 382 log_cb_(log_cb) {
384 DCHECK(!create_demuxer_stream_cb_.is_null()); 383 DCHECK(!create_demuxer_stream_cb_.is_null());
385 DCHECK(!increase_duration_cb_.is_null()); 384 DCHECK(!increase_duration_cb_.is_null());
(...skipping 21 matching lines...) Expand all
407 base::Unretained(this)), 406 base::Unretained(this)),
408 new_text_track_cb_.is_null(), 407 new_text_track_cb_.is_null(),
409 need_key_cb, 408 need_key_cb,
410 base::Bind(&SourceState::OnNewMediaSegment, 409 base::Bind(&SourceState::OnNewMediaSegment,
411 base::Unretained(this)), 410 base::Unretained(this)),
412 base::Bind(&SourceState::OnEndOfMediaSegment, 411 base::Bind(&SourceState::OnEndOfMediaSegment,
413 base::Unretained(this)), 412 base::Unretained(this)),
414 log_cb_); 413 log_cb_);
415 } 414 }
416 415
417 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) { 416 void SourceState::SetSequenceMode(bool sequence_mode) {
418 if (parsing_media_segment_) 417 DCHECK(!parsing_media_segment_);
419 return false;
420
421 timestamp_offset_ = timestamp_offset;
422 return true;
423 }
424
425 bool SourceState::SetSequenceMode(bool sequence_mode) {
426 if (parsing_media_segment_)
427 return false;
428 418
429 sequence_mode_ = sequence_mode; 419 sequence_mode_ = sequence_mode;
430 return true;
431 } 420 }
432 421
433 bool SourceState::Append(const uint8* data, size_t length, 422 bool SourceState::Append(const uint8* data, size_t length,
434 double* timestamp_offset) { 423 TimeDelta append_window_start,
435 timestamp_offset_updated_by_append_ = false; 424 TimeDelta append_window_end,
425 TimeDelta* timestamp_offset) {
426 DCHECK(timestamp_offset);
427 DCHECK(!timestamp_offset_during_append_);
428 timestamp_offset_during_append_ = timestamp_offset;
429 append_window_start_during_append_ = append_window_start;
430 append_window_end_during_append_ = append_window_end;
431
432 // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with
433 // append window and timestamp offset pointer. See http://crbug.com/351454.
436 bool err = stream_parser_->Parse(data, length); 434 bool err = stream_parser_->Parse(data, length);
437 435 timestamp_offset_during_append_ = NULL;
438 if (timestamp_offset_updated_by_append_ && timestamp_offset)
439 *timestamp_offset = timestamp_offset_.InSecondsF();
440
441 return err; 436 return err;
442 } 437 }
443 438
444 void SourceState::Abort() { 439 void SourceState::Abort() {
445 stream_parser_->Flush(); 440 stream_parser_->Flush();
446 audio_needs_keyframe_ = true; 441 audio_needs_keyframe_ = true;
447 video_needs_keyframe_ = true; 442 video_needs_keyframe_ = true;
448 parsing_media_segment_ = false; 443 parsing_media_segment_ = false;
449 } 444 }
450 445
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 // for the seek position. This is ok and playback should not be 621 // for the seek position. This is ok and playback should not be
627 // stalled because we don't have cues. If cues, with timestamps after 622 // stalled because we don't have cues. If cues, with timestamps after
628 // the seek time, eventually arrive they will be delivered properly 623 // the seek time, eventually arrive they will be delivered properly
629 // in response to ChunkDemuxerStream::Read() calls. 624 // in response to ChunkDemuxerStream::Read() calls.
630 625
631 return false; 626 return false;
632 } 627 }
633 628
634 void SourceState::AdjustBufferTimestamps( 629 void SourceState::AdjustBufferTimestamps(
635 const StreamParser::BufferQueue& buffers) { 630 const StreamParser::BufferQueue& buffers) {
636 if (timestamp_offset_ == TimeDelta()) 631 TimeDelta timestamp_offset = *timestamp_offset_during_append_;
632 if (timestamp_offset == TimeDelta())
637 return; 633 return;
638 634
639 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); 635 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
640 itr != buffers.end(); ++itr) { 636 itr != buffers.end(); ++itr) {
641 (*itr)->SetDecodeTimestamp( 637 (*itr)->SetDecodeTimestamp(
642 (*itr)->GetDecodeTimestamp() + timestamp_offset_); 638 (*itr)->GetDecodeTimestamp() + timestamp_offset);
643 (*itr)->set_timestamp((*itr)->timestamp() + timestamp_offset_); 639 (*itr)->set_timestamp((*itr)->timestamp() + timestamp_offset);
644 } 640 }
645 } 641 }
646 642
647 bool SourceState::OnNewConfigs( 643 bool SourceState::OnNewConfigs(
648 bool allow_audio, bool allow_video, 644 bool allow_audio, bool allow_video,
649 const AudioDecoderConfig& audio_config, 645 const AudioDecoderConfig& audio_config,
650 const VideoDecoderConfig& video_config, 646 const VideoDecoderConfig& video_config,
651 const StreamParser::TextTrackConfigMap& text_configs) { 647 const StreamParser::TextTrackConfigMap& text_configs) {
652 DVLOG(1) << "OnNewConfigs(" << allow_audio << ", " << allow_video 648 DVLOG(1) << "OnNewConfigs(" << allow_audio << ", " << allow_video
653 << ", " << audio_config.IsValidConfig() 649 << ", " << audio_config.IsValidConfig()
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 void SourceState::OnEndOfMediaSegment() { 771 void SourceState::OnEndOfMediaSegment() {
776 DVLOG(2) << "OnEndOfMediaSegment()"; 772 DVLOG(2) << "OnEndOfMediaSegment()";
777 parsing_media_segment_ = false; 773 parsing_media_segment_ = false;
778 new_media_segment_ = false; 774 new_media_segment_ = false;
779 } 775 }
780 776
781 bool SourceState::OnNewBuffers( 777 bool SourceState::OnNewBuffers(
782 const StreamParser::BufferQueue& audio_buffers, 778 const StreamParser::BufferQueue& audio_buffers,
783 const StreamParser::BufferQueue& video_buffers, 779 const StreamParser::BufferQueue& video_buffers,
784 const StreamParser::TextBufferQueueMap& text_map) { 780 const StreamParser::TextBufferQueueMap& text_map) {
781 DVLOG(2) << "OnNewBuffers()";
782 DCHECK(timestamp_offset_during_append_);
785 DCHECK(!audio_buffers.empty() || !video_buffers.empty() || 783 DCHECK(!audio_buffers.empty() || !video_buffers.empty() ||
786 !text_map.empty()); 784 !text_map.empty());
787 785
788 // TODO(wolenetz): DCHECK + return false if any of these buffers have UNKNOWN 786 // TODO(wolenetz): DCHECK + return false if any of these buffers have UNKNOWN
789 // type() in upcoming coded frame processing compliant implementation. See 787 // type() in upcoming coded frame processing compliant implementation. See
790 // http://crbug.com/249422. 788 // http://crbug.com/249422.
791 789
792 AdjustBufferTimestamps(audio_buffers); 790 AdjustBufferTimestamps(audio_buffers);
793 AdjustBufferTimestamps(video_buffers); 791 AdjustBufferTimestamps(video_buffers);
794 792
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 itr != buffers.end(); ++itr) { 906 itr != buffers.end(); ++itr) {
909 // Filter out buffers that are outside the append window. Anytime 907 // Filter out buffers that are outside the append window. Anytime
910 // a buffer gets dropped we need to set |*needs_keyframe| to true 908 // a buffer gets dropped we need to set |*needs_keyframe| to true
911 // because we can only resume decoding at keyframes. 909 // because we can only resume decoding at keyframes.
912 TimeDelta presentation_timestamp = (*itr)->timestamp(); 910 TimeDelta presentation_timestamp = (*itr)->timestamp();
913 911
914 // TODO(acolwell): Change |frame_end_timestamp| value to 912 // TODO(acolwell): Change |frame_end_timestamp| value to
915 // |presentation_timestamp + (*itr)->duration()|, like the spec 913 // |presentation_timestamp + (*itr)->duration()|, like the spec
916 // requires, once frame durations are actually present in all buffers. 914 // requires, once frame durations are actually present in all buffers.
917 TimeDelta frame_end_timestamp = presentation_timestamp; 915 TimeDelta frame_end_timestamp = presentation_timestamp;
918 if (presentation_timestamp < append_window_start_ || 916 if (presentation_timestamp < append_window_start_during_append_ ||
919 frame_end_timestamp > append_window_end_) { 917 frame_end_timestamp > append_window_end_during_append_) {
920 DVLOG(1) << "Dropping buffer outside append window." 918 DVLOG(1) << "Dropping buffer outside append window."
921 << " presentation_timestamp " 919 << " presentation_timestamp "
922 << presentation_timestamp.InSecondsF(); 920 << presentation_timestamp.InSecondsF();
923 *needs_keyframe = true; 921 *needs_keyframe = true;
924 922
925 // This triggers a discontinuity so we need to treat the next frames 923 // This triggers a discontinuity so we need to treat the next frames
926 // appended within the append window as if they were the beginning of a 924 // appended within the append window as if they were the beginning of a
927 // new segment. 925 // new segment.
928 new_media_segment_ = true; 926 new_media_segment_ = true;
929 continue; 927 continue;
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after
1414 DCHECK(!id.empty()); 1412 DCHECK(!id.empty());
1415 1413
1416 SourceStateMap::const_iterator itr = source_state_map_.find(id); 1414 SourceStateMap::const_iterator itr = source_state_map_.find(id);
1417 1415
1418 DCHECK(itr != source_state_map_.end()); 1416 DCHECK(itr != source_state_map_.end());
1419 return itr->second->GetBufferedRanges(duration_, state_ == ENDED); 1417 return itr->second->GetBufferedRanges(duration_, state_ == ENDED);
1420 } 1418 }
1421 1419
1422 void ChunkDemuxer::AppendData(const std::string& id, 1420 void ChunkDemuxer::AppendData(const std::string& id,
1423 const uint8* data, size_t length, 1421 const uint8* data, size_t length,
1424 double* timestamp_offset) { 1422 TimeDelta append_window_start,
1423 TimeDelta append_window_end,
1424 TimeDelta* timestamp_offset) {
1425 DVLOG(1) << "AppendData(" << id << ", " << length << ")"; 1425 DVLOG(1) << "AppendData(" << id << ", " << length << ")";
1426 1426
1427 DCHECK(!id.empty()); 1427 DCHECK(!id.empty());
1428 DCHECK(timestamp_offset);
1428 1429
1429 Ranges<TimeDelta> ranges; 1430 Ranges<TimeDelta> ranges;
1430 1431
1431 { 1432 {
1432 base::AutoLock auto_lock(lock_); 1433 base::AutoLock auto_lock(lock_);
1433 DCHECK_NE(state_, ENDED); 1434 DCHECK_NE(state_, ENDED);
1434 1435
1435 // Capture if any of the SourceBuffers are waiting for data before we start 1436 // Capture if any of the SourceBuffers are waiting for data before we start
1436 // parsing. 1437 // parsing.
1437 bool old_waiting_for_data = IsSeekWaitingForData_Locked(); 1438 bool old_waiting_for_data = IsSeekWaitingForData_Locked();
1438 1439
1439 if (length == 0u) 1440 if (length == 0u)
1440 return; 1441 return;
1441 1442
1442 DCHECK(data); 1443 DCHECK(data);
1443 1444
1444 switch (state_) { 1445 switch (state_) {
1445 case INITIALIZING: 1446 case INITIALIZING:
1446 DCHECK(IsValidId(id)); 1447 DCHECK(IsValidId(id));
1447 if (!source_state_map_[id]->Append(data, length, 1448 if (!source_state_map_[id]->Append(data, length,
1449 append_window_start,
1450 append_window_end,
1448 timestamp_offset)) { 1451 timestamp_offset)) {
1449 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); 1452 ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
1450 return; 1453 return;
1451 } 1454 }
1452 break; 1455 break;
1453 1456
1454 case INITIALIZED: { 1457 case INITIALIZED: {
1455 DCHECK(IsValidId(id)); 1458 DCHECK(IsValidId(id));
1456 if (!source_state_map_[id]->Append(data, length, 1459 if (!source_state_map_[id]->Append(data, length,
1460 append_window_start,
1461 append_window_end,
1457 timestamp_offset)) { 1462 timestamp_offset)) {
1458 ReportError_Locked(PIPELINE_ERROR_DECODE); 1463 ReportError_Locked(PIPELINE_ERROR_DECODE);
1459 return; 1464 return;
1460 } 1465 }
1461 } break; 1466 } break;
1462 1467
1463 case PARSE_ERROR: 1468 case PARSE_ERROR:
1464 DVLOG(1) << "AppendData(): Ignoring data after a parse error."; 1469 DVLOG(1) << "AppendData(): Ignoring data after a parse error.";
1465 return; 1470 return;
1466 1471
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1559 user_specified_duration_ = duration; 1564 user_specified_duration_ = duration;
1560 duration_ = duration_td; 1565 duration_ = duration_td;
1561 host_->SetDuration(duration_); 1566 host_->SetDuration(duration_);
1562 1567
1563 for (SourceStateMap::iterator itr = source_state_map_.begin(); 1568 for (SourceStateMap::iterator itr = source_state_map_.begin();
1564 itr != source_state_map_.end(); ++itr) { 1569 itr != source_state_map_.end(); ++itr) {
1565 itr->second->OnSetDuration(duration_); 1570 itr->second->OnSetDuration(duration_);
1566 } 1571 }
1567 } 1572 }
1568 1573
1569 bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { 1574 bool ChunkDemuxer::IsParsingMediaSegment(const std::string& id) {
1570 base::AutoLock auto_lock(lock_); 1575 base::AutoLock auto_lock(lock_);
1571 DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; 1576 DVLOG(1) << "IsParsingMediaSegment(" << id << ")";
1572 CHECK(IsValidId(id)); 1577 CHECK(IsValidId(id));
1573 1578
1574 return source_state_map_[id]->SetTimestampOffset(offset); 1579 return source_state_map_[id]->parsing_media_segment();
1575 } 1580 }
1576 1581
1577 bool ChunkDemuxer::SetSequenceMode(const std::string& id, 1582 void ChunkDemuxer::SetSequenceMode(const std::string& id,
1578 bool sequence_mode) { 1583 bool sequence_mode) {
1579 base::AutoLock auto_lock(lock_); 1584 base::AutoLock auto_lock(lock_);
1580 DVLOG(1) << "SetSequenceMode(" << id << ", " << sequence_mode << ")"; 1585 DVLOG(1) << "SetSequenceMode(" << id << ", " << sequence_mode << ")";
1581 CHECK(IsValidId(id)); 1586 CHECK(IsValidId(id));
1582 DCHECK_NE(state_, ENDED); 1587 DCHECK_NE(state_, ENDED);
1583 1588
1584 return source_state_map_[id]->SetSequenceMode(sequence_mode); 1589 source_state_map_[id]->SetSequenceMode(sequence_mode);
1585 } 1590 }
1586 1591
1587 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { 1592 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) {
1588 DVLOG(1) << "MarkEndOfStream(" << status << ")"; 1593 DVLOG(1) << "MarkEndOfStream(" << status << ")";
1589 base::AutoLock auto_lock(lock_); 1594 base::AutoLock auto_lock(lock_);
1590 DCHECK_NE(state_, WAITING_FOR_INIT); 1595 DCHECK_NE(state_, WAITING_FOR_INIT);
1591 DCHECK_NE(state_, ENDED); 1596 DCHECK_NE(state_, ENDED);
1592 1597
1593 if (state_ == SHUTDOWN || state_ == PARSE_ERROR) 1598 if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
1594 return; 1599 return;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1627 DCHECK_EQ(state_, ENDED); 1632 DCHECK_EQ(state_, ENDED);
1628 1633
1629 ChangeState_Locked(INITIALIZED); 1634 ChangeState_Locked(INITIALIZED);
1630 1635
1631 for (SourceStateMap::iterator itr = source_state_map_.begin(); 1636 for (SourceStateMap::iterator itr = source_state_map_.begin();
1632 itr != source_state_map_.end(); ++itr) { 1637 itr != source_state_map_.end(); ++itr) {
1633 itr->second->UnmarkEndOfStream(); 1638 itr->second->UnmarkEndOfStream();
1634 } 1639 }
1635 } 1640 }
1636 1641
1637 void ChunkDemuxer::SetAppendWindowStart(const std::string& id,
1638 TimeDelta start) {
1639 base::AutoLock auto_lock(lock_);
1640 DVLOG(1) << "SetAppendWindowStart(" << id << ", "
1641 << start.InSecondsF() << ")";
1642 CHECK(IsValidId(id));
1643 source_state_map_[id]->set_append_window_start(start);
1644 }
1645
1646 void ChunkDemuxer::SetAppendWindowEnd(const std::string& id, TimeDelta end) {
1647 base::AutoLock auto_lock(lock_);
1648 DVLOG(1) << "SetAppendWindowEnd(" << id << ", " << end.InSecondsF() << ")";
1649 CHECK(IsValidId(id));
1650 source_state_map_[id]->set_append_window_end(end);
1651 }
1652
1653 void ChunkDemuxer::Shutdown() { 1642 void ChunkDemuxer::Shutdown() {
1654 DVLOG(1) << "Shutdown()"; 1643 DVLOG(1) << "Shutdown()";
1655 base::AutoLock auto_lock(lock_); 1644 base::AutoLock auto_lock(lock_);
1656 1645
1657 if (state_ == SHUTDOWN) 1646 if (state_ == SHUTDOWN)
1658 return; 1647 return;
1659 1648
1660 ShutdownAllStreams(); 1649 ShutdownAllStreams();
1661 1650
1662 ChangeState_Locked(SHUTDOWN); 1651 ChangeState_Locked(SHUTDOWN);
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1880 } 1869 }
1881 1870
1882 void ChunkDemuxer::ShutdownAllStreams() { 1871 void ChunkDemuxer::ShutdownAllStreams() {
1883 for (SourceStateMap::iterator itr = source_state_map_.begin(); 1872 for (SourceStateMap::iterator itr = source_state_map_.begin();
1884 itr != source_state_map_.end(); ++itr) { 1873 itr != source_state_map_.end(); ++itr) {
1885 itr->second->Shutdown(); 1874 itr->second->Shutdown();
1886 } 1875 }
1887 } 1876 }
1888 1877
1889 } // namespace media 1878 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | media/filters/chunk_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698