tor-browser

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

passes_test.cc (15466B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #include <jxl/cms.h>
      7 #include <jxl/memory_manager.h>
      8 #include <jxl/types.h>
      9 
     10 #include <cstddef>
     11 #include <cstdint>
     12 #include <future>
     13 #include <string>
     14 #include <utility>
     15 #include <vector>
     16 
     17 #include "lib/extras/codec.h"
     18 #include "lib/extras/dec/jxl.h"
     19 #include "lib/jxl/base/data_parallel.h"
     20 #include "lib/jxl/base/override.h"
     21 #include "lib/jxl/base/rect.h"
     22 #include "lib/jxl/base/span.h"
     23 #include "lib/jxl/base/status.h"
     24 #include "lib/jxl/common.h"
     25 #include "lib/jxl/enc_params.h"
     26 #include "lib/jxl/image.h"
     27 #include "lib/jxl/image_bundle.h"
     28 #include "lib/jxl/image_ops.h"
     29 #include "lib/jxl/test_memory_manager.h"
     30 #include "lib/jxl/test_utils.h"
     31 #include "lib/jxl/testing.h"
     32 
     33 namespace jxl {
     34 
     35 using ::jxl::test::ButteraugliDistance;
     36 using ::jxl::test::ReadTestData;
     37 using ::jxl::test::Roundtrip;
     38 using ::jxl::test::ThreadPoolForTests;
     39 
     40 namespace {
     41 
     42 TEST(PassesTest, RoundtripSmallPasses) {
     43  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
     44  const std::vector<uint8_t> orig =
     45      ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png");
     46  CodecInOut io{memory_manager};
     47  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io));
     48  ASSERT_TRUE(io.ShrinkTo(io.xsize() / 8, io.ysize() / 8));
     49 
     50  CompressParams cparams;
     51  cparams.butteraugli_distance = 1.0;
     52  cparams.progressive_mode = Override::kOn;
     53  cparams.SetCms(*JxlGetDefaultCms());
     54 
     55  CodecInOut io2{memory_manager};
     56  JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _));
     57  EXPECT_SLIGHTLY_BELOW(
     58      ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
     59                          *JxlGetDefaultCms(),
     60                          /*distmap=*/nullptr),
     61      1.0);
     62 }
     63 
     64 TEST(PassesTest, RoundtripUnalignedPasses) {
     65  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
     66  const std::vector<uint8_t> orig =
     67      ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png");
     68  CodecInOut io{memory_manager};
     69  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io));
     70  ASSERT_TRUE(io.ShrinkTo(io.xsize() / 12, io.ysize() / 7));
     71 
     72  CompressParams cparams;
     73  cparams.butteraugli_distance = 2.0;
     74  cparams.progressive_mode = Override::kOn;
     75  cparams.SetCms(*JxlGetDefaultCms());
     76 
     77  CodecInOut io2{memory_manager};
     78  JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _));
     79  EXPECT_SLIGHTLY_BELOW(
     80      ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
     81                          *JxlGetDefaultCms(),
     82                          /*distmap=*/nullptr),
     83      1.72);
     84 }
     85 
     86 TEST(PassesTest, RoundtripMultiGroupPasses) {
     87  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
     88  const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
     89  CodecInOut io{memory_manager};
     90  {
     91    ThreadPoolForTests pool(4);
     92    ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
     93  }
     94  ASSERT_TRUE(io.ShrinkTo(600, 1024));  // partial X, full Y group
     95 
     96  auto test = [&](float target_distance, float threshold) {
     97    ThreadPoolForTests pool(4);
     98    CompressParams cparams;
     99    cparams.butteraugli_distance = target_distance;
    100    cparams.progressive_mode = Override::kOn;
    101    cparams.SetCms(*JxlGetDefaultCms());
    102    CodecInOut io2{memory_manager};
    103    JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _,
    104                            /* compressed_size */ nullptr, pool.get()));
    105    EXPECT_SLIGHTLY_BELOW(
    106        ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
    107                            *JxlGetDefaultCms(),
    108                            /*distmap=*/nullptr, pool.get()),
    109        target_distance + threshold);
    110  };
    111 
    112  auto run1 = std::async(std::launch::async, test, 1.0f, 0.25f);
    113  auto run2 = std::async(std::launch::async, test, 2.0f, 0.0f);
    114 }
    115 
    116 TEST(PassesTest, RoundtripLargeFastPasses) {
    117  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
    118  ThreadPoolForTests pool(8);
    119  const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
    120  CodecInOut io{memory_manager};
    121  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
    122 
    123  CompressParams cparams;
    124  cparams.speed_tier = SpeedTier::kSquirrel;
    125  cparams.progressive_mode = Override::kOn;
    126  cparams.SetCms(*JxlGetDefaultCms());
    127 
    128  CodecInOut io2{memory_manager};
    129  JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _,
    130                          /* compressed_size */ nullptr, pool.get()));
    131 }
    132 
    133 // Checks for differing size/distance in two consecutive runs of distance 2,
    134 // which involves additional processing including adaptive reconstruction.
    135 // Failing this may be a sign of race conditions or invalid memory accesses.
    136 TEST(PassesTest, RoundtripProgressiveConsistent) {
    137  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
    138  ThreadPoolForTests pool(8);
    139  const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
    140  CodecInOut io{memory_manager};
    141  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
    142 
    143  CompressParams cparams;
    144  cparams.speed_tier = SpeedTier::kSquirrel;
    145  cparams.progressive_mode = Override::kOn;
    146  cparams.butteraugli_distance = 2.0;
    147  cparams.SetCms(*JxlGetDefaultCms());
    148 
    149  // Try each xsize mod kBlockDim to verify right border handling.
    150  for (size_t xsize = 48; xsize > 40; --xsize) {
    151    ASSERT_TRUE(io.ShrinkTo(xsize, 15));
    152 
    153    CodecInOut io2{memory_manager};
    154    size_t size2;
    155    JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _, &size2, pool.get()));
    156 
    157    CodecInOut io3{memory_manager};
    158    size_t size3;
    159    JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io3, _, &size3, pool.get()));
    160 
    161    // Exact same compressed size.
    162    EXPECT_EQ(size2, size3);
    163 
    164    // Exact same distance.
    165    const float dist2 = ButteraugliDistance(
    166        io.frames, io2.frames, ButteraugliParams(), *JxlGetDefaultCms(),
    167        /*distmap=*/nullptr, pool.get());
    168    const float dist3 = ButteraugliDistance(
    169        io.frames, io3.frames, ButteraugliParams(), *JxlGetDefaultCms(),
    170        /*distmap=*/nullptr, pool.get());
    171    EXPECT_EQ(dist2, dist3);
    172  }
    173 }
    174 
    175 TEST(PassesTest, AllDownsampleFeasible) {
    176  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
    177  ThreadPoolForTests pool(8);
    178  const std::vector<uint8_t> orig =
    179      ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png");
    180  CodecInOut io{memory_manager};
    181  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
    182 
    183  std::vector<uint8_t> compressed;
    184 
    185  CompressParams cparams;
    186  cparams.speed_tier = SpeedTier::kSquirrel;
    187  cparams.progressive_mode = Override::kOn;
    188  cparams.butteraugli_distance = 1.0;
    189  ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
    190 
    191  EXPECT_LE(compressed.size(), 240000u);
    192  float target_butteraugli[9] = {};
    193  target_butteraugli[1] = 2.5f;
    194  target_butteraugli[2] = 16.0f;
    195  target_butteraugli[4] = 20.0f;
    196  target_butteraugli[8] = 80.0f;
    197 
    198  // The default progressive encoding scheme should make all these downsampling
    199  // factors achievable.
    200  // TODO(veluca): re-enable downsampling 16.
    201  std::vector<size_t> downsamplings = {1, 2, 4, 8};  //, 16};
    202 
    203  auto check = [&](const uint32_t task, size_t /* thread */) -> Status {
    204    const size_t downsampling = downsamplings[task];
    205    extras::JXLDecompressParams dparams;
    206    dparams.max_downsampling = downsampling;
    207    CodecInOut output{memory_manager};
    208    JXL_RETURN_IF_ERROR(test::DecodeFile(dparams, Bytes(compressed), &output));
    209    EXPECT_EQ(output.xsize(), io.xsize()) << "downsampling = " << downsampling;
    210    EXPECT_EQ(output.ysize(), io.ysize()) << "downsampling = " << downsampling;
    211    EXPECT_LE(ButteraugliDistance(io.frames, output.frames, ButteraugliParams(),
    212                                  *JxlGetDefaultCms(),
    213                                  /*distmap=*/nullptr, nullptr),
    214              target_butteraugli[downsampling])
    215        << "downsampling: " << downsampling;
    216    return true;
    217  };
    218  EXPECT_TRUE(RunOnPool(pool.get(), 0, downsamplings.size(), ThreadPool::NoInit,
    219                        check, "TestDownsampling"));
    220 }
    221 
    222 TEST(PassesTest, AllDownsampleFeasibleQProgressive) {
    223  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
    224  ThreadPoolForTests pool(8);
    225  const std::vector<uint8_t> orig =
    226      ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png");
    227  CodecInOut io{memory_manager};
    228  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
    229 
    230  std::vector<uint8_t> compressed;
    231 
    232  CompressParams cparams;
    233  cparams.speed_tier = SpeedTier::kSquirrel;
    234  cparams.qprogressive_mode = Override::kOn;
    235  cparams.butteraugli_distance = 1.0;
    236  ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
    237 
    238  EXPECT_LE(compressed.size(), 220000u);
    239 
    240  float target_butteraugli[9] = {};
    241  target_butteraugli[1] = 3.0f;
    242  target_butteraugli[2] = 6.0f;
    243  target_butteraugli[4] = 10.0f;
    244  target_butteraugli[8] = 80.0f;
    245 
    246  // The default progressive encoding scheme should make all these downsampling
    247  // factors achievable.
    248  std::vector<size_t> downsamplings = {1, 2, 4, 8};
    249 
    250  auto check = [&](const uint32_t task, size_t /* thread */) -> Status {
    251    const size_t downsampling = downsamplings[task];
    252    extras::JXLDecompressParams dparams;
    253    dparams.max_downsampling = downsampling;
    254    CodecInOut output{memory_manager};
    255    JXL_RETURN_IF_ERROR(test::DecodeFile(dparams, Bytes(compressed), &output));
    256    EXPECT_EQ(output.xsize(), io.xsize()) << "downsampling = " << downsampling;
    257    EXPECT_EQ(output.ysize(), io.ysize()) << "downsampling = " << downsampling;
    258    EXPECT_LE(ButteraugliDistance(io.frames, output.frames, ButteraugliParams(),
    259                                  *JxlGetDefaultCms(),
    260                                  /*distmap=*/nullptr),
    261              target_butteraugli[downsampling])
    262        << "downsampling: " << downsampling;
    263    return true;
    264  };
    265  EXPECT_TRUE(RunOnPool(pool.get(), 0, downsamplings.size(), ThreadPool::NoInit,
    266                        check, "TestQProgressive"));
    267 }
    268 
    269 TEST(PassesTest, ProgressiveDownsample2DegradesCorrectlyGrayscale) {
    270  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
    271  ThreadPoolForTests pool(8);
    272  const std::vector<uint8_t> orig = ReadTestData(
    273      "external/wesaturate/500px/cvo9xd_keong_macan_grayscale.png");
    274  CodecInOut io_orig{memory_manager};
    275  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, pool.get()));
    276  Rect rect(0, 0, io_orig.xsize(), 128);
    277  // need 2 DC groups for the DC frame to actually be progressive.
    278  JXL_TEST_ASSIGN_OR_DIE(Image3F large,
    279                         Image3F::Create(memory_manager, 4242, rect.ysize()));
    280  ZeroFillImage(&large);
    281  ASSERT_TRUE(CopyImageTo(rect, *io_orig.Main().color(), rect, &large));
    282  CodecInOut io{memory_manager};
    283  io.metadata = io_orig.metadata;
    284  ASSERT_TRUE(io.SetFromImage(std::move(large), io_orig.Main().c_current()));
    285 
    286  std::vector<uint8_t> compressed;
    287 
    288  CompressParams cparams;
    289  cparams.speed_tier = SpeedTier::kSquirrel;
    290  cparams.progressive_dc = 1;
    291  cparams.responsive = JXL_TRUE;
    292  cparams.qprogressive_mode = Override::kOn;
    293  cparams.butteraugli_distance = 1.0;
    294  ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
    295 
    296  EXPECT_LE(compressed.size(), 10000u);
    297 
    298  extras::JXLDecompressParams dparams;
    299  dparams.max_downsampling = 1;
    300  CodecInOut output{memory_manager};
    301  ASSERT_TRUE(test::DecodeFile(dparams, Bytes(compressed), &output));
    302 
    303  dparams.max_downsampling = 2;
    304  CodecInOut output_d2{memory_manager};
    305  ASSERT_TRUE(test::DecodeFile(dparams, Bytes(compressed), &output_d2));
    306 
    307  // 0 if reading all the passes, ~15 if skipping the 8x pass.
    308  float butteraugli_distance_down2_full = ButteraugliDistance(
    309      output.frames, output_d2.frames, ButteraugliParams(), *JxlGetDefaultCms(),
    310      /*distmap=*/nullptr);
    311 
    312  EXPECT_LE(butteraugli_distance_down2_full, 3.2f);
    313  EXPECT_GE(butteraugli_distance_down2_full, 1.0f);
    314 }
    315 
    316 TEST(PassesTest, ProgressiveDownsample2DegradesCorrectly) {
    317  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
    318  ThreadPoolForTests pool(8);
    319  const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
    320  CodecInOut io_orig{memory_manager};
    321  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, pool.get()));
    322  Rect rect(0, 0, io_orig.xsize(), 128);
    323  // need 2 DC groups for the DC frame to actually be progressive.
    324  JXL_TEST_ASSIGN_OR_DIE(Image3F large,
    325                         Image3F::Create(memory_manager, 4242, rect.ysize()));
    326  ZeroFillImage(&large);
    327  ASSERT_TRUE(CopyImageTo(rect, *io_orig.Main().color(), rect, &large));
    328  CodecInOut io{memory_manager};
    329  ASSERT_TRUE(io.SetFromImage(std::move(large), io_orig.Main().c_current()));
    330 
    331  std::vector<uint8_t> compressed;
    332 
    333  CompressParams cparams;
    334  cparams.speed_tier = SpeedTier::kSquirrel;
    335  cparams.progressive_dc = 1;
    336  cparams.responsive = JXL_TRUE;
    337  cparams.qprogressive_mode = Override::kOn;
    338  cparams.butteraugli_distance = 1.0;
    339  ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
    340 
    341  EXPECT_LE(compressed.size(), 220000u);
    342 
    343  extras::JXLDecompressParams dparams;
    344  dparams.max_downsampling = 1;
    345  CodecInOut output{memory_manager};
    346  ASSERT_TRUE(test::DecodeFile(dparams, Bytes(compressed), &output));
    347 
    348  dparams.max_downsampling = 2;
    349  CodecInOut output_d2{memory_manager};
    350  ASSERT_TRUE(test::DecodeFile(dparams, Bytes(compressed), &output_d2));
    351 
    352  // 0 if reading all the passes, ~15 if skipping the 8x pass.
    353  float butteraugli_distance_down2_full = ButteraugliDistance(
    354      output.frames, output_d2.frames, ButteraugliParams(), *JxlGetDefaultCms(),
    355      /*distmap=*/nullptr);
    356 
    357  EXPECT_LE(butteraugli_distance_down2_full, 3.0f);
    358  EXPECT_GE(butteraugli_distance_down2_full, 1.0f);
    359 }
    360 
    361 TEST(PassesTest, NonProgressiveDCImage) {
    362  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
    363  ThreadPoolForTests pool(8);
    364  const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
    365  CodecInOut io{memory_manager};
    366  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
    367 
    368  std::vector<uint8_t> compressed;
    369 
    370  CompressParams cparams;
    371  cparams.speed_tier = SpeedTier::kSquirrel;
    372  cparams.progressive_mode = Override::kOff;
    373  cparams.butteraugli_distance = 2.0;
    374  ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
    375 
    376  // Even in non-progressive mode, it should be possible to return a DC-only
    377  // image.
    378  extras::JXLDecompressParams dparams;
    379  dparams.max_downsampling = 100;
    380  CodecInOut output{memory_manager};
    381  ASSERT_TRUE(
    382      test::DecodeFile(dparams, Bytes(compressed), &output, pool.get()));
    383  EXPECT_EQ(output.xsize(), io.xsize());
    384  EXPECT_EQ(output.ysize(), io.ysize());
    385 }
    386 
    387 TEST(PassesTest, RoundtripSmallNoGaborishPasses) {
    388  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
    389  const std::vector<uint8_t> orig =
    390      ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png");
    391  CodecInOut io{memory_manager};
    392  ASSERT_TRUE(SetFromBytes(Bytes(orig), &io));
    393  ASSERT_TRUE(io.ShrinkTo(io.xsize() / 8, io.ysize() / 8));
    394 
    395  CompressParams cparams;
    396  cparams.gaborish = Override::kOff;
    397  cparams.butteraugli_distance = 1.0;
    398  cparams.progressive_mode = Override::kOn;
    399  cparams.SetCms(*JxlGetDefaultCms());
    400 
    401  CodecInOut io2{memory_manager};
    402  JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _));
    403  EXPECT_SLIGHTLY_BELOW(
    404      ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
    405                          *JxlGetDefaultCms(),
    406                          /*distmap=*/nullptr),
    407      1.0);
    408 }
    409 
    410 }  // namespace
    411 }  // namespace jxl