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

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

Issue 20123002: Add Chromium-side support for SourceBuffer.appendWindowStart and SourceBuffer.appendWindowEnd. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase and remove URL in comment to make presubmit happy. Created 7 years, 4 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 10
(...skipping 26 matching lines...) Expand all
37 37
38 SourceState(scoped_ptr<StreamParser> stream_parser, const LogCB& log_cb, 38 SourceState(scoped_ptr<StreamParser> stream_parser, const LogCB& log_cb,
39 const CreateDemuxerStreamCB& create_demuxer_stream_cb, 39 const CreateDemuxerStreamCB& create_demuxer_stream_cb,
40 const IncreaseDurationCB& increase_duration_cb); 40 const IncreaseDurationCB& increase_duration_cb);
41 41
42 void Init(const StreamParser::InitCB& init_cb, 42 void Init(const StreamParser::InitCB& init_cb,
43 bool allow_audio, 43 bool allow_audio,
44 bool allow_video, 44 bool allow_video,
45 const StreamParser::NewTextBuffersCB& text_cb, 45 const StreamParser::NewTextBuffersCB& text_cb,
46 const StreamParser::NeedKeyCB& need_key_cb, 46 const StreamParser::NeedKeyCB& need_key_cb,
47 const AddTextTrackCB& add_text_track_cb, 47 const AddTextTrackCB& add_text_track_cb);
48 const StreamParser::NewMediaSegmentCB& new_segment_cb);
49 48
50 // Appends new data to the StreamParser. 49 // Appends new data to the StreamParser.
51 // Returns true if the data was successfully appended. Returns false if an 50 // Returns true if the data was successfully appended. Returns false if an
52 // error occurred. 51 // error occurred.
53 bool Append(const uint8* data, size_t length); 52 bool Append(const uint8* data, size_t length);
54 53
55 // Aborts the current append sequence and resets the parser. 54 // Aborts the current append sequence and resets the parser.
56 void Abort(); 55 void Abort();
57 56
58 // Sets |timestamp_offset_| if possible. 57 // Sets |timestamp_offset_| if possible.
59 // Returns if the offset was set. Returns false if the offset could not be 58 // Returns if the offset was set. Returns false if the offset could not be
60 // updated at this time. 59 // updated at this time.
61 bool SetTimestampOffset(TimeDelta timestamp_offset); 60 bool SetTimestampOffset(TimeDelta timestamp_offset);
62 61
63 TimeDelta timestamp_offset() const { return timestamp_offset_; } 62 TimeDelta timestamp_offset() const { return timestamp_offset_; }
64 63
64 void set_append_window_start(TimeDelta start) {
65 append_window_start_ = start;
66 }
67 void set_append_window_end(TimeDelta end) { append_window_end_ = end; }
68
65 private: 69 private:
66 // Called by the |stream_parser_| when a new initialization segment is 70 // Called by the |stream_parser_| when a new initialization segment is
67 // encountered. 71 // encountered.
68 // Returns true on a successful call. Returns false if an error occured while 72 // Returns true on a successful call. Returns false if an error occured while
69 // processing decoder configurations. 73 // processing decoder configurations.
70 bool OnNewConfigs(bool allow_audio, bool allow_video, 74 bool OnNewConfigs(bool allow_audio, bool allow_video,
71 const AudioDecoderConfig& audio_config, 75 const AudioDecoderConfig& audio_config,
72 const VideoDecoderConfig& video_config); 76 const VideoDecoderConfig& video_config);
73 77
74 // Called by the |stream_parser_| at the beginning of a new media segment. 78 // Called by the |stream_parser_| at the beginning of a new media segment.
75 // |timestamp| is the timestamp on the first buffer in the segment. 79 void OnNewMediaSegment();
76 // It modifies the state of this object and then calls |new_segment_cb| with
77 // modified version of |timestamp|.
78 void OnNewMediaSegment(const StreamParser::NewMediaSegmentCB& new_segment_cb,
79 TimeDelta timestamp);
80 80
81 // Called by the |stream_parser_| at the end of a media segment. 81 // Called by the |stream_parser_| at the end of a media segment.
82 void OnEndOfMediaSegment(); 82 void OnEndOfMediaSegment();
83 83
84 // Called by the |stream_parser_| when new buffers have been parsed. It 84 // Called by the |stream_parser_| when new buffers have been parsed. It
85 // applies |timestamp_offset_| to all buffers in |buffers| and then calls 85 // applies |timestamp_offset_| to all buffers in |audio_buffers| and
86 // Append() on either |audio_| or |video_| with the modified buffers based on 86 // |video_buffers| and then calls Append() on |audio_| and/or
87 // the value of |type|. 87 // |video_| with the modified buffers.
88 // Returns true on a successful call. Returns false if an error occured while 88 // Returns true on a successful call. Returns false if an error occured while
89 // processing the buffers. 89 // processing the buffers.
90 bool OnBuffers(DemuxerStream::Type type, 90 bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers,
91 const StreamParser::BufferQueue& buffers); 91 const StreamParser::BufferQueue& video_buffers);
92 92
93 // Called by the |stream_parser_| when new text buffers have been parsed. It 93 // Called by the |stream_parser_| when new text buffers have been parsed. It
94 // applies |timestamp_offset_| to all buffers in |buffers| and then calls 94 // applies |timestamp_offset_| to all buffers in |buffers| and then calls
95 // |new_buffers_cb| with the modified buffers. 95 // |new_buffers_cb| with the modified buffers.
96 // Returns true on a successful call. Returns false if an error occured while 96 // Returns true on a successful call. Returns false if an error occured while
97 // processing the buffers. 97 // processing the buffers.
98 bool OnTextBuffers(const StreamParser::NewTextBuffersCB& new_buffers_cb, 98 bool OnTextBuffers(const StreamParser::NewTextBuffersCB& new_buffers_cb,
99 TextTrack* text_track, 99 TextTrack* text_track,
100 const StreamParser::BufferQueue& buffers); 100 const StreamParser::BufferQueue& buffers);
101 101
102 // Helper function that adds |timestamp_offset_| to each buffer in |buffers|. 102 // Helper function that adds |timestamp_offset_| to each buffer in |buffers|.
103 void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers); 103 void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers);
104 104
105 // Filters out buffers that are outside of the append window
106 // [|append_window_start_|, |append_window_end_|).
107 // |needs_keyframe| is a pointer to the |xxx_need_keyframe_| flag
108 // associated with the |buffers|. Its state is read an updated as
109 // this method filters |buffers|.
110 // Buffers that are inside the append window are appended to the end
111 // of |filtered_buffers|.
112 void FilterWithAppendWindow(const StreamParser::BufferQueue& buffers,
113 bool* needs_keyframe,
114 StreamParser::BufferQueue* filtered_buffers);
115
105 CreateDemuxerStreamCB create_demuxer_stream_cb_; 116 CreateDemuxerStreamCB create_demuxer_stream_cb_;
106 IncreaseDurationCB increase_duration_cb_; 117 IncreaseDurationCB increase_duration_cb_;
107 118
108 // The offset to apply to media segment timestamps. 119 // The offset to apply to media segment timestamps.
109 TimeDelta timestamp_offset_; 120 TimeDelta timestamp_offset_;
110 121
122 TimeDelta append_window_start_;
123 TimeDelta append_window_end_;
124
125 // Set to true if the next buffers appended within the append window
126 // represent the start of a new media segment. This flag being set
127 // triggers a call to |new_segment_cb_| when the new buffers are
128 // appended. The flag is set on actual media segment boundaries and
129 // when the "append window" filtering causes discontinuities in the
130 // appended data.
131 bool new_media_segment_;
132
111 // Keeps track of whether |timestamp_offset_| can be modified. 133 // Keeps track of whether |timestamp_offset_| can be modified.
112 bool can_update_offset_; 134 bool can_update_offset_;
113 135
114 // The object used to parse appended data. 136 // The object used to parse appended data.
115 scoped_ptr<StreamParser> stream_parser_; 137 scoped_ptr<StreamParser> stream_parser_;
116 138
117 ChunkDemuxerStream* audio_; 139 ChunkDemuxerStream* audio_;
140 bool audio_needs_keyframe_;
141
118 ChunkDemuxerStream* video_; 142 ChunkDemuxerStream* video_;
143 bool video_needs_keyframe_;
119 144
120 LogCB log_cb_; 145 LogCB log_cb_;
121 146
122 DISALLOW_COPY_AND_ASSIGN(SourceState); 147 DISALLOW_COPY_AND_ASSIGN(SourceState);
123 }; 148 };
124 149
125 class ChunkDemuxerStream : public DemuxerStream { 150 class ChunkDemuxerStream : public DemuxerStream {
126 public: 151 public:
127 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; 152 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
128 153
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 238
214 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream); 239 DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream);
215 }; 240 };
216 241
217 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, 242 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser,
218 const LogCB& log_cb, 243 const LogCB& log_cb,
219 const CreateDemuxerStreamCB& create_demuxer_stream_cb, 244 const CreateDemuxerStreamCB& create_demuxer_stream_cb,
220 const IncreaseDurationCB& increase_duration_cb) 245 const IncreaseDurationCB& increase_duration_cb)
221 : create_demuxer_stream_cb_(create_demuxer_stream_cb), 246 : create_demuxer_stream_cb_(create_demuxer_stream_cb),
222 increase_duration_cb_(increase_duration_cb), 247 increase_duration_cb_(increase_duration_cb),
248 append_window_end_(kInfiniteDuration()),
249 new_media_segment_(false),
223 can_update_offset_(true), 250 can_update_offset_(true),
224 stream_parser_(stream_parser.release()), 251 stream_parser_(stream_parser.release()),
225 audio_(NULL), 252 audio_(NULL),
253 audio_needs_keyframe_(true),
226 video_(NULL), 254 video_(NULL),
255 video_needs_keyframe_(true),
227 log_cb_(log_cb) { 256 log_cb_(log_cb) {
228 DCHECK(!create_demuxer_stream_cb_.is_null()); 257 DCHECK(!create_demuxer_stream_cb_.is_null());
229 DCHECK(!increase_duration_cb_.is_null()); 258 DCHECK(!increase_duration_cb_.is_null());
230 } 259 }
231 260
232 void SourceState::Init(const StreamParser::InitCB& init_cb, 261 void SourceState::Init(const StreamParser::InitCB& init_cb,
233 bool allow_audio, 262 bool allow_audio,
234 bool allow_video, 263 bool allow_video,
235 const StreamParser::NewTextBuffersCB& text_cb, 264 const StreamParser::NewTextBuffersCB& text_cb,
236 const StreamParser::NeedKeyCB& need_key_cb, 265 const StreamParser::NeedKeyCB& need_key_cb,
237 const AddTextTrackCB& add_text_track_cb, 266 const AddTextTrackCB& add_text_track_cb) {
238 const StreamParser::NewMediaSegmentCB& new_segment_cb) {
239 StreamParser::NewBuffersCB audio_cb; 267 StreamParser::NewBuffersCB audio_cb;
240 StreamParser::NewBuffersCB video_cb;
241
242 if (allow_audio) {
243 audio_cb = base::Bind(&SourceState::OnBuffers,
244 base::Unretained(this), DemuxerStream::AUDIO);
245 }
246
247 if (allow_video) {
248 video_cb = base::Bind(&SourceState::OnBuffers,
249 base::Unretained(this), DemuxerStream::VIDEO);
250 }
251 268
252 stream_parser_->Init(init_cb, 269 stream_parser_->Init(init_cb,
253 base::Bind(&SourceState::OnNewConfigs, 270 base::Bind(&SourceState::OnNewConfigs,
254 base::Unretained(this), 271 base::Unretained(this),
255 allow_audio, 272 allow_audio,
256 allow_video), 273 allow_video),
257 audio_cb, 274 base::Bind(&SourceState::OnNewBuffers,
258 video_cb, 275 base::Unretained(this)),
259 base::Bind(&SourceState::OnTextBuffers, 276 base::Bind(&SourceState::OnTextBuffers,
260 base::Unretained(this), text_cb), 277 base::Unretained(this), text_cb),
261 need_key_cb, 278 need_key_cb,
262 add_text_track_cb, 279 add_text_track_cb,
263 base::Bind(&SourceState::OnNewMediaSegment, 280 base::Bind(&SourceState::OnNewMediaSegment,
264 base::Unretained(this), new_segment_cb), 281 base::Unretained(this)),
265 base::Bind(&SourceState::OnEndOfMediaSegment, 282 base::Bind(&SourceState::OnEndOfMediaSegment,
266 base::Unretained(this)), 283 base::Unretained(this)),
267 log_cb_); 284 log_cb_);
268 } 285 }
269 286
270 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) { 287 bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) {
271 if (!can_update_offset_) 288 if (!can_update_offset_)
272 return false; 289 return false;
273 290
274 timestamp_offset_ = timestamp_offset; 291 timestamp_offset_ = timestamp_offset;
275 return true; 292 return true;
276 } 293 }
277 294
278 bool SourceState::Append(const uint8* data, size_t length) { 295 bool SourceState::Append(const uint8* data, size_t length) {
279 return stream_parser_->Parse(data, length); 296 return stream_parser_->Parse(data, length);
280 } 297 }
281 298
282 void SourceState::Abort() { 299 void SourceState::Abort() {
283 stream_parser_->Flush(); 300 stream_parser_->Flush();
301 audio_needs_keyframe_ = true;
302 video_needs_keyframe_ = true;
284 can_update_offset_ = true; 303 can_update_offset_ = true;
285 } 304 }
286 305
287 void SourceState::AdjustBufferTimestamps( 306 void SourceState::AdjustBufferTimestamps(
288 const StreamParser::BufferQueue& buffers) { 307 const StreamParser::BufferQueue& buffers) {
289 if (timestamp_offset_ == TimeDelta()) 308 if (timestamp_offset_ == TimeDelta())
290 return; 309 return;
291 310
292 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); 311 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
293 itr != buffers.end(); ++itr) { 312 itr != buffers.end(); ++itr) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 } 374 }
356 } 375 }
357 376
358 success &= video_->UpdateVideoConfig(video_config, log_cb_); 377 success &= video_->UpdateVideoConfig(video_config, log_cb_);
359 } 378 }
360 379
361 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed"); 380 DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed");
362 return success; 381 return success;
363 } 382 }
364 383
365 void SourceState::OnNewMediaSegment( 384 void SourceState::OnNewMediaSegment() {
366 const StreamParser::NewMediaSegmentCB& new_segment_cb, 385 DVLOG(2) << "OnNewMediaSegment()";
367 TimeDelta timestamp) {
368 DCHECK(timestamp != kNoTimestamp());
369 DVLOG(2) << "OnNewMediaSegment(" << timestamp.InSecondsF() << ")";
370
371 can_update_offset_ = false; 386 can_update_offset_ = false;
372 new_segment_cb.Run(timestamp + timestamp_offset_); 387 new_media_segment_ = true;
373 } 388 }
374 389
375 void SourceState::OnEndOfMediaSegment() { 390 void SourceState::OnEndOfMediaSegment() {
376 DVLOG(2) << "OnEndOfMediaSegment()"; 391 DVLOG(2) << "OnEndOfMediaSegment()";
377 can_update_offset_ = true; 392 can_update_offset_ = true;
393 new_media_segment_ = false;
378 } 394 }
379 395
380 bool SourceState::OnBuffers(DemuxerStream::Type type, 396 bool SourceState::OnNewBuffers(const StreamParser::BufferQueue& audio_buffers,
381 const StreamParser::BufferQueue& buffers) { 397 const StreamParser::BufferQueue& video_buffers) {
382 DCHECK(!buffers.empty()); 398 DCHECK(!audio_buffers.empty() || !video_buffers.empty());
383 AdjustBufferTimestamps(buffers); 399 AdjustBufferTimestamps(audio_buffers);
400 AdjustBufferTimestamps(video_buffers);
384 401
385 ChunkDemuxerStream* stream = NULL; 402 StreamParser::BufferQueue filtered_audio;
386 switch (type) { 403 StreamParser::BufferQueue filtered_video;
387 case DemuxerStream::AUDIO: 404
388 stream = audio_; 405 FilterWithAppendWindow(audio_buffers, &audio_needs_keyframe_,
389 break; 406 &filtered_audio);
390 case DemuxerStream::VIDEO: 407
391 stream = video_; 408 FilterWithAppendWindow(video_buffers, &video_needs_keyframe_,
392 break; 409 &filtered_video);
393 case DemuxerStream::UNKNOWN: 410
394 case DemuxerStream::NUM_TYPES: 411 if (filtered_audio.empty() && filtered_video.empty())
395 NOTREACHED(); 412 return true;
396 return false; 413
414 if (new_media_segment_) {
415 // Find the earliest timestamp in the filtered buffers and use that for the
416 // segment start timestamp.
417 TimeDelta segment_timestamp = kNoTimestamp();
418
419 if (!filtered_audio.empty())
420 segment_timestamp = filtered_audio.front()->GetDecodeTimestamp();
421
422 if (!filtered_video.empty() &&
423 (segment_timestamp == kNoTimestamp() ||
424 filtered_video.front()->GetDecodeTimestamp() < segment_timestamp)) {
425 segment_timestamp = filtered_video.front()->GetDecodeTimestamp();
426 }
427
428 new_media_segment_ = false;
429
430 if (audio_)
431 audio_->OnNewMediaSegment(segment_timestamp);
432
433 if (video_)
434 video_->OnNewMediaSegment(segment_timestamp);
397 } 435 }
398 436
399 if (!stream->Append(buffers)) 437 if (!filtered_audio.empty()) {
400 return false; 438 if (!audio_ || !audio_->Append(filtered_audio))
401 increase_duration_cb_.Run(buffers.back()->timestamp(), stream); 439 return false;
440 increase_duration_cb_.Run(filtered_audio.back()->timestamp(), audio_);
441 }
442
443 if (!filtered_video.empty()) {
444 if (!video_ || !video_->Append(filtered_video))
445 return false;
446 increase_duration_cb_.Run(filtered_video.back()->timestamp(), video_);
447 }
448
402 return true; 449 return true;
403 } 450 }
404 451
405 bool SourceState::OnTextBuffers( 452 bool SourceState::OnTextBuffers(
406 const StreamParser::NewTextBuffersCB& new_buffers_cb, 453 const StreamParser::NewTextBuffersCB& new_buffers_cb,
407 TextTrack* text_track, 454 TextTrack* text_track,
408 const StreamParser::BufferQueue& buffers) { 455 const StreamParser::BufferQueue& buffers) {
409 if (new_buffers_cb.is_null()) 456 if (new_buffers_cb.is_null())
410 return false; 457 return false;
411 458
412 AdjustBufferTimestamps(buffers); 459 AdjustBufferTimestamps(buffers);
413 460
414 return new_buffers_cb.Run(text_track, buffers); 461 return new_buffers_cb.Run(text_track, buffers);
415 } 462 }
416 463
464 void SourceState::FilterWithAppendWindow(
465 const StreamParser::BufferQueue& buffers, bool* needs_keyframe,
466 StreamParser::BufferQueue* filtered_buffers) {
467 DCHECK(needs_keyframe);
468 DCHECK(filtered_buffers);
469
470 // This loop implements steps 1.9, 1.10, & 1.11 of the "Coded frame
471 // processing loop" in the Media Source Extensions spec.
472 // These steps filter out buffers that are not within the "append
473 // window" and handles resyncing on the next random access point
474 // (i.e., next keyframe) if a buffer gets dropped.
475 for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
476 itr != buffers.end(); ++itr) {
477 // Filter out buffers that are outside the append window. Anytime
478 // a buffer gets dropped we need to set |*needs_keyframe| to true
479 // because we can only resume decoding at keyframes.
480 TimeDelta presentation_timestamp = (*itr)->timestamp();
481
482 // TODO(acolwell): Change |frame_end_timestamp| value to
483 // |presentation_timestamp + (*itr)->duration()|, like the spec
484 // requires, once frame durations are actually present in all buffers.
485 TimeDelta frame_end_timestamp = presentation_timestamp;
486 if (presentation_timestamp < append_window_start_ ||
487 frame_end_timestamp > append_window_end_) {
488 DVLOG(1) << "Dropping buffer outside append window."
489 << " presentation_timestamp "
490 << presentation_timestamp.InSecondsF();
491 *needs_keyframe = true;
492
493 // This triggers a discontinuity so we need to treat the next frames
494 // appended within the append window as if they were the beginning of a
495 // new segment.
496 new_media_segment_ = true;
497 continue;
498 }
499
500 // If |*needs_keyframe| is true then filter out buffers until we
501 // encounter the next keyframe.
502 if (*needs_keyframe) {
503 if (!(*itr)->IsKeyframe()) {
504 DVLOG(1) << "Dropping non-keyframe. presentation_timestamp "
505 << presentation_timestamp.InSecondsF();
506 continue;
507 }
508
509 *needs_keyframe = false;
510 }
511
512 filtered_buffers->push_back(*itr);
513 }
514 }
515
417 ChunkDemuxerStream::ChunkDemuxerStream(Type type) 516 ChunkDemuxerStream::ChunkDemuxerStream(Type type)
418 : type_(type), 517 : type_(type),
419 state_(UNINITIALIZED) { 518 state_(UNINITIALIZED) {
420 } 519 }
421 520
422 void ChunkDemuxerStream::StartReturningData() { 521 void ChunkDemuxerStream::StartReturningData() {
423 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()"; 522 DVLOG(1) << "ChunkDemuxerStream::StartReturningData()";
424 base::AutoLock auto_lock(lock_); 523 base::AutoLock auto_lock(lock_);
425 DCHECK(read_cb_.is_null()); 524 DCHECK(read_cb_.is_null());
426 ChangeState_Locked(RETURNING_DATA_FOR_READS); 525 ChangeState_Locked(RETURNING_DATA_FOR_READS);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 606
508 // Clamp the end of the stream's buffered ranges to fit within the duration. 607 // Clamp the end of the stream's buffered ranges to fit within the duration.
509 // This can be done by intersecting the stream's range with the valid time 608 // This can be done by intersecting the stream's range with the valid time
510 // range. 609 // range.
511 Ranges<TimeDelta> valid_time_range; 610 Ranges<TimeDelta> valid_time_range;
512 valid_time_range.Add(range.start(0), duration); 611 valid_time_range.Add(range.start(0), duration);
513 return range.IntersectionWith(valid_time_range); 612 return range.IntersectionWith(valid_time_range);
514 } 613 }
515 614
516 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) { 615 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) {
616 DVLOG(2) << "ChunkDemuxerStream::OnNewMediaSegment("
617 << start_timestamp.InSecondsF() << ")";
517 base::AutoLock auto_lock(lock_); 618 base::AutoLock auto_lock(lock_);
518 stream_->OnNewMediaSegment(start_timestamp); 619 stream_->OnNewMediaSegment(start_timestamp);
519 } 620 }
520 621
521 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config, 622 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config,
522 const LogCB& log_cb) { 623 const LogCB& log_cb) {
523 DCHECK(config.IsValidConfig()); 624 DCHECK(config.IsValidConfig());
524 DCHECK_EQ(type_, AUDIO); 625 DCHECK_EQ(type_, AUDIO);
525 base::AutoLock auto_lock(lock_); 626 base::AutoLock auto_lock(lock_);
526 if (!stream_) { 627 if (!stream_) {
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 897
797 if (has_video) 898 if (has_video)
798 source_id_video_ = id; 899 source_id_video_ = id;
799 900
800 scoped_ptr<SourceState> source_state( 901 scoped_ptr<SourceState> source_state(
801 new SourceState(stream_parser.Pass(), log_cb_, 902 new SourceState(stream_parser.Pass(), log_cb_,
802 base::Bind(&ChunkDemuxer::CreateDemuxerStream, 903 base::Bind(&ChunkDemuxer::CreateDemuxerStream,
803 base::Unretained(this)), 904 base::Unretained(this)),
804 base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary, 905 base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary,
805 base::Unretained(this)))); 906 base::Unretained(this))));
907
806 source_state->Init( 908 source_state->Init(
807 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)), 909 base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)),
808 has_audio, 910 has_audio,
809 has_video, 911 has_video,
810 base::Bind(&ChunkDemuxer::OnTextBuffers, base::Unretained(this)), 912 base::Bind(&ChunkDemuxer::OnTextBuffers, base::Unretained(this)),
811 need_key_cb_, 913 need_key_cb_,
812 add_text_track_cb_, 914 add_text_track_cb_);
813 base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id));
814 915
815 source_state_map_[id] = source_state.release(); 916 source_state_map_[id] = source_state.release();
816 return kOk; 917 return kOk;
817 } 918 }
818 919
819 void ChunkDemuxer::RemoveId(const std::string& id) { 920 void ChunkDemuxer::RemoveId(const std::string& id) {
820 base::AutoLock auto_lock(lock_); 921 base::AutoLock auto_lock(lock_);
821 CHECK(IsValidId(id)); 922 CHECK(IsValidId(id));
822 923
823 delete source_state_map_[id]; 924 delete source_state_map_[id];
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 1187
1087 ChangeState_Locked(INITIALIZED); 1188 ChangeState_Locked(INITIALIZED);
1088 1189
1089 if (audio_) 1190 if (audio_)
1090 audio_->UnmarkEndOfStream(); 1191 audio_->UnmarkEndOfStream();
1091 1192
1092 if (video_) 1193 if (video_)
1093 video_->UnmarkEndOfStream(); 1194 video_->UnmarkEndOfStream();
1094 } 1195 }
1095 1196
1197 void ChunkDemuxer::SetAppendWindowStart(const std::string& id,
1198 TimeDelta start) {
1199 base::AutoLock auto_lock(lock_);
1200 DVLOG(1) << "SetAppendWindowStart(" << id << ", "
1201 << start.InSecondsF() << ")";
1202 CHECK(IsValidId(id));
1203 source_state_map_[id]->set_append_window_start(start);
1204 }
1205
1206 void ChunkDemuxer::SetAppendWindowEnd(const std::string& id, TimeDelta end) {
1207 base::AutoLock auto_lock(lock_);
1208 DVLOG(1) << "SetAppendWindowEnd(" << id << ", " << end.InSecondsF() << ")";
1209 CHECK(IsValidId(id));
1210 source_state_map_[id]->set_append_window_end(end);
1211 }
1212
1096 void ChunkDemuxer::Shutdown() { 1213 void ChunkDemuxer::Shutdown() {
1097 DVLOG(1) << "Shutdown()"; 1214 DVLOG(1) << "Shutdown()";
1098 base::AutoLock auto_lock(lock_); 1215 base::AutoLock auto_lock(lock_);
1099 1216
1100 if (state_ == SHUTDOWN) 1217 if (state_ == SHUTDOWN)
1101 return; 1218 return;
1102 1219
1103 if (audio_) 1220 if (audio_)
1104 audio_->Shutdown(); 1221 audio_->Shutdown();
1105 1222
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 WebMWebVTTParser::Parse(buffer->data(), 1369 WebMWebVTTParser::Parse(buffer->data(),
1253 buffer->data_size(), 1370 buffer->data_size(),
1254 &id, &settings, &content); 1371 &id, &settings, &content);
1255 1372
1256 text_track->addWebVTTCue(start, end, id, content, settings); 1373 text_track->addWebVTTCue(start, end, id, content, settings);
1257 } 1374 }
1258 1375
1259 return true; 1376 return true;
1260 } 1377 }
1261 1378
1262 void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id,
1263 TimeDelta timestamp) {
1264 DCHECK(timestamp != kNoTimestamp());
1265 DVLOG(2) << "OnNewMediaSegment(" << source_id << ", "
1266 << timestamp.InSecondsF() << ")";
1267 lock_.AssertAcquired();
1268
1269 CHECK(IsValidId(source_id));
1270 if (audio_ && source_id == source_id_audio_)
1271 audio_->OnNewMediaSegment(timestamp);
1272 if (video_ && source_id == source_id_video_)
1273 video_->OnNewMediaSegment(timestamp);
1274 }
1275
1276 bool ChunkDemuxer::IsValidId(const std::string& source_id) const { 1379 bool ChunkDemuxer::IsValidId(const std::string& source_id) const {
1277 lock_.AssertAcquired(); 1380 lock_.AssertAcquired();
1278 return source_state_map_.count(source_id) > 0u; 1381 return source_state_map_.count(source_id) > 0u;
1279 } 1382 }
1280 1383
1281 void ChunkDemuxer::UpdateDuration(TimeDelta new_duration) { 1384 void ChunkDemuxer::UpdateDuration(TimeDelta new_duration) {
1282 DCHECK(duration_ != new_duration); 1385 DCHECK(duration_ != new_duration);
1283 user_specified_duration_ = -1; 1386 user_specified_duration_ = -1;
1284 duration_ = new_duration; 1387 duration_ = new_duration;
1285 host_->SetDuration(new_duration); 1388 host_->SetDuration(new_duration);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1344 1447
1345 void ChunkDemuxer::CompletePendingReadsIfPossible() { 1448 void ChunkDemuxer::CompletePendingReadsIfPossible() {
1346 if (audio_) 1449 if (audio_)
1347 audio_->CompletePendingReadIfPossible(); 1450 audio_->CompletePendingReadIfPossible();
1348 1451
1349 if (video_) 1452 if (video_)
1350 video_->CompletePendingReadIfPossible(); 1453 video_->CompletePendingReadIfPossible();
1351 } 1454 }
1352 1455
1353 } // namespace media 1456 } // 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