[FFmpeg-devel] [PATCH] lavfi/fade: Add ability to do video fade based on time

Andy n Deanna andyndeanna at gmail.com
Wed Apr 17 04:20:13 CEST 2013


Attached is a resubmit of a patch to allow video fade filters based on 
time.  Note that I had previously neglected to subscribe to the 
ffmpeg-devel list, so if you have commented before I may have missed it.

Previous email conversation is also attached.

Thanks,
Andy
-------------- next part --------------
>From 641c0ea90a83223c5d49228bf82e1c54018c98fc Mon Sep 17 00:00:00 2001
From: Andy Martin <amartin at ubuntu.(none)>
Date: Tue, 16 Apr 2013 21:35:02 -0400
Subject: [PATCH] lavfi/fade: Added ability to do video fade based on
 timestamp

---
 doc/filters.texi      |   18 +++++++++++
 libavfilter/vf_fade.c |   84 +++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 5228c82..91e109d 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -3010,6 +3010,17 @@ fade-in effect the output video will have the same intensity as the input video,
 at the end of the fade-out transition the output video will be completely black.
 Default is 25.
 
+ at item start_time, st
+Specify the timestamp (in seconds) of the frame to start to apply the fade
+effect. If both start_frame and start_time are specified, the fade will start at
+whichever comes last.  Default is 0.
+
+ at item duration, d
+The number of seconds for which the fade effect has to last. At the end of the
+fade-in effect the output video will have the same intensity as the input video,
+at the end of the fade-out transition the output video will be completely black.
+If both duration and nb_frames are specified, duration is used. Default is 0.
+
 @item alpha
 If set to 1, fade only alpha channel, if one exists on the input.
 Default value is 0.
@@ -3053,6 +3064,13 @@ Fade in alpha over first 25 frames of video:
 @example
 fade=in:0:25:alpha=1
 @end example
+
+ at item
+Make first 5.5 seconds black, then fade in for 0.5 seconds:
+ at example
+fade=t=in:st=5.5:d=0.5
+ at end example
+
 @end itemize
 
 @section field
diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c
index 71e0f01..3785eb8 100644
--- a/libavfilter/vf_fade.c
+++ b/libavfilter/vf_fade.c
@@ -54,13 +54,14 @@ typedef struct {
     int type;
     int factor, fade_per_frame;
     int start_frame, nb_frames;
-    unsigned int frame_index, stop_frame;
+    unsigned int frame_index;
     int hsub, vsub, bpp;
     unsigned int black_level, black_level_scaled;
     uint8_t is_packed_rgb;
     uint8_t rgba_map[4];
     int alpha;
-
+    double start_time, duration;
+    enum {VF_FADE_WAITING=0, VF_FADE_FADING, VF_FADE_DONE} fade_state;
 } FadeContext;
 
 static av_cold int init(AVFilterContext *ctx)
@@ -68,18 +69,17 @@ static av_cold int init(AVFilterContext *ctx)
     FadeContext *fade = ctx->priv;
 
     fade->fade_per_frame = (1 << 16) / fade->nb_frames;
-    if (fade->type == FADE_IN) {
-        fade->factor = 0;
-    } else if (fade->type == FADE_OUT) {
-        fade->fade_per_frame = -fade->fade_per_frame;
-        fade->factor = (1 << 16);
+    fade->fade_state = VF_FADE_WAITING;
+    
+    if (fade->duration != 0.0) {
+        // If duration (seconds) is non-zero, assume that we are not fading based on frames
+        fade->nb_frames = 0; // Mostly to clean up logging
     }
-    fade->stop_frame = fade->start_frame + fade->nb_frames;
-
+     
     av_log(ctx, AV_LOG_VERBOSE,
-           "type:%s start_frame:%d nb_frames:%d alpha:%d\n",
-           fade->type == FADE_IN ? "in" : "out", fade->start_frame,
-           fade->nb_frames, fade->alpha);
+           "type:%s start_frame:%d nb_frames:%d start_time:%f duration:%f alpha:%d\n",
+           fade->type == FADE_IN ? "in" : "out", fade->start_frame, fade->nb_frames, 
+           fade->start_time, fade->duration,fade->alpha);
     return 0;
 }
 
@@ -153,7 +153,53 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
     FadeContext *fade = inlink->dst->priv;
     uint8_t *p;
     int i, j, plane;
-
+    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 (fade->fade_state == VF_FADE_WAITING) {
+            fade->factor=0;
+            if ((frame_timestamp > fade->start_time) && (fade->frame_index >= fade->start_frame)) {
+                // Time to start fading
+                fade->fade_state = VF_FADE_FADING;
+                
+                // Save start time in case we are starting based on frames and fading based on time
+                if ((fade->start_time == 0) && (fade->start_frame != 0)) {
+                    fade->start_time = frame_timestamp;
+                }
+                
+                // Save start frame in case we are starting based on time and fading based on frames
+                if ((fade->start_time != 0) && (fade->start_frame == 0)) {
+                    fade->start_frame = fade->frame_index;
+                }
+            }
+    }
+    if (fade->fade_state == VF_FADE_FADING) {
+        if (fade->duration == 0) {
+            // Fading based on frame count
+            fade->factor = (fade->frame_index - fade->start_frame) * fade->fade_per_frame;
+            if (fade->frame_index > (fade->start_frame + fade->nb_frames)) {
+                fade->fade_state = VF_FADE_DONE;
+            }
+            
+        } else {
+            // Fading based on duration
+            fade->factor = (frame_timestamp - fade->start_time) * (float) UINT16_MAX / fade->duration;
+            if (frame_timestamp > (fade->start_time + fade->duration)) {
+                fade->fade_state = VF_FADE_DONE;
+            }
+        }    
+    }
+    if (fade->fade_state == VF_FADE_DONE) {
+        fade->factor=UINT16_MAX;
+    }
+    
+    fade->factor = av_clip_uint16(fade->factor);
+    
+    // Invert fade_factor if Fading Out
+    if (fade->type == 1) {
+        fade->factor=UINT16_MAX-fade->factor;
+    }
+    
     if (fade->factor < UINT16_MAX) {
         if (fade->alpha) {
             // alpha only
@@ -188,10 +234,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
         }
     }
 
-    if (fade->frame_index >= fade->start_frame &&
-        fade->frame_index <= fade->stop_frame)
-        fade->factor += fade->fade_per_frame;
-    fade->factor = av_clip_uint16(fade->factor);
     fade->frame_index++;
 
     return ff_filter_frame(inlink->dst->outputs[0], frame);
@@ -214,6 +256,14 @@ static const AVOption fade_options[] = {
                                                     OFFSET(nb_frames),   AV_OPT_TYPE_INT, { .i64 = 25 }, 0, INT_MAX, FLAGS },
     { "n",           "Number of frames to which the effect should be applied.",
                                                     OFFSET(nb_frames),   AV_OPT_TYPE_INT, { .i64 = 25 }, 0, INT_MAX, FLAGS },
+    { "start_time",  "Number of seconds of the beginning of the effect.",    
+                                                    OFFSET(start_time),   AV_OPT_TYPE_DOUBLE, {.dbl = 0.   }, 0, 7*24*60*60,FLAGS },
+    { "st",          "Number of seconds of the beginning of the effect.",    
+                                                    OFFSET(start_time),   AV_OPT_TYPE_DOUBLE, {.dbl = 0.   }, 0, 7*24*60*60,FLAGS },
+    { "duration",    "Duration of the effect in seconds.", 
+                                                    OFFSET(duration),     AV_OPT_TYPE_DOUBLE, {.dbl = 0.   }, 0, 24*60*60,  FLAGS },
+    { "d",            "Duration of the effect in seconds.", 
+                                                    OFFSET(duration),     AV_OPT_TYPE_DOUBLE, {.dbl = 0.   }, 0, 24*60*60,  FLAGS },
     { "alpha",       "fade alpha if it is available on the input", OFFSET(alpha),       AV_OPT_TYPE_INT, {.i64 = 0    }, 0,       1, FLAGS },
     { NULL },
 };
-- 
1.7.10.4

-------------- next part --------------
An embedded message was scrubbed...
From: Paul B Mahol <onemda at gmail.com>
Subject: Re: [FFmpeg-devel] ffmpeg vf_fade patch
Date: Mon, 08 Apr 2013 08:48:45 +0000
Size: 12727
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130416/92fe2d32/attachment.mht>


More information about the ffmpeg-devel mailing list