| OLD | NEW |
| 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/base/stream_parser_buffer.h" | 5 #include "media/base/stream_parser_buffer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 11 #include "media/base/timestamp_constants.h" | 11 #include "media/base/timestamp_constants.h" |
| 12 | 12 |
| 13 namespace media { | 13 namespace media { |
| 14 | 14 |
| 15 static scoped_refptr<StreamParserBuffer> CopyBuffer( | |
| 16 const StreamParserBuffer& buffer) { | |
| 17 if (buffer.end_of_stream()) | |
| 18 return StreamParserBuffer::CreateEOSBuffer(); | |
| 19 | |
| 20 scoped_refptr<StreamParserBuffer> copied_buffer = | |
| 21 StreamParserBuffer::CopyFrom(buffer.data(), | |
| 22 buffer.data_size(), | |
| 23 buffer.side_data(), | |
| 24 buffer.side_data_size(), | |
| 25 buffer.is_key_frame(), | |
| 26 buffer.type(), | |
| 27 buffer.track_id()); | |
| 28 copied_buffer->SetDecodeTimestamp(buffer.GetDecodeTimestamp()); | |
| 29 copied_buffer->SetConfigId(buffer.GetConfigId()); | |
| 30 copied_buffer->set_timestamp(buffer.timestamp()); | |
| 31 copied_buffer->set_duration(buffer.duration()); | |
| 32 copied_buffer->set_is_duration_estimated(buffer.is_duration_estimated()); | |
| 33 copied_buffer->set_discard_padding(buffer.discard_padding()); | |
| 34 copied_buffer->set_splice_timestamp(buffer.splice_timestamp()); | |
| 35 const DecryptConfig* decrypt_config = buffer.decrypt_config(); | |
| 36 if (decrypt_config) { | |
| 37 copied_buffer->set_decrypt_config(base::MakeUnique<DecryptConfig>( | |
| 38 decrypt_config->key_id(), decrypt_config->iv(), | |
| 39 decrypt_config->subsamples())); | |
| 40 } | |
| 41 | |
| 42 return copied_buffer; | |
| 43 } | |
| 44 | |
| 45 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CreateEOSBuffer() { | 15 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CreateEOSBuffer() { |
| 46 return make_scoped_refptr(new StreamParserBuffer(NULL, 0, NULL, 0, false, | 16 return make_scoped_refptr(new StreamParserBuffer(NULL, 0, NULL, 0, false, |
| 47 DemuxerStream::UNKNOWN, 0)); | 17 DemuxerStream::UNKNOWN, 0)); |
| 48 } | 18 } |
| 49 | 19 |
| 50 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom( | 20 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom( |
| 51 const uint8_t* data, | 21 const uint8_t* data, |
| 52 int data_size, | 22 int data_size, |
| 53 bool is_key_frame, | 23 bool is_key_frame, |
| 54 Type type, | 24 Type type, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 int StreamParserBuffer::GetConfigId() const { | 82 int StreamParserBuffer::GetConfigId() const { |
| 113 return config_id_; | 83 return config_id_; |
| 114 } | 84 } |
| 115 | 85 |
| 116 void StreamParserBuffer::SetConfigId(int config_id) { | 86 void StreamParserBuffer::SetConfigId(int config_id) { |
| 117 config_id_ = config_id; | 87 config_id_ = config_id; |
| 118 if (preroll_buffer_.get()) | 88 if (preroll_buffer_.get()) |
| 119 preroll_buffer_->SetConfigId(config_id); | 89 preroll_buffer_->SetConfigId(config_id); |
| 120 } | 90 } |
| 121 | 91 |
| 122 int StreamParserBuffer::GetSpliceBufferConfigId(size_t index) const { | |
| 123 return index < splice_buffers().size() | |
| 124 ? splice_buffers_[index]->GetConfigId() | |
| 125 : GetConfigId(); | |
| 126 } | |
| 127 | |
| 128 const char* StreamParserBuffer::GetTypeName() const { | 92 const char* StreamParserBuffer::GetTypeName() const { |
| 129 switch (type()) { | 93 switch (type()) { |
| 130 case DemuxerStream::AUDIO: | 94 case DemuxerStream::AUDIO: |
| 131 return "audio"; | 95 return "audio"; |
| 132 case DemuxerStream::VIDEO: | 96 case DemuxerStream::VIDEO: |
| 133 return "video"; | 97 return "video"; |
| 134 case DemuxerStream::TEXT: | 98 case DemuxerStream::TEXT: |
| 135 return "text"; | 99 return "text"; |
| 136 case DemuxerStream::UNKNOWN: | 100 case DemuxerStream::UNKNOWN: |
| 137 return "unknown"; | 101 return "unknown"; |
| 138 } | 102 } |
| 139 NOTREACHED(); | 103 NOTREACHED(); |
| 140 return ""; | 104 return ""; |
| 141 } | 105 } |
| 142 | 106 |
| 143 void StreamParserBuffer::ConvertToSpliceBuffer( | |
| 144 const BufferQueue& pre_splice_buffers) { | |
| 145 DCHECK(splice_buffers_.empty()); | |
| 146 DCHECK(duration() > base::TimeDelta()) | |
| 147 << "Only buffers with a valid duration can convert to a splice buffer." | |
| 148 << " pts " << timestamp().InSecondsF() | |
| 149 << " dts " << GetDecodeTimestamp().InSecondsF() | |
| 150 << " dur " << duration().InSecondsF(); | |
| 151 DCHECK(!end_of_stream()); | |
| 152 | |
| 153 // Splicing requires non-estimated sample accurate durations to be confident | |
| 154 // things will sound smooth. Also, we cannot be certain whether estimated | |
| 155 // overlap is really a splice scenario, or just over estimation. | |
| 156 DCHECK(!is_duration_estimated_); | |
| 157 | |
| 158 // Make a copy of this first, before making any changes. | |
| 159 scoped_refptr<StreamParserBuffer> overlapping_buffer = CopyBuffer(*this); | |
| 160 overlapping_buffer->set_splice_timestamp(kNoTimestamp); | |
| 161 | |
| 162 const scoped_refptr<StreamParserBuffer>& first_splice_buffer = | |
| 163 pre_splice_buffers.front(); | |
| 164 | |
| 165 // Ensure the given buffers are actually before the splice point. | |
| 166 DCHECK(first_splice_buffer->timestamp() <= overlapping_buffer->timestamp()); | |
| 167 | |
| 168 // TODO(dalecurtis): We should also clear |data| and |side_data|, but since | |
| 169 // that implies EOS care must be taken to ensure there are no clients relying | |
| 170 // on that behavior. | |
| 171 | |
| 172 // Move over any preroll from this buffer. | |
| 173 if (preroll_buffer_.get()) { | |
| 174 DCHECK(!overlapping_buffer->preroll_buffer_.get()); | |
| 175 overlapping_buffer->preroll_buffer_.swap(preroll_buffer_); | |
| 176 } | |
| 177 | |
| 178 // Rewrite |this| buffer as a splice buffer. | |
| 179 SetDecodeTimestamp(first_splice_buffer->GetDecodeTimestamp()); | |
| 180 SetConfigId(first_splice_buffer->GetConfigId()); | |
| 181 set_timestamp(first_splice_buffer->timestamp()); | |
| 182 set_is_key_frame(first_splice_buffer->is_key_frame()); | |
| 183 type_ = first_splice_buffer->type(); | |
| 184 track_id_ = first_splice_buffer->track_id(); | |
| 185 set_splice_timestamp(overlapping_buffer->timestamp()); | |
| 186 | |
| 187 // The splice duration is the duration of all buffers before the splice plus | |
| 188 // the highest ending timestamp after the splice point. | |
| 189 DCHECK(overlapping_buffer->duration() > base::TimeDelta()); | |
| 190 DCHECK(pre_splice_buffers.back()->duration() > base::TimeDelta()); | |
| 191 set_duration( | |
| 192 std::max(overlapping_buffer->timestamp() + overlapping_buffer->duration(), | |
| 193 pre_splice_buffers.back()->timestamp() + | |
| 194 pre_splice_buffers.back()->duration()) - | |
| 195 first_splice_buffer->timestamp()); | |
| 196 | |
| 197 // Copy all pre splice buffers into our wrapper buffer. | |
| 198 for (BufferQueue::const_iterator it = pre_splice_buffers.begin(); | |
| 199 it != pre_splice_buffers.end(); | |
| 200 ++it) { | |
| 201 const scoped_refptr<StreamParserBuffer>& buffer = *it; | |
| 202 DCHECK(!buffer->end_of_stream()); | |
| 203 DCHECK(!buffer->preroll_buffer().get()); | |
| 204 DCHECK(buffer->splice_buffers().empty()); | |
| 205 DCHECK(!buffer->is_duration_estimated()); | |
| 206 splice_buffers_.push_back(CopyBuffer(*buffer.get())); | |
| 207 splice_buffers_.back()->set_splice_timestamp(splice_timestamp()); | |
| 208 } | |
| 209 | |
| 210 splice_buffers_.push_back(overlapping_buffer); | |
| 211 } | |
| 212 | |
| 213 void StreamParserBuffer::SetPrerollBuffer( | 107 void StreamParserBuffer::SetPrerollBuffer( |
| 214 const scoped_refptr<StreamParserBuffer>& preroll_buffer) { | 108 const scoped_refptr<StreamParserBuffer>& preroll_buffer) { |
| 215 DCHECK(!preroll_buffer_.get()); | 109 DCHECK(!preroll_buffer_.get()); |
| 216 DCHECK(!end_of_stream()); | 110 DCHECK(!end_of_stream()); |
| 217 DCHECK(!preroll_buffer->end_of_stream()); | 111 DCHECK(!preroll_buffer->end_of_stream()); |
| 218 DCHECK(!preroll_buffer->preroll_buffer_.get()); | 112 DCHECK(!preroll_buffer->preroll_buffer_.get()); |
| 219 DCHECK(preroll_buffer->splice_timestamp() == kNoTimestamp); | |
| 220 DCHECK(preroll_buffer->splice_buffers().empty()); | |
| 221 DCHECK(preroll_buffer->timestamp() <= timestamp()); | 113 DCHECK(preroll_buffer->timestamp() <= timestamp()); |
| 222 DCHECK(preroll_buffer->discard_padding() == DecoderBuffer::DiscardPadding()); | 114 DCHECK(preroll_buffer->discard_padding() == DecoderBuffer::DiscardPadding()); |
| 223 DCHECK_EQ(preroll_buffer->type(), type()); | 115 DCHECK_EQ(preroll_buffer->type(), type()); |
| 224 DCHECK_EQ(preroll_buffer->track_id(), track_id()); | 116 DCHECK_EQ(preroll_buffer->track_id(), track_id()); |
| 225 | 117 |
| 226 preroll_buffer_ = preroll_buffer; | 118 preroll_buffer_ = preroll_buffer; |
| 227 preroll_buffer_->set_timestamp(timestamp()); | 119 preroll_buffer_->set_timestamp(timestamp()); |
| 120 preroll_buffer_->SetConfigId(GetConfigId()); |
| 228 preroll_buffer_->SetDecodeTimestamp(GetDecodeTimestamp()); | 121 preroll_buffer_->SetDecodeTimestamp(GetDecodeTimestamp()); |
| 229 | 122 |
| 230 // Mark the entire buffer for discard. | 123 // Mark the entire buffer for discard. |
| 231 preroll_buffer_->set_discard_padding( | 124 preroll_buffer_->set_discard_padding( |
| 232 std::make_pair(kInfiniteDuration, base::TimeDelta())); | 125 std::make_pair(kInfiniteDuration, base::TimeDelta())); |
| 233 } | 126 } |
| 234 | 127 |
| 235 void StreamParserBuffer::set_timestamp(base::TimeDelta timestamp) { | 128 void StreamParserBuffer::set_timestamp(base::TimeDelta timestamp) { |
| 236 DecoderBuffer::set_timestamp(timestamp); | 129 DecoderBuffer::set_timestamp(timestamp); |
| 237 if (preroll_buffer_.get()) | 130 if (preroll_buffer_.get()) |
| 238 preroll_buffer_->set_timestamp(timestamp); | 131 preroll_buffer_->set_timestamp(timestamp); |
| 239 } | 132 } |
| 240 | 133 |
| 241 } // namespace media | 134 } // namespace media |
| OLD | NEW |