2 * Copyright (c) 2018 Marton Balint
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
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
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "config_components.h"
23 #include "libavutil/opt.h"
24 #include "libavutil/time.h"
30 typedef struct CueContext
{
39 static int activate(AVFilterContext
*ctx
)
41 AVFilterLink
*inlink
= ctx
->inputs
[0];
42 AVFilterLink
*outlink
= ctx
->outputs
[0];
43 CueContext
*s
= ctx
->priv
;
45 FF_FILTER_FORWARD_STATUS_BACK(outlink
, inlink
);
47 if (ff_inlink_queued_frames(inlink
)) {
48 AVFrame
*frame
= ff_inlink_peek_frame(inlink
, 0);
49 int64_t pts
= av_rescale_q(frame
->pts
, inlink
->time_base
, AV_TIME_BASE_Q
);
56 if (pts
- s
->first_pts
< s
->preroll
) {
57 int ret
= ff_inlink_consume_frame(inlink
, &frame
);
60 return ff_filter_frame(outlink
, frame
);
66 frame
= ff_inlink_peek_frame(inlink
, ff_inlink_queued_frames(inlink
) - 1);
67 pts
= av_rescale_q(frame
->pts
, inlink
->time_base
, AV_TIME_BASE_Q
);
68 if (!(pts
- s
->first_pts
< s
->buffer
&& (av_gettime() - s
->cue
) < 0))
73 while ((diff
= (av_gettime() - s
->cue
)) < 0)
74 av_usleep(av_clip(-diff
/ 2, 100, 1000000));
78 int ret
= ff_inlink_consume_frame(inlink
, &frame
);
81 return ff_filter_frame(outlink
, frame
);
85 FF_FILTER_FORWARD_STATUS(inlink
, outlink
);
86 FF_FILTER_FORWARD_WANTED(outlink
, inlink
);
88 return FFERROR_NOT_READY
;
91 #define OFFSET(x) offsetof(CueContext, x)
92 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
93 static const AVOption options
[] = {
94 { "cue", "cue unix timestamp in microseconds", OFFSET(cue
), AV_OPT_TYPE_INT64
, { .i64
= 0 }, 0, INT64_MAX
, FLAGS
},
95 { "preroll", "preroll duration in seconds", OFFSET(preroll
), AV_OPT_TYPE_DURATION
, { .i64
= 0 }, 0, INT64_MAX
, FLAGS
},
96 { "buffer", "buffer duration in seconds", OFFSET(buffer
), AV_OPT_TYPE_DURATION
, { .i64
= 0 }, 0, INT64_MAX
, FLAGS
},
100 AVFILTER_DEFINE_CLASS_EXT(cue_acue
, "(a)cue", options
);
102 #if CONFIG_CUE_FILTER
103 const FFFilter ff_vf_cue
= {
105 .p
.description
= NULL_IF_CONFIG_SMALL("Delay filtering to match a cue."),
106 .p
.priv_class
= &cue_acue_class
,
107 .priv_size
= sizeof(CueContext
),
108 FILTER_INPUTS(ff_video_default_filterpad
),
109 FILTER_OUTPUTS(ff_video_default_filterpad
),
110 .activate
= activate
,
112 #endif /* CONFIG_CUE_FILTER */
114 #if CONFIG_ACUE_FILTER
115 const FFFilter ff_af_acue
= {
117 .p
.description
= NULL_IF_CONFIG_SMALL("Delay filtering to match a cue."),
118 .p
.priv_class
= &cue_acue_class
,
119 .p
.flags
= AVFILTER_FLAG_METADATA_ONLY
,
120 .priv_size
= sizeof(CueContext
),
121 FILTER_INPUTS(ff_audio_default_filterpad
),
122 FILTER_OUTPUTS(ff_audio_default_filterpad
),
123 .activate
= activate
,
125 #endif /* CONFIG_ACUE_FILTER */