]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_fade.c
avformat/3dostr: Check sample_rate
[ffmpeg] / libavfilter / vf_fade.c
index c4fb0bb058ac04a677d724e6aa5201a3dfde02b7..10523fd18ed3af055f3e4bdfab5e15b528899a62 100644 (file)
@@ -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
@@ -221,8 +222,8 @@ static av_always_inline void filter_rgb_planar(FadeContext *s, const AVFrame *fr
         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);
@@ -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;
             }
         }
@@ -539,8 +542,8 @@ static const AVOption fade_options[] = {
                                                     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 }
 };
 
@@ -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,
     },
@@ -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,
 };