Make VideoSendStream/VideoReceiveStream configs const.

Benefits of this is that the send config previously had unclear locking
requirements, a lock was used to lock parts parts of it while
reconfiguring the VideoEncoder. Primary work was splitting out video
streams from config as well as encoder_settings as these change on
ReconfigureVideoEncoder. Now threading requirements for both member
configs are clear (as they are read-only), and encoder_settings doesn't
stay in the config as a stale pointer.

CreateVideoSendStream now takes video streams separately as well as the
encoder_settings pointer, analogous to ReconfigureVideoEncoder.

This change required changing so that pacing is silently enabled when
using suspend_below_min_bitrate rather than silently setting it.

R=henrik.lundin@webrtc.org, mflodman@webrtc.org, pthatcher@webrtc.org, stefan@webrtc.org
BUG=3260

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6349 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pbos@webrtc.org 2014-06-06 10:49:19 +00:00
parent 4b83a471de
commit 6ae48c6609
19 changed files with 400 additions and 384 deletions

View File

@ -197,22 +197,15 @@ WebRtcVideoEncoderFactory2::~WebRtcVideoEncoderFactory2() {
class DefaultVideoEncoderFactory : public WebRtcVideoEncoderFactory2 {
public:
virtual bool CreateEncoderSettings(
webrtc::VideoSendStream::Config::EncoderSettings* encoder_settings,
const VideoOptions& options,
virtual std::vector<webrtc::VideoStream> CreateVideoStreams(
const VideoCodec& codec,
const VideoOptions& options,
size_t num_streams) OVERRIDE {
assert(SupportsCodec(codec));
if (num_streams != 1) {
LOG(LS_ERROR) << "Unsupported number of streams: " << num_streams;
return false;
return std::vector<webrtc::VideoStream>();
}
if (!SupportsCodec(codec)) {
LOG(LS_ERROR) << "Can't create encoder settings for unsupported codec: '"
<< codec.name << "'";
return false;
}
*encoder_settings = webrtc::VideoSendStream::Config::EncoderSettings();
webrtc::VideoStream stream;
stream.width = codec.width;
@ -230,13 +223,16 @@ class DefaultVideoEncoderFactory : public WebRtcVideoEncoderFactory2 {
int max_qp = 56;
codec.GetParam(kCodecParamMaxQuantization, &max_qp);
stream.max_qp = max_qp;
encoder_settings->streams.push_back(stream);
std::vector<webrtc::VideoStream> streams;
streams.push_back(stream);
return streams;
}
encoder_settings->encoder = webrtc::VP8Encoder::Create();
encoder_settings->payload_type = kDefaultVideoCodecPref.payload_type;
encoder_settings->payload_name = kDefaultVideoCodecPref.name;
return true;
virtual webrtc::VideoEncoder* CreateVideoEncoder(
const VideoCodec& codec,
const VideoOptions& options) OVERRIDE {
assert(SupportsCodec(codec));
return webrtc::VP8Encoder::Create();
}
virtual bool SupportsCodec(const VideoCodec& codec) OVERRIDE {
@ -471,11 +467,11 @@ WebRtcVideoEncoderFactory2* WebRtcVideoEngine2::GetVideoEncoderFactory() const {
return default_video_encoder_factory_.get();
}
// Thin map between cricket::VideoFrame and an existing webrtc::I420VideoFrame
// Thin map between VideoFrame and an existing webrtc::I420VideoFrame
// to avoid having to copy the rendered VideoFrame prematurely.
// This implementation is only safe to use in a const context and should never
// be written to.
class WebRtcVideoRenderFrame : public cricket::VideoFrame {
class WebRtcVideoRenderFrame : public VideoFrame {
public:
explicit WebRtcVideoRenderFrame(const webrtc::I420VideoFrame* frame)
: frame_(frame) {}
@ -924,14 +920,17 @@ bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
// CreateEncoderSettings will allocate a suitable VideoEncoder instance
// matching current settings.
if (!encoder_factory_->CreateEncoderSettings(&config.encoder_settings,
options_,
codec_settings.codec,
config.rtp.ssrcs.size())) {
LOG(LS_ERROR) << "Failed to create suitable encoder settings.";
std::vector<webrtc::VideoStream> video_streams =
encoder_factory_->CreateVideoStreams(
codec_settings.codec, options_, config.rtp.ssrcs.size());
if (video_streams.empty()) {
return false;
}
config.encoder_settings.encoder =
encoder_factory_->CreateVideoEncoder(codec_settings.codec, options_);
config.encoder_settings.payload_name = codec_settings.codec.name;
config.encoder_settings.payload_type = codec_settings.codec.id;
config.rtp.c_name = sp.cname;
config.rtp.fec = codec_settings.fec;
if (!config.rtp.rtx.ssrcs.empty()) {
@ -942,7 +941,12 @@ bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
config.rtp.max_packet_size = kVideoMtu;
WebRtcVideoSendStream* stream =
new WebRtcVideoSendStream(call_.get(), config, encoder_factory_);
new WebRtcVideoSendStream(call_.get(),
config,
options_,
codec_settings.codec,
video_streams,
encoder_factory_);
send_streams_[ssrc] = stream;
if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
@ -1339,21 +1343,35 @@ void WebRtcVideoChannel2::SetCodecForAllSendStreams(
}
}
WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
VideoSendStreamParameters(
const webrtc::VideoSendStream::Config& config,
const VideoOptions& options,
const VideoCodec& codec,
const std::vector<webrtc::VideoStream>& video_streams)
: config(config),
options(options),
codec(codec),
video_streams(video_streams) {
}
WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
webrtc::Call* call,
const webrtc::VideoSendStream::Config& config,
const VideoOptions& options,
const VideoCodec& codec,
const std::vector<webrtc::VideoStream>& video_streams,
WebRtcVideoEncoderFactory2* encoder_factory)
: call_(call),
config_(config),
parameters_(config, options, codec, video_streams),
encoder_factory_(encoder_factory),
capturer_(NULL),
stream_(NULL),
sending_(false),
muted_(false),
format_(static_cast<int>(config.encoder_settings.streams.back().height),
static_cast<int>(config.encoder_settings.streams.back().width),
VideoFormat::FpsToInterval(
config.encoder_settings.streams.back().max_framerate),
format_(static_cast<int>(video_streams.back().height),
static_cast<int>(video_streams.back().width),
VideoFormat::FpsToInterval(video_streams.back().max_framerate),
FOURCC_I420) {
RecreateWebRtcStream();
}
@ -1361,7 +1379,7 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
DisconnectCapturer();
call_->DestroyVideoSendStream(stream_);
delete config_.encoder_settings.encoder;
delete parameters_.config.encoder_settings.encoder;
}
static void SetWebRtcFrameToBlack(webrtc::I420VideoFrame* video_frame) {
@ -1428,8 +1446,8 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
}
LOG(LS_VERBOSE) << "SwapFrame: " << video_frame_.width() << "x"
<< video_frame_.height() << " -> (codec) "
<< config_.encoder_settings.streams.back().width << "x"
<< config_.encoder_settings.streams.back().height;
<< parameters_.video_streams.back().width << "x"
<< parameters_.video_streams.back().height;
stream_->Input()->SwapFrame(&video_frame_);
}
@ -1480,10 +1498,10 @@ bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
if (format.width == 0 && format.height == 0) {
LOG(LS_INFO)
<< "0x0 resolution selected. Captured frames will be dropped for ssrc: "
<< config_.rtp.ssrcs[0] << ".";
<< parameters_.config.rtp.ssrcs[0] << ".";
} else {
// TODO(pbos): Fix me, this only affects the last stream!
config_.encoder_settings.streams.back().max_framerate =
parameters_.video_streams.back().max_framerate =
VideoFormat::IntervalToFps(format.interval);
SetDimensions(format.width, format.height);
}
@ -1513,44 +1531,46 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
const VideoOptions& options,
const VideoCodecSettings& codec) {
talk_base::CritScope cs(&lock_);
webrtc::VideoEncoder* old_encoder = config_.encoder_settings.encoder;
if (!encoder_factory_->CreateEncoderSettings(
&config_.encoder_settings,
options,
codec.codec,
config_.encoder_settings.streams.size())) {
LOG(LS_ERROR) << "Could not create encoder settings for: '"
<< codec.codec.name
<< "'. This is most definitely a bug as SetCodec should only "
"receive codecs which the encoder factory claims to "
"support.";
std::vector<webrtc::VideoStream> video_streams =
encoder_factory_->CreateVideoStreams(
codec.codec, options, parameters_.video_streams.size());
if (video_streams.empty()) {
return;
}
parameters_.video_streams = video_streams;
format_ = VideoFormat(codec.codec.width,
codec.codec.height,
VideoFormat::FpsToInterval(30),
FOURCC_I420);
config_.rtp.fec = codec.fec;
webrtc::VideoEncoder* old_encoder =
parameters_.config.encoder_settings.encoder;
parameters_.config.encoder_settings.encoder =
encoder_factory_->CreateVideoEncoder(codec.codec, options);
parameters_.config.rtp.fec = codec.fec;
// TODO(pbos): Should changing RTX payload type be allowed?
parameters_.codec = codec.codec;
parameters_.options = options;
RecreateWebRtcStream();
delete old_encoder;
}
void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(int width,
int height) {
assert(!config_.encoder_settings.streams.empty());
int height) {
assert(!parameters_.video_streams.empty());
LOG(LS_VERBOSE) << "SetDimensions: " << width << "x" << height;
if (config_.encoder_settings.streams.back().width == width &&
config_.encoder_settings.streams.back().height == height) {
if (parameters_.video_streams.back().width == width &&
parameters_.video_streams.back().height == height) {
return;
}
// TODO(pbos): Fix me, this only affects the last stream!
config_.encoder_settings.streams.back().width = width;
config_.encoder_settings.streams.back().height = height;
// TODO(pbos): Last parameter shouldn't always be NULL?
if (!stream_->ReconfigureVideoEncoder(config_.encoder_settings.streams,
NULL)) {
parameters_.video_streams.back().width = width;
parameters_.video_streams.back().height = height;
// TODO(pbos): Wire up encoder_parameters, webrtc:3424.
if (!stream_->ReconfigureVideoEncoder(parameters_.video_streams, NULL)) {
LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: "
<< width << "x" << height;
return;
@ -1573,7 +1593,10 @@ void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
if (stream_ != NULL) {
call_->DestroyVideoSendStream(stream_);
}
stream_ = call_->CreateVideoSendStream(config_);
// TODO(pbos): Wire up encoder_parameters, webrtc:3424.
stream_ = call_->CreateVideoSendStream(
parameters_.config, parameters_.video_streams, NULL);
if (sending_) {
stream_->Start();
}

View File

@ -83,11 +83,15 @@ class WebRtcVideoChannel2;
class WebRtcVideoEncoderFactory2 {
public:
virtual ~WebRtcVideoEncoderFactory2();
virtual bool CreateEncoderSettings(
webrtc::VideoSendStream::Config::EncoderSettings* encoder_settings,
virtual std::vector<webrtc::VideoStream> CreateVideoStreams(
const VideoCodec& codec,
const VideoOptions& options,
const cricket::VideoCodec& codec,
size_t num_streams) = 0;
virtual webrtc::VideoEncoder* CreateVideoEncoder(
const VideoCodec& codec,
const VideoOptions& options) = 0;
virtual bool SupportsCodec(const cricket::VideoCodec& codec) = 0;
};
@ -258,7 +262,7 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
struct VideoCodecSettings {
VideoCodecSettings();
cricket::VideoCodec codec;
VideoCodec codec;
webrtc::FecConfig fec;
int rtx_payload_type;
};
@ -266,8 +270,11 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
class WebRtcVideoSendStream : public sigslot::has_slots<> {
public:
WebRtcVideoSendStream(webrtc::Call* call,
const webrtc::VideoSendStream::Config& config,
WebRtcVideoEncoderFactory2* encoder_factory);
const webrtc::VideoSendStream::Config& config,
const VideoOptions& options,
const VideoCodec& codec,
const std::vector<webrtc::VideoStream>& video_streams,
WebRtcVideoEncoderFactory2* encoder_factory);
~WebRtcVideoSendStream();
void SetCodec(const VideoOptions& options, const VideoCodecSettings& codec);
@ -281,6 +288,25 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
void Stop();
private:
// Parameters needed to reconstruct the underlying stream.
// webrtc::VideoSendStream doesn't support setting a lot of options on the
// fly, so when those need to be changed we tear down and reconstruct with
// similar parameters depending on which options changed etc.
struct VideoSendStreamParameters {
VideoSendStreamParameters(
const webrtc::VideoSendStream::Config& config,
const VideoOptions& options,
const VideoCodec& codec,
const std::vector<webrtc::VideoStream>& video_streams);
webrtc::VideoSendStream::Config config;
VideoOptions options;
VideoCodec codec;
// Sent resolutions + bitrates etc. by the underlying VideoSendStream,
// typically changes when setting a new resolution or reconfiguring
// bitrates.
std::vector<webrtc::VideoStream> video_streams;
};
void RecreateWebRtcStream();
void SetDimensions(int width, int height);
@ -289,7 +315,8 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
talk_base::CriticalSection lock_;
webrtc::VideoSendStream* stream_ GUARDED_BY(lock_);
webrtc::VideoSendStream::Config config_ GUARDED_BY(lock_);
VideoSendStreamParameters parameters_ GUARDED_BY(lock_);
VideoCapturer* capturer_ GUARDED_BY(lock_);
bool sending_ GUARDED_BY(lock_);
bool muted_ GUARDED_BY(lock_);

View File

@ -52,12 +52,12 @@ static const uint32 kRtxSsrcs1[] = {4};
namespace cricket {
class FakeVideoSendStream : public webrtc::VideoSendStream {
public:
explicit FakeVideoSendStream(const webrtc::VideoSendStream::Config& config)
: sending_(false) {
config_ = config;
}
FakeVideoSendStream(const webrtc::VideoSendStream::Config& config,
const std::vector<webrtc::VideoStream>& video_streams)
: sending_(false), config_(config), video_streams_(video_streams) {}
webrtc::VideoSendStream::Config GetConfig() { return config_; }
std::vector<webrtc::VideoStream> GetVideoStreams() { return video_streams_; }
bool IsSending() { return sending_; }
@ -68,9 +68,8 @@ class FakeVideoSendStream : public webrtc::VideoSendStream {
virtual bool ReconfigureVideoEncoder(
const std::vector<webrtc::VideoStream>& streams,
void* encoder_specific) OVERRIDE {
// TODO(pbos): Store encoder_specific ptr?
config_.encoder_settings.streams = streams;
const void* encoder_specific) OVERRIDE {
video_streams_ = streams;
return true;
}
@ -85,6 +84,7 @@ class FakeVideoSendStream : public webrtc::VideoSendStream {
bool sending_;
webrtc::VideoSendStream::Config config_;
std::vector<webrtc::VideoStream> video_streams_;
};
class FakeVideoReceiveStream : public webrtc::VideoReceiveStream {
@ -178,8 +178,11 @@ class FakeCall : public webrtc::Call {
}
virtual webrtc::VideoSendStream* CreateVideoSendStream(
const webrtc::VideoSendStream::Config& config) OVERRIDE {
FakeVideoSendStream* fake_stream = new FakeVideoSendStream(config);
const webrtc::VideoSendStream::Config& config,
const std::vector<webrtc::VideoStream>& video_streams,
const void* encoder_settings) OVERRIDE {
FakeVideoSendStream* fake_stream =
new FakeVideoSendStream(config, video_streams);
video_send_streams_.push_back(fake_stream);
return fake_stream;
}
@ -515,13 +518,10 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test {
FakeVideoSendStream* stream = AddSendStream();
webrtc::VideoSendStream::Config::EncoderSettings encoder_settings =
stream->GetConfig().encoder_settings;
ASSERT_EQ(1u, encoder_settings.streams.size());
EXPECT_EQ(atoi(min_bitrate),
encoder_settings.streams.back().min_bitrate_bps / 1000);
EXPECT_EQ(atoi(max_bitrate),
encoder_settings.streams.back().max_bitrate_bps / 1000);
std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
ASSERT_EQ(1u, video_streams.size());
EXPECT_EQ(atoi(min_bitrate), video_streams.back().min_bitrate_bps / 1000);
EXPECT_EQ(atoi(max_bitrate), video_streams.back().max_bitrate_bps / 1000);
VideoCodec codec;
EXPECT_TRUE(channel_->GetSendCodec(&codec));
@ -556,15 +556,14 @@ TEST_F(WebRtcVideoChannel2Test, DISABLED_StartSendBitrate) {
const unsigned int kVideoTargetSendBitrateKbps = 300;
const unsigned int kVideoMaxSendBitrateKbps = 2000;
FakeVideoSendStream* stream = AddSendStream();
webrtc::VideoSendStream::Config::EncoderSettings encoder_settings =
stream->GetConfig().encoder_settings;
ASSERT_EQ(1u, encoder_settings.streams.size());
std::vector<webrtc::VideoStream> video_streams = stream->GetVideoStreams();
ASSERT_EQ(1u, video_streams.size());
EXPECT_EQ(kVideoMinSendBitrateKbps,
encoder_settings.streams.back().min_bitrate_bps / 1000);
video_streams.back().min_bitrate_bps / 1000);
EXPECT_EQ(kVideoTargetSendBitrateKbps,
encoder_settings.streams.back().target_bitrate_bps / 1000);
video_streams.back().target_bitrate_bps / 1000);
EXPECT_EQ(kVideoMaxSendBitrateKbps,
encoder_settings.streams.back().max_bitrate_bps / 1000);
video_streams.back().max_bitrate_bps / 1000);
#if 0
// TODO(pbos): un-#if
VerifyVP8SendCodec(send_channel, kVP8Codec.width, kVP8Codec.height, 0,
@ -925,9 +924,8 @@ TEST_F(WebRtcVideoChannel2Test, SetSendCodecsWithMaxQuantization) {
codecs.push_back(kVp8Codec);
codecs[0].params[kCodecParamMaxQuantization] = kMaxQuantization;
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
EXPECT_EQ(
static_cast<unsigned int>(atoi(kMaxQuantization)),
AddSendStream()->GetConfig().encoder_settings.streams.back().max_qp);
EXPECT_EQ(static_cast<unsigned int>(atoi(kMaxQuantization)),
AddSendStream()->GetVideoStreams().back().max_qp);
VideoCodec codec;
EXPECT_TRUE(channel_->GetSendCodec(&codec));

View File

@ -83,7 +83,9 @@ class Call {
virtual VideoSendStream::Config GetDefaultSendConfig() = 0;
virtual VideoSendStream* CreateVideoSendStream(
const VideoSendStream::Config& config) = 0;
const VideoSendStream::Config& config,
const std::vector<VideoStream>& video_streams,
const void* encoder_settings) = 0;
virtual void DestroyVideoSendStream(VideoSendStream* send_stream) = 0;

View File

@ -16,18 +16,14 @@
namespace webrtc {
namespace test {
VideoSendStream::Config::EncoderSettings CreateEncoderSettings(
VideoEncoder* encoder,
const char* payload_name,
int payload_type,
size_t num_streams) {
std::vector<VideoStream> CreateVideoStreams(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];
std::vector<VideoStream> stream_settings(kNumSettings);
stream_settings[0].width = 320;
stream_settings[0].height = 180;
@ -52,28 +48,20 @@ VideoSendStream::Config::EncoderSettings CreateEncoderSettings(
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;
stream_settings.resize(num_streams);
return stream_settings;
}
VideoCodec CreateDecoderVideoCodec(
const VideoSendStream::Config::EncoderSettings& settings) {
assert(settings.streams.size() > 0);
const VideoSendStream::Config::EncoderSettings& encoder_settings) {
VideoCodec codec;
memset(&codec, 0, sizeof(codec));
codec.plType = settings.payload_type;
strcpy(codec.plName, settings.payload_name.c_str());
codec.plType = encoder_settings.payload_type;
strcpy(codec.plName, encoder_settings.payload_name.c_str());
codec.codecType =
(settings.payload_name == "VP8" ? kVideoCodecVP8 : kVideoCodecGeneric);
(encoder_settings.payload_name == "VP8" ? kVideoCodecVP8
: kVideoCodecGeneric);
if (codec.codecType == kVideoCodecVP8) {
codec.codecSpecific.VP8.resilience = kResilientStream;
@ -85,33 +73,9 @@ VideoCodec CreateDecoderVideoCodec(
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;
codec.width = 320;
codec.height = 180;
codec.startBitrate = codec.minBitrate = codec.maxBitrate = 300;
return codec;
}

View File

@ -14,14 +14,10 @@
namespace webrtc {
namespace test {
VideoSendStream::Config::EncoderSettings CreateEncoderSettings(
VideoEncoder* encoder,
const char* payload_name,
int payload_type,
size_t num_streams);
std::vector<VideoStream> CreateVideoStreams(size_t num_streams);
VideoCodec CreateDecoderVideoCodec(
const VideoSendStream::Config::EncoderSettings& settings);
const VideoSendStream::Config::EncoderSettings& encoder_settings);
} // namespace test
} // namespace webrtc

View File

@ -70,8 +70,10 @@ class BitrateEstimatorTest : public ::testing::Test {
send_config_ = sender_call_->GetDefaultSendConfig();
send_config_.rtp.ssrcs.push_back(kSendSsrc);
// Encoders will be set separately per stream.
send_config_.encoder_settings =
test::CreateEncoderSettings(NULL, "FAKE", kSendPayloadType, 1);
send_config_.encoder_settings.encoder = NULL;
send_config_.encoder_settings.payload_name = "FAKE";
send_config_.encoder_settings.payload_type = kSendPayloadType;
video_streams_ = test::CreateVideoStreams(1);
receive_config_ = receiver_call_->GetDefaultReceiveConfig();
assert(receive_config_.codecs.empty());
@ -169,15 +171,15 @@ class BitrateEstimatorTest : public ::testing::Test {
fake_decoder_() {
test_->send_config_.rtp.ssrcs[0]++;
test_->send_config_.encoder_settings.encoder = &fake_encoder_;
send_stream_ =
test_->sender_call_->CreateVideoSendStream(test_->send_config_);
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_ = test_->sender_call_->CreateVideoSendStream(
test_->send_config_, test_->video_streams_, NULL);
assert(test_->video_streams_.size() == 1);
frame_generator_capturer_.reset(
test::FrameGeneratorCapturer::Create(send_stream_->Input(),
test_->video_streams_[0].width,
test_->video_streams_[0].height,
30,
Clock::GetRealTimeClock()));
send_stream_->Start();
frame_generator_capturer_->Start();
@ -227,6 +229,7 @@ class BitrateEstimatorTest : public ::testing::Test {
scoped_ptr<Call> sender_call_;
scoped_ptr<Call> receiver_call_;
VideoSendStream::Config send_config_;
std::vector<VideoStream> video_streams_;
VideoReceiveStream::Config receive_config_;
std::vector<Stream*> streams_;
};

View File

@ -70,7 +70,9 @@ class Call : public webrtc::Call, public PacketReceiver {
virtual VideoSendStream::Config GetDefaultSendConfig() OVERRIDE;
virtual VideoSendStream* CreateVideoSendStream(
const VideoSendStream::Config& config) OVERRIDE;
const VideoSendStream::Config& config,
const std::vector<VideoStream>& video_streams,
const void* encoder_settings) OVERRIDE;
virtual void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream)
OVERRIDE;
@ -175,15 +177,19 @@ VideoSendStream::Config Call::GetDefaultSendConfig() {
}
VideoSendStream* Call::CreateVideoSendStream(
const VideoSendStream::Config& config) {
const VideoSendStream::Config& config,
const std::vector<VideoStream>& video_streams,
const void* encoder_settings) {
assert(config.rtp.ssrcs.size() > 0);
VideoSendStream* send_stream = new VideoSendStream(
config_.send_transport,
overuse_observer_proxy_.get(),
video_engine_,
config,
base_channel_id_);
VideoSendStream* send_stream =
new VideoSendStream(config_.send_transport,
overuse_observer_proxy_.get(),
video_engine_,
config,
video_streams,
encoder_settings,
base_channel_id_);
WriteLockScoped write_lock(*send_lock_);
for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) {

View File

@ -53,18 +53,19 @@ class CallPerfTest : public ::testing::Test {
: send_stream_(NULL), fake_encoder_(Clock::GetRealTimeClock()) {}
protected:
VideoSendStream::Config GetSendTestConfig(Call* call) {
VideoSendStream::Config config = call->GetDefaultSendConfig();
config.rtp.ssrcs.push_back(kSendSsrc);
config.encoder_settings = test::CreateEncoderSettings(
&fake_encoder_, "FAKE", kSendPayloadType, 1);
return config;
void CreateTestConfig(Call* call) {
send_config_ = call->GetDefaultSendConfig();
send_config_.rtp.ssrcs.push_back(kSendSsrc);
send_config_.encoder_settings.encoder = &fake_encoder_;
send_config_.encoder_settings.payload_type = kSendPayloadType;
send_config_.encoder_settings.payload_name = "FAKE";
video_streams_ = test::CreateVideoStreams(1);
}
void RunVideoSendTest(Call* call,
const VideoSendStream::Config& config,
test::RtpRtcpObserver* observer) {
send_stream_ = call->CreateVideoSendStream(config);
send_stream_ = call->CreateVideoSendStream(config, video_streams_, NULL);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
test::FrameGeneratorCapturer::Create(
send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
@ -86,6 +87,8 @@ class CallPerfTest : public ::testing::Test {
int start_time_ms,
int run_time_ms);
VideoSendStream::Config send_config_;
std::vector<VideoStream> video_streams_;
VideoSendStream* send_stream_;
test::FakeEncoder fake_encoder_;
};
@ -288,35 +291,34 @@ TEST_F(CallPerfTest, PlaysOutAudioAndVideoInSync) {
test::FakeDecoder fake_decoder;
VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
CreateTestConfig(sender_call.get());
VideoReceiveStream::Config receive_config =
receiver_call->GetDefaultReceiveConfig();
assert(receive_config.codecs.empty());
VideoCodec codec =
test::CreateDecoderVideoCodec(send_config.encoder_settings);
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.encoder_settings.payload_type;
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.remote_ssrc = send_config_.rtp.ssrcs[0];
receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
receive_config.renderer = &observer;
receive_config.audio_channel_id = channel;
VideoSendStream* send_stream =
sender_call->CreateVideoSendStream(send_config);
sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL);
VideoReceiveStream* receive_stream =
receiver_call->CreateVideoReceiveStream(receive_config);
scoped_ptr<test::FrameGeneratorCapturer> capturer(
test::FrameGeneratorCapturer::Create(
send_stream->Input(),
send_config.encoder_settings.streams[0].width,
send_config.encoder_settings.streams[0].height,
30,
Clock::GetRealTimeClock()));
test::FrameGeneratorCapturer::Create(send_stream->Input(),
video_streams_[0].width,
video_streams_[0].height,
30,
Clock::GetRealTimeClock()));
receive_stream->Start();
send_stream->Start();
capturer->Start();
@ -465,16 +467,15 @@ void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
// Configure send stream.
VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
CreateTestConfig(sender_call.get());
VideoSendStream* send_stream =
sender_call->CreateVideoSendStream(send_config);
sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL);
scoped_ptr<test::FrameGeneratorCapturer> capturer(
test::FrameGeneratorCapturer::Create(
send_stream->Input(),
send_config.encoder_settings.streams[0].width,
send_config.encoder_settings.streams[0].height,
30,
Clock::GetRealTimeClock()));
test::FrameGeneratorCapturer::Create(send_stream->Input(),
video_streams_[0].width,
video_streams_[0].height,
30,
Clock::GetRealTimeClock()));
observer.SetCapturer(capturer.get());
// Configure receive stream.
@ -482,15 +483,15 @@ void CallPerfTest::TestCaptureNtpTime(const FakeNetworkPipe::Config& net_config,
receiver_call->GetDefaultReceiveConfig();
assert(receive_config.codecs.empty());
VideoCodec codec =
test::CreateDecoderVideoCodec(send_config.encoder_settings);
test::CreateDecoderVideoCodec(send_config_.encoder_settings);
receive_config.codecs.push_back(codec);
assert(receive_config.external_decoders.empty());
ExternalVideoDecoder decoder;
test::FakeDecoder fake_decoder;
decoder.decoder = &fake_decoder;
decoder.payload_type = send_config.encoder_settings.payload_type;
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.remote_ssrc = send_config_.rtp.ssrcs[0];
receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
receive_config.renderer = &observer;
// Enable the receiver side rtt calculation.
@ -559,8 +560,8 @@ TEST_F(CallPerfTest, RegisterCpuOveruseObserver) {
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);
CreateTestConfig(call.get());
RunVideoSendTest(call.get(), send_config_, &observer);
}
void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
@ -636,43 +637,42 @@ void CallPerfTest::TestMinTransmitBitrate(bool pad_to_min_bitrate) {
scoped_ptr<Call> receiver_call(
Call::Create(Call::Config(observer.ReceiveTransport())));
VideoSendStream::Config send_config = GetSendTestConfig(sender_call.get());
CreateTestConfig(sender_call.get());
fake_encoder_.SetMaxBitrate(kMaxEncodeBitrateKbps);
observer.SetReceivers(receiver_call->Receiver(), sender_call->Receiver());
send_config.pacing = true;
send_config_.pacing = true;
if (pad_to_min_bitrate) {
send_config.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
send_config_.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
} else {
assert(send_config.rtp.min_transmit_bitrate_bps == 0);
assert(send_config_.rtp.min_transmit_bitrate_bps == 0);
}
VideoReceiveStream::Config receive_config =
receiver_call->GetDefaultReceiveConfig();
receive_config.codecs.clear();
VideoCodec codec =
test::CreateDecoderVideoCodec(send_config.encoder_settings);
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.encoder_settings.payload_type;
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.remote_ssrc = send_config_.rtp.ssrcs[0];
receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
VideoSendStream* send_stream =
sender_call->CreateVideoSendStream(send_config);
sender_call->CreateVideoSendStream(send_config_, video_streams_, NULL);
VideoReceiveStream* receive_stream =
receiver_call->CreateVideoReceiveStream(receive_config);
scoped_ptr<test::FrameGeneratorCapturer> capturer(
test::FrameGeneratorCapturer::Create(
send_stream->Input(),
send_config.encoder_settings.streams[0].width,
send_config.encoder_settings.streams[0].height,
30,
Clock::GetRealTimeClock()));
test::FrameGeneratorCapturer::Create(send_stream->Input(),
video_streams_[0].width,
video_streams_[0].height,
30,
Clock::GetRealTimeClock()));
observer.SetSendStream(send_stream);
receive_stream->Start();
send_stream->Start();

View File

@ -73,8 +73,10 @@ class CallTest : public ::testing::Test {
receive_config_ = receiver_call_->GetDefaultReceiveConfig();
send_config_.rtp.ssrcs.push_back(kSendSsrc);
send_config_.encoder_settings = test::CreateEncoderSettings(
&fake_encoder_, "FAKE", kSendPayloadType, 1);
send_config_.encoder_settings.encoder = &fake_encoder_;
send_config_.encoder_settings.payload_name = "FAKE";
send_config_.encoder_settings.payload_type = kSendPayloadType;
video_streams_ = test::CreateVideoStreams(1);
assert(receive_config_.codecs.empty());
VideoCodec codec =
@ -92,17 +94,18 @@ class CallTest : public ::testing::Test {
assert(send_stream_ == NULL);
assert(receive_stream_ == NULL);
send_stream_ = sender_call_->CreateVideoSendStream(send_config_);
send_stream_ =
sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL);
receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_);
}
void CreateFrameGenerator() {
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()));
frame_generator_capturer_.reset(
test::FrameGeneratorCapturer::Create(send_stream_->Input(),
video_streams_[0].width,
video_streams_[0].height,
30,
Clock::GetRealTimeClock()));
}
void StartSending() {
@ -139,6 +142,7 @@ class CallTest : public ::testing::Test {
scoped_ptr<Call> receiver_call_;
VideoSendStream::Config send_config_;
std::vector<VideoStream> video_streams_;
VideoReceiveStream::Config receive_config_;
VideoSendStream* send_stream_;
@ -350,8 +354,7 @@ TEST_F(CallTest, TransmitsFirstFrame) {
StartSending();
scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
send_config_.encoder_settings.streams[0].width,
send_config_.encoder_settings.streams[0].height));
video_streams_[0].width, video_streams_[0].height));
send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
EXPECT_EQ(kEventSignaled, renderer.Wait())
@ -701,10 +704,9 @@ TEST_F(CallTest, UsesFrameCallbacks) {
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;
ASSERT_EQ(1u, video_streams_.size()) << "Test setup error.";
video_streams_[0].width = kWidth;
video_streams_[0].height = kHeight;
send_config_.pre_encode_callback = &pre_encode_callback;
receive_config_.codecs.clear();
VideoCodec codec =
@ -1055,15 +1057,18 @@ TEST_F(CallTest, SendsAndReceivesMultipleStreams) {
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];
send_config.encoder_settings.encoder = encoders[i].get();
send_config.encoder_settings.payload_name = "VP8";
send_config.encoder_settings.payload_type = 124;
std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
VideoStream* stream = &video_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] =
sender_call->CreateVideoSendStream(send_config, video_streams, NULL);
send_streams[i]->Start();
VideoReceiveStream::Config receive_config =
@ -1154,8 +1159,7 @@ TEST_F(CallTest, ObserversEncodedFrames) {
StartSending();
scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
send_config_.encoder_settings.streams[0].width,
send_config_.encoder_settings.streams[0].height));
video_streams_[0].width, video_streams_[0].height));
send_stream_->Input()->SwapFrame(frame_generator->NextFrame());
EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())

View File

@ -398,16 +398,19 @@ TEST_P(FullStackTest, NoPacketLoss) {
send_config.rtp.ssrcs.push_back(kSendSsrc);
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];
send_config.encoder_settings.encoder = encoder.get();
send_config.encoder_settings.payload_name = "VP8";
send_config.encoder_settings.payload_type = 124;
std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
VideoStream* stream = &video_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);
VideoSendStream* send_stream =
call->CreateVideoSendStream(send_config, video_streams, NULL);
analyzer.input_ = send_stream->Input();
scoped_ptr<test::FrameGeneratorCapturer> file_capturer(

View File

@ -72,19 +72,21 @@ void Loopback() {
send_config.local_renderer = local_preview.get();
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];
send_config.encoder_settings.encoder = encoder.get();
send_config.encoder_settings.payload_name = "VP8";
send_config.encoder_settings.payload_type = 124;
std::vector<VideoStream> video_streams = test::CreateVideoStreams(1);
VideoStream* stream = &video_streams[0];
stream->width = flags::Width();
stream->height = flags::Height();
stream->min_bitrate_bps = static_cast<int>(flags::MinBitrate()) * 1000;
stream->target_bitrate_bps =
static_cast<int>(flags::MaxBitrate()) * 1000;
stream->target_bitrate_bps = static_cast<int>(flags::MaxBitrate()) * 1000;
stream->max_bitrate_bps = static_cast<int>(flags::MaxBitrate()) * 1000;
stream->max_framerate = 30;
stream->max_qp = 56;
VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
VideoSendStream* send_stream =
call->CreateVideoSendStream(send_config, video_streams, NULL);
Clock* test_clock = Clock::GetRealTimeClock();

View File

@ -430,12 +430,15 @@ class RampUpTest : public ::testing::Test {
receiver_transport.SetReceiver(call->Receiver());
test::FakeEncoder encoder(Clock::GetRealTimeClock());
send_config.encoder_settings =
test::CreateEncoderSettings(&encoder, "FAKE", 125, num_streams);
send_config.encoder_settings.encoder = &encoder;
send_config.encoder_settings.payload_type = 125;
send_config.encoder_settings.payload_name = "FAKE";
std::vector<VideoStream> video_streams =
test::CreateVideoStreams(num_streams);
if (num_streams == 1) {
send_config.encoder_settings.streams[0].target_bitrate_bps = 2000000;
send_config.encoder_settings.streams[0].max_bitrate_bps = 2000000;
video_streams[0].target_bitrate_bps = 2000000;
video_streams[0].max_bitrate_bps = 2000000;
}
send_config.pacing = pacing;
@ -455,25 +458,22 @@ class RampUpTest : public ::testing::Test {
// For multi stream rampup until all streams are being sent. That means
// enough birate to sent all the target streams plus the min bitrate of
// the last one.
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;
int expected_bitrate_bps = video_streams.back().min_bitrate_bps;
for (size_t i = 0; i < video_streams.size() - 1; ++i) {
expected_bitrate_bps += video_streams[i].target_bitrate_bps;
}
stream_observer.set_expected_bitrate_bps(expected_bitrate_bps);
}
VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
VideoSendStream* send_stream =
call->CreateVideoSendStream(send_config, video_streams, NULL);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
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()));
test::FrameGeneratorCapturer::Create(send_stream->Input(),
video_streams.back().width,
video_streams.back().height,
video_streams.back().max_framerate,
Clock::GetRealTimeClock()));
send_stream->Start();
frame_generator_capturer->Start();
@ -504,23 +504,29 @@ class RampUpTest : public ::testing::Test {
receiver_transport.SetReceiver(call->Receiver());
test::FakeEncoder encoder(Clock::GetRealTimeClock());
send_config.encoder_settings =
test::CreateEncoderSettings(&encoder, "FAKE", 125, number_of_streams);
send_config.encoder_settings.encoder = &encoder;
send_config.encoder_settings.payload_type = 125;
send_config.encoder_settings.payload_name = "FAKE";
std::vector<VideoStream> video_streams =
test::CreateVideoStreams(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());
send_config.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsoluteSendTimeExtensionId));
send_config.suspend_below_min_bitrate = true;
send_config.pacing = true;
VideoSendStream* send_stream = call->CreateVideoSendStream(send_config);
VideoSendStream* send_stream =
call->CreateVideoSendStream(send_config, video_streams, NULL);
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;
for (size_t i = 0; i < video_streams.size(); ++i) {
size_t stream_width = video_streams[i].width;
size_t stream_height = video_streams[i].height;
if (stream_width > width)
width = stream_width;
if (stream_height > height)

View File

@ -150,13 +150,13 @@ VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
external_codec_ = ViEExternalCodec::GetInterface(video_engine);
for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
ExternalVideoDecoder* decoder = &config_.external_decoders[i];
const ExternalVideoDecoder& decoder = config_.external_decoders[i];
if (external_codec_->RegisterExternalReceiveCodec(
channel_,
decoder->payload_type,
decoder->decoder,
decoder->renderer,
decoder->expected_delay_ms) != 0) {
decoder.payload_type,
decoder.decoder,
decoder.renderer,
decoder.expected_delay_ms) != 0) {
// TODO(pbos): Abort gracefully? Can this be a runtime error?
abort();
}

View File

@ -69,7 +69,7 @@ class VideoReceiveStream : public webrtc::VideoReceiveStream,
private:
TransportAdapter transport_adapter_;
EncodedFrameCallbackAdapter encoded_frame_proxy_;
VideoReceiveStream::Config config_;
const VideoReceiveStream::Config config_;
Clock* const clock_;
ViEBase* video_engine_base_;

View File

@ -15,6 +15,7 @@
#include <vector>
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/video_engine/include/vie_base.h"
#include "webrtc/video_engine/include/vie_capture.h"
#include "webrtc/video_engine/include/vie_codec.h"
@ -32,18 +33,7 @@ VideoSendStream::Config::EncoderSettings::ToString() const {
ss << "{payload_name: " << payload_name;
ss << ", payload_type: " << payload_type;
if (encoder != NULL)
ss << ", (encoder)";
if (encoder_settings != NULL)
ss << ", (encoder_settings)";
ss << ", streams: {";
for (size_t i = 0; i < streams.size(); ++i) {
ss << streams[i].ToString();
if (i != streams.size() - 1)
ss << "}, {";
}
ss << '}';
ss << ", encoder: " << (encoder != NULL ? "(encoder)" : "NULL");
ss << '}';
return ss.str();
}
@ -124,10 +114,11 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
CpuOveruseObserver* overuse_observer,
webrtc::VideoEngine* video_engine,
const VideoSendStream::Config& config,
const std::vector<VideoStream> video_streams,
const void* encoder_settings,
int base_channel)
: transport_adapter_(transport),
encoded_frame_proxy_(config.post_encode_callback),
codec_lock_(CriticalSectionWrapper::CreateCriticalSection()),
config_(config),
external_codec_(NULL),
channel_(-1),
@ -141,7 +132,7 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
assert(config_.rtp.ssrcs.size() > 0);
if (config_.suspend_below_min_bitrate)
config_.pacing = true;
assert(config_.pacing);
rtp_rtcp_->SetTransmissionSmoothingStatus(channel_, config_.pacing);
assert(config_.rtp.min_transmit_bitrate_bps >= 0);
@ -216,10 +207,8 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
}
codec_ = ViECodec::GetInterface(video_engine);
if (!ReconfigureVideoEncoder(config_.encoder_settings.streams,
config_.encoder_settings.encoder_settings)) {
if (!ReconfigureVideoEncoder(video_streams, encoder_settings))
abort();
}
if (overuse_observer)
video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer);
@ -232,9 +221,8 @@ VideoSendStream::VideoSendStream(newapi::Transport* transport,
&encoded_frame_proxy_);
}
if (config_.suspend_below_min_bitrate) {
if (config_.suspend_below_min_bitrate)
codec_->SuspendBelowMinBitrate(channel_);
}
rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(channel_,
stats_proxy_.get());
@ -304,15 +292,12 @@ void VideoSendStream::Stop() {
bool VideoSendStream::ReconfigureVideoEncoder(
const std::vector<VideoStream>& streams,
void* encoder_settings) {
const 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());
VideoCodec video_codec;
memset(&video_codec, 0, sizeof(video_codec));
video_codec.codecType =
@ -383,8 +368,8 @@ bool VideoSendStream::ReconfigureVideoEncoder(
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;
assert(streams[0].max_framerate > 0);
video_codec.maxFramerate = streams[0].max_framerate;
if (codec_->SetSendCodec(channel_, video_codec) != 0)
return false;
@ -396,9 +381,6 @@ bool VideoSendStream::ReconfigureVideoEncoder(
static_cast<unsigned char>(i));
}
config_.encoder_settings.streams = streams;
config_.encoder_settings.encoder_settings = encoder_settings;
if (config_.rtp.rtx.ssrcs.empty())
return true;

View File

@ -42,6 +42,8 @@ class VideoSendStream : public webrtc::VideoSendStream,
CpuOveruseObserver* overuse_observer,
webrtc::VideoEngine* video_engine,
const VideoSendStream::Config& config,
const std::vector<VideoStream> video_streams,
const void* encoder_settings,
int base_channel);
virtual ~VideoSendStream();
@ -50,7 +52,7 @@ class VideoSendStream : public webrtc::VideoSendStream,
virtual void Stop() OVERRIDE;
virtual bool ReconfigureVideoEncoder(const std::vector<VideoStream>& streams,
void* encoder_settings) OVERRIDE;
const void* encoder_settings) OVERRIDE;
virtual Stats GetStats() const OVERRIDE;
@ -70,8 +72,7 @@ class VideoSendStream : public webrtc::VideoSendStream,
private:
TransportAdapter transport_adapter_;
EncodedFrameCallbackAdapter encoded_frame_proxy_;
scoped_ptr<CriticalSectionWrapper> codec_lock_;
VideoSendStream::Config config_;
const VideoSendStream::Config config_;
ViEBase* video_engine_base_;
ViECapture* capture_;

View File

@ -45,9 +45,9 @@ class VideoSendStreamTest : public ::testing::Test {
protected:
void RunSendTest(Call* call,
const VideoSendStream::Config& config,
test::RtpRtcpObserver* observer) {
send_stream_ = call->CreateVideoSendStream(config);
send_stream_ =
call->CreateVideoSendStream(send_config_, video_streams_, NULL);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
test::FrameGeneratorCapturer::Create(
send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
@ -62,17 +62,16 @@ class VideoSendStreamTest : public ::testing::Test {
call->DestroyVideoSendStream(send_stream_);
}
VideoSendStream::Config GetSendTestConfig(Call* call, size_t num_streams) {
void CreateTestConfig(Call* call, size_t num_streams) {
assert(num_streams <= kNumSendSsrcs);
VideoSendStream::Config config = call->GetDefaultSendConfig();
config.encoder_settings = test::CreateEncoderSettings(
&fake_encoder_, "FAKE", kFakeSendPayloadType, num_streams);
config.encoder_settings.encoder = &fake_encoder_;
config.encoder_settings.payload_type = kFakeSendPayloadType;
send_config_ = call->GetDefaultSendConfig();
send_config_.encoder_settings.encoder = &fake_encoder_;
send_config_.encoder_settings.payload_name = "FAKE";
send_config_.encoder_settings.payload_type = kFakeSendPayloadType;
video_streams_ = test::CreateVideoStreams(num_streams);
send_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;
return config;
send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]);
}
void TestNackRetransmission(uint32_t retransmit_ssrc,
@ -91,6 +90,8 @@ class VideoSendStreamTest : public ::testing::Test {
static const uint32_t kSendRtxSsrc;
static const uint32_t kSendSsrcs[kNumSendSsrcs];
VideoSendStream::Config send_config_;
std::vector<VideoStream> video_streams_;
VideoSendStream* send_stream_;
test::FakeEncoder fake_encoder_;
};
@ -158,24 +159,23 @@ void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs,
Call::Config call_config(observer.SendTransport());
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config =
GetSendTestConfig(call.get(), num_ssrcs);
CreateTestConfig(call.get(), num_ssrcs);
if (num_ssrcs > 1) {
// Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
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;
for (size_t i = 0; i < video_streams_.size(); ++i) {
video_streams_[i].min_bitrate_bps = 10000;
video_streams_[i].target_bitrate_bps = 10000;
video_streams_[i].max_bitrate_bps = 10000;
}
}
std::vector<VideoStream> all_streams = send_config.encoder_settings.streams;
std::vector<VideoStream> all_streams = video_streams_;
if (send_single_ssrc_first)
send_config.encoder_settings.streams.resize(1);
video_streams_.resize(1);
send_stream_ = call->CreateVideoSendStream(send_config);
send_stream_ =
call->CreateVideoSendStream(send_config_, video_streams_, NULL);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
test::FrameGeneratorCapturer::Create(
send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
@ -204,8 +204,9 @@ TEST_F(VideoSendStreamTest, CanStartStartedStream) {
Call::Config call_config(&transport);
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config config = GetSendTestConfig(call.get(), 1);
VideoSendStream* stream = call->CreateVideoSendStream(config);
CreateTestConfig(call.get(), 1);
VideoSendStream* stream =
call->CreateVideoSendStream(send_config_, video_streams_, NULL);
stream->Start();
stream->Start();
call->DestroyVideoSendStream(stream);
@ -216,8 +217,9 @@ TEST_F(VideoSendStreamTest, CanStopStoppedStream) {
Call::Config call_config(&transport);
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config config = GetSendTestConfig(call.get(), 1);
VideoSendStream* stream = call->CreateVideoSendStream(config);
CreateTestConfig(call.get(), 1);
VideoSendStream* stream =
call->CreateVideoSendStream(send_config_, video_streams_, NULL);
stream->Stop();
stream->Stop();
call->DestroyVideoSendStream(stream);
@ -260,10 +262,10 @@ TEST_F(VideoSendStreamTest, SupportsCName) {
Call::Config call_config(observer.SendTransport());
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.rtp.c_name = kCName;
CreateTestConfig(call.get(), 1);
send_config_.rtp.c_name = kCName;
RunSendTest(call.get(), send_config, &observer);
RunSendTest(call.get(), &observer);
}
TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
@ -292,11 +294,11 @@ TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
Call::Config call_config(observer.SendTransport());
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.rtp.extensions.push_back(
CreateTestConfig(call.get(), 1);
send_config_.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
RunSendTest(call.get(), send_config, &observer);
RunSendTest(call.get(), &observer);
}
TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
@ -339,12 +341,12 @@ TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
Call::Config call_config(observer.SendTransport());
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.encoder_settings.encoder = &encoder;
send_config.rtp.extensions.push_back(
CreateTestConfig(call.get(), 1);
send_config_.encoder_settings.encoder = &encoder;
send_config_.rtp.extensions.push_back(
RtpExtension(RtpExtension::kTOffset, kTOffsetExtensionId));
RunSendTest(call.get(), send_config, &observer);
RunSendTest(call.get(), &observer);
}
class FakeReceiveStatistics : public NullReceiveStatistics {
@ -413,8 +415,9 @@ TEST_F(VideoSendStreamTest, SwapsI420VideoFrames) {
Call::Config call_config(&transport);
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
VideoSendStream* video_send_stream = call->CreateVideoSendStream(send_config);
CreateTestConfig(call.get(), 1);
VideoSendStream* video_send_stream =
call->CreateVideoSendStream(send_config_, video_streams_, NULL);
video_send_stream->Start();
I420VideoFrame frame;
@ -492,11 +495,11 @@ TEST_F(VideoSendStreamTest, SupportsFec) {
observer.SetReceivers(call->Receiver(), NULL);
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.rtp.fec.red_payload_type = kRedPayloadType;
send_config.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
CreateTestConfig(call.get(), 1);
send_config_.rtp.fec.red_payload_type = kRedPayloadType;
send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
RunSendTest(call.get(), send_config, &observer);
RunSendTest(call.get(), &observer);
}
void VideoSendStreamTest::TestNackRetransmission(
@ -568,14 +571,14 @@ void VideoSendStreamTest::TestNackRetransmission(
scoped_ptr<Call> call(Call::Create(call_config));
observer.SetReceivers(call->Receiver(), NULL);
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.rtp.nack.rtp_history_ms = 1000;
send_config.rtp.rtx.payload_type = retransmit_payload_type;
send_config.pacing = enable_pacing;
CreateTestConfig(call.get(), 1);
send_config_.rtp.nack.rtp_history_ms = 1000;
send_config_.rtp.rtx.payload_type = retransmit_payload_type;
send_config_.pacing = enable_pacing;
if (retransmit_ssrc != kSendSsrc)
send_config.rtp.rtx.ssrcs.push_back(retransmit_ssrc);
send_config_.rtp.rtx.ssrcs.push_back(retransmit_ssrc);
RunSendTest(call.get(), send_config, &observer);
RunSendTest(call.get(), &observer);
}
TEST_F(VideoSendStreamTest, RetransmitsNack) {
@ -762,27 +765,27 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
observer.SetReceivers(call->Receiver(), NULL);
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
CreateTestConfig(call.get(), 1);
if (with_fec) {
send_config.rtp.fec.red_payload_type = kRedPayloadType;
send_config.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
send_config_.rtp.fec.red_payload_type = kRedPayloadType;
send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
}
if (format == kVP8)
send_config.encoder_settings.payload_name = "VP8";
send_config_.encoder_settings.payload_name = "VP8";
send_config.pacing = false;
send_config.encoder_settings.encoder = &encoder;
send_config.rtp.max_packet_size = kMaxPacketSize;
send_config.post_encode_callback = &observer;
send_config_.pacing = false;
send_config_.encoder_settings.encoder = &encoder;
send_config_.rtp.max_packet_size = kMaxPacketSize;
send_config_.post_encode_callback = &observer;
// Add an extension header, to make the RTP header larger than the base
// length of 12 bytes.
static const uint8_t kAbsSendTimeExtensionId = 13;
send_config.rtp.extensions.push_back(
send_config_.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
RunSendTest(call.get(), send_config, &observer);
RunSendTest(call.get(), &observer);
}
// TODO(sprang): Is there any way of speeding up these tests?
@ -948,18 +951,19 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
scoped_ptr<Call> call(Call::Create(call_config));
observer.SetReceiver(call->Receiver());
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.rtp.nack.rtp_history_ms = 1000;
send_config.pre_encode_callback = &observer;
send_config.suspend_below_min_bitrate = true;
int min_bitrate_bps = send_config.encoder_settings.streams[0].min_bitrate_bps;
CreateTestConfig(call.get(), 1);
send_config_.rtp.nack.rtp_history_ms = 1000;
send_config_.pre_encode_callback = &observer;
send_config_.suspend_below_min_bitrate = true;
send_config_.pacing = true;
int min_bitrate_bps = video_streams_[0].min_bitrate_bps;
observer.set_low_remb_bps(min_bitrate_bps - 10000);
int threshold_window = std::max(min_bitrate_bps / 10, 10000);
ASSERT_GT(send_config.encoder_settings.streams[0].max_bitrate_bps,
ASSERT_GT(video_streams_[0].max_bitrate_bps,
min_bitrate_bps + threshold_window + 5000);
observer.set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
RunSendTest(call.get(), send_config, &observer);
RunSendTest(call.get(), &observer);
observer.Stop();
}
@ -1022,9 +1026,10 @@ TEST_F(VideoSendStreamTest, NoPaddingWhenVideoIsMuted) {
scoped_ptr<Call> call(Call::Create(call_config));
observer.SetReceivers(call->Receiver(), call->Receiver());
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 3);
CreateTestConfig(call.get(), 3);
send_stream_ = call->CreateVideoSendStream(send_config);
send_stream_ =
call->CreateVideoSendStream(send_config_, video_streams_, NULL);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
test::FrameGeneratorCapturer::Create(
send_stream_->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
@ -1107,11 +1112,13 @@ TEST_F(VideoSendStreamTest, ProducesStats) {
Call::Config call_config(observer.SendTransport());
scoped_ptr<Call> call(Call::Create(call_config));
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.rtp.c_name = kCName;
observer.SetConfig(send_config);
CreateTestConfig(call.get(), 1);
send_config_.rtp.c_name = kCName;
send_config_.pacing = true;
observer.SetConfig(send_config_);
send_stream_ = call->CreateVideoSendStream(send_config);
send_stream_ =
call->CreateVideoSendStream(send_config_, video_streams_, NULL);
observer.SetSendStream(send_stream_);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
test::FrameGeneratorCapturer::Create(
@ -1202,9 +1209,10 @@ TEST_F(VideoSendStreamTest, MinTransmitBitrateRespectsRemb) {
scoped_ptr<Call> call(Call::Create(call_config));
observer.SetReceivers(&observer, call->Receiver());
VideoSendStream::Config send_config = GetSendTestConfig(call.get(), 1);
send_config.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
send_stream_ = call->CreateVideoSendStream(send_config);
CreateTestConfig(call.get(), 1);
send_config_.rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
send_stream_ =
call->CreateVideoSendStream(send_config_, video_streams_, NULL);
observer.SetSendStream(send_stream_);
scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(

View File

@ -66,8 +66,7 @@ class VideoSendStream {
std::string ToString() const;
struct EncoderSettings {
EncoderSettings()
: payload_type(-1), encoder(NULL), encoder_settings(NULL) {}
EncoderSettings() : payload_type(-1), encoder(NULL) {}
std::string ToString() const;
std::string payload_name;
@ -76,13 +75,6 @@ class VideoSendStream {
// 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.
@ -155,8 +147,7 @@ class VideoSendStream {
// True if the stream should be suspended when the available bitrate fall
// below the minimum configured bitrate. If this variable is false, the
// stream may send at a rate higher than the estimated available bitrate.
// Enabling suspend_below_min_bitrate will also enable pacing and padding,
// otherwise, the video will be unable to recover from suspension.
// |suspend_below_min_bitrate| requires |pacing| to be enabled as well.
bool suspend_below_min_bitrate;
};
@ -171,7 +162,7 @@ class VideoSendStream {
// 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;
const void* encoder_settings) = 0;
virtual Stats GetStats() const = 0;