FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/hevc_sei.c
Date: 2023-03-31 03:41:15
Exec Total Coverage
Lines: 108 148 73.0%
Functions: 10 10 100.0%
Branches: 51 79 64.6%

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 "hevc_ps.h"
28 #include "hevc_sei.h"
29
30 6852 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 6852 hash_type = bytestream2_get_byte(gb);
38
39
2/2
✓ Branch 0 taken 20556 times.
✓ Branch 1 taken 6852 times.
27408 for (cIdx = 0; cIdx < 3/*((s->sps->chroma_format_idc == 0) ? 1 : 3)*/; cIdx++) {
40
2/2
✓ Branch 0 taken 19509 times.
✓ Branch 1 taken 1047 times.
20556 if (hash_type == 0) {
41 19509 s->is_md5 = 1;
42 19509 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 6852 return 0;
50 }
51
52 6 static int decode_nal_sei_mastering_display_info(HEVCSEIMasteringDisplay *s,
53 GetByteContext *gb)
54 {
55 int i;
56
57
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (bytestream2_get_bytes_left(gb) < 24)
58 return AVERROR_INVALIDDATA;
59
60 // Mastering primaries
61
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 for (i = 0; i < 3; i++) {
62 18 s->display_primaries[i][0] = bytestream2_get_be16u(gb);
63 18 s->display_primaries[i][1] = bytestream2_get_be16u(gb);
64 }
65 // White point (x, y)
66 6 s->white_point[0] = bytestream2_get_be16u(gb);
67 6 s->white_point[1] = bytestream2_get_be16u(gb);
68
69 // Max and min luminance of mastering display
70 6 s->max_luminance = bytestream2_get_be32u(gb);
71 6 s->min_luminance = bytestream2_get_be32u(gb);
72
73 // As this SEI message comes before the first frame that references it,
74 // initialize the flag to 2 and decrement on IRAP access unit so it
75 // persists for the coded video sequence (e.g., between two IRAPs)
76 6 s->present = 2;
77
78 6 return 0;
79 }
80
81 6 static int decode_nal_sei_content_light_info(HEVCSEIContentLight *s,
82 GetByteContext *gb)
83 {
84
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (bytestream2_get_bytes_left(gb) < 4)
85 return AVERROR_INVALIDDATA;
86
87 // Max and average light levels
88 6 s->max_content_light_level = bytestream2_get_be16u(gb);
89 6 s->max_pic_average_light_level = bytestream2_get_be16u(gb);
90 // As this SEI message comes before the first frame that references it,
91 // initialize the flag to 2 and decrement on IRAP access unit so it
92 // persists for the coded video sequence (e.g., between two IRAPs)
93 6 s->present = 2;
94
95 6 return 0;
96 }
97
98 1276 static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb,
99 const HEVCParamSets *ps, void *logctx)
100 {
101 1276 HEVCSEIPictureTiming *h = &s->picture_timing;
102 HEVCSPS *sps;
103
104
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 1210 times.
1276 if (!ps->sps_list[s->active_seq_parameter_set_id])
105 66 return(AVERROR(ENOMEM));
106 1210 sps = (HEVCSPS*)ps->sps_list[s->active_seq_parameter_set_id]->data;
107
108
2/2
✓ Branch 0 taken 727 times.
✓ Branch 1 taken 483 times.
1210 if (sps->vui.frame_field_info_present_flag) {
109 727 int pic_struct = get_bits(gb, 4);
110 727 h->picture_struct = AV_PICTURE_STRUCTURE_UNKNOWN;
111
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) {
112 10 av_log(logctx, AV_LOG_DEBUG, "BOTTOM Field\n");
113 10 h->picture_struct = AV_PICTURE_STRUCTURE_BOTTOM_FIELD;
114
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) {
115 11 av_log(logctx, AV_LOG_DEBUG, "TOP Field\n");
116 11 h->picture_struct = AV_PICTURE_STRUCTURE_TOP_FIELD;
117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 } else if (pic_struct == 7) {
118 av_log(logctx, AV_LOG_DEBUG, "Frame/Field Doubling\n");
119 h->picture_struct = HEVC_SEI_PIC_STRUCT_FRAME_DOUBLING;
120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
706 } else if (pic_struct == 8) {
121 av_log(logctx, AV_LOG_DEBUG, "Frame/Field Tripling\n");
122 h->picture_struct = HEVC_SEI_PIC_STRUCT_FRAME_TRIPLING;
123 }
124 }
125
126 1210 return 0;
127 }
128
129 30 static int decode_nal_sei_active_parameter_sets(HEVCSEI *s, GetBitContext *gb, void *logctx)
130 {
131 int num_sps_ids_minus1;
132 unsigned active_seq_parameter_set_id;
133
134 30 get_bits(gb, 4); // active_video_parameter_set_id
135 30 get_bits(gb, 1); // self_contained_cvs_flag
136 30 get_bits(gb, 1); // num_sps_ids_minus1
137 30 num_sps_ids_minus1 = get_ue_golomb_long(gb); // num_sps_ids_minus1
138
139
2/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
30 if (num_sps_ids_minus1 < 0 || num_sps_ids_minus1 > 15) {
140 av_log(logctx, AV_LOG_ERROR, "num_sps_ids_minus1 %d invalid\n", num_sps_ids_minus1);
141 return AVERROR_INVALIDDATA;
142 }
143
144 30 active_seq_parameter_set_id = get_ue_golomb_long(gb);
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (active_seq_parameter_set_id >= HEVC_MAX_SPS_COUNT) {
146 av_log(logctx, AV_LOG_ERROR, "active_parameter_set_id %d invalid\n", active_seq_parameter_set_id);
147 return AVERROR_INVALIDDATA;
148 }
149 30 s->active_seq_parameter_set_id = active_seq_parameter_set_id;
150
151 30 return 0;
152 }
153
154 136 static int decode_nal_sei_timecode(HEVCSEITimeCode *s, GetBitContext *gb)
155 {
156 136 s->num_clock_ts = get_bits(gb, 2);
157
158
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 136 times.
272 for (int i = 0; i < s->num_clock_ts; i++) {
159 136 s->clock_timestamp_flag[i] = get_bits(gb, 1);
160
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (s->clock_timestamp_flag[i]) {
162 s->units_field_based_flag[i] = get_bits(gb, 1);
163 s->counting_type[i] = get_bits(gb, 5);
164 s->full_timestamp_flag[i] = get_bits(gb, 1);
165 s->discontinuity_flag[i] = get_bits(gb, 1);
166 s->cnt_dropped_flag[i] = get_bits(gb, 1);
167
168 s->n_frames[i] = get_bits(gb, 9);
169
170 if (s->full_timestamp_flag[i]) {
171 s->seconds_value[i] = av_clip(get_bits(gb, 6), 0, 59);
172 s->minutes_value[i] = av_clip(get_bits(gb, 6), 0, 59);
173 s->hours_value[i] = av_clip(get_bits(gb, 5), 0, 23);
174 } else {
175 s->seconds_flag[i] = get_bits(gb, 1);
176 if (s->seconds_flag[i]) {
177 s->seconds_value[i] = av_clip(get_bits(gb, 6), 0, 59);
178 s->minutes_flag[i] = get_bits(gb, 1);
179 if (s->minutes_flag[i]) {
180 s->minutes_value[i] = av_clip(get_bits(gb, 6), 0, 59);
181 s->hours_flag[i] = get_bits(gb, 1);
182 if (s->hours_flag[i]) {
183 s->hours_value[i] = av_clip(get_bits(gb, 5), 0, 23);
184 }
185 }
186 }
187 }
188
189 s->time_offset_length[i] = get_bits(gb, 5);
190 if (s->time_offset_length[i] > 0) {
191 s->time_offset_value[i] = get_bits_long(gb, s->time_offset_length[i]);
192 }
193 }
194 }
195
196 136 s->present = 1;
197 136 return 0;
198 }
199
200 1709 static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte,
201 void *logctx, HEVCSEI *s,
202 const HEVCParamSets *ps, int type)
203 {
204
6/7
✗ Branch 0 not taken.
✓ Branch 1 taken 1276 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 136 times.
✓ Branch 6 taken 255 times.
1709 switch (type) {
205 case 256: // Mismatched value from HM 8.1
206 return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte);
207 1276 case SEI_TYPE_PIC_TIMING:
208 1276 return decode_nal_sei_pic_timing(s, gb, ps, logctx);
209 6 case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME:
210 6 return decode_nal_sei_mastering_display_info(&s->mastering_display, gbyte);
211 6 case SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO:
212 6 return decode_nal_sei_content_light_info(&s->content_light, gbyte);
213 30 case SEI_TYPE_ACTIVE_PARAMETER_SETS:
214 30 return decode_nal_sei_active_parameter_sets(s, gb, logctx);
215 136 case SEI_TYPE_TIME_CODE:
216 136 return decode_nal_sei_timecode(&s->timecode, gb);
217 255 default: {
218 255 int ret = ff_h2645_sei_message_decode(&s->common, type, AV_CODEC_ID_HEVC,
219 gb, gbyte, logctx);
220
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 161 times.
255 if (ret == FF_H2645_SEI_MESSAGE_UNHANDLED)
221 94 av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type);
222 255 return ret;
223 }
224 }
225 }
226
227 6852 static int decode_nal_sei_suffix(GetBitContext *gb, GetByteContext *gbyte,
228 void *logctx, HEVCSEI *s, int type)
229 {
230
1/2
✓ Branch 0 taken 6852 times.
✗ Branch 1 not taken.
6852 switch (type) {
231 6852 case SEI_TYPE_DECODED_PICTURE_HASH:
232 6852 return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte);
233 default:
234 av_log(logctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", type);
235 return 0;
236 }
237 }
238
239 8561 static int decode_nal_sei_message(GetByteContext *gb, void *logctx, HEVCSEI *s,
240 const HEVCParamSets *ps, int nal_unit_type)
241 {
242 GetByteContext message_gbyte;
243 GetBitContext message_gb;
244 8561 int payload_type = 0;
245 8561 int payload_size = 0;
246 8561 int byte = 0xFF;
247 av_unused int ret;
248 8561 av_log(logctx, AV_LOG_DEBUG, "Decoding SEI\n");
249
250
2/2
✓ Branch 0 taken 8561 times.
✓ Branch 1 taken 8561 times.
17122 while (byte == 0xFF) {
251
2/4
✓ Branch 1 taken 8561 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8561 times.
8561 if (bytestream2_get_bytes_left(gb) < 2 || payload_type > INT_MAX - 255)
252 return AVERROR_INVALIDDATA;
253 8561 byte = bytestream2_get_byteu(gb);
254 8561 payload_type += byte;
255 }
256 8561 byte = 0xFF;
257
2/2
✓ Branch 0 taken 8628 times.
✓ Branch 1 taken 8561 times.
17189 while (byte == 0xFF) {
258
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8628 times.
8628 if (bytestream2_get_bytes_left(gb) < 1 + payload_size)
259 return AVERROR_INVALIDDATA;
260 8628 byte = bytestream2_get_byteu(gb);
261 8628 payload_size += byte;
262 }
263
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8561 times.
8561 if (bytestream2_get_bytes_left(gb) < payload_size)
264 return AVERROR_INVALIDDATA;
265 8561 bytestream2_init(&message_gbyte, gb->buffer, payload_size);
266 8561 ret = init_get_bits8(&message_gb, gb->buffer, payload_size);
267 av_assert1(ret >= 0);
268 8561 bytestream2_skipu(gb, payload_size);
269
2/2
✓ Branch 0 taken 1709 times.
✓ Branch 1 taken 6852 times.
8561 if (nal_unit_type == HEVC_NAL_SEI_PREFIX) {
270 1709 return decode_nal_sei_prefix(&message_gb, &message_gbyte,
271 logctx, s, ps, payload_type);
272 } else { /* nal_unit_type == NAL_SEI_SUFFIX */
273 6852 return decode_nal_sei_suffix(&message_gb, &message_gbyte,
274 logctx, s, payload_type);
275 }
276 }
277
278 8552 int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s,
279 const HEVCParamSets *ps, enum HEVCNALUnitType type)
280 {
281 GetByteContext gbyte;
282 int ret;
283
284 av_assert1((get_bits_count(gb) % 8) == 0);
285 8552 bytestream2_init(&gbyte, gb->buffer + get_bits_count(gb) / 8,
286 8552 get_bits_left(gb) / 8);
287
288 do {
289 8561 ret = decode_nal_sei_message(&gbyte, logctx, s, ps, type);
290
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 8495 times.
8561 if (ret < 0)
291 66 return ret;
292
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 8486 times.
8495 } while (bytestream2_get_bytes_left(&gbyte) > 0);
293 8486 return 1;
294 }
295