FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bsf/evc_frame_merge.c
Date: 2024-02-29 09:57:37
Exec Total Coverage
Lines: 97 143 67.8%
Functions: 5 6 83.3%
Branches: 38 74 51.4%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2019 James Almer <jamrial@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include "get_bits.h"
21 #include "bsf.h"
22 #include "bsf_internal.h"
23
24 #include "evc.h"
25 #include "evc_parse.h"
26 #include "evc_ps.h"
27
28 // Access unit data
29 typedef struct AccessUnitBuffer {
30 uint8_t *data; // the data buffer
31 size_t data_size; // size of data in bytes
32 unsigned capacity; // buffer capacity
33 } AccessUnitBuffer;
34
35 typedef struct EVCFMergeContext {
36 AVPacket *in, *buffer_pkt;
37 EVCParamSets ps;
38 EVCParserPoc poc;
39 AccessUnitBuffer au_buffer;
40 } EVCFMergeContext;
41
42 300 static int end_of_access_unit_found(const EVCParamSets *ps, const EVCParserSliceHeader *sh,
43 const EVCParserPoc *poc, enum EVCNALUnitType nalu_type)
44 {
45 300 EVCParserPPS *pps = ps->pps[sh->slice_pic_parameter_set_id];
46 300 EVCParserSPS *sps = ps->sps[pps->pps_seq_parameter_set_id];
47
48
2/4
✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 300 times.
300 av_assert0(sps && pps);
49
50
1/2
✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
300 if (sps->profile_idc == 0) { // BASELINE profile
51
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
300 if (nalu_type == EVC_NOIDR_NUT || nalu_type == EVC_IDR_NUT)
52 300 return 1;
53 } else { // MAIN profile
54 if (nalu_type == EVC_NOIDR_NUT) {
55 if (poc->PicOrderCntVal != poc->prevPicOrderCntVal)
56 return 1;
57 } else if (nalu_type == EVC_IDR_NUT)
58 return 1;
59 }
60 return 0;
61 }
62
63 static void evc_frame_merge_flush(AVBSFContext *bsf)
64 {
65 EVCFMergeContext *ctx = bsf->priv_data;
66
67 ff_evc_ps_free(&ctx->ps);
68 av_packet_unref(ctx->in);
69 av_packet_unref(ctx->buffer_pkt);
70 ctx->au_buffer.data_size = 0;
71 }
72
73 303 static int parse_nal_unit(AVBSFContext *bsf, const uint8_t *buf, int buf_size)
74 {
75 303 EVCFMergeContext *ctx = bsf->priv_data;
76 GetBitContext gb;
77 enum EVCNALUnitType nalu_type;
78 int tid, err;
79
80 303 err = init_get_bits8(&gb, buf, buf_size);
81
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 if (err < 0)
82 return err;
83
84 // @see ISO_IEC_23094-1_2020, 7.4.2.2 NAL unit header semantic (Table 4 - NAL unit type codes and NAL unit type classes)
85 // @see enum EVCNALUnitType in evc.h
86
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 303 times.
303 if (get_bits1(&gb)) {// forbidden_zero_bit
87 av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit header\n");
88 return AVERROR_INVALIDDATA;
89 }
90
91 303 nalu_type = get_bits(&gb, 6) - 1;
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 if (nalu_type < EVC_NOIDR_NUT || nalu_type > EVC_UNSPEC_NUT62) {
93 av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit type: (%d)\n", nalu_type);
94 return AVERROR_INVALIDDATA;
95 }
96
97 303 tid = get_bits(&gb, 3);
98 303 skip_bits(&gb, 5); // nuh_reserved_zero_5bits
99 303 skip_bits1(&gb); // nuh_extension_flag
100
101
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 300 times.
✓ Branch 3 taken 1 times.
303 switch (nalu_type) {
102 1 case EVC_SPS_NUT:
103 1 err = ff_evc_parse_sps(&gb, &ctx->ps);
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0) {
105 av_log(bsf, AV_LOG_ERROR, "SPS parsing error\n");
106 return err;
107 }
108 1 break;
109 1 case EVC_PPS_NUT:
110 1 err = ff_evc_parse_pps(&gb, &ctx->ps);
111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0) {
112 av_log(bsf, AV_LOG_ERROR, "PPS parsing error\n");
113 return err;
114 }
115 1 break;
116 300 case EVC_IDR_NUT: // Coded slice of a IDR or non-IDR picture
117 case EVC_NOIDR_NUT: {
118 EVCParserSliceHeader sh;
119
120 300 err = ff_evc_parse_slice_header(&gb, &sh, &ctx->ps, nalu_type);
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 if (err < 0) {
122 av_log(bsf, AV_LOG_ERROR, "Slice header parsing error\n");
123 return err;
124 }
125
126 // POC (picture order count of the current picture) derivation
127 // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count
128 300 err = ff_evc_derive_poc(&ctx->ps, &sh, &ctx->poc, nalu_type, tid);
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 if (err < 0)
130 return err;
131
132 300 return end_of_access_unit_found(&ctx->ps, &sh, &ctx->poc, nalu_type);
133
134 break;
135 }
136 1 case EVC_SEI_NUT: // Supplemental Enhancement Information
137 case EVC_APS_NUT: // Adaptation parameter set
138 case EVC_FD_NUT: // Filler data
139 default:
140 1 break;
141 }
142
143 3 return 0;
144 }
145
146 303 static int evc_frame_merge_filter(AVBSFContext *bsf, AVPacket *out)
147 {
148 303 EVCFMergeContext *ctx = bsf->priv_data;
149 303 AVPacket *in = ctx->in, *buffer_pkt = ctx->buffer_pkt;
150 size_t data_size;
151 303 int au_end_found = 0, err;
152
153
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 300 times.
606 while (!au_end_found) {
154 uint8_t *buffer;
155 uint32_t nalu_size;
156
157
1/2
✓ Branch 0 taken 306 times.
✗ Branch 1 not taken.
306 if (!in->size) {
158 306 av_packet_unref(in);
159 306 err = ff_bsf_get_packet_ref(bsf, in);
160
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 303 times.
306 if (err < 0) {
161
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (err == AVERROR_EOF && ctx->au_buffer.data_size > 0)
162 break;
163 3 return err;
164 }
165 /* Buffer packets with timestamps (there should be at most one per AU)
166 * or any packet if buffer_pkt is empty. The latter is needed to
167 * passthrough positions in case there are no timestamps like with
168 * the raw EVC demuxer. */
169
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 300 times.
303 if (!buffer_pkt->data ||
170
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 in->pts != AV_NOPTS_VALUE && buffer_pkt->pts == AV_NOPTS_VALUE) {
171 300 err = av_packet_ref(buffer_pkt, in);
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 if (err < 0)
173 goto end;
174 }
175 }
176
177 // Buffer size is not enough for buffer to store NAL unit 4-bytes prefix (length)
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 if (in->size < EVC_NALU_LENGTH_PREFIX_SIZE)
179 return AVERROR_INVALIDDATA;
180
181 303 nalu_size = evc_read_nal_unit_length(in->data, EVC_NALU_LENGTH_PREFIX_SIZE, bsf);
182
2/4
✓ Branch 0 taken 303 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 303 times.
303 if (!nalu_size || nalu_size > INT_MAX) {
183 av_log(bsf, AV_LOG_ERROR, "Invalid NAL unit size: (%u)\n", nalu_size);
184 err = AVERROR_INVALIDDATA;
185 goto end;
186 }
187
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 if (in->size < nalu_size + EVC_NALU_LENGTH_PREFIX_SIZE) {
189 err = AVERROR_INVALIDDATA;
190 goto end;
191 }
192
193 303 err = parse_nal_unit(bsf, in->data + EVC_NALU_LENGTH_PREFIX_SIZE, nalu_size);
194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 if (err < 0) {
195 av_log(bsf, AV_LOG_ERROR, "Parsing of NAL unit failed\n");
196 goto end;
197 }
198 303 au_end_found = err;
199
200 303 nalu_size += EVC_NALU_LENGTH_PREFIX_SIZE;
201
202 303 data_size = ctx->au_buffer.data_size + nalu_size;
203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 if (data_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
204 av_log(bsf, AV_LOG_ERROR, "Assembled packet is too big\n");
205 err = AVERROR(ERANGE);
206 goto end;
207 }
208
209 303 buffer = av_fast_realloc(ctx->au_buffer.data, &ctx->au_buffer.capacity,
210 data_size);
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 if (!buffer) {
212 av_freep(&ctx->au_buffer.data);
213 err = AVERROR_INVALIDDATA;
214 goto end;
215 }
216
217 303 ctx->au_buffer.data = buffer;
218 303 memcpy(ctx->au_buffer.data + ctx->au_buffer.data_size, in->data, nalu_size);
219
220 303 ctx->au_buffer.data_size = data_size;
221
222 303 in->data += nalu_size;
223 303 in->size -= nalu_size;
224 }
225
226 300 av_packet_unref(in);
227 300 data_size = ctx->au_buffer.data_size;
228
229 300 ctx->au_buffer.data_size = 0;
230 // drop the data in buffer_pkt, if any, but keep the props
231 300 av_buffer_unref(&buffer_pkt->buf);
232 300 err = av_buffer_realloc(&buffer_pkt->buf, data_size + AV_INPUT_BUFFER_PADDING_SIZE);
233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 if (err < 0)
234 goto end;
235
236 300 buffer_pkt->data = buffer_pkt->buf->data;
237 300 buffer_pkt->size = data_size;
238 300 av_packet_move_ref(out, buffer_pkt);
239 300 memcpy(out->data, ctx->au_buffer.data, data_size);
240 300 memset(out->data + data_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
241
242 300 err = 0;
243 300 end:
244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 if (err < 0) {
245 av_packet_unref(in);
246 av_packet_unref(buffer_pkt);
247 ctx->au_buffer.data_size = 0;
248 }
249 300 return err;
250 }
251
252 1 static int evc_frame_merge_init(AVBSFContext *bsf)
253 {
254 1 EVCFMergeContext *ctx = bsf->priv_data;
255
256 1 ctx->in = av_packet_alloc();
257 1 ctx->buffer_pkt = av_packet_alloc();
258
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!ctx->in || !ctx->buffer_pkt)
259 return AVERROR(ENOMEM);
260
261 1 return 0;
262 }
263
264 1 static void evc_frame_merge_close(AVBSFContext *bsf)
265 {
266 1 EVCFMergeContext *ctx = bsf->priv_data;
267
268 1 av_packet_free(&ctx->in);
269 1 av_packet_free(&ctx->buffer_pkt);
270 1 ff_evc_ps_free(&ctx->ps);
271
272 1 ctx->au_buffer.capacity = 0;
273 1 av_freep(&ctx->au_buffer.data);
274 1 ctx->au_buffer.data_size = 0;
275 1 }
276
277 static const enum AVCodecID evc_frame_merge_codec_ids[] = {
278 AV_CODEC_ID_EVC, AV_CODEC_ID_NONE,
279 };
280
281 const FFBitStreamFilter ff_evc_frame_merge_bsf = {
282 .p.name = "evc_frame_merge",
283 .p.codec_ids = evc_frame_merge_codec_ids,
284 .priv_data_size = sizeof(EVCFMergeContext),
285 .init = evc_frame_merge_init,
286 .flush = evc_frame_merge_flush,
287 .close = evc_frame_merge_close,
288 .filter = evc_frame_merge_filter,
289 };
290