Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(305)

Unified Diff: webrtc/video/end_to_end_tests.cc

Issue 1247293002: Add support for transport wide sequence numbers (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase, again Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/video/call_perf_tests.cc ('k') | webrtc/video/video_receive_stream.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/video/end_to_end_tests.cc
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index 416c8dd5d8b868c917c6d2945e478244a021e092..36206fae9cd2e7a58bf09fa190dbe9b6594cbb6e 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -1133,120 +1133,304 @@ TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
// Test sets up a Call multiple senders with different resolutions and SSRCs.
// Another is set up to receive all three of these with different renderers.
+class MultiStreamTest {
+ public:
+ static const size_t kNumStreams = 3;
+ struct CodecSettings {
+ uint32_t ssrc;
+ int width;
+ int height;
+ } codec_settings[kNumStreams];
+
+ MultiStreamTest() {
+ // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
+ codec_settings[0] = {1, 640, 480};
+ codec_settings[1] = {2, 320, 240};
+ codec_settings[2] = {3, 240, 160};
+ }
+
+ virtual ~MultiStreamTest() {}
+
+ void RunTest() {
+ rtc::scoped_ptr<test::DirectTransport> sender_transport(
+ CreateSendTransport());
+ rtc::scoped_ptr<test::DirectTransport> receiver_transport(
+ CreateReceiveTransport());
+
+ rtc::scoped_ptr<Call> sender_call(
+ Call::Create(Call::Config(sender_transport.get())));
+ rtc::scoped_ptr<Call> receiver_call(
+ Call::Create(Call::Config(receiver_transport.get())));
+ sender_transport->SetReceiver(receiver_call->Receiver());
+ receiver_transport->SetReceiver(sender_call->Receiver());
+
+ rtc::scoped_ptr<VideoEncoder> encoders[kNumStreams];
+ for (size_t i = 0; i < kNumStreams; ++i)
+ encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
+
+ VideoSendStream* send_streams[kNumStreams];
+ VideoReceiveStream* receive_streams[kNumStreams];
+
+ test::FrameGeneratorCapturer* frame_generators[kNumStreams];
+ ScopedVector<VideoDecoder> allocated_decoders;
+ 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;
+
+ VideoSendStream::Config send_config;
+ send_config.rtp.ssrcs.push_back(ssrc);
+ send_config.encoder_settings.encoder = encoders[i].get();
+ send_config.encoder_settings.payload_name = "VP8";
+ send_config.encoder_settings.payload_type = 124;
+ VideoEncoderConfig encoder_config;
+ encoder_config.streams = test::CreateVideoStreams(1);
+ VideoStream* stream = &encoder_config.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;
+
+ UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);
+
+ send_streams[i] =
+ sender_call->CreateVideoSendStream(send_config, encoder_config);
+ send_streams[i]->Start();
+
+ VideoReceiveStream::Config receive_config;
+ receive_config.rtp.remote_ssrc = ssrc;
+ receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalSsrc;
+ VideoReceiveStream::Decoder decoder =
+ test::CreateMatchingDecoder(send_config.encoder_settings);
+ allocated_decoders.push_back(decoder.decoder);
+ receive_config.decoders.push_back(decoder);
+
+ UpdateReceiveConfig(i, &receive_config);
+
+ receive_streams[i] =
+ receiver_call->CreateVideoReceiveStream(receive_config);
+ receive_streams[i]->Start();
+
+ frame_generators[i] = test::FrameGeneratorCapturer::Create(
+ send_streams[i]->Input(), width, height, 30,
+ Clock::GetRealTimeClock());
+ frame_generators[i]->Start();
+ }
+
+ Wait();
+
+ for (size_t i = 0; i < kNumStreams; ++i) {
+ frame_generators[i]->Stop();
+ sender_call->DestroyVideoSendStream(send_streams[i]);
+ receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
+ delete frame_generators[i];
+ }
+
+ sender_transport->StopSending();
+ receiver_transport->StopSending();
+ }
+
+ protected:
+ virtual void Wait() = 0;
+ // Note: frame_generator is a point-to-pointer, since the actual instance
+ // hasn't been created at the time of this call. Only when packets/frames
+ // start flowing should this be dereferenced.
+ virtual void UpdateSendConfig(
+ size_t stream_index,
+ VideoSendStream::Config* send_config,
+ VideoEncoderConfig* encoder_config,
+ test::FrameGeneratorCapturer** frame_generator) {}
+ virtual void UpdateReceiveConfig(size_t stream_index,
+ VideoReceiveStream::Config* receive_config) {
+ }
+ virtual test::DirectTransport* CreateSendTransport() {
+ return new test::DirectTransport();
+ }
+ virtual test::DirectTransport* CreateReceiveTransport() {
+ return new test::DirectTransport();
+ }
+};
+
// Each renderer verifies that it receives the expected resolution, and as soon
// as every renderer has received a frame, the test finishes.
TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
- static const size_t kNumStreams = 3;
-
class VideoOutputObserver : public VideoRenderer {
public:
- VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
- int width,
- int height)
- : capturer_(capturer),
- width_(width),
- height_(height),
+ VideoOutputObserver(const MultiStreamTest::CodecSettings& settings,
+ uint32_t ssrc,
+ test::FrameGeneratorCapturer** frame_generator)
+ : settings_(settings),
+ ssrc_(ssrc),
+ frame_generator_(frame_generator),
done_(EventWrapper::Create()) {}
void RenderFrame(const VideoFrame& video_frame,
int time_to_render_ms) override {
- EXPECT_EQ(width_, video_frame.width());
- EXPECT_EQ(height_, video_frame.height());
- (*capturer_)->Stop();
+ EXPECT_EQ(settings_.width, video_frame.width());
+ EXPECT_EQ(settings_.height, video_frame.height());
+ (*frame_generator_)->Stop();
done_->Set();
}
+ uint32_t Ssrc() { return ssrc_; }
+
bool IsTextureSupported() const override { return false; }
EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
private:
- test::FrameGeneratorCapturer** capturer_;
- int width_;
- int height_;
+ const MultiStreamTest::CodecSettings& settings_;
+ const uint32_t ssrc_;
+ test::FrameGeneratorCapturer** const frame_generator_;
rtc::scoped_ptr<EventWrapper> done_;
};
- struct {
- uint32_t ssrc;
- int width;
- int height;
- } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
+ class Tester : public MultiStreamTest {
+ public:
+ Tester() {}
+ virtual ~Tester() {}
+
+ protected:
+ void Wait() override {
+ for (const auto& observer : observers_) {
+ EXPECT_EQ(EventTypeWrapper::kEventSignaled, observer->Wait())
+ << "Time out waiting for from on ssrc " << observer->Ssrc();
+ }
+ }
- test::DirectTransport sender_transport, receiver_transport;
- rtc::scoped_ptr<Call> sender_call(
- Call::Create(Call::Config(&sender_transport)));
- rtc::scoped_ptr<Call> receiver_call(
- Call::Create(Call::Config(&receiver_transport)));
- sender_transport.SetReceiver(receiver_call->Receiver());
- receiver_transport.SetReceiver(sender_call->Receiver());
-
- VideoSendStream* send_streams[kNumStreams];
- VideoReceiveStream* receive_streams[kNumStreams];
-
- VideoOutputObserver* observers[kNumStreams];
- test::FrameGeneratorCapturer* frame_generators[kNumStreams];
-
- rtc::scoped_ptr<VideoEncoder> encoders[kNumStreams];
- for (size_t i = 0; i < kNumStreams; ++i)
- encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
-
- ScopedVector<VideoDecoder> allocated_decoders;
- 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);
+ void UpdateSendConfig(
+ size_t stream_index,
+ VideoSendStream::Config* send_config,
+ VideoEncoderConfig* encoder_config,
+ test::FrameGeneratorCapturer** frame_generator) override {
+ observers_[stream_index].reset(new VideoOutputObserver(
+ codec_settings[stream_index], send_config->rtp.ssrcs.front(),
+ frame_generator));
+ }
- VideoSendStream::Config send_config;
- send_config.rtp.ssrcs.push_back(ssrc);
- send_config.encoder_settings.encoder = encoders[i].get();
- send_config.encoder_settings.payload_name = "VP8";
- send_config.encoder_settings.payload_type = 124;
- VideoEncoderConfig encoder_config;
- encoder_config.streams = test::CreateVideoStreams(1);
- VideoStream* stream = &encoder_config.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, encoder_config);
- send_streams[i]->Start();
+ void UpdateReceiveConfig(
+ size_t stream_index,
+ VideoReceiveStream::Config* receive_config) override {
+ receive_config->renderer = observers_[stream_index].get();
+ }
- VideoReceiveStream::Config receive_config;
- receive_config.renderer = observers[i];
- receive_config.rtp.remote_ssrc = ssrc;
- receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
- VideoReceiveStream::Decoder decoder =
- test::CreateMatchingDecoder(send_config.encoder_settings);
- allocated_decoders.push_back(decoder.decoder);
- receive_config.decoders.push_back(decoder);
- receive_streams[i] =
- receiver_call->CreateVideoReceiveStream(receive_config);
- receive_streams[i]->Start();
+ private:
+ rtc::scoped_ptr<VideoOutputObserver> observers_[kNumStreams];
+ } tester;
- frame_generators[i] = test::FrameGeneratorCapturer::Create(
- send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
- frame_generators[i]->Start();
- }
+ tester.RunTest();
+}
- for (size_t i = 0; i < kNumStreams; ++i) {
- EXPECT_EQ(kEventSignaled, observers[i]->Wait())
- << "Timed out while waiting for observer " << i << " to render.";
- }
+TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) {
+ // TODO(sprang): Extend this to verify received values once send-side BWE
+ // is in place.
- for (size_t i = 0; i < kNumStreams; ++i) {
- frame_generators[i]->Stop();
- sender_call->DestroyVideoSendStream(send_streams[i]);
- receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
- delete frame_generators[i];
- delete observers[i];
- }
+ static const int kExtensionId = 5;
- sender_transport.StopSending();
- receiver_transport.StopSending();
+ class RtpExtensionHeaderObserver : public test::DirectTransport {
+ public:
+ RtpExtensionHeaderObserver()
+ : done_(EventWrapper::Create()),
+ parser_(RtpHeaderParser::Create()),
+ last_seq_(0),
+ padding_observed_(false),
+ rtx_padding_observed_(false) {
+ parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
+ kExtensionId);
+ }
+ virtual ~RtpExtensionHeaderObserver() {}
+
+ bool SendRtp(const uint8_t* data, size_t length) override {
+ RTPHeader header;
+ EXPECT_TRUE(parser_->Parse(data, length, &header));
+ if (header.extension.hasTransportSequenceNumber) {
+ if (!streams_observed_.empty()) {
+ EXPECT_EQ(static_cast<uint16_t>(last_seq_ + 1),
+ header.extension.transportSequenceNumber);
+ }
+ last_seq_ = header.extension.transportSequenceNumber;
+
+ size_t payload_length =
+ length - (header.headerLength + header.paddingLength);
+ if (payload_length == 0) {
+ padding_observed_ = true;
+ } else if (header.payloadType == kSendRtxPayloadType) {
+ rtx_padding_observed_ = true;
+ } else {
+ streams_observed_.insert(header.ssrc);
+ }
+
+ if (streams_observed_.size() == MultiStreamTest::kNumStreams &&
+ padding_observed_ && rtx_padding_observed_) {
+ done_->Set();
+ }
+ }
+ return test::DirectTransport::SendRtp(data, length);
+ }
+
+ EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
+
+ rtc::scoped_ptr<EventWrapper> done_;
+ rtc::scoped_ptr<RtpHeaderParser> parser_;
+ uint16_t last_seq_;
+ std::set<uint32_t> streams_observed_;
+ bool padding_observed_;
+ bool rtx_padding_observed_;
+ };
+
+ class TransportSequenceNumberTester : public MultiStreamTest {
+ public:
+ TransportSequenceNumberTester() : observer_(nullptr) {}
+ virtual ~TransportSequenceNumberTester() {}
+
+ protected:
+ void Wait() override {
+ DCHECK(observer_ != nullptr);
+ EXPECT_EQ(EventTypeWrapper::kEventSignaled, observer_->Wait());
+ }
+
+ void UpdateSendConfig(
+ size_t stream_index,
+ VideoSendStream::Config* send_config,
+ VideoEncoderConfig* encoder_config,
+ test::FrameGeneratorCapturer** frame_generator) override {
+ send_config->rtp.extensions.clear();
+ send_config->rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
+
+ // Force some padding to be sent.
+ const int kPaddingBitrateBps = 50000;
+ int total_target_bitrate = 0;
+ for (const VideoStream& stream : encoder_config->streams)
+ total_target_bitrate += stream.target_bitrate_bps;
+ encoder_config->min_transmit_bitrate_bps =
+ total_target_bitrate + kPaddingBitrateBps;
+
+ // Configure RTX for redundant payload padding.
+ send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+ send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
+ send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
+ }
+
+ void UpdateReceiveConfig(
+ size_t stream_index,
+ VideoReceiveStream::Config* receive_config) override {
+ receive_config->rtp.extensions.clear();
+ receive_config->rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kTransportSequenceNumber, kExtensionId));
+ }
+
+ virtual test::DirectTransport* CreateSendTransport() {
+ observer_ = new RtpExtensionHeaderObserver();
+ return observer_;
+ }
+
+ private:
+ RtpExtensionHeaderObserver* observer_;
+ } tester;
+
+ tester.RunTest();
}
TEST_F(EndToEndTest, ObserversEncodedFrames) {
@@ -1806,7 +1990,8 @@ void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
num_ssrcs_(num_ssrcs),
send_single_ssrc_first_(send_single_ssrc_first),
ssrcs_to_observe_(num_ssrcs),
- expect_single_ssrc_(send_single_ssrc_first) {
+ expect_single_ssrc_(send_single_ssrc_first),
+ send_stream_(nullptr) {
for (size_t i = 0; i < num_ssrcs; ++i)
valid_ssrcs_[ssrcs[i]] = true;
}
@@ -1898,7 +2083,9 @@ TEST_F(EndToEndTest, ReportsSetEncoderRates) {
public:
EncoderRateStatsTest()
: EndToEndTest(kDefaultTimeoutMs),
- FakeEncoder(Clock::GetRealTimeClock()) {}
+ FakeEncoder(Clock::GetRealTimeClock()),
+ send_stream_(nullptr),
+ bitrate_kbps_(0) {}
void OnStreamsCreated(
VideoSendStream* send_stream,
@@ -2534,6 +2721,8 @@ TEST_F(EndToEndTest, RespectsNetworkState) {
FakeEncoder(Clock::GetRealTimeClock()),
encoded_frames_(EventWrapper::Create()),
packet_event_(EventWrapper::Create()),
+ sender_call_(nullptr),
+ receiver_call_(nullptr),
sender_state_(kNetworkUp),
sender_rtp_(0),
sender_rtcp_(0),
« no previous file with comments | « webrtc/video/call_perf_tests.cc ('k') | webrtc/video/video_receive_stream.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698