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 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 42 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CreateEOSBuffer() { 43 return make_scoped_refptr(new StreamParserBuffer(NULL, 0, NULL, 0, false, 44 DemuxerStream::UNKNOWN, 0)); 45 } 46 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 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 64 base::TimeDelta StreamParserBuffer::GetDecodeTimestamp() const { 65 if (decode_timestamp_ == kNoTimestamp()) 66 return timestamp(); 67 return decode_timestamp_; 68 } 69 70 void StreamParserBuffer::SetDecodeTimestamp(base::TimeDelta timestamp) { 71 decode_timestamp_ = timestamp; 72 if (preroll_buffer_) 73 preroll_buffer_->SetDecodeTimestamp(timestamp); 74 } 75 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_(kNoTimestamp()), 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 94 StreamParserBuffer::~StreamParserBuffer() {} 95 96 int StreamParserBuffer::GetConfigId() const { 97 return config_id_; 98 } 99 100 void StreamParserBuffer::SetConfigId(int config_id) { 101 config_id_ = config_id; 102 if (preroll_buffer_) 103 preroll_buffer_->SetConfigId(config_id); 104 } 105 106 void StreamParserBuffer::ConvertToSpliceBuffer( 107 const BufferQueue& pre_splice_buffers) { 108 DCHECK(splice_buffers_.empty()); 109 DCHECK(!end_of_stream()); 110 111 // Make a copy of this first, before making any changes. 112 scoped_refptr<StreamParserBuffer> overlapping_buffer = CopyBuffer(*this); 113 overlapping_buffer->set_splice_timestamp(kNoTimestamp()); 114 115 const scoped_refptr<StreamParserBuffer>& first_splice_buffer = 116 pre_splice_buffers.front(); 117 118 // Ensure the given buffers are actually before the splice point. 119 DCHECK(first_splice_buffer->timestamp() <= overlapping_buffer->timestamp()); 120 121 // TODO(dalecurtis): We should also clear |data| and |side_data|, but since 122 // that implies EOS care must be taken to ensure there are no clients relying 123 // on that behavior. 124 125 // Move over any preroll from this buffer. 126 if (preroll_buffer_) { 127 DCHECK(!overlapping_buffer->preroll_buffer_); 128 overlapping_buffer->preroll_buffer_.swap(preroll_buffer_); 129 } 130 131 // Rewrite |this| buffer as a splice buffer. 132 SetDecodeTimestamp(first_splice_buffer->GetDecodeTimestamp()); 133 SetConfigId(first_splice_buffer->GetConfigId()); 134 set_timestamp(first_splice_buffer->timestamp()); 135 is_keyframe_ = first_splice_buffer->IsKeyframe(); 136 type_ = first_splice_buffer->type(); 137 track_id_ = first_splice_buffer->track_id(); 138 set_splice_timestamp(overlapping_buffer->timestamp()); 139 140 // The splice duration is the duration of all buffers before the splice plus 141 // the highest ending timestamp after the splice point. 142 set_duration( 143 std::max(overlapping_buffer->timestamp() + overlapping_buffer->duration(), 144 pre_splice_buffers.back()->timestamp() + 145 pre_splice_buffers.back()->duration()) - 146 first_splice_buffer->timestamp()); 147 148 // Copy all pre splice buffers into our wrapper buffer. 149 for (BufferQueue::const_iterator it = pre_splice_buffers.begin(); 150 it != pre_splice_buffers.end(); 151 ++it) { 152 const scoped_refptr<StreamParserBuffer>& buffer = *it; 153 DCHECK(!buffer->end_of_stream()); 154 DCHECK(!buffer->preroll_buffer()); 155 DCHECK(buffer->splice_buffers().empty()); 156 splice_buffers_.push_back(CopyBuffer(*buffer)); 157 splice_buffers_.back()->set_splice_timestamp(splice_timestamp()); 158 } 159 160 splice_buffers_.push_back(overlapping_buffer); 161 } 162 163 void StreamParserBuffer::SetPrerollBuffer( 164 const scoped_refptr<StreamParserBuffer>& preroll_buffer) { 165 DCHECK(!preroll_buffer_); 166 DCHECK(!end_of_stream()); 167 DCHECK(!preroll_buffer->end_of_stream()); 168 DCHECK(!preroll_buffer->preroll_buffer_); 169 DCHECK(preroll_buffer->splice_timestamp() == kNoTimestamp()); 170 DCHECK(preroll_buffer->splice_buffers().empty()); 171 DCHECK(preroll_buffer->timestamp() <= timestamp()); 172 DCHECK(preroll_buffer->discard_padding() == DecoderBuffer::DiscardPadding()); 173 DCHECK_EQ(preroll_buffer->type(), type()); 174 DCHECK_EQ(preroll_buffer->track_id(), track_id()); 175 176 preroll_buffer_ = preroll_buffer; 177 preroll_buffer_->set_timestamp(timestamp()); 178 preroll_buffer_->SetDecodeTimestamp(GetDecodeTimestamp()); 179 180 // Mark the entire buffer for discard. 181 preroll_buffer_->set_discard_padding( 182 std::make_pair(kInfiniteDuration(), base::TimeDelta())); 183 } 184 185 void StreamParserBuffer::set_timestamp(base::TimeDelta timestamp) { 186 DecoderBuffer::set_timestamp(timestamp); 187 if (preroll_buffer_) 188 preroll_buffer_->set_timestamp(timestamp); 189 } 190 191 } // namespace media 192