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 #ifndef MEDIA_CAST_LOGGING_ENCODING_EVENT_SUBSCRIBER_H_
6 #define MEDIA_CAST_LOGGING_ENCODING_EVENT_SUBSCRIBER_H_
7 
8 #include <stddef.h>
9 
10 #include <map>
11 #include <memory>
12 #include <vector>
13 
14 #include "base/macros.h"
15 #include "base/threading/thread_checker.h"
16 #include "media/cast/logging/logging_defines.h"
17 #include "media/cast/logging/proto/raw_events.pb.h"
18 #include "media/cast/logging/raw_event_subscriber.h"
19 
20 namespace media {
21 namespace cast {
22 
23 // Number of packets per frame recorded by the subscriber.
24 // Once the max number of packets has been reached, a new aggregated proto
25 // will be created.
26 static const int kMaxPacketsPerFrame = 256;
27 // Number of events per frame/packet proto recorded by the subscriber.
28 // Once the max number of events has been reached, a new aggregated proto
29 // will be created.
30 static const int kMaxEventsPerProto = 16;
31 // Max number of AggregatedFrameEvent / AggregatedPacketEvent protos stored for
32 // a frame. Once the max number of protos has been reached for that frame,
33 // further events for that frame will be dropped.
34 static const int kMaxProtosPerFrame = 10;
35 
36 using FrameEventList =
37     std::vector<std::unique_ptr<proto::AggregatedFrameEvent>>;
38 using PacketEventList =
39     std::vector<std::unique_ptr<proto::AggregatedPacketEvent>>;
40 
41 // A RawEventSubscriber implementation that subscribes to events,
42 // encodes them in protocol buffer format, and aggregates them into a more
43 // compact structure. Aggregation is per-frame, and uses a map with RTP
44 // timestamp as key. Periodically, old entries in the map will be transferred
45 // to a storage vector. This helps keep the size of the map small and
46 // lookup times fast. The storage itself is a circular buffer that will
47 // overwrite old entries once it has reached the size configured by user.
48 class EncodingEventSubscriber : public RawEventSubscriber {
49  public:
50   // |event_media_type|: The subscriber will only process events that
51   // corresponds to this type.
52   // |max_frames|: How many events to keep in the frame / packet storage.
53   // This helps keep memory usage bounded.
54   // Every time one of |OnReceive[Frame,Packet]Event()| is
55   // called, it will check if the respective map size has exceeded |max_frames|.
56   // If so, it will remove the oldest aggregated entry (ordered by RTP
57   // timestamp).
58   EncodingEventSubscriber(EventMediaType event_media_type, size_t max_frames);
59 
60   ~EncodingEventSubscriber() final;
61 
62   // RawReventSubscriber implementations.
63   void OnReceiveFrameEvent(const FrameEvent& frame_event) final;
64   void OnReceivePacketEvent(const PacketEvent& packet_event) final;
65 
66   // Assigns frame events and packet events received so far to |frame_events|
67   // and |packet_events| and resets the internal state.
68   // In addition, assign metadata associated with these events to |metadata|.
69   // The protos in |frame_events| and |packets_events| are sorted in
70   // ascending RTP timestamp order.
71   void GetEventsAndReset(proto::LogMetadata* metadata,
72                          FrameEventList* frame_events,
73                          PacketEventList* packet_events);
74 
75  private:
76   using FrameEventMap =
77       std::map<RtpTimeDelta, std::unique_ptr<proto::AggregatedFrameEvent>>;
78   using PacketEventMap =
79       std::map<RtpTimeDelta, std::unique_ptr<proto::AggregatedPacketEvent>>;
80 
81   // Transfer up to |max_num_entries| smallest entries from |frame_event_map_|
82   // to |frame_event_storage_|. This helps keep size of |frame_event_map_| small
83   // and lookup speed fast.
84   void TransferFrameEvents(size_t max_num_entries);
85   // See above.
86   void TransferPacketEvents(size_t max_num_entries);
87 
88   void AddFrameEventToStorage(
89       std::unique_ptr<proto::AggregatedFrameEvent> frame_event_proto);
90   void AddPacketEventToStorage(
91       std::unique_ptr<proto::AggregatedPacketEvent> packet_event_proto);
92 
93   bool ShouldCreateNewProto(
94       uint32_t relative_rtp_timestamp_lower_32_bits) const;
95   void IncrementStoredProtoCount(uint32_t relative_rtp_timestamp_lower_32_bits);
96   void DecrementStoredProtoCount(uint32_t relative_rtp_timestamp_lower_32_bits);
97 
98   // Returns the difference between |rtp_timestamp| and |first_rtp_timestamp_|.
99   // Sets |first_rtp_timestamp_| if it is not already set.
100   RtpTimeDelta GetRelativeRtpTimestamp(RtpTimeTicks rtp_timestamp);
101 
102   // Clears the maps and first RTP timestamp seen.
103   void Reset();
104 
105   const EventMediaType event_media_type_;
106   const size_t max_frames_;
107 
108   FrameEventMap frame_event_map_;
109   FrameEventList frame_event_storage_;
110   int frame_event_storage_index_;
111 
112   PacketEventMap packet_event_map_;
113   PacketEventList packet_event_storage_;
114   int packet_event_storage_index_;
115 
116   // Maps from the lower 32 bits of a RTP timestamp to the number of
117   // AggregatedFrameEvent / AggregatedPacketEvent protos that have been stored
118   // for that frame.
119   std::map<uint32_t, int> stored_proto_counts_;
120 
121   // All functions must be called on the main thread.
122   base::ThreadChecker thread_checker_;
123 
124   // Set to true on first event encountered after a |Reset()|.
125   bool seen_first_rtp_timestamp_;
126 
127   // Set to RTP timestamp of first event encountered after a |Reset()|.
128   RtpTimeTicks first_rtp_timestamp_;
129 
130   DISALLOW_COPY_AND_ASSIGN(EncodingEventSubscriber);
131 };
132 
133 }  // namespace cast
134 }  // namespace media
135 
136 #endif  // MEDIA_CAST_LOGGING_ENCODING_EVENT_SUBSCRIBER_H_
137