Add multithreaded fake encoder and corresponding FlexFEC VideoSendStreamTest.

This test would have found the issue that was fixed in
https://codereview.webrtc.org/2562983002/.

BUG=webrtc:5654

Review-Url: https://codereview.webrtc.org/2573453002
Cr-Commit-Position: refs/heads/master@{#15675}
This commit is contained in:
brandtr 2016-12-19 05:47:28 -08:00 committed by Commit bot
parent b78306a7d3
commit 696c9c6b64
4 changed files with 142 additions and 43 deletions

View File

@ -12,6 +12,7 @@
#include <algorithm>
#include "webrtc/base/atomicops.h"
#include "webrtc/base/checks.h"
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
#include "webrtc/system_wrappers/include/sleep.h"
@ -225,5 +226,61 @@ int32_t DelayedEncoder::Encode(const VideoFrame& input_image,
SleepMs(delay_ms);
return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
}
MultiThreadedFakeH264Encoder::MultiThreadedFakeH264Encoder(Clock* clock)
: test::FakeH264Encoder(clock),
current_queue_(0),
queue1_("Queue 1"),
queue2_("Queue 2") {}
MultiThreadedFakeH264Encoder::~MultiThreadedFakeH264Encoder() = default;
class MultiThreadedFakeH264Encoder::EncodeTask : public rtc::QueuedTask {
public:
EncodeTask(MultiThreadedFakeH264Encoder* encoder,
const VideoFrame& input_image,
const CodecSpecificInfo* codec_specific_info,
const std::vector<FrameType>* frame_types)
: encoder_(encoder),
input_image_(input_image),
codec_specific_info_(),
frame_types_(*frame_types) {
if (codec_specific_info)
codec_specific_info_ = *codec_specific_info;
}
private:
bool Run() override {
encoder_->EncodeCallback(input_image_, &codec_specific_info_,
&frame_types_);
return true;
}
MultiThreadedFakeH264Encoder* const encoder_;
VideoFrame input_image_;
CodecSpecificInfo codec_specific_info_;
std::vector<FrameType> frame_types_;
};
int32_t MultiThreadedFakeH264Encoder::Encode(
const VideoFrame& input_image,
const CodecSpecificInfo* codec_specific_info,
const std::vector<FrameType>* frame_types) {
int current_queue = rtc::AtomicOps::Increment(&current_queue_);
rtc::TaskQueue& queue = (current_queue % 2 == 0) ? queue1_ : queue2_;
queue.PostTask(std::unique_ptr<rtc::QueuedTask>(
new EncodeTask(this, input_image, codec_specific_info, frame_types)));
return 0;
}
int32_t MultiThreadedFakeH264Encoder::EncodeCallback(
const VideoFrame& input_image,
const CodecSpecificInfo* codec_specific_info,
const std::vector<FrameType>* frame_types) {
return FakeH264Encoder::Encode(input_image, codec_specific_info, frame_types);
}
} // namespace test
} // namespace webrtc

View File

@ -14,6 +14,7 @@
#include <vector>
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/task_queue.h"
#include "webrtc/common_types.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/video_encoder.h"
@ -86,6 +87,31 @@ class DelayedEncoder : public test::FakeEncoder {
rtc::CriticalSection lock_;
int delay_ms_ GUARDED_BY(&lock_);
};
// This class implements a multi-threaded fake encoder by posting
// FakeH264Encoder::Encode(.) tasks to |queue1_| and |queue2_|, in an
// alternating fashion.
class MultiThreadedFakeH264Encoder : public test::FakeH264Encoder {
public:
MultiThreadedFakeH264Encoder(Clock* clock);
virtual ~MultiThreadedFakeH264Encoder() override;
int32_t Encode(const VideoFrame& input_image,
const CodecSpecificInfo* codec_specific_info,
const std::vector<FrameType>* frame_types) override;
int32_t EncodeCallback(const VideoFrame& input_image,
const CodecSpecificInfo* codec_specific_info,
const std::vector<FrameType>* frame_types);
protected:
class EncodeTask;
int current_queue_;
rtc::TaskQueue queue1_;
rtc::TaskQueue queue2_;
};
} // namespace test
} // namespace webrtc

View File

@ -84,6 +84,7 @@ if (rtc_include_tests) {
"video_quality_test.h",
]
deps = [
"../base:rtc_task_queue",
"../media:rtc_media_base",
"../system_wrappers",
"//testing/gtest",

View File

@ -356,25 +356,17 @@ class UlpfecObserver : public test::EndToEndTest {
bool use_nack,
bool expect_red,
bool expect_ulpfec,
const std::string& codec)
const std::string& codec,
VideoEncoder* encoder)
: EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs),
encoder_(encoder),
payload_name_(codec),
use_nack_(use_nack),
expect_red_(expect_red),
expect_ulpfec_(expect_ulpfec),
sent_media_(false),
sent_ulpfec_(false),
header_extensions_enabled_(header_extensions_enabled) {
if (codec == "H264") {
encoder_.reset(new test::FakeH264Encoder(Clock::GetRealTimeClock()));
} else if (codec == "VP8") {
encoder_.reset(VP8Encoder::Create());
} else if (codec == "VP9") {
encoder_.reset(VP9Encoder::Create());
} else {
RTC_NOTREACHED();
}
}
header_extensions_enabled_(header_extensions_enabled) {}
private:
Action OnSendRtp(const uint8_t* packet, size_t length) override {
@ -462,7 +454,7 @@ class UlpfecObserver : public test::EndToEndTest {
(*receive_configs)[0].rtp.nack.rtp_history_ms =
VideoSendStreamTest::kNackRtpHistoryMs;
}
send_config->encoder_settings.encoder = encoder_.get();
send_config->encoder_settings.encoder = encoder_;
send_config->encoder_settings.payload_name = payload_name_;
send_config->rtp.ulpfec.red_payload_type =
VideoSendStreamTest::kRedPayloadType;
@ -486,8 +478,8 @@ class UlpfecObserver : public test::EndToEndTest {
}
std::unique_ptr<internal::TransportAdapter> transport_adapter_;
std::unique_ptr<VideoEncoder> encoder_;
const std::string payload_name_;
VideoEncoder* const encoder_;
std::string payload_name_;
const bool use_nack_;
const bool expect_red_;
const bool expect_ulpfec_;
@ -498,12 +490,14 @@ class UlpfecObserver : public test::EndToEndTest {
};
TEST_F(VideoSendStreamTest, SupportsUlpfecWithExtensions) {
UlpfecObserver test(true, false, true, true, "VP8");
std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
UlpfecObserver test(true, false, true, true, "VP8", encoder.get());
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsUlpfecWithoutExtensions) {
UlpfecObserver test(false, false, true, true, "VP8");
std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
UlpfecObserver test(false, false, true, true, "VP8", encoder.get());
RunBaseTest(&test);
}
@ -512,51 +506,56 @@ TEST_F(VideoSendStreamTest, SupportsUlpfecWithoutExtensions) {
// bandwidth since the receiver has to wait for FEC retransmissions to determine
// that the received state is actually decodable.
TEST_F(VideoSendStreamTest, DoesNotUtilizeUlpfecForH264WithNackEnabled) {
UlpfecObserver test(false, true, true, false, "H264");
std::unique_ptr<VideoEncoder> encoder(
new test::FakeH264Encoder(Clock::GetRealTimeClock()));
UlpfecObserver test(false, true, true, false, "H264", encoder.get());
RunBaseTest(&test);
}
// Without retransmissions FEC for H264 is fine.
TEST_F(VideoSendStreamTest, DoesUtilizeUlpfecForH264WithoutNackEnabled) {
UlpfecObserver test(false, false, true, true, "H264");
std::unique_ptr<VideoEncoder> encoder(
new test::FakeH264Encoder(Clock::GetRealTimeClock()));
UlpfecObserver test(false, false, true, true, "H264", encoder.get());
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, DoesUtilizeUlpfecForVp8WithNackEnabled) {
UlpfecObserver test(false, true, true, true, "VP8");
std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
UlpfecObserver test(false, true, true, true, "VP8", encoder.get());
RunBaseTest(&test);
}
#if !defined(RTC_DISABLE_VP9)
TEST_F(VideoSendStreamTest, DoesUtilizeUlpfecForVp9WithNackEnabled) {
UlpfecObserver test(false, true, true, true, "VP9");
std::unique_ptr<VideoEncoder> encoder(VP9Encoder::Create());
UlpfecObserver test(false, true, true, true, "VP9", encoder.get());
RunBaseTest(&test);
}
#endif // !defined(RTC_DISABLE_VP9)
TEST_F(VideoSendStreamTest, SupportsUlpfecWithMultiThreadedH264) {
std::unique_ptr<VideoEncoder> encoder(
new test::MultiThreadedFakeH264Encoder(Clock::GetRealTimeClock()));
UlpfecObserver test(false, false, true, true, "H264", encoder.get());
RunBaseTest(&test);
}
// TODO(brandtr): Move these FlexFEC tests when we have created
// FlexfecSendStream.
class FlexfecObserver : public test::EndToEndTest {
public:
FlexfecObserver(bool header_extensions_enabled,
bool use_nack,
const std::string& codec)
const std::string& codec,
VideoEncoder* encoder)
: EndToEndTest(VideoSendStreamTest::kDefaultTimeoutMs),
encoder_(encoder),
payload_name_(codec),
use_nack_(use_nack),
sent_media_(false),
sent_flexfec_(false),
header_extensions_enabled_(header_extensions_enabled) {
if (codec == "H264") {
encoder_.reset(new test::FakeH264Encoder(Clock::GetRealTimeClock()));
} else if (codec == "VP8") {
encoder_.reset(VP8Encoder::Create());
} else if (codec == "VP9") {
encoder_.reset(VP9Encoder::Create());
} else {
RTC_NOTREACHED();
}
}
header_extensions_enabled_(header_extensions_enabled) {}
size_t GetNumFlexfecStreams() const override { return 1; }
@ -611,7 +610,7 @@ class FlexfecObserver : public test::EndToEndTest {
(*receive_configs)[0].rtp.nack.rtp_history_ms =
VideoSendStreamTest::kNackRtpHistoryMs;
}
send_config->encoder_settings.encoder = encoder_.get();
send_config->encoder_settings.encoder = encoder_;
send_config->encoder_settings.payload_name = payload_name_;
if (header_extensions_enabled_) {
send_config->rtp.extensions.push_back(RtpExtension(
@ -630,8 +629,8 @@ class FlexfecObserver : public test::EndToEndTest {
}
std::unique_ptr<internal::TransportAdapter> transport_adapter_;
std::unique_ptr<VideoEncoder> encoder_;
const std::string payload_name_;
VideoEncoder* const encoder_;
std::string payload_name_;
const bool use_nack_;
bool sent_media_;
bool sent_flexfec_;
@ -639,39 +638,55 @@ class FlexfecObserver : public test::EndToEndTest {
};
TEST_F(VideoSendStreamTest, SupportsFlexfecVp8) {
FlexfecObserver test(false, false, "VP8");
std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
FlexfecObserver test(false, false, "VP8", encoder.get());
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp8) {
FlexfecObserver test(false, true, "VP8");
std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
FlexfecObserver test(false, true, "VP8", encoder.get());
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsFlexfecWithRtpExtensionsVp8) {
FlexfecObserver test(true, false, "VP8");
std::unique_ptr<VideoEncoder> encoder(VP8Encoder::Create());
FlexfecObserver test(true, false, "VP8", encoder.get());
RunBaseTest(&test);
}
#if !defined(RTC_DISABLE_VP9)
TEST_F(VideoSendStreamTest, SupportsFlexfecVp9) {
FlexfecObserver test(false, false, "VP9");
std::unique_ptr<VideoEncoder> encoder(VP9Encoder::Create());
FlexfecObserver test(false, false, "VP9", encoder.get());
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackVp9) {
FlexfecObserver test(false, true, "VP9");
std::unique_ptr<VideoEncoder> encoder(VP9Encoder::Create());
FlexfecObserver test(false, true, "VP9", encoder.get());
RunBaseTest(&test);
}
#endif // defined(RTC_DISABLE_VP9)
TEST_F(VideoSendStreamTest, SupportsFlexfecH264) {
FlexfecObserver test(false, false, "H264");
std::unique_ptr<VideoEncoder> encoder(
new test::FakeH264Encoder(Clock::GetRealTimeClock()));
FlexfecObserver test(false, false, "H264", encoder.get());
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsFlexfecWithNackH264) {
FlexfecObserver test(false, true, "H264");
std::unique_ptr<VideoEncoder> encoder(
new test::FakeH264Encoder(Clock::GetRealTimeClock()));
FlexfecObserver test(false, true, "H264", encoder.get());
RunBaseTest(&test);
}
TEST_F(VideoSendStreamTest, SupportsFlexfecWithMultiThreadedH264) {
std::unique_ptr<VideoEncoder> encoder(
new test::MultiThreadedFakeH264Encoder(Clock::GetRealTimeClock()));
FlexfecObserver test(false, false, "H264", encoder.get());
RunBaseTest(&test);
}