FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/bsf/sink.c
Date: 2026-09-29 17:04:06
Exec Total Coverage
Lines: 4 58 6.9%
Functions: 1 7 14.3%
Branches: 0 30 0.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 * Packet sink. Heavily based on libavfilter/buffersink.c
22 */
23
24 #include "libavutil/avassert.h"
25 #include "libavutil/opt.h"
26
27 #include "libavcodec/bsf.h"
28 #include "libavcodec/bsf_internal.h"
29 #include "libavcodec/packet.h"
30 #include "libavcodec/packet_internal.h"
31
32 typedef struct BufferSinkContext {
33 const AVClass *class;
34 unsigned warning_limit;
35
36 AVPacket *peeked_pkt;
37 } BufferSinkContext;
38
39 ✗ static int return_or_keep_packet(BufferSinkContext *buf, AVPacket *out, AVPacket *in, int flags)
40 {
41 ✗ if ((flags & AV_BSF_SINK_FLAG_PEEK)) {
42 ✗ buf->peeked_pkt = in;
43 ✗ return av_packet_ref(out, in);
44 } else {
45 ✗ buf->peeked_pkt = NULL;
46 ✗ av_packet_move_ref(out, in);
47 ✗ av_packet_free(&in);
48 ✗ return 0;
49 }
50 }
51
52 ✗ int attribute_align_arg av_bsf_sink_get_packet(AVBitStreamFilterContext *ctx, AVPacket *pkt, int flags)
53 {
54 ✗ BufferSinkContext *buf = ctx->priv_data;
55 ✗ AVBitStreamFilterLink *inlink = ctx->inputs[0];
56 ✗ BitStreamFilterLinkInternal *li = ff_link_internal(inlink);
57 int status, ret;
58 AVPacket *cur_pkt;
59 int64_t pts;
60 ✗ int buffersrc_empty = 0;
61
62 ✗ if (buf->peeked_pkt)
63 ✗ return return_or_keep_packet(buf, pkt, buf->peeked_pkt, flags);
64
65 while (1) {
66 ✗ ret = ff_bsf_inlink_consume_packet(inlink, &cur_pkt);
67 ✗ if (ret < 0) {
68 ✗ return ret;
69 ✗ } else if (ret) {
70 ✗ return return_or_keep_packet(buf, pkt, cur_pkt, flags);
71 ✗ } else if (ff_bsf_inlink_acknowledge_status(inlink, &status, &pts)) {
72 ✗ return status;
73 ✗ } else if ((flags & AV_BSF_SINK_FLAG_NO_REQUEST)) {
74 ✗ return AVERROR(EAGAIN);
75 ✗ } else if (li->packet_wanted_out) {
76 ✗ ret = ff_bsf_graph_run_once(ctx->graph);
77 ✗ if (ret == FFERROR_SOURCE_EMPTY) {
78 ✗ buffersrc_empty = 1;
79 ✗ } else if (ret == AVERROR(EAGAIN)) {
80 ✗ if (buffersrc_empty)
81 ✗ return ret;
82 ✗ ff_bsf_inlink_request_packet(inlink);
83 ✗ } else if (ret < 0) {
84 ✗ return ret;
85 }
86 } else {
87 ✗ ff_bsf_inlink_request_packet(inlink);
88 }
89 }
90 }
91
92 ✗ static int init(AVBitStreamFilterContext *ctx)
93 {
94 ✗ BufferSinkContext *s = ctx->priv_data;
95
96 ✗ s->warning_limit = 100;
97
98 ✗ return 0;
99 }
100
101 3 static void uninit(AVBitStreamFilterContext *ctx)
102 {
103 3 BufferSinkContext *buf = ctx->priv_data;
104
105 3 av_packet_free(&buf->peeked_pkt);
106 3 }
107
108 ✗ static int activate(AVBitStreamFilterContext *ctx)
109 {
110 ✗ BufferSinkContext *buf = ctx->priv_data;
111 ✗ BitStreamFilterLinkInternal * const li = ff_link_internal(ctx->inputs[0]);
112
113 ✗ if (buf->warning_limit &&
114 ✗ av_container_fifo_can_read(li->fifo) >= buf->warning_limit) {
115 ✗ av_log(ctx, AV_LOG_WARNING,
116 "%d buffers queued in %s, something may be wrong.\n",
117 buf->warning_limit,
118 ✗ (char *)av_x_if_null(ctx->name, ctx->filter->name));
119 ✗ buf->warning_limit *= 10;
120 }
121
122 /* The packet is queued, the rest is up to av_bsf_sink_get_packet */
123 ✗ return 0;
124 }
125
126 ✗ AVRational av_bsf_sink_get_time_base(const AVBitStreamFilterContext *ctx)
127 {
128 ✗ av_assert0(ff_bsf(ctx->filter)->activate == activate);
129 ✗ return ctx->inputs[0]->time_base;
130 }
131
132 ✗ const AVCodecParameters *av_bsf_sink_get_parameters(const AVBitStreamFilterContext *ctx)
133 {
134 ✗ av_assert0(ff_bsf(ctx->filter)->activate == activate);
135 ✗ return ctx->inputs[0]->par;
136 }
137
138 BSF_DEFINE_CLASS_EXT(sink, "sink", NULL);
139
140 const FFBitStreamFilter ff_sink_bsf = {
141 .p.name = "sink",
142 .p.priv_class = &sink_class,
143 .priv_data_size = sizeof(BufferSinkContext),
144 .init2 = init,
145 .uninit = uninit,
146 .activate = activate,
147 BSFILTER_INPUTS(ff_default_bsf_pad),
148 };
149