FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bsf/side_data.c
Date: 2026-10-24 07:26:44
Exec Total Coverage
Lines: 27 27 100.0%
Functions: 3 3 100.0%
Branches: 14 14 100.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 /**
20 * @file
21 * Side data bitstream filter -- remove side data from packets and from the
22 * stream, or select packets by their side data.
23 */
24
25 #include "libavcodec/bsf.h"
26 #include "libavcodec/bsf_internal.h"
27 #include "libavcodec/packet_internal.h"
28
29 #include "libavutil/opt.h"
30
31 typedef struct SideDataContext {
32 const AVClass *class;
33
34 int *remove;
35 unsigned nb_remove;
36 int *select;
37 unsigned nb_select;
38 } SideDataContext;
39
40 5 static int side_data_init(AVBSFContext *ctx)
41 {
42 5 SideDataContext *s = ctx->priv_data;
43
44
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 for (unsigned i = 0; i < s->nb_remove; i++)
45 3 av_packet_side_data_remove(ctx->par_out->coded_side_data,
46 3 &ctx->par_out->nb_coded_side_data,
47 3 s->remove[i]);
48
49 5 return 0;
50 }
51
52 100 static int is_selected(const SideDataContext *s, const AVPacket *pkt)
53 {
54
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 68 times.
100 if (!s->nb_select)
55 32 return 1;
56
57
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 66 times.
134 for (unsigned i = 0; i < s->nb_select; i++)
58
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
68 if (av_packet_side_data_get(pkt->side_data, pkt->side_data_elems,
59 68 s->select[i]))
60 2 return 1;
61
62 66 return 0;
63 }
64
65 135 static int side_data_filter(AVBSFContext *ctx, AVPacket *pkt)
66 {
67 135 SideDataContext *s = ctx->priv_data;
68 135 int ret = ff_bsf_get_packet_ref(ctx, pkt);
69
70
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 100 times.
135 if (ret < 0)
71 35 return ret;
72
73
2/2
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 34 times.
100 if (!is_selected(s, pkt)) {
74 66 av_packet_unref(pkt);
75 66 return AVERROR(EAGAIN);
76 }
77
78
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 34 times.
66 for (unsigned i = 0; i < s->nb_remove; i++)
79 32 av_packet_side_data_remove(pkt->side_data, &pkt->side_data_elems,
80 32 s->remove[i]);
81
82 34 return 0;
83 }
84
85 static const AVOptionArrayDef types_def = { .sep = '+' };
86
87 #define OFFSET(x) offsetof(SideDataContext, x)
88 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_BSF_PARAM)
89 #define TYPE_CONST(type, handle) \
90 { handle, NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_PKT_DATA_ ## type }, .flags = FLAGS, .unit = "type" },
91 static const AVOption options[] = {
92 { "remove", "side data types to remove, joined with '+'", OFFSET(remove), AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, { .arr = &types_def }, 0, AV_PKT_DATA_NB - 1, FLAGS, .unit = "type" },
93 { "select", "side data types of the packets to keep, joined with '+'", OFFSET(select), AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, { .arr = &types_def }, 0, AV_PKT_DATA_NB - 1, FLAGS, .unit = "type" },
94 FF_PACKET_SIDE_DATA_HANDLES(TYPE_CONST)
95 { NULL },
96 };
97
98 static const AVClass side_data_class = {
99 .class_name = "side_data bsf",
100 .item_name = av_default_item_name,
101 .option = options,
102 .version = LIBAVUTIL_VERSION_INT,
103 };
104
105 const FFBitStreamFilter ff_side_data_bsf = {
106 .p.name = "side_data",
107 .p.priv_class = &side_data_class,
108 .priv_data_size = sizeof(SideDataContext),
109 .init = side_data_init,
110 .filter = side_data_filter,
111 };
112