Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / media / cast / logging / encoding_event_subscriber.cc
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 #include "media/cast/logging/encoding_event_subscriber.h"
6
7 #include <cstring>
8 #include <utility>
9
10 #include "base/logging.h"
11 #include "media/cast/logging/proto/proto_utils.h"
12
13 using google::protobuf::RepeatedPtrField;
14 using media::cast::proto::AggregatedFrameEvent;
15 using media::cast::proto::AggregatedPacketEvent;
16 using media::cast::proto::BasePacketEvent;
17 using media::cast::proto::LogMetadata;
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 BasePacketEvent* GetNewBasePacketEvent(AggregatedPacketEvent* event_proto,
35     int packet_id, int size) {
36   BasePacketEvent* base = event_proto->add_base_packet_event();
37   base->set_packet_id(packet_id);
38   base->set_size(size);
39   return base;
40 }
41
42 }
43
44 namespace media {
45 namespace cast {
46
47 EncodingEventSubscriber::EncodingEventSubscriber(
48     EventMediaType event_media_type,
49     size_t max_frames)
50     : event_media_type_(event_media_type),
51       max_frames_(max_frames),
52       frame_event_storage_index_(0),
53       packet_event_storage_index_(0),
54       seen_first_rtp_timestamp_(false),
55       first_rtp_timestamp_(0u) {}
56
57 EncodingEventSubscriber::~EncodingEventSubscriber() {
58   DCHECK(thread_checker_.CalledOnValidThread());
59 }
60
61 void EncodingEventSubscriber::OnReceiveFrameEvent(
62     const FrameEvent& frame_event) {
63   DCHECK(thread_checker_.CalledOnValidThread());
64
65   if (!ShouldProcessEvent(frame_event.type))
66     return;
67
68   RtpTimestamp relative_rtp_timestamp =
69       GetRelativeRtpTimestamp(frame_event.rtp_timestamp);
70   FrameEventMap::iterator it = frame_event_map_.find(relative_rtp_timestamp);
71   linked_ptr<AggregatedFrameEvent> event_proto;
72
73   // Look up existing entry. If not found, create a new entry and add to map.
74   if (it == frame_event_map_.end()) {
75     event_proto.reset(new AggregatedFrameEvent);
76     event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
77     frame_event_map_.insert(
78         std::make_pair(relative_rtp_timestamp, event_proto));
79   } else {
80     event_proto = it->second;
81     if (event_proto->event_type_size() >= kMaxEventsPerProto) {
82       DVLOG(2) << "Too many events in frame " << frame_event.rtp_timestamp
83                << ". Using new frame event proto.";
84       AddFrameEventToStorage(event_proto);
85       event_proto.reset(new AggregatedFrameEvent);
86       event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
87       it->second = event_proto;
88     }
89   }
90
91   event_proto->add_event_type(ToProtoEventType(frame_event.type));
92   event_proto->add_event_timestamp_ms(
93       (frame_event.timestamp - base::TimeTicks()).InMilliseconds());
94
95   if (frame_event.type == kAudioFrameEncoded) {
96     event_proto->set_encoded_frame_size(frame_event.size);
97   } else if (frame_event.type == kVideoFrameEncoded) {
98     event_proto->set_encoded_frame_size(frame_event.size);
99     event_proto->set_key_frame(frame_event.key_frame);
100     event_proto->set_target_bitrate(frame_event.target_bitrate);
101   } else if (frame_event.type == kAudioPlayoutDelay ||
102              frame_event.type == kVideoRenderDelay) {
103     event_proto->set_delay_millis(frame_event.delay_delta.InMilliseconds());
104   }
105
106   if (frame_event_map_.size() > kMaxMapSize)
107     TransferFrameEvents(kNumMapEntriesToTransfer);
108
109   DCHECK(frame_event_map_.size() <= kMaxMapSize);
110   DCHECK(frame_event_storage_.size() <= max_frames_);
111 }
112
113 void EncodingEventSubscriber::OnReceivePacketEvent(
114     const PacketEvent& packet_event) {
115   DCHECK(thread_checker_.CalledOnValidThread());
116
117   if (!ShouldProcessEvent(packet_event.type))
118     return;
119   RtpTimestamp relative_rtp_timestamp =
120       GetRelativeRtpTimestamp(packet_event.rtp_timestamp);
121   PacketEventMap::iterator it =
122       packet_event_map_.find(relative_rtp_timestamp);
123   linked_ptr<AggregatedPacketEvent> event_proto;
124   BasePacketEvent* base_packet_event_proto = NULL;
125
126   // Look up existing entry. If not found, create a new entry and add to map.
127   if (it == packet_event_map_.end()) {
128     event_proto.reset(new AggregatedPacketEvent);
129     event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
130     packet_event_map_.insert(
131         std::make_pair(relative_rtp_timestamp, event_proto));
132     base_packet_event_proto = GetNewBasePacketEvent(
133         event_proto.get(), packet_event.packet_id, packet_event.size);
134   } else {
135     // Found existing entry, now look up existing BasePacketEvent using packet
136     // ID. If not found, create a new entry and add to proto.
137     event_proto = it->second;
138     RepeatedPtrField<BasePacketEvent>* field =
139         event_proto->mutable_base_packet_event();
140     for (RepeatedPtrField<BasePacketEvent>::pointer_iterator base_it =
141              field->pointer_begin();
142          base_it != field->pointer_end();
143          ++base_it) {
144       if ((*base_it)->packet_id() == packet_event.packet_id) {
145         base_packet_event_proto = *base_it;
146         break;
147       }
148     }
149     if (!base_packet_event_proto) {
150       if (event_proto->base_packet_event_size() >= kMaxPacketsPerFrame) {
151         DVLOG(3) << "Too many packets in AggregatedPacketEvent "
152                  << packet_event.rtp_timestamp << ". "
153                  << "Using new packet event proto.";
154         AddPacketEventToStorage(event_proto);
155         event_proto.reset(new AggregatedPacketEvent);
156         event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
157         it->second = event_proto;
158       }
159
160       base_packet_event_proto = GetNewBasePacketEvent(
161           event_proto.get(), packet_event.packet_id, packet_event.size);
162     } else if (base_packet_event_proto->event_type_size() >=
163                kMaxEventsPerProto) {
164       DVLOG(3) << "Too many events in packet "
165                << packet_event.rtp_timestamp << ", "
166                << packet_event.packet_id << ". Using new packet event proto.";
167       AddPacketEventToStorage(event_proto);
168       event_proto.reset(new AggregatedPacketEvent);
169       event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp);
170       it->second = event_proto;
171       base_packet_event_proto = GetNewBasePacketEvent(
172           event_proto.get(), packet_event.packet_id, packet_event.size);
173     }
174   }
175
176   base_packet_event_proto->add_event_type(
177       ToProtoEventType(packet_event.type));
178   base_packet_event_proto->add_event_timestamp_ms(
179       (packet_event.timestamp - base::TimeTicks()).InMilliseconds());
180
181   // |base_packet_event_proto| could have been created with a receiver event
182   // which does not have the packet size and we would need to overwrite it when
183   // we see a sender event, which does have the packet size.
184   if (packet_event.size > 0) {
185     base_packet_event_proto->set_size(packet_event.size);
186   }
187
188   if (packet_event_map_.size() > kMaxMapSize)
189     TransferPacketEvents(kNumMapEntriesToTransfer);
190
191   DCHECK(packet_event_map_.size() <= kMaxMapSize);
192   DCHECK(packet_event_storage_.size() <= max_frames_);
193 }
194
195 void EncodingEventSubscriber::GetEventsAndReset(LogMetadata* metadata,
196     FrameEventList* frame_events, PacketEventList* packet_events) {
197   DCHECK(thread_checker_.CalledOnValidThread());
198
199   // Flush all events.
200   TransferFrameEvents(frame_event_map_.size());
201   TransferPacketEvents(packet_event_map_.size());
202   std::sort(frame_event_storage_.begin(), frame_event_storage_.end(),
203             &IsRtpTimestampLessThan<linked_ptr<AggregatedFrameEvent> >);
204   std::sort(packet_event_storage_.begin(), packet_event_storage_.end(),
205             &IsRtpTimestampLessThan<linked_ptr<AggregatedPacketEvent> >);
206
207   metadata->set_is_audio(event_media_type_ == AUDIO_EVENT);
208   metadata->set_first_rtp_timestamp(first_rtp_timestamp_);
209   metadata->set_num_frame_events(frame_event_storage_.size());
210   metadata->set_num_packet_events(packet_event_storage_.size());
211   metadata->set_reference_timestamp_ms_at_unix_epoch(
212       (base::TimeTicks::UnixEpoch() - base::TimeTicks()).InMilliseconds());
213   frame_events->swap(frame_event_storage_);
214   packet_events->swap(packet_event_storage_);
215   Reset();
216 }
217
218 bool EncodingEventSubscriber::ShouldProcessEvent(CastLoggingEvent event) {
219   return GetEventMediaType(event) == event_media_type_;
220 }
221
222 void EncodingEventSubscriber::TransferFrameEvents(size_t max_num_entries) {
223   DCHECK(frame_event_map_.size() >= max_num_entries);
224
225   FrameEventMap::iterator it = frame_event_map_.begin();
226   for (size_t i = 0;
227        i < max_num_entries && it != frame_event_map_.end();
228        i++, ++it) {
229     AddFrameEventToStorage(it->second);
230   }
231
232   frame_event_map_.erase(frame_event_map_.begin(), it);
233 }
234
235 void EncodingEventSubscriber::TransferPacketEvents(size_t max_num_entries) {
236   PacketEventMap::iterator it = packet_event_map_.begin();
237   for (size_t i = 0;
238        i < max_num_entries && it != packet_event_map_.end();
239        i++, ++it) {
240     AddPacketEventToStorage(it->second);
241   }
242
243   packet_event_map_.erase(packet_event_map_.begin(), it);
244 }
245
246 void EncodingEventSubscriber::AddFrameEventToStorage(
247     const linked_ptr<AggregatedFrameEvent>& frame_event_proto) {
248   if (frame_event_storage_.size() >= max_frames_) {
249     frame_event_storage_[frame_event_storage_index_] = frame_event_proto;
250   } else {
251     frame_event_storage_.push_back(frame_event_proto);
252   }
253
254   frame_event_storage_index_ = (frame_event_storage_index_ + 1) % max_frames_;
255 }
256
257 void EncodingEventSubscriber::AddPacketEventToStorage(
258     const linked_ptr<AggregatedPacketEvent>& packet_event_proto) {
259   if (packet_event_storage_.size() >= max_frames_)
260     packet_event_storage_[packet_event_storage_index_] = packet_event_proto;
261   else
262     packet_event_storage_.push_back(packet_event_proto);
263
264   packet_event_storage_index_ = (packet_event_storage_index_ + 1) % max_frames_;
265 }
266
267 RtpTimestamp EncodingEventSubscriber::GetRelativeRtpTimestamp(
268     RtpTimestamp rtp_timestamp) {
269   if (!seen_first_rtp_timestamp_) {
270     seen_first_rtp_timestamp_ = true;
271     first_rtp_timestamp_ = rtp_timestamp;
272   }
273
274   return rtp_timestamp - first_rtp_timestamp_;
275 }
276
277 void EncodingEventSubscriber::Reset() {
278   frame_event_map_.clear();
279   frame_event_storage_.clear();
280   frame_event_storage_index_ = 0;
281   packet_event_map_.clear();
282   packet_event_storage_.clear();
283   packet_event_storage_index_ = 0;
284   seen_first_rtp_timestamp_ = false;
285   first_rtp_timestamp_ = 0u;
286 }
287
288 }  // namespace cast
289 }  // namespace media