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()); | |
miu
2016/09/08 01:07:34
These DCHECKs suggest the fields should not have b
erickung1
2016/09/13 03:52:52
After the discussion, the field in proto buffer wi
miu
2016/09/13 05:40:57
Should we keep these checks? If they are needed, a
erickung1
2016/09/15 02:13:32
Done.
| |
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)); | |
miu
2016/09/08 01:07:34
You can simplify here and eliminate the local vari
erickung1
2016/09/13 03:52:53
Done.
| |
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()), | |
miu
2016/09/08 01:07:34
Don't use c_str() here. Use data() instead.
erickung1
2016/09/13 03:52:52
Done.
| |
102 buffer_message.side_data().size()); | |
103 } | |
104 | |
105 return buffer; | |
106 } | |
107 | |
108 void SerializeDecryptConfig(const ::media::DecryptConfig* decrypt_config, | |
miu
2016/09/08 01:07:34
nit: Please pass by const-reference instead of con
erickung1
2016/09/13 03:52:53
Done.
| |
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++]; | |
miu
2016/09/08 01:07:34
In Chrome, please use base::BigEndianReader instea
erickung1
2016/09/13 03:52:52
Done.
| |
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; | |
miu
2016/09/08 01:07:34
naming nit: How about decoder_buffer_message?
erickung1
2016/09/13 03:52:53
Done.
| |
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; | |
miu
2016/09/08 01:07:34
Like above, please use base::BigEndianWriter here:
erickung1
2016/09/13 03:52:52
Done.
| |
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, | |
miu
2016/09/08 01:07:34
FYI--DCHECKs() do not evaluate in release builds.
erickung1
2016/09/13 03:52:52
Done.
| |
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 |