FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/hevc/sei.c
Date: 2025-03-08 20:38:41
Exec Total Coverage
Lines: 121 178 68.0%
Functions: 10 10 100.0%
Branches: 59 105 56.2%

Line Branch Exec Source
1 /*
2 * HEVC Supplementary Enhancement Information messages
3 *
4 * Copyright (C) 2012 - 2013 Guillaume Martres
5 * Copyright (C) 2012 - 2013 Gildas Cocherel
6 * Copyright (C) 2013 Vittorio Giovara
7 *
8 * This file is part of FFmpeg.
9 *
10 * FFmpeg is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * FFmpeg is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with FFmpeg; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "bytestream.h"
26 #include "golomb.h"
27 #include "ps.h"
28 #include "sei.h"
29
30 7047 static int decode_nal_sei_decoded_picture_hash(HEVCSEIPictureHash *s,
31 GetByteContext *gb)
32 {
33 int cIdx;
34 uint8_t hash_type;
35 //uint16_t picture_crc;
36 //uint32_t picture_checksum;
37 7047 hash_type = bytestream2_get_byte(gb);
38
39
2/2
✓ Branch 0 taken 21141 times.
✓ Branch 1 taken 7047 times.
28188 for (cIdx = 0; cIdx < 3/*((s->sps->chroma_format_idc == 0) ? 1 : 3)*/; cIdx++) {
40
2/2
✓ Branch 0 taken 20091 times.
✓ Branch 1 taken 1050 times.
21141 if (hash_type == 0) {
41 20091 s->is_md5 = 1;
42 20091 bytestream2_get_buffer(gb, s->md5[cIdx], sizeof(s->md5[cIdx]));
43 } else if (hash_type == 1) {
44 // picture_crc = get_bits(gb, 16);
45 } else if (hash_type == 2) {
46 // picture_checksum = get_bits_long(gb, 32);
47 }
48 }
49 7047 return 0;
50 }
51
52 1394 static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb,
53 const HEVCParamSets *ps, void *logctx)
54 {
55 1394 HEVCSEIPictureTiming *h = &s->picture_timing;
56 1394 const HEVCSPS *sps = ps->sps_list[s->active_seq_parameter_set_id];
57
58
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 1328 times.
1394 if (!sps)
59 66 return AVERROR_INVALIDDATA;
60
61
2/2
✓ Branch 0 taken 727 times.
✓ Branch 1 taken 601 times.
1328 if (sps->vui.frame_field_info_present_flag) {
62 727 int pic_struct = get_bits(gb, 4);
63 727 h->picture_struct = AV_PICTURE_STRUCTURE_UNKNOWN;
64
4/6
✓ Branch 0 taken 727 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 717 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 717 times.
727 if (pic_struct == 2 || pic_struct == 10 || pic_struct == 12) {
65 10 av_log(logctx, AV_LOG_DEBUG, "BOTTOM Field\n");
66 10 h->picture_struct = AV_PICTURE_STRUCTURE_BOTTOM_FIELD;
67
4/6
✓ Branch 0 taken 717 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 717 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 706 times.
717 } else if (pic_struct == 1 || pic_struct == 9 || pic_struct == 11) {
68 11 av_log(logctx, AV_LOG_DEBUG, "TOP Field\n");
69 11 h->picture_struct = AV_PICTURE_STRUCTURE_TOP_FIELD;
70
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 } else if (pic_struct == 7) {
71 av_log(logctx, AV_LOG_DEBUG, "Frame/Field Doubling\n");
72 h->picture_struct = HEVC_SEI_PIC_STRUCT_FRAME_DOUBLING;
73
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 } else if (pic_struct == 8) {
74 av_log(logctx, AV_LOG_DEBUG, "Frame/Field Tripling\n");
75 h->picture_struct = HEVC_SEI_PIC_STRUCT_FRAME_TRIPLING;
76 }
77 }
78
79 1328 return 0;
80 }
81
82 52 static int decode_nal_sei_recovery_point(HEVCSEI *s, GetBitContext *gb)
83 {
84 52 HEVCSEIRecoveryPoint *rec = &s->recovery_point;
85 52 int recovery_poc_cnt = get_se_golomb(gb);
86
87
2/4
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 52 times.
52 if (recovery_poc_cnt > INT16_MAX || recovery_poc_cnt < INT16_MIN)
88 return AVERROR_INVALIDDATA;
89 52 rec->recovery_poc_cnt = recovery_poc_cnt;
90 52 rec->exact_match_flag = get_bits1(gb);
91 52 rec->broken_link_flag = get_bits1(gb);
92 52 rec->has_recovery_poc = 1;
93
94 52 return 0;
95 }
96
97 35 static int decode_nal_sei_active_parameter_sets(HEVCSEI *s, GetBitContext *gb, void *logctx)
98 {
99 int num_sps_ids_minus1;
100 unsigned active_seq_parameter_set_id;
101
102 35 get_bits(gb, 4); // active_video_parameter_set_id
103 35 get_bits(gb, 1); // self_contained_cvs_flag
104 35 get_bits(gb, 1); // num_sps_ids_minus1
105 35 num_sps_ids_minus1 = get_ue_golomb_long(gb); // num_sps_ids_minus1
106
107
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35 times.
35 if (num_sps_ids_minus1 < 0 || num_sps_ids_minus1 > 15) {
108 av_log(logctx, AV_LOG_ERROR, "num_sps_ids_minus1 %d invalid\n", num_sps_ids_minus1);
109 return AVERROR_INVALIDDATA;
110 }
111
112 35 active_seq_parameter_set_id = get_ue_golomb_long(gb);
113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (active_seq_parameter_set_id >= HEVC_MAX_SPS_COUNT) {
114 av_log(logctx, AV_LOG_ERROR, "active_parameter_set_id %d invalid\n", active_seq_parameter_set_id);
115 return AVERROR_INVALIDDATA;
116 }
117 35 s->active_seq_parameter_set_id = active_seq_parameter_set_id;
118
119 35 return 0;
120 }
121
122 136 static int decode_nal_sei_timecode(HEVCSEITimeCode *s, GetBitContext *gb)
123 {
124 136 s->num_clock_ts = get_bits(gb, 2);
125
126
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 136 times.
272 for (int i = 0; i < s->num_clock_ts; i++) {
127 136 s->clock_timestamp_flag[i] = get_bits(gb, 1);
128
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (s->clock_timestamp_flag[i]) {
130 s->units_field_based_flag[i] = get_bits(gb, 1);
131 s->counting_type[i] = get_bits(gb, 5);
132 s->full_timestamp_flag[i] = get_bits(gb, 1);
133 s->discontinuity_flag[i] = get_bits(gb, 1);
134 s->cnt_dropped_flag[i] = get_bits(gb, 1);
135
136 s->n_frames[i] = get_bits(gb, 9);
137
138 if (s->full_timestamp_flag[i]) {
139 s->seconds_value[i] = av_clip(get_bits(gb, 6), 0, 59);
140 s->minutes_value[i] = av_clip(get_bits(gb, 6), 0, 59);
141 s->hours_value[i] = av_clip(get_bits(gb, 5), 0, 23);
142 } else {
143 s->seconds_flag[i] = get_bits(gb, 1);
144 if (s->seconds_flag[i]) {
145 s->seconds_value[i] = av_clip(get_bits(gb, 6), 0, 59);
146 s->minutes_flag[i] = get_bits(gb, 1);
147 if (s->minutes_flag[i]) {
148 s->minutes_value[i] = av_clip(get_bits(gb, 6), 0, 59);
149 s->hours_flag[i] = get_bits(gb, 1);
150 if (s->hours_flag[i]) {
151 s->hours_value[i] = av_clip(get_bits(gb, 5), 0, 23);
152 }
153 }
154 }
155 }
156
157 s->time_offset_length[i] = get_bits(gb, 5);
158 if (s->time_offset_length[i] > 0) {
159 s->time_offset_value[i] = get_bits_long(gb, s->time_offset_length[i]);
160 }
161 }
162 }
163
164 136 s->present = 1;
165 136 return 0;
166 }
167
168 4 static int decode_nal_sei_3d_reference_displays_info(HEVCSEITDRDI *s, GetBitContext *gb)
169 {
170 4 s->prec_ref_display_width = get_ue_golomb(gb);
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->prec_ref_display_width > 31)
172 return AVERROR_INVALIDDATA;
173 4 s->ref_viewing_distance_flag = get_bits1(gb);
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->ref_viewing_distance_flag) {
175 s->prec_ref_viewing_dist = get_ue_golomb(gb);
176 if (s->prec_ref_viewing_dist > 31)
177 return AVERROR_INVALIDDATA;
178 }
179 4 s->num_ref_displays = get_ue_golomb(gb);
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->num_ref_displays > 31)
181 return AVERROR_INVALIDDATA;
182 4 s->num_ref_displays += 1;
183
184
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 for (int i = 0; i < s->num_ref_displays; i++) {
185 int length;
186 4 s->left_view_id[i] = get_ue_golomb(gb);
187 4 s->right_view_id[i] = get_ue_golomb(gb);
188 4 s->exponent_ref_display_width[i] = get_bits(gb, 6);
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->exponent_ref_display_width[i] > 62)
190 return AVERROR_INVALIDDATA;
191
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 else if (!s->exponent_ref_display_width[i])
192
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 length = FFMAX(0, (int)s->prec_ref_display_width - 30);
193 else
194 length = FFMAX(0, (int)s->exponent_ref_display_width[i] +
195 (int)s->prec_ref_display_width - 31);
196 4 s->mantissa_ref_display_width[i] = get_bits_long(gb, length);
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->ref_viewing_distance_flag) {
198 s->exponent_ref_viewing_distance[i] = get_bits(gb, 6);
199 if (s->exponent_ref_viewing_distance[i] > 62)
200 return AVERROR_INVALIDDATA;
201 else if (!s->exponent_ref_viewing_distance[i])
202 length = FFMAX(0, (int)s->prec_ref_viewing_dist - 30);
203 else
204 length = FFMAX(0, (int)s->exponent_ref_viewing_distance[i] +
205 (int)s->prec_ref_viewing_dist - 31);
206 s->mantissa_ref_viewing_distance[i] = get_bits_long(gb, length);
207 }
208 4 s->additional_shift_present_flag[i] = get_bits1(gb);
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (s->additional_shift_present_flag[i]) {
210 s->num_sample_shift[i] = get_bits(gb, 10);
211 if (s->num_sample_shift[i] > 1023)
212 return AVERROR_INVALIDDATA;
213 s->num_sample_shift[i] -= 512;
214 }
215 }
216 4 s->three_dimensional_reference_displays_extension_flag = get_bits1(gb);
217
218 4 return 0;
219 }
220
221 1889 static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte,
222 void *logctx, HEVCSEI *s,
223 const HEVCParamSets *ps, int type)
224 {
225
6/7
✗ Branch 0 not taken.
✓ Branch 1 taken 1394 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 35 times.
✓ Branch 4 taken 136 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 268 times.
1889 switch (type) {
226 case 256: // Mismatched value from HM 8.1
227 return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte);
228 1394 case SEI_TYPE_PIC_TIMING:
229 1394 return decode_nal_sei_pic_timing(s, gb, ps, logctx);
230 52 case SEI_TYPE_RECOVERY_POINT:
231 52 return decode_nal_sei_recovery_point(s, gb);
232 35 case SEI_TYPE_ACTIVE_PARAMETER_SETS:
233 35 return decode_nal_sei_active_parameter_sets(s, gb, logctx);
234 136 case SEI_TYPE_TIME_CODE:
235 136 return decode_nal_sei_timecode(&s->timecode, gb);
236 4 case SEI_TYPE_THREE_DIMENSIONAL_REFERENCE_DISPLAYS_INFO:
237 4 return decode_nal_sei_3d_reference_displays_info(&s->tdrdi, gb);
238 268 default: {
239 268 int ret = ff_h2645_sei_message_decode(&s->common, type, AV_CODEC_ID_HEVC,
240 gb, gbyte, logctx);
241
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 213 times.
268 if (ret == FF_H2645_SEI_MESSAGE_UNHANDLED)
242 55 av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type);
243 268 return ret;
244 }
245 }
246 }
247
248 7047 static int decode_nal_sei_suffix(GetBitContext *gb, GetByteContext *gbyte,
249 void *logctx, HEVCSEI *s, int type)
250 {
251
1/2
✓ Branch 0 taken 7047 times.
✗ Branch 1 not taken.
7047 switch (type) {
252 7047 case SEI_TYPE_DECODED_PICTURE_HASH:
253 7047 return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte);
254 default:
255 av_log(logctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", type);
256 return 0;
257 }
258 }
259
260 8936 static int decode_nal_sei_message(GetByteContext *gb, void *logctx, HEVCSEI *s,
261 const HEVCParamSets *ps, int nal_unit_type)
262 {
263 GetByteContext message_gbyte;
264 GetBitContext message_gb;
265 8936 int payload_type = 0;
266 8936 int payload_size = 0;
267 8936 int byte = 0xFF;
268 av_unused int ret;
269 8936 av_log(logctx, AV_LOG_DEBUG, "Decoding SEI\n");
270
271
2/2
✓ Branch 0 taken 8936 times.
✓ Branch 1 taken 8936 times.
17872 while (byte == 0xFF) {
272
2/4
✓ Branch 1 taken 8936 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8936 times.
8936 if (bytestream2_get_bytes_left(gb) < 2 || payload_type > INT_MAX - 255)
273 return AVERROR_INVALIDDATA;
274 8936 byte = bytestream2_get_byteu(gb);
275 8936 payload_type += byte;
276 }
277 8936 byte = 0xFF;
278
2/2
✓ Branch 0 taken 9093 times.
✓ Branch 1 taken 8936 times.
18029 while (byte == 0xFF) {
279
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9093 times.
9093 if (bytestream2_get_bytes_left(gb) < 1 + payload_size)
280 return AVERROR_INVALIDDATA;
281 9093 byte = bytestream2_get_byteu(gb);
282 9093 payload_size += byte;
283 }
284
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8936 times.
8936 if (bytestream2_get_bytes_left(gb) < payload_size)
285 return AVERROR_INVALIDDATA;
286 8936 bytestream2_init(&message_gbyte, gb->buffer, payload_size);
287 8936 ret = init_get_bits8(&message_gb, gb->buffer, payload_size);
288 av_assert1(ret >= 0);
289 8936 bytestream2_skipu(gb, payload_size);
290
2/2
✓ Branch 0 taken 1889 times.
✓ Branch 1 taken 7047 times.
8936 if (nal_unit_type == HEVC_NAL_SEI_PREFIX) {
291 1889 return decode_nal_sei_prefix(&message_gb, &message_gbyte,
292 logctx, s, ps, payload_type);
293 } else { /* nal_unit_type == NAL_SEI_SUFFIX */
294 7047 return decode_nal_sei_suffix(&message_gb, &message_gbyte,
295 logctx, s, payload_type);
296 }
297 }
298
299 8924 int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s,
300 const HEVCParamSets *ps, enum HEVCNALUnitType type)
301 {
302 GetByteContext gbyte;
303 int ret;
304
305 av_assert1((get_bits_count(gb) % 8) == 0);
306 8924 bytestream2_init(&gbyte, gb->buffer + get_bits_count(gb) / 8,
307 8924 get_bits_left(gb) / 8);
308
309 do {
310 8936 ret = decode_nal_sei_message(&gbyte, logctx, s, ps, type);
311
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 8870 times.
8936 if (ret < 0)
312 66 return ret;
313
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 8858 times.
8870 } while (bytestream2_get_bytes_left(&gbyte) > 0);
314 8858 return 1;
315 }
316