[DVQA] Allow processing of frames dropped by decoder
Bug: b/257402861 Change-Id: I4d495c33c162c4e3a0afef5b83adf19b6d79dfce Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/284160 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/main@{#38693}
This commit is contained in:
parent
bbdb768989
commit
6d91a718c8
@ -126,16 +126,6 @@ FrameComparison ValidateFrameComparison(FrameComparison comparison) {
|
||||
RTC_DCHECK(comparison.frame_stats.decoded_frame_height.has_value())
|
||||
<< "Dropped frame comparison has to have decoded_frame_height when "
|
||||
<< "decode_end_time is set";
|
||||
} else {
|
||||
RTC_DCHECK(!comparison.frame_stats.received_time.IsFinite())
|
||||
<< "Dropped frame comparison can't have received_time when "
|
||||
<< "decode_end_time is not set and there were no decoder failures";
|
||||
RTC_DCHECK(!comparison.frame_stats.decode_start_time.IsFinite())
|
||||
<< "Dropped frame comparison can't have decode_start_time when "
|
||||
<< "decode_end_time is not set and there were no decoder failures";
|
||||
RTC_DCHECK(!comparison.frame_stats.used_decoder.has_value())
|
||||
<< "Dropped frame comparison can't have used_decoder when "
|
||||
<< "decode_end_time is not set and there were no decoder failures";
|
||||
}
|
||||
RTC_DCHECK(!comparison.frame_stats.rendered_time.IsFinite())
|
||||
<< "Dropped frame comparison can't have rendered_time";
|
||||
@ -448,8 +438,7 @@ void DefaultVideoQualityAnalyzerFramesComparator::ProcessComparison(
|
||||
FrameDropPhase dropped_phase;
|
||||
if (frame_stats.decode_end_time.IsFinite()) {
|
||||
dropped_phase = FrameDropPhase::kAfterDecoder;
|
||||
} else if (frame_stats.decode_start_time.IsFinite() &&
|
||||
frame_stats.decoder_failed) {
|
||||
} else if (frame_stats.decode_start_time.IsFinite()) {
|
||||
dropped_phase = FrameDropPhase::kByDecoder;
|
||||
} else if (frame_stats.encoded_time.IsFinite()) {
|
||||
dropped_phase = FrameDropPhase::kTransport;
|
||||
|
||||
@ -1092,8 +1092,78 @@ TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
|
||||
EXPECT_THAT(stats.decoders, IsEmpty());
|
||||
}
|
||||
|
||||
// TODO(titovartem): add test that just pre decoded frame can't be received as
|
||||
// dropped one because decoder always returns either decoded frame or error.
|
||||
TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
|
||||
PreDecodedDroppedKeyFrameAccountedInStats) {
|
||||
DefaultVideoQualityAnalyzerCpuMeasurer cpu_measurer;
|
||||
DefaultVideoQualityAnalyzerFramesComparator comparator(
|
||||
Clock::GetRealTimeClock(), cpu_measurer,
|
||||
DefaultVideoQualityAnalyzerOptions());
|
||||
|
||||
Timestamp captured_time = Clock::GetRealTimeClock()->CurrentTime();
|
||||
uint16_t frame_id = 1;
|
||||
size_t stream = 0;
|
||||
size_t sender = 0;
|
||||
size_t receiver = 1;
|
||||
InternalStatsKey stats_key(stream, sender, receiver);
|
||||
|
||||
// Frame captured
|
||||
FrameStats frame_stats(/*frame_id=*/1, captured_time);
|
||||
// Frame pre encoded
|
||||
frame_stats.pre_encode_time = captured_time + TimeDelta::Millis(10);
|
||||
// Frame encoded
|
||||
frame_stats.encoded_time = captured_time + TimeDelta::Millis(20);
|
||||
frame_stats.used_encoder =
|
||||
Vp8CodecForOneFrame(frame_id, frame_stats.encoded_time);
|
||||
frame_stats.encoded_frame_type = VideoFrameType::kVideoFrameKey;
|
||||
frame_stats.encoded_image_size = DataSize::Bytes(1000);
|
||||
frame_stats.target_encode_bitrate = 2000;
|
||||
// Frame pre decoded
|
||||
frame_stats.pre_decoded_frame_type = VideoFrameType::kVideoFrameKey;
|
||||
frame_stats.pre_decoded_image_size = DataSize::Bytes(500);
|
||||
frame_stats.received_time = captured_time + TimeDelta::Millis(30);
|
||||
frame_stats.decode_start_time = captured_time + TimeDelta::Millis(40);
|
||||
|
||||
comparator.Start(/*max_threads_count=*/1);
|
||||
comparator.EnsureStatsForStream(stream, sender, /*peers_count=*/2,
|
||||
captured_time, captured_time);
|
||||
comparator.AddComparison(stats_key,
|
||||
/*captured=*/absl::nullopt,
|
||||
/*rendered=*/absl::nullopt,
|
||||
FrameComparisonType::kDroppedFrame, frame_stats);
|
||||
comparator.Stop(/*last_rendered_frame_times=*/{});
|
||||
|
||||
EXPECT_EQ(comparator.stream_stats().size(), 1lu);
|
||||
StreamStats stats = comparator.stream_stats().at(stats_key);
|
||||
EXPECT_EQ(stats.stream_started_time, captured_time);
|
||||
expectEmpty(stats.psnr);
|
||||
expectEmpty(stats.ssim);
|
||||
expectEmpty(stats.transport_time_ms);
|
||||
expectEmpty(stats.total_delay_incl_transport_ms);
|
||||
expectEmpty(stats.time_between_rendered_frames_ms);
|
||||
expectEmpty(stats.encode_frame_rate);
|
||||
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.encode_time_ms), 10.0);
|
||||
expectEmpty(stats.decode_time_ms);
|
||||
expectEmpty(stats.receive_to_render_time_ms);
|
||||
expectEmpty(stats.skipped_between_rendered);
|
||||
expectEmpty(stats.freeze_time_ms);
|
||||
expectEmpty(stats.time_between_freezes_ms);
|
||||
expectEmpty(stats.resolution_of_decoded_frame);
|
||||
EXPECT_DOUBLE_EQ(GetFirstOrDie(stats.target_encode_bitrate), 2000.0);
|
||||
expectEmpty(stats.recv_key_frame_size_bytes);
|
||||
expectEmpty(stats.recv_delta_frame_size_bytes);
|
||||
EXPECT_EQ(stats.total_encoded_images_payload, 1000);
|
||||
EXPECT_EQ(stats.num_send_key_frames, 1);
|
||||
EXPECT_EQ(stats.num_recv_key_frames, 0);
|
||||
EXPECT_THAT(stats.dropped_by_phase, Eq(std::map<FrameDropPhase, int64_t>{
|
||||
{FrameDropPhase::kBeforeEncoder, 0},
|
||||
{FrameDropPhase::kByEncoder, 0},
|
||||
{FrameDropPhase::kTransport, 0},
|
||||
{FrameDropPhase::kByDecoder, 1},
|
||||
{FrameDropPhase::kAfterDecoder, 0}}));
|
||||
EXPECT_EQ(stats.encoders,
|
||||
std::vector<StreamCodecInfo>{*frame_stats.used_encoder});
|
||||
EXPECT_THAT(stats.decoders, IsEmpty());
|
||||
}
|
||||
|
||||
TEST(DefaultVideoQualityAnalyzerFramesComparatorTest,
|
||||
DecodedDroppedKeyFrameAccountedInStats) {
|
||||
|
||||
@ -2123,6 +2123,45 @@ TEST(DefaultVideoQualityAnalyzerTest, InfraMetricsNotCollectedByDefault) {
|
||||
EXPECT_EQ(stats.on_decoder_error_processing_time_ms.NumSamples(), 0);
|
||||
}
|
||||
|
||||
TEST(DefaultVideoQualityAnalyzerTest,
|
||||
FrameDroppedByDecoderIsAccountedCorrectly) {
|
||||
std::unique_ptr<test::FrameGeneratorInterface> frame_generator =
|
||||
test::CreateSquareFrameGenerator(kFrameWidth, kFrameHeight,
|
||||
/*type=*/absl::nullopt,
|
||||
/*num_squares=*/absl::nullopt);
|
||||
|
||||
DefaultVideoQualityAnalyzerOptions options = AnalyzerOptionsForTest();
|
||||
options.report_infra_metrics = false;
|
||||
DefaultVideoQualityAnalyzer analyzer(Clock::GetRealTimeClock(),
|
||||
test::GetGlobalMetricsLogger(), options);
|
||||
analyzer.Start("test_case", std::vector<std::string>{"alice", "bob"},
|
||||
kAnalyzerMaxThreadsCount);
|
||||
|
||||
VideoFrame to_be_dropped_frame =
|
||||
NextFrame(frame_generator.get(), /*timestamp_us=*/1);
|
||||
uint16_t frame_id =
|
||||
analyzer.OnFrameCaptured("alice", "alice_video", to_be_dropped_frame);
|
||||
to_be_dropped_frame.set_id(frame_id);
|
||||
analyzer.OnFramePreEncode("alice", to_be_dropped_frame);
|
||||
analyzer.OnFrameEncoded("alice", to_be_dropped_frame.id(),
|
||||
FakeEncode(to_be_dropped_frame),
|
||||
VideoQualityAnalyzerInterface::EncoderStats(), false);
|
||||
VideoFrame received_to_be_dropped_frame = DeepCopy(to_be_dropped_frame);
|
||||
analyzer.OnFramePreDecode("bob", received_to_be_dropped_frame.id(),
|
||||
FakeEncode(received_to_be_dropped_frame));
|
||||
PassFramesThroughAnalyzer(analyzer, "alice", "alice_video", {"bob"},
|
||||
/*frames_count=*/1, *frame_generator);
|
||||
|
||||
// Give analyzer some time to process frames on async thread. The computations
|
||||
// have to be fast (heavy metrics are disabled!), so if doesn't fit 100ms it
|
||||
// means we have an issue!
|
||||
SleepMs(100);
|
||||
analyzer.Stop();
|
||||
|
||||
StreamStats stats = analyzer.GetStats().at(StatsKey("alice_video", "bob"));
|
||||
ASSERT_EQ(stats.dropped_by_phase[FrameDropPhase::kByDecoder], 1);
|
||||
}
|
||||
|
||||
class DefaultVideoQualityAnalyzerTimeBetweenFreezesTest
|
||||
: public TestWithParam<bool> {};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user