~ubuntu-branches/debian/experimental/libav/experimental

« back to all changes in this revision

Viewing changes to libavfilter/vf_shuffleplanes.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2014-08-10 09:45:02 UTC
  • mfrom: (1.1.28) (2.1.45 sid)
  • Revision ID: package-import@ubuntu.com-20140810094502-p8pds4kq0zpig5oq
Tags: 6:11~alpha1-1
* New upstream Release v11
  - Fixes Unchecked conversion from double to enum (Closes: #749164)
* Add some post v11_alpha1 patches from upstream
* All SONAMEs bumped because of internal changes, but external API is
  promised to have not changed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of Libav.
 
3
 *
 
4
 * Libav is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2.1 of the License, or (at your option) any later version.
 
8
 *
 
9
 * Libav is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with Libav; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
17
 */
 
18
 
 
19
#include "libavutil/avstring.h"
 
20
#include "libavutil/common.h"
 
21
#include "libavutil/internal.h"
 
22
#include "libavutil/opt.h"
 
23
#include "libavutil/pixdesc.h"
 
24
#include "libavutil/pixfmt.h"
 
25
 
 
26
#include "avfilter.h"
 
27
#include "internal.h"
 
28
#include "video.h"
 
29
 
 
30
typedef struct ShufflePlanesContext {
 
31
    const AVClass *class;
 
32
 
 
33
    /* number of planes in the selected pixel format */
 
34
    int planes;
 
35
 
 
36
    /* mapping indices */
 
37
    int map[4];
 
38
 
 
39
    /* set to 1 if some plane is used more than once, so we need to make a copy */
 
40
    int copy;
 
41
} ShufflePlanesContext;
 
42
 
 
43
static av_cold int shuffleplanes_config_input(AVFilterLink *inlink)
 
44
{
 
45
    AVFilterContext    *ctx = inlink->dst;
 
46
    ShufflePlanesContext *s = ctx->priv;
 
47
    const AVPixFmtDescriptor *desc;
 
48
    int used[4] = { 0 };
 
49
    int i;
 
50
 
 
51
    s->copy   = 0;
 
52
    s->planes = av_pix_fmt_count_planes(inlink->format);
 
53
    desc      = av_pix_fmt_desc_get(inlink->format);
 
54
 
 
55
    for (i = 0; i < s->planes; i++) {
 
56
        if (s->map[i] >= s->planes) {
 
57
            av_log(ctx, AV_LOG_ERROR,
 
58
                   "Non-existing input plane #%d mapped to output plane #%d.\n",
 
59
                   s->map[i], i);
 
60
            return AVERROR(EINVAL);
 
61
        }
 
62
 
 
63
        if ((desc->log2_chroma_h || desc->log2_chroma_w) &&
 
64
            (i == 1 || i == 2) != (s->map[i] == 1 || s->map[i] == 2)) {
 
65
            av_log(ctx, AV_LOG_ERROR,
 
66
                   "Cannot map between a subsampled chroma plane and a luma "
 
67
                   "or alpha plane.\n");
 
68
            return AVERROR(EINVAL);
 
69
        }
 
70
 
 
71
        if ((desc->flags & AV_PIX_FMT_FLAG_PAL ||
 
72
             desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) &&
 
73
            (i == 1) != (s->map[i] == 1)) {
 
74
            av_log(ctx, AV_LOG_ERROR,
 
75
                   "Cannot map between a palette plane and a data plane.\n");
 
76
            return AVERROR(EINVAL);
 
77
        }
 
78
        if (used[s->map[i]])
 
79
            s->copy = 1;
 
80
        used[s->map[i]]++;
 
81
    }
 
82
 
 
83
    return 0;
 
84
}
 
85
 
 
86
static int shuffleplanes_filter_frame(AVFilterLink *inlink, AVFrame *frame)
 
87
{
 
88
    AVFilterContext          *ctx = inlink->dst;
 
89
    ShufflePlanesContext       *s = ctx->priv;
 
90
    uint8_t *shuffled_data[4]     = { NULL };
 
91
    int      shuffled_linesize[4] = { 0 };
 
92
    int i, ret;
 
93
 
 
94
    for (i = 0; i < s->planes; i++) {
 
95
        shuffled_data[i]     = frame->data[s->map[i]];
 
96
        shuffled_linesize[i] = frame->linesize[s->map[i]];
 
97
    }
 
98
    memcpy(frame->data,     shuffled_data,     sizeof(shuffled_data));
 
99
    memcpy(frame->linesize, shuffled_linesize, sizeof(shuffled_linesize));
 
100
 
 
101
    if (s->copy) {
 
102
        AVFrame *copy = ff_get_video_buffer(ctx->outputs[0], frame->width, frame->height);
 
103
 
 
104
        if (!copy) {
 
105
            ret = AVERROR(ENOMEM);
 
106
            goto fail;
 
107
        }
 
108
 
 
109
        av_frame_copy(copy, frame);
 
110
 
 
111
        ret = av_frame_copy_props(copy, frame);
 
112
        if (ret < 0) {
 
113
            av_frame_free(&copy);
 
114
            goto fail;
 
115
        }
 
116
 
 
117
        av_frame_free(&frame);
 
118
        frame = copy;
 
119
    }
 
120
 
 
121
    return ff_filter_frame(ctx->outputs[0], frame);
 
122
fail:
 
123
    av_frame_free(&frame);
 
124
    return ret;
 
125
}
 
126
 
 
127
#define OFFSET(x) offsetof(ShufflePlanesContext, x)
 
128
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
 
129
static const AVOption shuffleplanes_options[] = {
 
130
    { "map0", "Index of the input plane to be used as the first output plane ",  OFFSET(map[0]), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4, FLAGS },
 
131
    { "map1", "Index of the input plane to be used as the second output plane ", OFFSET(map[1]), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 4, FLAGS },
 
132
    { "map2", "Index of the input plane to be used as the third output plane ",  OFFSET(map[2]), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 4, FLAGS },
 
133
    { "map3", "Index of the input plane to be used as the fourth output plane ", OFFSET(map[3]), AV_OPT_TYPE_INT, { .i64 = 3 }, 0, 4, FLAGS },
 
134
    { NULL },
 
135
};
 
136
 
 
137
static const AVClass shuffleplanes_class = {
 
138
    .class_name = "shuffleplanes",
 
139
    .item_name  = av_default_item_name,
 
140
    .option     = shuffleplanes_options,
 
141
    .version    = LIBAVUTIL_VERSION_INT,
 
142
};
 
143
 
 
144
static const AVFilterPad shuffleplanes_inputs[] = {
 
145
    {
 
146
        .name             = "default",
 
147
        .type             = AVMEDIA_TYPE_VIDEO,
 
148
        .config_props     = shuffleplanes_config_input,
 
149
        .filter_frame     = shuffleplanes_filter_frame,
 
150
        .get_video_buffer = ff_null_get_video_buffer,
 
151
    },
 
152
    { NULL },
 
153
};
 
154
 
 
155
static const AVFilterPad shuffleplanes_outputs[] = {
 
156
    {
 
157
        .name = "default",
 
158
        .type = AVMEDIA_TYPE_VIDEO,
 
159
    },
 
160
    { NULL },
 
161
};
 
162
 
 
163
AVFilter ff_vf_shuffleplanes = {
 
164
    .name         = "shuffleplanes",
 
165
    .description  = NULL_IF_CONFIG_SMALL("Shuffle video planes"),
 
166
 
 
167
    .priv_size    = sizeof(ShufflePlanesContext),
 
168
    .priv_class   = &shuffleplanes_class,
 
169
 
 
170
    .inputs       = shuffleplanes_inputs,
 
171
    .outputs      = shuffleplanes_outputs,
 
172
};