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}
diff --git a/test/pc/e2e/analyzer/video/default_encoded_image_data_injector.h b/test/pc/e2e/analyzer/video/default_encoded_image_data_injector.h
index 6ed87f5..b60c214 100644
--- a/test/pc/e2e/analyzer/video/default_encoded_image_data_injector.h
+++ b/test/pc/e2e/analyzer/video/default_encoded_image_data_injector.h
@@ -63,6 +63,8 @@
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;
};
diff --git a/test/pc/e2e/analyzer/video/default_encoded_image_data_injector_unittest.cc b/test/pc/e2e/analyzer/video/default_encoded_image_data_injector_unittest.cc
index 3ad978f..045a655 100644
--- a/test/pc/e2e/analyzer/video/default_encoded_image_data_injector_unittest.cc
+++ b/test/pc/e2e/analyzer/video/default_encoded_image_data_injector_unittest.cc
@@ -32,6 +32,7 @@
TEST(DefaultEncodedImageDataInjector, InjectExtractDiscardFalse) {
DefaultEncodedImageDataInjector injector;
+ injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@@ -50,6 +51,7 @@
TEST(DefaultEncodedImageDataInjector, InjectExtractDiscardTrue) {
DefaultEncodedImageDataInjector injector;
+ injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@@ -65,6 +67,7 @@
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, InjectExtractFromConcatenated) {
DefaultEncodedImageDataInjector injector;
+ injector.Start(1);
rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
@@ -151,6 +155,7 @@
TEST(DefaultEncodedImageDataInjector,
InjectExtractFromConcatenatedAllDiscarded) {
DefaultEncodedImageDataInjector injector;
+ injector.Start(1);
rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
diff --git a/test/pc/e2e/analyzer/video/encoded_image_data_injector.h b/test/pc/e2e/analyzer/video/encoded_image_data_injector.h
index 8e21862..ddd6959 100644
--- a/test/pc/e2e/analyzer/video/encoded_image_data_injector.h
+++ b/test/pc/e2e/analyzer/video/encoded_image_data_injector.h
@@ -47,6 +47,11 @@
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.
diff --git a/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.cc b/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.cc
index 8e7a511..419a7be 100644
--- a/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.cc
+++ b/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.cc
@@ -95,16 +95,17 @@
{
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.
diff --git a/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.h b/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.h
index c70c25b..8cf1bc4 100644
--- a/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.h
+++ b/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.h
@@ -50,6 +50,11 @@
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 @@
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 @@
};
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
diff --git a/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector_unittest.cc b/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector_unittest.cc
index e25361e..00197f3 100644
--- a/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector_unittest.cc
+++ b/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector_unittest.cc
@@ -28,10 +28,9 @@
return buffer;
}
-} // namespace
-
TEST(SingleProcessEncodedImageDataInjector, InjectExtractDiscardFalse) {
SingleProcessEncodedImageDataInjector injector;
+ injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@@ -52,6 +51,7 @@
TEST(SingleProcessEncodedImageDataInjector, InjectExtractDiscardTrue) {
SingleProcessEncodedImageDataInjector injector;
+ injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@@ -69,6 +69,7 @@
TEST(SingleProcessEncodedImageDataInjector, InjectWithUnsetSpatialLayerSizes) {
SingleProcessEncodedImageDataInjector injector;
+ injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@@ -94,6 +95,7 @@
TEST(SingleProcessEncodedImageDataInjector, InjectWithZeroSpatialLayerSizes) {
SingleProcessEncodedImageDataInjector injector;
+ injector.Start(1);
rtc::Buffer buffer = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
@@ -122,6 +124,7 @@
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, InjectExtractFromConcatenated) {
SingleProcessEncodedImageDataInjector injector;
+ injector.Start(1);
rtc::Buffer buffer1 = CreateBufferOfSizeNFilledWithValuesFromX(10, 1);
rtc::Buffer buffer2 = CreateBufferOfSizeNFilledWithValuesFromX(10, 11);
@@ -223,6 +227,7 @@
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, 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
diff --git a/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.cc b/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.cc
index 48e65ef..ebfb416 100644
--- a/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.cc
+++ b/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.cc
@@ -149,6 +149,7 @@
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(