| 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 <limits.h> | ||
| 20 | #include <stdio.h> | ||
| 21 | #include <string.h> | ||
| 22 | |||
| 23 | #include "libavutil/error.h" | ||
| 24 | #include "libavutil/frame.h" | ||
| 25 | #include "libavutil/hdr_dynamic_metadata.h" | ||
| 26 | #include "libavutil/mem.h" | ||
| 27 | #include "libavutil/rational.h" | ||
| 28 | |||
| 29 | /* Denominators av_dynamic_hdr_plus_to_t35() quantises to. The fixtures below | ||
| 30 | * express every rational in these terms, so a correct round trip reproduces | ||
| 31 | * the input exactly and the decoded values printed here can be compared | ||
| 32 | * against the fixture directly. */ | ||
| 33 | #define LUMINANCE_DEN 1 | ||
| 34 | #define PEAK_LUMINANCE_DEN 15 | ||
| 35 | #define RGB_DEN 100000 | ||
| 36 | #define FRACTION_PIXEL_DEN 1000 | ||
| 37 | #define KNEE_POINT_DEN 4095 | ||
| 38 | #define BEZIER_ANCHOR_DEN 1023 | ||
| 39 | #define SATURATION_DEN 8 | ||
| 40 | |||
| 41 | /* | ||
| 42 | * Printers. Every field a fixture populates is printed, so that a serializer | ||
| 43 | * or parser which drops or corrupts a value changes the FATE reference | ||
| 44 | * instead of silently passing a flag-only check. | ||
| 45 | */ | ||
| 46 | |||
| 47 | 2 | static void print_peak_matrix(const char *label, int rows, int cols, | |
| 48 | const AVRational m[25][25]) | ||
| 49 | { | ||
| 50 | 2 | printf(" %s %dx%d:", label, rows, cols); | |
| 51 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
|
7 | for (int i = 0; i < rows; i++) |
| 52 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 5 times.
|
17 | for (int j = 0; j < cols; j++) |
| 53 | 12 | printf(" %d/%d", m[i][j].num, m[i][j].den); | |
| 54 | 2 | printf("\n"); | |
| 55 | 2 | } | |
| 56 | |||
| 57 | 3 | static void print_window(int w, const AVHDRPlusColorTransformParams *p, | |
| 58 | int geometry) | ||
| 59 | { | ||
| 60 | 3 | printf(" window %d:\n", w); | |
| 61 | /* Window 0 covers the whole frame; its geometry is not serialized. */ | ||
| 62 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (geometry) { |
| 63 | 1 | printf(" corners: ul=%d/%d,%d/%d lr=%d/%d,%d/%d\n", | |
| 64 | 1 | p->window_upper_left_corner_x.num, | |
| 65 | 1 | p->window_upper_left_corner_x.den, | |
| 66 | 1 | p->window_upper_left_corner_y.num, | |
| 67 | 1 | p->window_upper_left_corner_y.den, | |
| 68 | 1 | p->window_lower_right_corner_x.num, | |
| 69 | 1 | p->window_lower_right_corner_x.den, | |
| 70 | 1 | p->window_lower_right_corner_y.num, | |
| 71 | 1 | p->window_lower_right_corner_y.den); | |
| 72 | 1 | printf(" ellipse: center=%u,%u rotation=%u semimajor_int=%u" | |
| 73 | " semimajor_ext=%u semiminor_ext=%u overlap=%u\n", | ||
| 74 | 1 | p->center_of_ellipse_x, p->center_of_ellipse_y, | |
| 75 | 1 | p->rotation_angle, p->semimajor_axis_internal_ellipse, | |
| 76 | 1 | p->semimajor_axis_external_ellipse, | |
| 77 | 1 | p->semiminor_axis_external_ellipse, | |
| 78 | 1 | p->overlap_process_option); | |
| 79 | } | ||
| 80 | 3 | printf(" maxscl: %d/%d %d/%d %d/%d average_maxrgb=%d/%d\n", | |
| 81 | 3 | p->maxscl[0].num, p->maxscl[0].den, | |
| 82 | 3 | p->maxscl[1].num, p->maxscl[1].den, | |
| 83 | 3 | p->maxscl[2].num, p->maxscl[2].den, | |
| 84 | 3 | p->average_maxrgb.num, p->average_maxrgb.den); | |
| 85 | 3 | printf(" distribution_maxrgb: n=%u", | |
| 86 | 3 | p->num_distribution_maxrgb_percentiles); | |
| 87 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
|
15 | for (int i = 0; i < p->num_distribution_maxrgb_percentiles; i++) |
| 88 | 12 | printf(" %u%%=%d/%d", p->distribution_maxrgb[i].percentage, | |
| 89 | 12 | p->distribution_maxrgb[i].percentile.num, | |
| 90 | 12 | p->distribution_maxrgb[i].percentile.den); | |
| 91 | 3 | printf("\n fraction_bright_pixels=%d/%d\n", | |
| 92 | 3 | p->fraction_bright_pixels.num, p->fraction_bright_pixels.den); | |
| 93 | 3 | printf(" tone_mapping_flag=%u", p->tone_mapping_flag); | |
| 94 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (p->tone_mapping_flag) { |
| 95 | 3 | printf(" knee=%d/%d,%d/%d anchors=%u:", | |
| 96 | 3 | p->knee_point_x.num, p->knee_point_x.den, | |
| 97 | 3 | p->knee_point_y.num, p->knee_point_y.den, | |
| 98 | 3 | p->num_bezier_curve_anchors); | |
| 99 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
|
18 | for (int i = 0; i < p->num_bezier_curve_anchors; i++) |
| 100 | 15 | printf(" %d/%d", p->bezier_curve_anchors[i].num, | |
| 101 | 15 | p->bezier_curve_anchors[i].den); | |
| 102 | } | ||
| 103 | 3 | printf("\n color_saturation_mapping_flag=%u", | |
| 104 | 3 | p->color_saturation_mapping_flag); | |
| 105 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if (p->color_saturation_mapping_flag) |
| 106 | 2 | printf(" weight=%d/%d", p->color_saturation_weight.num, | |
| 107 | 2 | p->color_saturation_weight.den); | |
| 108 | 3 | printf("\n"); | |
| 109 | 3 | } | |
| 110 | |||
| 111 | 2 | static void print_hdr_plus(const char *label, const AVDynamicHDRPlus *s) | |
| 112 | { | ||
| 113 | 2 | printf("%s:\n", label); | |
| 114 | 2 | printf(" application_version=%u num_windows=%u" | |
| 115 | " targeted_system_display_maximum_luminance=%d/%d\n", | ||
| 116 | 2 | s->application_version, s->num_windows, | |
| 117 | 2 | s->targeted_system_display_maximum_luminance.num, | |
| 118 | 2 | s->targeted_system_display_maximum_luminance.den); | |
| 119 | 2 | printf(" targeted_system_display_actual_peak_luminance_flag=%u\n", | |
| 120 | 2 | s->targeted_system_display_actual_peak_luminance_flag); | |
| 121 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (s->targeted_system_display_actual_peak_luminance_flag) |
| 122 | 1 | print_peak_matrix("targeted_peak", | |
| 123 | 1 | s->num_rows_targeted_system_display_actual_peak_luminance, | |
| 124 | 1 | s->num_cols_targeted_system_display_actual_peak_luminance, | |
| 125 | 1 | s->targeted_system_display_actual_peak_luminance); | |
| 126 | 2 | printf(" mastering_display_actual_peak_luminance_flag=%u\n", | |
| 127 | 2 | s->mastering_display_actual_peak_luminance_flag); | |
| 128 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (s->mastering_display_actual_peak_luminance_flag) |
| 129 | 1 | print_peak_matrix("mastering_peak", | |
| 130 | 1 | s->num_rows_mastering_display_actual_peak_luminance, | |
| 131 | 1 | s->num_cols_mastering_display_actual_peak_luminance, | |
| 132 | 1 | s->mastering_display_actual_peak_luminance); | |
| 133 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
|
5 | for (int w = 0; w < s->num_windows; w++) |
| 134 | 3 | print_window(w, &s->params[w], w > 0); | |
| 135 | 2 | } | |
| 136 | |||
| 137 | 4 | static void print_app5(const char *label, const AVDynamicHDRSmpte2094App5 *s) | |
| 138 | { | ||
| 139 | 4 | printf("%s:\n", label); | |
| 140 | 4 | printf(" application_version=%u minimum_application_version=%u\n", | |
| 141 | 4 | s->application_version, s->minimum_application_version); | |
| 142 | 4 | printf(" has_custom_hdr_reference_white_flag=%u", | |
| 143 | 4 | s->has_custom_hdr_reference_white_flag); | |
| 144 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (s->has_custom_hdr_reference_white_flag) |
| 145 | 1 | printf(" hdr_reference_white=0x%04x", s->hdr_reference_white); | |
| 146 | 4 | printf("\n has_adaptive_tone_map_flag=%u\n", | |
| 147 | 4 | s->has_adaptive_tone_map_flag); | |
| 148 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (!s->has_adaptive_tone_map_flag) |
| 149 | 1 | return; | |
| 150 | |||
| 151 | 3 | printf(" baseline_hdr_headroom=0x%04x" | |
| 152 | " use_reference_white_tone_mapping_flag=%u\n", | ||
| 153 | 3 | s->baseline_hdr_headroom, s->use_reference_white_tone_mapping_flag); | |
| 154 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (s->use_reference_white_tone_mapping_flag) |
| 155 | 1 | return; | |
| 156 | |||
| 157 | 2 | printf(" num_alternate_images=%u chromaticities_flag=%u" | |
| 158 | " has_common_component_mix_params_flag=%u" | ||
| 159 | " has_common_curve_params_flag=%u\n", | ||
| 160 | 2 | s->num_alternate_images, | |
| 161 | 2 | s->gain_application_space_chromaticities_flag, | |
| 162 | 2 | s->has_common_component_mix_params_flag, | |
| 163 | 2 | s->has_common_curve_params_flag); | |
| 164 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (s->gain_application_space_chromaticities_flag == 3) { |
| 165 | 1 | printf(" chromaticities:"); | |
| 166 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
|
9 | for (int r = 0; r < 8; r++) |
| 167 | 8 | printf(" 0x%04x", s->gain_application_space_chromaticities[r]); | |
| 168 | 1 | printf("\n"); | |
| 169 | } | ||
| 170 | |||
| 171 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
|
7 | for (int a = 0; a < s->num_alternate_images; a++) { |
| 172 | 5 | int n = s->gain_curve_num_control_points_minus_1[a] + 1; | |
| 173 | 5 | printf(" alternate %d: hdr_headroom=0x%04x component_mixing_type=%u\n", | |
| 174 | 5 | a, s->alternate_hdr_headrooms[a], s->component_mixing_type[a]); | |
| 175 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | if (s->component_mixing_type[a] == 3) { |
| 176 | 2 | printf(" mixing flag:coefficient:"); | |
| 177 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
|
14 | for (int k = 0; k < 6; k++) |
| 178 | 12 | printf(" %u:0x%04x", | |
| 179 | 12 | s->has_component_mixing_coefficient_flag[a][k], | |
| 180 | 12 | s->component_mixing_coefficient[a][k]); | |
| 181 | 2 | printf("\n"); | |
| 182 | } | ||
| 183 | 5 | printf(" curve: num_control_points=%d use_pchip_slope=%u\n", n, | |
| 184 | 5 | s->gain_curve_use_pchip_slope_flag[a]); | |
| 185 | 5 | printf(" x:"); | |
| 186 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
|
18 | for (int c = 0; c < n; c++) |
| 187 | 13 | printf(" 0x%04x", s->gain_curve_control_points_x[a][c]); | |
| 188 | 5 | printf("\n y:"); | |
| 189 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
|
18 | for (int c = 0; c < n; c++) |
| 190 | 13 | printf(" 0x%04x", s->gain_curve_control_points_y[a][c]); | |
| 191 | 5 | printf("\n"); | |
| 192 | /* theta is only serialized when the pchip slope is not used. */ | ||
| 193 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | if (!s->gain_curve_use_pchip_slope_flag[a]) { |
| 194 | 2 | printf(" theta:"); | |
| 195 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | for (int c = 0; c < n; c++) |
| 196 | 4 | printf(" 0x%04x", s->gain_curve_control_points_theta[a][c]); | |
| 197 | 2 | printf("\n"); | |
| 198 | } | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | /* | ||
| 203 | * Round-trip helpers: serialize, then parse back into a zeroed struct. | ||
| 204 | */ | ||
| 205 | |||
| 206 | 3 | static int hdr_plus_round_trip(const AVDynamicHDRPlus *in, AVDynamicHDRPlus *out) | |
| 207 | { | ||
| 208 | 3 | uint8_t *buf = NULL; | |
| 209 | 3 | size_t size = 0; | |
| 210 | int ret; | ||
| 211 | |||
| 212 | 3 | ret = av_dynamic_hdr_plus_to_t35(in, &buf, &size); | |
| 213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
| 214 | ✗ | return ret; | |
| 215 | |||
| 216 | 3 | memset(out, 0, sizeof(*out)); | |
| 217 | 3 | ret = av_dynamic_hdr_plus_from_t35(out, buf, size); | |
| 218 | 3 | av_free(buf); | |
| 219 | 3 | return ret; | |
| 220 | } | ||
| 221 | |||
| 222 | 4 | static int app5_round_trip(const AVDynamicHDRSmpte2094App5 *in, | |
| 223 | AVDynamicHDRSmpte2094App5 *out) | ||
| 224 | { | ||
| 225 | 4 | uint8_t *buf = NULL; | |
| 226 | 4 | size_t size = 0; | |
| 227 | int ret; | ||
| 228 | |||
| 229 | 4 | ret = av_dynamic_hdr_smpte2094_app5_to_t35(in, &buf, &size); | |
| 230 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (ret < 0) |
| 231 | ✗ | return ret; | |
| 232 | |||
| 233 | 4 | memset(out, 0, sizeof(*out)); | |
| 234 | 4 | ret = av_dynamic_hdr_smpte2094_app5_from_t35(out, buf, size); | |
| 235 | 4 | av_free(buf); | |
| 236 | 4 | return ret; | |
| 237 | } | ||
| 238 | |||
| 239 | /* | ||
| 240 | * Fixtures. | ||
| 241 | */ | ||
| 242 | |||
| 243 | /* A conforming ST 2094-40:2020 ApplicationVersion 1 payload: exactly one | ||
| 244 | * processing window, neither actual-peak-luminance item and no | ||
| 245 | * ColorSaturationWeight (§9.4 excludes all three for Version 1), and the nine | ||
| 246 | * distribution maxrgb percentiles §8.5.4 requires for that version. | ||
| 247 | * CTA-861-H fixes application_version at 1 for HDR10+ carried over T.35. | ||
| 248 | * | ||
| 249 | * The entries for 5% and 10% are not CFD percentile samples: §8.5.4 reserves | ||
| 250 | * every value other than 0.00000 and 0.00255 for that pair. No other entry may | ||
| 251 | * exceed the largest MaxSCL component either, since §8.3 takes MaxSCL over each | ||
| 252 | * RGB component separately while §8.5.2 draws the distribution from the | ||
| 253 | * per-pixel maximum component. */ | ||
| 254 | 1 | static void fill_hdr_plus_conforming(AVDynamicHDRPlus *s) | |
| 255 | { | ||
| 256 | static const uint8_t percentages[9] = { 1, 5, 10, 25, 50, 75, 90, 95, 99 }; | ||
| 257 | static const int percentiles[9] = { | ||
| 258 | 1000, 0, 255, 25000, 50000, 75000, 90000, 95000, 99000, | ||
| 259 | }; | ||
| 260 | |||
| 261 | 1 | memset(s, 0, sizeof(*s)); | |
| 262 | |||
| 263 | 1 | s->application_version = 1; | |
| 264 | 1 | s->num_windows = 1; | |
| 265 | 1 | s->targeted_system_display_maximum_luminance = | |
| 266 | (AVRational){ 400, LUMINANCE_DEN }; | ||
| 267 | 1 | s->targeted_system_display_actual_peak_luminance_flag = 0; | |
| 268 | 1 | s->mastering_display_actual_peak_luminance_flag = 0; | |
| 269 | |||
| 270 | 1 | s->params[0].maxscl[0] = (AVRational){ 50000, RGB_DEN }; | |
| 271 | 1 | s->params[0].maxscl[1] = (AVRational){ 60000, RGB_DEN }; | |
| 272 | 1 | s->params[0].maxscl[2] = (AVRational){ 99000, RGB_DEN }; | |
| 273 | 1 | s->params[0].average_maxrgb = (AVRational){ 40000, RGB_DEN }; | |
| 274 | |||
| 275 | 1 | s->params[0].num_distribution_maxrgb_percentiles = 9; | |
| 276 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
|
10 | for (int i = 0; i < 9; i++) { |
| 277 | 9 | s->params[0].distribution_maxrgb[i].percentage = percentages[i]; | |
| 278 | 9 | s->params[0].distribution_maxrgb[i].percentile = | |
| 279 | 9 | (AVRational){ percentiles[i], RGB_DEN }; | |
| 280 | } | ||
| 281 | 1 | s->params[0].fraction_bright_pixels = | |
| 282 | (AVRational){ 250, FRACTION_PIXEL_DEN }; | ||
| 283 | |||
| 284 | 1 | s->params[0].tone_mapping_flag = 1; | |
| 285 | 1 | s->params[0].knee_point_x = (AVRational){ 512, KNEE_POINT_DEN }; | |
| 286 | 1 | s->params[0].knee_point_y = (AVRational){ 1024, KNEE_POINT_DEN }; | |
| 287 | 1 | s->params[0].num_bezier_curve_anchors = 9; | |
| 288 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
|
10 | for (int i = 0; i < 9; i++) |
| 289 | 9 | s->params[0].bezier_curve_anchors[i] = | |
| 290 | 9 | (AVRational){ 100 * (i + 1), BEZIER_ANCHOR_DEN }; | |
| 291 | |||
| 292 | 1 | s->params[0].color_saturation_mapping_flag = 0; | |
| 293 | 1 | } | |
| 294 | |||
| 295 | /* Deliberately NOT a conforming Version 1 payload: it combines a second | ||
| 296 | * processing window, both actual-peak-luminance matrices and | ||
| 297 | * ColorSaturationWeight, all of which §9.4 excludes for Version 1. It exists | ||
| 298 | * only to drive the optional serializer/parser branches those fields guard. | ||
| 299 | * | ||
| 300 | * tone_mapping_flag stays set for every window because the serializer writes | ||
| 301 | * color_saturation_mapping_flag inside the tone-mapping block while the parser | ||
| 302 | * reads it outside; only tone_mapping_flag=1 round-trips today. */ | ||
| 303 | 1 | static void fill_hdr_plus_synthetic(AVDynamicHDRPlus *s) | |
| 304 | { | ||
| 305 | 1 | memset(s, 0, sizeof(*s)); | |
| 306 | |||
| 307 | 1 | s->application_version = 1; | |
| 308 | 1 | s->num_windows = 2; | |
| 309 | 1 | s->targeted_system_display_maximum_luminance = | |
| 310 | (AVRational){ 10000, LUMINANCE_DEN }; | ||
| 311 | |||
| 312 | 1 | s->params[1].window_upper_left_corner_x = (AVRational){ 100, 1 }; | |
| 313 | 1 | s->params[1].window_upper_left_corner_y = (AVRational){ 120, 1 }; | |
| 314 | 1 | s->params[1].window_lower_right_corner_x = (AVRational){ 500, 1 }; | |
| 315 | 1 | s->params[1].window_lower_right_corner_y = (AVRational){ 520, 1 }; | |
| 316 | 1 | s->params[1].center_of_ellipse_x = 300; | |
| 317 | 1 | s->params[1].center_of_ellipse_y = 320; | |
| 318 | 1 | s->params[1].rotation_angle = 45; | |
| 319 | 1 | s->params[1].semimajor_axis_internal_ellipse = 50; | |
| 320 | 1 | s->params[1].semimajor_axis_external_ellipse = 100; | |
| 321 | 1 | s->params[1].semiminor_axis_external_ellipse = 80; | |
| 322 | 1 | s->params[1].overlap_process_option = 1; | |
| 323 | |||
| 324 | 1 | s->params[0].maxscl[0] = (AVRational){ 50000, RGB_DEN }; | |
| 325 | 1 | s->params[0].maxscl[1] = (AVRational){ 60000, RGB_DEN }; | |
| 326 | 1 | s->params[0].maxscl[2] = (AVRational){ 70000, RGB_DEN }; | |
| 327 | 1 | s->params[0].average_maxrgb = (AVRational){ 40000, RGB_DEN }; | |
| 328 | 1 | s->params[0].num_distribution_maxrgb_percentiles = 2; | |
| 329 | 1 | s->params[0].distribution_maxrgb[0].percentage = 50; | |
| 330 | 1 | s->params[0].distribution_maxrgb[0].percentile = | |
| 331 | (AVRational){ 30000, RGB_DEN }; | ||
| 332 | 1 | s->params[0].distribution_maxrgb[1].percentage = 99; | |
| 333 | 1 | s->params[0].distribution_maxrgb[1].percentile = | |
| 334 | (AVRational){ 90000, RGB_DEN }; | ||
| 335 | 1 | s->params[0].fraction_bright_pixels = | |
| 336 | (AVRational){ 250, FRACTION_PIXEL_DEN }; | ||
| 337 | |||
| 338 | 1 | s->params[1].maxscl[0] = (AVRational){ 20000, RGB_DEN }; | |
| 339 | 1 | s->params[1].maxscl[1] = (AVRational){ 30000, RGB_DEN }; | |
| 340 | 1 | s->params[1].maxscl[2] = (AVRational){ 40000, RGB_DEN }; | |
| 341 | 1 | s->params[1].average_maxrgb = (AVRational){ 25000, RGB_DEN }; | |
| 342 | 1 | s->params[1].num_distribution_maxrgb_percentiles = 1; | |
| 343 | 1 | s->params[1].distribution_maxrgb[0].percentage = 25; | |
| 344 | 1 | s->params[1].distribution_maxrgb[0].percentile = | |
| 345 | (AVRational){ 12500, RGB_DEN }; | ||
| 346 | 1 | s->params[1].fraction_bright_pixels = | |
| 347 | (AVRational){ 100, FRACTION_PIXEL_DEN }; | ||
| 348 | |||
| 349 | 1 | s->targeted_system_display_actual_peak_luminance_flag = 1; | |
| 350 | 1 | s->num_rows_targeted_system_display_actual_peak_luminance = 2; | |
| 351 | 1 | s->num_cols_targeted_system_display_actual_peak_luminance = 3; | |
| 352 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (int i = 0; i < 2; i++) |
| 353 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | for (int j = 0; j < 3; j++) |
| 354 | 6 | s->targeted_system_display_actual_peak_luminance[i][j] = | |
| 355 | 6 | (AVRational){ i * 3 + j, PEAK_LUMINANCE_DEN }; | |
| 356 | |||
| 357 | 1 | s->mastering_display_actual_peak_luminance_flag = 1; | |
| 358 | 1 | s->num_rows_mastering_display_actual_peak_luminance = 3; | |
| 359 | 1 | s->num_cols_mastering_display_actual_peak_luminance = 2; | |
| 360 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for (int i = 0; i < 3; i++) |
| 361 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
|
9 | for (int j = 0; j < 2; j++) |
| 362 | 6 | s->mastering_display_actual_peak_luminance[i][j] = | |
| 363 | 6 | (AVRational){ 15 - (i * 2 + j), PEAK_LUMINANCE_DEN }; | |
| 364 | |||
| 365 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (int w = 0; w < 2; w++) { |
| 366 | 2 | s->params[w].tone_mapping_flag = 1; | |
| 367 | 2 | s->params[w].knee_point_x = (AVRational){ 500 + w, KNEE_POINT_DEN }; | |
| 368 | 2 | s->params[w].knee_point_y = (AVRational){ 800 + w, KNEE_POINT_DEN }; | |
| 369 | 2 | s->params[w].num_bezier_curve_anchors = 3; | |
| 370 | 2 | s->params[w].bezier_curve_anchors[0] = | |
| 371 | 2 | (AVRational){ 100 + w, BEZIER_ANCHOR_DEN }; | |
| 372 | 2 | s->params[w].bezier_curve_anchors[1] = | |
| 373 | 2 | (AVRational){ 500 + w, BEZIER_ANCHOR_DEN }; | |
| 374 | 2 | s->params[w].bezier_curve_anchors[2] = | |
| 375 | 2 | (AVRational){ 900 + w, BEZIER_ANCHOR_DEN }; | |
| 376 | 2 | s->params[w].color_saturation_mapping_flag = 1; | |
| 377 | 2 | s->params[w].color_saturation_weight = | |
| 378 | 2 | (AVRational){ 8 + w, SATURATION_DEN }; | |
| 379 | } | ||
| 380 | 1 | } | |
| 381 | |||
| 382 | 1 | static void test_hdr_plus(void) | |
| 383 | { | ||
| 384 | AVDynamicHDRPlus *hdr, *hdr_rt; | ||
| 385 | AVFrame *frame; | ||
| 386 | 1 | size_t size = 0, required = 0; | |
| 387 | 1 | uint8_t *buf = NULL; | |
| 388 | int ret; | ||
| 389 | |||
| 390 | 1 | printf("=== AVDynamicHDRPlus ===\n"); | |
| 391 | |||
| 392 | 1 | printf("Testing av_dynamic_hdr_plus_alloc()\n"); | |
| 393 | 1 | hdr = av_dynamic_hdr_plus_alloc(&size); | |
| 394 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("alloc: %s size>0=%s\n", hdr ? "OK" : "FAIL", |
| 395 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | size > 0 ? "yes" : "no"); |
| 396 | 1 | av_freep(&hdr); | |
| 397 | |||
| 398 | 1 | hdr = av_dynamic_hdr_plus_alloc(NULL); | |
| 399 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("alloc (no size): %s\n", hdr ? "OK" : "FAIL"); |
| 400 | 1 | av_freep(&hdr); | |
| 401 | |||
| 402 | 1 | printf("\nTesting av_dynamic_hdr_plus_create_side_data()\n"); | |
| 403 | 1 | frame = av_frame_alloc(); | |
| 404 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (frame) { |
| 405 | 1 | hdr = av_dynamic_hdr_plus_create_side_data(frame); | |
| 406 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("create_side_data: %s\n", hdr ? "OK" : "FAIL"); |
| 407 | 1 | av_frame_free(&frame); | |
| 408 | } | ||
| 409 | |||
| 410 | 1 | hdr = av_dynamic_hdr_plus_alloc(NULL); | |
| 411 | 1 | hdr_rt = av_dynamic_hdr_plus_alloc(NULL); | |
| 412 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (!hdr || !hdr_rt) { |
| 413 | ✗ | av_freep(&hdr); | |
| 414 | ✗ | av_freep(&hdr_rt); | |
| 415 | ✗ | return; | |
| 416 | } | ||
| 417 | 1 | fill_hdr_plus_conforming(hdr); | |
| 418 | |||
| 419 | /* Size-query mode: data=NULL, size receives the required byte count. */ | ||
| 420 | 1 | printf("\nTesting av_dynamic_hdr_plus_to_t35() size query\n"); | |
| 421 | 1 | required = 0; | |
| 422 | 1 | ret = av_dynamic_hdr_plus_to_t35(hdr, NULL, &required); | |
| 423 | 1 | printf("size query: ret=%d required>0=%s\n", ret, | |
| 424 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | required > 0 ? "yes" : "no"); |
| 425 | |||
| 426 | /* Allocation mode: *data=NULL, the function allocates the buffer. */ | ||
| 427 | 1 | printf("\nTesting av_dynamic_hdr_plus_to_t35() allocation\n"); | |
| 428 | 1 | buf = NULL; | |
| 429 | 1 | size = 0; | |
| 430 | 1 | ret = av_dynamic_hdr_plus_to_t35(hdr, &buf, &size); | |
| 431 | 1 | printf("alloc mode: ret=%d size_match=%s\n", ret, | |
| 432 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | size == required ? "yes" : "no"); |
| 433 | 1 | av_freep(&buf); | |
| 434 | |||
| 435 | /* Existing-buffer mode: a caller-owned buffer is filled in place. */ | ||
| 436 | 1 | printf("\nTesting av_dynamic_hdr_plus_to_t35() existing buffer\n"); | |
| 437 | 1 | buf = av_malloc(required); | |
| 438 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (buf) { |
| 439 | 1 | uint8_t *orig = buf; | |
| 440 | 1 | size = required; | |
| 441 | 1 | ret = av_dynamic_hdr_plus_to_t35(hdr, &buf, &size); | |
| 442 | 2 | printf("existing buf: ret=%d same_pointer=%s size_match=%s\n", ret, | |
| 443 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | buf == orig ? "yes" : "no", |
| 444 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | size == required ? "yes" : "no"); |
| 445 | 1 | av_freep(&buf); | |
| 446 | } | ||
| 447 | |||
| 448 | /* Buffer-too-small: caller-owned buffer shorter than required. */ | ||
| 449 | 1 | printf("\nTesting av_dynamic_hdr_plus_to_t35() buffer too small\n"); | |
| 450 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (required > 1) { |
| 451 | 1 | buf = av_malloc(required - 1); | |
| 452 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (buf) { |
| 453 | 1 | size = required - 1; | |
| 454 | 1 | ret = av_dynamic_hdr_plus_to_t35(hdr, &buf, &size); | |
| 455 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("too small: ret==AVERROR_BUFFER_TOO_SMALL=%s\n", |
| 456 | ret == AVERROR_BUFFER_TOO_SMALL ? "yes" : "no"); | ||
| 457 | 1 | av_freep(&buf); | |
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 461 | 1 | printf("\nTesting round trip, conforming ST 2094-40 Version 1 payload\n"); | |
| 462 | 1 | ret = hdr_plus_round_trip(hdr, hdr_rt); | |
| 463 | 1 | printf("round trip: ret=%d\n", ret); | |
| 464 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ret >= 0) |
| 465 | 1 | print_hdr_plus("decoded", hdr_rt); | |
| 466 | |||
| 467 | /* to_t35() ignores application_version and always writes the CTA-861-H | ||
| 468 | * value, so the parsed field does not echo an out-of-range input. */ | ||
| 469 | 1 | printf("\nTesting that to_t35() overrides application_version\n"); | |
| 470 | 1 | hdr->application_version = 7; | |
| 471 | 1 | ret = hdr_plus_round_trip(hdr, hdr_rt); | |
| 472 | 1 | printf("input=7 ret=%d decoded application_version=%u\n", ret, | |
| 473 | 1 | hdr_rt->application_version); | |
| 474 | 1 | hdr->application_version = 1; | |
| 475 | |||
| 476 | 1 | printf("\nTesting round trip, synthetic payload (branch coverage only)\n"); | |
| 477 | 1 | fill_hdr_plus_synthetic(hdr); | |
| 478 | 1 | ret = hdr_plus_round_trip(hdr, hdr_rt); | |
| 479 | 1 | printf("round trip: ret=%d\n", ret); | |
| 480 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ret >= 0) |
| 481 | 1 | print_hdr_plus("decoded", hdr_rt); | |
| 482 | |||
| 483 | 1 | printf("\nTesting error paths\n"); | |
| 484 | 1 | buf = NULL; | |
| 485 | 1 | size = 0; | |
| 486 | 1 | ret = av_dynamic_hdr_plus_to_t35(NULL, &buf, &size); | |
| 487 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("to_t35 NULL s: ret==AVERROR(EINVAL)=%s\n", |
| 488 | ret == AVERROR(EINVAL) ? "yes" : "no"); | ||
| 489 | |||
| 490 | 1 | ret = av_dynamic_hdr_plus_to_t35(hdr, NULL, NULL); | |
| 491 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("to_t35 no data no size: ret==AVERROR(EINVAL)=%s\n", |
| 492 | ret == AVERROR(EINVAL) ? "yes" : "no"); | ||
| 493 | |||
| 494 | 1 | ret = av_dynamic_hdr_plus_from_t35(NULL, (const uint8_t *)"", 0); | |
| 495 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("from_t35 NULL s: ret==AVERROR(EINVAL)=%s\n", |
| 496 | ret == AVERROR(EINVAL) ? "yes" : "no"); | ||
| 497 | |||
| 498 | { | ||
| 499 | /* Oversized input is rejected before parsing. */ | ||
| 500 | 1 | size_t big = AV_HDR_PLUS_MAX_PAYLOAD_SIZE + 1; | |
| 501 | 1 | uint8_t *oversized = av_mallocz(big); | |
| 502 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (oversized) { |
| 503 | 1 | ret = av_dynamic_hdr_plus_from_t35(hdr_rt, oversized, big); | |
| 504 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("from_t35 oversized: ret==AVERROR(EINVAL)=%s\n", |
| 505 | ret == AVERROR(EINVAL) ? "yes" : "no"); | ||
| 506 | 1 | av_free(oversized); | |
| 507 | } | ||
| 508 | } | ||
| 509 | |||
| 510 | 1 | av_freep(&hdr); | |
| 511 | 1 | av_freep(&hdr_rt); | |
| 512 | |||
| 513 | 1 | printf("\nTesting OOM path\n"); | |
| 514 | 1 | av_max_alloc(1); | |
| 515 | 1 | hdr = av_dynamic_hdr_plus_alloc(&size); | |
| 516 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | printf("alloc OOM: %s\n", hdr ? "FAIL" : "OK"); |
| 517 | 1 | av_max_alloc(INT_MAX); | |
| 518 | 1 | av_freep(&hdr); | |
| 519 | } | ||
| 520 | |||
| 521 | /* Table C.2 early-out: no adaptive tone map, custom reference white only. */ | ||
| 522 | 1 | static void fill_app5_minimal(AVDynamicHDRSmpte2094App5 *s) | |
| 523 | { | ||
| 524 | 1 | memset(s, 0, sizeof(*s)); | |
| 525 | 1 | s->application_version = 1; | |
| 526 | 1 | s->minimum_application_version = 0; | |
| 527 | 1 | s->has_custom_hdr_reference_white_flag = 1; | |
| 528 | 1 | s->hdr_reference_white = 0x0203; | |
| 529 | 1 | s->has_adaptive_tone_map_flag = 0; | |
| 530 | 1 | } | |
| 531 | |||
| 532 | /* Table C.3 early-out: reference-white tone mapping, no alternate images. */ | ||
| 533 | 1 | static void fill_app5_reference_white(AVDynamicHDRSmpte2094App5 *s) | |
| 534 | { | ||
| 535 | 1 | memset(s, 0, sizeof(*s)); | |
| 536 | 1 | s->application_version = 2; | |
| 537 | 1 | s->has_adaptive_tone_map_flag = 1; | |
| 538 | 1 | s->baseline_hdr_headroom = 0x0abc; | |
| 539 | 1 | s->use_reference_white_tone_mapping_flag = 1; | |
| 540 | 1 | } | |
| 541 | |||
| 542 | /* Per-image parameters: explicit gain application space chromaticities, | ||
| 543 | * component mixing type 3 with a mix of present and absent coefficients, and | ||
| 544 | * explicit control point slopes (theta). */ | ||
| 545 | 1 | static void fill_app5_per_image(AVDynamicHDRSmpte2094App5 *s) | |
| 546 | { | ||
| 547 | 1 | memset(s, 0, sizeof(*s)); | |
| 548 | 1 | s->application_version = 1; | |
| 549 | 1 | s->has_adaptive_tone_map_flag = 1; | |
| 550 | 1 | s->baseline_hdr_headroom = 0x0abc; | |
| 551 | 1 | s->num_alternate_images = 2; | |
| 552 | 1 | s->gain_application_space_chromaticities_flag = 3; | |
| 553 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
|
9 | for (int r = 0; r < 8; r++) |
| 554 | 8 | s->gain_application_space_chromaticities[r] = 100 * (r + 1); | |
| 555 | 1 | s->has_common_component_mix_params_flag = 0; | |
| 556 | 1 | s->has_common_curve_params_flag = 0; | |
| 557 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (int a = 0; a < 2; a++) { |
| 558 | 2 | s->alternate_hdr_headrooms[a] = 0x0100 + a; | |
| 559 | 2 | s->component_mixing_type[a] = 3; | |
| 560 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2 times.
|
14 | for (int k = 0; k < 6; k++) { |
| 561 | 12 | s->has_component_mixing_coefficient_flag[a][k] = k & 1; | |
| 562 | 12 | s->component_mixing_coefficient[a][k] = 0x1000 + 0x10 * a + k; | |
| 563 | } | ||
| 564 | 2 | s->gain_curve_num_control_points_minus_1[a] = 1; | |
| 565 | 2 | s->gain_curve_use_pchip_slope_flag[a] = 0; | |
| 566 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | for (int c = 0; c < 2; c++) { |
| 567 | 4 | s->gain_curve_control_points_x[a][c] = 0x2000 + 0x10 * a + c; | |
| 568 | 4 | s->gain_curve_control_points_y[a][c] = 0x3000 + 0x10 * a + c; | |
| 569 | 4 | s->gain_curve_control_points_theta[a][c] = 0x4000 + 0x10 * a + c; | |
| 570 | } | ||
| 571 | } | ||
| 572 | 1 | } | |
| 573 | |||
| 574 | /* The complementary selectors: no explicit chromaticities, a component mixing | ||
| 575 | * type other than 3, mixing and curve parameters shared from alternate 0, and | ||
| 576 | * the pchip slope, which omits theta from the payload. | ||
| 577 | * | ||
| 578 | * The common_* flags make the parser copy alternate 0's parameters to the | ||
| 579 | * other alternates, so the fixture sets them identically everywhere; only | ||
| 580 | * alternate_hdr_headrooms and the y control points stay per-image. */ | ||
| 581 | 1 | static void fill_app5_common(AVDynamicHDRSmpte2094App5 *s) | |
| 582 | { | ||
| 583 | 1 | memset(s, 0, sizeof(*s)); | |
| 584 | 1 | s->application_version = 1; | |
| 585 | 1 | s->has_adaptive_tone_map_flag = 1; | |
| 586 | 1 | s->baseline_hdr_headroom = 0x0def; | |
| 587 | 1 | s->num_alternate_images = 3; | |
| 588 | 1 | s->gain_application_space_chromaticities_flag = 0; | |
| 589 | 1 | s->has_common_component_mix_params_flag = 1; | |
| 590 | 1 | s->has_common_curve_params_flag = 1; | |
| 591 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | for (int a = 0; a < 3; a++) { |
| 592 | 3 | s->alternate_hdr_headrooms[a] = 0x0200 + a; | |
| 593 | 3 | s->component_mixing_type[a] = 1; | |
| 594 | 3 | s->gain_curve_num_control_points_minus_1[a] = 2; | |
| 595 | 3 | s->gain_curve_use_pchip_slope_flag[a] = 1; | |
| 596 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
|
12 | for (int c = 0; c < 3; c++) { |
| 597 | 9 | s->gain_curve_control_points_x[a][c] = 0x5000 + c; | |
| 598 | 9 | s->gain_curve_control_points_y[a][c] = 0x6000 + 0x10 * a + c; | |
| 599 | } | ||
| 600 | } | ||
| 601 | 1 | } | |
| 602 | |||
| 603 | 1 | static void test_app5(void) | |
| 604 | { | ||
| 605 | AVDynamicHDRSmpte2094App5 *app5, *app5_rt; | ||
| 606 | AVFrame *frame; | ||
| 607 | 1 | size_t size = 0, required = 0; | |
| 608 | 1 | uint8_t *buf = NULL; | |
| 609 | int ret; | ||
| 610 | |||
| 611 | 1 | printf("\n=== AVDynamicHDRSmpte2094App5 ===\n"); | |
| 612 | 1 | printf("Testing av_dynamic_hdr_smpte2094_app5_alloc()\n"); | |
| 613 | 1 | app5 = av_dynamic_hdr_smpte2094_app5_alloc(&size); | |
| 614 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("alloc: %s size>0=%s\n", app5 ? "OK" : "FAIL", |
| 615 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | size > 0 ? "yes" : "no"); |
| 616 | 1 | av_freep(&app5); | |
| 617 | |||
| 618 | 1 | printf("\nTesting av_dynamic_hdr_smpte2094_app5_create_side_data()\n"); | |
| 619 | 1 | frame = av_frame_alloc(); | |
| 620 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (frame) { |
| 621 | 1 | app5 = av_dynamic_hdr_smpte2094_app5_create_side_data(frame); | |
| 622 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("create_side_data: %s\n", app5 ? "OK" : "FAIL"); |
| 623 | 1 | av_frame_free(&frame); | |
| 624 | } | ||
| 625 | |||
| 626 | 1 | app5 = av_dynamic_hdr_smpte2094_app5_alloc(NULL); | |
| 627 | 1 | app5_rt = av_dynamic_hdr_smpte2094_app5_alloc(NULL); | |
| 628 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (!app5 || !app5_rt) { |
| 629 | ✗ | av_freep(&app5); | |
| 630 | ✗ | av_freep(&app5_rt); | |
| 631 | ✗ | return; | |
| 632 | } | ||
| 633 | 1 | fill_app5_minimal(app5); | |
| 634 | |||
| 635 | 1 | printf("\nTesting av_dynamic_hdr_smpte2094_app5_to_t35()\n"); | |
| 636 | 1 | required = 0; | |
| 637 | 1 | ret = av_dynamic_hdr_smpte2094_app5_to_t35(app5, NULL, &required); | |
| 638 | 1 | printf("size query: ret=%d required>0=%s\n", ret, | |
| 639 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | required > 0 ? "yes" : "no"); |
| 640 | |||
| 641 | 1 | buf = NULL; | |
| 642 | 1 | size = 0; | |
| 643 | 1 | ret = av_dynamic_hdr_smpte2094_app5_to_t35(app5, &buf, &size); | |
| 644 | 1 | printf("alloc mode: ret=%d size_match=%s\n", ret, | |
| 645 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | size == required ? "yes" : "no"); |
| 646 | 1 | av_freep(&buf); | |
| 647 | |||
| 648 | 1 | printf("\nTesting round trip, no adaptive tone map\n"); | |
| 649 | 1 | ret = app5_round_trip(app5, app5_rt); | |
| 650 | 1 | printf("round trip: ret=%d\n", ret); | |
| 651 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ret >= 0) |
| 652 | 1 | print_app5("decoded", app5_rt); | |
| 653 | |||
| 654 | 1 | printf("\nTesting round trip, reference-white tone mapping\n"); | |
| 655 | 1 | fill_app5_reference_white(app5); | |
| 656 | 1 | ret = app5_round_trip(app5, app5_rt); | |
| 657 | 1 | printf("round trip: ret=%d\n", ret); | |
| 658 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ret >= 0) |
| 659 | 1 | print_app5("decoded", app5_rt); | |
| 660 | |||
| 661 | 1 | printf("\nTesting round trip, per-image mixing and curve parameters\n"); | |
| 662 | 1 | fill_app5_per_image(app5); | |
| 663 | 1 | ret = app5_round_trip(app5, app5_rt); | |
| 664 | 1 | printf("round trip: ret=%d\n", ret); | |
| 665 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ret >= 0) |
| 666 | 1 | print_app5("decoded", app5_rt); | |
| 667 | |||
| 668 | 1 | printf("\nTesting round trip, common mixing and curve parameters\n"); | |
| 669 | 1 | fill_app5_common(app5); | |
| 670 | 1 | ret = app5_round_trip(app5, app5_rt); | |
| 671 | 1 | printf("round trip: ret=%d\n", ret); | |
| 672 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ret >= 0) |
| 673 | 1 | print_app5("decoded", app5_rt); | |
| 674 | |||
| 675 | 1 | printf("\nTesting error paths\n"); | |
| 676 | 1 | buf = NULL; | |
| 677 | 1 | size = 0; | |
| 678 | 1 | ret = av_dynamic_hdr_smpte2094_app5_to_t35(NULL, &buf, &size); | |
| 679 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("to_t35 NULL s: ret==AVERROR(EINVAL)=%s\n", |
| 680 | ret == AVERROR(EINVAL) ? "yes" : "no"); | ||
| 681 | |||
| 682 | 1 | ret = av_dynamic_hdr_smpte2094_app5_from_t35(NULL, (const uint8_t *)"", 0); | |
| 683 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("from_t35 NULL s: ret==AVERROR(EINVAL)=%s\n", |
| 684 | ret == AVERROR(EINVAL) ? "yes" : "no"); | ||
| 685 | |||
| 686 | /* application_version does not fit the 3-bit field. */ | ||
| 687 | 1 | app5->application_version = 8; | |
| 688 | 1 | ret = av_dynamic_hdr_smpte2094_app5_to_t35(app5, NULL, &size); | |
| 689 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("to_t35 invalid application_version: ret==AVERROR_INVALIDDATA=%s\n", |
| 690 | ret == AVERROR_INVALIDDATA ? "yes" : "no"); | ||
| 691 | 1 | app5->application_version = 1; | |
| 692 | |||
| 693 | /* minimum_application_version above the documented maximum. */ | ||
| 694 | 1 | app5->minimum_application_version = 3; | |
| 695 | 1 | ret = av_dynamic_hdr_smpte2094_app5_to_t35(app5, NULL, &size); | |
| 696 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("to_t35 invalid minimum_application_version:" |
| 697 | " ret==AVERROR_INVALIDDATA=%s\n", | ||
| 698 | ret == AVERROR_INVALIDDATA ? "yes" : "no"); | ||
| 699 | 1 | app5->minimum_application_version = 0; | |
| 700 | |||
| 701 | /* More alternate images than the 3-bit count admits. */ | ||
| 702 | 1 | app5->num_alternate_images = 5; | |
| 703 | 1 | ret = av_dynamic_hdr_smpte2094_app5_to_t35(app5, NULL, &size); | |
| 704 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | printf("to_t35 too many alternate images: ret==AVERROR_INVALIDDATA=%s\n", |
| 705 | ret == AVERROR_INVALIDDATA ? "yes" : "no"); | ||
| 706 | |||
| 707 | 1 | av_freep(&app5); | |
| 708 | 1 | av_freep(&app5_rt); | |
| 709 | |||
| 710 | 1 | printf("\nTesting OOM path\n"); | |
| 711 | 1 | av_max_alloc(1); | |
| 712 | 1 | app5 = av_dynamic_hdr_smpte2094_app5_alloc(&size); | |
| 713 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | printf("alloc OOM: %s\n", app5 ? "FAIL" : "OK"); |
| 714 | 1 | av_max_alloc(INT_MAX); | |
| 715 | 1 | av_freep(&app5); | |
| 716 | } | ||
| 717 | |||
| 718 | 1 | int main(void) | |
| 719 | { | ||
| 720 | 1 | test_hdr_plus(); | |
| 721 | 1 | test_app5(); | |
| 722 | 1 | return 0; | |
| 723 | } | ||
| 724 |