Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: media/cast/logging/encoding_event_subscriber.cc

Issue 241833002: Cast: Limit number of events/packets in EncodingEventSubscriber protos. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/encoding_event_subscriber.h" 5 #include "media/cast/logging/encoding_event_subscriber.h"
6 6
7 #include <cstring> 7 #include <cstring>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "media/cast/logging/proto/proto_utils.h" 11 #include "media/cast/logging/proto/proto_utils.h"
12 12
13 using google::protobuf::RepeatedPtrField; 13 using google::protobuf::RepeatedPtrField;
14 using media::cast::proto::AggregatedFrameEvent; 14 using media::cast::proto::AggregatedFrameEvent;
15 using media::cast::proto::AggregatedPacketEvent; 15 using media::cast::proto::AggregatedPacketEvent;
16 using media::cast::proto::BasePacketEvent; 16 using media::cast::proto::BasePacketEvent;
17 using media::cast::proto::LogMetadata; 17 using media::cast::proto::LogMetadata;
18 18
19 namespace {
20
21 // A size limit on maps to keep lookups fast.
22 const size_t kMaxMapSize = 200;
23
24 // The smallest (oredered by RTP timestamp) |kNumMapEntriesToTransfer| entries
25 // will be moved when the map size reaches |kMaxMapSize|.
26 // Must be smaller than |kMaxMapSize|.
27 const size_t kNumMapEntriesToTransfer = 100;
28
29 template <typename ProtoPtr>
30 bool IsRtpTimestampLessThan(const ProtoPtr& lhs, const ProtoPtr& rhs) {
31 return lhs->relative_rtp_timestamp() < rhs->relative_rtp_timestamp();
32 }
33
34 }
35
19 namespace media { 36 namespace media {
20 namespace cast { 37 namespace cast {
21 38
22 EncodingEventSubscriber::EncodingEventSubscriber( 39 EncodingEventSubscriber::EncodingEventSubscriber(
23 EventMediaType event_media_type, 40 EventMediaType event_media_type,
24 size_t max_frames) 41 size_t max_frames)
25 : event_media_type_(event_media_type), 42 : event_media_type_(event_media_type),
26 max_frames_(max_frames), 43 max_frames_(max_frames),
44 frame_event_storage_index_(0),
45 packet_event_storage_index_(0),
27 seen_first_rtp_timestamp_(false), 46 seen_first_rtp_timestamp_(false),
28 first_rtp_timestamp_(0u) {} 47 first_rtp_timestamp_(0u) {}
29 48
30 EncodingEventSubscriber::~EncodingEventSubscriber() { 49 EncodingEventSubscriber::~EncodingEventSubscriber() {
31 DCHECK(thread_checker_.CalledOnValidThread()); 50 DCHECK(thread_checker_.CalledOnValidThread());
32 } 51 }
33 52
34 void EncodingEventSubscriber::OnReceiveFrameEvent( 53 void EncodingEventSubscriber::OnReceiveFrameEvent(
35 const FrameEvent& frame_event) { 54 const FrameEvent& frame_event) {
36 DCHECK(thread_checker_.CalledOnValidThread()); 55 DCHECK(thread_checker_.CalledOnValidThread());
37 56
38 if (ShouldProcessEvent(frame_event.type)) { 57 if (!ShouldProcessEvent(frame_event.type))
39 RtpTimestamp relative_rtp_timestamp = 58 return;
40 GetRelativeRtpTimestamp(frame_event.rtp_timestamp);
41 FrameEventMap::iterator it = frame_event_map_.find(relative_rtp_timestamp);
42 linked_ptr<AggregatedFrameEvent> event_proto;
43 59
44 // Look up existing entry. If not found, create a new entry and add to map. 60 RtpTimestamp relative_rtp_timestamp =
45 if (it == frame_event_map_.end()) { 61 GetRelativeRtpTimestamp(frame_event.rtp_timestamp);
62 FrameEventMap::iterator it = frame_event_map_.find(relative_rtp_timestamp);
63 linked_ptr<AggregatedFrameEvent> event_proto;
64
65 // Look up existing entry. If not found, create a new entry and add to map.
66 if (it == frame_event_map_.end()) {
67 event_proto.reset(new AggregatedFrameEvent);
68 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
69 frame_event_map_.insert(
70 std::make_pair(relative_rtp_timestamp, event_proto));
71 } else {
72 event_proto = it->second;
73 if (event_proto->event_type_size() >= kMaxEventsPerProto) {
74 DVLOG(2) << "Too many events in frame " << frame_event.rtp_timestamp
75 << ". Using new frame event proto.";
76 AddFrameEventToStorage(event_proto);
46 event_proto.reset(new AggregatedFrameEvent); 77 event_proto.reset(new AggregatedFrameEvent);
47 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp); 78 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
48 frame_event_map_.insert( 79 it->second = event_proto;
49 std::make_pair(relative_rtp_timestamp, event_proto));
50 } else {
51 event_proto = it->second;
52 } 80 }
53
54 event_proto->add_event_type(ToProtoEventType(frame_event.type));
55 event_proto->add_event_timestamp_ms(
56 (frame_event.timestamp - base::TimeTicks()).InMilliseconds());
57
58 if (frame_event.type == kAudioFrameEncoded) {
59 event_proto->set_encoded_frame_size(frame_event.size);
60 } else if (frame_event.type == kVideoFrameEncoded) {
61 event_proto->set_encoded_frame_size(frame_event.size);
62 event_proto->set_key_frame(frame_event.key_frame);
63 } else if (frame_event.type == kAudioPlayoutDelay ||
64 frame_event.type == kVideoRenderDelay) {
65 event_proto->set_delay_millis(frame_event.delay_delta.InMilliseconds());
66 }
67
68 TruncateFrameEventMapIfNeeded();
69 } 81 }
70 82
71 DCHECK(frame_event_map_.size() <= max_frames_); 83 event_proto->add_event_type(ToProtoEventType(frame_event.type));
84 event_proto->add_event_timestamp_ms(
85 (frame_event.timestamp - base::TimeTicks()).InMilliseconds());
86
87 if (frame_event.type == kAudioFrameEncoded) {
88 event_proto->set_encoded_frame_size(frame_event.size);
89 } else if (frame_event.type == kVideoFrameEncoded) {
90 event_proto->set_encoded_frame_size(frame_event.size);
91 event_proto->set_key_frame(frame_event.key_frame);
92 } else if (frame_event.type == kAudioPlayoutDelay ||
93 frame_event.type == kVideoRenderDelay) {
94 event_proto->set_delay_millis(frame_event.delay_delta.InMilliseconds());
95 }
96
97 if (frame_event_map_.size() > kMaxMapSize)
98 TransferFrameEvents(kNumMapEntriesToTransfer);
99
100 DCHECK(frame_event_map_.size() <= kMaxMapSize);
101 DCHECK(frame_event_storage_.size() <= max_frames_);
72 } 102 }
73 103
74 void EncodingEventSubscriber::OnReceivePacketEvent( 104 void EncodingEventSubscriber::OnReceivePacketEvent(
75 const PacketEvent& packet_event) { 105 const PacketEvent& packet_event) {
76 DCHECK(thread_checker_.CalledOnValidThread()); 106 DCHECK(thread_checker_.CalledOnValidThread());
77 107
78 if (ShouldProcessEvent(packet_event.type)) { 108 if (!ShouldProcessEvent(packet_event.type))
79 RtpTimestamp relative_rtp_timestamp = 109 return;
80 GetRelativeRtpTimestamp(packet_event.rtp_timestamp); 110 RtpTimestamp relative_rtp_timestamp =
81 PacketEventMap::iterator it = 111 GetRelativeRtpTimestamp(packet_event.rtp_timestamp);
82 packet_event_map_.find(relative_rtp_timestamp); 112 PacketEventMap::iterator it =
83 linked_ptr<AggregatedPacketEvent> event_proto; 113 packet_event_map_.find(relative_rtp_timestamp);
84 BasePacketEvent* base_packet_event_proto = NULL; 114 linked_ptr<AggregatedPacketEvent> event_proto;
115 BasePacketEvent* base_packet_event_proto = NULL;
85 116
86 // Look up existing entry. If not found, create a new entry and add to map. 117 // Look up existing entry. If not found, create a new entry and add to map.
87 if (it == packet_event_map_.end()) { 118 if (it == packet_event_map_.end()) {
119 event_proto.reset(new AggregatedPacketEvent);
120 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
121 packet_event_map_.insert(
122 std::make_pair(relative_rtp_timestamp, event_proto));
123 base_packet_event_proto = event_proto->add_base_packet_event();
124 base_packet_event_proto->set_packet_id(packet_event.packet_id);
125 } else {
126 // Found existing entry, now look up existing BasePacketEvent using packet
127 // ID. If not found, create a new entry and add to proto.
128 event_proto = it->second;
129 RepeatedPtrField<BasePacketEvent>* field =
130 event_proto->mutable_base_packet_event();
131 for (RepeatedPtrField<BasePacketEvent>::pointer_iterator base_it =
132 field->pointer_begin();
133 base_it != field->pointer_end();
134 ++base_it) {
135 if ((*base_it)->packet_id() == packet_event.packet_id) {
136 base_packet_event_proto = *base_it;
137 break;
138 }
139 }
140 if (!base_packet_event_proto) {
141 if (event_proto->base_packet_event_size() >= kMaxPacketsPerFrame) {
142 DVLOG(3) << "Too many packets in AggregatedPacketEvent "
143 << packet_event.rtp_timestamp << ". "
144 << "Using new packet event proto.";
145 AddPacketEventToStorage(event_proto);
146 event_proto.reset(new AggregatedPacketEvent);
147 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
148 it->second = event_proto;
149 }
150
151 base_packet_event_proto = event_proto->add_base_packet_event();
152 base_packet_event_proto->set_packet_id(packet_event.packet_id);
153 } else if (base_packet_event_proto->event_type_size() >=
154 kMaxEventsPerProto) {
155 DVLOG(3) << "Too many events in packet "
156 << packet_event.rtp_timestamp << ", "
157 << packet_event.packet_id << ". Using new packet event proto.";
158 AddPacketEventToStorage(event_proto);
88 event_proto.reset(new AggregatedPacketEvent); 159 event_proto.reset(new AggregatedPacketEvent);
89 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp); 160 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
90 packet_event_map_.insert( 161 it->second = event_proto;
91 std::make_pair(relative_rtp_timestamp, event_proto));
92 base_packet_event_proto = event_proto->add_base_packet_event(); 162 base_packet_event_proto = event_proto->add_base_packet_event();
93 base_packet_event_proto->set_packet_id(packet_event.packet_id); 163 base_packet_event_proto->set_packet_id(packet_event.packet_id);
94 } else {
95 // Found existing entry, now look up existing BasePacketEvent using packet
96 // ID. If not found, create a new entry and add to proto.
97 event_proto = it->second;
98 RepeatedPtrField<BasePacketEvent>* field =
99 event_proto->mutable_base_packet_event();
100 for (RepeatedPtrField<BasePacketEvent>::pointer_iterator it =
101 field->pointer_begin();
102 it != field->pointer_end();
103 ++it) {
104 if ((*it)->packet_id() == packet_event.packet_id) {
105 base_packet_event_proto = *it;
106 break;
107 }
108 }
109 if (!base_packet_event_proto) {
110 base_packet_event_proto = event_proto->add_base_packet_event();
111 base_packet_event_proto->set_packet_id(packet_event.packet_id);
112 }
113 } 164 }
114
115 base_packet_event_proto->add_event_type(
116 ToProtoEventType(packet_event.type));
117 base_packet_event_proto->add_event_timestamp_ms(
118 (packet_event.timestamp - base::TimeTicks()).InMilliseconds());
119
120 TruncatePacketEventMapIfNeeded();
121 } 165 }
122 166
123 DCHECK(packet_event_map_.size() <= max_frames_); 167 base_packet_event_proto->add_event_type(
168 ToProtoEventType(packet_event.type));
169 base_packet_event_proto->add_event_timestamp_ms(
170 (packet_event.timestamp - base::TimeTicks()).InMilliseconds());
171
172 if (packet_event_map_.size() > kMaxMapSize)
173 TransferPacketEvents(kNumMapEntriesToTransfer);
174
175 DCHECK(packet_event_map_.size() <= kMaxMapSize);
176 DCHECK(packet_event_storage_.size() <= max_frames_);
124 } 177 }
125 178
126 void EncodingEventSubscriber::OnReceiveGenericEvent( 179 void EncodingEventSubscriber::OnReceiveGenericEvent(
127 const GenericEvent& generic_event) { 180 const GenericEvent& generic_event) {
128 DCHECK(thread_checker_.CalledOnValidThread()); 181 DCHECK(thread_checker_.CalledOnValidThread());
129 // Do nothing, there are no generic events we are interested in. 182 // Do nothing, there are no generic events we are interested in.
130 } 183 }
131 184
132 void EncodingEventSubscriber::GetEventsAndReset(LogMetadata* metadata, 185 void EncodingEventSubscriber::GetEventsAndReset(
133 FrameEventMap* frame_events, 186 LogMetadata* metadata, FrameEventList* frame_events,
134 PacketEventMap* packet_events) { 187 PacketEventList* packet_events) {
135 DCHECK(thread_checker_.CalledOnValidThread()); 188 DCHECK(thread_checker_.CalledOnValidThread());
136 189
190 // Flush all events.
191 TransferFrameEvents(frame_event_map_.size());
192 TransferPacketEvents(packet_event_map_.size());
193 std::sort(frame_event_storage_.begin(), frame_event_storage_.end(),
194 &IsRtpTimestampLessThan<linked_ptr<AggregatedFrameEvent> >);
195 std::sort(packet_event_storage_.begin(), packet_event_storage_.end(),
196 &IsRtpTimestampLessThan<linked_ptr<AggregatedPacketEvent> >);
197
137 metadata->set_is_audio(event_media_type_ == AUDIO_EVENT); 198 metadata->set_is_audio(event_media_type_ == AUDIO_EVENT);
138 metadata->set_first_rtp_timestamp(first_rtp_timestamp_); 199 metadata->set_first_rtp_timestamp(first_rtp_timestamp_);
139 metadata->set_num_frame_events(frame_event_map_.size()); 200 metadata->set_num_frame_events(frame_event_storage_.size());
140 metadata->set_num_packet_events(packet_event_map_.size()); 201 metadata->set_num_packet_events(packet_event_storage_.size());
141 metadata->set_reference_timestamp_ms_at_unix_epoch( 202 metadata->set_reference_timestamp_ms_at_unix_epoch(
142 (base::TimeTicks::UnixEpoch() - base::TimeTicks()).InMilliseconds()); 203 (base::TimeTicks::UnixEpoch() - base::TimeTicks()).InMilliseconds());
143 frame_events->swap(frame_event_map_); 204 frame_events->swap(frame_event_storage_);
144 packet_events->swap(packet_event_map_); 205 packet_events->swap(packet_event_storage_);
145 Reset(); 206 Reset();
146 } 207 }
147 208
148 bool EncodingEventSubscriber::ShouldProcessEvent(CastLoggingEvent event) { 209 bool EncodingEventSubscriber::ShouldProcessEvent(CastLoggingEvent event) {
149 return GetEventMediaType(event) == event_media_type_; 210 return GetEventMediaType(event) == event_media_type_;
150 } 211 }
151 212
152 void EncodingEventSubscriber::TruncateFrameEventMapIfNeeded() { 213 void EncodingEventSubscriber::TransferFrameEvents(size_t num_entries) {
153 // This works because this is called everytime an event is inserted and 214 DCHECK(frame_event_map_.size() >= num_entries);
154 // we only insert events one at a time. 215
155 if (frame_event_map_.size() > max_frames_) 216 FrameEventMap::iterator it = frame_event_map_.begin();
156 frame_event_map_.erase(frame_event_map_.begin()); 217 for (size_t i = 0; i < num_entries; i++, ++it)
218 AddFrameEventToStorage(it->second);
219
220 frame_event_map_.erase(frame_event_map_.begin(), it);
157 } 221 }
158 222
159 void EncodingEventSubscriber::TruncatePacketEventMapIfNeeded() { 223 void EncodingEventSubscriber::TransferPacketEvents(size_t num_entries) {
160 // This works because this is called everytime an event is inserted and 224 DCHECK(packet_event_map_.size() >= num_entries);
161 // we only insert events one at a time. 225
162 if (packet_event_map_.size() > max_frames_) 226 PacketEventMap::iterator it = packet_event_map_.begin();
163 packet_event_map_.erase(packet_event_map_.begin()); 227 for (size_t i = 0; i < num_entries; i++, ++it)
Alpha Left Google 2014/04/22 18:20:42 Try to erase the entry while iterating. That way y
imcheng 2014/04/22 19:29:33 Per offline discussion, changed the semantics of f
228 AddPacketEventToStorage(it->second);
229
230 packet_event_map_.erase(packet_event_map_.begin(), it);
231 }
232
233 void EncodingEventSubscriber::AddFrameEventToStorage(
234 const linked_ptr<AggregatedFrameEvent>& frame_event_proto) {
235 if (frame_event_storage_.size() >= max_frames_) {
236 frame_event_storage_[frame_event_storage_index_] = frame_event_proto;
237 } else {
238 frame_event_storage_.push_back(frame_event_proto);
239 }
240
241 frame_event_storage_index_ = (frame_event_storage_index_ + 1) % max_frames_;
242 }
243
244 void EncodingEventSubscriber::AddPacketEventToStorage(
245 const linked_ptr<AggregatedPacketEvent>& packet_event_proto) {
246 if (packet_event_storage_.size() >= max_frames_)
247 packet_event_storage_[packet_event_storage_index_] = packet_event_proto;
248 else
249 packet_event_storage_.push_back(packet_event_proto);
250
251 packet_event_storage_index_ = (packet_event_storage_index_ + 1) % max_frames_;
164 } 252 }
165 253
166 RtpTimestamp EncodingEventSubscriber::GetRelativeRtpTimestamp( 254 RtpTimestamp EncodingEventSubscriber::GetRelativeRtpTimestamp(
167 RtpTimestamp rtp_timestamp) { 255 RtpTimestamp rtp_timestamp) {
168 if (!seen_first_rtp_timestamp_) { 256 if (!seen_first_rtp_timestamp_) {
169 seen_first_rtp_timestamp_ = true; 257 seen_first_rtp_timestamp_ = true;
170 first_rtp_timestamp_ = rtp_timestamp; 258 first_rtp_timestamp_ = rtp_timestamp;
171 } 259 }
172 260
173 return rtp_timestamp - first_rtp_timestamp_; 261 return rtp_timestamp - first_rtp_timestamp_;
174 } 262 }
175 263
176 void EncodingEventSubscriber::Reset() { 264 void EncodingEventSubscriber::Reset() {
177 frame_event_map_.clear(); 265 frame_event_map_.clear();
266 frame_event_storage_.clear();
267 frame_event_storage_index_ = 0;
178 packet_event_map_.clear(); 268 packet_event_map_.clear();
269 packet_event_storage_.clear();
270 packet_event_storage_index_ = 0;
179 seen_first_rtp_timestamp_ = false; 271 seen_first_rtp_timestamp_ = false;
180 first_rtp_timestamp_ = 0u; 272 first_rtp_timestamp_ = 0u;
181 } 273 }
182 274
183 } // namespace cast 275 } // namespace cast
184 } // namespace media 276 } // namespace media
OLDNEW
« no previous file with comments | « media/cast/logging/encoding_event_subscriber.h ('k') | media/cast/logging/encoding_event_subscriber_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698