summaryrefslogtreecommitdiff
path: root/chromium/media/cast/logging/encoding_event_subscriber.h
blob: 614303f2012e942194e454ba7b4d7723bdd87869 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2014 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_ENCODING_EVENT_SUBSCRIBER_H_
#define MEDIA_CAST_LOGGING_ENCODING_EVENT_SUBSCRIBER_H_

#include <stddef.h>

#include <map>
#include <memory>
#include <vector>

#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "media/cast/logging/logging_defines.h"
#include "media/cast/logging/proto/raw_events.pb.h"
#include "media/cast/logging/raw_event_subscriber.h"

namespace media {
namespace cast {

// Number of packets per frame recorded by the subscriber.
// Once the max number of packets has been reached, a new aggregated proto
// will be created.
static const int kMaxPacketsPerFrame = 256;
// Number of events per frame/packet proto recorded by the subscriber.
// Once the max number of events has been reached, a new aggregated proto
// will be created.
static const int kMaxEventsPerProto = 16;
// Max number of AggregatedFrameEvent / AggregatedPacketEvent protos stored for
// a frame. Once the max number of protos has been reached for that frame,
// further events for that frame will be dropped.
static const int kMaxProtosPerFrame = 10;

using FrameEventList =
    std::vector<std::unique_ptr<proto::AggregatedFrameEvent>>;
using PacketEventList =
    std::vector<std::unique_ptr<proto::AggregatedPacketEvent>>;

// A RawEventSubscriber implementation that subscribes to events,
// encodes them in protocol buffer format, and aggregates them into a more
// compact structure. Aggregation is per-frame, and uses a map with RTP
// timestamp as key. Periodically, old entries in the map will be transferred
// to a storage vector. This helps keep the size of the map small and
// lookup times fast. The storage itself is a circular buffer that will
// overwrite old entries once it has reached the size configured by user.
class EncodingEventSubscriber final : public RawEventSubscriber {
 public:
  // |event_media_type|: The subscriber will only process events that
  // corresponds to this type.
  // |max_frames|: How many events to keep in the frame / packet storage.
  // This helps keep memory usage bounded.
  // Every time one of |OnReceive[Frame,Packet]Event()| is
  // called, it will check if the respective map size has exceeded |max_frames|.
  // If so, it will remove the oldest aggregated entry (ordered by RTP
  // timestamp).
  EncodingEventSubscriber(EventMediaType event_media_type, size_t max_frames);

  EncodingEventSubscriber(const EncodingEventSubscriber&) = delete;
  EncodingEventSubscriber& operator=(const EncodingEventSubscriber&) = delete;

  ~EncodingEventSubscriber() final;

  // RawReventSubscriber implementations.
  void OnReceiveFrameEvent(const FrameEvent& frame_event) final;
  void OnReceivePacketEvent(const PacketEvent& packet_event) final;

  // Assigns frame events and packet events received so far to |frame_events|
  // and |packet_events| and resets the internal state.
  // In addition, assign metadata associated with these events to |metadata|.
  // The protos in |frame_events| and |packets_events| are sorted in
  // ascending RTP timestamp order.
  void GetEventsAndReset(proto::LogMetadata* metadata,
                         FrameEventList* frame_events,
                         PacketEventList* packet_events);

 private:
  using FrameEventMap =
      std::map<RtpTimeDelta, std::unique_ptr<proto::AggregatedFrameEvent>>;
  using PacketEventMap =
      std::map<RtpTimeDelta, std::unique_ptr<proto::AggregatedPacketEvent>>;

  // Transfer up to |max_num_entries| smallest entries from |frame_event_map_|
  // to |frame_event_storage_|. This helps keep size of |frame_event_map_| small
  // and lookup speed fast.
  void TransferFrameEvents(size_t max_num_entries);
  // See above.
  void TransferPacketEvents(size_t max_num_entries);

  void AddFrameEventToStorage(
      std::unique_ptr<proto::AggregatedFrameEvent> frame_event_proto);
  void AddPacketEventToStorage(
      std::unique_ptr<proto::AggregatedPacketEvent> packet_event_proto);

  bool ShouldCreateNewProto(
      uint32_t relative_rtp_timestamp_lower_32_bits) const;
  void IncrementStoredProtoCount(uint32_t relative_rtp_timestamp_lower_32_bits);
  void DecrementStoredProtoCount(uint32_t relative_rtp_timestamp_lower_32_bits);

  // Returns the difference between |rtp_timestamp| and |first_rtp_timestamp_|.
  // Sets |first_rtp_timestamp_| if it is not already set.
  RtpTimeDelta GetRelativeRtpTimestamp(RtpTimeTicks rtp_timestamp);

  // Clears the maps and first RTP timestamp seen.
  void Reset();

  const EventMediaType event_media_type_;
  const size_t max_frames_;

  FrameEventMap frame_event_map_;
  FrameEventList frame_event_storage_;
  int frame_event_storage_index_;

  PacketEventMap packet_event_map_;
  PacketEventList packet_event_storage_;
  int packet_event_storage_index_;

  // Maps from the lower 32 bits of a RTP timestamp to the number of
  // AggregatedFrameEvent / AggregatedPacketEvent protos that have been stored
  // for that frame.
  std::map<uint32_t, int> stored_proto_counts_;

  // All functions must be called on the main thread.
  base::ThreadChecker thread_checker_;

  // Set to true on first event encountered after a |Reset()|.
  bool seen_first_rtp_timestamp_;

  // Set to RTP timestamp of first event encountered after a |Reset()|.
  RtpTimeTicks first_rtp_timestamp_;
};

}  // namespace cast
}  // namespace media

#endif  // MEDIA_CAST_LOGGING_ENCODING_EVENT_SUBSCRIBER_H_