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

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

Issue 2261503002: Define remote playback proto buffer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: DecoderBufferSegment more description and change interface name 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/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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698