OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 // |
5 #include "media/cast/logging/log_serializer.h" | 5 // The serialization format is as follows: |
6 | 6 // 8-bit integer describing |is_audio|. |
7 #include "base/big_endian.h" | 7 // 32-bit integer describing |first_rtp_timestamp|. |
8 | 8 // 32-bit integer describing number of frame events. |
9 namespace media { | |
10 namespace cast { | |
11 | |
12 LogSerializer::LogSerializer(const int max_serialized_bytes) | |
13 : index_so_far_(0), max_serialized_bytes_(max_serialized_bytes) { | |
14 DCHECK_GT(max_serialized_bytes_, 0); | |
15 } | |
16 | |
17 LogSerializer::~LogSerializer() {} | |
18 | |
19 // The format is as follows: | |
20 // 16-bit integer describing the folowing LogMetadata proto size in bytes. | |
21 // The LogMetadata proto. | |
22 // (The following repeated for number of frame events): | 9 // (The following repeated for number of frame events): |
23 // 16-bit integer describing the following AggregatedFrameEvent proto size | 10 // 16-bit integer describing the following AggregatedFrameEvent proto size |
24 // in bytes. | 11 // in bytes. |
25 // The AggregatedFrameEvent proto. | 12 // The AggregatedFrameEvent proto. |
26 // 32-bit integer describing number of packet events. | 13 // 32-bit integer describing number of packet events. |
27 // (The following repeated for number of packet events): | 14 // (The following repeated for number of packet events): |
28 // 16-bit integer describing the following AggregatedPacketEvent proto | 15 // 16-bit integer describing the following AggregatedPacketEvent proto |
29 // size in bytes. | 16 // size in bytes. |
30 // The AggregatedPacketEvent proto. | 17 // The AggregatedPacketEvent proto. |
31 bool LogSerializer::SerializeEventsForStream( | |
32 const media::cast::proto::LogMetadata& metadata, | |
33 const FrameEventMap& frame_events, | |
34 const PacketEventMap& packet_events) { | |
35 if (!serialized_log_so_far_) { | |
36 serialized_log_so_far_.reset(new std::string(max_serialized_bytes_, 0)); | |
37 } | |
38 | 18 |
39 int remaining_space = serialized_log_so_far_->size() - index_so_far_; | 19 #include "media/cast/logging/log_serializer.h" |
40 if (remaining_space <= 0) | |
41 return false; | |
42 | 20 |
43 base::BigEndianWriter writer(&(*serialized_log_so_far_)[index_so_far_], | 21 #include "base/big_endian.h" |
44 remaining_space); | 22 #include "third_party/zlib/zlib.h" |
| 23 |
| 24 namespace media { |
| 25 namespace cast { |
| 26 |
| 27 namespace { |
| 28 |
| 29 using media::cast::proto::AggregatedFrameEvent; |
| 30 using media::cast::proto::AggregatedPacketEvent; |
| 31 using media::cast::proto::LogMetadata; |
| 32 |
| 33 // Use 30MB of temp buffer to hold uncompressed data if |compress| is true. |
| 34 const int kMaxUncompressedBytes = 30 * 1000 * 1000; |
| 35 |
| 36 bool DoSerializeEvents(const LogMetadata& metadata, |
| 37 const FrameEventMap& frame_events, |
| 38 const PacketEventMap& packet_events, |
| 39 const int max_output_bytes, |
| 40 char* output, |
| 41 int* output_bytes) { |
| 42 base::BigEndianWriter writer(output, max_output_bytes); |
45 | 43 |
46 int proto_size = metadata.ByteSize(); | 44 int proto_size = metadata.ByteSize(); |
47 if (!writer.WriteU16(proto_size)) | 45 if (!writer.WriteU16(proto_size)) |
48 return false; | 46 return false; |
49 if (!metadata.SerializeToArray(writer.ptr(), writer.remaining())) | 47 if (!metadata.SerializeToArray(writer.ptr(), writer.remaining())) |
50 return false; | 48 return false; |
51 if (!writer.Skip(proto_size)) | 49 if (!writer.Skip(proto_size)) |
52 return false; | 50 return false; |
53 | 51 |
54 for (media::cast::FrameEventMap::const_iterator it = frame_events.begin(); | 52 for (media::cast::FrameEventMap::const_iterator it = frame_events.begin(); |
55 it != frame_events.end(); | 53 it != frame_events.end(); |
56 ++it) { | 54 ++it) { |
57 proto_size = it->second->ByteSize(); | 55 proto_size = it->second->ByteSize(); |
| 56 |
58 // Write size of the proto, then write the proto. | 57 // Write size of the proto, then write the proto. |
59 if (!writer.WriteU16(proto_size)) | 58 if (!writer.WriteU16(proto_size)) |
60 return false; | 59 return false; |
61 if (!it->second->SerializeToArray(writer.ptr(), writer.remaining())) | 60 if (!it->second->SerializeToArray(writer.ptr(), writer.remaining())) |
62 return false; | 61 return false; |
63 if (!writer.Skip(proto_size)) | 62 if (!writer.Skip(proto_size)) |
64 return false; | 63 return false; |
65 } | 64 } |
66 | 65 |
67 // Write packet events. | 66 // Write packet events. |
68 for (media::cast::PacketEventMap::const_iterator it = packet_events.begin(); | 67 for (media::cast::PacketEventMap::const_iterator it = packet_events.begin(); |
69 it != packet_events.end(); | 68 it != packet_events.end(); |
70 ++it) { | 69 ++it) { |
71 proto_size = it->second->ByteSize(); | 70 proto_size = it->second->ByteSize(); |
| 71 |
72 // Write size of the proto, then write the proto. | 72 // Write size of the proto, then write the proto. |
73 if (!writer.WriteU16(proto_size)) | 73 if (!writer.WriteU16(proto_size)) |
74 return false; | 74 return false; |
75 if (!it->second->SerializeToArray(writer.ptr(), writer.remaining())) | 75 if (!it->second->SerializeToArray(writer.ptr(), writer.remaining())) |
76 return false; | 76 return false; |
77 if (!writer.Skip(proto_size)) | 77 if (!writer.Skip(proto_size)) |
78 return false; | 78 return false; |
79 } | 79 } |
80 | 80 |
81 index_so_far_ = serialized_log_so_far_->size() - writer.remaining(); | 81 *output_bytes = max_output_bytes - writer.remaining(); |
82 return true; | 82 return true; |
83 } | 83 } |
84 | 84 |
85 scoped_ptr<std::string> LogSerializer::GetSerializedLogAndReset() { | 85 bool Compress(char* uncompressed_buffer, |
86 serialized_log_so_far_->resize(index_so_far_); | 86 int uncompressed_bytes, |
87 index_so_far_ = 0; | 87 int max_output_bytes, |
88 return serialized_log_so_far_.Pass(); | 88 char* output, |
| 89 int* output_bytes) { |
| 90 z_stream stream = {0}; |
| 91 int result = deflateInit2(&stream, |
| 92 Z_DEFAULT_COMPRESSION, |
| 93 Z_DEFLATED, |
| 94 // 16 is added to produce a gzip header + trailer. |
| 95 MAX_WBITS + 16, |
| 96 8, // memLevel = 8 is default. |
| 97 Z_DEFAULT_STRATEGY); |
| 98 DCHECK_EQ(Z_OK, result); |
| 99 |
| 100 stream.next_in = reinterpret_cast<uint8*>(uncompressed_buffer); |
| 101 stream.avail_in = uncompressed_bytes; |
| 102 stream.next_out = reinterpret_cast<uint8*>(output); |
| 103 stream.avail_out = max_output_bytes; |
| 104 |
| 105 // Do a one-shot compression. This will return Z_STREAM_END only if |output| |
| 106 // is large enough to hold all compressed data. |
| 107 result = deflate(&stream, Z_FINISH); |
| 108 bool success = (result == Z_STREAM_END); |
| 109 |
| 110 if (!success) |
| 111 DVLOG(2) << "deflate() failed. Result: " << result; |
| 112 |
| 113 result = deflateEnd(&stream); |
| 114 DCHECK(result == Z_OK || result == Z_DATA_ERROR); |
| 115 |
| 116 if (success) |
| 117 *output_bytes = max_output_bytes - stream.avail_out; |
| 118 |
| 119 return success; |
89 } | 120 } |
90 | 121 |
91 int LogSerializer::GetSerializedLength() const { return index_so_far_; } | 122 } // namespace |
| 123 |
| 124 bool SerializeEvents(const LogMetadata& log_metadata, |
| 125 const FrameEventMap& frame_events, |
| 126 const PacketEventMap& packet_events, |
| 127 bool compress, |
| 128 int max_output_bytes, |
| 129 char* output, |
| 130 int* output_bytes) { |
| 131 DCHECK_GT(max_output_bytes, 0); |
| 132 DCHECK(output); |
| 133 DCHECK(output_bytes); |
| 134 |
| 135 if (compress) { |
| 136 // Allocate a reasonably large temp buffer to hold uncompressed data. |
| 137 scoped_ptr<char[]> uncompressed_buffer(new char[kMaxUncompressedBytes]); |
| 138 int uncompressed_bytes; |
| 139 bool success = DoSerializeEvents(log_metadata, |
| 140 frame_events, |
| 141 packet_events, |
| 142 kMaxUncompressedBytes, |
| 143 uncompressed_buffer.get(), |
| 144 &uncompressed_bytes); |
| 145 if (!success) |
| 146 return false; |
| 147 return Compress(uncompressed_buffer.get(), |
| 148 uncompressed_bytes, |
| 149 max_output_bytes, |
| 150 output, |
| 151 output_bytes); |
| 152 } else { |
| 153 return DoSerializeEvents(log_metadata, |
| 154 frame_events, |
| 155 packet_events, |
| 156 max_output_bytes, |
| 157 output, |
| 158 output_bytes); |
| 159 } |
| 160 } |
92 | 161 |
93 } // namespace cast | 162 } // namespace cast |
94 } // namespace media | 163 } // namespace media |
OLD | NEW |