• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "media/base/stream_parser_buffer.h"
6 
7 #include "base/logging.h"
8 #include "media/base/buffers.h"
9 
10 namespace media {
11 
CopyBuffer(const StreamParserBuffer & buffer)12 static scoped_refptr<StreamParserBuffer> CopyBuffer(
13     const StreamParserBuffer& buffer) {
14   if (buffer.end_of_stream())
15     return StreamParserBuffer::CreateEOSBuffer();
16 
17   scoped_refptr<StreamParserBuffer> copied_buffer =
18       StreamParserBuffer::CopyFrom(buffer.data(),
19                                    buffer.data_size(),
20                                    buffer.side_data(),
21                                    buffer.side_data_size(),
22                                    buffer.IsKeyframe(),
23                                    buffer.type(),
24                                    buffer.track_id());
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_discard_padding(buffer.discard_padding());
30   copied_buffer->set_splice_timestamp(buffer.splice_timestamp());
31   const DecryptConfig* decrypt_config = buffer.decrypt_config();
32   if (decrypt_config) {
33     copied_buffer->set_decrypt_config(
34         make_scoped_ptr(new DecryptConfig(decrypt_config->key_id(),
35                                           decrypt_config->iv(),
36                                           decrypt_config->subsamples())));
37   }
38 
39   return copied_buffer;
40 }
41 
CreateEOSBuffer()42 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CreateEOSBuffer() {
43   return make_scoped_refptr(new StreamParserBuffer(NULL, 0, NULL, 0, false,
44                                                    DemuxerStream::UNKNOWN, 0));
45 }
46 
CopyFrom(const uint8 * data,int data_size,bool is_keyframe,Type type,TrackId track_id)47 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom(
48     const uint8* data, int data_size, bool is_keyframe, Type type,
49     TrackId track_id) {
50   return make_scoped_refptr(
51       new StreamParserBuffer(data, data_size, NULL, 0, is_keyframe, type,
52                              track_id));
53 }
54 
CopyFrom(const uint8 * data,int data_size,const uint8 * side_data,int side_data_size,bool is_keyframe,Type type,TrackId track_id)55 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom(
56     const uint8* data, int data_size,
57     const uint8* side_data, int side_data_size,
58     bool is_keyframe, Type type, TrackId track_id) {
59   return make_scoped_refptr(
60       new StreamParserBuffer(data, data_size, side_data, side_data_size,
61                              is_keyframe, type, track_id));
62 }
63 
GetDecodeTimestamp() const64 DecodeTimestamp StreamParserBuffer::GetDecodeTimestamp() const {
65   if (decode_timestamp_ == kNoDecodeTimestamp())
66     return DecodeTimestamp::FromPresentationTime(timestamp());
67   return decode_timestamp_;
68 }
69 
SetDecodeTimestamp(DecodeTimestamp timestamp)70 void StreamParserBuffer::SetDecodeTimestamp(DecodeTimestamp timestamp) {
71   decode_timestamp_ = timestamp;
72   if (preroll_buffer_.get())
73     preroll_buffer_->SetDecodeTimestamp(timestamp);
74 }
75 
StreamParserBuffer(const uint8 * data,int data_size,const uint8 * side_data,int side_data_size,bool is_keyframe,Type type,TrackId track_id)76 StreamParserBuffer::StreamParserBuffer(const uint8* data, int data_size,
77                                        const uint8* side_data,
78                                        int side_data_size, bool is_keyframe,
79                                        Type type, TrackId track_id)
80     : DecoderBuffer(data, data_size, side_data, side_data_size),
81       is_keyframe_(is_keyframe),
82       decode_timestamp_(kNoDecodeTimestamp()),
83       config_id_(kInvalidConfigId),
84       type_(type),
85       track_id_(track_id) {
86   // TODO(scherkus): Should DataBuffer constructor accept a timestamp and
87   // duration to force clients to set them? Today they end up being zero which
88   // is both a common and valid value and could lead to bugs.
89   if (data) {
90     set_duration(kNoTimestamp());
91   }
92 }
93 
~StreamParserBuffer()94 StreamParserBuffer::~StreamParserBuffer() {}
95 
GetConfigId() const96 int StreamParserBuffer::GetConfigId() const {
97   return config_id_;
98 }
99 
SetConfigId(int config_id)100 void StreamParserBuffer::SetConfigId(int config_id) {
101   config_id_ = config_id;
102   if (preroll_buffer_.get())
103     preroll_buffer_->SetConfigId(config_id);
104 }
105 
GetSpliceBufferConfigId(size_t index) const106 int StreamParserBuffer::GetSpliceBufferConfigId(size_t index) const {
107   return index < splice_buffers().size()
108       ? splice_buffers_[index]->GetConfigId()
109       : GetConfigId();
110 }
111 
ConvertToSpliceBuffer(const BufferQueue & pre_splice_buffers)112 void StreamParserBuffer::ConvertToSpliceBuffer(
113     const BufferQueue& pre_splice_buffers) {
114   DCHECK(splice_buffers_.empty());
115   DCHECK(duration() > base::TimeDelta())
116       << "Only buffers with a valid duration can convert to a splice buffer."
117       << " pts " << timestamp().InSecondsF()
118       << " dts " << GetDecodeTimestamp().InSecondsF()
119       << " dur " << duration().InSecondsF();
120   DCHECK(!end_of_stream());
121 
122   // Make a copy of this first, before making any changes.
123   scoped_refptr<StreamParserBuffer> overlapping_buffer = CopyBuffer(*this);
124   overlapping_buffer->set_splice_timestamp(kNoTimestamp());
125 
126   const scoped_refptr<StreamParserBuffer>& first_splice_buffer =
127       pre_splice_buffers.front();
128 
129   // Ensure the given buffers are actually before the splice point.
130   DCHECK(first_splice_buffer->timestamp() <= overlapping_buffer->timestamp());
131 
132   // TODO(dalecurtis): We should also clear |data| and |side_data|, but since
133   // that implies EOS care must be taken to ensure there are no clients relying
134   // on that behavior.
135 
136   // Move over any preroll from this buffer.
137   if (preroll_buffer_.get()) {
138     DCHECK(!overlapping_buffer->preroll_buffer_.get());
139     overlapping_buffer->preroll_buffer_.swap(preroll_buffer_);
140   }
141 
142   // Rewrite |this| buffer as a splice buffer.
143   SetDecodeTimestamp(first_splice_buffer->GetDecodeTimestamp());
144   SetConfigId(first_splice_buffer->GetConfigId());
145   set_timestamp(first_splice_buffer->timestamp());
146   is_keyframe_ = first_splice_buffer->IsKeyframe();
147   type_ = first_splice_buffer->type();
148   track_id_ = first_splice_buffer->track_id();
149   set_splice_timestamp(overlapping_buffer->timestamp());
150 
151   // The splice duration is the duration of all buffers before the splice plus
152   // the highest ending timestamp after the splice point.
153   DCHECK(overlapping_buffer->duration() > base::TimeDelta());
154   DCHECK(pre_splice_buffers.back()->duration() > base::TimeDelta());
155   set_duration(
156       std::max(overlapping_buffer->timestamp() + overlapping_buffer->duration(),
157                pre_splice_buffers.back()->timestamp() +
158                    pre_splice_buffers.back()->duration()) -
159       first_splice_buffer->timestamp());
160 
161   // Copy all pre splice buffers into our wrapper buffer.
162   for (BufferQueue::const_iterator it = pre_splice_buffers.begin();
163        it != pre_splice_buffers.end();
164        ++it) {
165     const scoped_refptr<StreamParserBuffer>& buffer = *it;
166     DCHECK(!buffer->end_of_stream());
167     DCHECK(!buffer->preroll_buffer().get());
168     DCHECK(buffer->splice_buffers().empty());
169     splice_buffers_.push_back(CopyBuffer(*buffer.get()));
170     splice_buffers_.back()->set_splice_timestamp(splice_timestamp());
171   }
172 
173   splice_buffers_.push_back(overlapping_buffer);
174 }
175 
SetPrerollBuffer(const scoped_refptr<StreamParserBuffer> & preroll_buffer)176 void StreamParserBuffer::SetPrerollBuffer(
177     const scoped_refptr<StreamParserBuffer>& preroll_buffer) {
178   DCHECK(!preroll_buffer_.get());
179   DCHECK(!end_of_stream());
180   DCHECK(!preroll_buffer->end_of_stream());
181   DCHECK(!preroll_buffer->preroll_buffer_.get());
182   DCHECK(preroll_buffer->splice_timestamp() == kNoTimestamp());
183   DCHECK(preroll_buffer->splice_buffers().empty());
184   DCHECK(preroll_buffer->timestamp() <= timestamp());
185   DCHECK(preroll_buffer->discard_padding() == DecoderBuffer::DiscardPadding());
186   DCHECK_EQ(preroll_buffer->type(), type());
187   DCHECK_EQ(preroll_buffer->track_id(), track_id());
188 
189   preroll_buffer_ = preroll_buffer;
190   preroll_buffer_->set_timestamp(timestamp());
191   preroll_buffer_->SetDecodeTimestamp(GetDecodeTimestamp());
192 
193   // Mark the entire buffer for discard.
194   preroll_buffer_->set_discard_padding(
195       std::make_pair(kInfiniteDuration(), base::TimeDelta()));
196 }
197 
set_timestamp(base::TimeDelta timestamp)198 void StreamParserBuffer::set_timestamp(base::TimeDelta timestamp) {
199   DecoderBuffer::set_timestamp(timestamp);
200   if (preroll_buffer_.get())
201     preroll_buffer_->set_timestamp(timestamp);
202 }
203 
204 }  // namespace media
205