Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / cast / logging / log_serializer.cc
blobc5cb252d781a3bc6bee05f58c4350335e948818c
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.
4 //
5 // The serialization format is as follows:
6 // 16-bit integer describing the following LogMetadata proto size in bytes.
7 // The LogMetadata proto.
8 // 32-bit integer describing number of frame events.
9 // (The following repeated for number of frame events):
10 // 16-bit integer describing the following AggregatedFrameEvent proto size
11 // in bytes.
12 // The AggregatedFrameEvent proto.
13 // 32-bit integer describing number of packet events.
14 // (The following repeated for number of packet events):
15 // 16-bit integer describing the following AggregatedPacketEvent proto
16 // size in bytes.
17 // The AggregatedPacketEvent proto.
19 #include "media/cast/logging/log_serializer.h"
21 #include "base/big_endian.h"
22 #include "base/logging.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "third_party/zlib/zlib.h"
26 namespace media {
27 namespace cast {
29 namespace {
31 using media::cast::proto::AggregatedFrameEvent;
32 using media::cast::proto::AggregatedPacketEvent;
33 using media::cast::proto::LogMetadata;
35 // Use 30MB of temp buffer to hold uncompressed data if |compress| is true.
36 const int kMaxUncompressedBytes = 30 * 1000 * 1000;
38 // The maximum allowed size per serialized proto.
39 const int kMaxSerializedProtoBytes = (1 << 16) - 1;
40 bool DoSerializeEvents(const LogMetadata& metadata,
41 const FrameEventList& frame_events,
42 const PacketEventList& packet_events,
43 const int max_output_bytes,
44 char* output,
45 int* output_bytes) {
46 base::BigEndianWriter writer(output, max_output_bytes);
48 int proto_size = metadata.ByteSize();
49 DCHECK(proto_size <= kMaxSerializedProtoBytes);
50 if (!writer.WriteU16(static_cast<uint16>(proto_size)))
51 return false;
52 if (!metadata.SerializeToArray(writer.ptr(), writer.remaining()))
53 return false;
54 if (!writer.Skip(proto_size))
55 return false;
57 RtpTimestamp prev_rtp_timestamp = 0;
58 for (media::cast::FrameEventList::const_iterator it = frame_events.begin();
59 it != frame_events.end();
60 ++it) {
61 media::cast::proto::AggregatedFrameEvent frame_event(**it);
63 // Adjust relative RTP timestamp so that it is relative to previous frame,
64 // rather than relative to first RTP timestamp.
65 // This is done to improve encoding size.
66 RtpTimestamp old_relative_rtp_timestamp =
67 frame_event.relative_rtp_timestamp();
68 frame_event.set_relative_rtp_timestamp(
69 old_relative_rtp_timestamp - prev_rtp_timestamp);
70 prev_rtp_timestamp = old_relative_rtp_timestamp;
72 proto_size = frame_event.ByteSize();
73 DCHECK(proto_size <= kMaxSerializedProtoBytes);
75 // Write size of the proto, then write the proto.
76 if (!writer.WriteU16(static_cast<uint16>(proto_size)))
77 return false;
78 if (!frame_event.SerializeToArray(writer.ptr(), writer.remaining()))
79 return false;
80 if (!writer.Skip(proto_size))
81 return false;
84 // Write packet events.
85 prev_rtp_timestamp = 0;
86 for (media::cast::PacketEventList::const_iterator it = packet_events.begin();
87 it != packet_events.end();
88 ++it) {
89 media::cast::proto::AggregatedPacketEvent packet_event(**it);
90 RtpTimestamp old_relative_rtp_timestamp =
91 packet_event.relative_rtp_timestamp();
92 packet_event.set_relative_rtp_timestamp(
93 old_relative_rtp_timestamp - prev_rtp_timestamp);
94 prev_rtp_timestamp = old_relative_rtp_timestamp;
96 proto_size = packet_event.ByteSize();
97 DCHECK(proto_size <= kMaxSerializedProtoBytes);
99 // Write size of the proto, then write the proto.
100 if (!writer.WriteU16(static_cast<uint16>(proto_size)))
101 return false;
102 if (!packet_event.SerializeToArray(writer.ptr(), writer.remaining()))
103 return false;
104 if (!writer.Skip(proto_size))
105 return false;
108 *output_bytes = max_output_bytes - writer.remaining();
109 return true;
112 bool Compress(char* uncompressed_buffer,
113 int uncompressed_bytes,
114 int max_output_bytes,
115 char* output,
116 int* output_bytes) {
117 z_stream stream = {0};
118 int result = deflateInit2(&stream,
119 Z_DEFAULT_COMPRESSION,
120 Z_DEFLATED,
121 // 16 is added to produce a gzip header + trailer.
122 MAX_WBITS + 16,
123 8, // memLevel = 8 is default.
124 Z_DEFAULT_STRATEGY);
125 DCHECK_EQ(Z_OK, result);
127 stream.next_in = reinterpret_cast<uint8*>(uncompressed_buffer);
128 stream.avail_in = uncompressed_bytes;
129 stream.next_out = reinterpret_cast<uint8*>(output);
130 stream.avail_out = max_output_bytes;
132 // Do a one-shot compression. This will return Z_STREAM_END only if |output|
133 // is large enough to hold all compressed data.
134 result = deflate(&stream, Z_FINISH);
135 bool success = (result == Z_STREAM_END);
137 if (!success)
138 DVLOG(2) << "deflate() failed. Result: " << result;
140 result = deflateEnd(&stream);
141 DCHECK(result == Z_OK || result == Z_DATA_ERROR);
143 if (success)
144 *output_bytes = max_output_bytes - stream.avail_out;
146 return success;
149 } // namespace
151 bool SerializeEvents(const LogMetadata& log_metadata,
152 const FrameEventList& frame_events,
153 const PacketEventList& packet_events,
154 bool compress,
155 int max_output_bytes,
156 char* output,
157 int* output_bytes) {
158 DCHECK_GT(max_output_bytes, 0);
159 DCHECK(output);
160 DCHECK(output_bytes);
162 if (compress) {
163 // Allocate a reasonably large temp buffer to hold uncompressed data.
164 scoped_ptr<char[]> uncompressed_buffer(new char[kMaxUncompressedBytes]);
165 int uncompressed_bytes;
166 bool success = DoSerializeEvents(log_metadata,
167 frame_events,
168 packet_events,
169 kMaxUncompressedBytes,
170 uncompressed_buffer.get(),
171 &uncompressed_bytes);
172 if (!success)
173 return false;
174 return Compress(uncompressed_buffer.get(),
175 uncompressed_bytes,
176 max_output_bytes,
177 output,
178 output_bytes);
179 } else {
180 return DoSerializeEvents(log_metadata,
181 frame_events,
182 packet_events,
183 max_output_bytes,
184 output,
185 output_bytes);
189 } // namespace cast
190 } // namespace media