summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--call.h2
-rw-r--r--common_types.h29
-rw-r--r--test/encoder_settings.cc120
-rw-r--r--test/encoder_settings.h28
-rw-r--r--test/fake_encoder.cc36
-rw-r--r--test/fake_encoder.h1
-rw-r--r--test/webrtc_test_common.gyp2
-rw-r--r--video/bitrate_estimator_tests.cc31
-rw-r--r--video/call.cc15
-rw-r--r--video/call_perf_tests.cc44
-rw-r--r--video/call_tests.cc84
-rw-r--r--video/full_stack.cc24
-rw-r--r--video/loopback.cc28
-rw-r--r--video/rampup_tests.cc70
-rw-r--r--video/video_receive_stream.cc1
-rw-r--r--video/video_send_stream.cc128
-rw-r--r--video/video_send_stream.h4
-rw-r--r--video/video_send_stream_tests.cc112
-rw-r--r--video_send_stream.h34
19 files changed, 510 insertions, 283 deletions
diff --git a/call.h b/call.h
index 1b95c298..5b556821 100644
--- a/call.h
+++ b/call.h
@@ -78,8 +78,6 @@ class Call {
static Call* Create(const Call::Config& config,
const webrtc::Config& webrtc_config);
- virtual std::vector<VideoCodec> GetVideoCodecs() = 0;
-
virtual VideoSendStream::Config GetDefaultSendConfig() = 0;
virtual VideoSendStream* CreateVideoSendStream(
diff --git a/common_types.h b/common_types.h
index 9478a2dd..f7e48402 100644
--- a/common_types.h
+++ b/common_types.h
@@ -11,6 +11,10 @@
#ifndef WEBRTC_COMMON_TYPES_H_
#define WEBRTC_COMMON_TYPES_H_
+#include <stddef.h>
+
+#include <vector>
+
#include "webrtc/typedefs.h"
#if defined(_MSC_VER)
@@ -657,7 +661,30 @@ struct PacketTime {
// If unknown, this value will be set to zero.
};
+struct VideoStream {
+ VideoStream()
+ : width(0),
+ height(0),
+ max_framerate(-1),
+ min_bitrate_bps(-1),
+ target_bitrate_bps(-1),
+ max_bitrate_bps(-1),
+ max_qp(-1) {}
+
+ size_t width;
+ size_t height;
+ int max_framerate;
+
+ int min_bitrate_bps;
+ int target_bitrate_bps;
+ int max_bitrate_bps;
+
+ int max_qp;
+
+ // Bitrate thresholds for enabling additional temporal layers.
+ std::vector<int> temporal_layers;
+};
+
} // namespace webrtc
#endif // WEBRTC_COMMON_TYPES_H_
-
diff --git a/test/encoder_settings.cc b/test/encoder_settings.cc
new file mode 100644
index 00000000..d02c29f9
--- /dev/null
+++ b/test/encoder_settings.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014 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/test/encoder_settings.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "webrtc/video_engine/vie_defines.h"
+
+namespace webrtc {
+namespace test {
+VideoSendStream::Config::EncoderSettings CreateEncoderSettings(
+ VideoEncoder* encoder,
+ const char* payload_name,
+ int payload_type,
+ size_t num_streams) {
+ assert(num_streams > 0);
+
+ // Add more streams to the settings above with reasonable values if required.
+ static const size_t kNumSettings = 3;
+ assert(num_streams <= kNumSettings);
+
+ VideoStream stream_settings[kNumSettings];
+
+ stream_settings[0].width = 320;
+ stream_settings[0].height = 180;
+ stream_settings[0].max_framerate = 30;
+ stream_settings[0].min_bitrate_bps = 50000;
+ stream_settings[0].target_bitrate_bps = stream_settings[0].max_bitrate_bps =
+ 150000;
+ stream_settings[0].max_qp = 56;
+
+ stream_settings[1].width = 640;
+ stream_settings[1].height = 360;
+ stream_settings[1].max_framerate = 30;
+ stream_settings[1].min_bitrate_bps = 200000;
+ stream_settings[1].target_bitrate_bps = stream_settings[1].max_bitrate_bps =
+ 450000;
+ stream_settings[1].max_qp = 56;
+
+ stream_settings[2].width = 1280;
+ stream_settings[2].height = 720;
+ stream_settings[2].max_framerate = 30;
+ stream_settings[2].min_bitrate_bps = 700000;
+ stream_settings[2].target_bitrate_bps = stream_settings[2].max_bitrate_bps =
+ 1500000;
+ stream_settings[2].max_qp = 56;
+
+ VideoSendStream::Config::EncoderSettings settings;
+
+ for (size_t i = 0; i < num_streams; ++i)
+ settings.streams.push_back(stream_settings[i]);
+
+ settings.encoder = encoder;
+ settings.payload_name = payload_name;
+ settings.payload_type = payload_type;
+ return settings;
+}
+
+VideoCodec CreateDecoderVideoCodec(
+ const VideoSendStream::Config::EncoderSettings& settings) {
+ assert(settings.streams.size() > 0);
+ VideoCodec codec;
+ memset(&codec, 0, sizeof(codec));
+
+ codec.plType = settings.payload_type;
+ strcpy(codec.plName, settings.payload_name.c_str());
+ codec.codecType =
+ (settings.payload_name == "VP8" ? kVideoCodecVP8 : kVideoCodecGeneric);
+
+ if (codec.codecType == kVideoCodecVP8) {
+ codec.codecSpecific.VP8.resilience = kResilientStream;
+ codec.codecSpecific.VP8.numberOfTemporalLayers = 1;
+ codec.codecSpecific.VP8.denoisingOn = true;
+ codec.codecSpecific.VP8.errorConcealmentOn = false;
+ codec.codecSpecific.VP8.automaticResizeOn = false;
+ codec.codecSpecific.VP8.frameDroppingOn = true;
+ codec.codecSpecific.VP8.keyFrameInterval = 3000;
+ }
+
+ codec.minBitrate = settings.streams[0].min_bitrate_bps / 1000;
+ for (size_t i = 0; i < settings.streams.size(); ++i) {
+ const VideoStream& stream = settings.streams[i];
+ if (stream.width > codec.width)
+ codec.width = static_cast<unsigned short>(stream.width);
+ if (stream.height > codec.height)
+ codec.height = static_cast<unsigned short>(stream.height);
+ if (static_cast<unsigned int>(stream.min_bitrate_bps / 1000) <
+ codec.minBitrate)
+ codec.minBitrate =
+ static_cast<unsigned int>(stream.min_bitrate_bps / 1000);
+ codec.maxBitrate += stream.max_bitrate_bps / 1000;
+ if (static_cast<unsigned int>(stream.max_qp) > codec.qpMax)
+ codec.qpMax = static_cast<unsigned int>(stream.max_qp);
+ }
+
+ if (codec.minBitrate < kViEMinCodecBitrate)
+ codec.minBitrate = kViEMinCodecBitrate;
+ if (codec.maxBitrate < kViEMinCodecBitrate)
+ codec.maxBitrate = kViEMinCodecBitrate;
+
+ codec.startBitrate = 300;
+
+ if (codec.startBitrate < codec.minBitrate)
+ codec.startBitrate = codec.minBitrate;
+ if (codec.startBitrate > codec.maxBitrate)
+ codec.startBitrate = codec.maxBitrate;
+
+ return codec;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/test/encoder_settings.h b/test/encoder_settings.h
new file mode 100644
index 00000000..1d8e355a
--- /dev/null
+++ b/test/encoder_settings.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014 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_TEST_ENCODER_SETTINGS_H_
+#define WEBRTC_TEST_ENCODER_SETTINGS_H_
+
+#include "webrtc/video_send_stream.h"
+
+namespace webrtc {
+namespace test {
+VideoSendStream::Config::EncoderSettings CreateEncoderSettings(
+ VideoEncoder* encoder,
+ const char* payload_name,
+ int payload_type,
+ size_t num_streams);
+
+VideoCodec CreateDecoderVideoCodec(
+ const VideoSendStream::Config::EncoderSettings& settings);
+} // namespace test
+} // namespace webrtc
+
+#endif // WEBRTC_TEST_ENCODER_SETTINGS_H_
diff --git a/test/fake_encoder.cc b/test/fake_encoder.cc
index fc8712e5..4ff81a18 100644
--- a/test/fake_encoder.cc
+++ b/test/fake_encoder.cc
@@ -29,40 +29,6 @@ FakeEncoder::FakeEncoder(Clock* clock)
FakeEncoder::~FakeEncoder() {}
-void FakeEncoder::SetCodecSettings(VideoCodec* codec,
- size_t num_streams) {
- assert(num_streams > 0);
- assert(num_streams <= kMaxSimulcastStreams);
-
- static const SimulcastStream stream_settings[] = {
- {320, 180, 0, 150, 150, 50, codec->qpMax},
- {640, 360, 0, 500, 500, 150, codec->qpMax},
- {1280, 720, 0, 1200, 1200, 600, codec->qpMax}};
- // Add more streams to the settings above with reasonable values if required.
- assert(num_streams <= sizeof(stream_settings) / sizeof(stream_settings[0]));
-
- codec->numberOfSimulcastStreams = static_cast<unsigned char>(num_streams);
-
- unsigned int sum_of_max_bitrates = 0;
- for (size_t i = 0; i < num_streams; ++i) {
- codec->simulcastStream[i] = stream_settings[i];
- sum_of_max_bitrates += stream_settings[i].maxBitrate;
- }
-
- size_t last_stream = num_streams - 1;
- codec->width = stream_settings[last_stream].width;
- codec->height = stream_settings[last_stream].height;
- // Start with the average for the middle stream's max/min settings.
- codec->startBitrate = (stream_settings[last_stream / 2].maxBitrate +
- stream_settings[last_stream / 2].minBitrate) /
- 2;
- codec->minBitrate = stream_settings[0].minBitrate;
- codec->maxBitrate = sum_of_max_bitrates;
-
- codec->codecType = kVideoCodecGeneric;
- strcpy(codec->plName, "FAKE");
-}
-
void FakeEncoder::SetMaxBitrate(int max_kbps) {
assert(max_kbps >= -1); // max_kbps == -1 disables it.
max_target_bitrate_kbps_ = max_kbps;
@@ -99,6 +65,7 @@ int32_t FakeEncoder::Encode(
bits_available = max_bits;
last_encode_time_ms_ = time_now_ms;
+ assert(config_.numberOfSimulcastStreams > 0);
for (int i = 0; i < config_.numberOfSimulcastStreams; ++i) {
CodecSpecificInfo specifics;
memset(&specifics, 0, sizeof(specifics));
@@ -124,6 +91,7 @@ int32_t FakeEncoder::Encode(
encoded._length = 0;
encoded._frameType = kSkipFrame;
}
+ assert(callback_ != NULL);
if (callback_->Encoded(encoded, &specifics, NULL) != 0)
return -1;
diff --git a/test/fake_encoder.h b/test/fake_encoder.h
index e2d8d6b4..c0709c12 100644
--- a/test/fake_encoder.h
+++ b/test/fake_encoder.h
@@ -24,7 +24,6 @@ class FakeEncoder : public VideoEncoder {
explicit FakeEncoder(Clock* clock);
virtual ~FakeEncoder();
- static void SetCodecSettings(VideoCodec* codec, size_t num_streams);
// Sets max bitrate. Not thread-safe, call before registering the encoder.
void SetMaxBitrate(int max_kbps);
diff --git a/test/webrtc_test_common.gyp b/test/webrtc_test_common.gyp
index 6920ab84..bec5803f 100644
--- a/test/webrtc_test_common.gyp
+++ b/test/webrtc_test_common.gyp
@@ -18,6 +18,8 @@
'configurable_frame_size_encoder.h',
'direct_transport.cc',
'direct_transport.h',
+ 'encoder_settings.cc',
+ 'encoder_settings.h',
'fake_audio_device.cc',
'fake_audio_device.h',
'fake_decoder.cc',
diff --git a/video/bitrate_estimator_tests.cc b/video/bitrate_estimator_tests.cc
index 58b196db..ea7c0fa0 100644
--- a/video/bitrate_estimator_tests.cc
+++ b/video/bitrate_estimator_tests.cc
@@ -18,6 +18,7 @@
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_decoder.h"
#include "webrtc/test/fake_encoder.h"
#include "webrtc/test/frame_generator_capturer.h"
@@ -64,14 +65,15 @@ class BitrateEstimatorTest : public ::testing::Test {
send_config_ = sender_call_->GetDefaultSendConfig();
send_config_.rtp.ssrcs.push_back(kSendSsrc);
- // send_config_.encoder will be set by every stream separately.
- send_config_.internal_source = false;
- test::FakeEncoder::SetCodecSettings(&send_config_.codec, 1);
- send_config_.codec.plType = kSendPayloadType;
+ // Encoders will be set separately per stream.
+ send_config_.encoder_settings =
+ test::CreateEncoderSettings(NULL, "FAKE", kSendPayloadType, 1);
receive_config_ = receiver_call_->GetDefaultReceiveConfig();
- receive_config_.codecs.clear();
- receive_config_.codecs.push_back(send_config_.codec);
+ assert(receive_config_.codecs.empty());
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config_.encoder_settings);
+ receive_config_.codecs.push_back(codec);
// receive_config_.external_decoders will be set by every stream separately.
receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
@@ -163,21 +165,22 @@ class BitrateEstimatorTest : public ::testing::Test {
fake_encoder_(Clock::GetRealTimeClock()),
fake_decoder_() {
test_->send_config_.rtp.ssrcs[0]++;
- test_->send_config_.encoder = &fake_encoder_;
+ test_->send_config_.encoder_settings.encoder = &fake_encoder_;
send_stream_ =
test_->sender_call_->CreateVideoSendStream(test_->send_config_);
- frame_generator_capturer_.reset(
- test::FrameGeneratorCapturer::Create(send_stream_->Input(),
- test_->send_config_.codec.width,
- test_->send_config_.codec.height,
- 30,
- Clock::GetRealTimeClock()));
+ assert(test_->send_config_.encoder_settings.streams.size() == 1);
+ frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
+ send_stream_->Input(),
+ test_->send_config_.encoder_settings.streams[0].width,
+ test_->send_config_.encoder_settings.streams[0].height,
+ 30,
+ Clock::GetRealTimeClock()));
send_stream_->StartSending();
frame_generator_capturer_->Start();
ExternalVideoDecoder decoder;
decoder.decoder = &fake_decoder_;
- decoder.payload_type = test_->send_config_.codec.plType;
+ decoder.payload_type = test_->send_config_.encoder_settings.payload_type;
test_->receive_config_.rtp.remote_ssrc = test_->send_config_.rtp.ssrcs[0];
test_->receive_config_.rtp.local_ssrc++;
test_->receive_config_.external_decoders.push_back(decoder);
diff --git a/video/call.cc b/video/call.cc
index 7c4699e4..bcdcbf76 100644
--- a/video/call.cc
+++ b/video/call.cc
@@ -65,7 +65,6 @@ class Call : public webrtc::Call, public PacketReceiver {
virtual ~Call();
virtual PacketReceiver* Receiver() OVERRIDE;
- virtual std::vector<VideoCodec> GetVideoCodecs() OVERRIDE;
virtual VideoSendStream::Config GetDefaultSendConfig() OVERRIDE;
@@ -246,28 +245,14 @@ Call::~Call() {
PacketReceiver* Call::Receiver() { return this; }
-std::vector<VideoCodec> Call::GetVideoCodecs() {
- std::vector<VideoCodec> codecs;
-
- VideoCodec codec;
- for (size_t i = 0; i < static_cast<size_t>(codec_->NumberOfCodecs()); ++i) {
- if (codec_->GetCodec(static_cast<unsigned char>(i), codec) == 0) {
- codecs.push_back(codec);
- }
- }
- return codecs;
-}
-
VideoSendStream::Config Call::GetDefaultSendConfig() {
VideoSendStream::Config config;
- codec_->GetCodec(0, config.codec);
return config;
}
VideoSendStream* Call::CreateVideoSendStream(
const VideoSendStream::Config& config) {
assert(config.rtp.ssrcs.size() > 0);
- assert(config.rtp.ssrcs.size() >= config.codec.numberOfSimulcastStreams);
VideoSendStream* send_stream = new VideoSendStream(
config_.send_transport,
diff --git a/video/call_perf_tests.cc b/video/call_perf_tests.cc
index 31cfab5f..e2f4775e 100644
--- a/video/call_perf_tests.cc
+++ b/video/call_perf_tests.cc
@@ -24,6 +24,7 @@
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_audio_device.h"
#include "webrtc/test/fake_decoder.h"
#include "webrtc/test/fake_encoder.h"
@@ -54,11 +55,9 @@ class CallPerfTest : public ::testing::Test {
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;
+ config.encoder_settings = test::CreateEncoderSettings(
+ &fake_encoder_, "FAKE", kSendPayloadType, 1);
return config;
}
@@ -312,11 +311,14 @@ TEST_P(ParamCallPerfTest, PlaysOutAudioAndVideoInSync) {
VideoReceiveStream::Config receive_config =
receiver_call->GetDefaultReceiveConfig();
- receive_config.codecs.clear();
- receive_config.codecs.push_back(send_config.codec);
+ assert(receive_config.codecs.empty());
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config.encoder_settings);
+ receive_config.codecs.push_back(codec);
+ assert(receive_config.external_decoders.empty());
ExternalVideoDecoder decoder;
decoder.decoder = &fake_decoder;
- decoder.payload_type = send_config.codec.plType;
+ decoder.payload_type = send_config.encoder_settings.payload_type;
receive_config.external_decoders.push_back(decoder);
receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
@@ -328,11 +330,12 @@ TEST_P(ParamCallPerfTest, PlaysOutAudioAndVideoInSync) {
VideoReceiveStream* receive_stream =
receiver_call->CreateVideoReceiveStream(receive_config);
scoped_ptr<test::FrameGeneratorCapturer> capturer(
- test::FrameGeneratorCapturer::Create(send_stream->Input(),
- send_config.codec.width,
- send_config.codec.height,
- 30,
- Clock::GetRealTimeClock()));
+ test::FrameGeneratorCapturer::Create(
+ send_stream->Input(),
+ send_config.encoder_settings.streams[0].width,
+ send_config.encoder_settings.streams[0].height,
+ 30,
+ Clock::GetRealTimeClock()));
receive_stream->StartReceiving();
send_stream->StartSending();
capturer->Start();
@@ -480,11 +483,13 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
VideoReceiveStream::Config receive_config =
receiver_call->GetDefaultReceiveConfig();
receive_config.codecs.clear();
- receive_config.codecs.push_back(send_config.codec);
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config.encoder_settings);
+ receive_config.codecs.push_back(codec);
test::FakeDecoder fake_decoder;
ExternalVideoDecoder decoder;
decoder.decoder = &fake_decoder;
- decoder.payload_type = send_config.codec.plType;
+ decoder.payload_type = send_config.encoder_settings.payload_type;
receive_config.external_decoders.push_back(decoder);
receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
@@ -494,11 +499,12 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
VideoReceiveStream* receive_stream =
receiver_call->CreateVideoReceiveStream(receive_config);
scoped_ptr<test::FrameGeneratorCapturer> capturer(
- test::FrameGeneratorCapturer::Create(send_stream->Input(),
- send_config.codec.width,
- send_config.codec.height,
- 30,
- Clock::GetRealTimeClock()));
+ test::FrameGeneratorCapturer::Create(
+ send_stream->Input(),
+ send_config.encoder_settings.streams[0].width,
+ send_config.encoder_settings.streams[0].height,
+ 30,
+ Clock::GetRealTimeClock()));
observer.SetSendStream(send_stream);
receive_stream->StartReceiving();
send_stream->StartSending();
diff --git a/video/call_tests.cc b/video/call_tests.cc
index 6e922d3d..505c9960 100644
--- a/video/call_tests.cc
+++ b/video/call_tests.cc
@@ -19,11 +19,13 @@
#include "webrtc/call.h"
#include "webrtc/frame_callback.h"
#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
+#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_audio_device.h"
#include "webrtc/test/fake_decoder.h"
#include "webrtc/test/fake_encoder.h"
@@ -69,16 +71,16 @@ class CallTest : public ::testing::Test {
receive_config_ = receiver_call_->GetDefaultReceiveConfig();
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;
+ send_config_.encoder_settings = test::CreateEncoderSettings(
+ &fake_encoder_, "FAKE", kSendPayloadType, 1);
- receive_config_.codecs.clear();
- receive_config_.codecs.push_back(send_config_.codec);
+ assert(receive_config_.codecs.empty());
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config_.encoder_settings);
+ receive_config_.codecs.push_back(codec);
ExternalVideoDecoder decoder;
decoder.decoder = &fake_decoder_;
- decoder.payload_type = send_config_.codec.plType;
+ decoder.payload_type = send_config_.encoder_settings.payload_type;
receive_config_.external_decoders.push_back(decoder);
receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
@@ -93,12 +95,12 @@ class CallTest : public ::testing::Test {
}
void CreateFrameGenerator() {
- frame_generator_capturer_.reset(
- test::FrameGeneratorCapturer::Create(send_stream_->Input(),
- send_config_.codec.width,
- send_config_.codec.height,
- 30,
- Clock::GetRealTimeClock()));
+ frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
+ send_stream_->Input(),
+ send_config_.encoder_settings.streams[0].width,
+ send_config_.encoder_settings.streams[0].height,
+ 30,
+ Clock::GetRealTimeClock()));
}
void StartSending() {
@@ -401,7 +403,8 @@ TEST_F(CallTest, TransmitsFirstFrame) {
StartSending();
scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
- send_config_.codec.width, send_config_.codec.height));
+ send_config_.encoder_settings.streams[0].width,
+ send_config_.encoder_settings.streams[0].height));
send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
EXPECT_EQ(kEventSignaled, renderer.Wait())
@@ -552,7 +555,7 @@ void CallTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
if (retransmit_over_rtx) {
send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrc);
send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
- int payload_type = send_config_.codec.plType;
+ int payload_type = send_config_.encoder_settings.payload_type;
receive_config_.rtp.rtx[payload_type].ssrc = kSendRtxSsrc;
receive_config_.rtp.rtx[payload_type].payload_type = kSendRtxPayloadType;
}
@@ -643,11 +646,19 @@ TEST_F(CallTest, UsesFrameCallbacks) {
receiver_transport.SetReceiver(sender_call_->Receiver());
CreateTestConfigs();
- send_config_.encoder = NULL;
- send_config_.codec = sender_call_->GetVideoCodecs()[0];
- send_config_.codec.width = kWidth;
- send_config_.codec.height = kHeight;
+ scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
+ send_config_.encoder_settings.encoder = encoder.get();
+ send_config_.encoder_settings.payload_name = "VP8";
+ ASSERT_EQ(1u, send_config_.encoder_settings.streams.size())
+ << "Test setup error.";
+ send_config_.encoder_settings.streams[0].width = kWidth;
+ send_config_.encoder_settings.streams[0].height = kHeight;
send_config_.pre_encode_callback = &pre_encode_callback;
+ receive_config_.codecs.clear();
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config_.encoder_settings);
+ receive_config_.external_decoders.clear();
+ receive_config_.codecs.push_back(codec);
receive_config_.pre_render_callback = &pre_render_callback;
receive_config_.renderer = &renderer;
@@ -949,7 +960,7 @@ TEST_F(CallTest, SendsAndReceivesMultipleStreams) {
done_->Set();
}
- void Wait() { done_->Wait(kDefaultTimeoutMs); }
+ EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
private:
test::FrameGeneratorCapturer** capturer_;
@@ -977,35 +988,49 @@ TEST_F(CallTest, SendsAndReceivesMultipleStreams) {
VideoOutputObserver* observers[kNumStreams];
test::FrameGeneratorCapturer* frame_generators[kNumStreams];
+ scoped_ptr<VP8Encoder> encoders[kNumStreams];
+ for (size_t i = 0; i < kNumStreams; ++i)
+ encoders[i].reset(VP8Encoder::Create());
+
for (size_t i = 0; i < kNumStreams; ++i) {
uint32_t ssrc = codec_settings[i].ssrc;
int width = codec_settings[i].width;
int height = codec_settings[i].height;
observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
+ VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
+ send_config.rtp.ssrcs.push_back(ssrc);
+ send_config.encoder_settings =
+ test::CreateEncoderSettings(encoders[i].get(), "VP8", 124, 1);
+ VideoStream* stream = &send_config.encoder_settings.streams[0];
+ stream->width = width;
+ stream->height = height;
+ stream->max_framerate = 5;
+ stream->min_bitrate_bps = stream->target_bitrate_bps =
+ stream->max_bitrate_bps = 100000;
+ send_streams[i] = sender_call->CreateVideoSendStream(send_config);
+ send_streams[i]->StartSending();
+
VideoReceiveStream::Config receive_config =
receiver_call->GetDefaultReceiveConfig();
receive_config.renderer = observers[i];
receive_config.rtp.remote_ssrc = ssrc;
receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config.encoder_settings);
+ receive_config.codecs.push_back(codec);
receive_streams[i] =
receiver_call->CreateVideoReceiveStream(receive_config);
receive_streams[i]->StartReceiving();
- VideoSendStream::Config send_config = sender_call->GetDefaultSendConfig();
- send_config.rtp.ssrcs.push_back(ssrc);
- send_config.codec.width = width;
- send_config.codec.height = height;
- send_streams[i] = sender_call->CreateVideoSendStream(send_config);
- send_streams[i]->StartSending();
-
frame_generators[i] = test::FrameGeneratorCapturer::Create(
send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
frame_generators[i]->Start();
}
for (size_t i = 0; i < kNumStreams; ++i) {
- observers[i]->Wait();
+ EXPECT_EQ(kEventSignaled, observers[i]->Wait())
+ << "Timed out while waiting for observer " << i << " to render.";
}
for (size_t i = 0; i < kNumStreams; ++i) {
@@ -1074,7 +1099,8 @@ TEST_F(CallTest, ObserversEncodedFrames) {
StartSending();
scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
- send_config_.codec.width, send_config_.codec.height));
+ send_config_.encoder_settings.streams[0].width,
+ send_config_.encoder_settings.streams[0].height));
send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
diff --git a/video/full_stack.cc b/video/full_stack.cc
index 9b0def6f..0d3c8ee9 100644
--- a/video/full_stack.cc
+++ b/video/full_stack.cc
@@ -18,15 +18,18 @@
#include "webrtc/call.h"
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
+#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/system_wrappers/interface/sleep.h"
-#include "webrtc/test/testsupport/fileutils.h"
#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/encoder_settings.h"
+#include "webrtc/test/fake_encoder.h"
#include "webrtc/test/frame_generator_capturer.h"
#include "webrtc/test/statistics.h"
+#include "webrtc/test/testsupport/fileutils.h"
#include "webrtc/typedefs.h"
DEFINE_int32(seconds, 10, "Seconds to run each clip.");
@@ -398,13 +401,15 @@ TEST_P(FullStackTest, NoPacketLoss) {
VideoSendStream::Config send_config = call->GetDefaultSendConfig();
send_config.rtp.ssrcs.push_back(kSendSsrc);
- // TODO(pbos): static_cast shouldn't be required after mflodman refactors the
- // VideoCodec struct.
- send_config.codec.width = static_cast<uint16_t>(params.clip.width);
- send_config.codec.height = static_cast<uint16_t>(params.clip.height);
- send_config.codec.minBitrate = params.bitrate;
- send_config.codec.startBitrate = params.bitrate;
- send_config.codec.maxBitrate = params.bitrate;
+ scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
+ send_config.encoder_settings =
+ test::CreateEncoderSettings(encoder.get(), "VP8", 124, 1);
+ VideoStream* stream = &send_config.encoder_settings.streams[0];
+ stream->width = params.clip.width;
+ stream->height = params.clip.height;
+ stream->min_bitrate_bps = stream->target_bitrate_bps =
+ stream->max_bitrate_bps = params.bitrate * 1000;
+ stream->max_framerate = params.clip.fps;
VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
analyzer.input_ = send_stream->Input();
@@ -422,6 +427,9 @@ TEST_P(FullStackTest, NoPacketLoss) {
<< ".yuv. Is this resource file present?";
VideoReceiveStream::Config receive_config = call->GetDefaultReceiveConfig();
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config.encoder_settings);
+ receive_config.codecs.push_back(codec);
receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
receive_config.renderer = &analyzer;
diff --git a/video/loopback.cc b/video/loopback.cc
index 48de326e..0131aa92 100644
--- a/video/loopback.cc
+++ b/video/loopback.cc
@@ -15,9 +15,12 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/call.h"
+#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/encoder_settings.h"
+#include "webrtc/test/fake_encoder.h"
#include "webrtc/test/flags.h"
#include "webrtc/test/run_loop.h"
#include "webrtc/test/run_tests.h"
@@ -53,16 +56,18 @@ TEST_F(LoopbackTest, Test) {
send_config.local_renderer = local_preview.get();
- // TODO(pbos): static_cast shouldn't be required after mflodman refactors the
- // VideoCodec struct.
- send_config.codec.width = static_cast<uint16_t>(test::flags::Width());
- send_config.codec.height = static_cast<uint16_t>(test::flags::Height());
- send_config.codec.minBitrate =
- static_cast<unsigned int>(test::flags::MinBitrate());
- send_config.codec.startBitrate =
- static_cast<unsigned int>(test::flags::StartBitrate());
- send_config.codec.maxBitrate =
- static_cast<unsigned int>(test::flags::MaxBitrate());
+ scoped_ptr<VP8Encoder> encoder(VP8Encoder::Create());
+ send_config.encoder_settings =
+ test::CreateEncoderSettings(encoder.get(), "VP8", 124, 1);
+ VideoStream* stream = &send_config.encoder_settings.streams[0];
+ stream->width = test::flags::Width();
+ stream->height = test::flags::Height();
+ stream->min_bitrate_bps = static_cast<int>(test::flags::MinBitrate()) * 1000;
+ stream->target_bitrate_bps =
+ static_cast<int>(test::flags::MaxBitrate()) * 1000;
+ stream->max_bitrate_bps = static_cast<int>(test::flags::MaxBitrate()) * 1000;
+ stream->max_framerate = 30;
+ stream->max_qp = 56;
VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
@@ -79,6 +84,9 @@ TEST_F(LoopbackTest, Test) {
receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
receive_config.renderer = loopback_video.get();
+ VideoCodec codec =
+ test::CreateDecoderVideoCodec(send_config.encoder_settings);
+ receive_config.codecs.push_back(codec);
VideoReceiveStream* receive_stream =
call->CreateVideoReceiveStream(receive_config);
diff --git a/video/rampup_tests.cc b/video/rampup_tests.cc
index a50ebb49..302c0a18 100644
--- a/video/rampup_tests.cc
+++ b/video/rampup_tests.cc
@@ -28,6 +28,7 @@
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_decoder.h"
#include "webrtc/test/fake_encoder.h"
#include "webrtc/test/frame_generator_capturer.h"
@@ -56,6 +57,7 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
new RTPPayloadRegistry(-1,
RTPPayloadStrategy::CreateStrategy(false))),
clock_(clock),
+ expected_bitrate_bps_(0),
rtx_media_ssrcs_(rtx_media_ssrcs),
total_sent_(0),
padding_sent_(0),
@@ -82,10 +84,15 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
rbe_factory.Create(this, clock, kRemoteBitrateEstimatorMinBitrateBps));
}
+ void set_expected_bitrate_bps(unsigned int expected_bitrate_bps) {
+ expected_bitrate_bps_ = expected_bitrate_bps;
+ }
+
virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
- unsigned int bitrate) {
+ unsigned int bitrate) OVERRIDE {
CriticalSectionScoped lock(critical_section_.get());
- if (bitrate >= kExpectedBitrateBps) {
+ assert(expected_bitrate_bps_ > 0);
+ if (bitrate >= expected_bitrate_bps_) {
// Just trigger if there was any rtx padding packet.
if (rtx_media_ssrcs_.empty() || rtx_media_sent_ > 0) {
TriggerTestDone();
@@ -140,8 +147,6 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
EventTypeWrapper Wait() { return test_done_->Wait(120 * 1000); }
private:
- static const unsigned int kExpectedBitrateBps = 1200000;
-
void ReportResult(const std::string& measurement,
size_t value,
const std::string& units) {
@@ -170,6 +175,7 @@ class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
scoped_ptr<RTPPayloadRegistry> payload_registry_;
scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
Clock* clock_;
+ unsigned int expected_bitrate_bps_;
SsrcMap rtx_media_ssrcs_;
size_t total_sent_;
size_t padding_sent_;
@@ -418,10 +424,8 @@ class RampUpTest : public ::testing::Test {
receiver_transport.SetReceiver(call->Receiver());
test::FakeEncoder encoder(Clock::GetRealTimeClock());
- send_config.encoder = &encoder;
- send_config.internal_source = false;
- test::FakeEncoder::SetCodecSettings(&send_config.codec, kNumberOfStreams);
- send_config.codec.plType = 125;
+ send_config.encoder_settings =
+ test::CreateEncoderSettings(&encoder, "FAKE", 125, kNumberOfStreams);
send_config.pacing = pacing;
send_config.rtp.nack.rtp_history_ms = 1000;
send_config.rtp.ssrcs = ssrcs;
@@ -432,14 +436,28 @@ class RampUpTest : public ::testing::Test {
send_config.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsoluteSendTimeExtensionId));
+ // Use target bitrates for all streams except the last one and the min
+ // bitrate for the last one. This ensures that we reach enough bitrate to
+ // send all streams.
+ int expected_bitrate_bps =
+ send_config.encoder_settings.streams.back().min_bitrate_bps;
+ for (size_t i = 0; i < send_config.encoder_settings.streams.size() - 1;
+ ++i) {
+ expected_bitrate_bps +=
+ send_config.encoder_settings.streams[i].target_bitrate_bps;
+ }
+
+ stream_observer.set_expected_bitrate_bps(expected_bitrate_bps);
+
VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
- test::FrameGeneratorCapturer::Create(send_stream->Input(),
- send_config.codec.width,
- send_config.codec.height,
- 30,
- Clock::GetRealTimeClock()));
+ test::FrameGeneratorCapturer::Create(
+ send_stream->Input(),
+ send_config.encoder_settings.streams.back().width,
+ send_config.encoder_settings.streams.back().height,
+ send_config.encoder_settings.streams.back().max_framerate,
+ Clock::GetRealTimeClock()));
send_stream->StartSending();
frame_generator_capturer->Start();
@@ -470,12 +488,8 @@ class RampUpTest : public ::testing::Test {
receiver_transport.SetReceiver(call->Receiver());
test::FakeEncoder encoder(Clock::GetRealTimeClock());
- send_config.encoder = &encoder;
- send_config.internal_source = false;
- test::FakeEncoder::SetCodecSettings(&send_config.codec, number_of_streams);
- send_config.codec.plType = 125;
- send_config.codec.startBitrate =
- send_config.codec.simulcastStream[0].minBitrate;
+ send_config.encoder_settings =
+ test::CreateEncoderSettings(&encoder, "FAKE", 125, number_of_streams);
send_config.rtp.nack.rtp_history_ms = 1000;
send_config.rtp.ssrcs.insert(
send_config.rtp.ssrcs.begin(), ssrcs.begin(), ssrcs.end());
@@ -486,10 +500,21 @@ class RampUpTest : public ::testing::Test {
VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
stream_observer.SetSendStream(send_stream);
+ size_t width = 0;
+ size_t height = 0;
+ for (size_t i = 0; i < send_config.encoder_settings.streams.size(); ++i) {
+ size_t stream_width = send_config.encoder_settings.streams[i].width;
+ size_t stream_height = send_config.encoder_settings.streams[i].height;
+ if (stream_width > width)
+ width = stream_width;
+ if (stream_height > height)
+ height = stream_height;
+ }
+
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
test::FrameGeneratorCapturer::Create(send_stream->Input(),
- send_config.codec.width,
- send_config.codec.height,
+ width,
+ height,
30,
Clock::GetRealTimeClock()));
@@ -522,7 +547,8 @@ TEST_F(RampUpTest, WithoutPacing) { RunRampUpTest(false, false); }
TEST_F(RampUpTest, WithPacing) { RunRampUpTest(true, false); }
-TEST_F(RampUpTest, WithPacingAndRtx) { RunRampUpTest(true, true); }
+// TODO(pbos): Re-enable, webrtc:2992.
+TEST_F(RampUpTest, DISABLED_WithPacingAndRtx) { RunRampUpTest(true, true); }
TEST_F(RampUpTest, UpDownUpOneStream) { RunRampUpDownUpTest(1, false); }
diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc
index 337eda4d..0301f095 100644
--- a/video/video_receive_stream.cc
+++ b/video/video_receive_stream.cc
@@ -99,6 +99,7 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
codec_ = ViECodec::GetInterface(video_engine);
+ assert(!config_.codecs.empty());
for (size_t i = 0; i < config_.codecs.size(); ++i) {
if (codec_->SetReceiveCodec(channel_, config_.codecs[i]) != 0) {
// TODO(pbos): Abort gracefully, this can be a runtime error.
diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc
index 5cacb565..a480acd2 100644
--- a/video/video_send_stream.cc
+++ b/video/video_send_stream.cc
@@ -21,6 +21,7 @@
#include "webrtc/video_engine/include/vie_image_process.h"
#include "webrtc/video_engine/include/vie_network.h"
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
+#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/video_send_stream.h"
namespace webrtc {
@@ -108,24 +109,26 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
network_->SetMTU(channel_,
static_cast<unsigned int>(config_.rtp.max_packet_size + 28));
- if (config.encoder) {
- external_codec_ = ViEExternalCodec::GetInterface(video_engine);
- if (external_codec_->RegisterExternalSendCodec(channel_,
- config.codec.plType,
- config.encoder,
- config.internal_source) !=
- 0) {
- abort();
- }
+ assert(config.encoder_settings.encoder != NULL);
+ assert(config.encoder_settings.payload_type >= 0);
+ assert(config.encoder_settings.payload_type <= 127);
+ external_codec_ = ViEExternalCodec::GetInterface(video_engine);
+ if (external_codec_->RegisterExternalSendCodec(
+ channel_,
+ config.encoder_settings.payload_type,
+ config.encoder_settings.encoder,
+ false) != 0) {
+ abort();
}
codec_ = ViECodec::GetInterface(video_engine);
- if (!SetCodec(config_.codec))
+ if (!ReconfigureVideoEncoder(config_.encoder_settings.streams,
+ config_.encoder_settings.encoder_settings)) {
abort();
+ }
- if (overuse_observer) {
+ if (overuse_observer)
video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer);
- }
image_process_ = ViEImageProcess::GetInterface(video_engine);
image_process_->RegisterPreEncodeCallback(channel_,
@@ -170,10 +173,8 @@ VideoSendStream::~VideoSendStream() {
capture_->DisconnectCaptureDevice(channel_);
capture_->ReleaseCaptureDevice(capture_id_);
- if (external_codec_) {
- external_codec_->DeRegisterExternalSendCodec(channel_,
- config_.codec.plType);
- }
+ external_codec_->DeRegisterExternalSendCodec(
+ channel_, config_.encoder_settings.payload_type);
video_engine_base_->DeleteChannel(channel_);
@@ -221,11 +222,91 @@ void VideoSendStream::StopSending() {
transport_adapter_.Disable();
}
-bool VideoSendStream::SetCodec(const VideoCodec& codec) {
- assert(config_.rtp.ssrcs.size() >= codec.numberOfSimulcastStreams);
+bool VideoSendStream::ReconfigureVideoEncoder(
+ const std::vector<VideoStream>& streams,
+ void* encoder_settings) {
+ assert(!streams.empty());
+ assert(config_.rtp.ssrcs.size() >= streams.size());
+ // TODO(pbos): Wire encoder_settings.
+ assert(encoder_settings == NULL);
+ // VideoStreams in config_.encoder_settings need to be locked.
CriticalSectionScoped crit(codec_lock_.get());
- if (codec_->SetSendCodec(channel_, codec) != 0)
+
+ VideoCodec video_codec;
+ memset(&video_codec, 0, sizeof(video_codec));
+ video_codec.codecType =
+ (config_.encoder_settings.payload_name == "VP8" ? kVideoCodecVP8
+ : kVideoCodecGeneric);
+
+ if (video_codec.codecType == kVideoCodecVP8) {
+ video_codec.codecSpecific.VP8.resilience = kResilientStream;
+ video_codec.codecSpecific.VP8.numberOfTemporalLayers = 1;
+ video_codec.codecSpecific.VP8.denoisingOn = true;
+ video_codec.codecSpecific.VP8.errorConcealmentOn = false;
+ video_codec.codecSpecific.VP8.automaticResizeOn = false;
+ video_codec.codecSpecific.VP8.frameDroppingOn = true;
+ video_codec.codecSpecific.VP8.keyFrameInterval = 3000;
+ }
+
+ strncpy(video_codec.plName,
+ config_.encoder_settings.payload_name.c_str(),
+ kPayloadNameSize - 1);
+ video_codec.plName[kPayloadNameSize - 1] = '\0';
+ video_codec.plType = config_.encoder_settings.payload_type;
+ video_codec.numberOfSimulcastStreams =
+ static_cast<unsigned char>(streams.size());
+ video_codec.minBitrate = streams[0].min_bitrate_bps / 1000;
+ assert(streams.size() <= kMaxSimulcastStreams);
+ for (size_t i = 0; i < streams.size(); ++i) {
+ SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
+ assert(streams[i].width > 0);
+ assert(streams[i].height > 0);
+ assert(streams[i].max_framerate > 0);
+ // Different framerates not supported per stream at the moment.
+ assert(streams[i].max_framerate == streams[0].max_framerate);
+ assert(streams[i].min_bitrate_bps >= 0);
+ assert(streams[i].target_bitrate_bps >= streams[i].min_bitrate_bps);
+ assert(streams[i].max_bitrate_bps >= streams[i].target_bitrate_bps);
+ assert(streams[i].max_qp >= 0);
+
+ sim_stream->width = static_cast<unsigned short>(streams[i].width);
+ sim_stream->height = static_cast<unsigned short>(streams[i].height);
+ sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000;
+ sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
+ sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
+ sim_stream->qpMax = streams[i].max_qp;
+ // TODO(pbos): Implement mapping for temporal layers.
+ assert(streams[i].temporal_layers.empty());
+
+ video_codec.width = std::max(video_codec.width,
+ static_cast<unsigned short>(streams[i].width));
+ video_codec.height = std::max(
+ video_codec.height, static_cast<unsigned short>(streams[i].height));
+ video_codec.minBitrate =
+ std::min(video_codec.minBitrate,
+ static_cast<unsigned int>(streams[i].min_bitrate_bps / 1000));
+ video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
+ video_codec.qpMax = std::max(video_codec.qpMax,
+ static_cast<unsigned int>(streams[i].max_qp));
+ }
+
+ if (video_codec.minBitrate < kViEMinCodecBitrate)
+ video_codec.minBitrate = kViEMinCodecBitrate;
+ if (video_codec.maxBitrate < kViEMinCodecBitrate)
+ video_codec.maxBitrate = kViEMinCodecBitrate;
+
+ video_codec.startBitrate = 300;
+
+ if (video_codec.startBitrate < video_codec.minBitrate)
+ video_codec.startBitrate = video_codec.minBitrate;
+ if (video_codec.startBitrate > video_codec.maxBitrate)
+ video_codec.startBitrate = video_codec.maxBitrate;
+
+ assert(config_.encoder_settings.streams[0].max_framerate > 0);
+ video_codec.maxFramerate = config_.encoder_settings.streams[0].max_framerate;
+
+ if (codec_->SetSendCodec(channel_, video_codec) != 0)
return false;
for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
@@ -235,8 +316,8 @@ bool VideoSendStream::SetCodec(const VideoCodec& codec) {
static_cast<unsigned char>(i));
}
- if (&config_.codec != &codec)
- config_.codec = codec;
+ config_.encoder_settings.streams = streams;
+ config_.encoder_settings.encoder_settings = encoder_settings;
if (config_.rtp.rtx.ssrcs.empty())
return true;
@@ -256,11 +337,6 @@ bool VideoSendStream::SetCodec(const VideoCodec& codec) {
return true;
}
-VideoCodec VideoSendStream::GetCodec() {
- CriticalSectionScoped crit(codec_lock_.get());
- return config_.codec;
-}
-
bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
return network_->ReceivedRTCPPacket(
channel_, packet, static_cast<int>(length)) == 0;
diff --git a/video/video_send_stream.h b/video/video_send_stream.h
index 3ea4fbfb..15cf6424 100644
--- a/video/video_send_stream.h
+++ b/video/video_send_stream.h
@@ -50,8 +50,8 @@ class VideoSendStream : public webrtc::VideoSendStream,
virtual void StopSending() OVERRIDE;
- virtual bool SetCodec(const VideoCodec& codec) OVERRIDE;
- virtual VideoCodec GetCodec() OVERRIDE;
+ virtual bool ReconfigureVideoEncoder(const std::vector<VideoStream>& streams,
+ void* encoder_settings) OVERRIDE;
virtual Stats GetStats() const OVERRIDE;
diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc
index 6a6b0e13..5a496988 100644
--- a/video/video_send_stream_tests.cc
+++ b/video/video_send_stream_tests.cc
@@ -23,6 +23,7 @@
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/system_wrappers/interface/thread_wrapper.h"
#include "webrtc/test/direct_transport.h"
+#include "webrtc/test/encoder_settings.h"
#include "webrtc/test/fake_encoder.h"
#include "webrtc/test/configurable_frame_size_encoder.h"
#include "webrtc/test/frame_generator_capturer.h"
@@ -59,17 +60,16 @@ class VideoSendStreamTest : public ::testing::Test {
call->DestroyVideoSendStream(send_stream_);
}
- VideoSendStream::Config GetSendTestConfig(Call* call,
- size_t number_of_streams) {
- assert(number_of_streams <= kNumSendSsrcs);
+ VideoSendStream::Config GetSendTestConfig(Call* call, size_t num_streams) {
+ assert(num_streams <= kNumSendSsrcs);
VideoSendStream::Config config = call->GetDefaultSendConfig();
- config.encoder = &fake_encoder_;
- config.internal_source = false;
- for (size_t i = 0; i < number_of_streams; ++i)
+ config.encoder_settings = test::CreateEncoderSettings(
+ &fake_encoder_, "FAKE", kFakeSendPayloadType, num_streams);
+ config.encoder_settings.encoder = &fake_encoder_;
+ config.encoder_settings.payload_type = kFakeSendPayloadType;
+ for (size_t i = 0; i < num_streams; ++i)
config.rtp.ssrcs.push_back(kSendSsrcs[i]);
config.pacing = true;
- test::FakeEncoder::SetCodecSettings(&config.codec, number_of_streams);
- config.codec.plType = kFakeSendPayloadType;
return config;
}
@@ -161,15 +161,17 @@ void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs,
if (num_ssrcs > 1) {
// Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
- for (size_t i = 0; i < num_ssrcs; ++i) {
- send_config.codec.simulcastStream[i].minBitrate = 10;
- send_config.codec.simulcastStream[i].targetBitrate = 10;
- send_config.codec.simulcastStream[i].maxBitrate = 10;
+ std::vector<VideoStream>* streams = &send_config.encoder_settings.streams;
+ for (size_t i = 0; i < streams->size(); ++i) {
+ (*streams)[i].min_bitrate_bps = 10000;
+ (*streams)[i].target_bitrate_bps = 10000;
+ (*streams)[i].max_bitrate_bps = 10000;
}
}
+ std::vector<VideoStream> all_streams = send_config.encoder_settings.streams;
if (send_single_ssrc_first)
- send_config.codec.numberOfSimulcastStreams = 1;
+ send_config.encoder_settings.streams.resize(1);
send_stream_ = call->CreateVideoSendStream(send_config);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
@@ -184,9 +186,7 @@ void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs,
if (send_single_ssrc_first) {
// Set full simulcast and continue with the rest of the SSRCs.
- send_config.codec.numberOfSimulcastStreams =
- static_cast<unsigned char>(num_ssrcs);
- send_stream_->SetCodec(send_config.codec);
+ send_stream_->ReconfigureVideoEncoder(all_streams, NULL);
EXPECT_EQ(kEventSignaled, observer.Wait())
<< "Timed out while waiting on additional SSRCs.";
}
@@ -338,7 +338,7 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
- send_config.encoder = &encoder;
+ send_config.encoder_settings.encoder = &encoder;
send_config.rtp.extensions.push_back(
RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
@@ -766,12 +766,11 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
send_config.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
}
- if (format == kVP8) {
- strcpy(send_config.codec.plName, "VP8");
- send_config.codec.codecType = kVideoCodecVP8;
- }
+ if (format == kVP8)
+ send_config.encoder_settings.payload_name = "VP8";
+
send_config.pacing = false;
- send_config.encoder = &encoder;
+ send_config.encoder_settings.encoder = &encoder;
send_config.rtp.max_packet_size = kMaxPacketSize;
send_config.post_encode_callback = &observer;
@@ -801,68 +800,6 @@ TEST_F(VideoSendStreamTest, FragmentsVp8AccordingToMaxPacketSizeWithFec) {
TestPacketFragmentationSize(kVP8, true);
}
-TEST_F(VideoSendStreamTest, CanChangeSendCodec) {
- static const uint8_t kFirstPayloadType = 121;
- static const uint8_t kSecondPayloadType = 122;
-
- class CodecChangeObserver : public test::RtpRtcpObserver {
- public:
- CodecChangeObserver(VideoSendStream** send_stream_ptr)
- : RtpRtcpObserver(30 * 1000),
- received_first_payload_(EventWrapper::Create()),
- send_stream_ptr_(send_stream_ptr) {}
-
- virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
- RTPHeader header;
- EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
- if (header.payloadType == kFirstPayloadType) {
- received_first_payload_->Set();
- } else if (header.payloadType == kSecondPayloadType) {
- observation_complete_->Set();
- }
-
- return SEND_PACKET;
- }
-
- virtual EventTypeWrapper Wait() OVERRIDE {
- EXPECT_EQ(kEventSignaled, received_first_payload_->Wait(30 * 1000))
- << "Timed out while waiting for first payload.";
-
- EXPECT_TRUE((*send_stream_ptr_)->SetCodec(second_codec_));
-
- EXPECT_EQ(kEventSignaled, RtpRtcpObserver::Wait())
- << "Timed out while waiting for second payload type.";
-
- // Return OK regardless, prevents double error reporting.
- return kEventSignaled;
- }
-
- void SetSecondCodec(const VideoCodec& codec) { second_codec_ = codec; }
-
- private:
- scoped_ptr<EventWrapper> received_first_payload_;
- VideoSendStream** send_stream_ptr_;
- VideoCodec second_codec_;
- } observer(&send_stream_);
-
- Call::Config call_config(observer.SendTransport());
- scoped_ptr<Call> call(Call::Create(call_config));
-
- std::vector<VideoCodec> codecs = call->GetVideoCodecs();
- ASSERT_GE(codecs.size(), 2u)
- << "Test needs at least 2 separate codecs to work.";
- codecs[0].plType = kFirstPayloadType;
- codecs[1].plType = kSecondPayloadType;
- observer.SetSecondCodec(codecs[1]);
-
- VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
- send_config.codec = codecs[0];
- send_config.encoder = NULL;
-
- RunSendTest(call.get(), send_config, &observer);
-}
-
// The test will go through a number of phases.
// 1. Start sending packets.
// 2. As soon as the RTP stream has been detected, signal a low REMB value to
@@ -1005,11 +942,10 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
send_config.rtp.nack.rtp_history_ms = 1000;
send_config.pre_encode_callback = &observer;
send_config.suspend_below_min_bitrate = true;
- unsigned int min_bitrate_bps =
- send_config.codec.simulcastStream[0].minBitrate * 1000;
+ int min_bitrate_bps = send_config.encoder_settings.streams[0].min_bitrate_bps;
observer.set_low_remb_bps(min_bitrate_bps - 10000);
- unsigned int threshold_window = std::max(min_bitrate_bps / 10, 10000u);
- ASSERT_GT(send_config.codec.simulcastStream[0].maxBitrate * 1000,
+ int threshold_window = std::max(min_bitrate_bps / 10, 10000);
+ ASSERT_GT(send_config.encoder_settings.streams[0].max_bitrate_bps,
min_bitrate_bps + threshold_window + 5000);
observer.set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
diff --git a/video_send_stream.h b/video_send_stream.h
index 8279c052..3fd6ef7d 100644
--- a/video_send_stream.h
+++ b/video_send_stream.h
@@ -61,12 +61,26 @@ class VideoSendStream {
post_encode_callback(NULL),
local_renderer(NULL),
render_delay_ms(0),
- encoder(NULL),
- internal_source(false),
target_delay_ms(0),
pacing(false),
suspend_below_min_bitrate(false) {}
- VideoCodec codec;
+ struct EncoderSettings {
+ EncoderSettings()
+ : payload_type(-1), encoder(NULL), encoder_settings(NULL) {}
+ std::string payload_name;
+ int payload_type;
+
+ // Uninitialized VideoEncoder instance to be used for encoding. Will be
+ // initialized from inside the VideoSendStream.
+ webrtc::VideoEncoder* encoder;
+ // TODO(pbos): Wire up encoder-specific settings.
+ // Encoder-specific settings, will be passed to the encoder during
+ // initialization.
+ void* encoder_settings;
+
+ // List of stream settings to encode (resolution, bitrates, framerate).
+ std::vector<VideoStream> streams;
+ } encoder_settings;
static const size_t kDefaultMaxPacketSize = 1500 - 40; // TCP over IPv4.
struct Rtp {
@@ -125,13 +139,6 @@ class VideoSendStream {
// Only valid if |renderer| is set.
int render_delay_ms;
- // TODO(mflodman) Move VideoEncoder to common_types.h and redefine.
- // External encoding. 'encoder' is the external encoder instance and
- // 'internal_source' is set to true if the encoder also captures the video
- // frames.
- VideoEncoder* encoder;
- bool internal_source;
-
// Target delay in milliseconds. A positive value indicates this stream is
// used for streaming instead of a real-time call.
int target_delay_ms;
@@ -155,8 +162,11 @@ class VideoSendStream {
virtual void StartSending() = 0;
virtual void StopSending() = 0;
- virtual bool SetCodec(const VideoCodec& codec) = 0;
- virtual VideoCodec GetCodec() = 0;
+ // Set which streams to send. Must have at least as many SSRCs as configured
+ // in the config. Encoder settings are passed on to the encoder instance along
+ // with the VideoStream settings.
+ virtual bool ReconfigureVideoEncoder(const std::vector<VideoStream>& streams,
+ void* encoder_settings) = 0;
virtual Stats GetStats() const = 0;