int alpha;
int is_planar;
uint64_t start_time, duration;
+ uint64_t start_time_pts, duration_pts;
enum {VF_FADE_WAITING=0, VF_FADE_FADING, VF_FADE_DONE} fade_state;
uint8_t color_rgba[4]; ///< fade color
int black_fade; ///< if color_rgba is black
uint8_t *pa = frame->data[3] + i * frame->linesize[3];
for (j = 0; j < frame->width; j++) {
#define INTERPP(c_name, c_idx) av_clip_uint8(((c[c_idx]<<16) + ((int)c_name - (int)c[c_idx]) * s->factor + (1<<15)) >> 16)
- pr[j] = INTERPP(pr[j], 1);
- pg[j] = INTERPP(pg[j], 0);
+ pr[j] = INTERPP(pr[j], 0);
+ pg[j] = INTERPP(pg[j], 1);
pb[j] = INTERPP(pb[j], 2);
if (do_alpha)
pa[j] = INTERPP(pa[j], 3);
return 0;
}
-static int config_props(AVFilterLink *inlink)
+static int config_input(AVFilterLink *inlink)
{
FadeContext *s = inlink->dst->priv;
const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(inlink->format);
s->is_rgb = pixdesc->flags & AV_PIX_FMT_FLAG_RGB;
s->is_packed_rgb = !s->is_planar && s->is_rgb;
+ if (s->duration)
+ s->duration_pts = av_rescale_q(s->duration, AV_TIME_BASE_Q, inlink->time_base);
+ if (s->start_time)
+ s->start_time_pts = av_rescale_q(s->start_time, AV_TIME_BASE_Q, inlink->time_base);
+
/* use CCIR601/709 black level for studio-level pixel non-alpha components */
s->black_level =
ff_fmt_is_in(inlink->format, studio_level_pix_fmts) && !s->alpha ? 16 * (1 << (s->depth - 8)): 0;
{
AVFilterContext *ctx = inlink->dst;
FadeContext *s = ctx->priv;
- double frame_timestamp = frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base);
// Calculate Fade assuming this is a Fade In
if (s->fade_state == VF_FADE_WAITING) {
s->factor=0;
- if (frame_timestamp >= s->start_time/(double)AV_TIME_BASE
+ if (frame->pts >= s->start_time_pts
&& inlink->frame_count_out >= s->start_frame) {
// Time to start fading
s->fade_state = VF_FADE_FADING;
// Save start time in case we are starting based on frames and fading based on time
- if (s->start_time == 0 && s->start_frame != 0) {
- s->start_time = frame_timestamp*(double)AV_TIME_BASE;
+ if (s->start_time_pts == 0 && s->start_frame != 0) {
+ s->start_time_pts = frame->pts;
}
// Save start frame in case we are starting based on time and fading based on frames
- if (s->start_time != 0 && s->start_frame == 0) {
+ if (s->start_time_pts != 0 && s->start_frame == 0) {
s->start_frame = inlink->frame_count_out;
}
}
}
if (s->fade_state == VF_FADE_FADING) {
- if (s->duration == 0) {
+ if (s->duration_pts == 0) {
// Fading based on frame count
s->factor = (inlink->frame_count_out - s->start_frame) * s->fade_per_frame;
if (inlink->frame_count_out > s->start_frame + s->nb_frames) {
} else {
// Fading based on duration
- s->factor = (frame_timestamp - s->start_time/(double)AV_TIME_BASE)
- * (float) UINT16_MAX / (s->duration/(double)AV_TIME_BASE);
- if (frame_timestamp > s->start_time/(double)AV_TIME_BASE
- + s->duration/(double)AV_TIME_BASE) {
+ s->factor = (frame->pts - s->start_time_pts) * UINT16_MAX / s->duration_pts;
+ if (frame->pts > s->start_time_pts + s->duration_pts) {
s->fade_state = VF_FADE_DONE;
}
}
OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS },
{ "d", "Duration of the effect in seconds.",
OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS },
- { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS },
+ { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS },
+ { "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS },
{ NULL }
};
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .config_props = config_props,
+ .config_props = config_input,
.filter_frame = filter_frame,
.needs_writable = 1,
},
.query_formats = query_formats,
.inputs = avfilter_vf_fade_inputs,
.outputs = avfilter_vf_fade_outputs,
- .flags = AVFILTER_FLAG_SLICE_THREADS,
+ .flags = AVFILTER_FLAG_SLICE_THREADS |
+ AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
};