Ignore title parameter for navigator.registerProtocolHandler
[chromium-blink-merge.git] / media / cast / logging / log_deserializer.cc
bloba4c79b3de950bef74568ab7c220525c0509989d5
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 <map>
8 #include <utility>
10 #include "base/big_endian.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "third_party/zlib/zlib.h"
14 using media::cast::FrameEventMap;
15 using media::cast::PacketEventMap;
16 using media::cast::RtpTimestamp;
17 using media::cast::proto::AggregatedFrameEvent;
18 using media::cast::proto::AggregatedPacketEvent;
19 using media::cast::proto::BasePacketEvent;
20 using media::cast::proto::LogMetadata;
22 namespace {
24 // Use 60MB of temp buffer to hold uncompressed data if |compress| is true.
25 // This is double the size of temp buffer used during compression (30MB)
26 // since the there are two streams in the blob.
27 // Keep in sync with media/cast/logging/log_serializer.cc.
28 const int kMaxUncompressedBytes = 60 * 1000 * 1000;
30 void MergePacketEvent(const AggregatedPacketEvent& from,
31 linked_ptr<AggregatedPacketEvent> to) {
32 for (int i = 0; i < from.base_packet_event_size(); i++) {
33 const BasePacketEvent& from_base_event = from.base_packet_event(i);
34 bool merged = false;
35 for (int j = 0; j < to->base_packet_event_size(); j++) {
36 BasePacketEvent* to_base_event = to->mutable_base_packet_event(j);
37 if (from_base_event.packet_id() == to_base_event->packet_id()) {
38 to_base_event->MergeFrom(from_base_event);
39 merged = true;
40 break;
43 if (!merged) {
44 BasePacketEvent* to_base_event = to->add_base_packet_event();
45 to_base_event->CopyFrom(from_base_event);
50 void MergeFrameEvent(const AggregatedFrameEvent& from,
51 linked_ptr<AggregatedFrameEvent> to) {
52 to->mutable_event_type()->MergeFrom(from.event_type());
53 to->mutable_event_timestamp_ms()->MergeFrom(from.event_timestamp_ms());
54 if (!to->has_encoded_frame_size() && from.has_encoded_frame_size())
55 to->set_encoded_frame_size(from.encoded_frame_size());
56 if (!to->has_delay_millis() && from.has_delay_millis())
57 to->set_delay_millis(from.delay_millis());
58 if (!to->has_key_frame() && from.has_key_frame())
59 to->set_key_frame(from.key_frame());
60 if (!to->has_target_bitrate() && from.has_target_bitrate())
61 to->set_target_bitrate(from.target_bitrate());
64 bool PopulateDeserializedLog(base::BigEndianReader* reader,
65 media::cast::DeserializedLog* log) {
66 FrameEventMap frame_event_map;
67 PacketEventMap packet_event_map;
69 int num_frame_events = log->metadata.num_frame_events();
70 RtpTimestamp relative_rtp_timestamp = 0;
71 uint16 proto_size = 0;
72 for (int i = 0; i < num_frame_events; i++) {
73 if (!reader->ReadU16(&proto_size))
74 return false;
76 linked_ptr<AggregatedFrameEvent> frame_event(new AggregatedFrameEvent);
77 if (!frame_event->ParseFromArray(reader->ptr(), proto_size))
78 return false;
79 if (!reader->Skip(proto_size))
80 return false;
82 // During serialization the RTP timestamp in proto is relative to previous
83 // frame.
84 // Adjust RTP timestamp back to value relative to first RTP timestamp.
85 frame_event->set_relative_rtp_timestamp(
86 frame_event->relative_rtp_timestamp() + relative_rtp_timestamp);
87 relative_rtp_timestamp = frame_event->relative_rtp_timestamp();
89 FrameEventMap::iterator it = frame_event_map.find(
90 frame_event->relative_rtp_timestamp());
91 if (it == frame_event_map.end()) {
92 frame_event_map.insert(
93 std::make_pair(frame_event->relative_rtp_timestamp(), frame_event));
94 } else {
95 // Events for the same frame might have been split into more than one
96 // proto. Merge them.
97 MergeFrameEvent(*frame_event, it->second);
101 log->frame_events.swap(frame_event_map);
103 int num_packet_events = log->metadata.num_packet_events();
104 relative_rtp_timestamp = 0;
105 for (int i = 0; i < num_packet_events; i++) {
106 if (!reader->ReadU16(&proto_size))
107 return false;
109 linked_ptr<AggregatedPacketEvent> packet_event(new AggregatedPacketEvent);
110 if (!packet_event->ParseFromArray(reader->ptr(), proto_size))
111 return false;
112 if (!reader->Skip(proto_size))
113 return false;
115 packet_event->set_relative_rtp_timestamp(
116 packet_event->relative_rtp_timestamp() + relative_rtp_timestamp);
117 relative_rtp_timestamp = packet_event->relative_rtp_timestamp();
119 PacketEventMap::iterator it = packet_event_map.find(
120 packet_event->relative_rtp_timestamp());
121 if (it == packet_event_map.end()) {
122 packet_event_map.insert(
123 std::make_pair(packet_event->relative_rtp_timestamp(), packet_event));
124 } else {
125 // Events for the same frame might have been split into more than one
126 // proto. Merge them.
127 MergePacketEvent(*packet_event, it->second);
131 log->packet_events.swap(packet_event_map);
133 return true;
136 bool DoDeserializeEvents(const char* data,
137 int data_bytes,
138 media::cast::DeserializedLog* audio_log,
139 media::cast::DeserializedLog* video_log) {
140 bool got_audio = false;
141 bool got_video = false;
142 base::BigEndianReader reader(data, data_bytes);
144 LogMetadata metadata;
145 uint16 proto_size = 0;
146 while (reader.remaining() > 0) {
147 if (!reader.ReadU16(&proto_size))
148 return false;
149 if (!metadata.ParseFromArray(reader.ptr(), proto_size))
150 return false;
151 reader.Skip(proto_size);
153 if (metadata.is_audio()) {
154 if (got_audio) {
155 VLOG(1) << "Got audio data twice.";
156 return false;
159 got_audio = true;
160 audio_log->metadata = metadata;
161 if (!PopulateDeserializedLog(&reader, audio_log))
162 return false;
163 } else {
164 if (got_video) {
165 VLOG(1) << "Got duplicate video log.";
166 return false;
169 got_video = true;
170 video_log->metadata = metadata;
171 if (!PopulateDeserializedLog(&reader, video_log))
172 return false;
175 return true;
178 bool Uncompress(const char* data,
179 int data_bytes,
180 int max_uncompressed_bytes,
181 char* uncompressed,
182 int* uncompressed_bytes) {
183 z_stream stream = {0};
185 stream.next_in = reinterpret_cast<uint8*>(const_cast<char*>(data));
186 stream.avail_in = data_bytes;
187 stream.next_out = reinterpret_cast<uint8*>(uncompressed);
188 stream.avail_out = max_uncompressed_bytes;
190 bool success = false;
191 while (stream.avail_in > 0 && stream.avail_out > 0) {
192 // 16 is added to read in gzip format.
193 int result = inflateInit2(&stream, MAX_WBITS + 16);
194 DCHECK_EQ(Z_OK, result);
196 result = inflate(&stream, Z_FINISH);
197 success = (result == Z_STREAM_END);
198 if (!success) {
199 DVLOG(2) << "inflate() failed. Result: " << result;
200 break;
203 result = inflateEnd(&stream);
204 DCHECK(result == Z_OK);
207 if (stream.avail_in == 0) {
208 success = true;
209 *uncompressed_bytes = max_uncompressed_bytes - stream.avail_out;
211 return success;
214 } // namespace
216 namespace media {
217 namespace cast {
219 bool DeserializeEvents(const char* data,
220 int data_bytes,
221 bool compressed,
222 DeserializedLog* audio_log,
223 DeserializedLog* video_log) {
224 DCHECK_GT(data_bytes, 0);
226 if (compressed) {
227 scoped_ptr<char[]> uncompressed(new char[kMaxUncompressedBytes]);
228 int uncompressed_bytes = 0;
229 if (!Uncompress(data,
230 data_bytes,
231 kMaxUncompressedBytes,
232 uncompressed.get(),
233 &uncompressed_bytes))
234 return false;
236 return DoDeserializeEvents(
237 uncompressed.get(), uncompressed_bytes, audio_log, video_log);
238 } else {
239 return DoDeserializeEvents(data, data_bytes, audio_log, video_log);
243 DeserializedLog::DeserializedLog() {}
244 DeserializedLog::~DeserializedLog() {}
246 } // namespace cast
247 } // namespace media