blob: 05bcf3b7a86380b33a32a51b386a34be32152124 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/cast/rtcp/sender_rtcp_event_subscriber.h"
#include <utility>
#include "base/logging.h"
#include "media/cast/rtcp/rtcp_defines.h"
namespace media {
namespace cast {
SenderRtcpEventSubscriber::SenderRtcpEventSubscriber(
const size_t max_size_to_retain)
: max_size_to_retain_(max_size_to_retain) {
DCHECK(max_size_to_retain_ > 0u);
}
SenderRtcpEventSubscriber::~SenderRtcpEventSubscriber() {
DCHECK(thread_checker_.CalledOnValidThread());
}
void SenderRtcpEventSubscriber::OnReceiveFrameEvent(
const FrameEvent& frame_event) {
DCHECK(thread_checker_.CalledOnValidThread());
if (frame_event.type != kVideoFrameCaptureBegin &&
frame_event.type != kVideoFrameSentToEncoder &&
frame_event.type != kVideoFrameEncoded) {
// Not interested in other events.
return;
}
RtcpEventMap::iterator it = rtcp_events_.find(frame_event.rtp_timestamp);
if (it == rtcp_events_.end()) {
// We have not stored this frame (RTP timestamp) in our map.
RtcpEvent rtcp_event;
rtcp_event.type = frame_event.type;
rtcp_event.timestamp = frame_event.timestamp;
// Do not need to fill out rtcp_event.delay_delta or rtcp_event.packet_id
// as they are not set in frame events we are interested in.
rtcp_events_.insert(std::make_pair(frame_event.rtp_timestamp, rtcp_event));
TruncateMapIfNeeded();
} else {
// We already have this frame (RTP timestamp) in our map.
// Only update events that are later in the chain.
// This is due to that events can be reordered on the wire.
if (frame_event.type == kVideoFrameCaptureBegin) {
return; // First event in chain can not be late by definition.
}
if (it->second.type == kVideoFrameEncoded) {
return; // Last event in chain should not be updated.
}
// Update existing entry.
it->second.type = frame_event.type;
}
DCHECK(rtcp_events_.size() <= max_size_to_retain_);
}
void SenderRtcpEventSubscriber::OnReceivePacketEvent(
const PacketEvent& packet_event) {
DCHECK(thread_checker_.CalledOnValidThread());
// Do nothing as RTP sender is not interested in packet events for RTCP.
}
void SenderRtcpEventSubscriber::GetRtcpEventsAndReset(
RtcpEventMap* rtcp_events) {
DCHECK(thread_checker_.CalledOnValidThread());
rtcp_events->swap(rtcp_events_);
rtcp_events_.clear();
}
void SenderRtcpEventSubscriber::TruncateMapIfNeeded() {
// If map size has exceeded |max_size_to_retain_|, remove entry with
// the smallest RTP timestamp.
if (rtcp_events_.size() > max_size_to_retain_) {
DVLOG(2) << "RTCP event map exceeded size limit; "
<< "removing oldest entry";
// This is fine since we only insert elements one at a time.
rtcp_events_.erase(rtcp_events_.begin());
}
}
} // namespace cast
} // namespace media