1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/renderer/media/websourcebuffer_impl.h" 6 7 #include <limits> 8 9 #include "base/float_util.h" 10 #include "media/filters/chunk_demuxer.h" 11 12 namespace content { 13 14 static base::TimeDelta DoubleToTimeDelta(double time) { 15 DCHECK(!base::IsNaN(time)); 16 DCHECK_NE(time, -std::numeric_limits<double>::infinity()); 17 18 if (time == std::numeric_limits<double>::infinity()) 19 return media::kInfiniteDuration(); 20 21 // Don't use base::TimeDelta::Max() here, as we want the largest finite time 22 // delta. 23 base::TimeDelta max_time = base::TimeDelta::FromInternalValue(kint64max - 1); 24 double max_time_in_seconds = max_time.InSecondsF(); 25 26 if (time >= max_time_in_seconds) 27 return max_time; 28 29 return base::TimeDelta::FromMicroseconds( 30 time * base::Time::kMicrosecondsPerSecond); 31 } 32 33 WebSourceBufferImpl::WebSourceBufferImpl( 34 const std::string& id, media::ChunkDemuxer* demuxer) 35 : id_(id), 36 demuxer_(demuxer), 37 append_window_end_(media::kInfiniteDuration()) { 38 DCHECK(demuxer_); 39 } 40 41 WebSourceBufferImpl::~WebSourceBufferImpl() { 42 DCHECK(!demuxer_) << "Object destroyed w/o removedFromMediaSource() call"; 43 } 44 45 bool WebSourceBufferImpl::setMode(WebSourceBuffer::AppendMode mode) { 46 if (demuxer_->IsParsingMediaSegment(id_)) 47 return false; 48 49 switch (mode) { 50 case WebSourceBuffer::AppendModeSegments: 51 demuxer_->SetSequenceMode(id_, false); 52 return true; 53 case WebSourceBuffer::AppendModeSequence: 54 demuxer_->SetSequenceMode(id_, true); 55 return true; 56 } 57 58 NOTREACHED(); 59 return false; 60 } 61 62 blink::WebTimeRanges WebSourceBufferImpl::buffered() { 63 media::Ranges<base::TimeDelta> ranges = demuxer_->GetBufferedRanges(id_); 64 blink::WebTimeRanges result(ranges.size()); 65 for (size_t i = 0; i < ranges.size(); i++) { 66 result[i].start = ranges.start(i).InSecondsF(); 67 result[i].end = ranges.end(i).InSecondsF(); 68 } 69 return result; 70 } 71 72 void WebSourceBufferImpl::append( 73 const unsigned char* data, 74 unsigned length, 75 double* timestamp_offset) { 76 base::TimeDelta old_offset = timestamp_offset_; 77 demuxer_->AppendData(id_, data, length, 78 append_window_start_, append_window_end_, 79 ×tamp_offset_); 80 81 // Coded frame processing may update the timestamp offset. If the caller 82 // provides a non-NULL |timestamp_offset| and frame processing changes the 83 // timestamp offset, report the new offset to the caller. Do not update the 84 // caller's offset otherwise, to preserve any pre-existing value that may have 85 // more than microsecond precision. 86 if (timestamp_offset && old_offset != timestamp_offset_) 87 *timestamp_offset = timestamp_offset_.InSecondsF(); 88 } 89 90 void WebSourceBufferImpl::abort() { 91 demuxer_->Abort(id_, 92 append_window_start_, append_window_end_, 93 ×tamp_offset_); 94 95 // TODO(wolenetz): abort should be able to modify the caller timestamp offset 96 // (just like WebSourceBufferImpl::append). 97 // See http://crbug.com/370229 for further details. 98 } 99 100 void WebSourceBufferImpl::remove(double start, double end) { 101 DCHECK_GE(start, 0); 102 DCHECK_GE(end, 0); 103 demuxer_->Remove(id_, DoubleToTimeDelta(start), DoubleToTimeDelta(end)); 104 } 105 106 bool WebSourceBufferImpl::setTimestampOffset(double offset) { 107 if (demuxer_->IsParsingMediaSegment(id_)) 108 return false; 109 110 timestamp_offset_ = DoubleToTimeDelta(offset); 111 112 // http://www.w3.org/TR/media-source/#widl-SourceBuffer-timestampOffset 113 // Step 6: If the mode attribute equals "sequence", then set the group start 114 // timestamp to new timestamp offset. 115 demuxer_->SetGroupStartTimestampIfInSequenceMode(id_, timestamp_offset_); 116 return true; 117 } 118 119 void WebSourceBufferImpl::setAppendWindowStart(double start) { 120 DCHECK_GE(start, 0); 121 append_window_start_ = DoubleToTimeDelta(start); 122 } 123 124 void WebSourceBufferImpl::setAppendWindowEnd(double end) { 125 DCHECK_GE(end, 0); 126 append_window_end_ = DoubleToTimeDelta(end); 127 } 128 129 void WebSourceBufferImpl::removedFromMediaSource() { 130 demuxer_->RemoveId(id_); 131 demuxer_ = NULL; 132 } 133 134 } // namespace content 135