Wire up statistics in video send stream of new video engine api

Note, this CL does not contain any tests. Those are implemeted as call
tests and will be submitted when the receive stream is wired up as well.

BUG=2235
R=mflodman@webrtc.org, pbos@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/5559006

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5344 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
sprang@webrtc.org 2014-01-07 09:54:34 +00:00
parent 0b7d8e6fcb
commit ccd42840bc
13 changed files with 575 additions and 45 deletions

View File

@ -246,6 +246,13 @@ struct RtcpStatistics {
uint32_t cumulative_lost;
uint32_t extended_max_sequence_number;
uint32_t jitter;
bool operator==(const RtcpStatistics& other) const {
return fraction_lost == other.fraction_lost &&
cumulative_lost == other.cumulative_lost &&
extended_max_sequence_number == other.extended_max_sequence_number &&
jitter == other.jitter;
}
};
// Callback, called whenever a new rtcp report block is transmitted.
@ -273,6 +280,13 @@ struct StreamDataCounters {
uint32_t packets; // Number of packets.
uint32_t retransmitted_packets; // Number of retransmitted packets.
uint32_t fec_packets; // Number of redundancy packets.
bool operator==(const StreamDataCounters& other) const {
return bytes == other.bytes && header_bytes == other.header_bytes &&
padding_bytes == other.padding_bytes && packets == other.packets &&
retransmitted_packets == other.retransmitted_packets &&
fec_packets == other.fec_packets;
}
};
// Callback, called whenever byte/packet counts have been updated.

View File

@ -16,6 +16,7 @@
#include <string>
#include <vector>
#include "webrtc/common_types.h"
#include "webrtc/typedefs.h"
namespace webrtc {
@ -33,6 +34,22 @@ struct RtpStatistics {
std::string c_name;
};
struct StreamStats {
StreamStats() : key_frames(0), delta_frames(0), bitrate_bps(0) {}
uint32_t key_frames;
uint32_t delta_frames;
int32_t bitrate_bps;
StreamDataCounters rtp_stats;
RtcpStatistics rtcp_stats;
bool operator==(const StreamStats& other) const {
return key_frames == other.key_frames &&
delta_frames == other.delta_frames &&
bitrate_bps == other.bitrate_bps && rtp_stats == other.rtp_stats &&
rtcp_stats == other.rtcp_stats;
}
};
// Settings for NACK, see RFC 4585 for details.
struct NackConfig {
NackConfig() : rtp_history_ms(0) {}

View File

@ -0,0 +1,114 @@
/*
* 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/system_wrappers/interface/critical_section_wrapper.h"
namespace webrtc {
SendStatisticsProxy::SendStatisticsProxy(
const VideoSendStream::Config& config,
SendStatisticsProxy::StreamStatsProvider* stats_provider)
: config_(config),
lock_(CriticalSectionWrapper::CreateCriticalSection()),
stats_provider_(stats_provider) {}
SendStatisticsProxy::~SendStatisticsProxy() {}
void SendStatisticsProxy::OutgoingRate(const int video_channel,
const unsigned int framerate,
const unsigned int bitrate) {
CriticalSectionScoped cs(lock_.get());
stats_.encode_frame_rate = framerate;
}
void SendStatisticsProxy::CapturedFrameRate(const int capture_id,
const unsigned char frame_rate) {
CriticalSectionScoped cs(lock_.get());
stats_.input_frame_rate = frame_rate;
}
VideoSendStream::Stats SendStatisticsProxy::GetStats() const {
VideoSendStream::Stats stats = stats_;
CriticalSectionScoped cs(lock_.get());
stats_provider_->GetSendSideDelay(&stats);
stats.c_name = stats_provider_->GetCName();
return stats;
}
StreamStats* SendStatisticsProxy::GetStatsEntry(uint32_t ssrc) {
std::map<uint32_t, 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())
return NULL;
return &stats_.substreams[ssrc]; // Insert new entry and return ptr.
}
void SendStatisticsProxy::StatisticsUpdated(const RtcpStatistics& statistics,
uint32_t ssrc) {
CriticalSectionScoped cs(lock_.get());
StreamStats* stats = GetStatsEntry(ssrc);
if (stats == NULL)
return;
stats->rtcp_stats = statistics;
}
void SendStatisticsProxy::DataCountersUpdated(
const StreamDataCounters& counters,
uint32_t ssrc) {
CriticalSectionScoped cs(lock_.get());
StreamStats* stats = GetStatsEntry(ssrc);
if (stats == NULL)
return;
stats->rtp_stats = counters;
}
void SendStatisticsProxy::Notify(const BitrateStatistics& bitrate,
uint32_t ssrc) {
CriticalSectionScoped cs(lock_.get());
StreamStats* stats = GetStatsEntry(ssrc);
if (stats == NULL)
return;
stats->bitrate_bps = bitrate.bitrate_bps;
}
void SendStatisticsProxy::FrameCountUpdated(FrameType frame_type,
uint32_t frame_count,
const unsigned int ssrc) {
CriticalSectionScoped cs(lock_.get());
StreamStats* stats = GetStatsEntry(ssrc);
if (stats == NULL)
return;
switch (frame_type) {
case kVideoFrameDelta:
stats->delta_frames = frame_count;
break;
case kVideoFrameKey:
stats->key_frames = frame_count;
break;
case kFrameEmpty:
case kAudioFrameSpeech:
case kAudioFrameCN:
break;
}
}
} // namespace webrtc

View File

@ -0,0 +1,91 @@
/*
* 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.
*/
#ifndef WEBRTC_VIDEO_SEND_STATISTICS_PROXY_H_
#define WEBRTC_VIDEO_SEND_STATISTICS_PROXY_H_
#include <string>
#include "webrtc/common_types.h"
#include "webrtc/video_engine/include/vie_codec.h"
#include "webrtc/video_engine/include/vie_capture.h"
#include "webrtc/video_send_stream.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
namespace webrtc {
class CriticalSectionWrapper;
class SendStatisticsProxy : public RtcpStatisticsCallback,
public StreamDataCountersCallback,
public BitrateStatisticsObserver,
public FrameCountObserver,
public ViEEncoderObserver,
public ViECaptureObserver {
public:
class StreamStatsProvider {
public:
StreamStatsProvider() {}
virtual ~StreamStatsProvider() {}
virtual bool GetSendSideDelay(VideoSendStream::Stats* stats) = 0;
virtual std::string GetCName() = 0;
};
SendStatisticsProxy(const VideoSendStream::Config& config,
StreamStatsProvider* stats_provider);
virtual ~SendStatisticsProxy();
VideoSendStream::Stats GetStats() const;
protected:
// From RtcpStatisticsCallback.
virtual void StatisticsUpdated(const RtcpStatistics& statistics,
uint32_t ssrc) OVERRIDE;
// From StreamDataCountersCallback.
virtual void DataCountersUpdated(const StreamDataCounters& counters,
uint32_t ssrc) OVERRIDE;
// From BitrateStatisticsObserver.
virtual void Notify(const BitrateStatistics& stats, uint32_t ssrc) OVERRIDE;
// From FrameCountObserver.
virtual void FrameCountUpdated(FrameType frame_type,
uint32_t frame_count,
const unsigned int ssrc) OVERRIDE;
// From ViEEncoderObserver.
virtual void OutgoingRate(const int video_channel,
const unsigned int framerate,
const unsigned int bitrate) OVERRIDE;
virtual void SuspendChange(int video_channel, bool is_suspended) OVERRIDE {}
// From ViECaptureObserver.
virtual void BrightnessAlarm(const int capture_id,
const Brightness brightness) OVERRIDE {}
virtual void CapturedFrameRate(const int capture_id,
const unsigned char frame_rate) OVERRIDE;
virtual void NoPictureAlarm(const int capture_id,
const CaptureAlarm alarm) OVERRIDE {}
private:
StreamStats* GetStatsEntry(uint32_t ssrc);
const VideoSendStream::Config config_;
scoped_ptr<CriticalSectionWrapper> lock_;
VideoSendStream::Stats stats_;
StreamStatsProvider* stats_provider_;
};
} // namespace webrtc
#endif // WEBRTC_VIDEO_SEND_STATISTICS_PROXY_H_

View File

@ -0,0 +1,191 @@
/*
* 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.
*/
// This file includes unit tests for SendStatisticsProxy.
#include "webrtc/video/send_statistics_proxy.h"
#include <map>
#include <string>
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
namespace webrtc {
class SendStatisticsProxyTest
: public ::testing::Test,
protected SendStatisticsProxy::StreamStatsProvider {
public:
SendStatisticsProxyTest() : avg_delay_ms_(0), max_delay_ms_(0) {}
virtual ~SendStatisticsProxyTest() {}
protected:
virtual void SetUp() {
statistics_proxy_.reset(
new SendStatisticsProxy(GetTestConfig(), this));
config_ = GetTestConfig();
expected_ = VideoSendStream::Stats();
}
VideoSendStream::Config GetTestConfig() {
VideoSendStream::Config config;
config.rtp.ssrcs.push_back(17);
config.rtp.ssrcs.push_back(42);
return config;
}
virtual bool GetSendSideDelay(VideoSendStream::Stats* stats) OVERRIDE {
stats->avg_delay_ms = avg_delay_ms_;
stats->max_delay_ms = max_delay_ms_;
return true;
}
virtual std::string GetCName() { return cname_; }
scoped_ptr<SendStatisticsProxy> statistics_proxy_;
VideoSendStream::Config config_;
int avg_delay_ms_;
int max_delay_ms_;
std::string cname_;
VideoSendStream::Stats expected_;
typedef std::map<uint32_t, StreamStats>::const_iterator StreamIterator;
};
TEST_F(SendStatisticsProxyTest, RtcpStatistics) {
RtcpStatisticsCallback* callback = statistics_proxy_.get();
for (std::vector<uint32_t>::const_iterator it = config_.rtp.ssrcs.begin();
it != config_.rtp.ssrcs.end();
++it) {
const uint32_t ssrc = *it;
StreamStats& ssrc_stats = expected_.substreams[ssrc];
// Add statistics with some arbitrary, but unique, numbers.
uint32_t offset = ssrc * sizeof(RtcpStatistics);
ssrc_stats.rtcp_stats.cumulative_lost = offset;
ssrc_stats.rtcp_stats.extended_max_sequence_number = offset + 1;
ssrc_stats.rtcp_stats.fraction_lost = offset + 2;
ssrc_stats.rtcp_stats.jitter = offset + 3;
callback->StatisticsUpdated(ssrc_stats.rtcp_stats, ssrc);
}
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
EXPECT_EQ(expected_, stats);
}
TEST_F(SendStatisticsProxyTest, FrameRates) {
const int capture_fps = 31;
const int encode_fps = 29;
ViECaptureObserver* capture_observer = statistics_proxy_.get();
capture_observer->CapturedFrameRate(0, capture_fps);
ViEEncoderObserver* encoder_observer = statistics_proxy_.get();
encoder_observer->OutgoingRate(0, encode_fps, 0);
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
EXPECT_EQ(capture_fps, stats.input_frame_rate);
EXPECT_EQ(encode_fps, stats.encode_frame_rate);
}
TEST_F(SendStatisticsProxyTest, FrameCounts) {
FrameCountObserver* observer = statistics_proxy_.get();
for (std::vector<uint32_t>::const_iterator it = config_.rtp.ssrcs.begin();
it != config_.rtp.ssrcs.end();
++it) {
const uint32_t ssrc = *it;
// Add statistics with some arbitrary, but unique, numbers.
StreamStats& stats = expected_.substreams[ssrc];
uint32_t offset = ssrc * sizeof(StreamStats);
stats.key_frames = offset;
stats.delta_frames = offset + 1;
observer->FrameCountUpdated(kVideoFrameKey, stats.key_frames, ssrc);
observer->FrameCountUpdated(kVideoFrameDelta, stats.delta_frames, ssrc);
}
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
EXPECT_EQ(expected_, stats);
}
TEST_F(SendStatisticsProxyTest, DataCounters) {
StreamDataCountersCallback* callback = statistics_proxy_.get();
for (std::vector<uint32_t>::const_iterator it = config_.rtp.ssrcs.begin();
it != config_.rtp.ssrcs.end();
++it) {
const uint32_t ssrc = *it;
StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
// Add statistics with some arbitrary, but unique, numbers.
uint32_t offset = ssrc * sizeof(StreamDataCounters);
counters.bytes = offset;
counters.header_bytes = offset + 1;
counters.fec_packets = offset + 2;
counters.padding_bytes = offset + 3;
counters.retransmitted_packets = offset + 4;
counters.packets = offset + 5;
callback->DataCountersUpdated(counters, ssrc);
}
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
EXPECT_EQ(expected_, stats);
}
TEST_F(SendStatisticsProxyTest, Bitrate) {
BitrateStatisticsObserver* observer = statistics_proxy_.get();
for (std::vector<uint32_t>::const_iterator it = config_.rtp.ssrcs.begin();
it != config_.rtp.ssrcs.end();
++it) {
const uint32_t ssrc = *it;
BitrateStatistics bitrate;
bitrate.bitrate_bps = ssrc;
observer->Notify(bitrate, ssrc);
expected_.substreams[ssrc].bitrate_bps = ssrc;
}
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
EXPECT_EQ(expected_, stats);
}
TEST_F(SendStatisticsProxyTest, StreamStats) {
avg_delay_ms_ = 1;
max_delay_ms_ = 2;
cname_ = "qwertyuiop";
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
EXPECT_EQ(avg_delay_ms_, stats.avg_delay_ms);
EXPECT_EQ(max_delay_ms_, stats.max_delay_ms);
EXPECT_EQ(cname_, stats.c_name);
}
TEST_F(SendStatisticsProxyTest, NoSubstreams) {
uint32_t exluded_ssrc =
*std::max_element(config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end()) + 1;
// From RtcpStatisticsCallback.
RtcpStatistics rtcp_stats;
RtcpStatisticsCallback* rtcp_callback = statistics_proxy_.get();
rtcp_callback->StatisticsUpdated(rtcp_stats, exluded_ssrc);
// From StreamDataCountersCallback.
StreamDataCounters rtp_stats;
StreamDataCountersCallback* rtp_callback = statistics_proxy_.get();
rtp_callback->DataCountersUpdated(rtp_stats, exluded_ssrc);
// From BitrateStatisticsObserver.
BitrateStatistics bitrate;
BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
bitrate_observer->Notify(bitrate, exluded_ssrc);
// From FrameCountObserver.
FrameCountObserver* fps_observer = statistics_proxy_.get();
fps_observer->FrameCountUpdated(kVideoFrameKey, 1, exluded_ssrc);
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
EXPECT_TRUE(stats.substreams.empty());
}
} // namespace webrtc

View File

@ -186,9 +186,32 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
if (config.suspend_below_min_bitrate) {
codec_->SuspendBelowMinBitrate(channel_);
}
stats_proxy_.reset(
new SendStatisticsProxy(config, this));
rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(channel_,
stats_proxy_.get());
rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(channel_,
stats_proxy_.get());
rtp_rtcp_->RegisterSendBitrateObserver(channel_, stats_proxy_.get());
rtp_rtcp_->RegisterSendFrameCountObserver(channel_, stats_proxy_.get());
codec_->RegisterEncoderObserver(channel_, *stats_proxy_);
capture_->RegisterObserver(capture_id_, *stats_proxy_);
}
VideoSendStream::~VideoSendStream() {
capture_->DeregisterObserver(capture_id_);
codec_->DeregisterEncoderObserver(channel_);
rtp_rtcp_->DeregisterSendFrameCountObserver(channel_, stats_proxy_.get());
rtp_rtcp_->DeregisterSendBitrateObserver(channel_, stats_proxy_.get());
rtp_rtcp_->DeregisterSendChannelRtpStatisticsCallback(channel_,
stats_proxy_.get());
rtp_rtcp_->DeregisterSendChannelRtcpStatisticsCallback(channel_,
stats_proxy_.get());
image_process_->DeRegisterPreEncodeCallback(channel_);
network_->DeregisterSendTransport(channel_);
@ -293,5 +316,21 @@ bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
return network_->ReceivedRTCPPacket(
channel_, packet, static_cast<int>(length)) == 0;
}
VideoSendStream::Stats VideoSendStream::GetStats() const {
return stats_proxy_->GetStats();
}
bool VideoSendStream::GetSendSideDelay(VideoSendStream::Stats* stats) {
return codec_->GetSendSideDelay(
channel_, &stats->avg_delay_ms, &stats->max_delay_ms);
}
std::string VideoSendStream::GetCName() {
char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength];
rtp_rtcp_->GetRTCPCName(channel_, rtcp_cname);
return rtcp_cname;
}
} // namespace internal
} // namespace webrtc

View File

@ -11,10 +11,9 @@
#ifndef WEBRTC_VIDEO_VIDEO_SEND_STREAM_H_
#define WEBRTC_VIDEO_VIDEO_SEND_STREAM_H_
#include <vector>
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/video/encoded_frame_callback_adapter.h"
#include "webrtc/video/send_statistics_proxy.h"
#include "webrtc/video/transport_adapter.h"
#include "webrtc/video_receive_stream.h"
#include "webrtc/video_send_stream.h"
@ -37,7 +36,8 @@ namespace internal {
class ResolutionAdaptor;
class VideoSendStream : public webrtc::VideoSendStream,
public VideoSendStreamInput {
public VideoSendStreamInput,
public SendStatisticsProxy::StreamStatsProvider {
public:
VideoSendStream(newapi::Transport* transport,
bool overuse_detection,
@ -47,12 +47,6 @@ class VideoSendStream : public webrtc::VideoSendStream,
virtual ~VideoSendStream();
virtual void PutFrame(const I420VideoFrame& frame) OVERRIDE;
virtual void SwapFrame(I420VideoFrame* frame) OVERRIDE;
virtual VideoSendStreamInput* Input() OVERRIDE;
virtual void StartSending() OVERRIDE;
virtual void StopSending() OVERRIDE;
@ -60,9 +54,22 @@ class VideoSendStream : public webrtc::VideoSendStream,
virtual bool SetCodec(const VideoCodec& codec) OVERRIDE;
virtual VideoCodec GetCodec() OVERRIDE;
public:
virtual Stats GetStats() const OVERRIDE;
bool DeliverRtcp(const uint8_t* packet, size_t length);
// From VideoSendStreamInput.
virtual void PutFrame(const I420VideoFrame& frame) OVERRIDE;
virtual void SwapFrame(I420VideoFrame* frame) OVERRIDE;
// From webrtc::VideoSendStream.
virtual VideoSendStreamInput* Input() OVERRIDE;
protected:
// From SendStatisticsProxy::StreamStatsProvider.
virtual bool GetSendSideDelay(VideoSendStream::Stats* stats) OVERRIDE;
virtual std::string GetCName() OVERRIDE;
private:
I420VideoFrame input_frame_;
TransportAdapter transport_adapter_;
@ -82,6 +89,8 @@ class VideoSendStream : public webrtc::VideoSendStream,
int channel_;
int capture_id_;
scoped_ptr<ResolutionAdaptor> overuse_observer_;
scoped_ptr<SendStatisticsProxy> stats_proxy_;
};
} // namespace internal
} // namespace webrtc

View File

@ -35,7 +35,8 @@ namespace webrtc {
class VideoSendStreamTest : public ::testing::Test {
public:
VideoSendStreamTest() : fake_encoder_(Clock::GetRealTimeClock()) {}
VideoSendStreamTest()
: send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
protected:
void RunSendTest(Call* call,
@ -190,7 +191,7 @@ void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs,
frame_generator_capturer->Stop();
send_stream_->StopSending();
call->DestroyVideoSendStream(send_stream_);
};
}
TEST_F(VideoSendStreamTest, SendsSetSsrc) { SendsSetSsrcs(1, false); }
@ -936,4 +937,64 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
call->DestroyVideoSendStream(send_stream_);
}
TEST_F(VideoSendStreamTest, ProducesStats) {
static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
class StatsObserver : public test::RtpRtcpObserver {
public:
StatsObserver() : RtpRtcpObserver(30 * 1000), stream_(NULL) {}
virtual Action OnSendRtcp(const uint8_t* packet, size_t length) OVERRIDE {
VideoSendStream::Stats stats = stream_->GetStats();
// Check that all applicable data sources have been used.
if (stats.input_frame_rate > 0 && stats.encode_frame_rate > 0 &&
stats.avg_delay_ms > 0 && stats.c_name == kCName &&
!stats.substreams.empty()) {
uint32_t ssrc = stats.substreams.begin()->first;
EXPECT_NE(
config_.rtp.ssrcs.end(),
std::find(
config_.rtp.ssrcs.begin(), config_.rtp.ssrcs.end(), ssrc));
// Check for data populated by various sources. RTCP excluded as this
// data is received from remote side. Tested in call tests instead.
StreamStats& entry = stats.substreams[ssrc];
if (entry.key_frames > 0u && entry.bitrate_bps > 0 &&
entry.rtp_stats.packets > 0u) {
observation_complete_->Set();
}
}
return SEND_PACKET;
}
void SetConfig(const VideoSendStream::Config& config) { config_ = config; }
void SetSendStream(VideoSendStream* stream) { stream_ = stream; }
VideoSendStream* stream_;
VideoSendStream::Config config_;
} observer;
Call::Config call_config(observer.SendTransport());
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.rtp.c_name = kCName;
observer.SetConfig(send_config);
send_stream_ = call->CreateVideoSendStream(send_config);
observer.SetSendStream(send_stream_);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
test::FrameGeneratorCapturer::Create(
send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
send_stream_->StartSending();
frame_generator_capturer->Start();
EXPECT_EQ(kEventSignaled, observer.Wait());
observer.StopSending();
frame_generator_capturer->Stop();
send_stream_->StopSending();
call->DestroyVideoSendStream(send_stream_);
}
} // namespace webrtc

View File

@ -14,6 +14,8 @@
'video/call.cc',
'video/encoded_frame_callback_adapter.cc',
'video/encoded_frame_callback_adapter.h',
'video/send_statistics_proxy.cc',
'video/send_statistics_proxy.h',
'video/transport_adapter.cc',
'video/transport_adapter.h',
'video/video_receive_stream.cc',

View File

@ -345,8 +345,6 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec,
}
rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(
rtp_rtcp_->GetSendChannelRtcpStatisticsCallback());
simulcast_rtp_rtcp_.push_back(rtp_rtcp);
}
// Remove last in list if we have too many.

View File

@ -400,7 +400,6 @@ class ViEChannel
scoped_ptr<RtcpBandwidthObserver> bandwidth_observer_;
int send_timestamp_extension_id_;
int absolute_send_time_extension_id_;
bool using_packet_spread_;
Transport* external_transport_;

View File

@ -11,8 +11,8 @@
#ifndef WEBRTC_VIDEO_SEND_STREAM_H_
#define WEBRTC_VIDEO_SEND_STREAM_H_
#include <map>
#include <string>
#include <vector>
#include "webrtc/common_types.h"
#include "webrtc/config.h"
@ -41,32 +41,28 @@ class VideoSendStream {
struct Stats {
Stats()
: input_frame_rate(0),
encode_frame(0),
key_frames(0),
delta_frames(0),
video_packets(0),
retransmitted_packets(0),
fec_packets(0),
padding_packets(0),
send_bitrate_bps(0),
delay_ms(0) {}
RtpStatistics rtp;
int input_frame_rate;
int encode_frame;
uint32_t key_frames;
uint32_t delta_frames;
uint32_t video_packets;
uint32_t retransmitted_packets;
uint32_t fec_packets;
uint32_t padding_packets;
int32_t send_bitrate_bps;
int delay_ms;
};
encode_frame_rate(0),
avg_delay_ms(0),
max_delay_ms(0) {}
class StatsCallback {
public:
virtual ~StatsCallback() {}
virtual void ReceiveStats(const std::vector<Stats>& stats) = 0;
int input_frame_rate;
int encode_frame_rate;
int avg_delay_ms;
int max_delay_ms;
std::string c_name;
std::map<uint32_t, StreamStats> substreams;
bool operator==(const Stats& other) const {
if (input_frame_rate != other.input_frame_rate ||
encode_frame_rate != other.encode_frame_rate ||
avg_delay_ms != other.avg_delay_ms ||
max_delay_ms != other.max_delay_ms || c_name != other.c_name ||
substreams.size() != other.substreams.size()) {
return false;
}
return std::equal(
substreams.begin(), substreams.end(), other.substreams.begin());
}
};
struct Config {
@ -79,7 +75,6 @@ class VideoSendStream {
internal_source(false),
target_delay_ms(0),
pacing(false),
stats_callback(NULL),
suspend_below_min_bitrate(false) {}
VideoCodec codec;
@ -140,9 +135,6 @@ class VideoSendStream {
// packets onto the network.
bool pacing;
// Callback for periodically receiving send stats.
StatsCallback* stats_callback;
// True if the stream should be suspended when the available bitrate fall
// below the minimum configured bitrate. If this variable is false, the
// stream may send at a rate higher than the estimated available bitrate.
@ -161,6 +153,8 @@ class VideoSendStream {
virtual bool SetCodec(const VideoCodec& codec) = 0;
virtual VideoCodec GetCodec() = 0;
virtual Stats GetStats() const = 0;
protected:
virtual ~VideoSendStream() {}
};

View File

@ -35,6 +35,7 @@
'sources': [
'video/bitrate_estimator_tests.cc',
'video/call_tests.cc',
'video/send_statistics_proxy_unittest.cc',
'video/video_send_stream_tests.cc',
'test/common_unittest.cc',
'test/testsupport/metrics/video_metrics_unittest.cc',