Remove INJECT_EVENTS permissions from test APKs.
[chromium-blink-merge.git] / media / cast / logging / log_deserializer.cc
blob5e5b189115c805996d7e8b3bdb74038cb5924fdd
1 // Copyright 2014 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.
5 #include "media/cast/logging/log_deserializer.h"
7 #include <utility>
9 #include "base/big_endian.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "third_party/zlib/zlib.h"
13 using media::cast::FrameEventMap;
14 using media::cast::PacketEventMap;
15 using media::cast::RtpTimestamp;
16 using media::cast::proto::AggregatedFrameEvent;
17 using media::cast::proto::AggregatedPacketEvent;
18 using media::cast::proto::BasePacketEvent;
19 using media::cast::proto::LogMetadata;
21 namespace {
23 // Use 60MB of temp buffer to hold uncompressed data if |compress| is true.
24 // This is double the size of temp buffer used during compression (30MB)
25 // since the there are two streams in the blob.
26 // Keep in sync with media/cast/logging/log_serializer.cc.
27 const int kMaxUncompressedBytes = 60 * 1000 * 1000;
29 void MergePacketEvent(const AggregatedPacketEvent& from,
30 linked_ptr<AggregatedPacketEvent> to) {
31 for (int i = 0; i < from.base_packet_event_size(); i++) {
32 const BasePacketEvent& from_base_event = from.base_packet_event(i);
33 bool merged = false;
34 for (int j = 0; j < to->base_packet_event_size(); j++) {
35 BasePacketEvent* to_base_event = to->mutable_base_packet_event(j);
36 if (from_base_event.packet_id() == to_base_event->packet_id()) {
37 int packet_size = std::max(
38 from_base_event.size(), to_base_event->size());
39 // Need special merge logic here because we need to prevent a valid
40 // packet size (> 0) from being overwritten with an invalid one (= 0).
41 to_base_event->MergeFrom(from_base_event);
42 to_base_event->set_size(packet_size);
43 merged = true;
44 break;
47 if (!merged) {
48 BasePacketEvent* to_base_event = to->add_base_packet_event();
49 to_base_event->CopyFrom(from_base_event);
54 void MergeFrameEvent(const AggregatedFrameEvent& from,
55 linked_ptr<AggregatedFrameEvent> to) {
56 to->mutable_event_type()->MergeFrom(from.event_type());
57 to->mutable_event_timestamp_ms()->MergeFrom(from.event_timestamp_ms());
58 if (!to->has_encoded_frame_size() && from.has_encoded_frame_size())
59 to->set_encoded_frame_size(from.encoded_frame_size());
60 if (!to->has_delay_millis() && from.has_delay_millis())
61 to->set_delay_millis(from.delay_millis());
62 if (!to->has_key_frame() && from.has_key_frame())
63 to->set_key_frame(from.key_frame());
64 if (!to->has_target_bitrate() && from.has_target_bitrate())
65 to->set_target_bitrate(from.target_bitrate());
68 bool PopulateDeserializedLog(base::BigEndianReader* reader,
69 media::cast::DeserializedLog* log) {
70 FrameEventMap frame_event_map;
71 PacketEventMap packet_event_map;
73 int num_frame_events = log->metadata.num_frame_events();
74 RtpTimestamp relative_rtp_timestamp = 0;
75 uint16 proto_size = 0;
76 for (int i = 0; i < num_frame_events; i++) {
77 if (!reader->ReadU16(&proto_size))
78 return false;
80 linked_ptr<AggregatedFrameEvent> frame_event(new AggregatedFrameEvent);
81 if (!frame_event->ParseFromArray(reader->ptr(), proto_size))
82 return false;
83 if (!reader->Skip(proto_size))
84 return false;
86 // During serialization the RTP timestamp in proto is relative to previous
87 // frame.
88 // Adjust RTP timestamp back to value relative to first RTP timestamp.
89 frame_event->set_relative_rtp_timestamp(
90 frame_event->relative_rtp_timestamp() + relative_rtp_timestamp);
91 relative_rtp_timestamp = frame_event->relative_rtp_timestamp();
93 FrameEventMap::iterator it = frame_event_map.find(
94 frame_event->relative_rtp_timestamp());
95 if (it == frame_event_map.end()) {
96 frame_event_map.insert(
97 std::make_pair(frame_event->relative_rtp_timestamp(), frame_event));
98 } else {
99 // Events for the same frame might have been split into more than one
100 // proto. Merge them.
101 MergeFrameEvent(*frame_event, it->second);
105 log->frame_events.swap(frame_event_map);
107 int num_packet_events = log->metadata.num_packet_events();
108 relative_rtp_timestamp = 0;
109 for (int i = 0; i < num_packet_events; i++) {
110 if (!reader->ReadU16(&proto_size))
111 return false;
113 linked_ptr<AggregatedPacketEvent> packet_event(new AggregatedPacketEvent);
114 if (!packet_event->ParseFromArray(reader->ptr(), proto_size))
115 return false;
116 if (!reader->Skip(proto_size))
117 return false;
119 packet_event->set_relative_rtp_timestamp(
120 packet_event->relative_rtp_timestamp() + relative_rtp_timestamp);
121 relative_rtp_timestamp = packet_event->relative_rtp_timestamp();
123 PacketEventMap::iterator it = packet_event_map.find(
124 packet_event->relative_rtp_timestamp());
125 if (it == packet_event_map.end()) {
126 packet_event_map.insert(
127 std::make_pair(packet_event->relative_rtp_timestamp(), packet_event));
128 } else {
129 // Events for the same frame might have been split into more than one
130 // proto. Merge them.
131 MergePacketEvent(*packet_event, it->second);
135 log->packet_events.swap(packet_event_map);
137 return true;
140 bool DoDeserializeEvents(const char* data,
141 int data_bytes,
142 media::cast::DeserializedLog* audio_log,
143 media::cast::DeserializedLog* video_log) {
144 bool got_audio = false;
145 bool got_video = false;
146 base::BigEndianReader reader(data, data_bytes);
148 LogMetadata metadata;
149 uint16 proto_size = 0;
150 while (reader.remaining() > 0) {
151 if (!reader.ReadU16(&proto_size))
152 return false;
153 if (!metadata.ParseFromArray(reader.ptr(), proto_size))
154 return false;
155 reader.Skip(proto_size);
157 if (metadata.is_audio()) {
158 if (got_audio) {
159 VLOG(1) << "Got audio data twice.";
160 return false;
163 got_audio = true;
164 audio_log->metadata = metadata;
165 if (!PopulateDeserializedLog(&reader, audio_log))
166 return false;
167 } else {
168 if (got_video) {
169 VLOG(1) << "Got duplicate video log.";
170 return false;
173 got_video = true;
174 video_log->metadata = metadata;
175 if (!PopulateDeserializedLog(&reader, video_log))
176 return false;
179 return true;
182 bool Uncompress(const char* data,
183 int data_bytes,
184 int max_uncompressed_bytes,
185 char* uncompressed,
186 int* uncompressed_bytes) {
187 z_stream stream = {0};
189 stream.next_in = reinterpret_cast<uint8*>(const_cast<char*>(data));
190 stream.avail_in = data_bytes;
191 stream.next_out = reinterpret_cast<uint8*>(uncompressed);
192 stream.avail_out = max_uncompressed_bytes;
194 bool success = false;
195 while (stream.avail_in > 0 && stream.avail_out > 0) {
196 // 16 is added to read in gzip format.
197 int result = inflateInit2(&stream, MAX_WBITS + 16);
198 DCHECK_EQ(Z_OK, result);
200 result = inflate(&stream, Z_FINISH);
201 success = (result == Z_STREAM_END);
202 if (!success) {
203 DVLOG(2) << "inflate() failed. Result: " << result;
204 break;
207 result = inflateEnd(&stream);
208 DCHECK(result == Z_OK);
211 if (stream.avail_in == 0) {
212 success = true;
213 *uncompressed_bytes = max_uncompressed_bytes - stream.avail_out;
215 return success;
218 } // namespace
220 namespace media {
221 namespace cast {
223 bool DeserializeEvents(const char* data,
224 int data_bytes,
225 bool compressed,
226 DeserializedLog* audio_log,
227 DeserializedLog* video_log) {
228 DCHECK_GT(data_bytes, 0);
230 if (compressed) {
231 scoped_ptr<char[]> uncompressed(new char[kMaxUncompressedBytes]);
232 int uncompressed_bytes = 0;
233 if (!Uncompress(data,
234 data_bytes,
235 kMaxUncompressedBytes,
236 uncompressed.get(),
237 &uncompressed_bytes))
238 return false;
240 return DoDeserializeEvents(
241 uncompressed.get(), uncompressed_bytes, audio_log, video_log);
242 } else {
243 return DoDeserializeEvents(data, data_bytes, audio_log, video_log);
247 DeserializedLog::DeserializedLog() {}
248 DeserializedLog::~DeserializedLog() {}
250 } // namespace cast
251 } // namespace media