History

avcodec/tests/mjpegenc_huffman: Also test length counts

This is better than just testing that the tree is not overdetermined.

Andreas Rheinhardt committed 1 year ago

Commit c8ce9de1 parent 76842431 file · +37 −11Browse files

Showing the changes to libavcodec/tests (1 of 1 file). Show all

Unified · Split

libavcodec/tests/mjpegenc_huffman.c+37−11
@@ -31,15 +31,16 @@ · 30 unmodified lines
3131 #include "libavcodec/mjpegenc_huffman.c"
3232
3333 // Validate the computed lengths satisfy the JPEG restrictions and is optimal.
34−static int check_lengths(int L, int expected_length,
35− const int *probs, int nprobs)
34+static int check_lengths(int L, const int *probs, int nprobs,
35+ int expected_length, const uint8_t expected_len_counts[/* L + 1 */])
3636 {
3737 HuffTable lengths[256];
3838 PTable val_counts[256];
39+ uint8_t len_counts[17] = { 0 };
3940 int actual_length = 0, i, j, k, prob, length;
4041 int ret = 0;
41− double cantor_measure = 0;
4242 av_assert0(nprobs <= 256);
43+ av_assert0(L < FF_ARRAY_ELEMS(len_counts));
4344
4445 for (i = 0; i < nprobs; i++) {
4546 val_counts[i] = (PTable){.value = i, .prob = probs[i]};
@@ -47,6 +48,26 @@ static int check_lengths(int L, int expected_length, · 1 unmodified line
4748
4849 mjpegenc_huffman_compute_bits(val_counts, lengths, nprobs, L);
4950
51+ for (int i = 0; i < nprobs; ++i) {
52+ if (lengths[i].length > L) {
53+ fprintf(stderr,
54+ "Len %d of element %d of Huffman table with %d elements exceeds max length %d\n",
55+ lengths[i].length, i, nprobs, L);
56+ return 1;
57+ }
58+ len_counts[lengths[i].length]++;
59+ }
60+ // Test that the lengths can be made part of a complete, prefix-free tree:
61+ unsigned code = 0;
62+ for (int i = 1; i <= L; ++i) {
63+ code <<= 1;
64+ code += len_counts[i];
65+ }
66+ if (code > 1U << L) {
67+ fprintf(stderr, "Huffman tree overdetermined/invalid\n");
68+ ret = 1;
69+ }
70+
5071 for (i = 0; i < nprobs; i++) {
5172 // Find the value's prob and length
5273 for (j = 0; j < nprobs; j++)
@@ -59,22 +80,18 @@ static int check_lengths(int L, int expected_length, · 6 unmodified lines
5980
6081 if (prob) {
6182 actual_length += prob * length;
62− cantor_measure += 1. / (1 << length);
6383 }
6484
6585 if (length > L || length < 1) return 1;
6686 }
67− // Check that the codes can be prefix-free.
68− if (cantor_measure > 1) ret = 1;
6987 // Check that the total length is optimal
7088 if (actual_length != expected_length) ret = 1;
7189
7290 if (ret == 1) {
7391 fprintf(stderr,
74− "Cantor measure: %f\n"
7592 "Actual length: %d\n"
7693 "Expected length: %d\n",
77− cantor_measure, actual_length, expected_length);
94+ actual_length, expected_length);
7895 }
7996
8097 return ret;
@@ -83,6 +100,9 @@ static int check_lengths(int L, int expected_length, · 2 unmodified lines
83100 static const int probs_zeroes[] = {
84101 6, 6, 0, 0, 0
85102 };
103+static const uint8_t len_counts_zeroes[] = {
104+ 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
105+};
86106
87107 static const int probs_skewed[] = {
88108 2, 0, 0, 0, 0, 1, 0, 0, 20, 0, 2, 0, 10, 5, 1, 1, 9, 1, 1, 6, 0, 5, 0, 1, 0, 7, 6,
@@ -96,6 +116,9 @@ static const int probs_skewed[] = { · 7 unmodified lines
96116 0, 3, 0, 0, 28, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 23, 0, 0, 0, 0,
97117 0, 21, 1, 0, 3, 24, 2, 0, 0, 7, 0, 0, 1, 5, 1, 2, 0, 5
98118 };
119+static const uint8_t len_counts_skewed[] = {
120+ 0, 1, 0, 0, 1, 2, 7, 11, 18, 31, 28, 40, 0, 1, 0, 0, 116,
121+};
99122
100123 static const int probs_sat[] = {
101124 74, 8, 14, 7, 9345, 40, 0, 2014, 2, 1, 115, 0, 2, 1, 194, 388, 20, 0, 0, 2, 1, 121,
@@ -110,6 +133,9 @@ static const int probs_sat[] = { · 8 unmodified lines
110133 0, 1085, 0, 0, 0, 3, 489, 36, 1, 0, 1, 9420, 294, 28, 0, 57, 5, 0, 9, 2, 0, 1, 2,
111134 2, 0, 0, 9, 2, 29, 2, 2, 7, 0, 5, 490, 0, 7, 5, 0, 1, 8, 0, 0, 23255, 0, 1
112135 };
136+static const uint8_t len_counts_sat[] = {
137+ 0, 1, 0, 2, 1, 2, 2, 5, 5, 7, 7, 8, 17, 23, 16, 24, 136,
138+};
113139
114140 // Test the example given on @see
115141 // http://guru.multimedia.cx/small-tasks-for-ffmpeg/
@@ -154,13 +180,13 @@ int main(int argc, char **argv) · 38 unmodified lines
154180 }
155181
156182 // Check handling of zero probabilities
157− if (check_lengths(16, 18, probs_zeroes, FF_ARRAY_ELEMS(probs_zeroes)))
183+ if (check_lengths(16, probs_zeroes, FF_ARRAY_ELEMS(probs_zeroes), 18, len_counts_zeroes))
158184 ret = 1;
159185 // Check skewed distribution over 256 without saturated lengths
160− if (check_lengths(16, 41282, probs_skewed, FF_ARRAY_ELEMS(probs_skewed)))
186+ if (check_lengths(16, probs_skewed, FF_ARRAY_ELEMS(probs_skewed), 41282, len_counts_skewed))
161187 ret = 1;
162188 // Check skewed distribution over 256 with saturated lengths
163− if (check_lengths(16, 669904, probs_sat, FF_ARRAY_ELEMS(probs_sat)))
189+ if (check_lengths(16, probs_sat, FF_ARRAY_ELEMS(probs_sat), 669904, len_counts_sat))
164190 ret = 1;
165191
166192 return ret;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t