~siretart/ubuntu/utopic/libav/libav10

« back to all changes in this revision

Viewing changes to libavfilter/vf_fade.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2014-05-11 12:28:45 UTC
  • mfrom: (1.1.22) (2.1.38 experimental)
  • Revision ID: package-import@ubuntu.com-20140511122845-gxvpts83i958y0i5
Tags: 6:10.1-1
* New upstream release 10:
   - pcm-dvd: Fix 20bit decoding (bug/592)
   - avi: Improve non-interleaved detection (bug/666)
   - arm: hpeldsp: fix put_pixels8_y2_{,no_rnd_}armv6
   - arm: hpeldsp: prevent overreads in armv6 asm (bug/646)
   - avfilter: Add missing emms_c when needed
   - rtmpproto: Check the buffer sizes when copying app/playpath strings
   - swscale: Fix an undefined behaviour
   - vp9: Read the frame size as unsigned
   - dcadec: Use correct channel count in stereo downmix check
   - dcadec: Do not decode the XCh extension when downmixing to stereo
   - matroska: add the Opus mapping
   - matroskadec: read the CodecDelay element
   - rtmpproto: Make sure to pass on the error code if read_connect failed
   - lavr: allocate the resampling buffer with a positive size
   - mp3enc: Properly write bitrate value in XING header (Closes: #736088)
   - golomb: Fix the implementation of get_se_golomb_long
* Drop debian/libav-tools.maintscript. ffserver is no longer found in
  stable, and this seems to cause other problems today (Closes: #742676)

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 */
27
27
 
28
28
#include "libavutil/common.h"
 
29
#include "libavutil/opt.h"
29
30
#include "libavutil/pixdesc.h"
30
31
#include "avfilter.h"
31
32
#include "formats.h"
32
33
#include "internal.h"
33
34
#include "video.h"
34
35
 
 
36
#define FADE_IN  0
 
37
#define FADE_OUT 1
 
38
 
35
39
typedef struct {
 
40
    const AVClass *class;
 
41
    int type;
36
42
    int factor, fade_per_frame;
37
 
    unsigned int frame_index, start_frame, stop_frame;
 
43
    int start_frame, nb_frames;
 
44
    unsigned int frame_index, stop_frame;
38
45
    int hsub, vsub, bpp;
39
46
} FadeContext;
40
47
 
41
 
static av_cold int init(AVFilterContext *ctx, const char *args)
 
48
static av_cold int init(AVFilterContext *ctx)
42
49
{
43
 
    FadeContext *fade = ctx->priv;
44
 
    unsigned int nb_frames;
45
 
    char in_out[4];
46
 
 
47
 
    if (!args ||
48
 
        sscanf(args, " %3[^:]:%u:%u", in_out, &fade->start_frame, &nb_frames) != 3) {
49
 
        av_log(ctx, AV_LOG_ERROR,
50
 
               "Expected 3 arguments '(in|out):#:#':'%s'\n", args);
51
 
        return AVERROR(EINVAL);
52
 
    }
53
 
 
54
 
    nb_frames = nb_frames ? nb_frames : 1;
55
 
    fade->fade_per_frame = (1 << 16) / nb_frames;
56
 
    if (!strcmp(in_out, "in"))
57
 
        fade->factor = 0;
58
 
    else if (!strcmp(in_out, "out")) {
59
 
        fade->fade_per_frame = -fade->fade_per_frame;
60
 
        fade->factor = (1 << 16);
61
 
    } else {
62
 
        av_log(ctx, AV_LOG_ERROR,
63
 
               "first argument must be 'in' or 'out':'%s'\n", in_out);
64
 
        return AVERROR(EINVAL);
65
 
    }
66
 
    fade->stop_frame = fade->start_frame + nb_frames;
 
50
    FadeContext *s = ctx->priv;
 
51
 
 
52
    s->fade_per_frame = (1 << 16) / s->nb_frames;
 
53
    if (s->type == FADE_IN) {
 
54
        s->factor = 0;
 
55
    } else if (s->type == FADE_OUT) {
 
56
        s->fade_per_frame = -s->fade_per_frame;
 
57
        s->factor = (1 << 16);
 
58
    }
 
59
    s->stop_frame = s->start_frame + s->nb_frames;
67
60
 
68
61
    av_log(ctx, AV_LOG_VERBOSE,
69
62
           "type:%s start_frame:%d nb_frames:%d\n",
70
 
           in_out, fade->start_frame, nb_frames);
 
63
           s->type == FADE_IN ? "in" : "out", s->start_frame,
 
64
           s->nb_frames);
71
65
    return 0;
72
66
}
73
67
 
88
82
 
89
83
static int config_props(AVFilterLink *inlink)
90
84
{
91
 
    FadeContext *fade = inlink->dst->priv;
 
85
    FadeContext *s = inlink->dst->priv;
92
86
    const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(inlink->format);
93
87
 
94
 
    fade->hsub = pixdesc->log2_chroma_w;
95
 
    fade->vsub = pixdesc->log2_chroma_h;
96
 
 
97
 
    fade->bpp = av_get_bits_per_pixel(pixdesc) >> 3;
98
 
    return 0;
99
 
}
100
 
 
101
 
static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
102
 
{
103
 
    FadeContext *fade = inlink->dst->priv;
104
 
    uint8_t *p;
 
88
    s->hsub = pixdesc->log2_chroma_w;
 
89
    s->vsub = pixdesc->log2_chroma_h;
 
90
 
 
91
    s->bpp = av_get_bits_per_pixel(pixdesc) >> 3;
 
92
    return 0;
 
93
}
 
94
 
 
95
static int filter_slice_luma(AVFilterContext *ctx, void *arg, int jobnr,
 
96
                             int nb_jobs)
 
97
{
 
98
    FadeContext *s = ctx->priv;
 
99
    AVFrame *frame = arg;
 
100
    int slice_h     = frame->height / nb_jobs;
 
101
    int slice_start = jobnr * slice_h;
 
102
    int slice_end   = (jobnr == nb_jobs - 1) ? frame->height : (jobnr + 1) * slice_h;
 
103
    int i, j;
 
104
 
 
105
    for (i = slice_start; i < slice_end; i++) {
 
106
        uint8_t *p = frame->data[0] + i * frame->linesize[0];
 
107
        for (j = 0; j < frame->width * s->bpp; j++) {
 
108
            /* s->factor is using 16 lower-order bits for decimal
 
109
             * places. 32768 = 1 << 15, it is an integer representation
 
110
             * of 0.5 and is for rounding. */
 
111
            *p = (*p * s->factor + 32768) >> 16;
 
112
            p++;
 
113
        }
 
114
    }
 
115
 
 
116
    return 0;
 
117
}
 
118
 
 
119
static int filter_slice_chroma(AVFilterContext *ctx, void *arg, int jobnr,
 
120
                               int nb_jobs)
 
121
{
 
122
    FadeContext *s = ctx->priv;
 
123
    AVFrame *frame = arg;
 
124
    int slice_h     = FFALIGN(frame->height / nb_jobs, 1 << s->vsub);
 
125
    int slice_start = jobnr * slice_h;
 
126
    int slice_end   = (jobnr == nb_jobs - 1) ? frame->height : (jobnr + 1) * slice_h;
105
127
    int i, j, plane;
106
128
 
107
 
    if (fade->factor < UINT16_MAX) {
 
129
    for (plane = 1; plane < 3; plane++) {
 
130
        for (i = slice_start; i < slice_end; i++) {
 
131
            uint8_t *p = frame->data[plane] + (i >> s->vsub) * frame->linesize[plane];
 
132
            for (j = 0; j < frame->width >> s->hsub; j++) {
 
133
                /* 8421367 = ((128 << 1) + 1) << 15. It is an integer
 
134
                 * representation of 128.5. The .5 is for rounding
 
135
                 * purposes. */
 
136
                *p = ((*p - 128) * s->factor + 8421367) >> 16;
 
137
                p++;
 
138
            }
 
139
        }
 
140
    }
 
141
 
 
142
    return 0;
 
143
}
 
144
 
 
145
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
 
146
{
 
147
    AVFilterContext *ctx = inlink->dst;
 
148
    FadeContext *s       = ctx->priv;
 
149
 
 
150
    if (s->factor < UINT16_MAX) {
108
151
        /* luma or rgb plane */
109
 
        for (i = 0; i < frame->video->h; i++) {
110
 
            p = frame->data[0] + i * frame->linesize[0];
111
 
            for (j = 0; j < inlink->w * fade->bpp; j++) {
112
 
                /* fade->factor is using 16 lower-order bits for decimal
113
 
                 * places. 32768 = 1 << 15, it is an integer representation
114
 
                 * of 0.5 and is for rounding. */
115
 
                *p = (*p * fade->factor + 32768) >> 16;
116
 
                p++;
117
 
            }
118
 
        }
 
152
        ctx->internal->execute(ctx, filter_slice_luma, frame, NULL,
 
153
                               FFMIN(frame->height, ctx->graph->nb_threads));
119
154
 
120
155
        if (frame->data[1] && frame->data[2]) {
121
156
            /* chroma planes */
122
 
            for (plane = 1; plane < 3; plane++) {
123
 
                for (i = 0; i < frame->video->h; i++) {
124
 
                    p = frame->data[plane] + (i >> fade->vsub) * frame->linesize[plane];
125
 
                    for (j = 0; j < inlink->w >> fade->hsub; j++) {
126
 
                        /* 8421367 = ((128 << 1) + 1) << 15. It is an integer
127
 
                         * representation of 128.5. The .5 is for rounding
128
 
                         * purposes. */
129
 
                        *p = ((*p - 128) * fade->factor + 8421367) >> 16;
130
 
                        p++;
131
 
                    }
132
 
                }
133
 
            }
 
157
            ctx->internal->execute(ctx, filter_slice_chroma, frame, NULL,
 
158
                                   FFMIN(frame->height, ctx->graph->nb_threads));
134
159
        }
135
160
    }
136
161
 
137
 
    if (fade->frame_index >= fade->start_frame &&
138
 
        fade->frame_index <= fade->stop_frame)
139
 
        fade->factor += fade->fade_per_frame;
140
 
    fade->factor = av_clip_uint16(fade->factor);
141
 
    fade->frame_index++;
 
162
    if (s->frame_index >= s->start_frame &&
 
163
        s->frame_index <= s->stop_frame)
 
164
        s->factor += s->fade_per_frame;
 
165
    s->factor = av_clip_uint16(s->factor);
 
166
    s->frame_index++;
142
167
 
143
168
    return ff_filter_frame(inlink->dst->outputs[0], frame);
144
169
}
145
170
 
 
171
#define OFFSET(x) offsetof(FadeContext, x)
 
172
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
 
173
static const AVOption options[] = {
 
174
    { "type", "'in' or 'out' for fade-in/fade-out", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = FADE_IN }, FADE_IN, FADE_OUT, FLAGS, "type" },
 
175
        { "in",  "fade-in",  0, AV_OPT_TYPE_CONST, { .i64 = FADE_IN },  .unit = "type" },
 
176
        { "out", "fade-out", 0, AV_OPT_TYPE_CONST, { .i64 = FADE_OUT }, .unit = "type" },
 
177
    { "start_frame", "Number of the first frame to which to apply the effect.",
 
178
                                                    OFFSET(start_frame), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
 
179
    { "nb_frames",   "Number of frames to which the effect should be applied.",
 
180
                                                    OFFSET(nb_frames),   AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, FLAGS },
 
181
    { NULL },
 
182
};
 
183
 
 
184
static const AVClass fade_class = {
 
185
    .class_name = "fade",
 
186
    .item_name  = av_default_item_name,
 
187
    .option     = options,
 
188
    .version    = LIBAVUTIL_VERSION_INT,
 
189
};
 
190
 
146
191
static const AVFilterPad avfilter_vf_fade_inputs[] = {
147
192
    {
148
193
        .name             = "default",
150
195
        .config_props     = config_props,
151
196
        .get_video_buffer = ff_null_get_video_buffer,
152
197
        .filter_frame     = filter_frame,
153
 
        .min_perms        = AV_PERM_READ | AV_PERM_WRITE,
154
 
        .rej_perms        = AV_PERM_PRESERVE,
 
198
        .needs_writable   = 1,
155
199
    },
156
200
    { NULL }
157
201
};
164
208
    { NULL }
165
209
};
166
210
 
167
 
AVFilter avfilter_vf_fade = {
 
211
AVFilter ff_vf_fade = {
168
212
    .name          = "fade",
169
213
    .description   = NULL_IF_CONFIG_SMALL("Fade in/out input video"),
170
214
    .init          = init,
171
215
    .priv_size     = sizeof(FadeContext),
 
216
    .priv_class    = &fade_class,
172
217
    .query_formats = query_formats,
173
218
 
174
219
    .inputs    = avfilter_vf_fade_inputs,
175
220
    .outputs   = avfilter_vf_fade_outputs,
 
221
    .flags     = AVFILTER_FLAG_SLICE_THREADS,
176
222
};