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