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:
parent
b78306a7d3
commit
696c9c6b64
@ -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(¤t_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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user