[FFmpeg-cvslog] avcodec/tests/mjpegenc_huffman: Also test length counts
Andreas Rheinhardt
git at videolan.org
Fri Apr 18 10:11:09 EEST 2025
ffmpeg | branch: master | Andreas Rheinhardt <andreas.rheinhardt at outlook.com> | Mon Apr 14 20:39:53 2025 +0200| [c8ce9de5a0c0b8a2d511adc4e9502c2840064f72] | committer: Andreas Rheinhardt
avcodec/tests/mjpegenc_huffman: Also test length counts
This is better than just testing that the tree is not overdetermined.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=c8ce9de5a0c0b8a2d511adc4e9502c2840064f72
---
libavcodec/tests/mjpegenc_huffman.c | 48 ++++++++++++++++++++++++++++---------
1 file changed, 37 insertions(+), 11 deletions(-)
diff --git a/libavcodec/tests/mjpegenc_huffman.c b/libavcodec/tests/mjpegenc_huffman.c
index 39ad10c454..4f94dd99dc 100644
--- a/libavcodec/tests/mjpegenc_huffman.c
+++ b/libavcodec/tests/mjpegenc_huffman.c
@@ -31,15 +31,16 @@
#include "libavcodec/mjpegenc_huffman.c"
// Validate the computed lengths satisfy the JPEG restrictions and is optimal.
-static int check_lengths(int L, int expected_length,
- const int *probs, int nprobs)
+static int check_lengths(int L, const int *probs, int nprobs,
+ int expected_length, const uint8_t expected_len_counts[/* L + 1 */])
{
HuffTable lengths[256];
PTable val_counts[256];
+ uint8_t len_counts[17] = { 0 };
int actual_length = 0, i, j, k, prob, length;
int ret = 0;
- double cantor_measure = 0;
av_assert0(nprobs <= 256);
+ av_assert0(L < FF_ARRAY_ELEMS(len_counts));
for (i = 0; i < nprobs; i++) {
val_counts[i] = (PTable){.value = i, .prob = probs[i]};
@@ -47,6 +48,26 @@ static int check_lengths(int L, int expected_length,
mjpegenc_huffman_compute_bits(val_counts, lengths, nprobs, L);
+ for (int i = 0; i < nprobs; ++i) {
+ if (lengths[i].length > L) {
+ fprintf(stderr,
+ "Len %d of element %d of Huffman table with %d elements exceeds max length %d\n",
+ lengths[i].length, i, nprobs, L);
+ return 1;
+ }
+ len_counts[lengths[i].length]++;
+ }
+ // Test that the lengths can be made part of a complete, prefix-free tree:
+ unsigned code = 0;
+ for (int i = 1; i <= L; ++i) {
+ code <<= 1;
+ code += len_counts[i];
+ }
+ if (code > 1U << L) {
+ fprintf(stderr, "Huffman tree overdetermined/invalid\n");
+ ret = 1;
+ }
+
for (i = 0; i < nprobs; i++) {
// Find the value's prob and length
for (j = 0; j < nprobs; j++)
@@ -59,22 +80,18 @@ static int check_lengths(int L, int expected_length,
if (prob) {
actual_length += prob * length;
- cantor_measure += 1. / (1 << length);
}
if (length > L || length < 1) return 1;
}
- // Check that the codes can be prefix-free.
- if (cantor_measure > 1) ret = 1;
// Check that the total length is optimal
if (actual_length != expected_length) ret = 1;
if (ret == 1) {
fprintf(stderr,
- "Cantor measure: %f\n"
"Actual length: %d\n"
"Expected length: %d\n",
- cantor_measure, actual_length, expected_length);
+ actual_length, expected_length);
}
return ret;
@@ -83,6 +100,9 @@ static int check_lengths(int L, int expected_length,
static const int probs_zeroes[] = {
6, 6, 0, 0, 0
};
+static const uint8_t len_counts_zeroes[] = {
+ 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
+};
static const int probs_skewed[] = {
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[] = {
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,
0, 21, 1, 0, 3, 24, 2, 0, 0, 7, 0, 0, 1, 5, 1, 2, 0, 5
};
+static const uint8_t len_counts_skewed[] = {
+ 0, 1, 0, 0, 1, 2, 7, 11, 18, 31, 28, 40, 0, 1, 0, 0, 116,
+};
static const int probs_sat[] = {
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[] = {
0, 1085, 0, 0, 0, 3, 489, 36, 1, 0, 1, 9420, 294, 28, 0, 57, 5, 0, 9, 2, 0, 1, 2,
2, 0, 0, 9, 2, 29, 2, 2, 7, 0, 5, 490, 0, 7, 5, 0, 1, 8, 0, 0, 23255, 0, 1
};
+static const uint8_t len_counts_sat[] = {
+ 0, 1, 0, 2, 1, 2, 2, 5, 5, 7, 7, 8, 17, 23, 16, 24, 136,
+};
// Test the example given on @see
// http://guru.multimedia.cx/small-tasks-for-ffmpeg/
@@ -154,13 +180,13 @@ int main(int argc, char **argv)
}
// Check handling of zero probabilities
- if (check_lengths(16, 18, probs_zeroes, FF_ARRAY_ELEMS(probs_zeroes)))
+ if (check_lengths(16, probs_zeroes, FF_ARRAY_ELEMS(probs_zeroes), 18, len_counts_zeroes))
ret = 1;
// Check skewed distribution over 256 without saturated lengths
- if (check_lengths(16, 41282, probs_skewed, FF_ARRAY_ELEMS(probs_skewed)))
+ if (check_lengths(16, probs_skewed, FF_ARRAY_ELEMS(probs_skewed), 41282, len_counts_skewed))
ret = 1;
// Check skewed distribution over 256 with saturated lengths
- if (check_lengths(16, 669904, probs_sat, FF_ARRAY_ELEMS(probs_sat)))
+ if (check_lengths(16, probs_sat, FF_ARRAY_ELEMS(probs_sat), 669904, len_counts_sat))
ret = 1;
return ret;
More information about the ffmpeg-cvslog
mailing list