| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of FFmpeg. | ||
| 3 | * | ||
| 4 | * FFmpeg is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU Lesser General Public | ||
| 6 | * License as published by the Free Software Foundation; either | ||
| 7 | * version 2.1 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * Lesser General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU Lesser General Public | ||
| 15 | * License along with FFmpeg; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <inttypes.h> | ||
| 20 | #include <stdint.h> | ||
| 21 | #include <stdio.h> | ||
| 22 | |||
| 23 | #include "libavutil/avutil.h" | ||
| 24 | #include "libavutil/macros.h" | ||
| 25 | #include "libavutil/mathematics.h" | ||
| 26 | #include "libavutil/rational.h" | ||
| 27 | |||
| 28 | 1 | int main(void) | |
| 29 | { | ||
| 30 | int64_t last; | ||
| 31 | |||
| 32 | /* av_gcd */ | ||
| 33 | 1 | printf("Testing av_gcd()\n"); | |
| 34 | static const struct { int64_t a, b, expected; } gcd_tests[] = { | ||
| 35 | { 0, 0, 0 }, | ||
| 36 | { 1, 0, 1 }, | ||
| 37 | { 0, 1, 1 }, | ||
| 38 | { 6, 4, 2 }, | ||
| 39 | { 12, 8, 4 }, | ||
| 40 | { 17, 13, 1 }, | ||
| 41 | { 100, 75, 25 }, | ||
| 42 | { -6, 4, 2 }, | ||
| 43 | { 6, -4, 2 }, | ||
| 44 | }; | ||
| 45 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
|
10 | for (int i = 0; i < FF_ARRAY_ELEMS(gcd_tests); i++) |
| 46 | 9 | printf("gcd(%"PRId64", %"PRId64") = %"PRId64" %s\n", | |
| 47 | 9 | gcd_tests[i].a, gcd_tests[i].b, | |
| 48 | 9 | av_gcd(gcd_tests[i].a, gcd_tests[i].b), | |
| 49 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | av_gcd(gcd_tests[i].a, gcd_tests[i].b) == gcd_tests[i].expected ? "OK" : "FAIL"); |
| 50 | |||
| 51 | /* av_rescale */ | ||
| 52 | 1 | printf("\nTesting av_rescale()\n"); | |
| 53 | 1 | printf("rescale(6, 3, 2) = %"PRId64"\n", av_rescale(6, 3, 2)); | |
| 54 | 1 | printf("rescale(0, 3, 2) = %"PRId64"\n", av_rescale(0, 3, 2)); | |
| 55 | 1 | printf("rescale(1, 1, 1) = %"PRId64"\n", av_rescale(1, 1, 1)); | |
| 56 | 1 | printf("rescale(-6, 3, 2) = %"PRId64"\n", av_rescale(-6, 3, 2)); | |
| 57 | 1 | printf("rescale(90000, 1, 90000) = %"PRId64"\n", av_rescale(90000, 1, 90000)); | |
| 58 | |||
| 59 | /* av_rescale_rnd with different rounding modes */ | ||
| 60 | 1 | printf("\nTesting av_rescale_rnd()\n"); | |
| 61 | static const struct { | ||
| 62 | int64_t a, b, c; | ||
| 63 | enum AVRounding rnd; | ||
| 64 | int64_t expected; | ||
| 65 | } rnd_tests[] = { | ||
| 66 | { 7, 1, 2, AV_ROUND_ZERO, 3 }, | ||
| 67 | { 7, 1, 2, AV_ROUND_INF, 4 }, | ||
| 68 | { 7, 1, 2, AV_ROUND_DOWN, 3 }, | ||
| 69 | { 7, 1, 2, AV_ROUND_UP, 4 }, | ||
| 70 | { 7, 1, 2, AV_ROUND_NEAR_INF, 4 }, | ||
| 71 | { -7, 1, 2, AV_ROUND_ZERO, -3 }, | ||
| 72 | { -7, 1, 2, AV_ROUND_INF, -4 }, | ||
| 73 | { -7, 1, 2, AV_ROUND_DOWN, -4 }, | ||
| 74 | { -7, 1, 2, AV_ROUND_UP, -3 }, | ||
| 75 | { 6, 1, 2, AV_ROUND_NEAR_INF, 3 }, | ||
| 76 | }; | ||
| 77 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
|
11 | for (int i = 0; i < FF_ARRAY_ELEMS(rnd_tests); i++) { |
| 78 | 10 | int64_t r = av_rescale_rnd(rnd_tests[i].a, rnd_tests[i].b, | |
| 79 | 10 | rnd_tests[i].c, rnd_tests[i].rnd); | |
| 80 | 10 | printf("rescale_rnd(%"PRId64", %"PRId64", %"PRId64", %d) = %"PRId64" %s\n", | |
| 81 | 10 | rnd_tests[i].a, rnd_tests[i].b, rnd_tests[i].c, | |
| 82 | 10 | rnd_tests[i].rnd, r, | |
| 83 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | r == rnd_tests[i].expected ? "OK" : "FAIL"); |
| 84 | } | ||
| 85 | |||
| 86 | /* AV_ROUND_PASS_MINMAX */ | ||
| 87 | 1 | printf("\nTesting AV_ROUND_PASS_MINMAX\n"); | |
| 88 | 1 | printf("INT64_MIN passthrough: %s\n", | |
| 89 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | av_rescale_rnd(INT64_MIN, 1, 2, |
| 90 | AV_ROUND_UP | AV_ROUND_PASS_MINMAX) == INT64_MIN ? "OK" : "FAIL"); | ||
| 91 | 1 | printf("INT64_MAX passthrough: %s\n", | |
| 92 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | av_rescale_rnd(INT64_MAX, 1, 2, |
| 93 | AV_ROUND_UP | AV_ROUND_PASS_MINMAX) == INT64_MAX ? "OK" : "FAIL"); | ||
| 94 | 1 | printf("normal with PASS_MINMAX: %"PRId64"\n", | |
| 95 | av_rescale_rnd(3, 1, 2, AV_ROUND_UP | AV_ROUND_PASS_MINMAX)); | ||
| 96 | |||
| 97 | /* large value rescale (exercises 128-bit multiply path) */ | ||
| 98 | 1 | printf("\nTesting large value rescale\n"); | |
| 99 | 1 | printf("rescale(INT64_MAX/2, 2, 1) = %"PRId64"\n", | |
| 100 | av_rescale_rnd(INT64_MAX / 2, 2, 1, AV_ROUND_ZERO)); | ||
| 101 | 1 | printf("rescale(1000000007, 1000000009, 1000000007) = %"PRId64"\n", | |
| 102 | av_rescale(1000000007LL, 1000000009LL, 1000000007LL)); | ||
| 103 | /* b and c both > INT_MAX triggers 128-bit multiply */ | ||
| 104 | 1 | printf("rescale_rnd(10, INT_MAX+1, INT_MAX+1, ZERO) = %"PRId64"\n", | |
| 105 | av_rescale_rnd(10, (int64_t)INT32_MAX + 1, (int64_t)INT32_MAX + 1, AV_ROUND_ZERO)); | ||
| 106 | 1 | printf("rescale_rnd(7, 3000000000, 2000000000, NEAR_INF) = %"PRId64"\n", | |
| 107 | av_rescale_rnd(7, 3000000000LL, 2000000000LL, AV_ROUND_NEAR_INF)); | ||
| 108 | |||
| 109 | /* av_rescale_q */ | ||
| 110 | 1 | printf("\nTesting av_rescale_q()\n"); | |
| 111 | 1 | printf("rescale_q(90000, 1/90000, 1/1000) = %"PRId64"\n", | |
| 112 | 1 | av_rescale_q(90000, (AVRational){1, 90000}, (AVRational){1, 1000})); | |
| 113 | 1 | printf("rescale_q(48000, 1/48000, 1/44100) = %"PRId64"\n", | |
| 114 | 1 | av_rescale_q(48000, (AVRational){1, 48000}, (AVRational){1, 44100})); | |
| 115 | |||
| 116 | /* av_compare_ts */ | ||
| 117 | 1 | printf("\nTesting av_compare_ts()\n"); | |
| 118 | 1 | printf("compare(1, 1/1, 1, 1/1) = %d\n", | |
| 119 | 1 | av_compare_ts(1, (AVRational){1, 1}, 1, (AVRational){1, 1})); | |
| 120 | 1 | printf("compare(1, 1/1, 2, 1/1) = %d\n", | |
| 121 | 1 | av_compare_ts(1, (AVRational){1, 1}, 2, (AVRational){1, 1})); | |
| 122 | 1 | printf("compare(2, 1/1, 1, 1/1) = %d\n", | |
| 123 | 1 | av_compare_ts(2, (AVRational){1, 1}, 1, (AVRational){1, 1})); | |
| 124 | 1 | printf("compare(1, 1/1000, 1, 1/90000) = %d\n", | |
| 125 | 1 | av_compare_ts(1, (AVRational){1, 1000}, 1, (AVRational){1, 90000})); | |
| 126 | /* large values trigger rescale-based comparison path */ | ||
| 127 | 1 | printf("compare(INT64_MAX/2, 1/1, INT64_MAX/3, 1/1) = %d\n", | |
| 128 | 1 | av_compare_ts(INT64_MAX / 2, (AVRational){1, 1}, | |
| 129 | 1 | INT64_MAX / 3, (AVRational){1, 1})); | |
| 130 | |||
| 131 | /* av_compare_mod */ | ||
| 132 | 1 | printf("\nTesting av_compare_mod()\n"); | |
| 133 | 1 | printf("compare_mod(3, 1, 16) = %"PRId64"\n", av_compare_mod(3, 1, 16)); | |
| 134 | 1 | printf("compare_mod(1, 3, 16) = %"PRId64"\n", av_compare_mod(1, 3, 16)); | |
| 135 | 1 | printf("compare_mod(5, 5, 16) = %"PRId64"\n", av_compare_mod(5, 5, 16)); | |
| 136 | |||
| 137 | /* av_rescale_delta */ | ||
| 138 | 1 | printf("\nTesting av_rescale_delta()\n"); | |
| 139 | 1 | last = AV_NOPTS_VALUE; | |
| 140 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (int i = 0; i < 4; i++) |
| 141 | 4 | printf("delta step %d: %"PRId64"\n", i, | |
| 142 | 4 | av_rescale_delta((AVRational){1, 48000}, i * 1024, | |
| 143 | 4 | (AVRational){1, 48000}, 1024, | |
| 144 | 4 | &last, (AVRational){1, 44100})); | |
| 145 | /* trigger clip-based path: use different in_tb and fs_tb */ | ||
| 146 | 1 | last = AV_NOPTS_VALUE; | |
| 147 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (int i = 0; i < 4; i++) |
| 148 | 4 | printf("delta clip %d: %"PRId64"\n", i, | |
| 149 | 4 | av_rescale_delta((AVRational){1, 44100}, i * 940, | |
| 150 | 4 | (AVRational){1, 48000}, 1024, | |
| 151 | 4 | &last, (AVRational){1, 90000})); | |
| 152 | |||
| 153 | /* av_add_stable */ | ||
| 154 | 1 | printf("\nTesting av_add_stable()\n"); | |
| 155 | 1 | printf("add_stable(0, 1/1, 1/1000, 500) = %"PRId64"\n", | |
| 156 | 1 | av_add_stable((AVRational){1, 1}, 0, (AVRational){1, 1000}, 500)); | |
| 157 | 1 | printf("add_stable(1000, 1/90000, 1/48000, 1024) = %"PRId64"\n", | |
| 158 | 1 | av_add_stable((AVRational){1, 90000}, 1000, (AVRational){1, 48000}, 1024)); | |
| 159 | /* non-exact division path (m >= d, general case) */ | ||
| 160 | 1 | printf("add_stable(0, 1/48000, 1/90000, 90000) = %"PRId64"\n", | |
| 161 | 1 | av_add_stable((AVRational){1, 48000}, 0, (AVRational){1, 90000}, 90000)); | |
| 162 | 1 | printf("add_stable(100, 1/1000, 1/90000, 3000) = %"PRId64"\n", | |
| 163 | 1 | av_add_stable((AVRational){1, 1000}, 100, (AVRational){1, 90000}, 3000)); | |
| 164 | /* repeated addition: verify no rounding error accumulation */ | ||
| 165 | { | ||
| 166 | 1 | int64_t ts = 0; | |
| 167 |
2/2✓ Branch 0 taken 10000 times.
✓ Branch 1 taken 1 times.
|
10001 | for (int i = 0; i < 10000; i++) |
| 168 | 10000 | ts = av_add_stable((AVRational){1, 48000}, ts, (AVRational){1, 48000}, 1024); | |
| 169 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("add_stable 10000x1024 at 1/48000: %"PRId64" (expected %"PRId64") %s\n", |
| 170 | ts, (int64_t)10000 * 1024, | ||
| 171 | ts == (int64_t)10000 * 1024 ? "OK" : "FAIL"); | ||
| 172 | } | ||
| 173 | |||
| 174 | 1 | return 0; | |
| 175 | } | ||
| 176 |