FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/hevc_sei.c
Date: 2024-04-24 18:52:15
Exec Total Coverage
Lines: 87 125 69.6%
Functions: 8 8 100.0%
Branches: 45 71 63.4%

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 6856 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 6856 hash_type = bytestream2_get_byte(gb);
38
39
2/2
✓ Branch 0 taken 20568 times.
✓ Branch 1 taken 6856 times.
27424 for (cIdx = 0; cIdx < 3/*((s->sps->chroma_format_idc == 0) ? 1 : 3)*/; cIdx++) {
40
2/2
✓ Branch 0 taken 19521 times.
✓ Branch 1 taken 1047 times.
20568 if (hash_type == 0) {
41 19521 s->is_md5 = 1;
42 19521 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 6856 return 0;
50 }
51
52 1276 static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb,
53 const HEVCParamSets *ps, void *logctx)
54 {
55 1276 HEVCSEIPictureTiming *h = &s->picture_timing;
56 1276 const HEVCSPS *sps = ps->sps_list[s->active_seq_parameter_set_id];
57
58
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 1210 times.
1276 if (!sps)
59 66 return(AVERROR(ENOMEM));
60
61
2/2
✓ Branch 0 taken 727 times.
✓ Branch 1 taken 483 times.
1210 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 1210 return 0;
80 }
81
82 30 static int decode_nal_sei_active_parameter_sets(HEVCSEI *s, GetBitContext *gb, void *logctx)
83 {
84 int num_sps_ids_minus1;
85 unsigned active_seq_parameter_set_id;
86
87 30 get_bits(gb, 4); // active_video_parameter_set_id
88 30 get_bits(gb, 1); // self_contained_cvs_flag
89 30 get_bits(gb, 1); // num_sps_ids_minus1
90 30 num_sps_ids_minus1 = get_ue_golomb_long(gb); // num_sps_ids_minus1
91
92
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) {
93 av_log(logctx, AV_LOG_ERROR, "num_sps_ids_minus1 %d invalid\n", num_sps_ids_minus1);
94 return AVERROR_INVALIDDATA;
95 }
96
97 30 active_seq_parameter_set_id = get_ue_golomb_long(gb);
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (active_seq_parameter_set_id >= HEVC_MAX_SPS_COUNT) {
99 av_log(logctx, AV_LOG_ERROR, "active_parameter_set_id %d invalid\n", active_seq_parameter_set_id);
100 return AVERROR_INVALIDDATA;
101 }
102 30 s->active_seq_parameter_set_id = active_seq_parameter_set_id;
103
104 30 return 0;
105 }
106
107 136 static int decode_nal_sei_timecode(HEVCSEITimeCode *s, GetBitContext *gb)
108 {
109 136 s->num_clock_ts = get_bits(gb, 2);
110
111
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 136 times.
272 for (int i = 0; i < s->num_clock_ts; i++) {
112 136 s->clock_timestamp_flag[i] = get_bits(gb, 1);
113
114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (s->clock_timestamp_flag[i]) {
115 s->units_field_based_flag[i] = get_bits(gb, 1);
116 s->counting_type[i] = get_bits(gb, 5);
117 s->full_timestamp_flag[i] = get_bits(gb, 1);
118 s->discontinuity_flag[i] = get_bits(gb, 1);
119 s->cnt_dropped_flag[i] = get_bits(gb, 1);
120
121 s->n_frames[i] = get_bits(gb, 9);
122
123 if (s->full_timestamp_flag[i]) {
124 s->seconds_value[i] = av_clip(get_bits(gb, 6), 0, 59);
125 s->minutes_value[i] = av_clip(get_bits(gb, 6), 0, 59);
126 s->hours_value[i] = av_clip(get_bits(gb, 5), 0, 23);
127 } else {
128 s->seconds_flag[i] = get_bits(gb, 1);
129 if (s->seconds_flag[i]) {
130 s->seconds_value[i] = av_clip(get_bits(gb, 6), 0, 59);
131 s->minutes_flag[i] = get_bits(gb, 1);
132 if (s->minutes_flag[i]) {
133 s->minutes_value[i] = av_clip(get_bits(gb, 6), 0, 59);
134 s->hours_flag[i] = get_bits(gb, 1);
135 if (s->hours_flag[i]) {
136 s->hours_value[i] = av_clip(get_bits(gb, 5), 0, 23);
137 }
138 }
139 }
140 }
141
142 s->time_offset_length[i] = get_bits(gb, 5);
143 if (s->time_offset_length[i] > 0) {
144 s->time_offset_value[i] = get_bits_long(gb, s->time_offset_length[i]);
145 }
146 }
147 }
148
149 136 s->present = 1;
150 136 return 0;
151 }
152
153 1726 static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte,
154 void *logctx, HEVCSEI *s,
155 const HEVCParamSets *ps, int type)
156 {
157
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 1276 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 136 times.
✓ Branch 4 taken 284 times.
1726 switch (type) {
158 case 256: // Mismatched value from HM 8.1
159 return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte);
160 1276 case SEI_TYPE_PIC_TIMING:
161 1276 return decode_nal_sei_pic_timing(s, gb, ps, logctx);
162 30 case SEI_TYPE_ACTIVE_PARAMETER_SETS:
163 30 return decode_nal_sei_active_parameter_sets(s, gb, logctx);
164 136 case SEI_TYPE_TIME_CODE:
165 136 return decode_nal_sei_timecode(&s->timecode, gb);
166 284 default: {
167 284 int ret = ff_h2645_sei_message_decode(&s->common, type, AV_CODEC_ID_HEVC,
168 gb, gbyte, logctx);
169
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 190 times.
284 if (ret == FF_H2645_SEI_MESSAGE_UNHANDLED)
170 94 av_log(logctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", type);
171 284 return ret;
172 }
173 }
174 }
175
176 6856 static int decode_nal_sei_suffix(GetBitContext *gb, GetByteContext *gbyte,
177 void *logctx, HEVCSEI *s, int type)
178 {
179
1/2
✓ Branch 0 taken 6856 times.
✗ Branch 1 not taken.
6856 switch (type) {
180 6856 case SEI_TYPE_DECODED_PICTURE_HASH:
181 6856 return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte);
182 default:
183 av_log(logctx, AV_LOG_DEBUG, "Skipped SUFFIX SEI %d\n", type);
184 return 0;
185 }
186 }
187
188 8582 static int decode_nal_sei_message(GetByteContext *gb, void *logctx, HEVCSEI *s,
189 const HEVCParamSets *ps, int nal_unit_type)
190 {
191 GetByteContext message_gbyte;
192 GetBitContext message_gb;
193 8582 int payload_type = 0;
194 8582 int payload_size = 0;
195 8582 int byte = 0xFF;
196 av_unused int ret;
197 8582 av_log(logctx, AV_LOG_DEBUG, "Decoding SEI\n");
198
199
2/2
✓ Branch 0 taken 8582 times.
✓ Branch 1 taken 8582 times.
17164 while (byte == 0xFF) {
200
2/4
✓ Branch 1 taken 8582 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8582 times.
8582 if (bytestream2_get_bytes_left(gb) < 2 || payload_type > INT_MAX - 255)
201 return AVERROR_INVALIDDATA;
202 8582 byte = bytestream2_get_byteu(gb);
203 8582 payload_type += byte;
204 }
205 8582 byte = 0xFF;
206
2/2
✓ Branch 0 taken 8673 times.
✓ Branch 1 taken 8582 times.
17255 while (byte == 0xFF) {
207
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8673 times.
8673 if (bytestream2_get_bytes_left(gb) < 1 + payload_size)
208 return AVERROR_INVALIDDATA;
209 8673 byte = bytestream2_get_byteu(gb);
210 8673 payload_size += byte;
211 }
212
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8582 times.
8582 if (bytestream2_get_bytes_left(gb) < payload_size)
213 return AVERROR_INVALIDDATA;
214 8582 bytestream2_init(&message_gbyte, gb->buffer, payload_size);
215 8582 ret = init_get_bits8(&message_gb, gb->buffer, payload_size);
216 av_assert1(ret >= 0);
217 8582 bytestream2_skipu(gb, payload_size);
218
2/2
✓ Branch 0 taken 1726 times.
✓ Branch 1 taken 6856 times.
8582 if (nal_unit_type == HEVC_NAL_SEI_PREFIX) {
219 1726 return decode_nal_sei_prefix(&message_gb, &message_gbyte,
220 logctx, s, ps, payload_type);
221 } else { /* nal_unit_type == NAL_SEI_SUFFIX */
222 6856 return decode_nal_sei_suffix(&message_gb, &message_gbyte,
223 logctx, s, payload_type);
224 }
225 }
226
227 8573 int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s,
228 const HEVCParamSets *ps, enum HEVCNALUnitType type)
229 {
230 GetByteContext gbyte;
231 int ret;
232
233 av_assert1((get_bits_count(gb) % 8) == 0);
234 8573 bytestream2_init(&gbyte, gb->buffer + get_bits_count(gb) / 8,
235 8573 get_bits_left(gb) / 8);
236
237 do {
238 8582 ret = decode_nal_sei_message(&gbyte, logctx, s, ps, type);
239
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 8516 times.
8582 if (ret < 0)
240 66 return ret;
241
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 8507 times.
8516 } while (bytestream2_get_bytes_left(&gbyte) > 0);
242 8507 return 1;
243 }
244