| OLD | NEW |
| 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 event_proto->set_target_bitrate(frame_event.target_bitrate); | |
| 64 } else if (frame_event.type == kAudioPlayoutDelay || | |
| 65 frame_event.type == kVideoRenderDelay) { | |
| 66 event_proto->set_delay_millis(frame_event.delay_delta.InMilliseconds()); | |
| 67 } | |
| 68 | |
| 69 TruncateFrameEventMapIfNeeded(); | |
| 70 } | 81 } |
| 71 | 82 |
| 72 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 event_proto->set_target_bitrate(frame_event.target_bitrate); |
| 93 } else if (frame_event.type == kAudioPlayoutDelay || |
| 94 frame_event.type == kVideoRenderDelay) { |
| 95 event_proto->set_delay_millis(frame_event.delay_delta.InMilliseconds()); |
| 96 } |
| 97 |
| 98 if (frame_event_map_.size() > kMaxMapSize) |
| 99 TransferFrameEvents(kNumMapEntriesToTransfer); |
| 100 |
| 101 DCHECK(frame_event_map_.size() <= kMaxMapSize); |
| 102 DCHECK(frame_event_storage_.size() <= max_frames_); |
| 73 } | 103 } |
| 74 | 104 |
| 75 void EncodingEventSubscriber::OnReceivePacketEvent( | 105 void EncodingEventSubscriber::OnReceivePacketEvent( |
| 76 const PacketEvent& packet_event) { | 106 const PacketEvent& packet_event) { |
| 77 DCHECK(thread_checker_.CalledOnValidThread()); | 107 DCHECK(thread_checker_.CalledOnValidThread()); |
| 78 | 108 |
| 79 if (ShouldProcessEvent(packet_event.type)) { | 109 if (!ShouldProcessEvent(packet_event.type)) |
| 80 RtpTimestamp relative_rtp_timestamp = | 110 return; |
| 81 GetRelativeRtpTimestamp(packet_event.rtp_timestamp); | 111 RtpTimestamp relative_rtp_timestamp = |
| 82 PacketEventMap::iterator it = | 112 GetRelativeRtpTimestamp(packet_event.rtp_timestamp); |
| 83 packet_event_map_.find(relative_rtp_timestamp); | 113 PacketEventMap::iterator it = |
| 84 linked_ptr<AggregatedPacketEvent> event_proto; | 114 packet_event_map_.find(relative_rtp_timestamp); |
| 85 BasePacketEvent* base_packet_event_proto = NULL; | 115 linked_ptr<AggregatedPacketEvent> event_proto; |
| 116 BasePacketEvent* base_packet_event_proto = NULL; |
| 86 | 117 |
| 87 // Look up existing entry. If not found, create a new entry and add to map. | 118 // Look up existing entry. If not found, create a new entry and add to map. |
| 88 if (it == packet_event_map_.end()) { | 119 if (it == packet_event_map_.end()) { |
| 120 event_proto.reset(new AggregatedPacketEvent); |
| 121 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp); |
| 122 packet_event_map_.insert( |
| 123 std::make_pair(relative_rtp_timestamp, event_proto)); |
| 124 base_packet_event_proto = event_proto->add_base_packet_event(); |
| 125 base_packet_event_proto->set_packet_id(packet_event.packet_id); |
| 126 } else { |
| 127 // Found existing entry, now look up existing BasePacketEvent using packet |
| 128 // ID. If not found, create a new entry and add to proto. |
| 129 event_proto = it->second; |
| 130 RepeatedPtrField<BasePacketEvent>* field = |
| 131 event_proto->mutable_base_packet_event(); |
| 132 for (RepeatedPtrField<BasePacketEvent>::pointer_iterator base_it = |
| 133 field->pointer_begin(); |
| 134 base_it != field->pointer_end(); |
| 135 ++base_it) { |
| 136 if ((*base_it)->packet_id() == packet_event.packet_id) { |
| 137 base_packet_event_proto = *base_it; |
| 138 break; |
| 139 } |
| 140 } |
| 141 if (!base_packet_event_proto) { |
| 142 if (event_proto->base_packet_event_size() >= kMaxPacketsPerFrame) { |
| 143 DVLOG(3) << "Too many packets in AggregatedPacketEvent " |
| 144 << packet_event.rtp_timestamp << ". " |
| 145 << "Using new packet event proto."; |
| 146 AddPacketEventToStorage(event_proto); |
| 147 event_proto.reset(new AggregatedPacketEvent); |
| 148 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp); |
| 149 it->second = event_proto; |
| 150 } |
| 151 |
| 152 base_packet_event_proto = event_proto->add_base_packet_event(); |
| 153 base_packet_event_proto->set_packet_id(packet_event.packet_id); |
| 154 } else if (base_packet_event_proto->event_type_size() >= |
| 155 kMaxEventsPerProto) { |
| 156 DVLOG(3) << "Too many events in packet " |
| 157 << packet_event.rtp_timestamp << ", " |
| 158 << packet_event.packet_id << ". Using new packet event proto."; |
| 159 AddPacketEventToStorage(event_proto); |
| 89 event_proto.reset(new AggregatedPacketEvent); | 160 event_proto.reset(new AggregatedPacketEvent); |
| 90 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp); | 161 event_proto->set_relative_rtp_timestamp(relative_rtp_timestamp); |
| 91 packet_event_map_.insert( | 162 it->second = event_proto; |
| 92 std::make_pair(relative_rtp_timestamp, event_proto)); | |
| 93 base_packet_event_proto = event_proto->add_base_packet_event(); | 163 base_packet_event_proto = event_proto->add_base_packet_event(); |
| 94 base_packet_event_proto->set_packet_id(packet_event.packet_id); | 164 base_packet_event_proto->set_packet_id(packet_event.packet_id); |
| 95 } else { | |
| 96 // Found existing entry, now look up existing BasePacketEvent using packet | |
| 97 // ID. If not found, create a new entry and add to proto. | |
| 98 event_proto = it->second; | |
| 99 RepeatedPtrField<BasePacketEvent>* field = | |
| 100 event_proto->mutable_base_packet_event(); | |
| 101 for (RepeatedPtrField<BasePacketEvent>::pointer_iterator it = | |
| 102 field->pointer_begin(); | |
| 103 it != field->pointer_end(); | |
| 104 ++it) { | |
| 105 if ((*it)->packet_id() == packet_event.packet_id) { | |
| 106 base_packet_event_proto = *it; | |
| 107 break; | |
| 108 } | |
| 109 } | |
| 110 if (!base_packet_event_proto) { | |
| 111 base_packet_event_proto = event_proto->add_base_packet_event(); | |
| 112 base_packet_event_proto->set_packet_id(packet_event.packet_id); | |
| 113 } | |
| 114 } | 165 } |
| 115 | |
| 116 base_packet_event_proto->add_event_type( | |
| 117 ToProtoEventType(packet_event.type)); | |
| 118 base_packet_event_proto->add_event_timestamp_ms( | |
| 119 (packet_event.timestamp - base::TimeTicks()).InMilliseconds()); | |
| 120 | |
| 121 TruncatePacketEventMapIfNeeded(); | |
| 122 } | 166 } |
| 123 | 167 |
| 124 DCHECK(packet_event_map_.size() <= max_frames_); | 168 base_packet_event_proto->add_event_type( |
| 169 ToProtoEventType(packet_event.type)); |
| 170 base_packet_event_proto->add_event_timestamp_ms( |
| 171 (packet_event.timestamp - base::TimeTicks()).InMilliseconds()); |
| 172 |
| 173 if (packet_event_map_.size() > kMaxMapSize) |
| 174 TransferPacketEvents(kNumMapEntriesToTransfer); |
| 175 |
| 176 DCHECK(packet_event_map_.size() <= kMaxMapSize); |
| 177 DCHECK(packet_event_storage_.size() <= max_frames_); |
| 125 } | 178 } |
| 126 | 179 |
| 127 void EncodingEventSubscriber::GetEventsAndReset(LogMetadata* metadata, | 180 void EncodingEventSubscriber::GetEventsAndReset(LogMetadata* metadata, |
| 128 FrameEventMap* frame_events, | 181 FrameEventList* frame_events, PacketEventList* packet_events) { |
| 129 PacketEventMap* packet_events) { | |
| 130 DCHECK(thread_checker_.CalledOnValidThread()); | 182 DCHECK(thread_checker_.CalledOnValidThread()); |
| 131 | 183 |
| 184 // Flush all events. |
| 185 TransferFrameEvents(frame_event_map_.size()); |
| 186 TransferPacketEvents(packet_event_map_.size()); |
| 187 std::sort(frame_event_storage_.begin(), frame_event_storage_.end(), |
| 188 &IsRtpTimestampLessThan<linked_ptr<AggregatedFrameEvent> >); |
| 189 std::sort(packet_event_storage_.begin(), packet_event_storage_.end(), |
| 190 &IsRtpTimestampLessThan<linked_ptr<AggregatedPacketEvent> >); |
| 191 |
| 132 metadata->set_is_audio(event_media_type_ == AUDIO_EVENT); | 192 metadata->set_is_audio(event_media_type_ == AUDIO_EVENT); |
| 133 metadata->set_first_rtp_timestamp(first_rtp_timestamp_); | 193 metadata->set_first_rtp_timestamp(first_rtp_timestamp_); |
| 134 metadata->set_num_frame_events(frame_event_map_.size()); | 194 metadata->set_num_frame_events(frame_event_storage_.size()); |
| 135 metadata->set_num_packet_events(packet_event_map_.size()); | 195 metadata->set_num_packet_events(packet_event_storage_.size()); |
| 136 metadata->set_reference_timestamp_ms_at_unix_epoch( | 196 metadata->set_reference_timestamp_ms_at_unix_epoch( |
| 137 (base::TimeTicks::UnixEpoch() - base::TimeTicks()).InMilliseconds()); | 197 (base::TimeTicks::UnixEpoch() - base::TimeTicks()).InMilliseconds()); |
| 138 frame_events->swap(frame_event_map_); | 198 frame_events->swap(frame_event_storage_); |
| 139 packet_events->swap(packet_event_map_); | 199 packet_events->swap(packet_event_storage_); |
| 140 Reset(); | 200 Reset(); |
| 141 } | 201 } |
| 142 | 202 |
| 143 bool EncodingEventSubscriber::ShouldProcessEvent(CastLoggingEvent event) { | 203 bool EncodingEventSubscriber::ShouldProcessEvent(CastLoggingEvent event) { |
| 144 return GetEventMediaType(event) == event_media_type_; | 204 return GetEventMediaType(event) == event_media_type_; |
| 145 } | 205 } |
| 146 | 206 |
| 147 void EncodingEventSubscriber::TruncateFrameEventMapIfNeeded() { | 207 void EncodingEventSubscriber::TransferFrameEvents(size_t max_num_entries) { |
| 148 // This works because this is called everytime an event is inserted and | 208 DCHECK(frame_event_map_.size() >= max_num_entries); |
| 149 // we only insert events one at a time. | 209 |
| 150 if (frame_event_map_.size() > max_frames_) | 210 FrameEventMap::iterator it = frame_event_map_.begin(); |
| 151 frame_event_map_.erase(frame_event_map_.begin()); | 211 for (size_t i = 0; |
| 212 i < max_num_entries && it != frame_event_map_.end(); |
| 213 i++, ++it) { |
| 214 AddFrameEventToStorage(it->second); |
| 215 } |
| 216 |
| 217 frame_event_map_.erase(frame_event_map_.begin(), it); |
| 152 } | 218 } |
| 153 | 219 |
| 154 void EncodingEventSubscriber::TruncatePacketEventMapIfNeeded() { | 220 void EncodingEventSubscriber::TransferPacketEvents(size_t max_num_entries) { |
| 155 // This works because this is called everytime an event is inserted and | 221 PacketEventMap::iterator it = packet_event_map_.begin(); |
| 156 // we only insert events one at a time. | 222 for (size_t i = 0; |
| 157 if (packet_event_map_.size() > max_frames_) | 223 i < max_num_entries && it != packet_event_map_.end(); |
| 158 packet_event_map_.erase(packet_event_map_.begin()); | 224 i++, ++it) { |
| 225 AddPacketEventToStorage(it->second); |
| 226 } |
| 227 |
| 228 packet_event_map_.erase(packet_event_map_.begin(), it); |
| 229 } |
| 230 |
| 231 void EncodingEventSubscriber::AddFrameEventToStorage( |
| 232 const linked_ptr<AggregatedFrameEvent>& frame_event_proto) { |
| 233 if (frame_event_storage_.size() >= max_frames_) { |
| 234 frame_event_storage_[frame_event_storage_index_] = frame_event_proto; |
| 235 } else { |
| 236 frame_event_storage_.push_back(frame_event_proto); |
| 237 } |
| 238 |
| 239 frame_event_storage_index_ = (frame_event_storage_index_ + 1) % max_frames_; |
| 240 } |
| 241 |
| 242 void EncodingEventSubscriber::AddPacketEventToStorage( |
| 243 const linked_ptr<AggregatedPacketEvent>& packet_event_proto) { |
| 244 if (packet_event_storage_.size() >= max_frames_) |
| 245 packet_event_storage_[packet_event_storage_index_] = packet_event_proto; |
| 246 else |
| 247 packet_event_storage_.push_back(packet_event_proto); |
| 248 |
| 249 packet_event_storage_index_ = (packet_event_storage_index_ + 1) % max_frames_; |
| 159 } | 250 } |
| 160 | 251 |
| 161 RtpTimestamp EncodingEventSubscriber::GetRelativeRtpTimestamp( | 252 RtpTimestamp EncodingEventSubscriber::GetRelativeRtpTimestamp( |
| 162 RtpTimestamp rtp_timestamp) { | 253 RtpTimestamp rtp_timestamp) { |
| 163 if (!seen_first_rtp_timestamp_) { | 254 if (!seen_first_rtp_timestamp_) { |
| 164 seen_first_rtp_timestamp_ = true; | 255 seen_first_rtp_timestamp_ = true; |
| 165 first_rtp_timestamp_ = rtp_timestamp; | 256 first_rtp_timestamp_ = rtp_timestamp; |
| 166 } | 257 } |
| 167 | 258 |
| 168 return rtp_timestamp - first_rtp_timestamp_; | 259 return rtp_timestamp - first_rtp_timestamp_; |
| 169 } | 260 } |
| 170 | 261 |
| 171 void EncodingEventSubscriber::Reset() { | 262 void EncodingEventSubscriber::Reset() { |
| 172 frame_event_map_.clear(); | 263 frame_event_map_.clear(); |
| 264 frame_event_storage_.clear(); |
| 265 frame_event_storage_index_ = 0; |
| 173 packet_event_map_.clear(); | 266 packet_event_map_.clear(); |
| 267 packet_event_storage_.clear(); |
| 268 packet_event_storage_index_ = 0; |
| 174 seen_first_rtp_timestamp_ = false; | 269 seen_first_rtp_timestamp_ = false; |
| 175 first_rtp_timestamp_ = 0u; | 270 first_rtp_timestamp_ = 0u; |
| 176 } | 271 } |
| 177 | 272 |
| 178 } // namespace cast | 273 } // namespace cast |
| 179 } // namespace media | 274 } // namespace media |
| OLD | NEW |