Restore bit depth check in LibvpxVp9Decoder

ReturnFrame() used to reject decoded images with bit depths other than 8
and 10. The check was lost when it started to switch on img->fmt instead
of img->bit_depth in
https://webrtc-review.googlesource.com/c/src/+/266180. Since then,
12-bit frames (VP9 profile 2 and 3) are wrapped in 10-bit buffers and,
for BT.2020 content, hit RTC_DCHECK_NOTREACHED() in
ExtractVP9ColorSpace().

Return WEBRTC_VIDEO_CODEC_NO_OUTPUT for such frames again, since no
frame buffer type can represent 12-bit content.

Fixed: chromium:569701823
Change-Id: I7ba5437dfeffc581c2dbc516ab492252928cdc67
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/507600
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#48799}
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index 6c15cd1..d8790cf 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -1834,6 +1834,7 @@
         "../../api:field_trials",
         "../../api:frame_generator_api",
         "../../api:make_ref_counted",
+        "../../api:mock_video_decoder",
         "../../api:mock_video_encoder",
         "../../api:scoped_refptr",
         "../../api/environment:environment_factory",
diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_decoder.cc b/modules/video_coding/codecs/vp9/libvpx_vp9_decoder.cc
index 0dafd3e..92b66d7 100644
--- a/modules/video_coding/codecs/vp9/libvpx_vp9_decoder.cc
+++ b/modules/video_coding/codecs/vp9/libvpx_vp9_decoder.cc
@@ -274,6 +274,15 @@
     return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
   }
 
+  // The buffer types below only represent 8-bit and 10-bit content. Without
+  // this check, e.g. 12-bit samples (VP9 profile 2 and 3) would be wrapped as
+  // 10-bit buffers, and ExtractVP9ColorSpace() would get an unexpected depth.
+  if (img->bit_depth != 8 && img->bit_depth != 10) {
+    RTC_LOG(LS_ERROR) << "Unsupported bit depth produced by the decoder: "
+                      << img->bit_depth;
+    return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
+  }
+
   // This buffer contains all of `img`'s image data, a reference counted
   // Vp9FrameBuffer. (libvpx is done with the buffers after a few
   // vpx_codec_decode calls or vpx_codec_destroy).
diff --git a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
index 6f688df..9742d27 100644
--- a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
+++ b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
@@ -27,6 +27,7 @@
 #include "api/scoped_refptr.h"
 #include "api/test/create_frame_generator.h"
 #include "api/test/frame_generator_interface.h"
+#include "api/test/mock_video_decoder.h"
 #include "api/test/mock_video_encoder.h"
 #include "api/units/data_rate.h"
 #include "api/units/timestamp.h"
@@ -2352,6 +2353,45 @@
             31);
 }
 
+// A 16x16 mid-gray VP9 key frame with 12-bit samples (profile 2) and the
+// BT.2020 color space, encoded by libvpx.
+constexpr uint8_t kVp9KeyFrameWith12BitDepth[] = {
+    0x92, 0x49, 0x83, 0x42, 0xd0, 0x00, 0x78, 0x00, 0x7b, 0x03, 0x1c,
+    0x12, 0x0e, 0x0c, 0x29, 0x00, 0x00, 0x10, 0x40, 0x00, 0x37, 0x80};
+
+TEST(Vp9ImplTest, DecodeReturnsNoOutputForUnsupportedBitDepth) {
+  // Decoding 12-bit samples requires libvpx to be built with high bit depth
+  // support, which VP9 profile 2 support also depends on.
+  bool profile_2_is_supported = false;
+  for (const auto& format : SupportedVP9DecoderCodecs()) {
+    if (ParseSdpForVP9Profile(format.parameters) == VP9Profile::kProfile2) {
+      profile_2_is_supported = true;
+    }
+  }
+  if (!profile_2_is_supported) {
+    GTEST_SKIP() << "libvpx is built without high bit depth support.";
+  }
+  std::optional<Vp9UncompressedHeader> header =
+      ParseUncompressedVp9Header(kVp9KeyFrameWith12BitDepth);
+  ASSERT_TRUE(header);
+  ASSERT_EQ(header->bit_detph, Vp9BitDept::k12Bit);
+  ASSERT_EQ(header->color_space, Vp9ColorSpace::CS_BT_2020);
+
+  MockDecodedImageCallback callback;
+  EXPECT_CALL(callback, Decoded(_, _, _)).Times(0);
+  std::unique_ptr<VideoDecoder> decoder = VP9Decoder::Create();
+  decoder->RegisterDecodeCompleteCallback(&callback);
+  ASSERT_TRUE(decoder->Configure(VideoDecoder::Settings()));
+
+  EncodedImage encoded_image;
+  encoded_image.SetEncodedData(EncodedImageBuffer::Create(
+      kVp9KeyFrameWith12BitDepth, sizeof(kVp9KeyFrameWith12BitDepth)));
+  encoded_image.set_frame_type(VideoFrameType::kVideoFrameKey);
+  // There are no frame buffer types that can represent 12-bit content.
+  EXPECT_EQ(decoder->Decode(encoded_image, /*render_time_ms=*/0),
+            WEBRTC_VIDEO_CODEC_NO_OUTPUT);
+}
+
 TEST_F(TestVp9Impl, EncodeWithDynamicRate) {
   // Configured dynamic rate field trial and re-create the encoder.
   field_trials_.Set("WebRTC-VideoRateControl", "vp9_dynamic_rate:true");