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
3 // found in the LICENSE file.
5 #include "media/base/stream_parser_buffer.h"
7 #include "base/logging.h"
8 #include "media/base/buffers.h"
12 static scoped_refptr
<StreamParserBuffer
> CopyBuffer(
13 const StreamParserBuffer
& buffer
) {
14 if (buffer
.end_of_stream())
15 return StreamParserBuffer::CreateEOSBuffer();
17 scoped_refptr
<StreamParserBuffer
> copied_buffer
=
18 StreamParserBuffer::CopyFrom(buffer
.data(),
21 buffer
.side_data_size(),
22 buffer
.is_key_frame(),
25 copied_buffer
->SetDecodeTimestamp(buffer
.GetDecodeTimestamp());
26 copied_buffer
->SetConfigId(buffer
.GetConfigId());
27 copied_buffer
->set_timestamp(buffer
.timestamp());
28 copied_buffer
->set_duration(buffer
.duration());
29 copied_buffer
->set_is_duration_estimated(buffer
.is_duration_estimated());
30 copied_buffer
->set_discard_padding(buffer
.discard_padding());
31 copied_buffer
->set_splice_timestamp(buffer
.splice_timestamp());
32 const DecryptConfig
* decrypt_config
= buffer
.decrypt_config();
34 copied_buffer
->set_decrypt_config(
35 make_scoped_ptr(new DecryptConfig(decrypt_config
->key_id(),
37 decrypt_config
->subsamples())));
43 scoped_refptr
<StreamParserBuffer
> StreamParserBuffer::CreateEOSBuffer() {
44 return make_scoped_refptr(new StreamParserBuffer(NULL
, 0, NULL
, 0, false,
45 DemuxerStream::UNKNOWN
, 0));
48 scoped_refptr
<StreamParserBuffer
> StreamParserBuffer::CopyFrom(
49 const uint8
* data
, int data_size
, bool is_key_frame
, Type type
,
51 return make_scoped_refptr(
52 new StreamParserBuffer(data
, data_size
, NULL
, 0, is_key_frame
, type
,
56 scoped_refptr
<StreamParserBuffer
> StreamParserBuffer::CopyFrom(
57 const uint8
* data
, int data_size
,
58 const uint8
* side_data
, int side_data_size
,
59 bool is_key_frame
, Type type
, TrackId track_id
) {
60 return make_scoped_refptr(
61 new StreamParserBuffer(data
, data_size
, side_data
, side_data_size
,
62 is_key_frame
, type
, track_id
));
65 DecodeTimestamp
StreamParserBuffer::GetDecodeTimestamp() const {
66 if (decode_timestamp_
== kNoDecodeTimestamp())
67 return DecodeTimestamp::FromPresentationTime(timestamp());
68 return decode_timestamp_
;
71 void StreamParserBuffer::SetDecodeTimestamp(DecodeTimestamp timestamp
) {
72 decode_timestamp_
= timestamp
;
73 if (preroll_buffer_
.get())
74 preroll_buffer_
->SetDecodeTimestamp(timestamp
);
77 StreamParserBuffer::StreamParserBuffer(const uint8
* data
,
79 const uint8
* side_data
,
84 : DecoderBuffer(data
, data_size
, side_data
, side_data_size
),
85 decode_timestamp_(kNoDecodeTimestamp()),
86 config_id_(kInvalidConfigId
),
89 is_duration_estimated_(false) {
90 // TODO(scherkus): Should DataBuffer constructor accept a timestamp and
91 // duration to force clients to set them? Today they end up being zero which
92 // is both a common and valid value and could lead to bugs.
94 set_duration(kNoTimestamp());
98 set_is_key_frame(true);
101 StreamParserBuffer::~StreamParserBuffer() {}
103 int StreamParserBuffer::GetConfigId() const {
107 void StreamParserBuffer::SetConfigId(int config_id
) {
108 config_id_
= config_id
;
109 if (preroll_buffer_
.get())
110 preroll_buffer_
->SetConfigId(config_id
);
113 int StreamParserBuffer::GetSpliceBufferConfigId(size_t index
) const {
114 return index
< splice_buffers().size()
115 ? splice_buffers_
[index
]->GetConfigId()
119 void StreamParserBuffer::ConvertToSpliceBuffer(
120 const BufferQueue
& pre_splice_buffers
) {
121 DCHECK(splice_buffers_
.empty());
122 DCHECK(duration() > base::TimeDelta())
123 << "Only buffers with a valid duration can convert to a splice buffer."
124 << " pts " << timestamp().InSecondsF()
125 << " dts " << GetDecodeTimestamp().InSecondsF()
126 << " dur " << duration().InSecondsF();
127 DCHECK(!end_of_stream());
129 // Splicing requires non-estimated sample accurate durations to be confident
130 // things will sound smooth. Also, we cannot be certain whether estimated
131 // overlap is really a splice scenario, or just over estimation.
132 DCHECK(!is_duration_estimated_
);
134 // Make a copy of this first, before making any changes.
135 scoped_refptr
<StreamParserBuffer
> overlapping_buffer
= CopyBuffer(*this);
136 overlapping_buffer
->set_splice_timestamp(kNoTimestamp());
138 const scoped_refptr
<StreamParserBuffer
>& first_splice_buffer
=
139 pre_splice_buffers
.front();
141 // Ensure the given buffers are actually before the splice point.
142 DCHECK(first_splice_buffer
->timestamp() <= overlapping_buffer
->timestamp());
144 // TODO(dalecurtis): We should also clear |data| and |side_data|, but since
145 // that implies EOS care must be taken to ensure there are no clients relying
148 // Move over any preroll from this buffer.
149 if (preroll_buffer_
.get()) {
150 DCHECK(!overlapping_buffer
->preroll_buffer_
.get());
151 overlapping_buffer
->preroll_buffer_
.swap(preroll_buffer_
);
154 // Rewrite |this| buffer as a splice buffer.
155 SetDecodeTimestamp(first_splice_buffer
->GetDecodeTimestamp());
156 SetConfigId(first_splice_buffer
->GetConfigId());
157 set_timestamp(first_splice_buffer
->timestamp());
158 set_is_key_frame(first_splice_buffer
->is_key_frame());
159 type_
= first_splice_buffer
->type();
160 track_id_
= first_splice_buffer
->track_id();
161 set_splice_timestamp(overlapping_buffer
->timestamp());
163 // The splice duration is the duration of all buffers before the splice plus
164 // the highest ending timestamp after the splice point.
165 DCHECK(overlapping_buffer
->duration() > base::TimeDelta());
166 DCHECK(pre_splice_buffers
.back()->duration() > base::TimeDelta());
168 std::max(overlapping_buffer
->timestamp() + overlapping_buffer
->duration(),
169 pre_splice_buffers
.back()->timestamp() +
170 pre_splice_buffers
.back()->duration()) -
171 first_splice_buffer
->timestamp());
173 // Copy all pre splice buffers into our wrapper buffer.
174 for (BufferQueue::const_iterator it
= pre_splice_buffers
.begin();
175 it
!= pre_splice_buffers
.end();
177 const scoped_refptr
<StreamParserBuffer
>& buffer
= *it
;
178 DCHECK(!buffer
->end_of_stream());
179 DCHECK(!buffer
->preroll_buffer().get());
180 DCHECK(buffer
->splice_buffers().empty());
181 DCHECK(!buffer
->is_duration_estimated());
182 splice_buffers_
.push_back(CopyBuffer(*buffer
.get()));
183 splice_buffers_
.back()->set_splice_timestamp(splice_timestamp());
186 splice_buffers_
.push_back(overlapping_buffer
);
189 void StreamParserBuffer::SetPrerollBuffer(
190 const scoped_refptr
<StreamParserBuffer
>& preroll_buffer
) {
191 DCHECK(!preroll_buffer_
.get());
192 DCHECK(!end_of_stream());
193 DCHECK(!preroll_buffer
->end_of_stream());
194 DCHECK(!preroll_buffer
->preroll_buffer_
.get());
195 DCHECK(preroll_buffer
->splice_timestamp() == kNoTimestamp());
196 DCHECK(preroll_buffer
->splice_buffers().empty());
197 DCHECK(preroll_buffer
->timestamp() <= timestamp());
198 DCHECK(preroll_buffer
->discard_padding() == DecoderBuffer::DiscardPadding());
199 DCHECK_EQ(preroll_buffer
->type(), type());
200 DCHECK_EQ(preroll_buffer
->track_id(), track_id());
202 preroll_buffer_
= preroll_buffer
;
203 preroll_buffer_
->set_timestamp(timestamp());
204 preroll_buffer_
->SetDecodeTimestamp(GetDecodeTimestamp());
206 // Mark the entire buffer for discard.
207 preroll_buffer_
->set_discard_padding(
208 std::make_pair(kInfiniteDuration(), base::TimeDelta()));
211 void StreamParserBuffer::set_timestamp(base::TimeDelta timestamp
) {
212 DecoderBuffer::set_timestamp(timestamp
);
213 if (preroll_buffer_
.get())
214 preroll_buffer_
->set_timestamp(timestamp
);