backward_references.c 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715
  1. // Copyright 2012 Google Inc. All Rights Reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the COPYING file in the root of the source
  5. // tree. An additional intellectual property rights grant can be found
  6. // in the file PATENTS. All contributing project authors may
  7. // be found in the AUTHORS file in the root of the source tree.
  8. // -----------------------------------------------------------------------------
  9. //
  10. // Author: Jyrki Alakuijala ([email protected])
  11. //
  12. #include <assert.h>
  13. #include <math.h>
  14. #include "./backward_references.h"
  15. #include "./histogram.h"
  16. #include "../dsp/lossless.h"
  17. #include "../dsp/dsp.h"
  18. #include "../utils/color_cache.h"
  19. #include "../utils/utils.h"
  20. #define VALUES_IN_BYTE 256
  21. #define MIN_BLOCK_SIZE 256 // minimum block size for backward references
  22. #define MAX_ENTROPY (1e30f)
  23. // 1M window (4M bytes) minus 120 special codes for short distances.
  24. #define WINDOW_SIZE_BITS 20
  25. #define WINDOW_SIZE ((1 << WINDOW_SIZE_BITS) - 120)
  26. // Bounds for the match length.
  27. #define MIN_LENGTH 2
  28. // If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it
  29. // is used in VP8LHashChain.
  30. #define MAX_LENGTH_BITS 12
  31. // We want the max value to be attainable and stored in MAX_LENGTH_BITS bits.
  32. #define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1)
  33. #if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32
  34. #error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32"
  35. #endif
  36. // -----------------------------------------------------------------------------
  37. static const uint8_t plane_to_code_lut[128] = {
  38. 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255,
  39. 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79,
  40. 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87,
  41. 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91,
  42. 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100,
  43. 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109,
  44. 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114,
  45. 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117
  46. };
  47. static int DistanceToPlaneCode(int xsize, int dist) {
  48. const int yoffset = dist / xsize;
  49. const int xoffset = dist - yoffset * xsize;
  50. if (xoffset <= 8 && yoffset < 8) {
  51. return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1;
  52. } else if (xoffset > xsize - 8 && yoffset < 7) {
  53. return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1;
  54. }
  55. return dist + 120;
  56. }
  57. // Returns the exact index where array1 and array2 are different. For an index
  58. // inferior or equal to best_len_match, the return value just has to be strictly
  59. // inferior to best_len_match. The current behavior is to return 0 if this index
  60. // is best_len_match, and the index itself otherwise.
  61. // If no two elements are the same, it returns max_limit.
  62. static WEBP_INLINE int FindMatchLength(const uint32_t* const array1,
  63. const uint32_t* const array2,
  64. int best_len_match, int max_limit) {
  65. // Before 'expensive' linear match, check if the two arrays match at the
  66. // current best length index.
  67. if (array1[best_len_match] != array2[best_len_match]) return 0;
  68. return VP8LVectorMismatch(array1, array2, max_limit);
  69. }
  70. // -----------------------------------------------------------------------------
  71. // VP8LBackwardRefs
  72. struct PixOrCopyBlock {
  73. PixOrCopyBlock* next_; // next block (or NULL)
  74. PixOrCopy* start_; // data start
  75. int size_; // currently used size
  76. };
  77. static void ClearBackwardRefs(VP8LBackwardRefs* const refs) {
  78. assert(refs != NULL);
  79. if (refs->tail_ != NULL) {
  80. *refs->tail_ = refs->free_blocks_; // recycle all blocks at once
  81. }
  82. refs->free_blocks_ = refs->refs_;
  83. refs->tail_ = &refs->refs_;
  84. refs->last_block_ = NULL;
  85. refs->refs_ = NULL;
  86. }
  87. void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) {
  88. assert(refs != NULL);
  89. ClearBackwardRefs(refs);
  90. while (refs->free_blocks_ != NULL) {
  91. PixOrCopyBlock* const next = refs->free_blocks_->next_;
  92. WebPSafeFree(refs->free_blocks_);
  93. refs->free_blocks_ = next;
  94. }
  95. }
  96. void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) {
  97. assert(refs != NULL);
  98. memset(refs, 0, sizeof(*refs));
  99. refs->tail_ = &refs->refs_;
  100. refs->block_size_ =
  101. (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size;
  102. }
  103. VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) {
  104. VP8LRefsCursor c;
  105. c.cur_block_ = refs->refs_;
  106. if (refs->refs_ != NULL) {
  107. c.cur_pos = c.cur_block_->start_;
  108. c.last_pos_ = c.cur_pos + c.cur_block_->size_;
  109. } else {
  110. c.cur_pos = NULL;
  111. c.last_pos_ = NULL;
  112. }
  113. return c;
  114. }
  115. void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) {
  116. PixOrCopyBlock* const b = c->cur_block_->next_;
  117. c->cur_pos = (b == NULL) ? NULL : b->start_;
  118. c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_;
  119. c->cur_block_ = b;
  120. }
  121. // Create a new block, either from the free list or allocated
  122. static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) {
  123. PixOrCopyBlock* b = refs->free_blocks_;
  124. if (b == NULL) { // allocate new memory chunk
  125. const size_t total_size =
  126. sizeof(*b) + refs->block_size_ * sizeof(*b->start_);
  127. b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size);
  128. if (b == NULL) {
  129. refs->error_ |= 1;
  130. return NULL;
  131. }
  132. b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned
  133. } else { // recycle from free-list
  134. refs->free_blocks_ = b->next_;
  135. }
  136. *refs->tail_ = b;
  137. refs->tail_ = &b->next_;
  138. refs->last_block_ = b;
  139. b->next_ = NULL;
  140. b->size_ = 0;
  141. return b;
  142. }
  143. static WEBP_INLINE void BackwardRefsCursorAdd(VP8LBackwardRefs* const refs,
  144. const PixOrCopy v) {
  145. PixOrCopyBlock* b = refs->last_block_;
  146. if (b == NULL || b->size_ == refs->block_size_) {
  147. b = BackwardRefsNewBlock(refs);
  148. if (b == NULL) return; // refs->error_ is set
  149. }
  150. b->start_[b->size_++] = v;
  151. }
  152. int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src,
  153. VP8LBackwardRefs* const dst) {
  154. const PixOrCopyBlock* b = src->refs_;
  155. ClearBackwardRefs(dst);
  156. assert(src->block_size_ == dst->block_size_);
  157. while (b != NULL) {
  158. PixOrCopyBlock* const new_b = BackwardRefsNewBlock(dst);
  159. if (new_b == NULL) return 0; // dst->error_ is set
  160. memcpy(new_b->start_, b->start_, b->size_ * sizeof(*b->start_));
  161. new_b->size_ = b->size_;
  162. b = b->next_;
  163. }
  164. return 1;
  165. }
  166. // -----------------------------------------------------------------------------
  167. // Hash chains
  168. int VP8LHashChainInit(VP8LHashChain* const p, int size) {
  169. assert(p->size_ == 0);
  170. assert(p->offset_length_ == NULL);
  171. assert(size > 0);
  172. p->offset_length_ =
  173. (uint32_t*)WebPSafeMalloc(size, sizeof(*p->offset_length_));
  174. if (p->offset_length_ == NULL) return 0;
  175. p->size_ = size;
  176. return 1;
  177. }
  178. void VP8LHashChainClear(VP8LHashChain* const p) {
  179. assert(p != NULL);
  180. WebPSafeFree(p->offset_length_);
  181. p->size_ = 0;
  182. p->offset_length_ = NULL;
  183. }
  184. // -----------------------------------------------------------------------------
  185. #define HASH_MULTIPLIER_HI (0xc6a4a793U)
  186. #define HASH_MULTIPLIER_LO (0x5bd1e996U)
  187. static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) {
  188. uint32_t key;
  189. key = argb[1] * HASH_MULTIPLIER_HI;
  190. key += argb[0] * HASH_MULTIPLIER_LO;
  191. key = key >> (32 - HASH_BITS);
  192. return key;
  193. }
  194. // Returns the maximum number of hash chain lookups to do for a
  195. // given compression quality. Return value in range [8, 86].
  196. static int GetMaxItersForQuality(int quality) {
  197. return 8 + (quality * quality) / 128;
  198. }
  199. static int GetWindowSizeForHashChain(int quality, int xsize) {
  200. const int max_window_size = (quality > 75) ? WINDOW_SIZE
  201. : (quality > 50) ? (xsize << 8)
  202. : (quality > 25) ? (xsize << 6)
  203. : (xsize << 4);
  204. assert(xsize > 0);
  205. return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size;
  206. }
  207. static WEBP_INLINE int MaxFindCopyLength(int len) {
  208. return (len < MAX_LENGTH) ? len : MAX_LENGTH;
  209. }
  210. int VP8LHashChainFill(VP8LHashChain* const p, int quality,
  211. const uint32_t* const argb, int xsize, int ysize) {
  212. const int size = xsize * ysize;
  213. const int iter_max = GetMaxItersForQuality(quality);
  214. const int iter_min = iter_max - quality / 10;
  215. const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize);
  216. int pos;
  217. uint32_t base_position;
  218. int32_t* hash_to_first_index;
  219. // Temporarily use the p->offset_length_ as a hash chain.
  220. int32_t* chain = (int32_t*)p->offset_length_;
  221. assert(p->size_ != 0);
  222. assert(p->offset_length_ != NULL);
  223. hash_to_first_index =
  224. (int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index));
  225. if (hash_to_first_index == NULL) return 0;
  226. // Set the int32_t array to -1.
  227. memset(hash_to_first_index, 0xff, HASH_SIZE * sizeof(*hash_to_first_index));
  228. // Fill the chain linking pixels with the same hash.
  229. for (pos = 0; pos < size - 1; ++pos) {
  230. const uint32_t hash_code = GetPixPairHash64(argb + pos);
  231. chain[pos] = hash_to_first_index[hash_code];
  232. hash_to_first_index[hash_code] = pos;
  233. }
  234. WebPSafeFree(hash_to_first_index);
  235. // Find the best match interval at each pixel, defined by an offset to the
  236. // pixel and a length. The right-most pixel cannot match anything to the right
  237. // (hence a best length of 0) and the left-most pixel nothing to the left
  238. // (hence an offset of 0).
  239. p->offset_length_[0] = p->offset_length_[size - 1] = 0;
  240. for (base_position = size - 2 < 0 ? 0 : size - 2; base_position > 0;) {
  241. const int max_len = MaxFindCopyLength(size - 1 - base_position);
  242. const uint32_t* const argb_start = argb + base_position;
  243. int iter = iter_max;
  244. int best_length = 0;
  245. uint32_t best_distance = 0;
  246. const int min_pos =
  247. (base_position > window_size) ? base_position - window_size : 0;
  248. const int length_max = (max_len < 256) ? max_len : 256;
  249. uint32_t max_base_position;
  250. for (pos = chain[base_position]; pos >= min_pos; pos = chain[pos]) {
  251. int curr_length;
  252. if (--iter < 0) {
  253. break;
  254. }
  255. assert(base_position > (uint32_t)pos);
  256. curr_length =
  257. FindMatchLength(argb + pos, argb_start, best_length, max_len);
  258. if (best_length < curr_length) {
  259. best_length = curr_length;
  260. best_distance = base_position - pos;
  261. // Stop if we have reached the maximum length. Otherwise, make sure
  262. // we have executed a minimum number of iterations depending on the
  263. // quality.
  264. if ((best_length == MAX_LENGTH) ||
  265. (curr_length >= length_max && iter < iter_min)) {
  266. break;
  267. }
  268. }
  269. }
  270. // We have the best match but in case the two intervals continue matching
  271. // to the left, we have the best matches for the left-extended pixels.
  272. max_base_position = base_position;
  273. while (1) {
  274. assert(best_length <= MAX_LENGTH);
  275. assert(best_distance <= WINDOW_SIZE);
  276. p->offset_length_[base_position] =
  277. (best_distance << MAX_LENGTH_BITS) | (uint32_t)best_length;
  278. --base_position;
  279. // Stop if we don't have a match or if we are out of bounds.
  280. if (best_distance == 0 || base_position == 0) break;
  281. // Stop if we cannot extend the matching intervals to the left.
  282. if (base_position < best_distance ||
  283. argb[base_position - best_distance] != argb[base_position]) {
  284. break;
  285. }
  286. // Stop if we are matching at its limit because there could be a closer
  287. // matching interval with the same maximum length. Then again, if the
  288. // matching interval is as close as possible (best_distance == 1), we will
  289. // never find anything better so let's continue.
  290. if (best_length == MAX_LENGTH && best_distance != 1 &&
  291. base_position + MAX_LENGTH < max_base_position) {
  292. break;
  293. }
  294. if (best_length < MAX_LENGTH) {
  295. ++best_length;
  296. max_base_position = base_position;
  297. }
  298. }
  299. }
  300. return 1;
  301. }
  302. static WEBP_INLINE int HashChainFindOffset(const VP8LHashChain* const p,
  303. const int base_position) {
  304. return p->offset_length_[base_position] >> MAX_LENGTH_BITS;
  305. }
  306. static WEBP_INLINE int HashChainFindLength(const VP8LHashChain* const p,
  307. const int base_position) {
  308. return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1);
  309. }
  310. static WEBP_INLINE void HashChainFindCopy(const VP8LHashChain* const p,
  311. int base_position,
  312. int* const offset_ptr,
  313. int* const length_ptr) {
  314. *offset_ptr = HashChainFindOffset(p, base_position);
  315. *length_ptr = HashChainFindLength(p, base_position);
  316. }
  317. static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache,
  318. VP8LColorCache* const hashers,
  319. VP8LBackwardRefs* const refs) {
  320. PixOrCopy v;
  321. if (use_color_cache) {
  322. const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel);
  323. if (VP8LColorCacheLookup(hashers, key) == pixel) {
  324. v = PixOrCopyCreateCacheIdx(key);
  325. } else {
  326. v = PixOrCopyCreateLiteral(pixel);
  327. VP8LColorCacheSet(hashers, key, pixel);
  328. }
  329. } else {
  330. v = PixOrCopyCreateLiteral(pixel);
  331. }
  332. BackwardRefsCursorAdd(refs, v);
  333. }
  334. static int BackwardReferencesRle(int xsize, int ysize,
  335. const uint32_t* const argb,
  336. int cache_bits, VP8LBackwardRefs* const refs) {
  337. const int pix_count = xsize * ysize;
  338. int i, k;
  339. const int use_color_cache = (cache_bits > 0);
  340. VP8LColorCache hashers;
  341. if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) {
  342. return 0;
  343. }
  344. ClearBackwardRefs(refs);
  345. // Add first pixel as literal.
  346. AddSingleLiteral(argb[0], use_color_cache, &hashers, refs);
  347. i = 1;
  348. while (i < pix_count) {
  349. const int max_len = MaxFindCopyLength(pix_count - i);
  350. const int kMinLength = 4;
  351. const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len);
  352. const int prev_row_len = (i < xsize) ? 0 :
  353. FindMatchLength(argb + i, argb + i - xsize, 0, max_len);
  354. if (rle_len >= prev_row_len && rle_len >= kMinLength) {
  355. BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len));
  356. // We don't need to update the color cache here since it is always the
  357. // same pixel being copied, and that does not change the color cache
  358. // state.
  359. i += rle_len;
  360. } else if (prev_row_len >= kMinLength) {
  361. BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len));
  362. if (use_color_cache) {
  363. for (k = 0; k < prev_row_len; ++k) {
  364. VP8LColorCacheInsert(&hashers, argb[i + k]);
  365. }
  366. }
  367. i += prev_row_len;
  368. } else {
  369. AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
  370. i++;
  371. }
  372. }
  373. if (use_color_cache) VP8LColorCacheClear(&hashers);
  374. return !refs->error_;
  375. }
  376. static int BackwardReferencesLz77(int xsize, int ysize,
  377. const uint32_t* const argb, int cache_bits,
  378. const VP8LHashChain* const hash_chain,
  379. VP8LBackwardRefs* const refs) {
  380. int i;
  381. int i_last_check = -1;
  382. int ok = 0;
  383. int cc_init = 0;
  384. const int use_color_cache = (cache_bits > 0);
  385. const int pix_count = xsize * ysize;
  386. VP8LColorCache hashers;
  387. if (use_color_cache) {
  388. cc_init = VP8LColorCacheInit(&hashers, cache_bits);
  389. if (!cc_init) goto Error;
  390. }
  391. ClearBackwardRefs(refs);
  392. for (i = 0; i < pix_count;) {
  393. // Alternative#1: Code the pixels starting at 'i' using backward reference.
  394. int offset = 0;
  395. int len = 0;
  396. int j;
  397. HashChainFindCopy(hash_chain, i, &offset, &len);
  398. if (len > MIN_LENGTH + 1) {
  399. const int len_ini = len;
  400. int max_reach = 0;
  401. assert(i + len < pix_count);
  402. // Only start from what we have not checked already.
  403. i_last_check = (i > i_last_check) ? i : i_last_check;
  404. // We know the best match for the current pixel but we try to find the
  405. // best matches for the current pixel AND the next one combined.
  406. // The naive method would use the intervals:
  407. // [i,i+len) + [i+len, length of best match at i+len)
  408. // while we check if we can use:
  409. // [i,j) (where j<=i+len) + [j, length of best match at j)
  410. for (j = i_last_check + 1; j <= i + len_ini; ++j) {
  411. const int len_j = HashChainFindLength(hash_chain, j);
  412. const int reach =
  413. j + (len_j > MIN_LENGTH + 1 ? len_j : 1); // 1 for single literal.
  414. if (reach > max_reach) {
  415. len = j - i;
  416. max_reach = reach;
  417. }
  418. }
  419. } else {
  420. len = 1;
  421. }
  422. // Go with literal or backward reference.
  423. assert(len > 0);
  424. if (len == 1) {
  425. AddSingleLiteral(argb[i], use_color_cache, &hashers, refs);
  426. } else {
  427. BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
  428. if (use_color_cache) {
  429. for (j = i; j < i + len; ++j) VP8LColorCacheInsert(&hashers, argb[j]);
  430. }
  431. }
  432. i += len;
  433. }
  434. ok = !refs->error_;
  435. Error:
  436. if (cc_init) VP8LColorCacheClear(&hashers);
  437. return ok;
  438. }
  439. // -----------------------------------------------------------------------------
  440. typedef struct {
  441. double alpha_[VALUES_IN_BYTE];
  442. double red_[VALUES_IN_BYTE];
  443. double blue_[VALUES_IN_BYTE];
  444. double distance_[NUM_DISTANCE_CODES];
  445. double* literal_;
  446. } CostModel;
  447. static int BackwardReferencesTraceBackwards(
  448. int xsize, int ysize, const uint32_t* const argb, int quality,
  449. int cache_bits, const VP8LHashChain* const hash_chain,
  450. VP8LBackwardRefs* const refs);
  451. static void ConvertPopulationCountTableToBitEstimates(
  452. int num_symbols, const uint32_t population_counts[], double output[]) {
  453. uint32_t sum = 0;
  454. int nonzeros = 0;
  455. int i;
  456. for (i = 0; i < num_symbols; ++i) {
  457. sum += population_counts[i];
  458. if (population_counts[i] > 0) {
  459. ++nonzeros;
  460. }
  461. }
  462. if (nonzeros <= 1) {
  463. memset(output, 0, num_symbols * sizeof(*output));
  464. } else {
  465. const double logsum = VP8LFastLog2(sum);
  466. for (i = 0; i < num_symbols; ++i) {
  467. output[i] = logsum - VP8LFastLog2(population_counts[i]);
  468. }
  469. }
  470. }
  471. static int CostModelBuild(CostModel* const m, int cache_bits,
  472. VP8LBackwardRefs* const refs) {
  473. int ok = 0;
  474. VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits);
  475. if (histo == NULL) goto Error;
  476. VP8LHistogramCreate(histo, refs, cache_bits);
  477. ConvertPopulationCountTableToBitEstimates(
  478. VP8LHistogramNumCodes(histo->palette_code_bits_),
  479. histo->literal_, m->literal_);
  480. ConvertPopulationCountTableToBitEstimates(
  481. VALUES_IN_BYTE, histo->red_, m->red_);
  482. ConvertPopulationCountTableToBitEstimates(
  483. VALUES_IN_BYTE, histo->blue_, m->blue_);
  484. ConvertPopulationCountTableToBitEstimates(
  485. VALUES_IN_BYTE, histo->alpha_, m->alpha_);
  486. ConvertPopulationCountTableToBitEstimates(
  487. NUM_DISTANCE_CODES, histo->distance_, m->distance_);
  488. ok = 1;
  489. Error:
  490. VP8LFreeHistogram(histo);
  491. return ok;
  492. }
  493. static WEBP_INLINE double GetLiteralCost(const CostModel* const m, uint32_t v) {
  494. return m->alpha_[v >> 24] +
  495. m->red_[(v >> 16) & 0xff] +
  496. m->literal_[(v >> 8) & 0xff] +
  497. m->blue_[v & 0xff];
  498. }
  499. static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) {
  500. const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx;
  501. return m->literal_[literal_idx];
  502. }
  503. static WEBP_INLINE double GetLengthCost(const CostModel* const m,
  504. uint32_t length) {
  505. int code, extra_bits;
  506. VP8LPrefixEncodeBits(length, &code, &extra_bits);
  507. return m->literal_[VALUES_IN_BYTE + code] + extra_bits;
  508. }
  509. static WEBP_INLINE double GetDistanceCost(const CostModel* const m,
  510. uint32_t distance) {
  511. int code, extra_bits;
  512. VP8LPrefixEncodeBits(distance, &code, &extra_bits);
  513. return m->distance_[code] + extra_bits;
  514. }
  515. static void AddSingleLiteralWithCostModel(const uint32_t* const argb,
  516. VP8LColorCache* const hashers,
  517. const CostModel* const cost_model,
  518. int idx, int use_color_cache,
  519. double prev_cost, float* const cost,
  520. uint16_t* const dist_array) {
  521. double cost_val = prev_cost;
  522. const uint32_t color = argb[0];
  523. if (use_color_cache && VP8LColorCacheContains(hashers, color)) {
  524. const double mul0 = 0.68;
  525. const int ix = VP8LColorCacheGetIndex(hashers, color);
  526. cost_val += GetCacheCost(cost_model, ix) * mul0;
  527. } else {
  528. const double mul1 = 0.82;
  529. if (use_color_cache) VP8LColorCacheInsert(hashers, color);
  530. cost_val += GetLiteralCost(cost_model, color) * mul1;
  531. }
  532. if (cost[idx] > cost_val) {
  533. cost[idx] = (float)cost_val;
  534. dist_array[idx] = 1; // only one is inserted.
  535. }
  536. }
  537. // -----------------------------------------------------------------------------
  538. // CostManager and interval handling
  539. // Empirical value to avoid high memory consumption but good for performance.
  540. #define COST_CACHE_INTERVAL_SIZE_MAX 100
  541. // To perform backward reference every pixel at index index_ is considered and
  542. // the cost for the MAX_LENGTH following pixels computed. Those following pixels
  543. // at index index_ + k (k from 0 to MAX_LENGTH) have a cost of:
  544. // distance_cost_ at index_ + GetLengthCost(cost_model, k)
  545. // (named cost) (named cached cost)
  546. // and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an
  547. // array of size MAX_LENGTH.
  548. // Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the
  549. // minimal values using intervals, for which lower_ and upper_ bounds are kept.
  550. // An interval is defined by the index_ of the pixel that generated it and
  551. // is only useful in a range of indices from start_ to end_ (exclusive), i.e.
  552. // it contains the minimum value for pixels between start_ and end_.
  553. // Intervals are stored in a linked list and ordered by start_. When a new
  554. // interval has a better minimum, old intervals are split or removed.
  555. typedef struct CostInterval CostInterval;
  556. struct CostInterval {
  557. double lower_;
  558. double upper_;
  559. int start_;
  560. int end_;
  561. double distance_cost_;
  562. int index_;
  563. CostInterval* previous_;
  564. CostInterval* next_;
  565. };
  566. // The GetLengthCost(cost_model, k) part of the costs is also bounded for
  567. // efficiency in a set of intervals of a different type.
  568. // If those intervals are small enough, they are not used for comparison and
  569. // written into the costs right away.
  570. typedef struct {
  571. double lower_; // Lower bound of the interval.
  572. double upper_; // Upper bound of the interval.
  573. int start_;
  574. int end_; // Exclusive.
  575. int do_write_; // If !=0, the interval is saved to cost instead of being kept
  576. // for comparison.
  577. } CostCacheInterval;
  578. // This structure is in charge of managing intervals and costs.
  579. // It caches the different CostCacheInterval, caches the different
  580. // GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose
  581. // count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX).
  582. #define COST_MANAGER_MAX_FREE_LIST 10
  583. typedef struct {
  584. CostInterval* head_;
  585. int count_; // The number of stored intervals.
  586. CostCacheInterval* cache_intervals_;
  587. size_t cache_intervals_size_;
  588. double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k).
  589. double min_cost_cache_; // The minimum value in cost_cache_[1:].
  590. double max_cost_cache_; // The maximum value in cost_cache_[1:].
  591. float* costs_;
  592. uint16_t* dist_array_;
  593. // Most of the time, we only need few intervals -> use a free-list, to avoid
  594. // fragmentation with small allocs in most common cases.
  595. CostInterval intervals_[COST_MANAGER_MAX_FREE_LIST];
  596. CostInterval* free_intervals_;
  597. // These are regularly malloc'd remains. This list can't grow larger than than
  598. // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note.
  599. CostInterval* recycled_intervals_;
  600. // Buffer used in BackwardReferencesHashChainDistanceOnly to store the ends
  601. // of the intervals that can have impacted the cost at a pixel.
  602. int* interval_ends_;
  603. int interval_ends_size_;
  604. } CostManager;
  605. static int IsCostCacheIntervalWritable(int start, int end) {
  606. // 100 is the length for which we consider an interval for comparison, and not
  607. // for writing.
  608. // The first intervals are very small and go in increasing size. This constant
  609. // helps merging them into one big interval (up to index 150/200 usually from
  610. // which intervals start getting much bigger).
  611. // This value is empirical.
  612. return (end - start + 1 < 100);
  613. }
  614. static void CostIntervalAddToFreeList(CostManager* const manager,
  615. CostInterval* const interval) {
  616. interval->next_ = manager->free_intervals_;
  617. manager->free_intervals_ = interval;
  618. }
  619. static int CostIntervalIsInFreeList(const CostManager* const manager,
  620. const CostInterval* const interval) {
  621. return (interval >= &manager->intervals_[0] &&
  622. interval <= &manager->intervals_[COST_MANAGER_MAX_FREE_LIST - 1]);
  623. }
  624. static void CostManagerInitFreeList(CostManager* const manager) {
  625. int i;
  626. manager->free_intervals_ = NULL;
  627. for (i = 0; i < COST_MANAGER_MAX_FREE_LIST; ++i) {
  628. CostIntervalAddToFreeList(manager, &manager->intervals_[i]);
  629. }
  630. }
  631. static void DeleteIntervalList(CostManager* const manager,
  632. const CostInterval* interval) {
  633. while (interval != NULL) {
  634. const CostInterval* const next = interval->next_;
  635. if (!CostIntervalIsInFreeList(manager, interval)) {
  636. WebPSafeFree((void*)interval);
  637. } // else: do nothing
  638. interval = next;
  639. }
  640. }
  641. static void CostManagerClear(CostManager* const manager) {
  642. if (manager == NULL) return;
  643. WebPSafeFree(manager->costs_);
  644. WebPSafeFree(manager->cache_intervals_);
  645. WebPSafeFree(manager->interval_ends_);
  646. // Clear the interval lists.
  647. DeleteIntervalList(manager, manager->head_);
  648. manager->head_ = NULL;
  649. DeleteIntervalList(manager, manager->recycled_intervals_);
  650. manager->recycled_intervals_ = NULL;
  651. // Reset pointers, count_ and cache_intervals_size_.
  652. memset(manager, 0, sizeof(*manager));
  653. CostManagerInitFreeList(manager);
  654. }
  655. static int CostManagerInit(CostManager* const manager,
  656. uint16_t* const dist_array, int pix_count,
  657. const CostModel* const cost_model) {
  658. int i;
  659. const int cost_cache_size = (pix_count > MAX_LENGTH) ? MAX_LENGTH : pix_count;
  660. // This constant is tied to the cost_model we use.
  661. // Empirically, differences between intervals is usually of more than 1.
  662. const double min_cost_diff = 0.1;
  663. manager->costs_ = NULL;
  664. manager->cache_intervals_ = NULL;
  665. manager->interval_ends_ = NULL;
  666. manager->head_ = NULL;
  667. manager->recycled_intervals_ = NULL;
  668. manager->count_ = 0;
  669. manager->dist_array_ = dist_array;
  670. CostManagerInitFreeList(manager);
  671. // Fill in the cost_cache_.
  672. manager->cache_intervals_size_ = 1;
  673. manager->cost_cache_[0] = 0;
  674. for (i = 1; i < cost_cache_size; ++i) {
  675. manager->cost_cache_[i] = GetLengthCost(cost_model, i);
  676. // Get an approximation of the number of bound intervals.
  677. if (fabs(manager->cost_cache_[i] - manager->cost_cache_[i - 1]) >
  678. min_cost_diff) {
  679. ++manager->cache_intervals_size_;
  680. }
  681. // Compute the minimum of cost_cache_.
  682. if (i == 1) {
  683. manager->min_cost_cache_ = manager->cost_cache_[1];
  684. manager->max_cost_cache_ = manager->cost_cache_[1];
  685. } else if (manager->cost_cache_[i] < manager->min_cost_cache_) {
  686. manager->min_cost_cache_ = manager->cost_cache_[i];
  687. } else if (manager->cost_cache_[i] > manager->max_cost_cache_) {
  688. manager->max_cost_cache_ = manager->cost_cache_[i];
  689. }
  690. }
  691. // With the current cost models, we have 15 intervals, so we are safe by
  692. // setting a maximum of COST_CACHE_INTERVAL_SIZE_MAX.
  693. if (manager->cache_intervals_size_ > COST_CACHE_INTERVAL_SIZE_MAX) {
  694. manager->cache_intervals_size_ = COST_CACHE_INTERVAL_SIZE_MAX;
  695. }
  696. manager->cache_intervals_ = (CostCacheInterval*)WebPSafeMalloc(
  697. manager->cache_intervals_size_, sizeof(*manager->cache_intervals_));
  698. if (manager->cache_intervals_ == NULL) {
  699. CostManagerClear(manager);
  700. return 0;
  701. }
  702. // Fill in the cache_intervals_.
  703. {
  704. double cost_prev = -1e38f; // unprobably low initial value
  705. CostCacheInterval* prev = NULL;
  706. CostCacheInterval* cur = manager->cache_intervals_;
  707. const CostCacheInterval* const end =
  708. manager->cache_intervals_ + manager->cache_intervals_size_;
  709. // Consecutive values in cost_cache_ are compared and if a big enough
  710. // difference is found, a new interval is created and bounded.
  711. for (i = 0; i < cost_cache_size; ++i) {
  712. const double cost_val = manager->cost_cache_[i];
  713. if (i == 0 ||
  714. (fabs(cost_val - cost_prev) > min_cost_diff && cur + 1 < end)) {
  715. if (i > 1) {
  716. const int is_writable =
  717. IsCostCacheIntervalWritable(cur->start_, cur->end_);
  718. // Merge with the previous interval if both are writable.
  719. if (is_writable && cur != manager->cache_intervals_ &&
  720. prev->do_write_) {
  721. // Update the previous interval.
  722. prev->end_ = cur->end_;
  723. if (cur->lower_ < prev->lower_) {
  724. prev->lower_ = cur->lower_;
  725. } else if (cur->upper_ > prev->upper_) {
  726. prev->upper_ = cur->upper_;
  727. }
  728. } else {
  729. cur->do_write_ = is_writable;
  730. prev = cur;
  731. ++cur;
  732. }
  733. }
  734. // Initialize an interval.
  735. cur->start_ = i;
  736. cur->do_write_ = 0;
  737. cur->lower_ = cost_val;
  738. cur->upper_ = cost_val;
  739. } else {
  740. // Update the current interval bounds.
  741. if (cost_val < cur->lower_) {
  742. cur->lower_ = cost_val;
  743. } else if (cost_val > cur->upper_) {
  744. cur->upper_ = cost_val;
  745. }
  746. }
  747. cur->end_ = i + 1;
  748. cost_prev = cost_val;
  749. }
  750. manager->cache_intervals_size_ = cur + 1 - manager->cache_intervals_;
  751. }
  752. manager->costs_ = (float*)WebPSafeMalloc(pix_count, sizeof(*manager->costs_));
  753. if (manager->costs_ == NULL) {
  754. CostManagerClear(manager);
  755. return 0;
  756. }
  757. // Set the initial costs_ high for every pixel as we will keep the minimum.
  758. for (i = 0; i < pix_count; ++i) manager->costs_[i] = 1e38f;
  759. // The cost at pixel is influenced by the cost intervals from previous pixels.
  760. // Let us take the specific case where the offset is the same (which actually
  761. // happens a lot in case of uniform regions).
  762. // pixel i contributes to j>i a cost of: offset cost + cost_cache_[j-i]
  763. // pixel i+1 contributes to j>i a cost of: 2*offset cost + cost_cache_[j-i-1]
  764. // pixel i+2 contributes to j>i a cost of: 3*offset cost + cost_cache_[j-i-2]
  765. // and so on.
  766. // A pixel i influences the following length(j) < MAX_LENGTH pixels. What is
  767. // the value of j such that pixel i + j cannot influence any of those pixels?
  768. // This value is such that:
  769. // max of cost_cache_ < j*offset cost + min of cost_cache_
  770. // (pixel i + j 's cost cannot beat the worst cost given by pixel i).
  771. // This value will be used to optimize the cost computation in
  772. // BackwardReferencesHashChainDistanceOnly.
  773. {
  774. // The offset cost is computed in GetDistanceCost and has a minimum value of
  775. // the minimum in cost_model->distance_. The case where the offset cost is 0
  776. // will be dealt with differently later so we are only interested in the
  777. // minimum non-zero offset cost.
  778. double offset_cost_min = 0.;
  779. int size;
  780. for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
  781. if (cost_model->distance_[i] != 0) {
  782. if (offset_cost_min == 0.) {
  783. offset_cost_min = cost_model->distance_[i];
  784. } else if (cost_model->distance_[i] < offset_cost_min) {
  785. offset_cost_min = cost_model->distance_[i];
  786. }
  787. }
  788. }
  789. // In case all the cost_model->distance_ is 0, the next non-zero cost we
  790. // can have is from the extra bit in GetDistanceCost, hence 1.
  791. if (offset_cost_min < 1.) offset_cost_min = 1.;
  792. size = 1 + (int)ceil((manager->max_cost_cache_ - manager->min_cost_cache_) /
  793. offset_cost_min);
  794. // Empirically, we usually end up with a value below 100.
  795. if (size > MAX_LENGTH) size = MAX_LENGTH;
  796. manager->interval_ends_ =
  797. (int*)WebPSafeMalloc(size, sizeof(*manager->interval_ends_));
  798. if (manager->interval_ends_ == NULL) {
  799. CostManagerClear(manager);
  800. return 0;
  801. }
  802. manager->interval_ends_size_ = size;
  803. }
  804. return 1;
  805. }
  806. // Given the distance_cost for pixel 'index', update the cost at pixel 'i' if it
  807. // is smaller than the previously computed value.
  808. static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, int index,
  809. double distance_cost) {
  810. int k = i - index;
  811. double cost_tmp;
  812. assert(k >= 0 && k < MAX_LENGTH);
  813. cost_tmp = distance_cost + manager->cost_cache_[k];
  814. if (manager->costs_[i] > cost_tmp) {
  815. manager->costs_[i] = (float)cost_tmp;
  816. manager->dist_array_[i] = k + 1;
  817. }
  818. }
  819. // Given the distance_cost for pixel 'index', update the cost for all the pixels
  820. // between 'start' and 'end' excluded.
  821. static WEBP_INLINE void UpdateCostPerInterval(CostManager* const manager,
  822. int start, int end, int index,
  823. double distance_cost) {
  824. int i;
  825. for (i = start; i < end; ++i) UpdateCost(manager, i, index, distance_cost);
  826. }
  827. // Given two intervals, make 'prev' be the previous one of 'next' in 'manager'.
  828. static WEBP_INLINE void ConnectIntervals(CostManager* const manager,
  829. CostInterval* const prev,
  830. CostInterval* const next) {
  831. if (prev != NULL) {
  832. prev->next_ = next;
  833. } else {
  834. manager->head_ = next;
  835. }
  836. if (next != NULL) next->previous_ = prev;
  837. }
  838. // Pop an interval in the manager.
  839. static WEBP_INLINE void PopInterval(CostManager* const manager,
  840. CostInterval* const interval) {
  841. CostInterval* const next = interval->next_;
  842. if (interval == NULL) return;
  843. ConnectIntervals(manager, interval->previous_, next);
  844. if (CostIntervalIsInFreeList(manager, interval)) {
  845. CostIntervalAddToFreeList(manager, interval);
  846. } else { // recycle regularly malloc'd intervals too
  847. interval->next_ = manager->recycled_intervals_;
  848. manager->recycled_intervals_ = interval;
  849. }
  850. --manager->count_;
  851. assert(manager->count_ >= 0);
  852. }
  853. // Update the cost at index i by going over all the stored intervals that
  854. // overlap with i.
  855. static WEBP_INLINE void UpdateCostPerIndex(CostManager* const manager, int i) {
  856. CostInterval* current = manager->head_;
  857. while (current != NULL && current->start_ <= i) {
  858. if (current->end_ <= i) {
  859. // We have an outdated interval, remove it.
  860. CostInterval* next = current->next_;
  861. PopInterval(manager, current);
  862. current = next;
  863. } else {
  864. UpdateCost(manager, i, current->index_, current->distance_cost_);
  865. current = current->next_;
  866. }
  867. }
  868. }
  869. // Given a current orphan interval and its previous interval, before
  870. // it was orphaned (which can be NULL), set it at the right place in the list
  871. // of intervals using the start_ ordering and the previous interval as a hint.
  872. static WEBP_INLINE void PositionOrphanInterval(CostManager* const manager,
  873. CostInterval* const current,
  874. CostInterval* previous) {
  875. assert(current != NULL);
  876. if (previous == NULL) previous = manager->head_;
  877. while (previous != NULL && current->start_ < previous->start_) {
  878. previous = previous->previous_;
  879. }
  880. while (previous != NULL && previous->next_ != NULL &&
  881. previous->next_->start_ < current->start_) {
  882. previous = previous->next_;
  883. }
  884. if (previous != NULL) {
  885. ConnectIntervals(manager, current, previous->next_);
  886. } else {
  887. ConnectIntervals(manager, current, manager->head_);
  888. }
  889. ConnectIntervals(manager, previous, current);
  890. }
  891. // Insert an interval in the list contained in the manager by starting at
  892. // interval_in as a hint. The intervals are sorted by start_ value.
  893. static WEBP_INLINE void InsertInterval(CostManager* const manager,
  894. CostInterval* const interval_in,
  895. double distance_cost, double lower,
  896. double upper, int index, int start,
  897. int end) {
  898. CostInterval* interval_new;
  899. if (IsCostCacheIntervalWritable(start, end) ||
  900. manager->count_ >= COST_CACHE_INTERVAL_SIZE_MAX) {
  901. // Write down the interval if it is too small.
  902. UpdateCostPerInterval(manager, start, end, index, distance_cost);
  903. return;
  904. }
  905. if (manager->free_intervals_ != NULL) {
  906. interval_new = manager->free_intervals_;
  907. manager->free_intervals_ = interval_new->next_;
  908. } else if (manager->recycled_intervals_ != NULL) {
  909. interval_new = manager->recycled_intervals_;
  910. manager->recycled_intervals_ = interval_new->next_;
  911. } else { // malloc for good
  912. interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new));
  913. if (interval_new == NULL) {
  914. // Write down the interval if we cannot create it.
  915. UpdateCostPerInterval(manager, start, end, index, distance_cost);
  916. return;
  917. }
  918. }
  919. interval_new->distance_cost_ = distance_cost;
  920. interval_new->lower_ = lower;
  921. interval_new->upper_ = upper;
  922. interval_new->index_ = index;
  923. interval_new->start_ = start;
  924. interval_new->end_ = end;
  925. PositionOrphanInterval(manager, interval_new, interval_in);
  926. ++manager->count_;
  927. }
  928. // When an interval has its start_ or end_ modified, it needs to be
  929. // repositioned in the linked list.
  930. static WEBP_INLINE void RepositionInterval(CostManager* const manager,
  931. CostInterval* const interval) {
  932. if (IsCostCacheIntervalWritable(interval->start_, interval->end_)) {
  933. // Maybe interval has been resized and is small enough to be removed.
  934. UpdateCostPerInterval(manager, interval->start_, interval->end_,
  935. interval->index_, interval->distance_cost_);
  936. PopInterval(manager, interval);
  937. return;
  938. }
  939. // Early exit if interval is at the right spot.
  940. if ((interval->previous_ == NULL ||
  941. interval->previous_->start_ <= interval->start_) &&
  942. (interval->next_ == NULL ||
  943. interval->start_ <= interval->next_->start_)) {
  944. return;
  945. }
  946. ConnectIntervals(manager, interval->previous_, interval->next_);
  947. PositionOrphanInterval(manager, interval, interval->previous_);
  948. }
  949. // Given a new cost interval defined by its start at index, its last value and
  950. // distance_cost, add its contributions to the previous intervals and costs.
  951. // If handling the interval or one of its subintervals becomes to heavy, its
  952. // contribution is added to the costs right away.
  953. static WEBP_INLINE void PushInterval(CostManager* const manager,
  954. double distance_cost, int index,
  955. int last) {
  956. size_t i;
  957. CostInterval* interval = manager->head_;
  958. CostInterval* interval_next;
  959. const CostCacheInterval* const cost_cache_intervals =
  960. manager->cache_intervals_;
  961. for (i = 0; i < manager->cache_intervals_size_ &&
  962. cost_cache_intervals[i].start_ < last;
  963. ++i) {
  964. // Define the intersection of the ith interval with the new one.
  965. int start = index + cost_cache_intervals[i].start_;
  966. const int end = index + (cost_cache_intervals[i].end_ > last
  967. ? last
  968. : cost_cache_intervals[i].end_);
  969. const double lower_in = cost_cache_intervals[i].lower_;
  970. const double upper_in = cost_cache_intervals[i].upper_;
  971. const double lower_full_in = distance_cost + lower_in;
  972. const double upper_full_in = distance_cost + upper_in;
  973. if (cost_cache_intervals[i].do_write_) {
  974. UpdateCostPerInterval(manager, start, end, index, distance_cost);
  975. continue;
  976. }
  977. for (; interval != NULL && interval->start_ < end && start < end;
  978. interval = interval_next) {
  979. const double lower_full_interval =
  980. interval->distance_cost_ + interval->lower_;
  981. const double upper_full_interval =
  982. interval->distance_cost_ + interval->upper_;
  983. interval_next = interval->next_;
  984. // Make sure we have some overlap
  985. if (start >= interval->end_) continue;
  986. if (lower_full_in >= upper_full_interval) {
  987. // When intervals are represented, the lower, the better.
  988. // [**********************************************************]
  989. // start end
  990. // [----------------------------------]
  991. // interval->start_ interval->end_
  992. // If we are worse than what we already have, add whatever we have so
  993. // far up to interval.
  994. const int start_new = interval->end_;
  995. InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
  996. index, start, interval->start_);
  997. start = start_new;
  998. continue;
  999. }
  1000. // We know the two intervals intersect.
  1001. if (upper_full_in >= lower_full_interval) {
  1002. // There is no clear cut on which is best, so let's keep both.
  1003. // [*********[*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*]***********]
  1004. // start interval->start_ interval->end_ end
  1005. // OR
  1006. // [*********[*-*-*-*-*-*-*-*-*-*-*-]----------------------]
  1007. // start interval->start_ end interval->end_
  1008. const int end_new = (interval->end_ <= end) ? interval->end_ : end;
  1009. InsertInterval(manager, interval, distance_cost, lower_in, upper_in,
  1010. index, start, end_new);
  1011. start = end_new;
  1012. } else if (start <= interval->start_ && interval->end_ <= end) {
  1013. // [----------------------------------]
  1014. // interval->start_ interval->end_
  1015. // [**************************************************************]
  1016. // start end
  1017. // We can safely remove the old interval as it is fully included.
  1018. PopInterval(manager, interval);
  1019. } else {
  1020. if (interval->start_ <= start && end <= interval->end_) {
  1021. // [--------------------------------------------------------------]
  1022. // interval->start_ interval->end_
  1023. // [*****************************]
  1024. // start end
  1025. // We have to split the old interval as it fully contains the new one.
  1026. const int end_original = interval->end_;
  1027. interval->end_ = start;
  1028. InsertInterval(manager, interval, interval->distance_cost_,
  1029. interval->lower_, interval->upper_, interval->index_,
  1030. end, end_original);
  1031. } else if (interval->start_ < start) {
  1032. // [------------------------------------]
  1033. // interval->start_ interval->end_
  1034. // [*****************************]
  1035. // start end
  1036. interval->end_ = start;
  1037. } else {
  1038. // [------------------------------------]
  1039. // interval->start_ interval->end_
  1040. // [*****************************]
  1041. // start end
  1042. interval->start_ = end;
  1043. }
  1044. // The interval has been modified, we need to reposition it or write it.
  1045. RepositionInterval(manager, interval);
  1046. }
  1047. }
  1048. // Insert the remaining interval from start to end.
  1049. InsertInterval(manager, interval, distance_cost, lower_in, upper_in, index,
  1050. start, end);
  1051. }
  1052. }
  1053. static int BackwardReferencesHashChainDistanceOnly(
  1054. int xsize, int ysize, const uint32_t* const argb, int quality,
  1055. int cache_bits, const VP8LHashChain* const hash_chain,
  1056. VP8LBackwardRefs* const refs, uint16_t* const dist_array) {
  1057. int i;
  1058. int ok = 0;
  1059. int cc_init = 0;
  1060. const int pix_count = xsize * ysize;
  1061. const int use_color_cache = (cache_bits > 0);
  1062. const size_t literal_array_size = sizeof(double) *
  1063. (NUM_LITERAL_CODES + NUM_LENGTH_CODES +
  1064. ((cache_bits > 0) ? (1 << cache_bits) : 0));
  1065. const size_t cost_model_size = sizeof(CostModel) + literal_array_size;
  1066. CostModel* const cost_model =
  1067. (CostModel*)WebPSafeCalloc(1ULL, cost_model_size);
  1068. VP8LColorCache hashers;
  1069. const int skip_length = 32 + quality;
  1070. const int skip_min_distance_code = 2;
  1071. CostManager* cost_manager =
  1072. (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager));
  1073. if (cost_model == NULL || cost_manager == NULL) goto Error;
  1074. cost_model->literal_ = (double*)(cost_model + 1);
  1075. if (use_color_cache) {
  1076. cc_init = VP8LColorCacheInit(&hashers, cache_bits);
  1077. if (!cc_init) goto Error;
  1078. }
  1079. if (!CostModelBuild(cost_model, cache_bits, refs)) {
  1080. goto Error;
  1081. }
  1082. if (!CostManagerInit(cost_manager, dist_array, pix_count, cost_model)) {
  1083. goto Error;
  1084. }
  1085. // We loop one pixel at a time, but store all currently best points to
  1086. // non-processed locations from this point.
  1087. dist_array[0] = 0;
  1088. // Add first pixel as literal.
  1089. AddSingleLiteralWithCostModel(argb + 0, &hashers, cost_model, 0,
  1090. use_color_cache, 0.0, cost_manager->costs_,
  1091. dist_array);
  1092. for (i = 1; i < pix_count - 1; ++i) {
  1093. int offset = 0, len = 0;
  1094. double prev_cost = cost_manager->costs_[i - 1];
  1095. HashChainFindCopy(hash_chain, i, &offset, &len);
  1096. if (len >= MIN_LENGTH) {
  1097. const int code = DistanceToPlaneCode(xsize, offset);
  1098. const double offset_cost = GetDistanceCost(cost_model, code);
  1099. const int first_i = i;
  1100. int j_max = 0, interval_ends_index = 0;
  1101. const int is_offset_zero = (offset_cost == 0.);
  1102. if (!is_offset_zero) {
  1103. j_max = (int)ceil(
  1104. (cost_manager->max_cost_cache_ - cost_manager->min_cost_cache_) /
  1105. offset_cost);
  1106. if (j_max < 1) {
  1107. j_max = 1;
  1108. } else if (j_max > cost_manager->interval_ends_size_ - 1) {
  1109. // This could only happen in the case of MAX_LENGTH.
  1110. j_max = cost_manager->interval_ends_size_ - 1;
  1111. }
  1112. } // else j_max is unused anyway.
  1113. // Instead of considering all contributions from a pixel i by calling:
  1114. // PushInterval(cost_manager, prev_cost + offset_cost, i, len);
  1115. // we optimize these contributions in case offset_cost stays the same for
  1116. // consecutive pixels. This describes a set of pixels similar to a
  1117. // previous set (e.g. constant color regions).
  1118. for (; i < pix_count - 1; ++i) {
  1119. int offset_next, len_next;
  1120. prev_cost = cost_manager->costs_[i - 1];
  1121. if (is_offset_zero) {
  1122. // No optimization can be made so we just push all of the
  1123. // contributions from i.
  1124. PushInterval(cost_manager, prev_cost, i, len);
  1125. } else {
  1126. // j_max is chosen as the smallest j such that:
  1127. // max of cost_cache_ < j*offset cost + min of cost_cache_
  1128. // Therefore, the pixel influenced by i-j_max, cannot be influenced
  1129. // by i. Only the costs after the end of what i contributed need to be
  1130. // updated. cost_manager->interval_ends_ is a circular buffer that
  1131. // stores those ends.
  1132. const double distance_cost = prev_cost + offset_cost;
  1133. int j = cost_manager->interval_ends_[interval_ends_index];
  1134. if (i - first_i <= j_max ||
  1135. !IsCostCacheIntervalWritable(j, i + len)) {
  1136. PushInterval(cost_manager, distance_cost, i, len);
  1137. } else {
  1138. for (; j < i + len; ++j) {
  1139. UpdateCost(cost_manager, j, i, distance_cost);
  1140. }
  1141. }
  1142. // Store the new end in the circular buffer.
  1143. assert(interval_ends_index < cost_manager->interval_ends_size_);
  1144. cost_manager->interval_ends_[interval_ends_index] = i + len;
  1145. if (++interval_ends_index > j_max) interval_ends_index = 0;
  1146. }
  1147. // Check whether i is the last pixel to consider, as it is handled
  1148. // differently.
  1149. if (i + 1 >= pix_count - 1) break;
  1150. HashChainFindCopy(hash_chain, i + 1, &offset_next, &len_next);
  1151. if (offset_next != offset) break;
  1152. len = len_next;
  1153. UpdateCostPerIndex(cost_manager, i);
  1154. AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
  1155. use_color_cache, prev_cost,
  1156. cost_manager->costs_, dist_array);
  1157. }
  1158. // Submit the last pixel.
  1159. UpdateCostPerIndex(cost_manager, i + 1);
  1160. // This if is for speedup only. It roughly doubles the speed, and
  1161. // makes compression worse by .1 %.
  1162. if (len >= skip_length && code <= skip_min_distance_code) {
  1163. // Long copy for short distances, let's skip the middle
  1164. // lookups for better copies.
  1165. // 1) insert the hashes.
  1166. if (use_color_cache) {
  1167. int k;
  1168. for (k = 0; k < len; ++k) {
  1169. VP8LColorCacheInsert(&hashers, argb[i + k]);
  1170. }
  1171. }
  1172. // 2) jump.
  1173. {
  1174. const int i_next = i + len - 1; // for loop does ++i, thus -1 here.
  1175. for (; i <= i_next; ++i) UpdateCostPerIndex(cost_manager, i + 1);
  1176. i = i_next;
  1177. }
  1178. goto next_symbol;
  1179. }
  1180. if (len > MIN_LENGTH) {
  1181. int code_min_length;
  1182. double cost_total;
  1183. offset = HashChainFindOffset(hash_chain, i);
  1184. code_min_length = DistanceToPlaneCode(xsize, offset);
  1185. cost_total = prev_cost +
  1186. GetDistanceCost(cost_model, code_min_length) +
  1187. GetLengthCost(cost_model, 1);
  1188. if (cost_manager->costs_[i + 1] > cost_total) {
  1189. cost_manager->costs_[i + 1] = (float)cost_total;
  1190. dist_array[i + 1] = 2;
  1191. }
  1192. }
  1193. } else { // len < MIN_LENGTH
  1194. UpdateCostPerIndex(cost_manager, i + 1);
  1195. }
  1196. AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i,
  1197. use_color_cache, prev_cost,
  1198. cost_manager->costs_, dist_array);
  1199. next_symbol: ;
  1200. }
  1201. // Handle the last pixel.
  1202. if (i == (pix_count - 1)) {
  1203. AddSingleLiteralWithCostModel(
  1204. argb + i, &hashers, cost_model, i, use_color_cache,
  1205. cost_manager->costs_[pix_count - 2], cost_manager->costs_, dist_array);
  1206. }
  1207. ok = !refs->error_;
  1208. Error:
  1209. if (cc_init) VP8LColorCacheClear(&hashers);
  1210. CostManagerClear(cost_manager);
  1211. WebPSafeFree(cost_model);
  1212. WebPSafeFree(cost_manager);
  1213. return ok;
  1214. }
  1215. // We pack the path at the end of *dist_array and return
  1216. // a pointer to this part of the array. Example:
  1217. // dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232]
  1218. static void TraceBackwards(uint16_t* const dist_array,
  1219. int dist_array_size,
  1220. uint16_t** const chosen_path,
  1221. int* const chosen_path_size) {
  1222. uint16_t* path = dist_array + dist_array_size;
  1223. uint16_t* cur = dist_array + dist_array_size - 1;
  1224. while (cur >= dist_array) {
  1225. const int k = *cur;
  1226. --path;
  1227. *path = k;
  1228. cur -= k;
  1229. }
  1230. *chosen_path = path;
  1231. *chosen_path_size = (int)(dist_array + dist_array_size - path);
  1232. }
  1233. static int BackwardReferencesHashChainFollowChosenPath(
  1234. const uint32_t* const argb, int cache_bits,
  1235. const uint16_t* const chosen_path, int chosen_path_size,
  1236. const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) {
  1237. const int use_color_cache = (cache_bits > 0);
  1238. int ix;
  1239. int i = 0;
  1240. int ok = 0;
  1241. int cc_init = 0;
  1242. VP8LColorCache hashers;
  1243. if (use_color_cache) {
  1244. cc_init = VP8LColorCacheInit(&hashers, cache_bits);
  1245. if (!cc_init) goto Error;
  1246. }
  1247. ClearBackwardRefs(refs);
  1248. for (ix = 0; ix < chosen_path_size; ++ix) {
  1249. const int len = chosen_path[ix];
  1250. if (len != 1) {
  1251. int k;
  1252. const int offset = HashChainFindOffset(hash_chain, i);
  1253. BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len));
  1254. if (use_color_cache) {
  1255. for (k = 0; k < len; ++k) {
  1256. VP8LColorCacheInsert(&hashers, argb[i + k]);
  1257. }
  1258. }
  1259. i += len;
  1260. } else {
  1261. PixOrCopy v;
  1262. if (use_color_cache && VP8LColorCacheContains(&hashers, argb[i])) {
  1263. // push pixel as a color cache index
  1264. const int idx = VP8LColorCacheGetIndex(&hashers, argb[i]);
  1265. v = PixOrCopyCreateCacheIdx(idx);
  1266. } else {
  1267. if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]);
  1268. v = PixOrCopyCreateLiteral(argb[i]);
  1269. }
  1270. BackwardRefsCursorAdd(refs, v);
  1271. ++i;
  1272. }
  1273. }
  1274. ok = !refs->error_;
  1275. Error:
  1276. if (cc_init) VP8LColorCacheClear(&hashers);
  1277. return ok;
  1278. }
  1279. // Returns 1 on success.
  1280. static int BackwardReferencesTraceBackwards(
  1281. int xsize, int ysize, const uint32_t* const argb, int quality,
  1282. int cache_bits, const VP8LHashChain* const hash_chain,
  1283. VP8LBackwardRefs* const refs) {
  1284. int ok = 0;
  1285. const int dist_array_size = xsize * ysize;
  1286. uint16_t* chosen_path = NULL;
  1287. int chosen_path_size = 0;
  1288. uint16_t* dist_array =
  1289. (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array));
  1290. if (dist_array == NULL) goto Error;
  1291. if (!BackwardReferencesHashChainDistanceOnly(
  1292. xsize, ysize, argb, quality, cache_bits, hash_chain,
  1293. refs, dist_array)) {
  1294. goto Error;
  1295. }
  1296. TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size);
  1297. if (!BackwardReferencesHashChainFollowChosenPath(
  1298. argb, cache_bits, chosen_path, chosen_path_size, hash_chain, refs)) {
  1299. goto Error;
  1300. }
  1301. ok = 1;
  1302. Error:
  1303. WebPSafeFree(dist_array);
  1304. return ok;
  1305. }
  1306. static void BackwardReferences2DLocality(int xsize,
  1307. const VP8LBackwardRefs* const refs) {
  1308. VP8LRefsCursor c = VP8LRefsCursorInit(refs);
  1309. while (VP8LRefsCursorOk(&c)) {
  1310. if (PixOrCopyIsCopy(c.cur_pos)) {
  1311. const int dist = c.cur_pos->argb_or_distance;
  1312. const int transformed_dist = DistanceToPlaneCode(xsize, dist);
  1313. c.cur_pos->argb_or_distance = transformed_dist;
  1314. }
  1315. VP8LRefsCursorNext(&c);
  1316. }
  1317. }
  1318. // Returns entropy for the given cache bits.
  1319. static double ComputeCacheEntropy(const uint32_t* argb,
  1320. const VP8LBackwardRefs* const refs,
  1321. int cache_bits) {
  1322. const int use_color_cache = (cache_bits > 0);
  1323. int cc_init = 0;
  1324. double entropy = MAX_ENTROPY;
  1325. const double kSmallPenaltyForLargeCache = 4.0;
  1326. VP8LColorCache hashers;
  1327. VP8LRefsCursor c = VP8LRefsCursorInit(refs);
  1328. VP8LHistogram* histo = VP8LAllocateHistogram(cache_bits);
  1329. if (histo == NULL) goto Error;
  1330. if (use_color_cache) {
  1331. cc_init = VP8LColorCacheInit(&hashers, cache_bits);
  1332. if (!cc_init) goto Error;
  1333. }
  1334. if (!use_color_cache) {
  1335. while (VP8LRefsCursorOk(&c)) {
  1336. VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos);
  1337. VP8LRefsCursorNext(&c);
  1338. }
  1339. } else {
  1340. while (VP8LRefsCursorOk(&c)) {
  1341. const PixOrCopy* const v = c.cur_pos;
  1342. if (PixOrCopyIsLiteral(v)) {
  1343. const uint32_t pix = *argb++;
  1344. const uint32_t key = VP8LColorCacheGetIndex(&hashers, pix);
  1345. if (VP8LColorCacheLookup(&hashers, key) == pix) {
  1346. ++histo->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key];
  1347. } else {
  1348. VP8LColorCacheSet(&hashers, key, pix);
  1349. ++histo->blue_[pix & 0xff];
  1350. ++histo->literal_[(pix >> 8) & 0xff];
  1351. ++histo->red_[(pix >> 16) & 0xff];
  1352. ++histo->alpha_[pix >> 24];
  1353. }
  1354. } else {
  1355. int len = PixOrCopyLength(v);
  1356. int code, extra_bits;
  1357. VP8LPrefixEncodeBits(len, &code, &extra_bits);
  1358. ++histo->literal_[NUM_LITERAL_CODES + code];
  1359. VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits);
  1360. ++histo->distance_[code];
  1361. do {
  1362. VP8LColorCacheInsert(&hashers, *argb++);
  1363. } while(--len != 0);
  1364. }
  1365. VP8LRefsCursorNext(&c);
  1366. }
  1367. }
  1368. entropy = VP8LHistogramEstimateBits(histo) +
  1369. kSmallPenaltyForLargeCache * cache_bits;
  1370. Error:
  1371. if (cc_init) VP8LColorCacheClear(&hashers);
  1372. VP8LFreeHistogram(histo);
  1373. return entropy;
  1374. }
  1375. // Evaluate optimal cache bits for the local color cache.
  1376. // The input *best_cache_bits sets the maximum cache bits to use (passing 0
  1377. // implies disabling the local color cache). The local color cache is also
  1378. // disabled for the lower (<= 25) quality.
  1379. // Returns 0 in case of memory error.
  1380. static int CalculateBestCacheSize(const uint32_t* const argb,
  1381. int xsize, int ysize, int quality,
  1382. const VP8LHashChain* const hash_chain,
  1383. VP8LBackwardRefs* const refs,
  1384. int* const lz77_computed,
  1385. int* const best_cache_bits) {
  1386. int eval_low = 1;
  1387. int eval_high = 1;
  1388. double entropy_low = MAX_ENTROPY;
  1389. double entropy_high = MAX_ENTROPY;
  1390. const double cost_mul = 5e-4;
  1391. int cache_bits_low = 0;
  1392. int cache_bits_high = (quality <= 25) ? 0 : *best_cache_bits;
  1393. assert(cache_bits_high <= MAX_COLOR_CACHE_BITS);
  1394. *lz77_computed = 0;
  1395. if (cache_bits_high == 0) {
  1396. *best_cache_bits = 0;
  1397. // Local color cache is disabled.
  1398. return 1;
  1399. }
  1400. if (!BackwardReferencesLz77(xsize, ysize, argb, cache_bits_low, hash_chain,
  1401. refs)) {
  1402. return 0;
  1403. }
  1404. // Do a binary search to find the optimal entropy for cache_bits.
  1405. while (eval_low || eval_high) {
  1406. if (eval_low) {
  1407. entropy_low = ComputeCacheEntropy(argb, refs, cache_bits_low);
  1408. entropy_low += entropy_low * cache_bits_low * cost_mul;
  1409. eval_low = 0;
  1410. }
  1411. if (eval_high) {
  1412. entropy_high = ComputeCacheEntropy(argb, refs, cache_bits_high);
  1413. entropy_high += entropy_high * cache_bits_high * cost_mul;
  1414. eval_high = 0;
  1415. }
  1416. if (entropy_high < entropy_low) {
  1417. const int prev_cache_bits_low = cache_bits_low;
  1418. *best_cache_bits = cache_bits_high;
  1419. cache_bits_low = (cache_bits_low + cache_bits_high) / 2;
  1420. if (cache_bits_low != prev_cache_bits_low) eval_low = 1;
  1421. } else {
  1422. *best_cache_bits = cache_bits_low;
  1423. cache_bits_high = (cache_bits_low + cache_bits_high) / 2;
  1424. if (cache_bits_high != cache_bits_low) eval_high = 1;
  1425. }
  1426. }
  1427. *lz77_computed = 1;
  1428. return 1;
  1429. }
  1430. // Update (in-place) backward references for specified cache_bits.
  1431. static int BackwardRefsWithLocalCache(const uint32_t* const argb,
  1432. int cache_bits,
  1433. VP8LBackwardRefs* const refs) {
  1434. int pixel_index = 0;
  1435. VP8LColorCache hashers;
  1436. VP8LRefsCursor c = VP8LRefsCursorInit(refs);
  1437. if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0;
  1438. while (VP8LRefsCursorOk(&c)) {
  1439. PixOrCopy* const v = c.cur_pos;
  1440. if (PixOrCopyIsLiteral(v)) {
  1441. const uint32_t argb_literal = v->argb_or_distance;
  1442. if (VP8LColorCacheContains(&hashers, argb_literal)) {
  1443. const int ix = VP8LColorCacheGetIndex(&hashers, argb_literal);
  1444. *v = PixOrCopyCreateCacheIdx(ix);
  1445. } else {
  1446. VP8LColorCacheInsert(&hashers, argb_literal);
  1447. }
  1448. ++pixel_index;
  1449. } else {
  1450. // refs was created without local cache, so it can not have cache indexes.
  1451. int k;
  1452. assert(PixOrCopyIsCopy(v));
  1453. for (k = 0; k < v->len; ++k) {
  1454. VP8LColorCacheInsert(&hashers, argb[pixel_index++]);
  1455. }
  1456. }
  1457. VP8LRefsCursorNext(&c);
  1458. }
  1459. VP8LColorCacheClear(&hashers);
  1460. return 1;
  1461. }
  1462. static VP8LBackwardRefs* GetBackwardReferencesLowEffort(
  1463. int width, int height, const uint32_t* const argb,
  1464. int* const cache_bits, const VP8LHashChain* const hash_chain,
  1465. VP8LBackwardRefs refs_array[2]) {
  1466. VP8LBackwardRefs* refs_lz77 = &refs_array[0];
  1467. *cache_bits = 0;
  1468. if (!BackwardReferencesLz77(width, height, argb, 0, hash_chain, refs_lz77)) {
  1469. return NULL;
  1470. }
  1471. BackwardReferences2DLocality(width, refs_lz77);
  1472. return refs_lz77;
  1473. }
  1474. static VP8LBackwardRefs* GetBackwardReferences(
  1475. int width, int height, const uint32_t* const argb, int quality,
  1476. int* const cache_bits, const VP8LHashChain* const hash_chain,
  1477. VP8LBackwardRefs refs_array[2]) {
  1478. int lz77_is_useful;
  1479. int lz77_computed;
  1480. double bit_cost_lz77, bit_cost_rle;
  1481. VP8LBackwardRefs* best = NULL;
  1482. VP8LBackwardRefs* refs_lz77 = &refs_array[0];
  1483. VP8LBackwardRefs* refs_rle = &refs_array[1];
  1484. VP8LHistogram* histo = NULL;
  1485. if (!CalculateBestCacheSize(argb, width, height, quality, hash_chain,
  1486. refs_lz77, &lz77_computed, cache_bits)) {
  1487. goto Error;
  1488. }
  1489. if (lz77_computed) {
  1490. // Transform refs_lz77 for the optimized cache_bits.
  1491. if (*cache_bits > 0) {
  1492. if (!BackwardRefsWithLocalCache(argb, *cache_bits, refs_lz77)) {
  1493. goto Error;
  1494. }
  1495. }
  1496. } else {
  1497. if (!BackwardReferencesLz77(width, height, argb, *cache_bits, hash_chain,
  1498. refs_lz77)) {
  1499. goto Error;
  1500. }
  1501. }
  1502. if (!BackwardReferencesRle(width, height, argb, *cache_bits, refs_rle)) {
  1503. goto Error;
  1504. }
  1505. histo = VP8LAllocateHistogram(*cache_bits);
  1506. if (histo == NULL) goto Error;
  1507. {
  1508. // Evaluate LZ77 coding.
  1509. VP8LHistogramCreate(histo, refs_lz77, *cache_bits);
  1510. bit_cost_lz77 = VP8LHistogramEstimateBits(histo);
  1511. // Evaluate RLE coding.
  1512. VP8LHistogramCreate(histo, refs_rle, *cache_bits);
  1513. bit_cost_rle = VP8LHistogramEstimateBits(histo);
  1514. // Decide if LZ77 is useful.
  1515. lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
  1516. }
  1517. // Choose appropriate backward reference.
  1518. if (lz77_is_useful) {
  1519. // TraceBackwards is costly. Don't execute it at lower quality.
  1520. const int try_lz77_trace_backwards = (quality >= 25);
  1521. best = refs_lz77; // default guess: lz77 is better
  1522. if (try_lz77_trace_backwards) {
  1523. VP8LBackwardRefs* const refs_trace = refs_rle;
  1524. if (!VP8LBackwardRefsCopy(refs_lz77, refs_trace)) {
  1525. best = NULL;
  1526. goto Error;
  1527. }
  1528. if (BackwardReferencesTraceBackwards(width, height, argb, quality,
  1529. *cache_bits, hash_chain,
  1530. refs_trace)) {
  1531. double bit_cost_trace;
  1532. // Evaluate LZ77 coding.
  1533. VP8LHistogramCreate(histo, refs_trace, *cache_bits);
  1534. bit_cost_trace = VP8LHistogramEstimateBits(histo);
  1535. if (bit_cost_trace < bit_cost_lz77) {
  1536. best = refs_trace;
  1537. }
  1538. }
  1539. }
  1540. } else {
  1541. best = refs_rle;
  1542. }
  1543. BackwardReferences2DLocality(width, best);
  1544. Error:
  1545. VP8LFreeHistogram(histo);
  1546. return best;
  1547. }
  1548. VP8LBackwardRefs* VP8LGetBackwardReferences(
  1549. int width, int height, const uint32_t* const argb, int quality,
  1550. int low_effort, int* const cache_bits,
  1551. const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[2]) {
  1552. if (low_effort) {
  1553. return GetBackwardReferencesLowEffort(width, height, argb, cache_bits,
  1554. hash_chain, refs_array);
  1555. } else {
  1556. return GetBackwardReferences(width, height, argb, quality, cache_bits,
  1557. hash_chain, refs_array);
  1558. }
  1559. }