diff options
author | mikhal@google.com <mikhal@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-22 00:55:02 +0000 |
---|---|---|
committer | mikhal@google.com <mikhal@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-22 00:55:02 +0000 |
commit | e885f989bb7988e0b65d47c9d9797347fca0d822 (patch) | |
tree | 4a61f8925320400da42a3d7b90b864c2767b52e2 /media | |
parent | afaa03ce00f0fa13ae78569c97ecc82bab66d157 (diff) | |
download | chromium_src-e885f989bb7988e0b65d47c9d9797347fca0d822.zip chromium_src-e885f989bb7988e0b65d47c9d9797347fca0d822.tar.gz chromium_src-e885f989bb7988e0b65d47c9d9797347fca0d822.tar.bz2 |
Adding a logging class to cast.
This cl is first in a series - follow-up cl's will include using this class in Cast and performing data analysis.
Review URL: https://codereview.chromium.org/26909002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229984 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/cast/cast.gyp | 1 | ||||
-rw-r--r-- | media/cast/logging/logging.cc | 113 | ||||
-rw-r--r-- | media/cast/logging/logging.gyp | 27 | ||||
-rw-r--r-- | media/cast/logging/logging.h | 92 | ||||
-rw-r--r-- | media/cast/logging/logging_defines.h | 88 | ||||
-rw-r--r-- | media/cast/logging/logging_internal.cc | 79 | ||||
-rw-r--r-- | media/cast/logging/logging_internal.h | 95 |
7 files changed, 495 insertions, 0 deletions
diff --git a/media/cast/cast.gyp b/media/cast/cast.gyp index afa2f86..dccfcec 100644 --- a/media/cast/cast.gyp +++ b/media/cast/cast.gyp @@ -31,6 +31,7 @@ 'cast_config', 'cast_receiver.gyp:cast_receiver', 'cast_sender.gyp:cast_sender', + 'logging/logging.gyp:cast_logging', '<(DEPTH)/base/base.gyp:run_all_unittests', '<(DEPTH)/net/net.gyp:net', '<(DEPTH)/testing/gmock.gyp:gmock', diff --git a/media/cast/logging/logging.cc b/media/cast/logging/logging.cc new file mode 100644 index 0000000..ce68aa4 --- /dev/null +++ b/media/cast/logging/logging.cc @@ -0,0 +1,113 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/cast/logging/logging.h" + +#include "base/debug/trace_event.h" +#include "base/logging.h" +#include "base/metrics/histogram.h" + +namespace media { +namespace cast { + +Logging::Logging(base::TickClock* clock) + : clock_(clock), + frame_map_(), + packet_map_(), + generic_map_(), + weak_factory_(this) {} + +Logging::~Logging() {} + +void Logging::InsertFrameEvent(CastLoggingEvent event, + uint32 rtp_timestamp, + uint8 frame_id) { + // Is this a new event? + FrameLogMap::iterator it = frame_map_.find(event); + if (it == frame_map_.end()) { + // Create new entry. + FrameLogData data(clock_); + data.Insert(rtp_timestamp, frame_id); + frame_map_.insert(std::make_pair(event, &data)); + } else { + // Insert to existing entry. + it->second->Insert(rtp_timestamp, frame_id); + } +} + +void Logging::InsertFrameEventWithSize(CastLoggingEvent event, + uint32 rtp_timestamp, + uint8 frame_id, + int size) { + // Is this a new event? + FrameLogMap::iterator it = frame_map_.find(event); + if (it == frame_map_.end()) { + // Create new entry. + FrameLogData data(clock_); + data.InsertWithSize(rtp_timestamp, frame_id, size); + frame_map_.insert(std::make_pair(event, &data)); + } else { + // Insert to existing entry. + it->second->InsertWithSize(rtp_timestamp, frame_id, size); + } +} + +void Logging::InsertFrameEventWithDelay(CastLoggingEvent event, + uint32 rtp_timestamp, + uint8 frame_id, + base::TimeDelta delay) { + // Is this a new event? + FrameLogMap::iterator it = frame_map_.find(event); + if (it == frame_map_.end()) { + // Create new entry. + FrameLogData data(clock_); + data.InsertWithDelay(rtp_timestamp, frame_id, delay); + frame_map_.insert(std::make_pair(event, &data)); + } else { + // Insert to existing entry. + it->second->InsertWithDelay(rtp_timestamp, frame_id, delay); + } +} + +void Logging::InsertPacketEvent(CastLoggingEvent event, + uint32 rtp_timestamp, + uint8 frame_id, + uint16 packet_id, + uint16 max_packet_id, + int size) { + // Is this a new event? + PacketLogMap::iterator it = packet_map_.find(event); + if (it == packet_map_.end()) { + // Create new entry. + PacketLogData data(clock_); + data.Insert(rtp_timestamp, frame_id, packet_id, max_packet_id, size); + packet_map_.insert(std::make_pair(event, &data)); + } else { + // Insert to existing entry. + it->second->Insert(rtp_timestamp, frame_id, packet_id, max_packet_id, size); + } +} + +void Logging::InsertGenericEvent(CastLoggingEvent event, int value) { + // Is this a new event? + GenericLogMap::iterator it = generic_map_.find(event); + if (it == generic_map_.end()) { + // Create new entry. + GenericLogData data(clock_); + data.Insert(value); + generic_map_.insert(std::make_pair(event, &data)); + } else { + // Insert to existing entry. + it->second->Insert(value); + } +} + +void Logging::Reset() { + frame_map_.clear(); + packet_map_.clear(); + generic_map_.clear(); +} +} // namespace cast +} // namespace media + diff --git a/media/cast/logging/logging.gyp b/media/cast/logging/logging.gyp new file mode 100644 index 0000000..d04ef6b --- /dev/null +++ b/media/cast/logging/logging.gyp @@ -0,0 +1,27 @@ +# Copyright 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + + +{ + 'targets': [ + { + 'target_name': 'cast_logging', + 'type': 'static_library', + 'include_dirs': [ + '<(DEPTH)/', + ], + 'sources': [ + 'logging.cc', + 'logging.h', + 'logging_defines.h', + 'logging_internal.cc', + 'logging_internal.h', + ], + 'dependencies': [ + '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/base/base.gyp:test_support_base', + ], + }, + ], # targets +}
\ No newline at end of file diff --git a/media/cast/logging/logging.h b/media/cast/logging/logging.h new file mode 100644 index 0000000..426fe3a --- /dev/null +++ b/media/cast/logging/logging.h @@ -0,0 +1,92 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_CAST_LOGGING_LOGGING_H_ +#define MEDIA_CAST_LOGGING_LOGGING_H_ + +// Generic class that handles event logging for the cast library. +// Logging has three possible forms: +// 1. [default] Raw data accessible by the application. +// 2. [optional] UMA stats. +// 3. [optional] Tracing. + +#include <map> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/linked_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/non_thread_safe.h" +#include "base/time/tick_clock.h" +#include "base/time/time.h" +#include "media/cast/logging/logging_defines.h" +#include "media/cast/logging/logging_internal.h" + +namespace media { +namespace cast { + +// Store all log types in a map based on the event. +typedef std::map<CastLoggingEvent, linked_ptr<FrameLogData> > FrameLogMap; +typedef std::map<CastLoggingEvent, linked_ptr<PacketLogData> > PacketLogMap; +typedef std::map<CastLoggingEvent, linked_ptr<GenericLogData> > GenericLogMap; + + +// This class is not thread safe, and should only be called from the main +// thread. +class Logging : public base::NonThreadSafe, + public base::SupportsWeakPtr<Logging> { + public: + // When tracing is enabled - all events will be added to the trace. + Logging(base::TickClock* clock); + ~Logging(); + // Inform of new event: three types of events: frame, packets and generic. + // Frame events can be inserted with different parameters. + void InsertFrameEvent(CastLoggingEvent event, + uint32 rtp_timestamp, + uint8 frame_id); + // Size - Inserting the size implies that this is an encoded frame. + void InsertFrameEventWithSize(CastLoggingEvent event, + uint32 rtp_timestamp, + uint8 frame_id, + int frame_size); + // Render/playout delay + void InsertFrameEventWithDelay(CastLoggingEvent event, + uint32 rtp_timestamp, + uint8 frame_id, + base::TimeDelta delay); + + // Insert a packet event. + void InsertPacketEvent(CastLoggingEvent event, + uint32 rtp_timestamp, + uint8 frame_id, + uint16 packet_id, + uint16 max_packet_id, + int size); + + void InsertGenericEvent(CastLoggingEvent event, int value); + + // Get log data. + void GetRawFrameData(FrameLogMap frame_data); + void GetRawPacketData(PacketLogMap packet_data); + void GetRawGenericData(GenericLogMap generic_data); + + // Reset all log data (not flags). + void Reset(); + + private: + base::WeakPtrFactory<Logging> weak_factory_; + base::TickClock* const clock_; // Not owned by this class. + FrameLogMap frame_map_; + PacketLogMap packet_map_; + GenericLogMap generic_map_; + + DISALLOW_COPY_AND_ASSIGN(Logging); +}; + +} // namespace cast +} // namespace media + +#endif // MEDIA_CAST_LOGGING_LOGGING_H_ + diff --git a/media/cast/logging/logging_defines.h b/media/cast/logging/logging_defines.h new file mode 100644 index 0000000..10c49dd --- /dev/null +++ b/media/cast/logging/logging_defines.h @@ -0,0 +1,88 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_CAST_LOGGING_LOGGING_DEFINES_H_ +#define MEDIA_CAST_LOGGING_LOGGING_DEFINES_H_ + +#include "base/logging.h" + +namespace media { +namespace cast { + +enum CastLoggingEvent { + // Generic events. + kRtt, + kPacketLoss, + kJitter, + kAckReceived, + kAckSent, + kLastEvent, + // Audio sender. + kAudioFrameCaptured, + kAudioFrameEncoded, + // Audio receiver. + kAudioPlayoutDelay, + kAudioFrameDecoded, + // Video sender. + kVideoFrameCaptured, + kVideoFrameSentToEncoder, + kVideoFrameEncoded, + // Video receiver. + kVideoFrameDecoded, + kVideoRenderDelay, + // Send-side packet events. + kPacketSentToPacer, + kPacketSentToNetwork, + kPacketRetransmited, + // Receive-side packet events. + kPacketReceived, +}; + +std::string CastEnumToString(CastLoggingEvent event) { + switch (event) { + case(kRtt): + return "Rtt"; + case(kPacketLoss): + return "PacketLoss"; + case(kJitter): + return "Jitter"; + case(kAckReceived): + return "AckReceived"; + case(kAckSent): + return "AckSent"; + case(kLastEvent): + return "LastEvent"; + case(kAudioFrameCaptured): + return "AudioFrameCaptured"; + case(kAudioFrameEncoded): + return "AudioFrameEncoded"; + case(kAudioPlayoutDelay): + return "AudioPlayoutDelay"; + case(kAudioFrameDecoded): + return "AudioFrameDecoded"; + case(kVideoFrameCaptured): + return "VideoFrameCaptured"; + case(kVideoFrameSentToEncoder): + return "VideoFrameSentToEncoder"; + case(kVideoFrameEncoded): + return "VideoFrameEncoded"; + case(kVideoFrameDecoded): + return "VideoFrameDecoded"; + case(kVideoRenderDelay): + return "VideoRenderDelay"; + case(kPacketSentToPacer): + return "PacketSentToPacer"; + case(kPacketSentToNetwork): + return "PacketSentToNetwork"; + case(kPacketRetransmited): + return "PacketRetransmited"; + case(kPacketReceived): + return "PacketReceived"; + } +} + +} // namespace cast +} // namespace media + +#endif // MEDIA_CAST_LOGGING_LOGGING_DEFINES_H_ diff --git a/media/cast/logging/logging_internal.cc b/media/cast/logging/logging_internal.cc new file mode 100644 index 0000000..aec0c96 --- /dev/null +++ b/media/cast/logging/logging_internal.cc @@ -0,0 +1,79 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/cast/logging/logging_internal.h" + +namespace media { +namespace cast { + +FrameLogData::FrameLogData(base::TickClock* clock) + : clock_(clock), + frame_map_() {} + +FrameLogData::~FrameLogData() {} + +void FrameLogData::Insert(uint32 rtp_timestamp, uint8 frame_id) { + FrameEvent info; + InsertBase(rtp_timestamp, frame_id, info); +} + +void FrameLogData::InsertWithSize( + uint32 rtp_timestamp, uint8 frame_id, int size) { + FrameEvent info; + info.size = size; + InsertBase(rtp_timestamp, frame_id, info); +} + +void FrameLogData::InsertWithDelay( + uint32 rtp_timestamp, uint8 frame_id, base::TimeDelta delay) { + FrameEvent info; + info.delay_delta = delay; + InsertBase(rtp_timestamp, frame_id, info); +} + +void FrameLogData::InsertBase( + uint32 rtp_timestamp, uint8 frame_id, FrameEvent info) { + info.timestamp = clock_->NowTicks(); + info.frame_id = frame_id; + frame_map_.insert(std::make_pair(rtp_timestamp, info)); +} + +PacketLogData::PacketLogData(base::TickClock* clock) + : clock_(clock), + packet_map_() {} + +PacketLogData::~PacketLogData() {} + +void PacketLogData::Insert(uint32 rtp_timestamp, + uint8 frame_id, uint16 packet_id, uint16 max_packet_id, int size) { + PacketEvent info; + info.size = size; + info.max_packet_id = max_packet_id; + info.frame_id = frame_id; + info.timestamp = clock_->NowTicks(); + // Is this a new frame? + PacketMap::iterator it = packet_map_.find(rtp_timestamp); + if (it == packet_map_.end()) { + // New rtp_timestamp id - create base packet map. + BasePacketMap base_map; + base_map.insert(std::make_pair(packet_id, info)); + packet_map_.insert(std::make_pair(rtp_timestamp, base_map)); + } else { + // Existing rtp_timestamp. + it->second.insert(std::make_pair(packet_id, info)); + } +} + +GenericLogData::GenericLogData(base::TickClock* clock) + : clock_(clock) {} + +GenericLogData::~GenericLogData() {} + +void GenericLogData::Insert(int data) { + data_.push_back(data); + timestamp_.push_back(clock_->NowTicks()); +} + +} // namespace cast +} // namespace media diff --git a/media/cast/logging/logging_internal.h b/media/cast/logging/logging_internal.h new file mode 100644 index 0000000..0f787600 --- /dev/null +++ b/media/cast/logging/logging_internal.h @@ -0,0 +1,95 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_CAST_LOGGING_LOGGING_INTERNAL_H_ +#define MEDIA_CAST_LOGGING_LOGGING_INTERNAL_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/time/tick_clock.h" +#include "base/time/time.h" + +namespace media { +namespace cast { + +// TODO(mikhal): Consider storing only the delta time and not absolute time. +struct FrameEvent { + uint8 frame_id; + int size; + base::TimeTicks timestamp; + base::TimeDelta delay_delta; // render/playout delay. +}; + +struct PacketEvent { + uint8 frame_id; + int max_packet_id; + int size; + base::TimeTicks timestamp; +}; + +// Frame and packet maps are sorted based on the rtp_timestamp. +typedef std::map<uint32, FrameEvent> FrameMap; +typedef std::map<uint16, PacketEvent> BasePacketMap; +typedef std::map<uint32, BasePacketMap> PacketMap; + +class FrameLogData { + public: + explicit FrameLogData(base::TickClock* clock); + ~FrameLogData(); + void Insert(uint32 rtp_timestamp, uint8 frame_id); + // Include size for encoded images (compute bitrate), + void InsertWithSize(uint32 rtp_timestamp, uint8 frame_id, int size); + // Include playout/render delay info. + void InsertWithDelay( + uint32 rtp_timestamp, uint8 frame_id, base::TimeDelta delay); + void Reset(); + + private: + void InsertBase(uint32 rtp_timestamp, uint8 frame_id, FrameEvent info); + + base::TickClock* const clock_; // Not owned by this class. + FrameMap frame_map_; + + DISALLOW_COPY_AND_ASSIGN(FrameLogData); +}; + +// TODO(mikhal): Should be able to handle packet bursts. +class PacketLogData { + public: + explicit PacketLogData(base::TickClock* clock); + ~PacketLogData(); + void Insert(uint32 rtp_timestamp, uint8 frame_id, uint16 packet_id, + uint16 max_packet_id, int size); + void Reset(); + + private: + base::TickClock* const clock_; // Not owned by this class. + PacketMap packet_map_; + + DISALLOW_COPY_AND_ASSIGN(PacketLogData); +}; + +class GenericLogData { + public: + explicit GenericLogData(base::TickClock* clock); + ~GenericLogData(); + void Insert(int value); + void Reset(); + + private: + base::TickClock* const clock_; // Not owned by this class. + std::vector<int> data_; + std::vector<base::TimeTicks> timestamp_; + + DISALLOW_COPY_AND_ASSIGN(GenericLogData); +}; + + +} // namespace cast +} // namespace media + +#endif // MEDIA_CAST_LOGGING_LOGGING_INTERNAL_H_ |