Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2010 Brandon Mintern
  3.  * Copyright (c) 2007 Bobby Bingham
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. /**
  23.  * @file
  24.  * video fade filter
  25.  * based heavily on vf_negate.c by Bobby Bingham
  26.  */
  27.  
  28. #include "libavutil/avstring.h"
  29. #include "libavutil/common.h"
  30. #include "libavutil/eval.h"
  31. #include "libavutil/opt.h"
  32. #include "libavutil/pixdesc.h"
  33. #include "avfilter.h"
  34. #include "drawutils.h"
  35. #include "formats.h"
  36. #include "internal.h"
  37. #include "video.h"
  38.  
  39. #define R 0
  40. #define G 1
  41. #define B 2
  42. #define A 3
  43.  
  44. #define Y 0
  45. #define U 1
  46. #define V 2
  47.  
  48. #define FADE_IN  0
  49. #define FADE_OUT 1
  50.  
  51. typedef struct {
  52.     const AVClass *class;
  53.     int type;
  54.     int factor, fade_per_frame;
  55.     int start_frame, nb_frames;
  56.     unsigned int frame_index;
  57.     int hsub, vsub, bpp;
  58.     unsigned int black_level, black_level_scaled;
  59.     uint8_t is_packed_rgb;
  60.     uint8_t rgba_map[4];
  61.     int alpha;
  62.     uint64_t start_time, duration;
  63.     enum {VF_FADE_WAITING=0, VF_FADE_FADING, VF_FADE_DONE} fade_state;
  64. } FadeContext;
  65.  
  66. static av_cold int init(AVFilterContext *ctx)
  67. {
  68.     FadeContext *s = ctx->priv;
  69.  
  70.     s->fade_per_frame = (1 << 16) / s->nb_frames;
  71.     s->fade_state = VF_FADE_WAITING;
  72.  
  73.     if (s->duration != 0) {
  74.         // If duration (seconds) is non-zero, assume that we are not fading based on frames
  75.         s->nb_frames = 0; // Mostly to clean up logging
  76.     }
  77.  
  78.     // Choose what to log. If both time-based and frame-based options, both lines will be in the log
  79.     if (s->start_frame || s->nb_frames) {
  80.         av_log(ctx, AV_LOG_VERBOSE,
  81.                "type:%s start_frame:%d nb_frames:%d alpha:%d\n",
  82.                s->type == FADE_IN ? "in" : "out", s->start_frame,
  83.                s->nb_frames,s->alpha);
  84.     }
  85.     if (s->start_time || s->duration) {
  86.         av_log(ctx, AV_LOG_VERBOSE,
  87.                "type:%s start_time:%f duration:%f alpha:%d\n",
  88.                s->type == FADE_IN ? "in" : "out", (s->start_time / (double)AV_TIME_BASE),
  89.                (s->duration / (double)AV_TIME_BASE),s->alpha);
  90.     }
  91.  
  92.     return 0;
  93. }
  94.  
  95. static int query_formats(AVFilterContext *ctx)
  96. {
  97.     static const enum AVPixelFormat pix_fmts[] = {
  98.         AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
  99.         AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUV410P,
  100.         AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P,
  101.         AV_PIX_FMT_YUV440P,  AV_PIX_FMT_YUVJ440P,
  102.         AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
  103.         AV_PIX_FMT_RGB24,    AV_PIX_FMT_BGR24,
  104.         AV_PIX_FMT_ARGB,     AV_PIX_FMT_ABGR,
  105.         AV_PIX_FMT_RGBA,     AV_PIX_FMT_BGRA,
  106.         AV_PIX_FMT_NONE
  107.     };
  108.  
  109.     ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
  110.     return 0;
  111. }
  112.  
  113. const static enum AVPixelFormat studio_level_pix_fmts[] = {
  114.     AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
  115.     AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUV410P,
  116.     AV_PIX_FMT_YUV440P,
  117.     AV_PIX_FMT_NONE
  118. };
  119.  
  120. static int config_props(AVFilterLink *inlink)
  121. {
  122.     FadeContext *s = inlink->dst->priv;
  123.     const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(inlink->format);
  124.  
  125.     s->hsub = pixdesc->log2_chroma_w;
  126.     s->vsub = pixdesc->log2_chroma_h;
  127.  
  128.     s->bpp = av_get_bits_per_pixel(pixdesc) >> 3;
  129.     s->alpha &= !!(pixdesc->flags & AV_PIX_FMT_FLAG_ALPHA);
  130.     s->is_packed_rgb = ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0;
  131.  
  132.     /* use CCIR601/709 black level for studio-level pixel non-alpha components */
  133.     s->black_level =
  134.             ff_fmt_is_in(inlink->format, studio_level_pix_fmts) && !s->alpha ? 16 : 0;
  135.     /* 32768 = 1 << 15, it is an integer representation
  136.      * of 0.5 and is for rounding. */
  137.     s->black_level_scaled = (s->black_level << 16) + 32768;
  138.     return 0;
  139. }
  140.  
  141. static int filter_slice_luma(AVFilterContext *ctx, void *arg, int jobnr,
  142.                              int nb_jobs)
  143. {
  144.     FadeContext *s = ctx->priv;
  145.     AVFrame *frame = arg;
  146.     int slice_start = (frame->height *  jobnr   ) / nb_jobs;
  147.     int slice_end   = (frame->height * (jobnr+1)) / nb_jobs;
  148.     int i, j;
  149.  
  150.     for (i = slice_start; i < slice_end; i++) {
  151.         uint8_t *p = frame->data[0] + i * frame->linesize[0];
  152.         for (j = 0; j < frame->width * s->bpp; j++) {
  153.             /* s->factor is using 16 lower-order bits for decimal
  154.              * places. 32768 = 1 << 15, it is an integer representation
  155.              * of 0.5 and is for rounding. */
  156.             *p = ((*p - s->black_level) * s->factor + s->black_level_scaled) >> 16;
  157.             p++;
  158.         }
  159.     }
  160.  
  161.     return 0;
  162. }
  163.  
  164. static int filter_slice_chroma(AVFilterContext *ctx, void *arg, int jobnr,
  165.                                int nb_jobs)
  166. {
  167.     FadeContext *s = ctx->priv;
  168.     AVFrame *frame = arg;
  169.     int i, j, plane;
  170.     const int width = FF_CEIL_RSHIFT(frame->width, s->hsub);
  171.     const int height= FF_CEIL_RSHIFT(frame->height, s->vsub);
  172.     int slice_start = (height *  jobnr   ) / nb_jobs;
  173.     int slice_end   = (height * (jobnr+1)) / nb_jobs;
  174.  
  175.     for (plane = 1; plane < 3; plane++) {
  176.         for (i = slice_start; i < slice_end; i++) {
  177.             uint8_t *p = frame->data[plane] + i * frame->linesize[plane];
  178.             for (j = 0; j < width; j++) {
  179.                 /* 8421367 = ((128 << 1) + 1) << 15. It is an integer
  180.                  * representation of 128.5. The .5 is for rounding
  181.                  * purposes. */
  182.                 *p = ((*p - 128) * s->factor + 8421367) >> 16;
  183.                 p++;
  184.             }
  185.         }
  186.     }
  187.  
  188.     return 0;
  189. }
  190.  
  191. static int filter_slice_alpha(AVFilterContext *ctx, void *arg, int jobnr,
  192.                               int nb_jobs)
  193. {
  194.     FadeContext *s = ctx->priv;
  195.     AVFrame *frame = arg;
  196.     int plane = s->is_packed_rgb ? 0 : A;
  197.     int slice_start = (frame->height *  jobnr   ) / nb_jobs;
  198.     int slice_end   = (frame->height * (jobnr+1)) / nb_jobs;
  199.     int i, j;
  200.  
  201.     for (i = slice_start; i < slice_end; i++) {
  202.         uint8_t *p = frame->data[plane] + i * frame->linesize[plane] + s->is_packed_rgb*s->rgba_map[A];
  203.         int step = s->is_packed_rgb ? 4 : 1;
  204.         for (j = 0; j < frame->width; j++) {
  205.             /* s->factor is using 16 lower-order bits for decimal
  206.              * places. 32768 = 1 << 15, it is an integer representation
  207.              * of 0.5 and is for rounding. */
  208.             *p = ((*p - s->black_level) * s->factor + s->black_level_scaled) >> 16;
  209.             p += step;
  210.         }
  211.     }
  212.  
  213.     return 0;
  214. }
  215.  
  216. static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
  217. {
  218.     AVFilterContext *ctx = inlink->dst;
  219.     FadeContext *s       = ctx->priv;
  220.     double frame_timestamp = frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base);
  221.  
  222.     // Calculate Fade assuming this is a Fade In
  223.     if (s->fade_state == VF_FADE_WAITING) {
  224.         s->factor=0;
  225.         if ((frame_timestamp >= (s->start_time/(double)AV_TIME_BASE))
  226.             && (s->frame_index >= s->start_frame)) {
  227.             // Time to start fading
  228.             s->fade_state = VF_FADE_FADING;
  229.  
  230.             // Save start time in case we are starting based on frames and fading based on time
  231.             if ((s->start_time == 0) && (s->start_frame != 0)) {
  232.                 s->start_time = frame_timestamp*(double)AV_TIME_BASE;
  233.             }
  234.  
  235.             // Save start frame in case we are starting based on time and fading based on frames
  236.             if ((s->start_time != 0) && (s->start_frame == 0)) {
  237.                 s->start_frame = s->frame_index;
  238.             }
  239.         }
  240.     }
  241.     if (s->fade_state == VF_FADE_FADING) {
  242.         if (s->duration == 0) {
  243.             // Fading based on frame count
  244.             s->factor = (s->frame_index - s->start_frame) * s->fade_per_frame;
  245.             if (s->frame_index > (s->start_frame + s->nb_frames)) {
  246.                 s->fade_state = VF_FADE_DONE;
  247.             }
  248.  
  249.         } else {
  250.             // Fading based on duration
  251.             s->factor = (frame_timestamp - (s->start_time/(double)AV_TIME_BASE))
  252.                             * (float) UINT16_MAX / (s->duration/(double)AV_TIME_BASE);
  253.             if (frame_timestamp > ((s->start_time/(double)AV_TIME_BASE)
  254.                                     + (s->duration/(double)AV_TIME_BASE))) {
  255.                 s->fade_state = VF_FADE_DONE;
  256.             }
  257.         }
  258.     }
  259.     if (s->fade_state == VF_FADE_DONE) {
  260.         s->factor=UINT16_MAX;
  261.     }
  262.  
  263.     s->factor = av_clip_uint16(s->factor);
  264.  
  265.     // Invert fade_factor if Fading Out
  266.     if (s->type == 1) {
  267.         s->factor=UINT16_MAX-s->factor;
  268.     }
  269.  
  270.     if (s->factor < UINT16_MAX) {
  271.         if (s->alpha) {
  272.             ctx->internal->execute(ctx, filter_slice_alpha, frame, NULL,
  273.                                 FFMIN(frame->height, ctx->graph->nb_threads));
  274.         } else {
  275.             /* luma or rgb plane */
  276.             ctx->internal->execute(ctx, filter_slice_luma, frame, NULL,
  277.                                 FFMIN(frame->height, ctx->graph->nb_threads));
  278.  
  279.             if (frame->data[1] && frame->data[2]) {
  280.                 /* chroma planes */
  281.                 ctx->internal->execute(ctx, filter_slice_chroma, frame, NULL,
  282.                                     FFMIN(frame->height, ctx->graph->nb_threads));
  283.             }
  284.         }
  285.     }
  286.  
  287.     s->frame_index++;
  288.  
  289.     return ff_filter_frame(inlink->dst->outputs[0], frame);
  290. }
  291.  
  292.  
  293. #define OFFSET(x) offsetof(FadeContext, x)
  294. #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  295.  
  296. static const AVOption fade_options[] = {
  297.     { "type", "'in' or 'out' for fade-in/fade-out", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = FADE_IN }, FADE_IN, FADE_OUT, FLAGS, "type" },
  298.     { "t",    "'in' or 'out' for fade-in/fade-out", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = FADE_IN }, FADE_IN, FADE_OUT, FLAGS, "type" },
  299.         { "in",  "fade-in",  0, AV_OPT_TYPE_CONST, { .i64 = FADE_IN },  .unit = "type" },
  300.         { "out", "fade-out", 0, AV_OPT_TYPE_CONST, { .i64 = FADE_OUT }, .unit = "type" },
  301.     { "start_frame", "Number of the first frame to which to apply the effect.",
  302.                                                     OFFSET(start_frame), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
  303.     { "s",           "Number of the first frame to which to apply the effect.",
  304.                                                     OFFSET(start_frame), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
  305.     { "nb_frames",   "Number of frames to which the effect should be applied.",
  306.                                                     OFFSET(nb_frames),   AV_OPT_TYPE_INT, { .i64 = 25 }, 0, INT_MAX, FLAGS },
  307.     { "n",           "Number of frames to which the effect should be applied.",
  308.                                                     OFFSET(nb_frames),   AV_OPT_TYPE_INT, { .i64 = 25 }, 0, INT_MAX, FLAGS },
  309.     { "alpha",       "fade alpha if it is available on the input", OFFSET(alpha),       AV_OPT_TYPE_INT, {.i64 = 0    }, 0,       1, FLAGS },
  310.     { "start_time",  "Number of seconds of the beginning of the effect.",
  311.                                                     OFFSET(start_time),  AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS },
  312.     { "st",          "Number of seconds of the beginning of the effect.",
  313.                                                     OFFSET(start_time),  AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS },
  314.     { "duration",    "Duration of the effect in seconds.",
  315.                                                     OFFSET(duration),    AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS },
  316.     { "d",           "Duration of the effect in seconds.",
  317.                                                     OFFSET(duration),    AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS },
  318.     { NULL }
  319. };
  320.  
  321. AVFILTER_DEFINE_CLASS(fade);
  322.  
  323. static const AVFilterPad avfilter_vf_fade_inputs[] = {
  324.     {
  325.         .name           = "default",
  326.         .type           = AVMEDIA_TYPE_VIDEO,
  327.         .config_props   = config_props,
  328.         .filter_frame   = filter_frame,
  329.         .needs_writable = 1,
  330.     },
  331.     { NULL }
  332. };
  333.  
  334. static const AVFilterPad avfilter_vf_fade_outputs[] = {
  335.     {
  336.         .name = "default",
  337.         .type = AVMEDIA_TYPE_VIDEO,
  338.     },
  339.     { NULL }
  340. };
  341.  
  342. AVFilter avfilter_vf_fade = {
  343.     .name          = "fade",
  344.     .description   = NULL_IF_CONFIG_SMALL("Fade in/out input video."),
  345.     .init          = init,
  346.     .priv_size     = sizeof(FadeContext),
  347.     .priv_class    = &fade_class,
  348.     .query_formats = query_formats,
  349.     .inputs        = avfilter_vf_fade_inputs,
  350.     .outputs       = avfilter_vf_fade_outputs,
  351.     .flags         = AVFILTER_FLAG_SLICE_THREADS,
  352. };
  353.