Path: blob/master/thirdparty/libwebp/src/utils/huffman_utils.c
9912 views
// Copyright 2012 Google Inc. All Rights Reserved.1//2// Use of this source code is governed by a BSD-style license3// that can be found in the COPYING file in the root of the source4// tree. An additional intellectual property rights grant can be found5// in the file PATENTS. All contributing project authors may6// be found in the AUTHORS file in the root of the source tree.7// -----------------------------------------------------------------------------8//9// Utilities for building and looking up Huffman trees.10//11// Author: Urvang Joshi ([email protected])1213#include <assert.h>14#include <stdlib.h>15#include <string.h>16#include "src/utils/huffman_utils.h"17#include "src/utils/utils.h"18#include "src/webp/format_constants.h"1920// Huffman data read via DecodeImageStream is represented in two (red and green)21// bytes.22#define MAX_HTREE_GROUPS 0x100002324HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) {25HTreeGroup* const htree_groups =26(HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups));27if (htree_groups == NULL) {28return NULL;29}30assert(num_htree_groups <= MAX_HTREE_GROUPS);31return htree_groups;32}3334void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) {35if (htree_groups != NULL) {36WebPSafeFree(htree_groups);37}38}3940// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the41// bit-wise reversal of the len least significant bits of key.42static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) {43uint32_t step = 1 << (len - 1);44while (key & step) {45step >>= 1;46}47return step ? (key & (step - 1)) + step : key;48}4950// Stores code in table[0], table[step], table[2*step], ..., table[end].51// Assumes that end is an integer multiple of step.52static WEBP_INLINE void ReplicateValue(HuffmanCode* table,53int step, int end,54HuffmanCode code) {55assert(end % step == 0);56do {57end -= step;58table[end] = code;59} while (end > 0);60}6162// Returns the table width of the next 2nd level table. count is the histogram63// of bit lengths for the remaining symbols, len is the code length of the next64// processed symbol65static WEBP_INLINE int NextTableBitSize(const int* const count,66int len, int root_bits) {67int left = 1 << (len - root_bits);68while (len < MAX_ALLOWED_CODE_LENGTH) {69left -= count[len];70if (left <= 0) break;71++len;72left <<= 1;73}74return len - root_bits;75}7677// sorted[code_lengths_size] is a pre-allocated array for sorting symbols78// by code length.79static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,80const int code_lengths[], int code_lengths_size,81uint16_t sorted[]) {82HuffmanCode* table = root_table; // next available space in table83int total_size = 1 << root_bits; // total size root table + 2nd level table84int len; // current code length85int symbol; // symbol index in original or sorted table86// number of codes of each length:87int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };88// offsets in sorted table for each length:89int offset[MAX_ALLOWED_CODE_LENGTH + 1];9091assert(code_lengths_size != 0);92assert(code_lengths != NULL);93assert((root_table != NULL && sorted != NULL) ||94(root_table == NULL && sorted == NULL));95assert(root_bits > 0);9697// Build histogram of code lengths.98for (symbol = 0; symbol < code_lengths_size; ++symbol) {99if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) {100return 0;101}102++count[code_lengths[symbol]];103}104105// Error, all code lengths are zeros.106if (count[0] == code_lengths_size) {107return 0;108}109110// Generate offsets into sorted symbol table by code length.111offset[1] = 0;112for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) {113if (count[len] > (1 << len)) {114return 0;115}116offset[len + 1] = offset[len] + count[len];117}118119// Sort symbols by length, by symbol order within each length.120for (symbol = 0; symbol < code_lengths_size; ++symbol) {121const int symbol_code_length = code_lengths[symbol];122if (code_lengths[symbol] > 0) {123if (sorted != NULL) {124if(offset[symbol_code_length] >= code_lengths_size) {125return 0;126}127sorted[offset[symbol_code_length]++] = symbol;128} else {129offset[symbol_code_length]++;130}131}132}133134// Special case code with only one value.135if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) {136if (sorted != NULL) {137HuffmanCode code;138code.bits = 0;139code.value = (uint16_t)sorted[0];140ReplicateValue(table, 1, total_size, code);141}142return total_size;143}144145{146int step; // step size to replicate values in current table147uint32_t low = 0xffffffffu; // low bits for current root entry148uint32_t mask = total_size - 1; // mask for low bits149uint32_t key = 0; // reversed prefix code150int num_nodes = 1; // number of Huffman tree nodes151int num_open = 1; // number of open branches in current tree level152int table_bits = root_bits; // key length of current table153int table_size = 1 << table_bits; // size of current table154symbol = 0;155// Fill in root table.156for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) {157num_open <<= 1;158num_nodes += num_open;159num_open -= count[len];160if (num_open < 0) {161return 0;162}163if (root_table == NULL) continue;164for (; count[len] > 0; --count[len]) {165HuffmanCode code;166code.bits = (uint8_t)len;167code.value = (uint16_t)sorted[symbol++];168ReplicateValue(&table[key], step, table_size, code);169key = GetNextKey(key, len);170}171}172173// Fill in 2nd level tables and add pointers to root table.174for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH;175++len, step <<= 1) {176num_open <<= 1;177num_nodes += num_open;178num_open -= count[len];179if (num_open < 0) {180return 0;181}182for (; count[len] > 0; --count[len]) {183HuffmanCode code;184if ((key & mask) != low) {185if (root_table != NULL) table += table_size;186table_bits = NextTableBitSize(count, len, root_bits);187table_size = 1 << table_bits;188total_size += table_size;189low = key & mask;190if (root_table != NULL) {191root_table[low].bits = (uint8_t)(table_bits + root_bits);192root_table[low].value = (uint16_t)((table - root_table) - low);193}194}195if (root_table != NULL) {196code.bits = (uint8_t)(len - root_bits);197code.value = (uint16_t)sorted[symbol++];198ReplicateValue(&table[key >> root_bits], step, table_size, code);199}200key = GetNextKey(key, len);201}202}203204// Check if tree is full.205if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {206return 0;207}208}209210return total_size;211}212213// Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits).214// More commonly, the value is around ~280.215#define MAX_CODE_LENGTHS_SIZE \216((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)217// Cut-off value for switching between heap and stack allocation.218#define SORTED_SIZE_CUTOFF 512219int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,220const int code_lengths[], int code_lengths_size) {221const int total_size =222BuildHuffmanTable(NULL, root_bits, code_lengths, code_lengths_size, NULL);223assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);224if (total_size == 0 || root_table == NULL) return total_size;225226if (root_table->curr_segment->curr_table + total_size >=227root_table->curr_segment->start + root_table->curr_segment->size) {228// If 'root_table' does not have enough memory, allocate a new segment.229// The available part of root_table->curr_segment is left unused because we230// need a contiguous buffer.231const int segment_size = root_table->curr_segment->size;232struct HuffmanTablesSegment* next =233(HuffmanTablesSegment*)WebPSafeMalloc(1, sizeof(*next));234if (next == NULL) return 0;235// Fill the new segment.236// We need at least 'total_size' but if that value is small, it is better to237// allocate a big chunk to prevent more allocations later. 'segment_size' is238// therefore chosen (any other arbitrary value could be chosen).239next->size = total_size > segment_size ? total_size : segment_size;240next->start =241(HuffmanCode*)WebPSafeMalloc(next->size, sizeof(*next->start));242if (next->start == NULL) {243WebPSafeFree(next);244return 0;245}246next->curr_table = next->start;247next->next = NULL;248// Point to the new segment.249root_table->curr_segment->next = next;250root_table->curr_segment = next;251}252if (code_lengths_size <= SORTED_SIZE_CUTOFF) {253// use local stack-allocated array.254uint16_t sorted[SORTED_SIZE_CUTOFF];255BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,256code_lengths, code_lengths_size, sorted);257} else { // rare case. Use heap allocation.258uint16_t* const sorted =259(uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));260if (sorted == NULL) return 0;261BuildHuffmanTable(root_table->curr_segment->curr_table, root_bits,262code_lengths, code_lengths_size, sorted);263WebPSafeFree(sorted);264}265return total_size;266}267268int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) {269// Have 'segment' point to the first segment for now, 'root'.270HuffmanTablesSegment* const root = &huffman_tables->root;271huffman_tables->curr_segment = root;272root->next = NULL;273// Allocate root.274root->start = (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start));275if (root->start == NULL) return 0;276root->curr_table = root->start;277root->size = size;278return 1;279}280281void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables) {282HuffmanTablesSegment *current, *next;283if (huffman_tables == NULL) return;284// Free the root node.285current = &huffman_tables->root;286next = current->next;287WebPSafeFree(current->start);288current->start = NULL;289current->next = NULL;290current = next;291// Free the following nodes.292while (current != NULL) {293next = current->next;294WebPSafeFree(current->start);295WebPSafeFree(current);296current = next;297}298}299300301