FFmpeg
huffman.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006 Konstantin Shishkov
3  * Copyright (c) 2007 Loren Merritt
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * huffman tree builder and VLC generator
25  */
26 
27 #include <stdint.h>
28 
29 #include "libavutil/qsort.h"
30 #include "libavutil/common.h"
31 
32 #include "huffman.h"
33 #include "vlc.h"
34 
35 /* symbol for Huffman tree node */
36 #define HNODE -1
37 
38 typedef struct HeapElem {
39  uint64_t val;
40  int name;
41 } HeapElem;
42 
43 static void heap_sift(HeapElem *h, int root, int size)
44 {
45  while (root * 2 + 1 < size) {
46  int child = root * 2 + 1;
47  if (child < size - 1 && h[child].val > h[child+1].val)
48  child++;
49  if (h[root].val > h[child].val) {
50  FFSWAP(HeapElem, h[root], h[child]);
51  root = child;
52  } else
53  break;
54  }
55 }
56 
57 int ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats, int stats_size, int skip0)
58 {
59  HeapElem *h = av_malloc_array(sizeof(*h), stats_size);
60  int *up = av_malloc_array(sizeof(*up) * 2, stats_size);
61  uint8_t *len = av_malloc_array(sizeof(*len) * 2, stats_size);
62  uint16_t *map= av_malloc_array(sizeof(*map), stats_size);
63  int offset, i, next;
64  int size = 0;
65  int ret = 0;
66 
67  if (!h || !up || !len || !map) {
68  ret = AVERROR(ENOMEM);
69  goto end;
70  }
71 
72  for (i = 0; i<stats_size; i++) {
73  dst[i] = 255;
74  if (stats[i] || !skip0)
75  map[size++] = i;
76  }
77 
78  for (offset = 1; ; offset <<= 1) {
79  for (i=0; i < size; i++) {
80  h[i].name = i;
81  h[i].val = (stats[map[i]] << 14) + offset;
82  }
83  for (i = size / 2 - 1; i >= 0; i--)
84  heap_sift(h, i, size);
85 
86  for (next = size; next < size * 2 - 1; next++) {
87  // merge the two smallest entries, and put it back in the heap
88  uint64_t min1v = h[0].val;
89  up[h[0].name] = next;
90  h[0].val = INT64_MAX;
91  heap_sift(h, 0, size);
92  up[h[0].name] = next;
93  h[0].name = next;
94  h[0].val += min1v;
95  heap_sift(h, 0, size);
96  }
97 
98  len[2 * size - 2] = 0;
99  for (i = 2 * size - 3; i >= size; i--)
100  len[i] = len[up[i]] + 1;
101  for (i = 0; i < size; i++) {
102  dst[map[i]] = len[up[i]] + 1;
103  if (dst[map[i]] >= 32) break;
104  }
105  if (i==size) break;
106  }
107 end:
108  av_free(h);
109  av_free(up);
110  av_free(len);
111  av_free(map);
112  return ret;
113 }
114 
115 static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat,
116  Node *nodes, int node,
117  uint32_t pfx, int pl, int *pos, int no_zero_count)
118 {
119  int s;
120 
121  s = nodes[node].sym;
122  if (s != HNODE || (no_zero_count && !nodes[node].count)) {
123  bits[*pos] = pfx;
124  lens[*pos] = pl;
125  xlat[*pos] = s;
126  (*pos)++;
127  } else {
128  pfx <<= 1;
129  pl++;
130  get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0, pfx, pl,
131  pos, no_zero_count);
132  pfx |= 1;
133  get_tree_codes(bits, lens, xlat, nodes, nodes[node].n0 + 1, pfx, pl,
134  pos, no_zero_count);
135  }
136 }
137 
138 static int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags, int nb_bits)
139 {
140  int no_zero_count = !(flags & FF_HUFFMAN_FLAG_ZERO_COUNT);
141  uint32_t bits[256];
142  int16_t lens[256];
143  uint8_t xlat[256];
144  int pos = 0;
145 
146  get_tree_codes(bits, lens, xlat, nodes, head, 0, 0,
147  &pos, no_zero_count);
148  return ff_init_vlc_sparse(vlc, nb_bits, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0);
149 }
150 
151 
152 /**
153  * nodes size must be 2*nb_codes
154  * first nb_codes nodes.count must be set
155  */
156 int ff_huff_build_tree(void *logctx, VLC *vlc, int nb_codes, int nb_bits,
157  Node *nodes, HuffCmp cmp, int flags)
158 {
159  int i, j;
160  int cur_node;
161  int64_t sum = 0;
162 
163  for (i = 0; i < nb_codes; i++) {
164  nodes[i].sym = i;
165  nodes[i].n0 = -2;
166  sum += nodes[i].count;
167  }
168 
169  if (sum >> 31) {
170  av_log(logctx, AV_LOG_ERROR,
171  "Too high symbol frequencies. "
172  "Tree construction is not possible\n");
173  return -1;
174  }
175  AV_QSORT(nodes, nb_codes, Node, cmp);
176  cur_node = nb_codes;
177  nodes[nb_codes*2-1].count = 0;
178  for (i = 0; i < nb_codes * 2 - 1; i += 2) {
179  uint32_t cur_count = nodes[i].count + nodes[i+1].count;
180  // find correct place to insert new node, and
181  // make space for the new node while at it
182  for(j = cur_node; j > i + 2; j--){
183  if(cur_count > nodes[j-1].count ||
184  (cur_count == nodes[j-1].count &&
186  break;
187  nodes[j] = nodes[j - 1];
188  }
189  nodes[j].sym = HNODE;
190  nodes[j].count = cur_count;
191  nodes[j].n0 = i;
192  cur_node++;
193  }
194  if (build_huff_tree(vlc, nodes, nb_codes * 2 - 2, flags, nb_bits) < 0) {
195  av_log(logctx, AV_LOG_ERROR, "Error building tree\n");
196  return -1;
197  }
198  return 0;
199 }
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
Node
Definition: agm.c:915
stats
static void stats(AVPacket *const *in, int n_in, unsigned *_max, unsigned *_sum)
Definition: vp9_superframe_bsf.c:34
HeapElem::val
uint64_t val
Definition: huffman.c:39
FF_HUFFMAN_FLAG_ZERO_COUNT
#define FF_HUFFMAN_FLAG_ZERO_COUNT
Definition: huffman.h:40
val
static double val(void *priv, double ch)
Definition: aeval.c:76
heap_sift
static void heap_sift(HeapElem *h, int root, int size)
Definition: huffman.c:43
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
s
#define s(width, name)
Definition: cbs_vp9.c:257
bits
uint8_t bits
Definition: vp3data.h:141
build_huff_tree
static int build_huff_tree(VLC *vlc, Node *nodes, int head, int flags, int nb_bits)
Definition: huffman.c:138
cmp
static av_always_inline int cmp(MpegEncContext *s, const int x, const int y, const int subx, const int suby, const int size, const int h, int ref_index, int src_index, me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags)
compares a block (either a full macroblock or a partition thereof) against a proposed motion-compensa...
Definition: motion_est.c:260
HNODE
#define HNODE
Definition: huffman.c:36
HeapElem::name
int name
Definition: huffman.c:40
ff_huff_gen_len_table
int ff_huff_gen_len_table(uint8_t *dst, const uint64_t *stats, int stats_size, int skip0)
Definition: huffman.c:57
ff_init_vlc_sparse
int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes, const void *bits, int bits_wrap, int bits_size, const void *codes, int codes_wrap, int codes_size, const void *symbols, int symbols_wrap, int symbols_size, int flags)
Definition: bitstream.c:323
qsort.h
size
int size
Definition: twinvq_data.h:10344
HeapElem
Definition: huffman.c:38
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
AV_QSORT
#define AV_QSORT(p, num, type, cmp)
Quicksort This sort is fast, and fully inplace but not stable and it is possible to construct input t...
Definition: qsort.h:33
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
common.h
len
int len
Definition: vorbis_enc_data.h:426
ret
ret
Definition: filter_design.txt:187
ff_huff_build_tree
int ff_huff_build_tree(void *logctx, VLC *vlc, int nb_codes, int nb_bits, Node *nodes, HuffCmp cmp, int flags)
nodes size must be 2*nb_codes first nb_codes nodes.count must be set
Definition: huffman.c:156
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
Node::n0
int16_t n0
Definition: huffman.h:35
pos
unsigned int pos
Definition: spdifenc.c:412
HuffCmp
int(* HuffCmp)(const void *va, const void *vb)
Definition: huffman.h:43
VLC
Definition: vlc.h:26
huffman.h
Node::sym
int16_t sym
Definition: huffman.h:34
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
get_tree_codes
static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat, Node *nodes, int node, uint32_t pfx, int pl, int *pos, int no_zero_count)
Definition: huffman.c:115
vlc.h
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
Node::count
uint32_t count
Definition: huffman.h:36
h
h
Definition: vp9dsp_template.c:2038
FF_HUFFMAN_FLAG_HNODE_FIRST
#define FF_HUFFMAN_FLAG_HNODE_FIRST
Definition: huffman.h:39