enc_progressive_split.h (4650B)
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 #ifndef LIB_JXL_PROGRESSIVE_SPLIT_H_ 7 #define LIB_JXL_PROGRESSIVE_SPLIT_H_ 8 9 #include <stddef.h> 10 #include <stdint.h> 11 12 #include <limits> 13 #include <memory> 14 #include <vector> 15 16 #include "lib/jxl/ac_strategy.h" 17 #include "lib/jxl/base/compiler_specific.h" 18 #include "lib/jxl/base/status.h" 19 #include "lib/jxl/chroma_from_luma.h" 20 #include "lib/jxl/common.h" // kMaxNumPasses 21 #include "lib/jxl/dct_util.h" 22 #include "lib/jxl/frame_header.h" 23 #include "lib/jxl/image.h" 24 #include "lib/jxl/image_ops.h" 25 #include "lib/jxl/splines.h" 26 27 // Functions to split DCT coefficients in multiple passes. All the passes of a 28 // single frame are added together. 29 30 namespace jxl { 31 32 constexpr size_t kNoDownsamplingFactor = std::numeric_limits<size_t>::max(); 33 34 struct PassDefinition { 35 // Side of the square of the coefficients that should be kept in each 8x8 36 // block. Must be greater than 1, and at most 8. Should be in non-decreasing 37 // order. 38 size_t num_coefficients; 39 40 // How much to shift the encoded values by, with rounding. 41 size_t shift; 42 43 // If specified, this indicates that if the requested downsampling factor is 44 // sufficiently high, then it is fine to stop decoding after this pass. 45 // By default, passes are not marked as being suitable for any downsampling. 46 size_t suitable_for_downsampling_of_at_least; 47 }; 48 49 struct ProgressiveMode { 50 size_t num_passes = 1; 51 PassDefinition passes[kMaxNumPasses] = { 52 PassDefinition{/*num_coefficients=*/8, /*shift=*/0, 53 /*suitable_for_downsampling_of_at_least=*/1}}; 54 55 ProgressiveMode() = default; 56 57 template <size_t nump> 58 explicit ProgressiveMode(const PassDefinition (&p)[nump]) { 59 JXL_ASSERT(nump <= kMaxNumPasses); 60 num_passes = nump; 61 PassDefinition previous_pass{ 62 /*num_coefficients=*/1, /*shift=*/0, 63 /*suitable_for_downsampling_of_at_least=*/kNoDownsamplingFactor}; 64 size_t last_downsampling_factor = kNoDownsamplingFactor; 65 for (size_t i = 0; i < nump; i++) { 66 JXL_ASSERT(p[i].num_coefficients > previous_pass.num_coefficients || 67 (p[i].num_coefficients == previous_pass.num_coefficients && 68 p[i].shift < previous_pass.shift)); 69 JXL_ASSERT(p[i].suitable_for_downsampling_of_at_least == 70 kNoDownsamplingFactor || 71 p[i].suitable_for_downsampling_of_at_least <= 72 last_downsampling_factor); 73 // Only used inside assert. 74 (void)last_downsampling_factor; 75 if (p[i].suitable_for_downsampling_of_at_least != kNoDownsamplingFactor) { 76 last_downsampling_factor = p[i].suitable_for_downsampling_of_at_least; 77 } 78 previous_pass = passes[i] = p[i]; 79 } 80 } 81 }; 82 83 class ProgressiveSplitter { 84 public: 85 void SetProgressiveMode(ProgressiveMode mode) { mode_ = mode; } 86 87 size_t GetNumPasses() const { return mode_.num_passes; } 88 89 void InitPasses(Passes* JXL_RESTRICT passes) const { 90 passes->num_passes = static_cast<uint32_t>(GetNumPasses()); 91 passes->num_downsample = 0; 92 JXL_ASSERT(passes->num_passes != 0); 93 passes->shift[passes->num_passes - 1] = 0; 94 if (passes->num_passes == 1) return; // Done, arrays are empty 95 96 for (uint32_t i = 0; i < mode_.num_passes - 1; ++i) { 97 const size_t min_downsampling_factor = 98 mode_.passes[i].suitable_for_downsampling_of_at_least; 99 passes->shift[i] = mode_.passes[i].shift; 100 if (1 < min_downsampling_factor && 101 min_downsampling_factor != kNoDownsamplingFactor) { 102 passes->downsample[passes->num_downsample] = min_downsampling_factor; 103 passes->last_pass[passes->num_downsample] = i; 104 if (mode_.passes[i + 1].suitable_for_downsampling_of_at_least < 105 min_downsampling_factor) { 106 passes->num_downsample += 1; 107 } 108 } 109 } 110 } 111 112 template <typename T> 113 void SplitACCoefficients(const T* JXL_RESTRICT block, const AcStrategy& acs, 114 size_t bx, size_t by, 115 T* JXL_RESTRICT output[kMaxNumPasses]); 116 117 private: 118 ProgressiveMode mode_; 119 }; 120 121 extern template void ProgressiveSplitter::SplitACCoefficients<int32_t>( 122 const int32_t* JXL_RESTRICT, const AcStrategy&, size_t, size_t, 123 int32_t* JXL_RESTRICT[kMaxNumPasses]); 124 125 extern template void ProgressiveSplitter::SplitACCoefficients<int16_t>( 126 const int16_t* JXL_RESTRICT, const AcStrategy&, size_t, size_t, 127 int16_t* JXL_RESTRICT[kMaxNumPasses]); 128 129 } // namespace jxl 130 131 #endif // LIB_JXL_PROGRESSIVE_SPLIT_H_