X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_fade.c;h=3c65b0f2acfca16cafa3571a4d54270104b807b6;hb=4e8d22478bc854949a9adbda97348f2997e1dc8d;hp=58d7f8cd49fc0b6dda0360b6ffe98dc906a25333;hpb=d64cbd4fda01c6e33e9e5e6f859e81c47bdb1760;p=ffmpeg diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c index 58d7f8cd49f..3c65b0f2acf 100644 --- a/libavfilter/vf_fade.c +++ b/libavfilter/vf_fade.c @@ -62,6 +62,7 @@ typedef struct FadeContext { 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 @@ -403,7 +404,7 @@ static int filter_slice_alpha16(AVFilterContext *ctx, void *arg, int jobnr, 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); @@ -422,6 +423,11 @@ static int config_props(AVFilterLink *inlink) 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; @@ -440,29 +446,28 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { 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) { @@ -471,10 +476,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } 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; } } @@ -550,7 +553,7 @@ static const AVFilterPad avfilter_vf_fade_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .config_props = config_props, + .config_props = config_input, .filter_frame = filter_frame, .needs_writable = 1, }, @@ -565,7 +568,7 @@ static const AVFilterPad avfilter_vf_fade_outputs[] = { { NULL } }; -AVFilter ff_vf_fade = { +const AVFilter ff_vf_fade = { .name = "fade", .description = NULL_IF_CONFIG_SMALL("Fade in/out input video."), .init = init, @@ -574,5 +577,6 @@ AVFilter ff_vf_fade = { .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, };