FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bsf/source.c
Date: 2026-07-21 08:37:06
Exec Total Coverage
Lines: 12 85 14.1%
Functions: 3 11 27.3%
Branches: 1 44 2.3%

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 * Packet source. Heavily based on libavfilter/buffersrc.c
22 */
23
24 #include <float.h>
25
26 #include "libavutil/container_fifo.h"
27 #include "libavutil/opt.h"
28
29 #include "libavcodec/bsf.h"
30 #include "libavcodec/bsf_internal.h"
31 #include "libavcodec/packet.h"
32 #include "libavcodec/packet_internal.h"
33
34 typedef struct SourceContext {
35 const AVClass *class;
36 AVCodecParameters *par;
37 AVRational time_base; ///< time_base to set in the output link
38
39 unsigned nb_failed_requests;
40 unsigned warning_limit;
41
42 int eof;
43 int64_t last_pts;
44 } SourceContext;
45
46 6 int av_bsf_source_parameters_set(AVBitStreamFilterContext *ctx, const AVCodecParameters *par)
47 {
48 6 SourceContext *s = ctx->priv_data;
49
50 6 return avcodec_parameters_copy(s->par, par);
51 }
52
53 static int push_packet(AVBitStreamFilterGraph *graph)
54 {
55 int ret;
56
57 while (1) {
58 ret = ff_bsf_graph_run_once(graph);
59 if (ret == AVERROR(EAGAIN))
60 break;
61 if (ret < 0 && ret != FFERROR_SOURCE_EMPTY)
62 return ret;
63 }
64 return 0;
65 }
66
67 int attribute_align_arg av_bsf_source_add_packet(AVBitStreamFilterContext *ctx, AVPacket *pkt, int flags)
68 {
69 SourceContext *s = ctx->priv_data;
70 AVPacket *copy;
71 int ret;
72
73 s->nb_failed_requests = 0;
74
75 if (!pkt || AVPACKET_IS_EMPTY(pkt))
76 return av_bsf_source_close(ctx, s->last_pts, flags);
77 if (s->eof)
78 return AVERROR_EOF;
79
80 s->last_pts = pkt->pts + pkt->duration;
81
82 copy = av_packet_alloc();
83 if (!copy)
84 return AVERROR(ENOMEM);
85
86 if ((flags & AV_BSF_SOURCE_FLAG_KEEP_REF)) {
87 ret = av_packet_ref(copy, pkt);
88 if (ret < 0) {
89 av_packet_free(&copy);
90 return ret;
91 }
92 } else
93 av_packet_move_ref(copy, pkt);
94
95 ret = ff_bsf_filter_packet(ctx->outputs[0], copy);
96 if (ret < 0)
97 return ret;
98
99 if ((flags & AV_BSF_SOURCE_FLAG_PUSH)) {
100 ret = push_packet(ctx->graph);
101 if (ret < 0)
102 return ret;
103 }
104
105 BitStreamFilterLinkInternal *const li = ff_link_internal(ctx->outputs[0]);
106 if (s->warning_limit &&
107 av_container_fifo_can_read(li->fifo) >= s->warning_limit) {
108 av_log(s, AV_LOG_WARNING,
109 "%d buffers queued in %s, something may be wrong.\n",
110 s->warning_limit,
111 (char *)av_x_if_null(ctx->name, ctx->filter->name));
112 s->warning_limit *= 10;
113 }
114
115 return 0;
116 }
117
118 int av_bsf_source_close(AVBitStreamFilterContext *ctx, int64_t pts, unsigned flags)
119 {
120 SourceContext *s = ctx->priv_data;
121
122 s->eof = 1;
123 ff_bsf_link_set_in_status(ctx->outputs[0], AVERROR_EOF, pts);
124 return 0;
125 }
126
127 int av_bsf_source_get_status(AVBitStreamFilterContext *ctx)
128 {
129 SourceContext *s = ctx->priv_data;
130
131 if (!s->eof && ff_bsf_outlink_get_status(ctx->outputs[0]))
132 s->eof = 1;
133
134 return s->eof ? AVERROR(EOF) : 0;
135 }
136
137 6 static av_cold int preinit(AVBitStreamFilterContext *ctx)
138 {
139 6 SourceContext *c = ctx->priv_data;
140
141 6 c->par = avcodec_parameters_alloc();
142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!c->par)
143 return AVERROR(ENOMEM);
144
145 6 return 0;
146 }
147
148 static av_cold int init(AVBitStreamFilterContext *ctx)
149 {
150 SourceContext *c = ctx->priv_data;
151
152 if (av_q2d(c->time_base) <= 0) {
153 av_log(ctx, AV_LOG_ERROR, "Invalid time base %d/%d\n", c->time_base.num, c->time_base.den);
154 return AVERROR(EINVAL);
155 }
156
157 c->warning_limit = 100;
158 return 0;
159 }
160
161 unsigned ff_bsf_source_get_nb_failed_requests(const AVBitStreamFilterContext *buffer_src)
162 {
163 return ((SourceContext *)buffer_src->priv_data)->nb_failed_requests;
164 }
165
166 #define OFFSET(x) offsetof(SourceContext, x)
167 #define FLAGS (AV_OPT_FLAG_BSF_PARAM|AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
168 static const AVOption buffer_options[] = {
169 { "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, FLAGS },
170 { NULL },
171 };
172
173 BSF_DEFINE_CLASS(buffer);
174
175 6 static av_cold void uninit(AVBitStreamFilterContext *ctx)
176 {
177 6 SourceContext *s = ctx->priv_data;
178 6 avcodec_parameters_free(&s->par);
179 6 }
180
181 static int config_props(AVBitStreamFilterLink *link)
182 {
183 SourceContext *c = link->src->priv_data;
184
185 link->time_base = c->time_base;
186 return avcodec_parameters_copy(link->par, c->par);
187 }
188
189 static int activate(AVBitStreamFilterContext *ctx)
190 {
191 AVBitStreamFilterLink *outlink = ctx->outputs[0];
192 SourceContext *c = ctx->priv_data;
193
194 if (!c->eof && ff_bsf_outlink_get_status(outlink)) {
195 c->eof = 1;
196 return 0;
197 }
198
199 if (c->eof) {
200 ff_bsf_link_set_in_status(outlink, AVERROR_EOF, c->last_pts);
201 return 0;
202 }
203 c->nb_failed_requests++;
204 return FFERROR_SOURCE_EMPTY;
205 }
206
207 static const AVBitStreamFilterPad source_outputs[] = {
208 {
209 .name = "default",
210 .config_props = config_props,
211 },
212 };
213
214 const FFBitStreamFilter ff_source_bsf = {
215 .p.name = "source",
216 .p.priv_class = &buffer_class,
217 .priv_data_size = sizeof(SourceContext),
218 .activate = activate,
219 .preinit = preinit,
220 .init2 = init,
221 .uninit = uninit,
222
223 BSFILTER_OUTPUTS(source_outputs),
224 };
225