Home | History | Annotate | Download | only in enc
      1 /* Copyright 2016 Google Inc. All Rights Reserved.
      2 
      3    Distributed under MIT license.
      4    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
      5 */
      6 
      7 /* Constants and formulas that affect speed-ratio trade-offs and thus define
      8    quality levels. */
      9 
     10 #ifndef BROTLI_ENC_QUALITY_H_
     11 #define BROTLI_ENC_QUALITY_H_
     12 
     13 #include <brotli/encode.h>
     14 
     15 #define FAST_ONE_PASS_COMPRESSION_QUALITY 0
     16 #define FAST_TWO_PASS_COMPRESSION_QUALITY 1
     17 #define ZOPFLIFICATION_QUALITY 10
     18 #define HQ_ZOPFLIFICATION_QUALITY 11
     19 
     20 #define MAX_QUALITY_FOR_STATIC_ENTROPY_CODES 2
     21 #define MIN_QUALITY_FOR_BLOCK_SPLIT 4
     22 #define MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS 4
     23 #define MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH 5
     24 #define MIN_QUALITY_FOR_CONTEXT_MODELING 5
     25 #define MIN_QUALITY_FOR_HQ_CONTEXT_MODELING 7
     26 #define MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING 10
     27 /* Only for "font" mode. */
     28 #define MIN_QUALITY_FOR_RECOMPUTE_DISTANCE_PREFIXES 10
     29 
     30 /* For quality below MIN_QUALITY_FOR_BLOCK_SPLIT there is no block splitting,
     31    so we buffer at most this much literals and commands. */
     32 #define MAX_NUM_DELAYED_SYMBOLS 0x2fff
     33 
     34 typedef struct BrotliHasherParams {
     35   int type;
     36   int bucket_bits;
     37   int block_bits;
     38   int hash_len;
     39   int num_last_distances_to_check;
     40 } BrotliHasherParams;
     41 
     42 /* Encoding parameters */
     43 typedef struct BrotliEncoderParams {
     44   BrotliEncoderMode mode;
     45   int quality;
     46   int lgwin;
     47   int lgblock;
     48   size_t size_hint;
     49   BROTLI_BOOL disable_literal_context_modeling;
     50   BrotliHasherParams hasher;
     51 } BrotliEncoderParams;
     52 
     53 /* Returns hash-table size for quality levels 0 and 1. */
     54 static BROTLI_INLINE size_t MaxHashTableSize(int quality) {
     55   return quality == FAST_ONE_PASS_COMPRESSION_QUALITY ? 1 << 15 : 1 << 17;
     56 }
     57 
     58 /* The maximum length for which the zopflification uses distinct distances. */
     59 #define MAX_ZOPFLI_LEN_QUALITY_10 150
     60 #define MAX_ZOPFLI_LEN_QUALITY_11 325
     61 
     62 /* Do not thoroughly search when a long copy is found. */
     63 #define BROTLI_LONG_COPY_QUICK_STEP 16384
     64 
     65 static BROTLI_INLINE size_t MaxZopfliLen(const BrotliEncoderParams* params) {
     66   return params->quality <= 10 ?
     67       MAX_ZOPFLI_LEN_QUALITY_10 :
     68       MAX_ZOPFLI_LEN_QUALITY_11;
     69 }
     70 
     71 /* Number of best candidates to evaluate to expand Zopfli chain. */
     72 static BROTLI_INLINE size_t MaxZopfliCandidates(
     73   const BrotliEncoderParams* params) {
     74   return params->quality <= 10 ? 1 : 5;
     75 }
     76 
     77 static BROTLI_INLINE void SanitizeParams(BrotliEncoderParams* params) {
     78   params->quality = BROTLI_MIN(int, BROTLI_MAX_QUALITY,
     79       BROTLI_MAX(int, BROTLI_MIN_QUALITY, params->quality));
     80   if (params->lgwin < BROTLI_MIN_WINDOW_BITS) {
     81     params->lgwin = BROTLI_MIN_WINDOW_BITS;
     82   } else if (params->lgwin > BROTLI_MAX_WINDOW_BITS) {
     83     params->lgwin = BROTLI_MAX_WINDOW_BITS;
     84   }
     85 }
     86 
     87 /* Returns optimized lg_block value. */
     88 static BROTLI_INLINE int ComputeLgBlock(const BrotliEncoderParams* params) {
     89   int lgblock = params->lgblock;
     90   if (params->quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||
     91       params->quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {
     92     lgblock = params->lgwin;
     93   } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {
     94     lgblock = 14;
     95   } else if (lgblock == 0) {
     96     lgblock = 16;
     97     if (params->quality >= 9 && params->lgwin > lgblock) {
     98       lgblock = BROTLI_MIN(int, 18, params->lgwin);
     99     }
    100   } else {
    101     lgblock = BROTLI_MIN(int, BROTLI_MAX_INPUT_BLOCK_BITS,
    102         BROTLI_MAX(int, BROTLI_MIN_INPUT_BLOCK_BITS, lgblock));
    103   }
    104   return lgblock;
    105 }
    106 
    107 /* Returns log2 of the size of main ring buffer area.
    108    Allocate at least lgwin + 1 bits for the ring buffer so that the newly
    109    added block fits there completely and we still get lgwin bits and at least
    110    read_block_size_bits + 1 bits because the copy tail length needs to be
    111    smaller than ring-buffer size. */
    112 static BROTLI_INLINE int ComputeRbBits(const BrotliEncoderParams* params) {
    113   return 1 + BROTLI_MAX(int, params->lgwin, params->lgblock);
    114 }
    115 
    116 static BROTLI_INLINE size_t MaxMetablockSize(
    117     const BrotliEncoderParams* params) {
    118   int bits =
    119       BROTLI_MIN(int, ComputeRbBits(params), BROTLI_MAX_INPUT_BLOCK_BITS);
    120   return (size_t)1 << bits;
    121 }
    122 
    123 /* When searching for backward references and have not seen matches for a long
    124    time, we can skip some match lookups. Unsuccessful match lookups are very
    125    expensive and this kind of a heuristic speeds up compression quite a lot.
    126    At first 8 byte strides are taken and every second byte is put to hasher.
    127    After 4x more literals stride by 16 bytes, every put 4-th byte to hasher.
    128    Applied only to qualities 2 to 9. */
    129 static BROTLI_INLINE size_t LiteralSpreeLengthForSparseSearch(
    130     const BrotliEncoderParams* params) {
    131   return params->quality < 9 ? 64 : 512;
    132 }
    133 
    134 static BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params,
    135                                        BrotliHasherParams* hparams) {
    136   if (params->quality > 9) {
    137     hparams->type = 10;
    138   } else if (params->quality == 4 && params->size_hint >= (1 << 20)) {
    139     hparams->type = 54;
    140   } else if (params->quality < 5) {
    141     hparams->type = params->quality;
    142   } else if (params->lgwin <= 16) {
    143     hparams->type = params->quality < 7 ? 40 : params->quality < 9 ? 41 : 42;
    144   } else if (params->size_hint >= (1 << 20) && params->lgwin >= 19) {
    145     hparams->type = 6;
    146     hparams->block_bits = params->quality - 1;
    147     hparams->bucket_bits = 15;
    148     hparams->hash_len = 5;
    149     hparams->num_last_distances_to_check =
    150         params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16;
    151   } else {
    152     hparams->type = 5;
    153     hparams->block_bits = params->quality - 1;
    154     hparams->bucket_bits = params->quality < 7 ? 14 : 15;
    155     hparams->num_last_distances_to_check =
    156         params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16;
    157   }
    158 }
    159 
    160 #endif  /* BROTLI_ENC_QUALITY_H_ */
    161