1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2006 Konstantin Shishkov 3cabdff1aSopenharmony_ci * Copyright (c) 2007 Loren Merritt 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * huffman tree builder and VLC generator 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include <stdint.h> 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "libavutil/error.h" 30cabdff1aSopenharmony_ci#include "libavutil/log.h" 31cabdff1aSopenharmony_ci#include "libavutil/macros.h" 32cabdff1aSopenharmony_ci#include "libavutil/mem.h" 33cabdff1aSopenharmony_ci#include "libavutil/qsort.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_ci#include "huffman.h" 36cabdff1aSopenharmony_ci#include "vlc.h" 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci/* symbol for Huffman tree node */ 39cabdff1aSopenharmony_ci#define HNODE -1 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_citypedef struct HeapElem { 42cabdff1aSopenharmony_ci uint64_t val; 43cabdff1aSopenharmony_ci int name; 44cabdff1aSopenharmony_ci} HeapElem; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_cistatic void heap_sift(HeapElem *h, int root, int size) 47cabdff1aSopenharmony_ci{ 48cabdff1aSopenharmony_ci while (root * 2 + 1 < size) { 49cabdff1aSopenharmony_ci int child = root * 2 + 1; 50cabdff1aSopenharmony_ci if (child < size - 1 && h[child].val > h[child+1].val) 51cabdff1aSopenharmony_ci child++; 52cabdff1aSopenharmony_ci if (h[root].val > h[child].val) { 53cabdff1aSopenharmony_ci FFSWAP(HeapElem, h[root], h[child]); 54cabdff1aSopenharmony_ci root = child; 55cabdff1aSopenharmony_ci } else 56cabdff1aSopenharmony_ci break; 57cabdff1aSopenharmony_ci } 58cabdff1aSopenharmony_ci} 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ciint ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats, int stats_size, int skip0) 61cabdff1aSopenharmony_ci{ 62cabdff1aSopenharmony_ci HeapElem *h = av_malloc_array(sizeof(*h), stats_size); 63cabdff1aSopenharmony_ci int *up = av_malloc_array(sizeof(*up) * 2, stats_size); 64cabdff1aSopenharmony_ci uint8_t *len = av_malloc_array(sizeof(*len) * 2, stats_size); 65cabdff1aSopenharmony_ci uint16_t *map= av_malloc_array(sizeof(*map), stats_size); 66cabdff1aSopenharmony_ci int offset, i, next; 67cabdff1aSopenharmony_ci int size = 0; 68cabdff1aSopenharmony_ci int ret = 0; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci if (!h || !up || !len || !map) { 71cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 72cabdff1aSopenharmony_ci goto end; 73cabdff1aSopenharmony_ci } 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_ci for (i = 0; i<stats_size; i++) { 76cabdff1aSopenharmony_ci dst[i] = 255; 77cabdff1aSopenharmony_ci if (stats[i] || !skip0) 78cabdff1aSopenharmony_ci map[size++] = i; 79cabdff1aSopenharmony_ci } 80cabdff1aSopenharmony_ci 81cabdff1aSopenharmony_ci for (offset = 1; ; offset <<= 1) { 82cabdff1aSopenharmony_ci for (i=0; i < size; i++) { 83cabdff1aSopenharmony_ci h[i].name = i; 84cabdff1aSopenharmony_ci h[i].val = (stats[map[i]] << 14) + offset; 85cabdff1aSopenharmony_ci } 86cabdff1aSopenharmony_ci for (i = size / 2 - 1; i >= 0; i--) 87cabdff1aSopenharmony_ci heap_sift(h, i, size); 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_ci for (next = size; next < size * 2 - 1; next++) { 90cabdff1aSopenharmony_ci // merge the two smallest entries, and put it back in the heap 91cabdff1aSopenharmony_ci uint64_t min1v = h[0].val; 92cabdff1aSopenharmony_ci up[h[0].name] = next; 93cabdff1aSopenharmony_ci h[0].val = INT64_MAX; 94cabdff1aSopenharmony_ci heap_sift(h, 0, size); 95cabdff1aSopenharmony_ci up[h[0].name] = next; 96cabdff1aSopenharmony_ci h[0].name = next; 97cabdff1aSopenharmony_ci h[0].val += min1v; 98cabdff1aSopenharmony_ci heap_sift(h, 0, size); 99cabdff1aSopenharmony_ci } 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci len[2 * size - 2] = 0; 102cabdff1aSopenharmony_ci for (i = 2 * size - 3; i >= size; i--) 103cabdff1aSopenharmony_ci len[i] = len[up[i]] + 1; 104cabdff1aSopenharmony_ci for (i = 0; i < size; i++) { 105cabdff1aSopenharmony_ci dst[map[i]] = len[up[i]] + 1; 106cabdff1aSopenharmony_ci if (dst[map[i]] >= 32) break; 107cabdff1aSopenharmony_ci } 108cabdff1aSopenharmony_ci if (i==size) break; 109cabdff1aSopenharmony_ci } 110cabdff1aSopenharmony_ciend: 111cabdff1aSopenharmony_ci av_free(h); 112cabdff1aSopenharmony_ci av_free(up); 113cabdff1aSopenharmony_ci av_free(len); 114cabdff1aSopenharmony_ci av_free(map); 115cabdff1aSopenharmony_ci return ret; 116cabdff1aSopenharmony_ci} 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_cistatic void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat, 119cabdff1aSopenharmony_ci Node *nodes, int node, 120cabdff1aSopenharmony_ci uint32_t pfx, int pl, int *pos, int no_zero_count) 121cabdff1aSopenharmony_ci{ 122cabdff1aSopenharmony_ci int s; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci s = nodes[node].sym; 125cabdff1aSopenharmony_ci if (s != HNODE || (no_zero_count && !nodes[node].count)) { 126cabdff1aSopenharmony_ci bits[*pos] = pfx; 127cabdff1aSopenharmony_ci lens[*pos] = pl; 128cabdff1aSopenharmony_ci xlat[*pos] = s; 129cabdff1aSopenharmony_ci (*pos)++; 130cabdff1aSopenharmony_ci } else { 131cabdff1aSopenharmony_ci pfx <<= 1; 132cabdff1aSopenharmony_ci pl++; 133cabdff1aSopenharmony_ci get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0, pfx, pl, 134cabdff1aSopenharmony_ci pos, no_zero_count); 135cabdff1aSopenharmony_ci pfx |= 1; 136cabdff1aSopenharmony_ci get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0 + 1, pfx, pl, 137cabdff1aSopenharmony_ci pos, no_zero_count); 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci} 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_cistatic int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags, int nb_bits) 142cabdff1aSopenharmony_ci{ 143cabdff1aSopenharmony_ci int no_zero_count = !(flags & FF_HUFFMAN_FLAG_ZERO_COUNT); 144cabdff1aSopenharmony_ci uint32_t bits[256]; 145cabdff1aSopenharmony_ci int16_t lens[256]; 146cabdff1aSopenharmony_ci uint8_t xlat[256]; 147cabdff1aSopenharmony_ci int pos = 0; 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci get_tree_codes(bits, lens, xlat, nodes, head, 0, 0, 150cabdff1aSopenharmony_ci &pos, no_zero_count); 151cabdff1aSopenharmony_ci return ff_init_vlc_sparse(vlc, nb_bits, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0); 152cabdff1aSopenharmony_ci} 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci/** 156cabdff1aSopenharmony_ci * nodes size must be 2*nb_codes 157cabdff1aSopenharmony_ci * first nb_codes nodes.count must be set 158cabdff1aSopenharmony_ci */ 159cabdff1aSopenharmony_ciint ff_huff_build_tree(void *logctx, VLC *vlc, int nb_codes, int nb_bits, 160cabdff1aSopenharmony_ci Node *nodes, HuffCmp cmp, int flags) 161cabdff1aSopenharmony_ci{ 162cabdff1aSopenharmony_ci int i, j; 163cabdff1aSopenharmony_ci int cur_node; 164cabdff1aSopenharmony_ci int64_t sum = 0; 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci for (i = 0; i < nb_codes; i++) { 167cabdff1aSopenharmony_ci nodes[i].sym = i; 168cabdff1aSopenharmony_ci nodes[i].n0 = -2; 169cabdff1aSopenharmony_ci sum += nodes[i].count; 170cabdff1aSopenharmony_ci } 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_ci if (sum >> 31) { 173cabdff1aSopenharmony_ci av_log(logctx, AV_LOG_ERROR, 174cabdff1aSopenharmony_ci "Too high symbol frequencies. " 175cabdff1aSopenharmony_ci "Tree construction is not possible\n"); 176cabdff1aSopenharmony_ci return -1; 177cabdff1aSopenharmony_ci } 178cabdff1aSopenharmony_ci AV_QSORT(nodes, nb_codes, Node, cmp); 179cabdff1aSopenharmony_ci cur_node = nb_codes; 180cabdff1aSopenharmony_ci nodes[nb_codes*2-1].count = 0; 181cabdff1aSopenharmony_ci for (i = 0; i < nb_codes * 2 - 1; i += 2) { 182cabdff1aSopenharmony_ci uint32_t cur_count = nodes[i].count + nodes[i+1].count; 183cabdff1aSopenharmony_ci // find correct place to insert new node, and 184cabdff1aSopenharmony_ci // make space for the new node while at it 185cabdff1aSopenharmony_ci for(j = cur_node; j > i + 2; j--){ 186cabdff1aSopenharmony_ci if(cur_count > nodes[j-1].count || 187cabdff1aSopenharmony_ci (cur_count == nodes[j-1].count && 188cabdff1aSopenharmony_ci !(flags & FF_HUFFMAN_FLAG_HNODE_FIRST))) 189cabdff1aSopenharmony_ci break; 190cabdff1aSopenharmony_ci nodes[j] = nodes[j - 1]; 191cabdff1aSopenharmony_ci } 192cabdff1aSopenharmony_ci nodes[j].sym = HNODE; 193cabdff1aSopenharmony_ci nodes[j].count = cur_count; 194cabdff1aSopenharmony_ci nodes[j].n0 = i; 195cabdff1aSopenharmony_ci cur_node++; 196cabdff1aSopenharmony_ci } 197cabdff1aSopenharmony_ci if (build_huff_tree(vlc, nodes, nb_codes * 2 - 2, flags, nb_bits) < 0) { 198cabdff1aSopenharmony_ci av_log(logctx, AV_LOG_ERROR, "Error building tree\n"); 199cabdff1aSopenharmony_ci return -1; 200cabdff1aSopenharmony_ci } 201cabdff1aSopenharmony_ci return 0; 202cabdff1aSopenharmony_ci} 203