Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Side by Side Diff: media/remoting/rpc/proto_utils.cc

Issue 2261503002: Define remote playback proto buffer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Change some field to unit32 and add missing enum type in RPC Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/proto_utils.h"
6
7 #include <algorithm>
8
9 #include "base/big_endian.h"
10 #include "base/logging.h"
11 #include "base/time/time.h"
12 #include "base/values.h"
13 #include "media/base/encryption_scheme.h"
14 #include "media/remoting/rpc/proto_enum_utils.h"
15
16 namespace media {
17 namespace remoting {
18
19 const int kInvalidHandle = -1;
20 const int kReceiverHandle = 0;
21
22 namespace {
23
24 const int kPayloadVersionFieldSize = 1;
miu 2016/09/16 18:14:13 For these three constants: 1. s/const/constexpr/
erickung1 2016/09/19 17:04:35 Done.
25 const int kProtoBufferHeaderSize = 2;
26 const int kDataBufferHeaderSize = 4;
27
28 std::unique_ptr<::media::DecryptConfig> ConvertProtoToDecryptConfig(
29 const pb::DecryptConfig& config_message) {
30 std::vector<::media::SubsampleEntry> entries;
miu 2016/09/16 18:14:13 nit: Please move declaration down to where this is
erickung1 2016/09/19 17:04:34 Done.
31
32 if (!config_message.has_key_id())
33 return nullptr;
34 if (!config_message.has_iv())
35 return nullptr;
36
37 for (int i = 0; i < config_message.sub_samples_size(); ++i) {
38 entries.push_back(
39 ::media::SubsampleEntry(config_message.sub_samples(i).clear_bytes(),
40 config_message.sub_samples(i).cypher_bytes()));
41 }
42
43 std::unique_ptr<::media::DecryptConfig> decrypt_config(
44 new ::media::DecryptConfig(config_message.key_id(), config_message.iv(),
45 entries));
46 return decrypt_config;
47 }
48
49 scoped_refptr<::media::DecoderBuffer> ConvertProtoToDecoderBuffer(
50 const pb::DecoderBuffer& buffer_message,
51 scoped_refptr<::media::DecoderBuffer> buffer) {
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 buffer->set_decrypt_config(
74 ConvertProtoToDecryptConfig(buffer_message.decrypt_config()));
75 }
76
77 bool has_discard = false;
78 base::TimeDelta front_discard;
79 if (buffer_message.has_front_discard_usec()) {
80 has_discard = true;
81 front_discard =
82 base::TimeDelta::FromMicroseconds(buffer_message.front_discard_usec());
83 }
84 base::TimeDelta back_discard;
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) {
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 ConvertDecryptConfigToProto(const ::media::DecryptConfig& decrypt_config,
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 ConvertDecoderBufferToProto(
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 ConvertDecryptConfigToProto(*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 uint16_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.ReadU16(&proto_size) &&
171 static_cast<int>(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 ConvertProtoToDecoderBuffer(
180 segment,
181 DecoderBuffer::CopyFrom(
182 reinterpret_cast<const uint8_t*>(reader.ptr()), buffer_size));
183 return decoder_buffer;
184 }
185
186 LOG(ERROR) << "Not able to convert byte array to ::media::DecoderBuffer";
187 return nullptr;
188 }
189
190 std::vector<uint8_t> DecoderBufferToByteArray(
191 const scoped_refptr<::media::DecoderBuffer>& decoder_buffer) {
192 pb::DecoderBuffer decoder_buffer_message;
193 ConvertDecoderBufferToProto(decoder_buffer, &decoder_buffer_message);
194
195 size_t decoder_buffer_size =
196 decoder_buffer->end_of_stream() ? 0 : decoder_buffer->data_size();
197 size_t size = kPayloadVersionFieldSize + kProtoBufferHeaderSize +
198 decoder_buffer_message.ByteSize() + kDataBufferHeaderSize +
199 decoder_buffer_size;
200 std::vector<uint8_t> buffer(size);
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.GetCachedSize())) &&
206 decoder_buffer_message.SerializeToArray(
207 writer.ptr(), decoder_buffer_message.GetCachedSize()) &&
208 writer.Skip(decoder_buffer_message.GetCachedSize()) &&
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 serialization of the data failed.
219 LOG(ERROR) << "Not able to convert ::media::DecoderBuffer to byte array";
220 buffer.clear();
221 return buffer;
222 }
223
224 void ConvertEncryptionSchemeToProto(
225 const ::media::EncryptionScheme& encryption_scheme,
226 pb::EncryptionScheme* message) {
227 DCHECK(message);
228 message->set_mode(
229 ToProtoEncryptionSchemeCipherMode(encryption_scheme.mode()).value());
230 message->set_encrypt_blocks(encryption_scheme.pattern().encrypt_blocks());
231 message->set_skip_blocks(encryption_scheme.pattern().skip_blocks());
232 }
233
234 ::media::EncryptionScheme ConvertProtoToEncryptionScheme(
235 const pb::EncryptionScheme& message) {
236 return ::media::EncryptionScheme(
237 ToMediaEncryptionSchemeCipherMode(message.mode()).value(),
238 ::media::EncryptionScheme::Pattern(message.encrypt_blocks(),
239 message.skip_blocks()));
240 }
241
242 void ConvertAudioDecoderConfigToProto(
243 const ::media::AudioDecoderConfig& audio_config,
244 pb::AudioDecoderConfig* audio_message) {
245 DCHECK(audio_config.IsValidConfig());
246 DCHECK(audio_message);
247
248 audio_message->set_codec(
249 ToProtoAudioDecoderConfigCodec(audio_config.codec()).value());
250 audio_message->set_sample_format(
251 ToProtoAudioDecoderConfigSampleFormat(audio_config.sample_format())
252 .value());
253 audio_message->set_channel_layout(
254 ToProtoAudioDecoderConfigChannelLayout(audio_config.channel_layout())
255 .value());
256 audio_message->set_samples_per_second(audio_config.samples_per_second());
257 audio_message->set_seek_preroll_usec(
258 audio_config.seek_preroll().InMicroseconds());
259 audio_message->set_codec_delay(audio_config.codec_delay());
260
261 if (!audio_config.extra_data().empty()) {
262 audio_message->set_extra_data(audio_config.extra_data().data(),
263 audio_config.extra_data().size());
264 }
265
266 if (audio_config.is_encrypted()) {
267 pb::EncryptionScheme* encryption_scheme_message =
268 audio_message->mutable_encryption_scheme();
269 ConvertEncryptionSchemeToProto(audio_config.encryption_scheme(),
270 encryption_scheme_message);
271 }
272 }
273
274 bool ConvertProtoToAudioDecoderConfig(
275 const pb::AudioDecoderConfig& audio_message,
276 ::media::AudioDecoderConfig* audio_config) {
277 DCHECK(audio_config);
278 audio_config->Initialize(
279 ToMediaAudioCodec(audio_message.codec()).value(),
280 ToMediaSampleFormat(audio_message.sample_format()).value(),
281 ToMediaChannelLayout(audio_message.channel_layout()).value(),
282 audio_message.samples_per_second(),
283 std::vector<uint8_t>(audio_message.extra_data().begin(),
284 audio_message.extra_data().end()),
285 ConvertProtoToEncryptionScheme(audio_message.encryption_scheme()),
286 base::TimeDelta::FromMicroseconds(audio_message.seek_preroll_usec()),
287 audio_message.codec_delay());
288 return audio_config->IsValidConfig();
289 }
290
291 void ConvertVideoDecoderConfigToProto(
292 const ::media::VideoDecoderConfig& video_config,
293 pb::VideoDecoderConfig* video_message) {
294 DCHECK(video_config.IsValidConfig());
295 DCHECK(video_message);
296
297 video_message->set_codec(
298 ToProtoVideoDecoderConfigCodec(video_config.codec()).value());
299 video_message->set_profile(
300 ToProtoVideoDecoderConfigProfile(video_config.profile()).value());
301 video_message->set_format(
302 ToProtoVideoDecoderConfigFormat(video_config.format()).value());
303 video_message->set_color_space(
304 ToProtoVideoDecoderConfigColorSpace(video_config.color_space()).value());
305
306 pb::Size* coded_size_message = video_message->mutable_coded_size();
307 coded_size_message->set_width(video_config.coded_size().width());
308 coded_size_message->set_height(video_config.coded_size().height());
309
310 pb::Rect* visible_rect_message = video_message->mutable_visible_rect();
311 visible_rect_message->set_x(video_config.visible_rect().x());
312 visible_rect_message->set_y(video_config.visible_rect().y());
313 visible_rect_message->set_width(video_config.visible_rect().width());
314 visible_rect_message->set_height(video_config.visible_rect().height());
315
316 pb::Size* natural_size_message = video_message->mutable_natural_size();
317 natural_size_message->set_width(video_config.natural_size().width());
318 natural_size_message->set_height(video_config.natural_size().height());
319
320 if (!video_config.extra_data().empty()) {
321 video_message->set_extra_data(video_config.extra_data().data(),
322 video_config.extra_data().size());
323 }
324
325 if (video_config.is_encrypted()) {
326 pb::EncryptionScheme* encryption_scheme_message =
327 video_message->mutable_encryption_scheme();
328 ConvertEncryptionSchemeToProto(video_config.encryption_scheme(),
329 encryption_scheme_message);
330 }
331 }
332
333 bool ConvertProtoToVideoDecoderConfig(
334 const pb::VideoDecoderConfig& video_message,
335 ::media::VideoDecoderConfig* video_config) {
336 DCHECK(video_config);
337 ::media::EncryptionScheme encryption_scheme;
338 video_config->Initialize(
339 ToMediaVideoCodec(video_message.codec()).value(),
340 ToMediaVideoCodecProfile(video_message.profile()).value(),
341 ToMediaVideoPixelFormat(video_message.format()).value(),
342 ToMediaColorSpace(video_message.color_space()).value(),
343 gfx::Size(video_message.coded_size().width(),
344 video_message.coded_size().height()),
345 gfx::Rect(video_message.visible_rect().x(),
346 video_message.visible_rect().y(),
347 video_message.visible_rect().width(),
348 video_message.visible_rect().height()),
349 gfx::Size(video_message.natural_size().width(),
350 video_message.natural_size().height()),
351 std::vector<uint8_t>(video_message.extra_data().begin(),
352 video_message.extra_data().end()),
353 ConvertProtoToEncryptionScheme(video_message.encryption_scheme()));
354 return video_config->IsValidConfig();
355 }
356
357 void ConvertCdmKeyInfoToProto(
358 const ::media::CdmKeysInfo& keys_information,
359 pb::CdmClientOnSessionKeysChange* key_change_message) {
360 for (const auto& info : keys_information) {
361 pb::CdmKeyInformation* key = key_change_message->add_key_information();
362 key->set_key_id(info->key_id.data(), info->key_id.size());
363 key->set_status(ToProtoCdmKeyInformation(info->status).value());
364 key->set_system_code(info->system_code);
365 }
366 }
367
368 void ConvertProtoToCdmKeyInfo(
369 const pb::CdmClientOnSessionKeysChange keychange_message,
370 CdmKeysInfo* key_information) {
371 DCHECK(key_information);
372 for (int i = 0; i < keychange_message.key_information_size(); ++i) {
miu 2016/09/16 18:14:13 nit: Please add: key_information->reserve(keychang
erickung1 2016/09/19 17:04:35 Done.
373 const pb::CdmKeyInformation key_info_msg =
374 keychange_message.key_information(i);
375
376 std::unique_ptr<::media::CdmKeyInformation> key(
377 new ::media::CdmKeyInformation(
378 key_info_msg.key_id(),
379 ToMediaCdmKeyInformationKeyStatus(key_info_msg.status()).value(),
380 key_info_msg.system_code()));
381 key_information->push_back(std::move(key));
382 }
383 }
384
385 void ConvertCdmPromiseToProto(const CdmPromiseResult& result,
386 pb::CdmPromise* promise_message) {
387 promise_message->set_success(result.success());
388 if (!result.success()) {
389 promise_message->set_exception(
390 ToProtoMediaKeysException(result.exception()).value());
391 promise_message->set_system_code(result.system_code());
392 promise_message->set_error_message(result.error_message());
393 }
394 }
395
396 void ConvertCdmPromiseWithSessionIdToProto(const CdmPromiseResult& result,
397 const std::string& session_id,
398 pb::CdmPromise* promise_message) {
399 ConvertCdmPromiseToProto(result, promise_message);
400 if (!session_id.empty())
miu 2016/09/16 18:14:13 Is an empty |session_id| valid? If that would indi
erickung1 2016/09/19 17:04:35 Done. I decided to remove the if condition, since
401 promise_message->set_session_id(session_id);
402 }
403
404 void ConvertCdmPromiseWithCdmIdToProto(const CdmPromiseResult& result,
405 int cdm_id,
406 pb::CdmPromise* promise_message) {
407 ConvertCdmPromiseToProto(result, promise_message);
408 promise_message->set_cdm_id(cdm_id);
409 }
410
411 bool ConvertProtoToCdmPromise(const pb::CdmPromise& promise_message,
412 CdmPromiseResult* result) {
413 if (!promise_message.has_success())
414 return false;
415
416 bool success = promise_message.success();
417 if (success) {
418 *result = CdmPromiseResult::SuccessResult();
419 return true;
420 }
421
422 ::media::MediaKeys::Exception exception = ::media::MediaKeys::UNKNOWN_ERROR;
423 uint32_t system_code = 0;
424 std::string error_message;
425
426 exception = ToMediaMediaKeysException(promise_message.exception()).value();
427 system_code = promise_message.system_code();
428 error_message = promise_message.error_message();
429 *result = CdmPromiseResult(exception, system_code, error_message);
430 return true;
431 }
432
433 bool ConvertProtoToCdmPromiseWithCdmIdSessionId(const pb::RpcMessage& message,
434 CdmPromiseResult* result,
435 int* cdm_id,
436 std::string* session_id) {
437 if (!message.has_cdm_promise_rpc())
438 return false;
439
440 const auto& promise_message = message.cdm_promise_rpc();
441 if (!ConvertProtoToCdmPromise(promise_message, result))
442 return false;
443
444 if (cdm_id)
445 *cdm_id = promise_message.cdm_id();
446 if (session_id)
447 *session_id = promise_message.session_id();
448
449 return true;
450 }
451
452 //==============================================================================
453 CdmPromiseResult::CdmPromiseResult()
454 : CdmPromiseResult(::media::MediaKeys::UNKNOWN_ERROR, 0, "") {}
455
456 CdmPromiseResult::CdmPromiseResult(::media::MediaKeys::Exception exception,
457 uint32_t system_code,
458 std::string error_message)
459 : success_(false),
460 exception_(exception),
461 system_code_(system_code),
462 error_message_(error_message) {}
463
464 CdmPromiseResult::CdmPromiseResult(const CdmPromiseResult& other) = default;
465
466 CdmPromiseResult::~CdmPromiseResult() = default;
467
468 CdmPromiseResult CdmPromiseResult::SuccessResult() {
469 CdmPromiseResult result(static_cast<::media::MediaKeys::Exception>(0), 0, "");
470 result.success_ = true;
471 return result;
472 }
473
474 } // namespace remoting
475 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698