FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/split.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 39 49 79.6%
Functions: 2 2 100.0%
Branches: 27 36 75.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2007 Bobby Bingham
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 /**
22 * @file
23 * audio and video splitter
24 */
25
26 #include <stdio.h>
27
28 #include "libavutil/attributes.h"
29 #include "libavutil/avstring.h"
30 #include "libavutil/internal.h"
31 #include "libavutil/opt.h"
32
33 #include "avfilter.h"
34 #include "audio.h"
35 #include "filters.h"
36 #include "video.h"
37
38 typedef struct SplitContext {
39 const AVClass *class;
40 int nb_outputs;
41 } SplitContext;
42
43 38 static av_cold int split_init(AVFilterContext *ctx)
44 {
45 38 SplitContext *s = ctx->priv;
46 int i, ret;
47
48
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 38 times.
114 for (i = 0; i < s->nb_outputs; i++) {
49 76 AVFilterPad pad = { 0 };
50
51 76 pad.type = ctx->filter->inputs[0].type;
52 76 pad.name = av_asprintf("output%d", i);
53
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (!pad.name)
54 return AVERROR(ENOMEM);
55
56
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
76 if ((ret = ff_append_outpad_free_name(ctx, &pad)) < 0)
57 return ret;
58 }
59
60 38 return 0;
61 }
62
63 1656 static int activate(AVFilterContext *ctx)
64 {
65 1656 AVFilterLink *inlink = ctx->inputs[0];
66 AVFrame *in;
67 1656 int status, ret, nb_eofs = 0;
68 int64_t pts;
69
70
2/2
✓ Branch 0 taken 3312 times.
✓ Branch 1 taken 1656 times.
4968 for (int i = 0; i < ctx->nb_outputs; i++)
71 3312 nb_eofs += ff_outlink_get_status(ctx->outputs[i]) == AVERROR_EOF;
72
73
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1653 times.
1656 if (nb_eofs == ctx->nb_outputs) {
74 3 ff_inlink_set_status(inlink, AVERROR_EOF);
75 3 return 0;
76 }
77
78 1653 ret = ff_inlink_consume_frame(inlink, &in);
79
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1653 times.
1653 if (ret < 0)
80 return ret;
81
2/2
✓ Branch 0 taken 539 times.
✓ Branch 1 taken 1114 times.
1653 if (ret > 0) {
82
2/2
✓ Branch 0 taken 1078 times.
✓ Branch 1 taken 539 times.
1617 for (int i = 0; i < ctx->nb_outputs; i++) {
83 AVFrame *buf_out;
84
85
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1078 times.
1078 if (ff_outlink_get_status(ctx->outputs[i]))
86 continue;
87 1078 buf_out = av_frame_clone(in);
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1078 times.
1078 if (!buf_out) {
89 ret = AVERROR(ENOMEM);
90 break;
91 }
92
93 1078 ret = ff_filter_frame(ctx->outputs[i], buf_out);
94
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1078 times.
1078 if (ret < 0)
95 break;
96 }
97
98 539 av_frame_free(&in);
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 539 times.
539 if (ret < 0)
100 return ret;
101 }
102
103
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 1637 times.
1653 if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
104
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
48 for (int i = 0; i < ctx->nb_outputs; i++) {
105
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (ff_outlink_get_status(ctx->outputs[i]))
106 continue;
107 32 ff_outlink_set_status(ctx->outputs[i], status, pts);
108 }
109 16 return 0;
110 }
111
112
2/2
✓ Branch 0 taken 2444 times.
✓ Branch 1 taken 539 times.
2983 for (int i = 0; i < ctx->nb_outputs; i++) {
113
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2444 times.
2444 if (ff_outlink_get_status(ctx->outputs[i]))
114 continue;
115
116
2/2
✓ Branch 1 taken 1098 times.
✓ Branch 2 taken 1346 times.
2444 if (ff_outlink_frame_wanted(ctx->outputs[i])) {
117 1098 ff_inlink_request_frame(inlink);
118 1098 return 0;
119 }
120 }
121
122 539 return FFERROR_NOT_READY;
123 }
124
125 #define OFFSET(x) offsetof(SplitContext, x)
126 #define FLAGS (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
127 static const AVOption options[] = {
128 { "outputs", "set number of outputs", OFFSET(nb_outputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT_MAX, FLAGS },
129 { NULL }
130 };
131
132 AVFILTER_DEFINE_CLASS_EXT(split, "(a)split", options);
133
134 const AVFilter ff_vf_split = {
135 .name = "split",
136 .description = NULL_IF_CONFIG_SMALL("Pass on the input to N video outputs."),
137 .priv_size = sizeof(SplitContext),
138 .priv_class = &split_class,
139 .init = split_init,
140 .activate = activate,
141 FILTER_INPUTS(ff_video_default_filterpad),
142 .outputs = NULL,
143 .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY,
144 };
145
146 const AVFilter ff_af_asplit = {
147 .name = "asplit",
148 .description = NULL_IF_CONFIG_SMALL("Pass on the audio input to N audio outputs."),
149 .priv_class = &split_class,
150 .priv_size = sizeof(SplitContext),
151 .init = split_init,
152 .activate = activate,
153 FILTER_INPUTS(ff_audio_default_filterpad),
154 .outputs = NULL,
155 .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY,
156 };
157