FFmpeg coverage


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