| 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 |