Fix logic reading spatial/temporal id in VideoStreamEncoder.
The temporal id must be read from `EncodedImage` rather than codec specifics for AV1. Furthermore, in some configs the spatial id of `EncodedImage` is populated and set to 0 while the simulcast id can also be simultaneously populated and set to values, including non-zero. To solve this, just take the max of the two. Bug: b/349561566 Change-Id: I46c61b7f0fff7a7ab8d7262c3a8d413f49b3286a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/355904 Reviewed-by: Philip Eliasson <philipel@webrtc.org> Commit-Queue: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42573}
This commit is contained in:
parent
445d403eca
commit
fe4c1dd6dc
@ -151,6 +151,7 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
|
|||||||
if (qp)
|
if (qp)
|
||||||
encoded.qp_ = *qp;
|
encoded.qp_ = *qp;
|
||||||
encoded.SetSimulcastIndex(i);
|
encoded.SetSimulcastIndex(i);
|
||||||
|
encoded.SetTemporalIndex(frame_info.layers[i].temporal_id);
|
||||||
CodecSpecificInfo codec_specific = EncodeHook(encoded, buffer);
|
CodecSpecificInfo codec_specific = EncodeHook(encoded, buffer);
|
||||||
|
|
||||||
if (callback->OnEncodedImage(encoded, &codec_specific).error !=
|
if (callback->OnEncodedImage(encoded, &codec_specific).error !=
|
||||||
|
|||||||
@ -2168,7 +2168,10 @@ EncodedImageCallback::Result VideoStreamEncoder::OnEncodedImage(
|
|||||||
image_copy.ClearEncodedData();
|
image_copy.ClearEncodedData();
|
||||||
|
|
||||||
int temporal_index = 0;
|
int temporal_index = 0;
|
||||||
if (codec_specific_info) {
|
if (encoded_image.TemporalIndex()) {
|
||||||
|
// Give precedence to the metadata on EncodedImage, if available.
|
||||||
|
temporal_index = *encoded_image.TemporalIndex();
|
||||||
|
} else if (codec_specific_info) {
|
||||||
if (codec_specific_info->codecType == kVideoCodecVP9) {
|
if (codec_specific_info->codecType == kVideoCodecVP9) {
|
||||||
temporal_index = codec_specific_info->codecSpecific.VP9.temporal_idx;
|
temporal_index = codec_specific_info->codecSpecific.VP9.temporal_idx;
|
||||||
} else if (codec_specific_info->codecType == kVideoCodecVP8) {
|
} else if (codec_specific_info->codecType == kVideoCodecVP8) {
|
||||||
@ -2412,8 +2415,8 @@ void VideoStreamEncoder::RunPostEncode(const EncodedImage& encoded_image,
|
|||||||
// TODO(https://crbug.com/webrtc/14891): If we want to support a mix of
|
// TODO(https://crbug.com/webrtc/14891): If we want to support a mix of
|
||||||
// simulcast and SVC we'll also need to consider the case where we have both
|
// simulcast and SVC we'll also need to consider the case where we have both
|
||||||
// simulcast and spatial indices.
|
// simulcast and spatial indices.
|
||||||
int stream_index = encoded_image.SpatialIndex().value_or(
|
int stream_index = std::max(encoded_image.SimulcastIndex().value_or(0),
|
||||||
encoded_image.SimulcastIndex().value_or(0));
|
encoded_image.SpatialIndex().value_or(0));
|
||||||
bitrate_adjuster_->OnEncodedFrame(frame_size, stream_index, temporal_index);
|
bitrate_adjuster_->OnEncodedFrame(frame_size, stream_index, temporal_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,6 +76,7 @@
|
|||||||
#include "test/video_encoder_proxy_factory.h"
|
#include "test/video_encoder_proxy_factory.h"
|
||||||
#include "video/config/encoder_stream_factory.h"
|
#include "video/config/encoder_stream_factory.h"
|
||||||
#include "video/config/video_encoder_config.h"
|
#include "video/config/video_encoder_config.h"
|
||||||
|
#include "video/encoder_bitrate_adjuster.h"
|
||||||
#include "video/frame_cadence_adapter.h"
|
#include "video/frame_cadence_adapter.h"
|
||||||
#include "video/send_statistics_proxy.h"
|
#include "video/send_statistics_proxy.h"
|
||||||
|
|
||||||
@ -2583,6 +2584,58 @@ TEST_F(VideoStreamEncoderTest,
|
|||||||
video_stream_encoder_->Stop();
|
video_stream_encoder_->Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(VideoStreamEncoderTest, CorrectlyAdjustsAv1Bitrate) {
|
||||||
|
ResetEncoder("AV1", /*num_streams*/ 2, /*num_temporal_layers=*/2,
|
||||||
|
/*num_spatial_layers=*/1, /*screenshare*/ false,
|
||||||
|
kDefaultFramerate,
|
||||||
|
VideoStreamEncoder::BitrateAllocationCallbackType::
|
||||||
|
kVideoLayersAllocation);
|
||||||
|
|
||||||
|
// Let link allocation and stable bitrate be 2x the target bitrate.
|
||||||
|
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
|
||||||
|
kTargetBitrate, 2 * kTargetBitrate, 2 * kTargetBitrate, 0, 0, 0);
|
||||||
|
|
||||||
|
video_source_.IncomingCapturedFrame(
|
||||||
|
CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
|
||||||
|
WaitForEncodedFrame(CurrentTimeMs());
|
||||||
|
|
||||||
|
// Before enough data has been gathered, some default pushback is applied.
|
||||||
|
VideoEncoder::RateControlParameters rate_settings =
|
||||||
|
*fake_encoder_.GetAndResetLastRateControlSettings();
|
||||||
|
// Allow 5% diff from target bitrate.
|
||||||
|
const double allowed_error_bps =
|
||||||
|
rate_settings.target_bitrate.get_sum_bps() * 0.05;
|
||||||
|
EXPECT_NEAR(rate_settings.bitrate.get_sum_bps(),
|
||||||
|
rate_settings.target_bitrate.get_sum_bps() /
|
||||||
|
EncoderBitrateAdjuster::kDefaultUtilizationFactor,
|
||||||
|
allowed_error_bps);
|
||||||
|
|
||||||
|
// Insert frames until bitrate adjuster is saturated.
|
||||||
|
const TimeDelta runtime =
|
||||||
|
TimeDelta::Millis(EncoderBitrateAdjuster::kWindowSizeMs);
|
||||||
|
const Timestamp start_time = clock()->CurrentTime();
|
||||||
|
while (clock()->CurrentTime() - start_time < runtime) {
|
||||||
|
video_source_.IncomingCapturedFrame(
|
||||||
|
CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
|
||||||
|
WaitForEncodedFrame(CurrentTimeMs());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure rate has been reallocated.
|
||||||
|
video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
|
||||||
|
kTargetBitrate - DataRate::BitsPerSec(500), 2 * kTargetBitrate,
|
||||||
|
2 * kTargetBitrate, 0, 0, 0);
|
||||||
|
video_source_.IncomingCapturedFrame(
|
||||||
|
CreateFrame(CurrentTimeMs(), codec_width_, codec_height_));
|
||||||
|
WaitForEncodedFrame(CurrentTimeMs());
|
||||||
|
|
||||||
|
// Pushback should no longer happen.
|
||||||
|
rate_settings = *fake_encoder_.GetAndResetLastRateControlSettings();
|
||||||
|
EXPECT_NEAR(rate_settings.bitrate.get_sum_bps(),
|
||||||
|
rate_settings.target_bitrate.get_sum_bps(), allowed_error_bps);
|
||||||
|
|
||||||
|
video_stream_encoder_->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
class ResolutionAlignmentTest
|
class ResolutionAlignmentTest
|
||||||
: public VideoStreamEncoderTest,
|
: public VideoStreamEncoderTest,
|
||||||
public ::testing::WithParamInterface<
|
public ::testing::WithParamInterface<
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user