tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

libyuv_unittest.cc (17891B)


      1 /*
      2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include <cmath>
     12 #include <cstdint>
     13 #include <cstdio>
     14 #include <cstring>
     15 #include <limits>
     16 #include <memory>
     17 #include <string>
     18 #include <vector>
     19 
     20 #include "api/scoped_refptr.h"
     21 #include "api/video/i010_buffer.h"
     22 #include "api/video/i210_buffer.h"
     23 #include "api/video/i410_buffer.h"
     24 #include "api/video/i420_buffer.h"
     25 #include "api/video/i422_buffer.h"
     26 #include "api/video/i444_buffer.h"
     27 #include "api/video/nv12_buffer.h"
     28 #include "api/video/video_frame.h"
     29 #include "api/video/video_frame_buffer.h"
     30 #include "api/video/video_rotation.h"
     31 #include "common_video/libyuv/include/webrtc_libyuv.h"
     32 #include "test/frame_utils.h"
     33 #include "test/gmock.h"
     34 #include "test/gtest.h"
     35 #include "test/testsupport/file_utils.h"
     36 #include "third_party/libyuv/include/libyuv/convert.h"
     37 #include "third_party/libyuv/include/libyuv/rotate.h"
     38 
     39 namespace webrtc {
     40 
     41 namespace {
     42 void Calc16ByteAlignedStride(int width, int* stride_y, int* stride_uv) {
     43  *stride_y = 16 * ((width + 15) / 16);
     44  *stride_uv = 16 * ((width + 31) / 32);
     45 }
     46 
     47 int PrintPlane(const uint8_t* buf,
     48               int width,
     49               int height,
     50               int stride,
     51               FILE* file) {
     52  for (int i = 0; i < height; i++, buf += stride) {
     53    if (fwrite(buf, 1, width, file) != static_cast<unsigned int>(width))
     54      return -1;
     55  }
     56  return 0;
     57 }
     58 
     59 int PrintVideoFrame(const I420BufferInterface& frame, FILE* file) {
     60  int width = frame.width();
     61  int height = frame.height();
     62  int chroma_width = frame.ChromaWidth();
     63  int chroma_height = frame.ChromaHeight();
     64 
     65  if (PrintPlane(frame.DataY(), width, height, frame.StrideY(), file) < 0) {
     66    return -1;
     67  }
     68  if (PrintPlane(frame.DataU(), chroma_width, chroma_height, frame.StrideU(),
     69                 file) < 0) {
     70    return -1;
     71  }
     72  if (PrintPlane(frame.DataV(), chroma_width, chroma_height, frame.StrideV(),
     73                 file) < 0) {
     74    return -1;
     75  }
     76  return 0;
     77 }
     78 
     79 }  // Anonymous namespace
     80 
     81 class TestLibYuv : public ::testing::Test {
     82 protected:
     83  TestLibYuv();
     84  void SetUp() override;
     85  void TearDown() override;
     86 
     87  FILE* source_file_;
     88  std::unique_ptr<VideoFrame> orig_frame_;
     89  const int width_;
     90  const int height_;
     91  const int size_y_;
     92  const int size_uv_;
     93  const size_t frame_length_;
     94 };
     95 
     96 TestLibYuv::TestLibYuv()
     97    : source_file_(nullptr),
     98      orig_frame_(),
     99      width_(352),
    100      height_(288),
    101      size_y_(width_ * height_),
    102      size_uv_(((width_ + 1) / 2) * ((height_ + 1) / 2)),
    103      frame_length_(CalcBufferSize(VideoType::kI420, 352, 288)) {}
    104 
    105 void TestLibYuv::SetUp() {
    106  const std::string input_file_name = test::ResourcePath("foreman_cif", "yuv");
    107  source_file_ = fopen(input_file_name.c_str(), "rb");
    108  ASSERT_TRUE(source_file_ != nullptr)
    109      << "Cannot read file: " << input_file_name << "\n";
    110 
    111  scoped_refptr<I420BufferInterface> buffer(
    112      test::ReadI420Buffer(width_, height_, source_file_));
    113 
    114  orig_frame_ = std::make_unique<VideoFrame>(VideoFrame::Builder()
    115                                                 .set_video_frame_buffer(buffer)
    116                                                 .set_rotation(kVideoRotation_0)
    117                                                 .set_timestamp_us(0)
    118                                                 .build());
    119 }
    120 
    121 void TestLibYuv::TearDown() {
    122  if (source_file_ != nullptr) {
    123    ASSERT_EQ(0, fclose(source_file_));
    124  }
    125  source_file_ = nullptr;
    126 }
    127 
    128 TEST_F(TestLibYuv, ConvertTest) {
    129  // Reading YUV frame - testing on the first frame of the foreman sequence
    130  int j = 0;
    131  std::string output_file_name =
    132      test::OutputPath() + "LibYuvTest_conversion.yuv";
    133  FILE* output_file = fopen(output_file_name.c_str(), "wb");
    134  ASSERT_TRUE(output_file != nullptr);
    135 
    136  double psnr = 0.0;
    137 
    138  scoped_refptr<I420Buffer> res_i420_buffer =
    139      I420Buffer::Create(width_, height_);
    140 
    141  printf("\nConvert #%d I420 <-> I420 \n", j);
    142  std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]);
    143  EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kI420, 0,
    144                               out_i420_buffer.get()));
    145  int y_size = width_ * height_;
    146  int u_size = res_i420_buffer->ChromaWidth() * res_i420_buffer->ChromaHeight();
    147  int ret = libyuv::I420Copy(
    148      out_i420_buffer.get(), width_, out_i420_buffer.get() + y_size,
    149      width_ >> 1, out_i420_buffer.get() + y_size + u_size, width_ >> 1,
    150      res_i420_buffer->MutableDataY(), res_i420_buffer->StrideY(),
    151      res_i420_buffer->MutableDataU(), res_i420_buffer->StrideU(),
    152      res_i420_buffer->MutableDataV(), res_i420_buffer->StrideV(), width_,
    153      height_);
    154  EXPECT_EQ(0, ret);
    155 
    156  if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
    157    return;
    158  }
    159  psnr =
    160      I420PSNR(*orig_frame_->video_frame_buffer()->GetI420(), *res_i420_buffer);
    161  EXPECT_EQ(48.0, psnr);
    162  j++;
    163 
    164  printf("\nConvert #%d I420 <-> RGB24\n", j);
    165  std::unique_ptr<uint8_t[]> res_rgb_buffer2(new uint8_t[width_ * height_ * 3]);
    166  // Align the stride values for the output frame.
    167  int stride_y = 0;
    168  int stride_uv = 0;
    169  Calc16ByteAlignedStride(width_, &stride_y, &stride_uv);
    170  res_i420_buffer =
    171      I420Buffer::Create(width_, height_, stride_y, stride_uv, stride_uv);
    172  EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kRGB24, 0,
    173                               res_rgb_buffer2.get()));
    174 
    175  ret = libyuv::ConvertToI420(
    176      res_rgb_buffer2.get(), 0, res_i420_buffer->MutableDataY(),
    177      res_i420_buffer->StrideY(), res_i420_buffer->MutableDataU(),
    178      res_i420_buffer->StrideU(), res_i420_buffer->MutableDataV(),
    179      res_i420_buffer->StrideV(), 0, 0, width_, height_,
    180      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
    181      ConvertVideoType(VideoType::kRGB24));
    182 
    183  EXPECT_EQ(0, ret);
    184  if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
    185    return;
    186  }
    187  psnr =
    188      I420PSNR(*orig_frame_->video_frame_buffer()->GetI420(), *res_i420_buffer);
    189 
    190  // Optimization Speed- quality trade-off => 45 dB only (platform dependant).
    191  EXPECT_GT(ceil(psnr), 44);
    192  j++;
    193 
    194  printf("\nConvert #%d I420 <-> UYVY\n", j);
    195  std::unique_ptr<uint8_t[]> out_uyvy_buffer(new uint8_t[width_ * height_ * 2]);
    196  EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kUYVY, 0,
    197                               out_uyvy_buffer.get()));
    198 
    199  ret = libyuv::ConvertToI420(
    200      out_uyvy_buffer.get(), 0, res_i420_buffer->MutableDataY(),
    201      res_i420_buffer->StrideY(), res_i420_buffer->MutableDataU(),
    202      res_i420_buffer->StrideU(), res_i420_buffer->MutableDataV(),
    203      res_i420_buffer->StrideV(), 0, 0, width_, height_,
    204      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
    205      ConvertVideoType(VideoType::kUYVY));
    206 
    207  EXPECT_EQ(0, ret);
    208  psnr =
    209      I420PSNR(*orig_frame_->video_frame_buffer()->GetI420(), *res_i420_buffer);
    210  EXPECT_EQ(48.0, psnr);
    211  if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
    212    return;
    213  }
    214  j++;
    215 
    216  printf("\nConvert #%d I420 <-> YUY2\n", j);
    217  std::unique_ptr<uint8_t[]> out_yuy2_buffer(new uint8_t[width_ * height_ * 2]);
    218  EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kYUY2, 0,
    219                               out_yuy2_buffer.get()));
    220 
    221  ret = libyuv::ConvertToI420(
    222      out_yuy2_buffer.get(), 0, res_i420_buffer->MutableDataY(),
    223      res_i420_buffer->StrideY(), res_i420_buffer->MutableDataU(),
    224      res_i420_buffer->StrideU(), res_i420_buffer->MutableDataV(),
    225      res_i420_buffer->StrideV(), 0, 0, width_, height_,
    226      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
    227      ConvertVideoType(VideoType::kYUY2));
    228 
    229  EXPECT_EQ(0, ret);
    230 
    231  if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
    232    return;
    233  }
    234 
    235  psnr =
    236      I420PSNR(*orig_frame_->video_frame_buffer()->GetI420(), *res_i420_buffer);
    237  EXPECT_EQ(48.0, psnr);
    238 
    239  printf("\nConvert #%d I420 <-> RGB565\n", j);
    240  std::unique_ptr<uint8_t[]> out_rgb565_buffer(
    241      new uint8_t[width_ * height_ * 2]);
    242  EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kRGB565, 0,
    243                               out_rgb565_buffer.get()));
    244 
    245  ret = libyuv::ConvertToI420(
    246      out_rgb565_buffer.get(), 0, res_i420_buffer->MutableDataY(),
    247      res_i420_buffer->StrideY(), res_i420_buffer->MutableDataU(),
    248      res_i420_buffer->StrideU(), res_i420_buffer->MutableDataV(),
    249      res_i420_buffer->StrideV(), 0, 0, width_, height_,
    250      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
    251      ConvertVideoType(VideoType::kRGB565));
    252 
    253  EXPECT_EQ(0, ret);
    254  if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
    255    return;
    256  }
    257  j++;
    258 
    259  psnr =
    260      I420PSNR(*orig_frame_->video_frame_buffer()->GetI420(), *res_i420_buffer);
    261  // TODO(leozwang) Investigate the right psnr should be set for I420ToRGB565,
    262  // Another example is I420ToRGB24, the psnr is 44
    263  // TODO(mikhal): Add psnr for RGB565, 1555, 4444, convert to ARGB.
    264  EXPECT_GT(ceil(psnr), 40);
    265 
    266  printf("\nConvert #%d I420 <-> ARGB8888\n", j);
    267  std::unique_ptr<uint8_t[]> out_argb8888_buffer(
    268      new uint8_t[width_ * height_ * 4]);
    269  EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kARGB, 0,
    270                               out_argb8888_buffer.get()));
    271 
    272  ret = libyuv::ConvertToI420(
    273      out_argb8888_buffer.get(), 0, res_i420_buffer->MutableDataY(),
    274      res_i420_buffer->StrideY(), res_i420_buffer->MutableDataU(),
    275      res_i420_buffer->StrideU(), res_i420_buffer->MutableDataV(),
    276      res_i420_buffer->StrideV(), 0, 0, width_, height_,
    277      res_i420_buffer->width(), res_i420_buffer->height(), libyuv::kRotate0,
    278      ConvertVideoType(VideoType::kARGB));
    279 
    280  EXPECT_EQ(0, ret);
    281 
    282  if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
    283    return;
    284  }
    285 
    286  psnr =
    287      I420PSNR(*orig_frame_->video_frame_buffer()->GetI420(), *res_i420_buffer);
    288  // TODO(leozwang) Investigate the right psnr should be set for
    289  // I420ToARGB8888,
    290  EXPECT_GT(ceil(psnr), 42);
    291 
    292  ASSERT_EQ(0, fclose(output_file));
    293 }
    294 
    295 TEST_F(TestLibYuv, ConvertAlignedFrame) {
    296  // Reading YUV frame - testing on the first frame of the foreman sequence
    297  std::string output_file_name =
    298      test::OutputPath() + "LibYuvTest_conversion.yuv";
    299  FILE* output_file = fopen(output_file_name.c_str(), "wb");
    300  ASSERT_TRUE(output_file != nullptr);
    301 
    302  double psnr = 0.0;
    303 
    304  int stride_y = 0;
    305  int stride_uv = 0;
    306  Calc16ByteAlignedStride(width_, &stride_y, &stride_uv);
    307 
    308  scoped_refptr<I420Buffer> res_i420_buffer =
    309      I420Buffer::Create(width_, height_, stride_y, stride_uv, stride_uv);
    310  std::unique_ptr<uint8_t[]> out_i420_buffer(new uint8_t[frame_length_]);
    311  EXPECT_EQ(0, ConvertFromI420(*orig_frame_, VideoType::kI420, 0,
    312                               out_i420_buffer.get()));
    313  int y_size = width_ * height_;
    314  int u_size = res_i420_buffer->ChromaWidth() * res_i420_buffer->ChromaHeight();
    315  int ret = libyuv::I420Copy(
    316      out_i420_buffer.get(), width_, out_i420_buffer.get() + y_size,
    317      width_ >> 1, out_i420_buffer.get() + y_size + u_size, width_ >> 1,
    318      res_i420_buffer->MutableDataY(), res_i420_buffer->StrideY(),
    319      res_i420_buffer->MutableDataU(), res_i420_buffer->StrideU(),
    320      res_i420_buffer->MutableDataV(), res_i420_buffer->StrideV(), width_,
    321      height_);
    322 
    323  EXPECT_EQ(0, ret);
    324 
    325  if (PrintVideoFrame(*res_i420_buffer, output_file) < 0) {
    326    return;
    327  }
    328  psnr =
    329      I420PSNR(*orig_frame_->video_frame_buffer()->GetI420(), *res_i420_buffer);
    330  EXPECT_EQ(48.0, psnr);
    331 }
    332 
    333 static uint8_t Average(int a, int b, int c, int d) {
    334  return (a + b + c + d + 2) / 4;
    335 }
    336 
    337 TEST_F(TestLibYuv, NV12Scale2x2to2x2) {
    338  const std::vector<uint8_t> src_y = {0, 1, 2, 3};
    339  const std::vector<uint8_t> src_uv = {0, 1};
    340  std::vector<uint8_t> dst_y(4);
    341  std::vector<uint8_t> dst_uv(2);
    342 
    343  uint8_t* tmp_buffer = nullptr;
    344 
    345  NV12Scale(tmp_buffer, src_y.data(), 2, src_uv.data(), 2, 2, 2, dst_y.data(),
    346            2, dst_uv.data(), 2, 2, 2);
    347 
    348  EXPECT_THAT(dst_y, ::testing::ContainerEq(src_y));
    349  EXPECT_THAT(dst_uv, ::testing::ContainerEq(src_uv));
    350 }
    351 
    352 TEST_F(TestLibYuv, NV12Scale4x4to2x2) {
    353  const uint8_t src_y[] = {0, 1, 2,  3,  4,  5,  6,  7,
    354                           8, 9, 10, 11, 12, 13, 14, 15};
    355  const uint8_t src_uv[] = {0, 1, 2, 3, 4, 5, 6, 7};
    356  std::vector<uint8_t> dst_y(4);
    357  std::vector<uint8_t> dst_uv(2);
    358 
    359  std::vector<uint8_t> tmp_buffer;
    360  const int src_chroma_width = (4 + 1) / 2;
    361  const int src_chroma_height = (4 + 1) / 2;
    362  const int dst_chroma_width = (2 + 1) / 2;
    363  const int dst_chroma_height = (2 + 1) / 2;
    364  tmp_buffer.resize(src_chroma_width * src_chroma_height * 2 +
    365                    dst_chroma_width * dst_chroma_height * 2);
    366  tmp_buffer.shrink_to_fit();
    367 
    368  NV12Scale(tmp_buffer.data(), src_y, 4, src_uv, 4, 4, 4, dst_y.data(), 2,
    369            dst_uv.data(), 2, 2, 2);
    370 
    371  EXPECT_THAT(dst_y, ::testing::ElementsAre(
    372                         Average(0, 1, 4, 5), Average(2, 3, 6, 7),
    373                         Average(8, 9, 12, 13), Average(10, 11, 14, 15)));
    374  EXPECT_THAT(dst_uv,
    375              ::testing::ElementsAre(Average(0, 2, 4, 6), Average(1, 3, 5, 7)));
    376 }
    377 
    378 TEST(I420WeightedPSNRTest, SmokeTest) {
    379  uint8_t ref_y[] = {0, 0, 0, 0};
    380  uint8_t ref_uv[] = {0};
    381  scoped_refptr<I420Buffer> ref_buffer =
    382      I420Buffer::Copy(/*width=*/2, /*height=*/2, ref_y, /*stride_y=*/2, ref_uv,
    383                       /*stride_u=*/1, ref_uv, /*stride_v=*/1);
    384 
    385  uint8_t test_y[] = {1, 1, 1, 1};
    386  uint8_t test_uv[] = {2};
    387  scoped_refptr<I420Buffer> test_buffer = I420Buffer::Copy(
    388      /*width=*/2, /*height=*/2, test_y, /*stride_y=*/2, test_uv,
    389      /*stride_u=*/1, test_uv, /*stride_v=*/1);
    390 
    391  auto psnr = [](double mse) { return 10.0 * log10(255.0 * 255.0 / mse); };
    392  EXPECT_NEAR(I420WeightedPSNR(*ref_buffer, *test_buffer),
    393              (6.0 * psnr(1.0) + psnr(4.0) + psnr(4.0)) / 8.0,
    394              /*abs_error=*/0.001);
    395 }
    396 
    397 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
    398 // Check that we catch int overflow if invalid dimensions get passed to
    399 // `I420Buffer::Create()`.
    400 TEST_F(TestLibYuv, I420DimensionsTooLarge) {
    401  // Dimensions large enough to cause overflow.
    402  constexpr int kWidth = 0xFFFF;
    403  constexpr int kHeight = 0xAAB0;
    404  // Sanity check for this test. This calculation, which is part of what
    405  // `I420Buffer::Create()` will do, should cause an `int` overflow.
    406  static_assert(
    407      (int64_t{kWidth} * int64_t{kHeight}) > std::numeric_limits<int>::max(),
    408      "");
    409 
    410  EXPECT_DEATH(I010Buffer::Create(kWidth, kHeight),
    411               "IsValueInRangeForNumericType");
    412  EXPECT_DEATH(I210Buffer::Create(kWidth, kHeight),
    413               "IsValueInRangeForNumericType");
    414 
    415  int stride_uv = (kWidth + 1) / 2;
    416  EXPECT_DEATH(I410Buffer::Create(kWidth, kHeight, /*stride_y=*/kWidth,
    417                                  stride_uv, stride_uv),
    418               "IsValueInRangeForNumericType");
    419  EXPECT_DEATH(I420Buffer::Create(kWidth, kHeight, /*stride_y=*/kWidth,
    420                                  stride_uv, stride_uv),
    421               "IsValueInRangeForNumericType");
    422  EXPECT_DEATH(I422Buffer::Create(kWidth, kHeight, /*stride_y=*/kWidth,
    423                                  stride_uv, stride_uv),
    424               "IsValueInRangeForNumericType");
    425  EXPECT_DEATH(I444Buffer::Create(kWidth, kHeight, /*stride_y=*/kWidth,
    426                                  stride_uv, stride_uv),
    427               "IsValueInRangeForNumericType");
    428  EXPECT_DEATH(
    429      NV12Buffer::Create(kWidth, kHeight, /*stride_y=*/kWidth, stride_uv),
    430      "IsValueInRangeForNumericType");
    431 }
    432 
    433 template <typename T>
    434 void TestInvalidDimensions5Params() {
    435  EXPECT_DEATH(T::Create(-11, 1, /*stride_y=*/1,
    436                         /*stride_u=*/1,
    437                         /*stride_v=*/1),
    438               "> 0");
    439  EXPECT_DEATH(T::Create(1, -11, /*stride_y=*/1,
    440                         /*stride_u=*/1,
    441                         /*stride_v=*/1),
    442               "> 0");
    443  EXPECT_DEATH(T::Create(1, 1, /*stride_y=*/-12,
    444                         /*stride_u=*/1,
    445                         /*stride_v=*/1),
    446               ">= width");
    447  EXPECT_DEATH(T::Create(1, 1, /*stride_y=*/1,
    448                         /*stride_u=*/-12,
    449                         /*stride_v=*/1),
    450               "> 0");
    451  EXPECT_DEATH(T::Create(1, 1, /*stride_y=*/1,
    452                         /*stride_u=*/1,
    453                         /*stride_v=*/-12),
    454               "> 0");
    455 }
    456 
    457 template <typename T>
    458 void TestInvalidDimensions4Params() {
    459  EXPECT_DEATH(T::Create(-11, 1, /*stride_y=*/1,
    460                         /*stride_uv=*/1),
    461               "> 0");
    462  EXPECT_DEATH(T::Create(1, -11, /*stride_y=*/1,
    463                         /*stride_uv=*/1),
    464               "> 0");
    465  EXPECT_DEATH(T::Create(1, 1, /*stride_y=*/-12,
    466                         /*stride_uv=*/1),
    467               ">= width");
    468  EXPECT_DEATH(T::Create(1, 1, /*stride_y=*/1,
    469                         /*stride_uv=*/-12),
    470               "> 0");
    471 }
    472 
    473 template <typename T>
    474 void TestInvalidDimensions2Param() {
    475  EXPECT_DEATH(T::Create(-11, 1), "> 0");
    476  EXPECT_DEATH(T::Create(1, -11), "> 0");
    477 }
    478 
    479 TEST_F(TestLibYuv, I420InvalidDimensions) {
    480  // Only width and height provided to `Create()`.
    481  TestInvalidDimensions2Param<I010Buffer>();
    482  TestInvalidDimensions2Param<I210Buffer>();
    483  // `Create() is provided with width, height, y, u, v.
    484  TestInvalidDimensions5Params<I410Buffer>();
    485  TestInvalidDimensions5Params<I420Buffer>();
    486  TestInvalidDimensions5Params<I422Buffer>();
    487  TestInvalidDimensions5Params<I444Buffer>();
    488  // `Create() is provided with width, height, y, u_and_v.
    489  TestInvalidDimensions4Params<NV12Buffer>();
    490 }
    491 
    492 #endif  // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
    493 
    494 }  // namespace webrtc