FFmpeg
Loading...
Searching...
No Matches
f_segment.c
Go to the documentation of this file.
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#include "config_components.h"
20
21#include <stdint.h>
22
23#include "libavutil/avstring.h"
24#include "libavutil/log.h"
26#include "libavutil/mem.h"
27#include "libavutil/opt.h"
29
30#include "avfilter.h"
31#include "filters.h"
32
46
47static void count_points(char *item_str, int *nb_items)
48{
49 char *p;
50
51 if (!item_str)
52 return;
53
54 *nb_items = 1;
55 for (p = item_str; *p; p++) {
56 if (*p == '|')
57 (*nb_items)++;
58 }
59}
60
61static int parse_points(AVFilterContext *ctx, char *item_str, int nb_points, int64_t *points)
62{
63 SegmentContext *s = ctx->priv;
64 char *arg, *p = item_str;
65 char *saveptr = NULL;
66 int64_t ref, cur = 0;
67 int ret = 0;
68
69 for (int i = 0; i < nb_points; i++) {
70 if (!(arg = av_strtok(p, "|", &saveptr)))
71 return AVERROR(EINVAL);
72
73 p = NULL;
74 ref = 0;
75 if (*arg == '+') {
76 ref = cur;
77 arg++;
78 }
79
80 if (s->use_timestamps) {
81 ret = av_parse_time(&points[i], arg, s->use_timestamps);
82 } else {
83 if (sscanf(arg, "%"SCNd64, &points[i]) != 1)
84 ret = AVERROR(EINVAL);
85 }
86
87 if (ret < 0) {
88 av_log(ctx, AV_LOG_ERROR, "Invalid splits supplied: %s\n", arg);
89 return ret;
90 }
91
92 cur = points[i];
93 points[i] += ref;
94 }
95
96 return 0;
97}
98
100{
101 SegmentContext *s = ctx->priv;
102 char *split_str;
103 int ret;
104
105 if (s->timestamps_str && s->points_str) {
106 av_log(ctx, AV_LOG_ERROR, "Both timestamps and counts supplied.\n");
107 return AVERROR(EINVAL);
108 } else if (s->timestamps_str) {
109 s->use_timestamps = 1;
110 split_str = s->timestamps_str;
111 } else if (s->points_str) {
112 split_str = s->points_str;
113 } else {
114 av_log(ctx, AV_LOG_ERROR, "Neither timestamps nor durations nor counts supplied.\n");
115 return AVERROR(EINVAL);
116 }
117
118 count_points(split_str, &s->nb_points);
119 s->nb_points++;
120
121 s->points = av_calloc(s->nb_points, sizeof(*s->points));
122 if (!s->points)
123 return AVERROR(ENOMEM);
124
125 ret = parse_points(ctx, split_str, s->nb_points - 1, s->points);
126 if (ret < 0)
127 return ret;
128
129 s->points[s->nb_points - 1] = INT64_MAX;
130
131 for (int i = 0; i < s->nb_points; i++) {
132 AVFilterPad pad = { 0 };
133
134 pad.type = type;
135 pad.name = av_asprintf("output%d", i);
136 if (!pad.name)
137 return AVERROR(ENOMEM);
138
139 if ((ret = ff_append_outpad_free_name(ctx, &pad)) < 0)
140 return ret;
141 }
142
143 return 0;
144}
145
146static int config_input(AVFilterLink *inlink)
147{
148 AVFilterContext *ctx = inlink->dst;
149 SegmentContext *s = ctx->priv;
150 AVRational tb = inlink->time_base;
151
152 if (s->use_timestamps) {
153 for (int i = 0; i < s->nb_points - 1; i++)
154 s->points[i] = av_rescale_q(s->points[i], AV_TIME_BASE_Q, tb);
155 }
156
157 return 0;
158}
159
161{
162 SegmentContext *s = ctx->priv;
163 AVFilterLink *inlink = ctx->inputs[0];
164 FilterLink *inl = ff_filter_link(inlink);
165 int ret = 0;
166
167 if (s->use_timestamps) {
168 ret = frame->pts >= s->points[s->current_point];
169 } else {
170 switch (inlink->type) {
172 ret = inl->frame_count_out - 1 >= s->points[s->current_point];
173 break;
175 ret = inl->sample_count_out - frame->nb_samples >= s->points[s->current_point];
176 break;
177 }
178 }
179
180 return ret;
181}
182
184{
185 AVFilterLink *inlink = ctx->inputs[0];
186 FilterLink *inl = ff_filter_link(inlink);
187 SegmentContext *s = ctx->priv;
188 AVFrame *frame = NULL;
189 int ret, status;
190 int64_t max_samples;
192 int64_t pts;
193
194 for (int i = s->current_point; i < s->nb_points; i++) {
196 }
197
198 switch (inlink->type) {
200 ret = ff_inlink_consume_frame(inlink, &frame);
201 break;
203 diff = s->points[s->current_point] - inl->sample_count_out;
204 while (diff <= 0) {
205 ff_outlink_set_status(ctx->outputs[s->current_point], AVERROR_EOF, s->last_pts);
206 s->current_point++;
207 if (s->current_point >= s->nb_points)
208 return AVERROR(EINVAL);
209
210 diff = s->points[s->current_point] - inl->sample_count_out;
211 }
212 if (s->use_timestamps) {
213 max_samples = av_rescale_q(diff, av_make_q(1, inlink->sample_rate), inlink->time_base);
214 } else {
215 max_samples = FFMAX(1, FFMIN(diff, INT_MAX));
216 }
217 if (max_samples <= 0 || max_samples > INT_MAX)
218 ret = ff_inlink_consume_frame(inlink, &frame);
219 else
220 ret = ff_inlink_consume_samples(inlink, 1, max_samples, &frame);
221 break;
222 default:
223 return AVERROR_BUG;
224 }
225
226 if (ret > 0) {
227 s->last_pts = frame->pts;
229 ff_outlink_set_status(ctx->outputs[s->current_point], AVERROR_EOF, frame->pts);
230 s->current_point++;
231 }
232
233 if (s->current_point >= s->nb_points) {
235 return AVERROR(EINVAL);
236 }
237
238 ret = ff_filter_frame(ctx->outputs[s->current_point], frame);
239 }
240
241 if (ret < 0) {
242 return ret;
243 } else if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
244 for (int i = s->current_point; i < s->nb_points; i++)
245 ff_outlink_set_status(ctx->outputs[i], status, pts);
246 return 0;
247 } else {
248 for (int i = s->current_point; i < s->nb_points; i++) {
249 if (ff_outlink_frame_wanted(ctx->outputs[i]))
251 }
252 return 0;
253 }
254}
255
257{
258 SegmentContext *s = ctx->priv;
259
260 av_freep(&s->points);
261}
262
263#define OFFSET(x) offsetof(SegmentContext, x)
264#define COMMON_OPTS \
265 { "timestamps", "timestamps of input at which to split input", OFFSET(timestamps_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, \
266
267#if CONFIG_SEGMENT_FILTER
268
269static av_cold int video_init(AVFilterContext *ctx)
270{
271 return init(ctx, AVMEDIA_TYPE_VIDEO);
272}
273
274#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
275static const AVOption segment_options[] = {
277 { "frames", "frames at which to split input", OFFSET(points_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
278 { NULL }
279};
280#undef FLAGS
281
283
284static const AVFilterPad segment_inputs[] = {
285 {
286 .name = "default",
287 .type = AVMEDIA_TYPE_VIDEO,
288 .config_props = config_input,
289 },
290};
291
292const FFFilter ff_vf_segment = {
293 .p.name = "segment",
294 .p.description = NULL_IF_CONFIG_SMALL("Segment video stream."),
295 .p.priv_class = &segment_class,
297 .init = video_init,
298 .uninit = uninit,
299 .priv_size = sizeof(SegmentContext),
301 FILTER_INPUTS(segment_inputs),
302};
303#endif // CONFIG_SEGMENT_FILTER
304
305#if CONFIG_ASEGMENT_FILTER
306
307static av_cold int audio_init(AVFilterContext *ctx)
308{
309 return init(ctx, AVMEDIA_TYPE_AUDIO);
310}
311
312#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
313static const AVOption asegment_options[] = {
315 { "samples", "samples at which to split input", OFFSET(points_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
316 { NULL }
317};
318#undef FLAGS
319
320AVFILTER_DEFINE_CLASS(asegment);
321
322static const AVFilterPad asegment_inputs[] = {
323 {
324 .name = "default",
325 .type = AVMEDIA_TYPE_AUDIO,
326 .config_props = config_input,
327 },
328};
329
330const FFFilter ff_af_asegment = {
331 .p.name = "asegment",
332 .p.description = NULL_IF_CONFIG_SMALL("Segment audio stream."),
333 .p.priv_class = &asegment_class,
335 .init = audio_init,
336 .uninit = uninit,
337 .priv_size = sizeof(SegmentContext),
339 FILTER_INPUTS(asegment_inputs),
340};
341#endif // CONFIG_ASEGMENT_FILTER
static int config_input(AVFilterLink *inlink)
const FFFilter ff_af_asegment
const FFFilter ff_vf_segment
static AVFormatContext * ctx
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition avfilter.c:1467
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_outlink_frame_wanted(AVFilterLink *link)
Test if a frame is wanted on an output link.
Definition avfilter.c:1690
int ff_append_outpad_free_name(AVFilterContext *f, AVFilterPad *p)
Definition avfilter.c:143
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
Definition avfilter.c:1540
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition avfilter.c:1520
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition avfilter.c:1623
Main libavfilter public API header.
char * av_asprintf(const char *fmt,...)
Definition avstring.c:115
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static int config_input(AVFilterLink *inlink)
Definition f_segment.c:146
static int current_segment_finished(AVFilterContext *ctx, AVFrame *frame)
Definition f_segment.c:160
static void count_points(char *item_str, int *nb_items)
Definition f_segment.c:47
static int activate(AVFilterContext *ctx)
Definition f_segment.c:183
static av_cold void uninit(AVFilterContext *ctx)
Definition f_segment.c:256
#define OFFSET(x)
Definition f_segment.c:263
static int parse_points(AVFilterContext *ctx, char *item_str, int nb_points, int64_t *points)
Definition f_segment.c:61
#define COMMON_OPTS
Definition f_segment.c:264
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS
The number of the filter outputs is not determined just by AVFilter.outputs.
Definition avfilter.h:161
#define AVFILTER_FLAG_METADATA_ONLY
The filter is a "metadata" filter - it does not modify the frame data in any way.
Definition avfilter.h:182
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition rational.h:71
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
AVMediaType
Definition avutil.h:198
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition avstring.c:179
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
cl_device_type type
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
const char * arg
Definition jacosubdec.c:65
#define FILTER_INPUTS(array)
Definition filters.h:264
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition filters.h:629
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
Definition filters.h:652
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
AVOptions.
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
Definition parseutils.c:592
misc parsing utilities
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
A filter pad used for either input or output.
Definition filters.h:40
enum AVMediaType type
AVFilterPad type.
Definition filters.h:51
const char * name
Pad name.
Definition filters.h:46
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
AVOption.
Definition opt.h:428
Rational number (pair of numerator and denominator).
Definition rational.h:58
int64_t last_pts
Definition f_segment.c:42
char * points_str
Definition f_segment.c:37
char * timestamps_str
Definition f_segment.c:36
int64_t * points
Definition f_segment.c:44
Definition hls.c:77
#define av_freep(p)
#define av_log(a,...)
static int ref[MAX_W *MAX_W]
static int64_t pts
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)