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() {}
|
||||
};
|
||||
|
||||
// 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
|
||||
// are assumed to have the same remote endpoint and will share bitrate estimates
|
||||
// etc.
|
||||
@ -40,21 +53,24 @@ class Call {
|
||||
explicit Config(newapi::Transport* send_transport)
|
||||
: webrtc_config(NULL),
|
||||
send_transport(send_transport),
|
||||
overuse_detection(false),
|
||||
voice_engine(NULL),
|
||||
trace_callback(NULL),
|
||||
trace_filter(kTraceDefault) {}
|
||||
trace_filter(kTraceDefault),
|
||||
overuse_callback(NULL) {}
|
||||
|
||||
webrtc::Config* webrtc_config;
|
||||
|
||||
newapi::Transport* send_transport;
|
||||
bool overuse_detection;
|
||||
|
||||
// VoiceEngine used for audio/video synchronization for this Call.
|
||||
VoiceEngine* voice_engine;
|
||||
|
||||
TraceCallback* trace_callback;
|
||||
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);
|
||||
|
@ -33,6 +33,32 @@ const char* RtpExtension::kTOffset = "urn:ietf:params:rtp-hdrext:toffset";
|
||||
const char* RtpExtension::kAbsSendTime =
|
||||
"http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
|
||||
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 {
|
||||
public:
|
||||
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<CpuOveruseObserverProxy> overuse_observer_proxy_;
|
||||
|
||||
VideoEngine* video_engine_;
|
||||
ViERTP_RTCP* rtp_rtcp_;
|
||||
ViECodec* codec_;
|
||||
@ -185,6 +213,11 @@ Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config)
|
||||
assert(video_engine != 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_);
|
||||
|
||||
rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_);
|
||||
@ -236,8 +269,9 @@ VideoSendStream* Call::CreateVideoSendStream(
|
||||
assert(config.rtp.ssrcs.size() > 0);
|
||||
assert(config.rtp.ssrcs.size() >= config.codec.numberOfSimulcastStreams);
|
||||
|
||||
VideoSendStream* send_stream = new VideoSendStream(config_.send_transport,
|
||||
config_.overuse_detection,
|
||||
VideoSendStream* send_stream = new VideoSendStream(
|
||||
config_.send_transport,
|
||||
overuse_observer_proxy_.get(),
|
||||
video_engine_,
|
||||
config,
|
||||
base_channel_id_);
|
||||
|
@ -45,6 +45,39 @@ static const uint32_t kReceiverLocalSsrc = 0x123456;
|
||||
static const uint8_t kSendPayloadType = 125;
|
||||
|
||||
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 {
|
||||
@ -236,15 +269,9 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
|
||||
|
||||
observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
|
||||
|
||||
test::FakeEncoder fake_encoder(Clock::GetRealTimeClock());
|
||||
test::FakeDecoder fake_decoder;
|
||||
|
||||
VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
|
||||
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;
|
||||
VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
|
||||
|
||||
VideoReceiveStream::Config receive_config =
|
||||
receiver_call->GetDefaultReceiveConfig();
|
||||
@ -301,4 +328,28 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
|
||||
receiver_call->DestroyVideoReceiveStream(receive_stream);
|
||||
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
|
||||
|
@ -43,7 +43,6 @@ TEST_F(LoopbackTest, Test) {
|
||||
|
||||
test::DirectTransport transport;
|
||||
Call::Config call_config(&transport);
|
||||
call_config.overuse_detection = true;
|
||||
scoped_ptr<Call> call(Call::Create(call_config));
|
||||
|
||||
// Loopback, call sends to itself.
|
||||
|
@ -26,58 +26,8 @@
|
||||
namespace webrtc {
|
||||
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,
|
||||
bool overuse_detection,
|
||||
CpuOveruseObserver* overuse_observer,
|
||||
webrtc::VideoEngine* video_engine,
|
||||
const VideoSendStream::Config& config,
|
||||
int base_channel)
|
||||
@ -169,11 +119,8 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
|
||||
if (!SetCodec(config_.codec))
|
||||
abort();
|
||||
|
||||
if (overuse_detection) {
|
||||
overuse_observer_.reset(new ResolutionAdaptor(
|
||||
codec_, channel_, config_.codec.width, config_.codec.height));
|
||||
video_engine_base_->RegisterCpuOveruseObserver(channel_,
|
||||
overuse_observer_.get());
|
||||
if (overuse_observer) {
|
||||
video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer);
|
||||
}
|
||||
|
||||
image_process_ = ViEImageProcess::GetInterface(video_engine);
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CpuOveruseObserver;
|
||||
class VideoEngine;
|
||||
class ViEBase;
|
||||
class ViECapture;
|
||||
@ -33,14 +34,12 @@ class ViERTP_RTCP;
|
||||
|
||||
namespace internal {
|
||||
|
||||
class ResolutionAdaptor;
|
||||
|
||||
class VideoSendStream : public webrtc::VideoSendStream,
|
||||
public VideoSendStreamInput,
|
||||
public SendStatisticsProxy::StreamStatsProvider {
|
||||
public:
|
||||
VideoSendStream(newapi::Transport* transport,
|
||||
bool overuse_detection,
|
||||
CpuOveruseObserver* overuse_observer,
|
||||
webrtc::VideoEngine* video_engine,
|
||||
const VideoSendStream::Config& config,
|
||||
int base_channel);
|
||||
@ -88,7 +87,6 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
||||
|
||||
int channel_;
|
||||
int capture_id_;
|
||||
scoped_ptr<ResolutionAdaptor> overuse_observer_;
|
||||
|
||||
scoped_ptr<SendStatisticsProxy> stats_proxy_;
|
||||
};
|
||||
|
Reference in New Issue
Block a user