Original cl description: This removes the none const pointer entry and SwapFrame. Since frames delivered using VideoSendStream no longer use the external capture module, VideoSendStream will not get an incoming framerate callback. VideoSendStream now uses a rtc::RateTracker. Also, the video engine must ensure that time stamps are always increasing. With this, time stamps (ntp, render_time and rtp timestamps ) are checked and set in ViECapturer::OnIncomingCapturedFrame This cl was previously reverted in https://webrtc-codereview.appspot.com/46549004/. Patchset 1 contains the original patch after rebase. Patshet 2 fix webrtc_perf_tests reported in chromium:465306 Note that chromium:465287 is being fixed in https://webrtc-codereview.appspot.com/43829004/ BUG=1128 R=magjed@webrtc.org, mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/47629004 Cr-Commit-Position: refs/heads/master@{#8776} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8776 4adac7df-926f-26a2-2b94-8c16560cd09d
195 lines
6.3 KiB
C++
195 lines
6.3 KiB
C++
/*
|
|
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "webrtc/video/send_statistics_proxy.h"
|
|
|
|
#include <map>
|
|
|
|
#include "webrtc/base/checks.h"
|
|
|
|
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
|
#include "webrtc/system_wrappers/interface/logging.h"
|
|
|
|
namespace webrtc {
|
|
|
|
const int SendStatisticsProxy::kStatsTimeoutMs = 5000;
|
|
|
|
SendStatisticsProxy::SendStatisticsProxy(Clock* clock,
|
|
const VideoSendStream::Config& config)
|
|
: clock_(clock),
|
|
config_(config),
|
|
crit_(CriticalSectionWrapper::CreateCriticalSection()) {
|
|
}
|
|
|
|
SendStatisticsProxy::~SendStatisticsProxy() {}
|
|
|
|
void SendStatisticsProxy::OutgoingRate(const int video_channel,
|
|
const unsigned int framerate,
|
|
const unsigned int bitrate) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
stats_.encode_frame_rate = framerate;
|
|
stats_.media_bitrate_bps = bitrate;
|
|
}
|
|
|
|
void SendStatisticsProxy::CpuOveruseMetricsUpdated(
|
|
const CpuOveruseMetrics& metrics) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
stats_.avg_encode_time_ms = metrics.avg_encode_time_ms;
|
|
stats_.encode_usage_percent = metrics.encode_usage_percent;
|
|
}
|
|
|
|
void SendStatisticsProxy::SuspendChange(int video_channel, bool is_suspended) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
stats_.suspended = is_suspended;
|
|
}
|
|
|
|
VideoSendStream::Stats SendStatisticsProxy::GetStats() {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
PurgeOldStats();
|
|
stats_.input_frame_rate =
|
|
static_cast<int>(input_frame_rate_tracker_.units_second());
|
|
return stats_;
|
|
}
|
|
|
|
void SendStatisticsProxy::PurgeOldStats() {
|
|
int64_t current_time_ms = clock_->TimeInMilliseconds();
|
|
for (std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
|
|
stats_.substreams.begin();
|
|
it != stats_.substreams.end(); ++it) {
|
|
uint32_t ssrc = it->first;
|
|
if (update_times_[ssrc].resolution_update_ms + kStatsTimeoutMs >
|
|
current_time_ms)
|
|
continue;
|
|
|
|
it->second.width = 0;
|
|
it->second.height = 0;
|
|
}
|
|
}
|
|
|
|
VideoSendStream::StreamStats* SendStatisticsProxy::GetStatsEntry(
|
|
uint32_t ssrc) {
|
|
std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
|
|
stats_.substreams.find(ssrc);
|
|
if (it != stats_.substreams.end())
|
|
return &it->second;
|
|
|
|
if (std::find(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end(), ssrc) ==
|
|
config_.rtp.ssrcs.end() &&
|
|
std::find(config_.rtp.rtx.ssrcs.begin(),
|
|
config_.rtp.rtx.ssrcs.end(),
|
|
ssrc) == config_.rtp.rtx.ssrcs.end()) {
|
|
return NULL;
|
|
}
|
|
|
|
return &stats_.substreams[ssrc]; // Insert new entry and return ptr.
|
|
}
|
|
|
|
void SendStatisticsProxy::OnSetRates(uint32_t bitrate_bps, int framerate) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
stats_.target_media_bitrate_bps = bitrate_bps;
|
|
}
|
|
|
|
void SendStatisticsProxy::OnSendEncodedImage(
|
|
const EncodedImage& encoded_image,
|
|
const RTPVideoHeader* rtp_video_header) {
|
|
size_t simulcast_idx =
|
|
rtp_video_header != NULL ? rtp_video_header->simulcastIdx : 0;
|
|
if (simulcast_idx >= config_.rtp.ssrcs.size()) {
|
|
LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx
|
|
<< " >= " << config_.rtp.ssrcs.size() << ").";
|
|
return;
|
|
}
|
|
uint32_t ssrc = config_.rtp.ssrcs[simulcast_idx];
|
|
|
|
CriticalSectionScoped lock(crit_.get());
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
|
if (stats == NULL)
|
|
return;
|
|
|
|
stats->width = encoded_image._encodedWidth;
|
|
stats->height = encoded_image._encodedHeight;
|
|
update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
|
|
}
|
|
|
|
void SendStatisticsProxy::OnIncomingFrame() {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
input_frame_rate_tracker_.Update(1);
|
|
}
|
|
|
|
void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
|
|
uint32_t ssrc,
|
|
const RtcpPacketTypeCounter& packet_counter) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
|
if (stats == NULL)
|
|
return;
|
|
|
|
stats->rtcp_packet_type_counts = packet_counter;
|
|
}
|
|
|
|
void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
|
|
uint32_t ssrc) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
|
if (stats == NULL)
|
|
return;
|
|
|
|
stats->rtcp_stats = statistics;
|
|
}
|
|
|
|
void SendStatisticsProxy::CNameChanged(const char* cname, uint32_t ssrc) {
|
|
}
|
|
|
|
void SendStatisticsProxy::DataCountersUpdated(
|
|
const StreamDataCounters& counters,
|
|
uint32_t ssrc) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
|
DCHECK(stats != NULL) << "DataCountersUpdated reported for unknown ssrc: "
|
|
<< ssrc;
|
|
|
|
stats->rtp_stats = counters;
|
|
}
|
|
|
|
void SendStatisticsProxy::Notify(const BitrateStatistics& total_stats,
|
|
const BitrateStatistics& retransmit_stats,
|
|
uint32_t ssrc) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
|
if (stats == NULL)
|
|
return;
|
|
|
|
stats->total_bitrate_bps = total_stats.bitrate_bps;
|
|
stats->retransmit_bitrate_bps = retransmit_stats.bitrate_bps;
|
|
}
|
|
|
|
void SendStatisticsProxy::FrameCountUpdated(const FrameCounts& frame_counts,
|
|
uint32_t ssrc) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
|
if (stats == NULL)
|
|
return;
|
|
|
|
stats->frame_counts = frame_counts;
|
|
}
|
|
|
|
void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
|
|
int max_delay_ms,
|
|
uint32_t ssrc) {
|
|
CriticalSectionScoped lock(crit_.get());
|
|
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
|
if (stats == NULL)
|
|
return;
|
|
stats->avg_delay_ms = avg_delay_ms;
|
|
stats->max_delay_ms = max_delay_ms;
|
|
}
|
|
|
|
} // namespace webrtc
|