FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bsf/noise.c
Date: 2024-06-18 05:56:57
Exec Total Coverage
Lines: 66 84 78.6%
Functions: 3 3 100.0%
Branches: 34 56 60.7%

Line Branch Exec Source
1 /*
2 * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
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
21 #include <stdlib.h>
22
23 #include "bsf.h"
24 #include "bsf_internal.h"
25
26 #include "libavutil/log.h"
27 #include "libavutil/mem.h"
28 #include "libavutil/opt.h"
29 #include "libavutil/eval.h"
30
31 static const char *const var_names[] = {
32 "n", ///< packet index, starting from zero
33 "tb", ///< timebase
34 "pts", ///< packet presentation timestamp
35 "dts", ///< packet decoding timestamp
36 "nopts", ///< AV_NOPTS_VALUE
37 "startpts", ///< first seen non-AV_NOPTS_VALUE packet timestamp
38 "startdts", ///< first seen non-AV_NOPTS_VALUE packet timestamp
39 "duration", "d", ///< packet duration
40 "pos", ///< original position of packet in its source
41 "size", ///< packet size
42 "key" , ///< packet keyframe flag
43 "state", ///< random-ish state
44 NULL
45 };
46
47 enum var_name {
48 VAR_N,
49 VAR_TB,
50 VAR_PTS,
51 VAR_DTS,
52 VAR_NOPTS,
53 VAR_STARTPTS,
54 VAR_STARTDTS,
55 VAR_DURATION, VAR_D,
56 VAR_POS,
57 VAR_SIZE,
58 VAR_KEY,
59 VAR_STATE,
60 VAR_VARS_NB
61 };
62
63 typedef struct NoiseContext {
64 const AVClass *class;
65
66 char *amount_str;
67 char *drop_str;
68 int dropamount;
69
70 AVExpr *amount_pexpr;
71 AVExpr *drop_pexpr;
72
73 double var_values[VAR_VARS_NB];
74
75 unsigned int state;
76 unsigned int pkt_idx;
77 } NoiseContext;
78
79 3 static int noise_init(AVBSFContext *ctx)
80 {
81 3 NoiseContext *s = ctx->priv_data;
82 int ret;
83
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!s->amount_str) {
85 s->amount_str = (!s->drop_str && !s->dropamount) ? av_strdup("-1") : av_strdup("0");
86 if (!s->amount_str)
87 return AVERROR(ENOMEM);
88 }
89
90
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ctx->par_in->codec_id == AV_CODEC_ID_WRAPPED_AVFRAME &&
91 strcmp(s->amount_str, "0")) {
92 av_log(ctx, AV_LOG_ERROR, "Wrapped AVFrame noising is unsupported\n");
93 return AVERROR_PATCHWELCOME;
94 }
95
96 3 ret = av_expr_parse(&s->amount_pexpr, s->amount_str,
97 var_names, NULL, NULL, NULL, NULL, 0, ctx);
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
99 av_log(ctx, AV_LOG_ERROR, "Error in parsing expr for amount: %s\n", s->amount_str);
100 return ret;
101 }
102
103
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
3 if (s->drop_str && s->dropamount) {
104 av_log(ctx, AV_LOG_WARNING, "Both drop '%s' and dropamount=%d set. Ignoring dropamount.\n",
105 s->drop_str, s->dropamount);
106 s->dropamount = 0;
107 }
108
109
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (s->drop_str) {
110 1 ret = av_expr_parse(&s->drop_pexpr, s->drop_str,
111 var_names, NULL, NULL, NULL, NULL, 0, ctx);
112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
113 av_log(ctx, AV_LOG_ERROR, "Error in parsing expr for drop: %s\n", s->drop_str);
114 return ret;
115 }
116 }
117
118
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 s->var_values[VAR_TB] = ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0;
119 3 s->var_values[VAR_NOPTS] = AV_NOPTS_VALUE;
120 3 s->var_values[VAR_STARTPTS] = AV_NOPTS_VALUE;
121 3 s->var_values[VAR_STARTDTS] = AV_NOPTS_VALUE;
122 3 s->var_values[VAR_STATE] = 0;
123
124 3 return 0;
125 }
126
127 24 static int noise(AVBSFContext *ctx, AVPacket *pkt)
128 {
129 24 NoiseContext *s = ctx->priv_data;
130 24 int i, ret, amount, drop = 0;
131 double res;
132
133 24 ret = ff_bsf_get_packet_ref(ctx, pkt);
134
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 11 times.
24 if (ret < 0)
135 13 return ret;
136
137 11 s->var_values[VAR_N] = s->pkt_idx++;
138 11 s->var_values[VAR_PTS] = pkt->pts;
139 11 s->var_values[VAR_DTS] = pkt->dts;
140 11 s->var_values[VAR_DURATION] =
141 11 s->var_values[VAR_D] = pkt->duration;
142 11 s->var_values[VAR_SIZE] = pkt->size;
143
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 s->var_values[VAR_KEY] = !!(pkt->flags & AV_PKT_FLAG_KEY);
144 11 s->var_values[VAR_POS] = pkt->pos;
145
146
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if (s->var_values[VAR_STARTPTS] == AV_NOPTS_VALUE)
147 3 s->var_values[VAR_STARTPTS] = pkt->pts;
148
149
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if (s->var_values[VAR_STARTDTS] == AV_NOPTS_VALUE)
150 3 s->var_values[VAR_STARTDTS] = pkt->dts;
151
152 11 res = av_expr_eval(s->amount_pexpr, s->var_values, NULL);
153
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (isnan(res))
155 amount = 0;
156
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
11 else if (res < 0)
157 5 amount = (s->state % 10001 + 1);
158 else
159 6 amount = (int)res;
160
161
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
11 if (s->drop_str) {
162 5 res = av_expr_eval(s->drop_pexpr, s->var_values, NULL);
163
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (isnan(res))
165 drop = 0;
166
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 else if (res < 0)
167 5 drop = !(s->state % FFABS((int)res));
168 else
169 drop = !!res;
170 }
171
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if(s->dropamount) {
173 drop = !(s->state % s->dropamount);
174 }
175
176 11 av_log(ctx, AV_LOG_VERBOSE, "Stream #%d packet %d pts %"PRId64" - amount %d drop %d\n",
177 11 pkt->stream_index, (unsigned int)s->var_values[VAR_N], pkt->pts, amount, drop);
178
179
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (drop) {
180 1 s->var_values[VAR_STATE] = ++s->state;
181 1 av_packet_unref(pkt);
182 1 return AVERROR(EAGAIN);
183 }
184
185
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (amount) {
186 10 ret = av_packet_make_writable(pkt);
187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0) {
188 av_packet_unref(pkt);
189 return ret;
190 }
191 }
192
193
2/2
✓ Branch 0 taken 306418 times.
✓ Branch 1 taken 10 times.
306428 for (i = 0; i < pkt->size; i++) {
194 306418 s->state += pkt->data[i] + 1;
195
3/4
✓ Branch 0 taken 306418 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7856 times.
✓ Branch 3 taken 298562 times.
306418 if (amount && s->state % amount == 0)
196 7856 pkt->data[i] = s->state;
197 }
198
199 10 s->var_values[VAR_STATE] = s->state;
200
201 10 return 0;
202 }
203
204 3 static void noise_close(AVBSFContext *bsf)
205 {
206 3 NoiseContext *s = bsf->priv_data;
207
208 3 av_expr_free(s->amount_pexpr);
209 3 av_expr_free(s->drop_pexpr);
210 3 s->amount_pexpr = s->drop_pexpr = NULL;
211 3 }
212
213 #define OFFSET(x) offsetof(NoiseContext, x)
214 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_BSF_PARAM)
215 static const AVOption options[] = {
216 { "amount", NULL, OFFSET(amount_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
217 { "drop", NULL, OFFSET(drop_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
218 { "dropamount", NULL, OFFSET(dropamount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
219 { NULL },
220 };
221
222 static const AVClass noise_class = {
223 .class_name = "noise",
224 .item_name = av_default_item_name,
225 .option = options,
226 .version = LIBAVUTIL_VERSION_INT,
227 };
228
229 const FFBitStreamFilter ff_noise_bsf = {
230 .p.name = "noise",
231 .p.priv_class = &noise_class,
232 .priv_data_size = sizeof(NoiseContext),
233 .init = noise_init,
234 .close = noise_close,
235 .filter = noise,
236 };
237