FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vvc/sei.c
Date: 2025-06-05 01:40:37
Exec Total Coverage
Lines: 28 136 20.6%
Functions: 4 10 40.0%
Branches: 6 58 10.3%

Line Branch Exec Source
1 /*
2 * VVC Supplementary Enhancement Information messages
3 *
4 * copyright (c) 2024 Wu Jianhua <toqsxw@outlook.com>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "sei.h"
24 #include "dec.h"
25 #include "libavutil/refstruct.h"
26
27 static int decode_film_grain_characteristics(H2645SEIFilmGrainCharacteristics *h, const SEIRawFilmGrainCharacteristics *s, const VVCFrameContext *fc)
28 {
29 const VVCSPS *sps = fc->ps.sps;
30
31 h->present = !s->fg_characteristics_cancel_flag;
32 if (h->present) {
33 h->model_id = s->fg_model_id;
34 h->separate_colour_description_present_flag = s->fg_separate_colour_description_present_flag;
35 if (h->separate_colour_description_present_flag) {
36 h->bit_depth_luma = s->fg_bit_depth_luma_minus8 + 8;
37 h->bit_depth_chroma = s->fg_bit_depth_chroma_minus8 + 8;
38 h->full_range = s->fg_full_range_flag;
39 h->color_primaries = s->fg_colour_primaries;
40 h->transfer_characteristics = s->fg_transfer_characteristics;
41 h->matrix_coeffs = s->fg_matrix_coeffs;
42 } else {
43 if (!sps) {
44 av_log(fc->log_ctx, AV_LOG_ERROR,
45 "No active SPS for film_grain_characteristics.\n");
46 return AVERROR_INVALIDDATA;
47 }
48 h->bit_depth_luma = sps->bit_depth;
49 h->bit_depth_chroma = sps->bit_depth;
50 h->full_range = sps->r->vui.vui_full_range_flag;
51 h->color_primaries = sps->r->vui.vui_colour_primaries;
52 h->transfer_characteristics = sps->r->vui.vui_transfer_characteristics;
53 h->matrix_coeffs = sps->r->vui.vui_matrix_coeffs ;
54 }
55
56 h->blending_mode_id = s->fg_blending_mode_id;
57 h->log2_scale_factor = s->fg_log2_scale_factor;
58
59 for (int c = 0; c < 3; c++) {
60 h->comp_model_present_flag[c] = s->fg_comp_model_present_flag[c];
61 if (h->comp_model_present_flag[c]) {
62 h->num_intensity_intervals[c] = s->fg_num_intensity_intervals_minus1[c] + 1;
63 h->num_model_values[c] = s->fg_num_model_values_minus1[c] + 1;
64
65 if (h->num_model_values[c] > 6)
66 return AVERROR_INVALIDDATA;
67
68 for (int i = 0; i < h->num_intensity_intervals[c]; i++) {
69 h->intensity_interval_lower_bound[c][i] = s->fg_intensity_interval_lower_bound[c][i];
70 h->intensity_interval_upper_bound[c][i] = s->fg_intensity_interval_upper_bound[c][i];
71 for (int j = 0; j < h->num_model_values[c]; j++)
72 h->comp_model_value[c][i][j] = s->fg_comp_model_value[c][i][j];
73 }
74 }
75 }
76
77 h->persistence_flag = s->fg_characteristics_persistence_flag;
78 }
79
80 return 0;
81 }
82
83 888 static int decode_decoded_picture_hash(H274SEIPictureHash *h, const SEIRawDecodedPictureHash *s)
84 {
85 888 h->present = 1;
86 888 h->hash_type = s->dph_sei_hash_type;
87
1/2
✓ Branch 0 taken 888 times.
✗ Branch 1 not taken.
888 if (h->hash_type == 0)
88 888 memcpy(h->md5, s->dph_sei_picture_md5, sizeof(h->md5));
89 else if (h->hash_type == 1)
90 memcpy(h->crc, s->dph_sei_picture_crc, sizeof(h->crc));
91 else if (h->hash_type == 2)
92 memcpy(h->checksum, s->dph_sei_picture_checksum, sizeof(h->checksum));
93
94 888 return 0;
95 }
96
97 static int decode_display_orientation(H2645SEIDisplayOrientation *h, const SEIRawDisplayOrientation *s)
98 {
99 int degrees[] = { 0, 0x8000, 0x4000, 0xC000 };
100
101 h->present = !s->display_orientation_cancel_flag;
102 if (h->present) {
103 if (s->display_orientation_transform_type > 7)
104 return AVERROR_INVALIDDATA;
105
106 h->vflip = 0;
107 if (s->display_orientation_transform_type == 1 ||
108 s->display_orientation_transform_type == 3 ||
109 s->display_orientation_transform_type == 4 ||
110 s->display_orientation_transform_type == 6) {
111 h->hflip = 1;
112 } else {
113 h->hflip = 0;
114 }
115 h->anticlockwise_rotation = degrees[s->display_orientation_transform_type >> 1];
116 }
117
118 return 0;
119 }
120
121 static int decode_content_light_level_info(H2645SEIContentLight *h, const SEIRawContentLightLevelInfo *s)
122 {
123 h->present = 1;
124 h->max_content_light_level = s->max_content_light_level;
125 h->max_pic_average_light_level = s->max_pic_average_light_level;
126
127 return 0;
128 }
129
130 static int decode_frame_field_info(H274SEIFrameFieldInfo *h, const SEIRawFrameFieldInformation *s)
131 {
132 if (s->ffi_source_scan_type > 3)
133 return AVERROR_INVALIDDATA;
134
135 h->present = 1;
136 if (s->ffi_field_pic_flag) {
137 if (s->ffi_bottom_field_flag)
138 h->picture_struct = AV_PICTURE_STRUCTURE_BOTTOM_FIELD;
139 else
140 h->picture_struct = AV_PICTURE_STRUCTURE_TOP_FIELD;
141 } else {
142 h->display_elemental_periods = s->ffi_display_elemental_periods_minus1 + 1;
143 }
144
145 h->source_scan_type = s->ffi_source_scan_type;
146 h->duplicate_flag = s->ffi_duplicate_flag;
147
148 return 0;
149 }
150
151 static int decode_ambient_viewing_environment(H2645SEIAmbientViewingEnvironment *h, const SEIRawAmbientViewingEnvironment *s)
152 {
153 h->present = 1;
154 h->ambient_illuminance = s->ambient_illuminance;
155 h->ambient_light_x = s->ambient_light_x;
156 h->ambient_light_y = s->ambient_light_y;
157
158 return 0;
159 }
160
161 static int decode_mastering_display_colour_volume(H2645SEIMasteringDisplay *h, const SEIRawMasteringDisplayColourVolume *s)
162 {
163 h->present = 1;
164
165 for (int c = 0; c < 3; c++) {
166 h->display_primaries[c][0] = s->display_primaries_x[c];
167 h->display_primaries[c][1] = s->display_primaries_y[c];
168 }
169
170 h->white_point[0] = s->white_point_x;
171 h->white_point[1] = s->white_point_y;
172
173 h->max_luminance = s->max_display_mastering_luminance;
174 h->min_luminance = s->min_display_mastering_luminance;
175
176 return 0;
177 }
178
179 956 int ff_vvc_sei_decode(VVCSEI *s, const H266RawSEI *sei, const struct VVCFrameContext *fc)
180 {
181 956 H2645SEI *c = &s->common;
182
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 956 times.
956 if (!sei)
184 return AVERROR_INVALIDDATA;
185
186
1/2
✓ Branch 0 taken 956 times.
✗ Branch 1 not taken.
956 for (int i = 0; i < sei->message_list.nb_messages; i++) {
187 956 SEIRawMessage *message = &sei->message_list.messages[i];
188 956 void *payload = message->payload;
189
190
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 888 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 68 times.
956 switch (message->payload_type) {
191 case SEI_TYPE_FILM_GRAIN_CHARACTERISTICS:
192 av_refstruct_unref(&c->film_grain_characteristics);
193 c->film_grain_characteristics = av_refstruct_allocz(sizeof(*c->film_grain_characteristics));
194 if (!c->film_grain_characteristics)
195 return AVERROR(ENOMEM);
196 return decode_film_grain_characteristics(c->film_grain_characteristics, payload, fc);
197
198 888 case SEI_TYPE_DECODED_PICTURE_HASH:
199 888 return decode_decoded_picture_hash(&s->picture_hash, payload);
200
201 case SEI_TYPE_DISPLAY_ORIENTATION:
202 return decode_display_orientation(&s->common.display_orientation, payload);
203
204 case SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO:
205 return decode_content_light_level_info(&s->common.content_light, payload);
206
207 case SEI_TYPE_FRAME_FIELD_INFO:
208 return decode_frame_field_info(&s->frame_field_info, payload);
209
210 case SEI_TYPE_AMBIENT_VIEWING_ENVIRONMENT:
211 return decode_ambient_viewing_environment(&s->common.ambient_viewing_environment, payload);
212
213 case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME:
214 return decode_mastering_display_colour_volume(&s->common.mastering_display, payload);
215
216 68 default:
217 68 av_log(fc->log_ctx, AV_LOG_DEBUG, "Skipped %s SEI %d\n",
218
1/2
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
68 sei->nal_unit_header.nal_unit_type == VVC_PREFIX_SEI_NUT ?
219 "PREFIX" : "SUFFIX", message->payload_type);
220 68 return FF_H2645_SEI_MESSAGE_UNHANDLED;
221 }
222 }
223
224 return 0;
225 }
226
227 873 int ff_vvc_sei_replace(VVCSEI *dst, const VVCSEI *src)
228 {
229 873 dst->picture_hash.present = 0; // drop hash
230 873 dst->frame_field_info.present = 0; // drop field info
231 873 return ff_h2645_sei_ctx_replace(&dst->common, &src->common);
232 }
233
234 704 void ff_vvc_sei_reset(VVCSEI *s)
235 {
236 704 ff_h2645_sei_reset(&s->common);
237 704 s->picture_hash.present = 0;
238 704 s->frame_field_info.present = 0;
239 704 }
240