Chromium Code Reviews| 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/big_endian.h" | |
| 13 #include "base/logging.h" | |
| 14 #include "base/time/time.h" | |
| 15 #include "base/values.h" | |
| 16 #include "media/base/decrypt_config.h" | |
| 17 #include "media/remoting/remoting_rpc_message.pb.h" | |
| 18 | |
| 19 namespace media { | |
| 20 namespace remoting { | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 const int kPayloadVersionFieldSize = 1; | |
| 25 const int kProtoBufferHeaderSize = 2; | |
| 26 const int kDataBufferHeaderSize = 4; | |
| 27 | |
| 28 std::unique_ptr<::media::DecryptConfig> DeserializeDecryptConfig( | |
|
miu
2016/09/13 05:40:57
naming nit: This isn't deserializing from a wire f
erickung1
2016/09/15 02:13:33
Done.
| |
| 29 const pb::DecryptConfig& config_message) { | |
| 30 std::vector<::media::SubsampleEntry> entries; | |
| 31 | |
| 32 DCHECK(config_message.has_key_id()); | |
| 33 DCHECK(config_message.has_iv()); | |
| 34 | |
| 35 for (int i = 0; i < config_message.sub_samples_size(); ++i) { | |
| 36 entries.push_back( | |
| 37 ::media::SubsampleEntry(config_message.sub_samples(i).clear_bytes(), | |
| 38 config_message.sub_samples(i).cypher_bytes())); | |
| 39 } | |
| 40 | |
| 41 std::unique_ptr<::media::DecryptConfig> decrypt_config( | |
| 42 new ::media::DecryptConfig(config_message.key_id(), config_message.iv(), | |
| 43 entries)); | |
| 44 return decrypt_config; | |
| 45 } | |
| 46 | |
| 47 scoped_refptr<::media::DecoderBuffer> DeserializeDecoderBuffer( | |
| 48 const pb::DecoderBuffer& buffer_message, | |
| 49 scoped_refptr<::media::DecoderBuffer> buffer) { | |
| 50 std::unique_ptr<::media::DecryptConfig> decrypt_config; | |
|
miu
2016/09/13 05:40:57
Looks like this variable is unused. Otherwise, ple
erickung1
2016/09/15 02:13:33
Done. remove |decrypt_config| and also move |front
| |
| 51 base::TimeDelta front_discard; | |
| 52 base::TimeDelta back_discard; | |
| 53 bool has_discard = true; | |
| 54 | |
| 55 if (buffer_message.is_eos()) { | |
| 56 VLOG(1) << "EOS data"; | |
| 57 return ::media::DecoderBuffer::CreateEOSBuffer(); | |
| 58 } | |
| 59 | |
| 60 if (buffer_message.has_timestamp_usec()) { | |
| 61 buffer->set_timestamp( | |
| 62 base::TimeDelta::FromMicroseconds(buffer_message.timestamp_usec())); | |
| 63 } | |
| 64 | |
| 65 if (buffer_message.has_duration_usec()) { | |
| 66 buffer->set_duration( | |
| 67 base::TimeDelta::FromMicroseconds(buffer_message.duration_usec())); | |
| 68 } | |
| 69 VLOG(2) << "timestamp:" << buffer_message.timestamp_usec() | |
| 70 << " duration:" << buffer_message.duration_usec(); | |
| 71 | |
| 72 if (buffer_message.has_is_key_frame()) | |
| 73 buffer->set_is_key_frame(buffer_message.is_key_frame()); | |
| 74 | |
| 75 if (buffer_message.has_decrypt_config()) { | |
| 76 buffer->set_decrypt_config( | |
| 77 DeserializeDecryptConfig(buffer_message.decrypt_config())); | |
| 78 } | |
| 79 | |
| 80 if (buffer_message.has_front_discard_usec()) { | |
| 81 has_discard = true; | |
| 82 front_discard = | |
| 83 base::TimeDelta::FromMicroseconds(buffer_message.front_discard_usec()); | |
| 84 } | |
| 85 if (buffer_message.has_back_discard_usec()) { | |
| 86 has_discard = true; | |
| 87 back_discard = | |
| 88 base::TimeDelta::FromMicroseconds(buffer_message.back_discard_usec()); | |
| 89 } | |
| 90 | |
| 91 if (has_discard) { | |
|
miu
2016/09/13 05:40:57
|has_discard| seems to be true no matter what. Is
erickung1
2016/09/15 02:13:33
Done. Yes, just noticed it and change the default
| |
| 92 buffer->set_discard_padding( | |
| 93 ::media::DecoderBuffer::DiscardPadding(front_discard, back_discard)); | |
| 94 } | |
| 95 | |
| 96 if (buffer_message.has_splice_timestamp_usec()) { | |
| 97 buffer->set_splice_timestamp(base::TimeDelta::FromMicroseconds( | |
| 98 buffer_message.splice_timestamp_usec())); | |
| 99 } | |
| 100 | |
| 101 if (buffer_message.has_side_data()) { | |
| 102 buffer->CopySideDataFrom( | |
| 103 reinterpret_cast<const uint8_t*>(buffer_message.side_data().data()), | |
| 104 buffer_message.side_data().size()); | |
| 105 } | |
| 106 | |
| 107 return buffer; | |
| 108 } | |
| 109 | |
| 110 void SerializeDecryptConfig(const ::media::DecryptConfig& decrypt_config, | |
|
miu
2016/09/13 05:40:57
naming nit: This isn't serializing to a wire forma
erickung1
2016/09/15 02:13:33
Done.
| |
| 111 pb::DecryptConfig* config_message) { | |
| 112 DCHECK(config_message); | |
| 113 | |
| 114 config_message->set_key_id(decrypt_config.key_id()); | |
| 115 config_message->set_iv(decrypt_config.iv()); | |
| 116 | |
| 117 for (const auto& entry : decrypt_config.subsamples()) { | |
| 118 pb::DecryptConfig::SubSample* sub_sample = | |
| 119 config_message->add_sub_samples(); | |
| 120 sub_sample->set_clear_bytes(entry.clear_bytes); | |
| 121 sub_sample->set_cypher_bytes(entry.cypher_bytes); | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 void SerializeDecoderBuffer( | |
| 126 const scoped_refptr<::media::DecoderBuffer>& decoder_buffer, | |
| 127 pb::DecoderBuffer* buffer_message) { | |
| 128 if (decoder_buffer->end_of_stream()) { | |
| 129 buffer_message->set_is_eos(true); | |
| 130 return; | |
| 131 } | |
| 132 | |
| 133 VLOG(2) << "timestamp:" << decoder_buffer->timestamp().InMicroseconds() | |
| 134 << " duration:" << decoder_buffer->duration().InMicroseconds(); | |
| 135 buffer_message->set_timestamp_usec( | |
| 136 decoder_buffer->timestamp().InMicroseconds()); | |
| 137 buffer_message->set_duration_usec( | |
| 138 decoder_buffer->duration().InMicroseconds()); | |
| 139 buffer_message->set_is_key_frame(decoder_buffer->is_key_frame()); | |
| 140 | |
| 141 if (decoder_buffer->decrypt_config()) { | |
| 142 SerializeDecryptConfig(*decoder_buffer->decrypt_config(), | |
| 143 buffer_message->mutable_decrypt_config()); | |
| 144 } | |
| 145 | |
| 146 buffer_message->set_front_discard_usec( | |
| 147 decoder_buffer->discard_padding().first.InMicroseconds()); | |
| 148 buffer_message->set_back_discard_usec( | |
| 149 decoder_buffer->discard_padding().second.InMicroseconds()); | |
| 150 buffer_message->set_splice_timestamp_usec( | |
| 151 decoder_buffer->splice_timestamp().InMicroseconds()); | |
| 152 | |
| 153 if (decoder_buffer->side_data_size()) { | |
| 154 buffer_message->set_side_data(decoder_buffer->side_data(), | |
| 155 decoder_buffer->side_data_size()); | |
| 156 } | |
| 157 } | |
| 158 | |
| 159 } // namespace | |
| 160 | |
| 161 scoped_refptr<::media::DecoderBuffer> ByteArrayToDecoderBuffer( | |
| 162 const uint8_t* data, | |
| 163 uint32_t size) { | |
| 164 base::BigEndianReader reader(reinterpret_cast<const char*>(data), size); | |
| 165 uint8_t payload_version = 0; | |
| 166 uint32_t proto_size = 0; | |
| 167 pb::DecoderBuffer segment; | |
| 168 uint32_t buffer_size = 0; | |
| 169 if (reader.ReadU8(&payload_version) && payload_version == 0 && | |
| 170 reader.ReadU32(&proto_size) && | |
|
miu
2016/09/13 05:40:57
Looks like this should be reader.ReadU16(&proto_si
erickung1
2016/09/15 02:13:33
Done. Yes, fixed in patch set#8 and also have this
| |
| 171 static_cast<int64_t>(proto_size) < reader.remaining() && | |
| 172 segment.ParseFromArray(reader.ptr(), proto_size) && | |
| 173 reader.Skip(proto_size) && reader.ReadU32(&buffer_size) && | |
| 174 static_cast<int64_t>(buffer_size) <= reader.remaining()) { | |
| 175 // Deserialize proto buffer. It passes the pre allocated DecoderBuffer into | |
| 176 // the function because the proto buffer may overwrite DecoderBuffer since | |
| 177 // it may be EOS buffer. | |
| 178 scoped_refptr<media::DecoderBuffer> decoder_buffer = | |
| 179 DeserializeDecoderBuffer( | |
| 180 segment, | |
| 181 DecoderBuffer::CopyFrom( | |
| 182 reinterpret_cast<const uint8_t*>(reader.ptr()), buffer_size)); | |
| 183 return decoder_buffer; | |
| 184 } | |
| 185 return nullptr; | |
| 186 } | |
| 187 | |
| 188 std::vector<uint8_t> DecoderBufferToByteArray( | |
| 189 const scoped_refptr<::media::DecoderBuffer> decoder_buffer) { | |
| 190 pb::DecoderBuffer decoder_buffer_message; | |
| 191 SerializeDecoderBuffer(decoder_buffer, &decoder_buffer_message); | |
| 192 | |
| 193 std::vector<uint8_t> buffer; | |
|
miu
2016/09/13 05:40:57
Let's move this down to just before the call to re
erickung1
2016/09/15 02:13:33
Done.
| |
| 194 size_t decoder_buffer_size = | |
| 195 decoder_buffer->end_of_stream() ? 0 : decoder_buffer->data_size(); | |
| 196 size_t size = kPayloadVersionFieldSize + kProtoBufferHeaderSize + | |
| 197 decoder_buffer_message.ByteSize() + kDataBufferHeaderSize + | |
|
miu
2016/09/13 05:40:57
I see you're calling decoder_buffer_message.ByteSi
erickung1
2016/09/15 02:13:33
Done.
| |
| 198 decoder_buffer_size; | |
| 199 buffer.resize(size); | |
| 200 | |
| 201 base::BigEndianWriter writer(reinterpret_cast<char*>(buffer.data()), | |
| 202 buffer.size()); | |
| 203 if (writer.WriteU8(0) && | |
| 204 writer.WriteU16( | |
| 205 static_cast<uint16_t>(decoder_buffer_message.ByteSize())) && | |
| 206 decoder_buffer_message.SerializeToArray( | |
| 207 writer.ptr(), decoder_buffer_message.ByteSize()) && | |
| 208 writer.Skip(decoder_buffer_message.ByteSize()) && | |
| 209 writer.WriteU32(decoder_buffer_size)) { | |
| 210 if (decoder_buffer_size) { | |
| 211 // DecoderBuffer frame data. | |
| 212 writer.WriteBytes(reinterpret_cast<const void*>(decoder_buffer->data()), | |
| 213 decoder_buffer->data_size()); | |
| 214 } | |
| 215 return buffer; | |
| 216 } | |
| 217 | |
| 218 // Reset buffer since data is corrupted during serialization. | |
|
miu
2016/09/13 05:40:57
s/data is corrupted during serialization/serializa
erickung1
2016/09/15 02:13:33
Done.
| |
| 219 buffer.clear(); | |
| 220 return buffer; | |
| 221 } | |
| 222 | |
| 223 } // namespace remoting | |
| 224 } // namespace media | |
| OLD | NEW |