Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / cast / logging / encoding_event_subscriber.cc
blob82ec06f2bae16ee9914668c67beb8d5b08d2d7dc
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.
5 #include "media/cast/logging/encoding_event_subscriber.h"
7 #include <algorithm>
8 #include <cstring>
9 #include <utility>
11 #include "base/logging.h"
12 #include "base/numerics/safe_conversions.h"
13 #include "media/cast/logging/proto/proto_utils.h"
15 using google::protobuf::RepeatedPtrField;
16 using media::cast::proto::AggregatedFrameEvent;
17 using media::cast::proto::AggregatedPacketEvent;
18 using media::cast::proto::BasePacketEvent;
19 using media::cast::proto::LogMetadata;
21 namespace {
23 // A size limit on maps to keep lookups fast.
24 const size_t kMaxMapSize = 200;
26 // The smallest (oredered by RTP timestamp) |kNumMapEntriesToTransfer| entries
27 // will be moved when the map size reaches |kMaxMapSize|.
28 // Must be smaller than |kMaxMapSize|.
29 const size_t kNumMapEntriesToTransfer = 100;
31 template <typename ProtoPtr>
32 bool IsRtpTimestampLessThan(const ProtoPtr& lhs, const ProtoPtr& rhs) {
33 return lhs->relative_rtp_timestamp() < rhs->relative_rtp_timestamp();
36 BasePacketEvent* GetNewBasePacketEvent(AggregatedPacketEvent* event_proto,
37 int packet_id, int size) {
38 BasePacketEvent* base = event_proto->add_base_packet_event();
39 base->set_packet_id(packet_id);
40 base->set_size(size);
41 return base;
46 namespace media {
47 namespace cast {
49 EncodingEventSubscriber::EncodingEventSubscriber(
50 EventMediaType event_media_type,
51 size_t max_frames)
52 : event_media_type_(event_media_type),
53 max_frames_(max_frames),
54 frame_event_storage_index_(0),
55 packet_event_storage_index_(0),
56 seen_first_rtp_timestamp_(false),
57 first_rtp_timestamp_(0u) {}
59 EncodingEventSubscriber::~EncodingEventSubscriber() {
60 DCHECK(thread_checker_.CalledOnValidThread());
63 void EncodingEventSubscriber::OnReceiveFrameEvent(
64 const FrameEvent& frame_event) {
65 DCHECK(thread_checker_.CalledOnValidThread());
67 if (event_media_type_ != frame_event.media_type)
68 return;
70 RtpTimestamp relative_rtp_timestamp =
71 GetRelativeRtpTimestamp(frame_event.rtp_timestamp);
72 FrameEventMap::iterator it = frame_event_map_.find(relative_rtp_timestamp);
73 linked_ptr<AggregatedFrameEvent> event_proto;
75 // Look up existing entry. If not found, create a new entry and add to map.
76 if (it == frame_event_map_.end()) {
77 event_proto.reset(new AggregatedFrameEvent);
78 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
79 frame_event_map_.insert(
80 std::make_pair(relative_rtp_timestamp, event_proto));
81 } else {
82 event_proto = it->second;
83 if (event_proto->event_type_size() >= kMaxEventsPerProto) {
84 DVLOG(2) << "Too many events in frame " << frame_event.rtp_timestamp
85 << ". Using new frame event proto.";
86 AddFrameEventToStorage(event_proto);
87 event_proto.reset(new AggregatedFrameEvent);
88 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
89 it->second = event_proto;
93 event_proto->add_event_type(ToProtoEventType(frame_event.type));
94 event_proto->add_event_timestamp_ms(
95 (frame_event.timestamp - base::TimeTicks()).InMilliseconds());
97 if (frame_event.type == FRAME_CAPTURE_END) {
98 if (frame_event.media_type == VIDEO_EVENT &&
99 frame_event.width > 0 && frame_event.height > 0) {
100 event_proto->set_width(frame_event.width);
101 event_proto->set_height(frame_event.height);
103 } else if (frame_event.type == FRAME_ENCODED) {
104 event_proto->set_encoded_frame_size(frame_event.size);
105 if (frame_event.encoder_cpu_utilization >= 0.0) {
106 event_proto->set_encoder_cpu_percent_utilized(base::saturated_cast<int32>(
107 frame_event.encoder_cpu_utilization * 100.0 + 0.5));
109 if (frame_event.idealized_bitrate_utilization >= 0.0) {
110 event_proto->set_idealized_bitrate_percent_utilized(
111 base::saturated_cast<int32>(
112 frame_event.idealized_bitrate_utilization * 100.0 + 0.5));
114 if (frame_event.media_type == VIDEO_EVENT) {
115 event_proto->set_key_frame(frame_event.key_frame);
116 event_proto->set_target_bitrate(frame_event.target_bitrate);
118 } else if (frame_event.type == FRAME_PLAYOUT) {
119 event_proto->set_delay_millis(frame_event.delay_delta.InMilliseconds());
122 if (frame_event_map_.size() > kMaxMapSize)
123 TransferFrameEvents(kNumMapEntriesToTransfer);
125 DCHECK(frame_event_map_.size() <= kMaxMapSize);
126 DCHECK(frame_event_storage_.size() <= max_frames_);
129 void EncodingEventSubscriber::OnReceivePacketEvent(
130 const PacketEvent& packet_event) {
131 DCHECK(thread_checker_.CalledOnValidThread());
133 if (event_media_type_ != packet_event.media_type)
134 return;
136 RtpTimestamp relative_rtp_timestamp =
137 GetRelativeRtpTimestamp(packet_event.rtp_timestamp);
138 PacketEventMap::iterator it =
139 packet_event_map_.find(relative_rtp_timestamp);
140 linked_ptr<AggregatedPacketEvent> event_proto;
141 BasePacketEvent* base_packet_event_proto = NULL;
143 // Look up existing entry. If not found, create a new entry and add to map.
144 if (it == packet_event_map_.end()) {
145 event_proto.reset(new AggregatedPacketEvent);
146 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
147 packet_event_map_.insert(
148 std::make_pair(relative_rtp_timestamp, event_proto));
149 base_packet_event_proto = GetNewBasePacketEvent(
150 event_proto.get(), packet_event.packet_id, packet_event.size);
151 } else {
152 // Found existing entry, now look up existing BasePacketEvent using packet
153 // ID. If not found, create a new entry and add to proto.
154 event_proto = it->second;
155 RepeatedPtrField<BasePacketEvent>* field =
156 event_proto->mutable_base_packet_event();
157 for (RepeatedPtrField<BasePacketEvent>::pointer_iterator base_it =
158 field->pointer_begin();
159 base_it != field->pointer_end();
160 ++base_it) {
161 if ((*base_it)->packet_id() == packet_event.packet_id) {
162 base_packet_event_proto = *base_it;
163 break;
166 if (!base_packet_event_proto) {
167 if (event_proto->base_packet_event_size() >= kMaxPacketsPerFrame) {
168 DVLOG(3) << "Too many packets in AggregatedPacketEvent "
169 << packet_event.rtp_timestamp << ". "
170 << "Using new packet event proto.";
171 AddPacketEventToStorage(event_proto);
172 event_proto.reset(new AggregatedPacketEvent);
173 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
174 it->second = event_proto;
177 base_packet_event_proto = GetNewBasePacketEvent(
178 event_proto.get(), packet_event.packet_id, packet_event.size);
179 } else if (base_packet_event_proto->event_type_size() >=
180 kMaxEventsPerProto) {
181 DVLOG(3) << "Too many events in packet "
182 << packet_event.rtp_timestamp << ", "
183 << packet_event.packet_id << ". Using new packet event proto.";
184 AddPacketEventToStorage(event_proto);
185 event_proto.reset(new AggregatedPacketEvent);
186 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
187 it->second = event_proto;
188 base_packet_event_proto = GetNewBasePacketEvent(
189 event_proto.get(), packet_event.packet_id, packet_event.size);
193 base_packet_event_proto->add_event_type(
194 ToProtoEventType(packet_event.type));
195 base_packet_event_proto->add_event_timestamp_ms(
196 (packet_event.timestamp - base::TimeTicks()).InMilliseconds());
198 // |base_packet_event_proto| could have been created with a receiver event
199 // which does not have the packet size and we would need to overwrite it when
200 // we see a sender event, which does have the packet size.
201 if (packet_event.size > 0) {
202 base_packet_event_proto->set_size(packet_event.size);
205 if (packet_event_map_.size() > kMaxMapSize)
206 TransferPacketEvents(kNumMapEntriesToTransfer);
208 DCHECK(packet_event_map_.size() <= kMaxMapSize);
209 DCHECK(packet_event_storage_.size() <= max_frames_);
212 void EncodingEventSubscriber::GetEventsAndReset(LogMetadata* metadata,
213 FrameEventList* frame_events, PacketEventList* packet_events) {
214 DCHECK(thread_checker_.CalledOnValidThread());
216 // Flush all events.
217 TransferFrameEvents(frame_event_map_.size());
218 TransferPacketEvents(packet_event_map_.size());
219 std::sort(frame_event_storage_.begin(), frame_event_storage_.end(),
220 &IsRtpTimestampLessThan<linked_ptr<AggregatedFrameEvent> >);
221 std::sort(packet_event_storage_.begin(), packet_event_storage_.end(),
222 &IsRtpTimestampLessThan<linked_ptr<AggregatedPacketEvent> >);
224 metadata->set_is_audio(event_media_type_ == AUDIO_EVENT);
225 metadata->set_first_rtp_timestamp(first_rtp_timestamp_);
226 metadata->set_num_frame_events(frame_event_storage_.size());
227 metadata->set_num_packet_events(packet_event_storage_.size());
228 metadata->set_reference_timestamp_ms_at_unix_epoch(
229 (base::TimeTicks::UnixEpoch() - base::TimeTicks()).InMilliseconds());
230 frame_events->swap(frame_event_storage_);
231 packet_events->swap(packet_event_storage_);
232 Reset();
235 void EncodingEventSubscriber::TransferFrameEvents(size_t max_num_entries) {
236 DCHECK(frame_event_map_.size() >= max_num_entries);
238 FrameEventMap::iterator it = frame_event_map_.begin();
239 for (size_t i = 0;
240 i < max_num_entries && it != frame_event_map_.end();
241 i++, ++it) {
242 AddFrameEventToStorage(it->second);
245 frame_event_map_.erase(frame_event_map_.begin(), it);
248 void EncodingEventSubscriber::TransferPacketEvents(size_t max_num_entries) {
249 PacketEventMap::iterator it = packet_event_map_.begin();
250 for (size_t i = 0;
251 i < max_num_entries && it != packet_event_map_.end();
252 i++, ++it) {
253 AddPacketEventToStorage(it->second);
256 packet_event_map_.erase(packet_event_map_.begin(), it);
259 void EncodingEventSubscriber::AddFrameEventToStorage(
260 const linked_ptr<AggregatedFrameEvent>& frame_event_proto) {
261 if (frame_event_storage_.size() >= max_frames_) {
262 frame_event_storage_[frame_event_storage_index_] = frame_event_proto;
263 } else {
264 frame_event_storage_.push_back(frame_event_proto);
267 frame_event_storage_index_ = (frame_event_storage_index_ + 1) % max_frames_;
270 void EncodingEventSubscriber::AddPacketEventToStorage(
271 const linked_ptr<AggregatedPacketEvent>& packet_event_proto) {
272 if (packet_event_storage_.size() >= max_frames_)
273 packet_event_storage_[packet_event_storage_index_] = packet_event_proto;
274 else
275 packet_event_storage_.push_back(packet_event_proto);
277 packet_event_storage_index_ = (packet_event_storage_index_ + 1) % max_frames_;
280 RtpTimestamp EncodingEventSubscriber::GetRelativeRtpTimestamp(
281 RtpTimestamp rtp_timestamp) {
282 if (!seen_first_rtp_timestamp_) {
283 seen_first_rtp_timestamp_ = true;
284 first_rtp_timestamp_ = rtp_timestamp;
287 return rtp_timestamp - first_rtp_timestamp_;
290 void EncodingEventSubscriber::Reset() {
291 frame_event_map_.clear();
292 frame_event_storage_.clear();
293 frame_event_storage_index_ = 0;
294 packet_event_map_.clear();
295 packet_event_storage_.clear();
296 packet_event_storage_index_ = 0;
297 seen_first_rtp_timestamp_ = false;
298 first_rtp_timestamp_ = 0u;
301 } // namespace cast
302 } // namespace media