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.
5 #include "media/blink/websourcebuffer_impl.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/callback_helpers.h"
13 #include "media/base/timestamp_constants.h"
14 #include "media/filters/chunk_demuxer.h"
15 #include "third_party/WebKit/public/platform/WebSourceBufferClient.h"
19 static base::TimeDelta
DoubleToTimeDelta(double time
) {
20 DCHECK(!std::isnan(time
));
21 DCHECK_NE(time
, -std::numeric_limits
<double>::infinity());
23 if (time
== std::numeric_limits
<double>::infinity())
24 return kInfiniteDuration();
26 // Don't use base::TimeDelta::Max() here, as we want the largest finite time
28 base::TimeDelta max_time
= base::TimeDelta::FromInternalValue(kint64max
- 1);
29 double max_time_in_seconds
= max_time
.InSecondsF();
31 if (time
>= max_time_in_seconds
)
34 return base::TimeDelta::FromMicroseconds(
35 time
* base::Time::kMicrosecondsPerSecond
);
38 WebSourceBufferImpl::WebSourceBufferImpl(
39 const std::string
& id
, ChunkDemuxer
* demuxer
)
43 append_window_end_(kInfiniteDuration()) {
47 WebSourceBufferImpl::~WebSourceBufferImpl() {
48 DCHECK(!demuxer_
) << "Object destroyed w/o removedFromMediaSource() call";
52 void WebSourceBufferImpl::setClient(blink::WebSourceBufferClient
* client
) {
58 bool WebSourceBufferImpl::setMode(WebSourceBuffer::AppendMode mode
) {
59 if (demuxer_
->IsParsingMediaSegment(id_
))
63 case WebSourceBuffer::AppendModeSegments
:
64 demuxer_
->SetSequenceMode(id_
, false);
66 case WebSourceBuffer::AppendModeSequence
:
67 demuxer_
->SetSequenceMode(id_
, true);
75 blink::WebTimeRanges
WebSourceBufferImpl::buffered() {
76 Ranges
<base::TimeDelta
> ranges
= demuxer_
->GetBufferedRanges(id_
);
77 blink::WebTimeRanges
result(ranges
.size());
78 for (size_t i
= 0; i
< ranges
.size(); i
++) {
79 result
[i
].start
= ranges
.start(i
).InSecondsF();
80 result
[i
].end
= ranges
.end(i
).InSecondsF();
85 bool WebSourceBufferImpl::evictCodedFrames(double currentPlaybackTime
,
87 return demuxer_
->EvictCodedFrames(
89 base::TimeDelta::FromSecondsD(currentPlaybackTime
),
93 void WebSourceBufferImpl::append(
94 const unsigned char* data
,
96 double* timestamp_offset
) {
97 base::TimeDelta old_offset
= timestamp_offset_
;
98 demuxer_
->AppendData(id_
, data
, length
,
99 append_window_start_
, append_window_end_
,
101 base::Bind(&WebSourceBufferImpl::InitSegmentReceived
,
102 base::Unretained(this)));
104 // Coded frame processing may update the timestamp offset. If the caller
105 // provides a non-NULL |timestamp_offset| and frame processing changes the
106 // timestamp offset, report the new offset to the caller. Do not update the
107 // caller's offset otherwise, to preserve any pre-existing value that may have
108 // more than microsecond precision.
109 if (timestamp_offset
&& old_offset
!= timestamp_offset_
)
110 *timestamp_offset
= timestamp_offset_
.InSecondsF();
113 void WebSourceBufferImpl::resetParserState() {
114 demuxer_
->ResetParserState(id_
,
115 append_window_start_
, append_window_end_
,
118 // TODO(wolenetz): resetParserState should be able to modify the caller
119 // timestamp offset (just like WebSourceBufferImpl::append).
120 // See http://crbug.com/370229 for further details.
123 void WebSourceBufferImpl::remove(double start
, double end
) {
126 demuxer_
->Remove(id_
, DoubleToTimeDelta(start
), DoubleToTimeDelta(end
));
129 bool WebSourceBufferImpl::setTimestampOffset(double offset
) {
130 if (demuxer_
->IsParsingMediaSegment(id_
))
133 timestamp_offset_
= DoubleToTimeDelta(offset
);
135 // http://www.w3.org/TR/media-source/#widl-SourceBuffer-timestampOffset
136 // Step 6: If the mode attribute equals "sequence", then set the group start
137 // timestamp to new timestamp offset.
138 demuxer_
->SetGroupStartTimestampIfInSequenceMode(id_
, timestamp_offset_
);
142 void WebSourceBufferImpl::setAppendWindowStart(double start
) {
144 append_window_start_
= DoubleToTimeDelta(start
);
147 void WebSourceBufferImpl::setAppendWindowEnd(double end
) {
149 append_window_end_
= DoubleToTimeDelta(end
);
152 void WebSourceBufferImpl::removedFromMediaSource() {
153 demuxer_
->RemoveId(id_
);
158 void WebSourceBufferImpl::InitSegmentReceived() {
159 DVLOG(1) << __FUNCTION__
;
160 client_
->initializationSegmentReceived();