Add support for multiple peers in SingleProcessEncodedImageDataInjector

Bug: webrtc:11779
Change-Id: Ie59e39e7fa903432ec13400b1c3e0e1456e812fc
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/180127
Reviewed-by: Andrey Logvin <landrey@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31790}
This commit is contained in:
Artem Titov 2020-07-24 20:32:31 +02:00 committed by Commit Bot
parent 4fd830acab
commit d5f42bdced
7 changed files with 99 additions and 5 deletions

View File

@ -63,6 +63,8 @@ class DefaultEncodedImageDataInjector : public EncodedImageDataInjector,
bool discard,
const EncodedImage& source,
int /*coding_entity_id*/) override;
void Start(int expected_receivers_count) override {}
EncodedImageExtractionResult ExtractData(const EncodedImage& source,
int coding_entity_id) override;
};

View File

@ -32,6 +32,7 @@ rtc::Buffer CreateBufferOfSizeNFilledWithValuesFromX(size_t n, uint8_t x) {
TEST(DefaultEncodedImageDataInjector, InjectExtractDiscardFalse) {
DefaultEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@ -50,6 +51,7 @@ TEST(DefaultEncodedImageDataInjector, InjectExtractDiscardFalse) {
TEST(DefaultEncodedImageDataInjector, InjectExtractDiscardTrue) {
DefaultEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@ -65,6 +67,7 @@ TEST(DefaultEncodedImageDataInjector, InjectExtractDiscardTrue) {
TEST(DefaultEncodedImageDataInjector, Inject3Extract3) {
DefaultEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
@ -108,6 +111,7 @@ TEST(DefaultEncodedImageDataInjector, Inject3Extract3) {
TEST(DefaultEncodedImageDataInjector, InjectExtractFromConcatenated) {
DefaultEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
@ -151,6 +155,7 @@ TEST(DefaultEncodedImageDataInjector, InjectExtractFromConcatenated) {
TEST(DefaultEncodedImageDataInjector,
InjectExtractFromConcatenatedAllDiscarded) {
DefaultEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);

View File

@ -47,6 +47,11 @@ class EncodedImageDataExtractor {
public:
virtual ~EncodedImageDataExtractor() = default;
// Invoked by framework before any image will come to the extractor.
// |expected_receivers_count| is the expected amount of receivers for each
// encoded image.
virtual void Start(int expected_receivers_count) = 0;
// Returns encoded image id, extracted from payload and also encoded image
// with its original payload. For concatenated spatial layers it should be the
// same id. |coding_entity_id| is unique id of decoder or encoder.

View File

@ -95,16 +95,17 @@ EncodedImageExtractionResult SingleProcessEncodedImageDataInjector::ExtractData(
{
MutexLock lock(&lock_);
auto ext_vector_it = extraction_cache_.find(next_id);
// TODO(titovartem) add support for receiving single frame multiple times
// when in simulcast key frame for another spatial stream can be received.
RTC_CHECK(ext_vector_it != extraction_cache_.end())
<< "Unknown frame_id=" << next_id;
auto info_it = ext_vector_it->second.infos.find(sub_id);
RTC_CHECK(info_it != ext_vector_it->second.infos.end())
<< "Unknown sub_id=" << sub_id << " for frame_id=" << next_id;
info_it->second.received_count++;
info = info_it->second;
ext_vector_it->second.infos.erase(info_it);
if (info.received_count == expected_receivers_count_) {
ext_vector_it->second.infos.erase(info_it);
}
}
// We need to discard encoded image only if all concatenated encoded images
// have to be discarded.

View File

@ -50,6 +50,11 @@ class SingleProcessEncodedImageDataInjector : public EncodedImageDataInjector,
bool discard,
const EncodedImage& source,
int coding_entity_id) override;
void Start(int expected_receivers_count) override {
MutexLock crit(&lock_);
expected_receivers_count_ = expected_receivers_count;
}
EncodedImageExtractionResult ExtractData(const EncodedImage& source,
int coding_entity_id) override;
@ -67,6 +72,8 @@ class SingleProcessEncodedImageDataInjector : public EncodedImageDataInjector,
bool discard;
// Data from first 3 bytes of origin encoded image's payload.
uint8_t origin_data[ExtractionInfo::kUsedBufferSize];
// Count of how many times this frame was received.
int received_count = 0;
};
struct ExtractionInfoVector {
@ -79,6 +86,7 @@ class SingleProcessEncodedImageDataInjector : public EncodedImageDataInjector,
};
Mutex lock_;
int expected_receivers_count_ RTC_GUARDED_BY(lock_);
// Stores a mapping from frame id to extraction info for spatial layers
// for this frame id. There can be a lot of them, because if frame was
// dropped we can't clean it up, because we won't receive a signal on

View File

@ -28,10 +28,9 @@ rtc::Buffer CreateBufferOfSizeNFilledWithValuesFromX(size_t n, uint8_t x) {
return buffer;
}
} // namespace
TEST(SingleProcessEncodedImageDataInjector, InjectExtractDiscardFalse) {
SingleProcessEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@ -52,6 +51,7 @@ TEST(SingleProcessEncodedImageDataInjector, InjectExtractDiscardFalse) {
TEST(SingleProcessEncodedImageDataInjector, InjectExtractDiscardTrue) {
SingleProcessEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@ -69,6 +69,7 @@ TEST(SingleProcessEncodedImageDataInjector, InjectExtractDiscardTrue) {
TEST(SingleProcessEncodedImageDataInjector, InjectWithUnsetSpatialLayerSizes) {
SingleProcessEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@ -94,6 +95,7 @@ TEST(SingleProcessEncodedImageDataInjector, InjectWithUnsetSpatialLayerSizes) {
TEST(SingleProcessEncodedImageDataInjector, InjectWithZeroSpatialLayerSizes) {
SingleProcessEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@ -122,6 +124,7 @@ TEST(SingleProcessEncodedImageDataInjector, InjectWithZeroSpatialLayerSizes) {
TEST(SingleProcessEncodedImageDataInjector, Inject3Extract3) {
SingleProcessEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
@ -171,6 +174,7 @@ TEST(SingleProcessEncodedImageDataInjector, Inject3Extract3) {
TEST(SingleProcessEncodedImageDataInjector, InjectExtractFromConcatenated) {
SingleProcessEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
@ -223,6 +227,7 @@ TEST(SingleProcessEncodedImageDataInjector, InjectExtractFromConcatenated) {
TEST(SingleProcessEncodedImageDataInjector,
InjectExtractFromConcatenatedAllDiscarded) {
SingleProcessEncodedImageDataInjector injector;
injector.Start(1);
rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
@ -268,5 +273,72 @@ TEST(SingleProcessEncodedImageDataInjector,
}
}
TEST(SingleProcessEncodedImageDataInjector, InjectOnceExtractTwice) {
SingleProcessEncodedImageDataInjector injector;
injector.Start(2);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
EncodedImage source(buffer.data(), 10, 10);
source.SetTimestamp(123456789);
EncodedImageExtractionResult out =
injector.ExtractData(injector.InjectData(/*id=*/512, /*discard=*/false,
source, /*coding_entity_id=*/1),
/*coding_entity_id=*/2);
EXPECT_EQ(out.id, 512);
EXPECT_FALSE(out.discard);
EXPECT_EQ(out.image.size(), 10ul);
EXPECT_EQ(out.image.capacity(), 10ul);
EXPECT_EQ(out.image.SpatialLayerFrameSize(0).value_or(0), 0ul);
for (int i = 0; i < 10; ++i) {
EXPECT_EQ(out.image.data()[i], i + 1);
}
out =
injector.ExtractData(injector.InjectData(/*id=*/512, /*discard=*/false,
source, /*coding_entity_id=*/1),
2);
EXPECT_EQ(out.id, 512);
EXPECT_FALSE(out.discard);
EXPECT_EQ(out.image.size(), 10ul);
EXPECT_EQ(out.image.capacity(), 10ul);
EXPECT_EQ(out.image.SpatialLayerFrameSize(0).value_or(0), 0ul);
for (int i = 0; i < 10; ++i) {
EXPECT_EQ(out.image.data()[i], i + 1);
}
}
// Death tests.
// Disabled on Android because death tests misbehave on Android, see
// base/test/gtest_util.h.
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
EncodedImage DeepCopyEncodedImage(const EncodedImage& source) {
EncodedImage copy = source;
copy.SetEncodedData(EncodedImageBuffer::Create(source.size()));
memcpy(copy.data(), source.data(), source.size());
return copy;
}
TEST(SingleProcessEncodedImageDataInjector, InjectOnceExtractMoreThenExpected) {
SingleProcessEncodedImageDataInjector injector;
injector.Start(2);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
EncodedImage source(buffer.data(), 10, 10);
source.SetTimestamp(123456789);
EncodedImage modified = injector.InjectData(/*id=*/512, /*discard=*/false,
source, /*coding_entity_id=*/1);
injector.ExtractData(DeepCopyEncodedImage(modified), /*coding_entity_id=*/2);
injector.ExtractData(DeepCopyEncodedImage(modified), /*coding_entity_id=*/2);
EXPECT_DEATH(injector.ExtractData(DeepCopyEncodedImage(modified),
/*coding_entity_id=*/2),
"Unknown sub_id=0 for frame_id=512");
}
#endif // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
} // namespace
} // namespace webrtc_pc_e2e
} // namespace webrtc

View File

@ -149,6 +149,7 @@ void VideoQualityAnalyzerInjectionHelper::Start(
rtc::ArrayView<const std::string> peer_names,
int max_threads_count) {
analyzer_->Start(std::move(test_case_name), peer_names, max_threads_count);
extractor_->Start(peer_names.size());
}
void VideoQualityAnalyzerInjectionHelper::OnStatsReports(