OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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/remoting/rpc/decoder_buffer_segment.h" |
| 6 |
| 7 #include <algorithm> |
| 8 #include <memory> |
| 9 #include <utility> |
| 10 #include <vector> |
| 11 |
| 12 #include "base/logging.h" |
| 13 #include "base/values.h" |
| 14 #include "media/base/decrypt_config.h" |
| 15 |
| 16 namespace media { |
| 17 namespace remoting { |
| 18 |
| 19 namespace { |
| 20 |
| 21 const int kPayloadVersionFieldSize = 1; |
| 22 const int kProtoBufferHeaderSize = 2; |
| 23 const int kDataBufferHeaderSize = 4; |
| 24 |
| 25 std::unique_ptr<::media::DecryptConfig> DeserializeDecryptConfig( |
| 26 const pb::DecryptConfig& config_message) { |
| 27 std::vector<::media::SubsampleEntry> entries; |
| 28 |
| 29 DCHECK(config_message.has_key_id()); |
| 30 DCHECK(config_message.has_iv()); |
| 31 |
| 32 for (int i = 0; i < config_message.sub_samples_size(); ++i) { |
| 33 entries.push_back( |
| 34 ::media::SubsampleEntry(config_message.sub_samples(i).clear_bytes(), |
| 35 config_message.sub_samples(i).cypher_bytes())); |
| 36 } |
| 37 |
| 38 std::unique_ptr<::media::DecryptConfig> decrypt_config( |
| 39 new ::media::DecryptConfig(config_message.key_id(), config_message.iv(), |
| 40 entries)); |
| 41 return decrypt_config; |
| 42 } |
| 43 |
| 44 scoped_refptr<::media::DecoderBuffer> DeserializeDecoderBuffer( |
| 45 const pb::DecoderBuffer& buffer_message, |
| 46 scoped_refptr<::media::DecoderBuffer> buffer) { |
| 47 std::unique_ptr<::media::DecryptConfig> decrypt_config; |
| 48 base::TimeDelta front_discard; |
| 49 base::TimeDelta back_discard; |
| 50 bool has_discard = true; |
| 51 |
| 52 if (buffer_message.is_eos()) { |
| 53 VLOG(1) << "EOS data"; |
| 54 return ::media::DecoderBuffer::CreateEOSBuffer(); |
| 55 } |
| 56 |
| 57 if (buffer_message.has_timestamp_usec()) { |
| 58 buffer->set_timestamp( |
| 59 base::TimeDelta::FromMicroseconds(buffer_message.timestamp_usec())); |
| 60 } |
| 61 |
| 62 if (buffer_message.has_duration_usec()) { |
| 63 buffer->set_duration( |
| 64 base::TimeDelta::FromMicroseconds(buffer_message.duration_usec())); |
| 65 } |
| 66 VLOG(2) << "timestamp:" << buffer_message.timestamp_usec() |
| 67 << " duration:" << buffer_message.duration_usec(); |
| 68 |
| 69 if (buffer_message.has_is_key_frame()) |
| 70 buffer->set_is_key_frame(buffer_message.is_key_frame()); |
| 71 |
| 72 if (buffer_message.has_decrypt_config()) { |
| 73 const pb::DecryptConfig config_message = buffer_message.decrypt_config(); |
| 74 decrypt_config = DeserializeDecryptConfig(config_message); |
| 75 buffer->set_decrypt_config(std::move(decrypt_config)); |
| 76 } |
| 77 |
| 78 if (buffer_message.has_front_discard_usec()) { |
| 79 has_discard = true; |
| 80 front_discard = |
| 81 base::TimeDelta::FromMicroseconds(buffer_message.front_discard_usec()); |
| 82 } |
| 83 if (buffer_message.has_back_discard_usec()) { |
| 84 has_discard = true; |
| 85 back_discard = |
| 86 base::TimeDelta::FromMicroseconds(buffer_message.back_discard_usec()); |
| 87 } |
| 88 |
| 89 if (has_discard) { |
| 90 buffer->set_discard_padding( |
| 91 ::media::DecoderBuffer::DiscardPadding(front_discard, back_discard)); |
| 92 } |
| 93 |
| 94 if (buffer_message.has_splice_timestamp_usec()) { |
| 95 buffer->set_splice_timestamp(base::TimeDelta::FromMicroseconds( |
| 96 buffer_message.splice_timestamp_usec())); |
| 97 } |
| 98 |
| 99 if (buffer_message.has_side_data()) { |
| 100 buffer->CopySideDataFrom( |
| 101 reinterpret_cast<const uint8_t*>(buffer_message.side_data().c_str()), |
| 102 buffer_message.side_data().size()); |
| 103 } |
| 104 |
| 105 return buffer; |
| 106 } |
| 107 |
| 108 void SerializeDecryptConfig(const ::media::DecryptConfig* decrypt_config, |
| 109 pb::DecryptConfig* config_message) { |
| 110 DCHECK(config_message); |
| 111 |
| 112 config_message->set_key_id(decrypt_config->key_id()); |
| 113 config_message->set_iv(decrypt_config->iv()); |
| 114 |
| 115 for (const auto& entry : decrypt_config->subsamples()) { |
| 116 pb::DecryptConfig::SubSample* sub_sample = |
| 117 config_message->add_sub_samples(); |
| 118 sub_sample->set_clear_bytes(entry.clear_bytes); |
| 119 sub_sample->set_cypher_bytes(entry.cypher_bytes); |
| 120 } |
| 121 } |
| 122 |
| 123 void SerializeDecoderBuffer( |
| 124 const scoped_refptr<::media::DecoderBuffer>& decoder_buffer, |
| 125 pb::DecoderBuffer* buffer_message) { |
| 126 if (decoder_buffer->end_of_stream()) { |
| 127 buffer_message->set_is_eos(true); |
| 128 return; |
| 129 } |
| 130 |
| 131 VLOG(2) << "timestamp:" << decoder_buffer->timestamp().InMicroseconds() |
| 132 << " duration:" << decoder_buffer->duration().InMicroseconds(); |
| 133 buffer_message->set_timestamp_usec( |
| 134 decoder_buffer->timestamp().InMicroseconds()); |
| 135 buffer_message->set_duration_usec( |
| 136 decoder_buffer->duration().InMicroseconds()); |
| 137 buffer_message->set_is_key_frame(decoder_buffer->is_key_frame()); |
| 138 |
| 139 if (decoder_buffer->decrypt_config()) { |
| 140 SerializeDecryptConfig(decoder_buffer->decrypt_config(), |
| 141 buffer_message->mutable_decrypt_config()); |
| 142 } |
| 143 |
| 144 buffer_message->set_front_discard_usec( |
| 145 decoder_buffer->discard_padding().first.InMicroseconds()); |
| 146 buffer_message->set_back_discard_usec( |
| 147 decoder_buffer->discard_padding().second.InMicroseconds()); |
| 148 buffer_message->set_splice_timestamp_usec( |
| 149 decoder_buffer->splice_timestamp().InMicroseconds()); |
| 150 |
| 151 if (decoder_buffer->side_data_size()) { |
| 152 buffer_message->set_side_data(decoder_buffer->side_data(), |
| 153 decoder_buffer->side_data_size()); |
| 154 } |
| 155 } |
| 156 |
| 157 } // namespace |
| 158 |
| 159 DecoderBufferSegment::DecoderBufferSegment( |
| 160 const scoped_refptr<::media::DecoderBuffer>& decoder_buffer) |
| 161 : decoder_buffer_(decoder_buffer) {} |
| 162 |
| 163 DecoderBufferSegment::~DecoderBufferSegment() = default; |
| 164 |
| 165 // static |
| 166 scoped_refptr<DecoderBufferSegment> DecoderBufferSegment::FromBuffer( |
| 167 const uint8_t* data, |
| 168 uint32_t size) { |
| 169 uint32_t pos = 0; |
| 170 |
| 171 int payload_version = data[pos++]; |
| 172 DCHECK_EQ(payload_version, 0); |
| 173 |
| 174 DCHECK(size > pos + kProtoBufferHeaderSize); |
| 175 uint32_t proto_size = (data[pos] << 8) | data[pos + 1]; |
| 176 pos += kProtoBufferHeaderSize; |
| 177 |
| 178 DCHECK(size > pos + proto_size); |
| 179 pb::DecoderBuffer segment; |
| 180 if (!segment.ParseFromArray(data + pos, proto_size)) { |
| 181 LOG(ERROR) << "Bad proto buffer"; |
| 182 return nullptr; |
| 183 } |
| 184 pos += proto_size; |
| 185 |
| 186 DCHECK(size >= pos + kDataBufferHeaderSize); |
| 187 uint32_t buffer_size = (data[pos] << 24) | (data[pos + 1] << 16) | |
| 188 (data[pos + 2] << 8) | data[pos + 3]; |
| 189 pos += kDataBufferHeaderSize; |
| 190 |
| 191 DCHECK(size == pos + buffer_size); |
| 192 // Create DecoderBuffer first to allocate buffer. |
| 193 scoped_refptr<DecoderBuffer> decoder_buffer = |
| 194 DecoderBuffer::CopyFrom(data + pos, buffer_size); |
| 195 // Deserialize proto buffer. It passes the pre allocated DecoderBuffer into |
| 196 // the function because the proto buffer may overwrite DecoderBuffer since it |
| 197 // may be EOS buffer. |
| 198 decoder_buffer = DeserializeDecoderBuffer(segment, std::move(decoder_buffer)); |
| 199 |
| 200 return new DecoderBufferSegment(decoder_buffer); |
| 201 } |
| 202 |
| 203 uint32_t DecoderBufferSegment::ToBuffer(std::vector<uint8_t>* buffer) { |
| 204 DCHECK(buffer); |
| 205 pb::DecoderBuffer decoder_buffer_data; |
| 206 SerializeDecoderBuffer(decoder_buffer_, &decoder_buffer_data); |
| 207 |
| 208 size_t decoder_buffer_size = |
| 209 decoder_buffer_->end_of_stream() ? 0 : decoder_buffer_->data_size(); |
| 210 size_t size = kPayloadVersionFieldSize + kProtoBufferHeaderSize + |
| 211 decoder_buffer_data.ByteSize() + kDataBufferHeaderSize + |
| 212 decoder_buffer_size; |
| 213 buffer->resize(size); |
| 214 int pos = 0; |
| 215 // payload_version, default is 0. |
| 216 (*buffer)[pos++] = 0; |
| 217 // Length of protobuf-encoded segment. |
| 218 (*buffer)[pos++] = (decoder_buffer_data.ByteSize() >> 8) & 0xff; |
| 219 (*buffer)[pos++] = decoder_buffer_data.ByteSize() & 0xff; |
| 220 // Protobuf-encoded DecoderBuffer. |
| 221 DCHECK(decoder_buffer_data.SerializeToArray((*buffer).data() + pos, |
| 222 decoder_buffer_data.ByteSize())); |
| 223 pos += decoder_buffer_data.ByteSize(); |
| 224 // Length of data segment. |
| 225 (*buffer)[pos++] = (decoder_buffer_size >> 24) & 0xff; |
| 226 (*buffer)[pos++] = (decoder_buffer_size >> 16) & 0xff; |
| 227 (*buffer)[pos++] = (decoder_buffer_size >> 8) & 0xff; |
| 228 (*buffer)[pos++] = decoder_buffer_size & 0xff; |
| 229 // DecoderBuffer frame data. |
| 230 if (decoder_buffer_size) { |
| 231 std::copy(decoder_buffer_->data(), |
| 232 decoder_buffer_->data() + decoder_buffer_->data_size(), |
| 233 (*buffer).data() + pos); |
| 234 } |
| 235 return size; |
| 236 } |
| 237 |
| 238 } // namespace remoting |
| 239 } // namespace media |
OLD | NEW |