OLD | NEW |
(Empty) | |
| 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 #include <algorithm> |
| 6 #include <cstdio> |
| 7 #include <iostream> |
| 8 #include <string> |
| 9 #include <sstream> |
| 10 |
| 11 #include "base/rand_util.h" |
| 12 #include "base/time/default_tick_clock.h" |
| 13 #include "media/cast/cast_defines.h" |
| 14 #include "media/cast/logging/logging_defines.h" |
| 15 #include "media/cast/logging/logging_raw.h" |
| 16 #include "media/cast/logging/proto/raw_events.pb.h" |
| 17 #include "media/cast/test/fake_single_thread_task_runner.h" |
| 18 #include "media/cast/logging/encoding_event_subscriber.h" |
| 19 #include "net/base/big_endian.h" |
| 20 #include "third_party/zlib/zlib.h" |
| 21 |
| 22 using media::cast::CastLoggingEvent; |
| 23 using media::cast::EncodingEventSubscriber; |
| 24 using media::cast::FrameEvent; |
| 25 using media::cast::FrameEventMap; |
| 26 using media::cast::GenericEventMap; |
| 27 using media::cast::LoggingRaw; |
| 28 using media::cast::PacketEventMap; |
| 29 using media::cast::proto::AggregatedFrameEvent; |
| 30 using media::cast::proto::AggregatedGenericEvent; |
| 31 using media::cast::proto::AggregatedPacketEvent; |
| 32 using media::cast::proto::BasePacketEvent; |
| 33 using media::cast::test::FakeSingleThreadTaskRunner; |
| 34 |
| 35 const int kFps = 30; |
| 36 const int kNumSeconds = 60 * 30; |
| 37 |
| 38 const int kNumVideoFrames = kFps * kNumSeconds; |
| 39 const CastLoggingEvent kVideoFrameEvents[] = { |
| 40 media::cast::kVideoFrameCaptured, |
| 41 media::cast::kVideoFrameReceived, |
| 42 media::cast::kVideoFrameSentToEncoder, |
| 43 media::cast::kVideoFrameEncoded, |
| 44 media::cast::kVideoFrameDecoded, |
| 45 media::cast::kVideoRenderDelay}; |
| 46 |
| 47 // Average number of packets per video frame. |
| 48 const int kNumPacketPerVideoFrame = 10; |
| 49 |
| 50 const CastLoggingEvent kVideoPacketEvents[] = { |
| 51 media::cast::kPacketSentToPacer, |
| 52 media::cast::kPacketSentToNetwork, |
| 53 media::cast::kVideoPacketReceived}; |
| 54 |
| 55 const CastLoggingEvent kOtherPacketEvents[] = { |
| 56 media::cast::kPacketRetransmitted, |
| 57 media::cast::kDuplicatePacketReceived}; |
| 58 |
| 59 // 15 MB. |
| 60 const int kCompressedMaxSize = 10 * 1000 * 1000; |
| 61 // 100 MB. |
| 62 const int kDecompressedMaxSize = 100 * 1000 * 1000; |
| 63 |
| 64 // TODO(imcheng): All these should return bool indicating success. |
| 65 void WriteTo(const FrameEventMap& frame_events, |
| 66 const PacketEventMap& packet_events, |
| 67 uint8* out, int out_buf_size, int* out_size); |
| 68 void Compress(uint8* in, int in_buf_size, |
| 69 uint8* out, int out_buf_size, int* out_size); |
| 70 void Decompress(uint8* in, int in_buf_size, |
| 71 uint8* out, int out_buf_size, int* out_size); |
| 72 void ReadFrom(const uint8* in, const int in_size); |
| 73 |
| 74 int main(int argc, char** argv) { |
| 75 EncodingEventSubscriber subscriber; |
| 76 LoggingRaw logging_raw; |
| 77 |
| 78 logging_raw.AddSubscriber(&subscriber); |
| 79 |
| 80 base::DefaultTickClock clock; |
| 81 base::TimeTicks base_now(clock.NowTicks()); |
| 82 base_now -= base::TimeDelta::FromSeconds(5400); |
| 83 printf("Time now: %ld\n", base_now.ToInternalValue()); |
| 84 |
| 85 printf("\n===========\n"); |
| 86 printf("Inserting frame events\n"); |
| 87 base::TimeTicks now(base_now); |
| 88 for (int i = 0; i < kNumVideoFrames; ++i) { |
| 89 now += base::TimeDelta::FromMilliseconds(33); |
| 90 base::TimeTicks base_now2(now); |
| 91 uint32 rtp_timestamp = media::cast::GetVideoRtpTimestamp(now); |
| 92 if (i < 5) { |
| 93 printf("Inserting first 5 event with RTP timestamp %u\n", rtp_timestamp); |
| 94 } |
| 95 if (kNumVideoFrames - i < 5) { |
| 96 printf("Inserting last 5 event with RTP timestamp %u\n", rtp_timestamp); |
| 97 } |
| 98 // Insert frame events for that frame. |
| 99 for (uint32 event_index = 0; event_index < arraysize(kVideoFrameEvents); |
| 100 ++event_index) { |
| 101 now += base::TimeDelta::FromMilliseconds(5); |
| 102 CastLoggingEvent type = kVideoFrameEvents[event_index]; |
| 103 if (type == media::cast::kVideoFrameEncoded) { |
| 104 int size = base::RandInt(32768, 65536); |
| 105 logging_raw.InsertFrameEventWithSize(now, type, rtp_timestamp, i, size); |
| 106 } else if (type == media::cast::kVideoRenderDelay) { |
| 107 base::TimeDelta delay( |
| 108 base::TimeDelta::FromMilliseconds(base::RandInt(0, 100))); |
| 109 logging_raw.InsertFrameEventWithDelay(now, type, rtp_timestamp, i, |
| 110 delay); |
| 111 } else { |
| 112 logging_raw.InsertFrameEvent(now, type, rtp_timestamp, i); |
| 113 } |
| 114 } |
| 115 now = base_now2; |
| 116 } |
| 117 |
| 118 printf("Inserting packet events\n"); |
| 119 now = base_now; |
| 120 for (int i = 0; i < kNumVideoFrames; ++i) { |
| 121 now += base::TimeDelta::FromMilliseconds(33); |
| 122 base::TimeTicks base_now2(now); |
| 123 uint32 rtp_timestamp = media::cast::GetVideoRtpTimestamp(now); |
| 124 |
| 125 // Insert packet events for that frame. |
| 126 for (int packet_id = 0; packet_id < kNumPacketPerVideoFrame; ++packet_id) { |
| 127 int size = base::RandInt(2048, 4096); |
| 128 for (uint32 event_index = 0; event_index < arraysize(kVideoPacketEvents); |
| 129 ++event_index) { |
| 130 now += base::TimeDelta::FromMilliseconds(1); |
| 131 CastLoggingEvent type = kVideoPacketEvents[event_index]; |
| 132 logging_raw.InsertPacketEvent(now, type, rtp_timestamp, i, packet_id, |
| 133 kNumPacketPerVideoFrame - 1, size); |
| 134 } |
| 135 |
| 136 // Randomly insert additional packet events. |
| 137 int rand = base::RandInt(0, 99); |
| 138 if (rand < 2) { |
| 139 now += base::TimeDelta::FromMilliseconds(1); |
| 140 logging_raw.InsertPacketEvent(now, media::cast::kPacketRetransmitted, |
| 141 rtp_timestamp, i, packet_id, |
| 142 kNumPacketPerVideoFrame - 1, size); |
| 143 } |
| 144 rand = base::RandInt(0, 99); |
| 145 if (rand < 2) { |
| 146 now += base::TimeDelta::FromMilliseconds(1); |
| 147 logging_raw.InsertPacketEvent( |
| 148 now, media::cast::kDuplicatePacketReceived, rtp_timestamp, i, |
| 149 packet_id, kNumPacketPerVideoFrame - 1, size); |
| 150 } |
| 151 } |
| 152 |
| 153 now = base_now2; |
| 154 } |
| 155 |
| 156 FrameEventMap frame_events; |
| 157 subscriber.GetFrameEventsAndReset(&frame_events); |
| 158 |
| 159 PacketEventMap packet_events; |
| 160 subscriber.GetPacketEventsAndReset(&packet_events); |
| 161 |
| 162 printf("Frame events map size: %lu\n", frame_events.size()); |
| 163 printf("Packet events map size: %lu\n", packet_events.size()); |
| 164 |
| 165 logging_raw.RemoveSubscriber(&subscriber); |
| 166 |
| 167 printf("\n===========\n"); |
| 168 printf("Performing serialization\n"); |
| 169 |
| 170 scoped_ptr<uint8[]> serialized_buf(new uint8[kDecompressedMaxSize]); |
| 171 int serialized_size; |
| 172 WriteTo(frame_events, packet_events, serialized_buf.get(), |
| 173 kDecompressedMaxSize, &serialized_size); |
| 174 printf("Serialized size: %d\n", serialized_size); |
| 175 |
| 176 printf("\n===========\n"); |
| 177 printf("Performing compression\n"); |
| 178 scoped_ptr<uint8[]> compressed_buf(new uint8[kCompressedMaxSize]); |
| 179 int compressed_size; |
| 180 Compress(serialized_buf.get(), serialized_size, compressed_buf.get(), |
| 181 kCompressedMaxSize, &compressed_size); |
| 182 printf("Compressed size: %d\n", compressed_size); |
| 183 serialized_buf.reset(); |
| 184 |
| 185 printf("\n===========\n"); |
| 186 printf("Performing decompression\n"); |
| 187 scoped_ptr<uint8[]> decompressed_buf(new uint8[kDecompressedMaxSize]); |
| 188 |
| 189 int decompressed_size; |
| 190 Decompress(compressed_buf.get(), compressed_size, |
| 191 decompressed_buf.get(), kDecompressedMaxSize, &decompressed_size); |
| 192 printf("Decompressed size: %d\n", decompressed_size); |
| 193 compressed_buf.reset(); |
| 194 |
| 195 printf("\n===========\n"); |
| 196 printf("Performing deserialization\n"); |
| 197 ReadFrom(decompressed_buf.get(), decompressed_size); |
| 198 |
| 199 printf("Done\n"); |
| 200 return 0; |
| 201 } |
| 202 |
| 203 void WriteTo(const FrameEventMap& frame_events, |
| 204 const PacketEventMap& packet_events, |
| 205 uint8* out, int out_buf_size, int* out_size) { |
| 206 |
| 207 // int index = 0; |
| 208 net::BigEndianWriter writer(out, out_buf_size); |
| 209 |
| 210 // Frame events - write size first, then write entries |
| 211 int frame_events_size = frame_events.size(); |
| 212 // memcpy(&out[index], &frame_events_size, sizeof(frame_events_size)); |
| 213 // index += sizeof(frame_events_size); |
| 214 bool success; |
| 215 success = writer.WriteU32(frame_events_size); |
| 216 // XXX: instead of DCHECKs, just return false. |
| 217 DCHECK(success); |
| 218 int i = 0; |
| 219 for (FrameEventMap::const_iterator it = frame_events.begin(); |
| 220 it != frame_events.end(); ++it) { |
| 221 int proto_size = it->second->ByteSize(); |
| 222 |
| 223 if (frame_events_size - i < 5) { |
| 224 printf("Serializing last 5 frame events, rtp ts: %u, %u\n", it->first, it-
>second->rtp_timestamp()); |
| 225 } |
| 226 i++; |
| 227 // Write size of the proto, then write the proto |
| 228 // memcpy(&out[index], &proto_size, sizeof(proto_size)); |
| 229 // index += sizeof(proto_size); |
| 230 success = writer.WriteU16(proto_size); |
| 231 DCHECK(success); |
| 232 |
| 233 // bool success = it->second->SerializeToArray(&out[index], out_size - index
); |
| 234 // DCHECK(success); |
| 235 // index += proto_size; |
| 236 success = it->second->SerializeToArray(writer.ptr(), writer.remaining()); |
| 237 DCHECK(success); |
| 238 success = writer.Skip(proto_size); |
| 239 DCHECK(success); |
| 240 } |
| 241 |
| 242 int frame_event_serialized_size = (char*)writer.ptr() - (char*)out; |
| 243 printf("Encoded frame events size: %d\n", frame_event_serialized_size); |
| 244 |
| 245 // Write packet events |
| 246 int packet_event_size = packet_events.size(); |
| 247 // memcpy(&out[index], &packet_event_size, sizeof(packet_event_size)); |
| 248 // index += sizeof(packet_event_size); |
| 249 success = writer.WriteU32(packet_event_size); |
| 250 DCHECK(success); |
| 251 i = 0; |
| 252 for (PacketEventMap::const_iterator it = packet_events.begin(); |
| 253 it != packet_events.end(); ++it) { |
| 254 int proto_size = it->second->ByteSize(); |
| 255 if (packet_event_size - i < 5) { |
| 256 printf("Last 5 encoded packet size: %d, rtp timestamp: %u, %u\n", proto_si
ze, it->first, it->second->rtp_timestamp()); |
| 257 } |
| 258 i++; |
| 259 // Write size of the proto, then write the proto |
| 260 // memcpy(&out[index], &proto_size, sizeof(proto_size)); |
| 261 // index += sizeof(proto_size); |
| 262 success = writer.WriteU16(proto_size); |
| 263 DCHECK(success); |
| 264 |
| 265 // bool success = it->second->SerializeToArray(&out[index], out_size - index
); |
| 266 // index += proto_size; |
| 267 // DCHECK(success); |
| 268 success = it->second->SerializeToArray(writer.ptr(), writer.remaining()); |
| 269 DCHECK(success); |
| 270 success = writer.Skip(proto_size); |
| 271 DCHECK(success); |
| 272 } |
| 273 |
| 274 int packet_event_serialized_size = |
| 275 out_buf_size - writer.remaining() - frame_event_serialized_size; |
| 276 printf("Encoded packet events buff count: %d\n", |
| 277 packet_event_serialized_size); |
| 278 |
| 279 *out_size = out_buf_size - writer.remaining(); |
| 280 } |
| 281 |
| 282 void Compress(uint8* in, int in_buf_size, |
| 283 uint8* out, int out_buf_size, int* out_size) { |
| 284 z_stream stream = {0}; |
| 285 int result = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, |
| 286 // 16 is added to produce a gzip header + trailer. |
| 287 MAX_WBITS + 16, 8, // memLevel = 8 is default. |
| 288 Z_DEFAULT_STRATEGY); |
| 289 DCHECK_EQ(Z_OK, result); |
| 290 stream.next_in = in; |
| 291 stream.avail_in = in_buf_size; |
| 292 stream.next_out = out; |
| 293 stream.avail_out = out_buf_size; |
| 294 result = deflate(&stream, Z_FINISH); |
| 295 DCHECK_EQ(Z_STREAM_END, result) |
| 296 << ", maybe the output buffer isn't large enough?"; |
| 297 result = deflateEnd(&stream); |
| 298 DCHECK_EQ(Z_OK, result); |
| 299 |
| 300 *out_size = out_buf_size - stream.avail_out; |
| 301 } |
| 302 |
| 303 void Decompress(uint8* in, int in_buf_size, |
| 304 uint8* out, int out_buf_size, int* out_size) { |
| 305 z_stream stream = {0}; |
| 306 // 16 is added to read in gzip format. |
| 307 int result = inflateInit2(&stream, MAX_WBITS + 16); |
| 308 DCHECK_EQ(Z_OK, result); |
| 309 stream.next_in = in; |
| 310 stream.avail_in = in_buf_size; |
| 311 stream.next_out = out; |
| 312 stream.avail_out = out_buf_size; |
| 313 result = inflate(&stream, Z_FINISH); |
| 314 DCHECK_EQ(Z_STREAM_END, result) |
| 315 << ", maybe the output buffer isn't large enough?"; |
| 316 result = inflateEnd(&stream); |
| 317 DCHECK_EQ(Z_OK, result); |
| 318 |
| 319 // Trim to size. |
| 320 *out_size = out_buf_size - stream.avail_out; |
| 321 } |
| 322 |
| 323 void ReadFrom(const uint8* in, const int in_size) { |
| 324 //ArrayInputStream array_input_stream(&decompressed_string[0], |
| 325 // decompressed_string.size()); |
| 326 //CodedInputStream in(&array_input_stream); |
| 327 |
| 328 // Reserve about 20MB. |
| 329 const int out_size = 20 * 1000 * 1000; |
| 330 scoped_ptr<uint8[]> out(new uint8[out_size]); |
| 331 bool success; |
| 332 |
| 333 //success = in.GetDirectBufferPointer( |
| 334 // reinterpret_cast<const void**>(&in_buffer), &buffer_size); |
| 335 //DCHECK(success); |
| 336 |
| 337 net::BigEndianReader reader(in, in_size); |
| 338 uint32 num_frame_events; |
| 339 //in_buffer = CodedInputStream::ReadLittleEndian32FromArray(in_buffer, |
| 340 // &num_frame_events)
; |
| 341 success = reader.ReadU32(&num_frame_events); |
| 342 DCHECK(success); |
| 343 |
| 344 printf("Read %u frame events\n", num_frame_events); |
| 345 |
| 346 for (uint32 i = 0; i < num_frame_events; i++) { |
| 347 uint16 proto_size = 0u; |
| 348 //in_buffer = |
| 349 // CodedInputStream::ReadLittleEndian32FromArray(in_buffer, &proto_size); |
| 350 success = reader.ReadU16(&proto_size); |
| 351 |
| 352 AggregatedFrameEvent frame_event; |
| 353 success = frame_event.ParseFromArray(reader.ptr(), proto_size); |
| 354 DCHECK(success) << ", " << i; |
| 355 reader.Skip(proto_size); |
| 356 //in_buffer += proto_size; |
| 357 if (i > num_frame_events - 5) { |
| 358 printf("Last 5 event:\n"); |
| 359 printf("RTP timestamp: %u\n", |
| 360 static_cast<uint32>(frame_event.rtp_timestamp())); |
| 361 printf("Event type size: %d\n", frame_event.event_type_size()); |
| 362 printf("Event timestamp micros size: %d\n", |
| 363 frame_event.event_timestamp_micros_size()); |
| 364 printf("Event encoded frame size: %d\n", |
| 365 frame_event.encoded_frame_size()); |
| 366 printf("Event delay millis: %d\n", frame_event.delay_millis()); |
| 367 } |
| 368 } |
| 369 |
| 370 uint32 num_packet_events = 0u; |
| 371 success = reader.ReadU32(&num_packet_events); |
| 372 DCHECK(success); |
| 373 //in_buffer = CodedInputStream::ReadLittleEndian32FromArray(in_buffer, |
| 374 // &num_packet_events
); |
| 375 printf("Read %u packet events\n", num_packet_events); |
| 376 |
| 377 for (uint32 i = 0; i < num_packet_events; i++) { |
| 378 uint16 proto_size; |
| 379 //in_buffer = |
| 380 // CodedInputStream::ReadLittleEndian32FromArray(in_buffer, &proto_size); |
| 381 success = reader.ReadU16(&proto_size); |
| 382 DCHECK(success); |
| 383 |
| 384 AggregatedPacketEvent packet_event; |
| 385 success = packet_event.ParseFromArray(reader.ptr(), proto_size); |
| 386 DCHECK(success) << ", " << i; |
| 387 reader.Skip(proto_size); |
| 388 |
| 389 // in_buffer += proto_size; |
| 390 if (i > num_packet_events - 5) { |
| 391 printf("Last 5 event:\n"); |
| 392 printf("RTP timestamp: %u\n", packet_event.rtp_timestamp()); |
| 393 int base_size = packet_event.base_packet_event_size(); |
| 394 printf("Base packet event size: %d\n", base_size); |
| 395 int base_packet_index = base::RandInt(0, base_size - 1); |
| 396 printf("Getting base packet event %d\n", base_packet_index); |
| 397 BasePacketEvent base_packet_event = |
| 398 packet_event.base_packet_event(base_packet_index); |
| 399 printf("Base Event %d timestamp packet id: %d\n", base_packet_index, |
| 400 base_packet_event.packet_id()); |
| 401 printf("Base Event %d event type size: %d\n", base_packet_index, |
| 402 base_packet_event.event_type_size()); |
| 403 } |
| 404 } |
| 405 } |
OLD | NEW |