Add workaround for OpenH264 related to U/V strides. This CL adds a workaround for a bug in OpenH264, where using an input frame where the U and V strides are different may result in a crash. This fix should be removed once the root cause has been addressed. Bug: chromium:491655161 Change-Id: I2e8bccefab3ffcd08bf1e086763407ceb461bba7 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/456121 Reviewed-by: Sergey Silkin <ssilkin@webrtc.org> Commit-Queue: Sergey Silkin <ssilkin@webrtc.org> Auto-Submit: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47131}
diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl.cc b/modules/video_coding/codecs/h264/h264_encoder_impl.cc index 0260202..b682013 100644 --- a/modules/video_coding/codecs/h264/h264_encoder_impl.cc +++ b/modules/video_coding/codecs/h264/h264_encoder_impl.cc
@@ -450,6 +450,11 @@ << " image to I420. Can't encode frame."; return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE; } + if (frame_buffer->StrideU() != frame_buffer->StrideV()) { + // TODO: crbug.com/chromium:491655161 - Remove once the root cause is fixed. + RTC_LOG(LS_ERROR) << "OpenH264 requires the U and V strides to be equal."; + return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE; + } RTC_CHECK(frame_buffer->type() == VideoFrameBuffer::Type::kI420 || frame_buffer->type() == VideoFrameBuffer::Type::kI420A);
diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl_unittest.cc b/modules/video_coding/codecs/h264/h264_encoder_impl_unittest.cc index 0149a8c..e5aade5 100644 --- a/modules/video_coding/codecs/h264/h264_encoder_impl_unittest.cc +++ b/modules/video_coding/codecs/h264/h264_encoder_impl_unittest.cc
@@ -18,6 +18,7 @@ #include "api/test/create_frame_generator.h" #include "api/test/frame_generator_interface.h" #include "api/test/mock_video_encoder.h" +#include "api/video/i420_buffer.h" #include "api/video/video_codec_type.h" #include "api/video/video_frame.h" #include "api/video_codecs/video_codec.h" @@ -137,6 +138,31 @@ } } +TEST(H264EncoderImplTest, RejectsFramesWithUnequalChromaStrides) { + H264EncoderImpl encoder(CreateEnvironment(), {}); + VideoCodec codec_settings; + SetDefaultSettings(&codec_settings); + MockEncodedImageCallback callback; + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + encoder.InitEncode(&codec_settings, kSettings)); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, + encoder.RegisterEncodeCompleteCallback(&callback)); + // Create a VideoFrame where the U and V strides are different. + auto buffer = I420Buffer::Create( + /*width=*/codec_settings.width, + /*height=*/codec_settings.height, + /*stride_y=*/codec_settings.width, + /*stride_u=*/(codec_settings.width + 1) / 2, + /*stride_v=*/(codec_settings.width + 1) / 2 + 1); + + VideoFrame frame = VideoFrame::Builder() + .set_video_frame_buffer(buffer) + .set_rtp_timestamp(0) + .build(); + + EXPECT_EQ(WEBRTC_VIDEO_CODEC_ENCODER_FAILURE, encoder.Encode(frame, nullptr)); +} + } // anonymous namespace } // namespace webrtc