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