1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2012 Google Inc. All Rights Reserved.
2a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//
30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license
40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source
50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found
60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may
70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree.
8a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
9a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//
10a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Author: Jyrki Alakuijala (jyrki@google.com)
11a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//
12a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
13a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifndef WEBP_ENC_BACKWARD_REFERENCES_H_
14a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define WEBP_ENC_BACKWARD_REFERENCES_H_
15a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
16a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include <assert.h>
17a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include <stdlib.h>
18e8a1b86cc3afe4791ab40d89240c40797a400131James Zern#include "../webp/types.h"
19e8a1b86cc3afe4791ab40d89240c40797a400131James Zern#include "../webp/format_constants.h"
20a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
218b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#ifdef __cplusplus
22a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraextern "C" {
23a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif
24a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
257c8da7ce66017295a65ec028084b90800be377f8James Zern// The maximum allowed limit is 11.
267c8da7ce66017295a65ec028084b90800be377f8James Zern#define MAX_COLOR_CACHE_BITS 10
27a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
28a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
29a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// PixOrCopy
30a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
31a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraenum Mode {
32a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  kLiteral,
33a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  kCacheIdx,
34a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  kCopy,
35a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  kNone
36a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora};
37a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
38a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroratypedef struct {
39a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  // mode as uint8_t to make the memory layout to be exactly 8 bytes.
40a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint8_t mode;
41a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint16_t len;
42a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint32_t argb_or_distance;
43a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} PixOrCopy;
44a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
45a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance,
46a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                                 uint16_t len) {
47a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  PixOrCopy retval;
48a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  retval.mode = kCopy;
49a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  retval.argb_or_distance = distance;
50a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  retval.len = len;
51a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return retval;
52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
54a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE PixOrCopy PixOrCopyCreateCacheIdx(int idx) {
55a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  PixOrCopy retval;
56a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(idx >= 0);
57a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(idx < (1 << MAX_COLOR_CACHE_BITS));
58a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  retval.mode = kCacheIdx;
59a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  retval.argb_or_distance = idx;
60a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  retval.len = 1;
61a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return retval;
62a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
63a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
64a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE PixOrCopy PixOrCopyCreateLiteral(uint32_t argb) {
65a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  PixOrCopy retval;
66a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  retval.mode = kLiteral;
67a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  retval.argb_or_distance = argb;
68a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  retval.len = 1;
69a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return retval;
70a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
71a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
72a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int PixOrCopyIsLiteral(const PixOrCopy* const p) {
73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (p->mode == kLiteral);
74a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
75a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
76a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int PixOrCopyIsCacheIdx(const PixOrCopy* const p) {
77a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (p->mode == kCacheIdx);
78a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
79a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
80a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int PixOrCopyIsCopy(const PixOrCopy* const p) {
81a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (p->mode == kCopy);
82a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
83a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
84a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t PixOrCopyLiteral(const PixOrCopy* const p,
85a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                             int component) {
86a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(p->mode == kLiteral);
87a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (p->argb_or_distance >> (component * 8)) & 0xff;
88a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
89a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
90a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) {
91a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return p->len;
92a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
93a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
94a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t PixOrCopyArgb(const PixOrCopy* const p) {
95a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(p->mode == kLiteral);
96a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return p->argb_or_distance;
97a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
98a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
99a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) {
100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(p->mode == kCacheIdx);
101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS));
102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return p->argb_or_distance;
103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
104a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) {
106a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  assert(p->mode == kCopy);
107a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return p->argb_or_distance;
108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
11133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// VP8LHashChain
11233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
11333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define HASH_BITS 18
11433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define HASH_SIZE (1 << HASH_BITS)
11533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
11633f74dabbc7920a65ed435d7417987589febdc16Vikas Aroratypedef struct VP8LHashChain VP8LHashChain;
11733f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastruct VP8LHashChain {
1180912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  // The 20 most significant bits contain the offset at which the best match
1190912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  // is found. These 20 bits are the limit defined by GetWindowSizeForHashChain
1200912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  // (through WINDOW_SIZE = 1<<20).
1210912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  // The lower 12 bits contain the length of the match. The 12 bit limit is
1220912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  // defined in MaxFindCopyLength with MAX_LENGTH=4096.
1230912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  uint32_t* offset_length_;
12433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // This is the maximum size of the hash_chain that can be constructed.
12533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // Typically this is the pixel count (width x height) for a given image.
12633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int size_;
12733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora};
128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
12933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Must be called first, to set size.
13033f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint VP8LHashChainInit(VP8LHashChain* const p, int size);
1310912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern// Pre-compute the best matches for argb.
1320912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zernint VP8LHashChainFill(VP8LHashChain* const p, int quality,
133fa39824bb690c5806358871f46940d0450973d8aJames Zern                      const uint32_t* const argb, int xsize, int ysize,
134fa39824bb690c5806358871f46940d0450973d8aJames Zern                      int low_effort);
13533f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LHashChainClear(VP8LHashChain* const p);  // release memory
136a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
13733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// -----------------------------------------------------------------------------
13833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// VP8LBackwardRefs (block-based backward-references storage)
13933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
14033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// maximum number of reference blocks the image will be segmented into
14133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define MAX_REFS_BLOCK_PER_IMAGE 16
14233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
14333f74dabbc7920a65ed435d7417987589febdc16Vikas Aroratypedef struct PixOrCopyBlock PixOrCopyBlock;   // forward declaration
14433f74dabbc7920a65ed435d7417987589febdc16Vikas Aroratypedef struct VP8LBackwardRefs VP8LBackwardRefs;
14533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
14633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Container for blocks chain
14733f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastruct VP8LBackwardRefs {
14833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int block_size_;               // common block-size
14933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int error_;                    // set to true if some memory error occurred
15033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  PixOrCopyBlock* refs_;         // list of currently used blocks
15133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  PixOrCopyBlock** tail_;        // for list recycling
15233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  PixOrCopyBlock* free_blocks_;  // free-list
15333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  PixOrCopyBlock* last_block_;   // used for adding new refs (internal)
15433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora};
155a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
15633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Initialize the object. 'block_size' is the common block size to store
15733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// references (typically, width * height / MAX_REFS_BLOCK_PER_IMAGE).
15833f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size);
15933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Release memory for backward references.
16033f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LBackwardRefsClear(VP8LBackwardRefs* const refs);
16133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error.
16233f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src,
16333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                         VP8LBackwardRefs* const dst);
164a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
16533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Cursor for iterating on references content
16633f74dabbc7920a65ed435d7417987589febdc16Vikas Aroratypedef struct {
16733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // public:
16833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  PixOrCopy* cur_pos;           // current position
16933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // private:
17033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  PixOrCopyBlock* cur_block_;   // current block in the refs list
17133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const PixOrCopy* last_pos_;   // sentinel for switching to next block
17233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} VP8LRefsCursor;
17333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
17433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Returns a cursor positioned at the beginning of the references list.
17533f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs);
17633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Returns true if cursor is pointing at a valid position.
17733f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE int VP8LRefsCursorOk(const VP8LRefsCursor* const c) {
17833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return (c->cur_pos != NULL);
17933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
18033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Move to next block of references. Internal, not to be called directly.
18133f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid VP8LRefsCursorNextBlock(VP8LRefsCursor* const c);
18233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Move to next position, or NULL. Should not be called if !VP8LRefsCursorOk().
18333f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) {
18433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  assert(c != NULL);
18533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  assert(VP8LRefsCursorOk(c));
18633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (++c->cur_pos == c->last_pos_) VP8LRefsCursorNextBlock(c);
18733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
188a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// -----------------------------------------------------------------------------
190a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Main entry points
191a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
192a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Evaluates best possible backward references for specified quality.
1937c8da7ce66017295a65ec028084b90800be377f8James Zern// The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache
1947c8da7ce66017295a65ec028084b90800be377f8James Zern// bits to use (passing 0 implies disabling the local color cache).
1957c8da7ce66017295a65ec028084b90800be377f8James Zern// The optimal cache bits is evaluated and set for the *cache_bits parameter.
19633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// The return value is the pointer to the best of the two backward refs viz,
19733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// refs[0] or refs[1].
19833f74dabbc7920a65ed435d7417987589febdc16Vikas AroraVP8LBackwardRefs* VP8LGetBackwardReferences(
19933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    int width, int height, const uint32_t* const argb, int quality,
2000912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    int low_effort, int* const cache_bits,
2010912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern    const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs[2]);
202a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
2038b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora#ifdef __cplusplus
204a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
205a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif
206a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
207a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif  // WEBP_ENC_BACKWARD_REFERENCES_H_
208