Add configuration for cpu overuse detection to video send stream.
BUG=2422 R=mflodman@webrtc.org, pbos@webrtc.org Review URL: https://webrtc-codereview.appspot.com/7129004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5468 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -31,6 +31,19 @@ class PacketReceiver {
|
|||||||
virtual ~PacketReceiver() {}
|
virtual ~PacketReceiver() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Callback interface for reporting when a system overuse is detected.
|
||||||
|
// The detection is based on the jitter of incoming captured frames.
|
||||||
|
class OveruseCallback {
|
||||||
|
public:
|
||||||
|
// Called as soon as an overuse is detected.
|
||||||
|
virtual void OnOveruse() = 0;
|
||||||
|
// Called periodically when the system is not overused any longer.
|
||||||
|
virtual void OnNormalUse() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~OveruseCallback() {}
|
||||||
|
};
|
||||||
|
|
||||||
// A Call instance can contain several send and/or receive streams. All streams
|
// A Call instance can contain several send and/or receive streams. All streams
|
||||||
// are assumed to have the same remote endpoint and will share bitrate estimates
|
// are assumed to have the same remote endpoint and will share bitrate estimates
|
||||||
// etc.
|
// etc.
|
||||||
@ -40,21 +53,24 @@ class Call {
|
|||||||
explicit Config(newapi::Transport* send_transport)
|
explicit Config(newapi::Transport* send_transport)
|
||||||
: webrtc_config(NULL),
|
: webrtc_config(NULL),
|
||||||
send_transport(send_transport),
|
send_transport(send_transport),
|
||||||
overuse_detection(false),
|
|
||||||
voice_engine(NULL),
|
voice_engine(NULL),
|
||||||
trace_callback(NULL),
|
trace_callback(NULL),
|
||||||
trace_filter(kTraceDefault) {}
|
trace_filter(kTraceDefault),
|
||||||
|
overuse_callback(NULL) {}
|
||||||
|
|
||||||
webrtc::Config* webrtc_config;
|
webrtc::Config* webrtc_config;
|
||||||
|
|
||||||
newapi::Transport* send_transport;
|
newapi::Transport* send_transport;
|
||||||
bool overuse_detection;
|
|
||||||
|
|
||||||
// VoiceEngine used for audio/video synchronization for this Call.
|
// VoiceEngine used for audio/video synchronization for this Call.
|
||||||
VoiceEngine* voice_engine;
|
VoiceEngine* voice_engine;
|
||||||
|
|
||||||
TraceCallback* trace_callback;
|
TraceCallback* trace_callback;
|
||||||
uint32_t trace_filter;
|
uint32_t trace_filter;
|
||||||
|
|
||||||
|
// Callback for overuse and normal usage based on the jitter of incoming
|
||||||
|
// captured frames. 'NULL' disables the callback.
|
||||||
|
OveruseCallback* overuse_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Call* Create(const Call::Config& config);
|
static Call* Create(const Call::Config& config);
|
||||||
|
@ -33,6 +33,32 @@ const char* RtpExtension::kTOffset = "urn:ietf:params:rtp-hdrext:toffset";
|
|||||||
const char* RtpExtension::kAbsSendTime =
|
const char* RtpExtension::kAbsSendTime =
|
||||||
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
|
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
class CpuOveruseObserverProxy : public webrtc::CpuOveruseObserver {
|
||||||
|
public:
|
||||||
|
CpuOveruseObserverProxy(OveruseCallback* overuse_callback)
|
||||||
|
: crit_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
|
overuse_callback_(overuse_callback) {
|
||||||
|
assert(overuse_callback != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~CpuOveruseObserverProxy() {}
|
||||||
|
|
||||||
|
virtual void OveruseDetected() OVERRIDE {
|
||||||
|
CriticalSectionScoped cs(crit_.get());
|
||||||
|
overuse_callback_->OnOveruse();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void NormalUsage() OVERRIDE {
|
||||||
|
CriticalSectionScoped cs(crit_.get());
|
||||||
|
overuse_callback_->OnNormalUse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
scoped_ptr<CriticalSectionWrapper> crit_;
|
||||||
|
OveruseCallback* overuse_callback_;
|
||||||
|
};
|
||||||
|
|
||||||
class Call : public webrtc::Call, public PacketReceiver {
|
class Call : public webrtc::Call, public PacketReceiver {
|
||||||
public:
|
public:
|
||||||
Call(webrtc::VideoEngine* video_engine, const Call::Config& config);
|
Call(webrtc::VideoEngine* video_engine, const Call::Config& config);
|
||||||
@ -78,6 +104,8 @@ class Call : public webrtc::Call, public PacketReceiver {
|
|||||||
|
|
||||||
scoped_ptr<RtpHeaderParser> rtp_header_parser_;
|
scoped_ptr<RtpHeaderParser> rtp_header_parser_;
|
||||||
|
|
||||||
|
scoped_ptr<CpuOveruseObserverProxy> overuse_observer_proxy_;
|
||||||
|
|
||||||
VideoEngine* video_engine_;
|
VideoEngine* video_engine_;
|
||||||
ViERTP_RTCP* rtp_rtcp_;
|
ViERTP_RTCP* rtp_rtcp_;
|
||||||
ViECodec* codec_;
|
ViECodec* codec_;
|
||||||
@ -185,6 +213,11 @@ Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config)
|
|||||||
assert(video_engine != NULL);
|
assert(video_engine != NULL);
|
||||||
assert(config.send_transport != NULL);
|
assert(config.send_transport != NULL);
|
||||||
|
|
||||||
|
if (config.overuse_callback) {
|
||||||
|
overuse_observer_proxy_.reset(
|
||||||
|
new CpuOveruseObserverProxy(config.overuse_callback));
|
||||||
|
}
|
||||||
|
|
||||||
global_trace_dispatcher->RegisterCallback(this, &config_);
|
global_trace_dispatcher->RegisterCallback(this, &config_);
|
||||||
|
|
||||||
rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_);
|
rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_);
|
||||||
@ -236,11 +269,12 @@ VideoSendStream* Call::CreateVideoSendStream(
|
|||||||
assert(config.rtp.ssrcs.size() > 0);
|
assert(config.rtp.ssrcs.size() > 0);
|
||||||
assert(config.rtp.ssrcs.size() >= config.codec.numberOfSimulcastStreams);
|
assert(config.rtp.ssrcs.size() >= config.codec.numberOfSimulcastStreams);
|
||||||
|
|
||||||
VideoSendStream* send_stream = new VideoSendStream(config_.send_transport,
|
VideoSendStream* send_stream = new VideoSendStream(
|
||||||
config_.overuse_detection,
|
config_.send_transport,
|
||||||
video_engine_,
|
overuse_observer_proxy_.get(),
|
||||||
config,
|
video_engine_,
|
||||||
base_channel_id_);
|
config,
|
||||||
|
base_channel_id_);
|
||||||
|
|
||||||
WriteLockScoped write_lock(*send_lock_);
|
WriteLockScoped write_lock(*send_lock_);
|
||||||
for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) {
|
for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) {
|
||||||
|
@ -45,6 +45,39 @@ static const uint32_t kReceiverLocalSsrc = 0x123456;
|
|||||||
static const uint8_t kSendPayloadType = 125;
|
static const uint8_t kSendPayloadType = 125;
|
||||||
|
|
||||||
class CallPerfTest : public ::testing::Test {
|
class CallPerfTest : public ::testing::Test {
|
||||||
|
public:
|
||||||
|
CallPerfTest()
|
||||||
|
: send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
|
||||||
|
protected:
|
||||||
|
VideoSendStream::Config GetSendTestConfig(Call* call) {
|
||||||
|
VideoSendStream::Config config = call->GetDefaultSendConfig();
|
||||||
|
config.encoder = &fake_encoder_;
|
||||||
|
config.internal_source = false;
|
||||||
|
config.rtp.ssrcs.push_back(kSendSsrc);
|
||||||
|
test::FakeEncoder::SetCodecSettings(&config.codec, 1);
|
||||||
|
config.codec.plType = kSendPayloadType;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
void RunVideoSendTest(Call* call,
|
||||||
|
const VideoSendStream::Config& config,
|
||||||
|
test::RtpRtcpObserver* observer) {
|
||||||
|
send_stream_ = call->CreateVideoSendStream(config);
|
||||||
|
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_);
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoSendStream* send_stream_;
|
||||||
|
test::FakeEncoder fake_encoder_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SyncRtcpObserver : public test::RtpRtcpObserver {
|
class SyncRtcpObserver : public test::RtpRtcpObserver {
|
||||||
@ -236,15 +269,9 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
|
|||||||
|
|
||||||
observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
|
observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
|
||||||
|
|
||||||
test::FakeEncoder fake_encoder(Clock::GetRealTimeClock());
|
|
||||||
test::FakeDecoder fake_decoder;
|
test::FakeDecoder fake_decoder;
|
||||||
|
|
||||||
VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
|
VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
|
||||||
send_config.rtp.ssrcs.push_back(kSendSsrc);
|
|
||||||
send_config.encoder = &fake_encoder;
|
|
||||||
send_config.internal_source = false;
|
|
||||||
test::FakeEncoder::SetCodecSettings(&send_config.codec, 1);
|
|
||||||
send_config.codec.plType = kSendPayloadType;
|
|
||||||
|
|
||||||
VideoReceiveStream::Config receive_config =
|
VideoReceiveStream::Config receive_config =
|
||||||
receiver_call->GetDefaultReceiveConfig();
|
receiver_call->GetDefaultReceiveConfig();
|
||||||
@ -301,4 +328,28 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
|
|||||||
receiver_call->DestroyVideoReceiveStream(receive_stream);
|
receiver_call->DestroyVideoReceiveStream(receive_stream);
|
||||||
VoiceEngine::Delete(voice_engine);
|
VoiceEngine::Delete(voice_engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CallPerfTest, RegisterCpuOveruseObserver) {
|
||||||
|
// Verifies that either a normal or overuse callback is triggered.
|
||||||
|
class OveruseCallbackObserver : public test::RtpRtcpObserver,
|
||||||
|
public webrtc::OveruseCallback {
|
||||||
|
public:
|
||||||
|
OveruseCallbackObserver() : RtpRtcpObserver(kLongTimeoutMs) {}
|
||||||
|
|
||||||
|
virtual void OnOveruse() OVERRIDE {
|
||||||
|
observation_complete_->Set();
|
||||||
|
}
|
||||||
|
virtual void OnNormalUse() OVERRIDE {
|
||||||
|
observation_complete_->Set();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OveruseCallbackObserver observer;
|
||||||
|
Call::Config call_config(observer.SendTransport());
|
||||||
|
call_config.overuse_callback = &observer;
|
||||||
|
scoped_ptr<Call> call(Call::Create(call_config));
|
||||||
|
|
||||||
|
VideoSendStream::Config send_config = GetSendTestConfig(call.get());
|
||||||
|
RunVideoSendTest(call.get(), send_config, &observer);
|
||||||
|
}
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -43,7 +43,6 @@ TEST_F(LoopbackTest, Test) {
|
|||||||
|
|
||||||
test::DirectTransport transport;
|
test::DirectTransport transport;
|
||||||
Call::Config call_config(&transport);
|
Call::Config call_config(&transport);
|
||||||
call_config.overuse_detection = true;
|
|
||||||
scoped_ptr<Call> call(Call::Create(call_config));
|
scoped_ptr<Call> call(Call::Create(call_config));
|
||||||
|
|
||||||
// Loopback, call sends to itself.
|
// Loopback, call sends to itself.
|
||||||
|
@ -26,58 +26,8 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// Super simple and temporary overuse logic. This will move to the application
|
|
||||||
// as soon as the new API allows changing send codec on the fly.
|
|
||||||
class ResolutionAdaptor : public webrtc::CpuOveruseObserver {
|
|
||||||
public:
|
|
||||||
ResolutionAdaptor(ViECodec* codec, int channel, size_t width, size_t height)
|
|
||||||
: codec_(codec),
|
|
||||||
channel_(channel),
|
|
||||||
max_width_(width),
|
|
||||||
max_height_(height) {}
|
|
||||||
|
|
||||||
virtual ~ResolutionAdaptor() {}
|
|
||||||
|
|
||||||
virtual void OveruseDetected() OVERRIDE {
|
|
||||||
VideoCodec codec;
|
|
||||||
if (codec_->GetSendCodec(channel_, codec) != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (codec.width / 2 < min_width || codec.height / 2 < min_height)
|
|
||||||
return;
|
|
||||||
|
|
||||||
codec.width /= 2;
|
|
||||||
codec.height /= 2;
|
|
||||||
codec_->SetSendCodec(channel_, codec);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void NormalUsage() OVERRIDE {
|
|
||||||
VideoCodec codec;
|
|
||||||
if (codec_->GetSendCodec(channel_, codec) != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (codec.width * 2u > max_width_ || codec.height * 2u > max_height_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
codec.width *= 2;
|
|
||||||
codec.height *= 2;
|
|
||||||
codec_->SetSendCodec(channel_, codec);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Temporary and arbitrary chosen minimum resolution.
|
|
||||||
static const size_t min_width = 160;
|
|
||||||
static const size_t min_height = 120;
|
|
||||||
|
|
||||||
ViECodec* codec_;
|
|
||||||
const int channel_;
|
|
||||||
|
|
||||||
const size_t max_width_;
|
|
||||||
const size_t max_height_;
|
|
||||||
};
|
|
||||||
|
|
||||||
VideoSendStream::VideoSendStream(newapi::Transport* transport,
|
VideoSendStream::VideoSendStream(newapi::Transport* transport,
|
||||||
bool overuse_detection,
|
CpuOveruseObserver* overuse_observer,
|
||||||
webrtc::VideoEngine* video_engine,
|
webrtc::VideoEngine* video_engine,
|
||||||
const VideoSendStream::Config& config,
|
const VideoSendStream::Config& config,
|
||||||
int base_channel)
|
int base_channel)
|
||||||
@ -169,11 +119,8 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
|
|||||||
if (!SetCodec(config_.codec))
|
if (!SetCodec(config_.codec))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
if (overuse_detection) {
|
if (overuse_observer) {
|
||||||
overuse_observer_.reset(new ResolutionAdaptor(
|
video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer);
|
||||||
codec_, channel_, config_.codec.width, config_.codec.height));
|
|
||||||
video_engine_base_->RegisterCpuOveruseObserver(channel_,
|
|
||||||
overuse_observer_.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
image_process_ = ViEImageProcess::GetInterface(video_engine);
|
image_process_ = ViEImageProcess::GetInterface(video_engine);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class CpuOveruseObserver;
|
||||||
class VideoEngine;
|
class VideoEngine;
|
||||||
class ViEBase;
|
class ViEBase;
|
||||||
class ViECapture;
|
class ViECapture;
|
||||||
@ -33,14 +34,12 @@ class ViERTP_RTCP;
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
class ResolutionAdaptor;
|
|
||||||
|
|
||||||
class VideoSendStream : public webrtc::VideoSendStream,
|
class VideoSendStream : public webrtc::VideoSendStream,
|
||||||
public VideoSendStreamInput,
|
public VideoSendStreamInput,
|
||||||
public SendStatisticsProxy::StreamStatsProvider {
|
public SendStatisticsProxy::StreamStatsProvider {
|
||||||
public:
|
public:
|
||||||
VideoSendStream(newapi::Transport* transport,
|
VideoSendStream(newapi::Transport* transport,
|
||||||
bool overuse_detection,
|
CpuOveruseObserver* overuse_observer,
|
||||||
webrtc::VideoEngine* video_engine,
|
webrtc::VideoEngine* video_engine,
|
||||||
const VideoSendStream::Config& config,
|
const VideoSendStream::Config& config,
|
||||||
int base_channel);
|
int base_channel);
|
||||||
@ -88,7 +87,6 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
|||||||
|
|
||||||
int channel_;
|
int channel_;
|
||||||
int capture_id_;
|
int capture_id_;
|
||||||
scoped_ptr<ResolutionAdaptor> overuse_observer_;
|
|
||||||
|
|
||||||
scoped_ptr<SendStatisticsProxy> stats_proxy_;
|
scoped_ptr<SendStatisticsProxy> stats_proxy_;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user