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