FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/evc_parse.c
Date: 2026-09-25 02:02:46
Exec Total Coverage
Lines: 50 117 42.7%
Functions: 2 2 100.0%
Branches: 26 84 31.0%

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 "golomb.h"
20 #include "evc.h"
21 #include "evc_parse.h"
22
23 // @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax)
24 900 int ff_evc_parse_slice_header(GetBitContext *gb, EVCParserSliceHeader *sh,
25 const EVCParamSets *ps, enum EVCNALUnitType nalu_type)
26 {
27 const EVCParserPPS *pps;
28 const EVCParserSPS *sps;
29 900 int num_tiles_in_slice = 0;
30 unsigned slice_pic_parameter_set_id;
31
32 900 slice_pic_parameter_set_id = get_ue_golomb_31(gb);
33
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
900 if (slice_pic_parameter_set_id >= EVC_MAX_PPS_COUNT)
35 ✗ return AVERROR_INVALIDDATA;
36
37 900 pps = ps->pps[slice_pic_parameter_set_id];
38
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
900 if(!pps)
39 ✗ return AVERROR_INVALIDDATA;
40
41 900 sps = ps->sps[pps->pps_seq_parameter_set_id];
42
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
900 if(!sps)
43 ✗ return AVERROR_INVALIDDATA;
44
45 900 memset(sh, 0, sizeof(*sh));
46 900 sh->slice_pic_parameter_set_id = slice_pic_parameter_set_id;
47
48
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
900 if (!pps->single_tile_in_pic_flag) {
49 ✗ sh->single_tile_in_slice_flag = get_bits1(gb);
50 ✗ sh->first_tile_id = get_bits(gb, pps->tile_id_len_minus1 + 1);
51 } else
52 900 sh->single_tile_in_slice_flag = 1;
53
54
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
900 if (!sh->single_tile_in_slice_flag) {
55 ✗ if (pps->arbitrary_slice_present_flag)
56 ✗ sh->arbitrary_slice_flag = get_bits1(gb);
57
58 ✗ if (!sh->arbitrary_slice_flag)
59 ✗ sh->last_tile_id = get_bits(gb, pps->tile_id_len_minus1 + 1);
60 else {
61 ✗ unsigned num_remaining_tiles_in_slice_minus1 = get_ue_golomb_long(gb);
62 ✗ if (num_remaining_tiles_in_slice_minus1 > EVC_MAX_TILE_ROWS * EVC_MAX_TILE_COLUMNS - 2)
63 ✗ return AVERROR_INVALIDDATA;
64
65 ✗ num_tiles_in_slice = num_remaining_tiles_in_slice_minus1 + 2;
66 ✗ sh->num_remaining_tiles_in_slice_minus1 = num_remaining_tiles_in_slice_minus1;
67 ✗ for (int i = 0; i < num_tiles_in_slice - 1; ++i)
68 ✗ sh->delta_tile_id_minus1[i] = get_ue_golomb_long(gb);
69 }
70 }
71
72 900 sh->slice_type = get_ue_golomb_31(gb);
73
74
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 897 times.
900 if (nalu_type == EVC_IDR_NUT)
75 3 sh->no_output_of_prior_pics_flag = get_bits1(gb);
76
77
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
900 if (sps->sps_mmvd_flag && ((sh->slice_type == EVC_SLICE_TYPE_B) || (sh->slice_type == EVC_SLICE_TYPE_P)))
78 ✗ sh->mmvd_group_enable_flag = get_bits1(gb);
79 else
80 900 sh->mmvd_group_enable_flag = 0;
81
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
900 if (sps->sps_alf_flag) {
83 ✗ int ChromaArrayType = sps->chroma_format_idc;
84
85 ✗ sh->slice_alf_enabled_flag = get_bits1(gb);
86
87 ✗ if (sh->slice_alf_enabled_flag) {
88 ✗ sh->slice_alf_luma_aps_id = get_bits(gb, 5);
89 ✗ sh->slice_alf_map_flag = get_bits1(gb);
90 ✗ sh->slice_alf_chroma_idc = get_bits(gb, 2);
91
92 ✗ if ((ChromaArrayType == 1 || ChromaArrayType == 2) && sh->slice_alf_chroma_idc > 0)
93 ✗ sh->slice_alf_chroma_aps_id = get_bits(gb, 5);
94 }
95 ✗ if (ChromaArrayType == 3) {
96 ✗ int sliceChromaAlfEnabledFlag = 0;
97 ✗ int sliceChroma2AlfEnabledFlag = 0;
98
99 ✗ if (sh->slice_alf_chroma_idc == 1) { // @see ISO_IEC_23094-1 (7.4.5)
100 ✗ sliceChromaAlfEnabledFlag = 1;
101 ✗ sliceChroma2AlfEnabledFlag = 0;
102 ✗ } else if (sh->slice_alf_chroma_idc == 2) {
103 ✗ sliceChromaAlfEnabledFlag = 0;
104 ✗ sliceChroma2AlfEnabledFlag = 1;
105 ✗ } else if (sh->slice_alf_chroma_idc == 3) {
106 ✗ sliceChromaAlfEnabledFlag = 1;
107 ✗ sliceChroma2AlfEnabledFlag = 1;
108 } else {
109 ✗ sliceChromaAlfEnabledFlag = 0;
110 ✗ sliceChroma2AlfEnabledFlag = 0;
111 }
112
113 ✗ if (!sh->slice_alf_enabled_flag)
114 ✗ sh->slice_alf_chroma_idc = get_bits(gb, 2);
115
116 ✗ if (sliceChromaAlfEnabledFlag) {
117 ✗ sh->slice_alf_chroma_aps_id = get_bits(gb, 5);
118 ✗ sh->slice_alf_chroma_map_flag = get_bits1(gb);
119 }
120
121 ✗ if (sliceChroma2AlfEnabledFlag) {
122 ✗ sh->slice_alf_chroma2_aps_id = get_bits(gb, 5);
123 ✗ sh->slice_alf_chroma2_map_flag = get_bits1(gb);
124 }
125 }
126 }
127
128
2/2
✓ Branch 0 taken 897 times.
✓ Branch 1 taken 3 times.
900 if (nalu_type != EVC_IDR_NUT) {
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 897 times.
897 if (sps->sps_pocs_flag)
130 ✗ sh->slice_pic_order_cnt_lsb = get_bits(gb, sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
131 }
132
133 // @note
134 // If necessary, add the missing fields to the EVCParserSliceHeader structure
135 // and then extend parser implementation
136
137 900 return 0;
138 }
139
140 900 int ff_evc_derive_poc(const EVCParamSets *ps, const EVCParserSliceHeader *sh,
141 EVCParserPoc *poc, enum EVCNALUnitType nalu_type, int tid)
142 {
143 900 const EVCParserPPS *pps = ps->pps[sh->slice_pic_parameter_set_id];
144 const EVCParserSPS *sps;
145
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
900 if (!pps)
147 ✗ return AVERROR_INVALIDDATA;
148
149 900 sps = ps->sps[pps->pps_seq_parameter_set_id];
150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
900 if (!sps)
151 ✗ return AVERROR_INVALIDDATA;
152
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 900 times.
900 if (sps->sps_pocs_flag) {
154 ✗ int PicOrderCntMsb = 0;
155 ✗ poc->prevPicOrderCntVal = poc->PicOrderCntVal;
156
157 ✗ if (nalu_type == EVC_IDR_NUT)
158 ✗ PicOrderCntMsb = 0;
159 else {
160 ✗ int MaxPicOrderCntLsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
161 ✗ int prevPicOrderCntLsb = poc->PicOrderCntVal & (MaxPicOrderCntLsb - 1);
162 ✗ int prevPicOrderCntMsb = poc->PicOrderCntVal - prevPicOrderCntLsb;
163
164 ✗ if ((sh->slice_pic_order_cnt_lsb < prevPicOrderCntLsb) &&
165 ✗ ((prevPicOrderCntLsb - sh->slice_pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2)))
166 ✗ PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb;
167 ✗ else if ((sh->slice_pic_order_cnt_lsb > prevPicOrderCntLsb) &&
168 ✗ ((sh->slice_pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2)))
169 ✗ PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb;
170 else
171 ✗ PicOrderCntMsb = prevPicOrderCntMsb;
172 }
173 ✗ poc->PicOrderCntVal = PicOrderCntMsb + sh->slice_pic_order_cnt_lsb;
174 } else {
175
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 897 times.
900 if (nalu_type == EVC_IDR_NUT) {
176 3 poc->PicOrderCntVal = 0;
177 3 poc->DocOffset = -1;
178 } else {
179 897 int SubGopLength = 1 << sps->log2_sub_gop_length;
180
181
2/4
✓ Branch 0 taken 897 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 897 times.
897 if (tid > (SubGopLength > 1 ? 1 + av_log2(SubGopLength - 1) : 0))
182 ✗ return AVERROR_INVALIDDATA;
183
184
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 843 times.
897 if (tid == 0) {
185 54 poc->PicOrderCntVal = poc->prevPicOrderCntVal + SubGopLength;
186 54 poc->DocOffset = 0;
187 54 poc->prevPicOrderCntVal = poc->PicOrderCntVal;
188 } else {
189 int ExpectedTemporalId;
190 int PocOffset;
191 843 int prevDocOffset = poc->DocOffset;
192
193 843 poc->DocOffset = (prevDocOffset + 1) % SubGopLength;
194
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 840 times.
843 if (poc->DocOffset == 0) {
195 3 poc->prevPicOrderCntVal += SubGopLength;
196 3 ExpectedTemporalId = 0;
197 } else
198 840 ExpectedTemporalId = 1 + av_log2(poc->DocOffset);
199
200
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 843 times.
852 while (tid != ExpectedTemporalId) {
201 9 poc->DocOffset = (poc->DocOffset + 1) % SubGopLength;
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (poc->DocOffset == 0)
203 ✗ ExpectedTemporalId = 0;
204 else
205 9 ExpectedTemporalId = 1 + av_log2(poc->DocOffset);
206 }
207 843 PocOffset = (int)(SubGopLength * ((2.0 * poc->DocOffset + 1) / (1 << tid) - 2));
208 843 poc->PicOrderCntVal = poc->prevPicOrderCntVal + PocOffset;
209 }
210 }
211 }
212
213 900 return 0;
214 }
215