~ubuntu-branches/ubuntu/saucy/gst-libav1.0/saucy-proposed

« back to all changes in this revision

Viewing changes to gst-libs/ext/libav/libavfilter/vf_transpose.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2013-07-30 09:00:15 UTC
  • mfrom: (1.1.16) (7.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20130730090015-sc1ou2yssu7q5w4e
Tags: 1.1.3-1
* New upstream development snapshot:
  + debian/control:
    - Build depend on GStreamer and gst-plugins-base >= 1.1.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 * Based on MPlayer libmpcodecs/vf_rotate.c.
26
26
 */
27
27
 
 
28
#include <stdio.h>
 
29
 
28
30
#include "libavutil/intreadwrite.h"
29
31
#include "libavutil/pixdesc.h"
30
32
#include "libavutil/imgutils.h"
 
33
#include "libavutil/internal.h"
31
34
#include "avfilter.h"
 
35
#include "formats.h"
 
36
#include "internal.h"
 
37
#include "video.h"
32
38
 
33
39
typedef struct {
34
40
    int hsub, vsub;
41
47
    int dir;
42
48
} TransContext;
43
49
 
44
 
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
 
50
static av_cold int init(AVFilterContext *ctx, const char *args)
45
51
{
46
52
    TransContext *trans = ctx->priv;
47
53
    trans->dir = 0;
59
65
 
60
66
static int query_formats(AVFilterContext *ctx)
61
67
{
62
 
    enum PixelFormat pix_fmts[] = {
63
 
        PIX_FMT_ARGB,         PIX_FMT_RGBA,
64
 
        PIX_FMT_ABGR,         PIX_FMT_BGRA,
65
 
        PIX_FMT_RGB24,        PIX_FMT_BGR24,
66
 
        PIX_FMT_RGB565BE,     PIX_FMT_RGB565LE,
67
 
        PIX_FMT_RGB555BE,     PIX_FMT_RGB555LE,
68
 
        PIX_FMT_BGR565BE,     PIX_FMT_BGR565LE,
69
 
        PIX_FMT_BGR555BE,     PIX_FMT_BGR555LE,
70
 
        PIX_FMT_GRAY16BE,     PIX_FMT_GRAY16LE,
71
 
        PIX_FMT_YUV420P16LE,  PIX_FMT_YUV420P16BE,
72
 
        PIX_FMT_YUV422P16LE,  PIX_FMT_YUV422P16BE,
73
 
        PIX_FMT_YUV444P16LE,  PIX_FMT_YUV444P16BE,
74
 
        PIX_FMT_NV12,         PIX_FMT_NV21,
75
 
        PIX_FMT_RGB8,         PIX_FMT_BGR8,
76
 
        PIX_FMT_RGB4_BYTE,    PIX_FMT_BGR4_BYTE,
77
 
        PIX_FMT_YUV444P,      PIX_FMT_YUV422P,
78
 
        PIX_FMT_YUV420P,      PIX_FMT_YUVJ420P,
79
 
        PIX_FMT_YUV411P,      PIX_FMT_YUV410P,
80
 
        PIX_FMT_YUVJ444P,     PIX_FMT_YUVJ422P,
81
 
        PIX_FMT_YUV440P,      PIX_FMT_YUVJ440P,
82
 
        PIX_FMT_YUVA420P,     PIX_FMT_GRAY8,
83
 
        PIX_FMT_NONE
 
68
    enum AVPixelFormat pix_fmts[] = {
 
69
        AV_PIX_FMT_ARGB,         AV_PIX_FMT_RGBA,
 
70
        AV_PIX_FMT_ABGR,         AV_PIX_FMT_BGRA,
 
71
        AV_PIX_FMT_RGB24,        AV_PIX_FMT_BGR24,
 
72
        AV_PIX_FMT_RGB565BE,     AV_PIX_FMT_RGB565LE,
 
73
        AV_PIX_FMT_RGB555BE,     AV_PIX_FMT_RGB555LE,
 
74
        AV_PIX_FMT_BGR565BE,     AV_PIX_FMT_BGR565LE,
 
75
        AV_PIX_FMT_BGR555BE,     AV_PIX_FMT_BGR555LE,
 
76
        AV_PIX_FMT_GRAY16BE,     AV_PIX_FMT_GRAY16LE,
 
77
        AV_PIX_FMT_YUV420P16LE,  AV_PIX_FMT_YUV420P16BE,
 
78
        AV_PIX_FMT_YUV422P16LE,  AV_PIX_FMT_YUV422P16BE,
 
79
        AV_PIX_FMT_YUV444P16LE,  AV_PIX_FMT_YUV444P16BE,
 
80
        AV_PIX_FMT_NV12,         AV_PIX_FMT_NV21,
 
81
        AV_PIX_FMT_RGB8,         AV_PIX_FMT_BGR8,
 
82
        AV_PIX_FMT_RGB4_BYTE,    AV_PIX_FMT_BGR4_BYTE,
 
83
        AV_PIX_FMT_YUV444P,      AV_PIX_FMT_YUV422P,
 
84
        AV_PIX_FMT_YUV420P,      AV_PIX_FMT_YUVJ420P,
 
85
        AV_PIX_FMT_YUV411P,      AV_PIX_FMT_YUV410P,
 
86
        AV_PIX_FMT_YUVJ444P,     AV_PIX_FMT_YUVJ422P,
 
87
        AV_PIX_FMT_YUV440P,      AV_PIX_FMT_YUVJ440P,
 
88
        AV_PIX_FMT_YUVA420P,     AV_PIX_FMT_GRAY8,
 
89
        AV_PIX_FMT_NONE
84
90
    };
85
91
 
86
 
    avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
 
92
    ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
87
93
    return 0;
88
94
}
89
95
 
92
98
    AVFilterContext *ctx = outlink->src;
93
99
    TransContext *trans = ctx->priv;
94
100
    AVFilterLink *inlink = ctx->inputs[0];
95
 
    const AVPixFmtDescriptor *pixdesc = &av_pix_fmt_descriptors[outlink->format];
96
 
 
97
 
    trans->hsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_w;
98
 
    trans->vsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_h;
99
 
 
100
 
    av_image_fill_max_pixsteps(trans->pixsteps, NULL, pixdesc);
 
101
    const AVPixFmtDescriptor *desc_out = av_pix_fmt_desc_get(outlink->format);
 
102
    const AVPixFmtDescriptor *desc_in  = av_pix_fmt_desc_get(inlink->format);
 
103
 
 
104
    trans->hsub = desc_in->log2_chroma_w;
 
105
    trans->vsub = desc_in->log2_chroma_h;
 
106
 
 
107
    av_image_fill_max_pixsteps(trans->pixsteps, NULL, desc_out);
101
108
 
102
109
    outlink->w = inlink->h;
103
110
    outlink->h = inlink->w;
107
114
    } else
108
115
        outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
109
116
 
110
 
    av_log(ctx, AV_LOG_INFO, "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n",
 
117
    av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n",
111
118
           inlink->w, inlink->h, trans->dir, outlink->w, outlink->h,
112
119
           trans->dir == 1 || trans->dir == 3 ? "clockwise" : "counterclockwise",
113
120
           trans->dir == 0 || trans->dir == 3);
114
121
    return 0;
115
122
}
116
123
 
117
 
static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
 
124
static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
118
125
{
119
126
    AVFilterLink *outlink = inlink->dst->outputs[0];
120
 
 
121
 
    outlink->out_buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE,
122
 
                                                 outlink->w, outlink->h);
123
 
    outlink->out_buf->pts = picref->pts;
124
 
 
125
 
    if (picref->video->pixel_aspect.num == 0) {
126
 
        outlink->out_buf->video->pixel_aspect = picref->video->pixel_aspect;
127
 
    } else {
128
 
        outlink->out_buf->video->pixel_aspect.num = picref->video->pixel_aspect.den;
129
 
        outlink->out_buf->video->pixel_aspect.den = picref->video->pixel_aspect.num;
130
 
    }
131
 
 
132
 
    avfilter_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
133
 
}
134
 
 
135
 
static void end_frame(AVFilterLink *inlink)
136
 
{
137
127
    TransContext *trans = inlink->dst->priv;
138
 
    AVFilterBufferRef *inpic  = inlink->cur_buf;
139
 
    AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf;
140
 
    AVFilterLink *outlink = inlink->dst->outputs[0];
 
128
    AVFilterBufferRef *out;
141
129
    int plane;
142
130
 
143
 
    for (plane = 0; outpic->data[plane]; plane++) {
 
131
    out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
 
132
    if (!out) {
 
133
        avfilter_unref_bufferp(&in);
 
134
        return AVERROR(ENOMEM);
 
135
    }
 
136
 
 
137
    out->pts = in->pts;
 
138
 
 
139
    if (in->video->pixel_aspect.num == 0) {
 
140
        out->video->pixel_aspect = in->video->pixel_aspect;
 
141
    } else {
 
142
        out->video->pixel_aspect.num = in->video->pixel_aspect.den;
 
143
        out->video->pixel_aspect.den = in->video->pixel_aspect.num;
 
144
    }
 
145
 
 
146
    for (plane = 0; out->data[plane]; plane++) {
144
147
        int hsub = plane == 1 || plane == 2 ? trans->hsub : 0;
145
148
        int vsub = plane == 1 || plane == 2 ? trans->vsub : 0;
146
149
        int pixstep = trans->pixsteps[plane];
147
 
        int inh  = inpic->video->h>>vsub;
148
 
        int outw = outpic->video->w>>hsub;
149
 
        int outh = outpic->video->h>>vsub;
150
 
        uint8_t *out, *in;
151
 
        int outlinesize, inlinesize;
 
150
        int inh  = in->video->h>>vsub;
 
151
        int outw = out->video->w>>hsub;
 
152
        int outh = out->video->h>>vsub;
 
153
        uint8_t *dst, *src;
 
154
        int dstlinesize, srclinesize;
152
155
        int x, y;
153
156
 
154
 
        out = outpic->data[plane]; outlinesize = outpic->linesize[plane];
155
 
        in  = inpic ->data[plane]; inlinesize  = inpic ->linesize[plane];
 
157
        dst = out->data[plane];
 
158
        dstlinesize = out->linesize[plane];
 
159
        src = in->data[plane];
 
160
        srclinesize = in->linesize[plane];
156
161
 
157
162
        if (trans->dir&1) {
158
 
            in +=  inpic->linesize[plane] * (inh-1);
159
 
            inlinesize *= -1;
 
163
            src +=  in->linesize[plane] * (inh-1);
 
164
            srclinesize *= -1;
160
165
        }
161
166
 
162
167
        if (trans->dir&2) {
163
 
            out += outpic->linesize[plane] * (outh-1);
164
 
            outlinesize *= -1;
 
168
            dst += out->linesize[plane] * (outh-1);
 
169
            dstlinesize *= -1;
165
170
        }
166
171
 
167
172
        for (y = 0; y < outh; y++) {
168
173
            switch (pixstep) {
169
174
            case 1:
170
175
                for (x = 0; x < outw; x++)
171
 
                    out[x] = in[x*inlinesize + y];
 
176
                    dst[x] = src[x*srclinesize + y];
172
177
                break;
173
178
            case 2:
174
179
                for (x = 0; x < outw; x++)
175
 
                    *((uint16_t *)(out + 2*x)) = *((uint16_t *)(in + x*inlinesize + y*2));
 
180
                    *((uint16_t *)(dst + 2*x)) = *((uint16_t *)(src + x*srclinesize + y*2));
176
181
                break;
177
182
            case 3:
178
183
                for (x = 0; x < outw; x++) {
179
 
                    int32_t v = AV_RB24(in + x*inlinesize + y*3);
180
 
                    AV_WB24(out + 3*x, v);
 
184
                    int32_t v = AV_RB24(src + x*srclinesize + y*3);
 
185
                    AV_WB24(dst + 3*x, v);
181
186
                }
182
187
                break;
183
188
            case 4:
184
189
                for (x = 0; x < outw; x++)
185
 
                    *((uint32_t *)(out + 4*x)) = *((uint32_t *)(in + x*inlinesize + y*4));
 
190
                    *((uint32_t *)(dst + 4*x)) = *((uint32_t *)(src + x*srclinesize + y*4));
186
191
                break;
187
192
            }
188
 
            out += outlinesize;
 
193
            dst += dstlinesize;
189
194
        }
190
195
    }
191
196
 
192
 
    avfilter_unref_buffer(inpic);
193
 
    avfilter_draw_slice(outlink, 0, outpic->video->h, 1);
194
 
    avfilter_end_frame(outlink);
195
 
    avfilter_unref_buffer(outpic);
 
197
    avfilter_unref_bufferp(&in);
 
198
    return ff_filter_frame(outlink, out);
196
199
}
197
200
 
 
201
static const AVFilterPad avfilter_vf_transpose_inputs[] = {
 
202
    {
 
203
        .name        = "default",
 
204
        .type        = AVMEDIA_TYPE_VIDEO,
 
205
        .filter_frame = filter_frame,
 
206
        .min_perms   = AV_PERM_READ,
 
207
    },
 
208
    { NULL }
 
209
};
 
210
 
 
211
static const AVFilterPad avfilter_vf_transpose_outputs[] = {
 
212
    {
 
213
        .name         = "default",
 
214
        .config_props = config_props_output,
 
215
        .type         = AVMEDIA_TYPE_VIDEO,
 
216
    },
 
217
    { NULL }
 
218
};
 
219
 
198
220
AVFilter avfilter_vf_transpose = {
199
221
    .name      = "transpose",
200
222
    .description = NULL_IF_CONFIG_SMALL("Transpose input video."),
204
226
 
205
227
    .query_formats = query_formats,
206
228
 
207
 
    .inputs    = (AVFilterPad[]) {{ .name            = "default",
208
 
                                    .type            = AVMEDIA_TYPE_VIDEO,
209
 
                                    .start_frame     = start_frame,
210
 
                                    .end_frame       = end_frame,
211
 
                                    .min_perms       = AV_PERM_READ, },
212
 
                                  { .name = NULL}},
213
 
    .outputs   = (AVFilterPad[]) {{ .name            = "default",
214
 
                                    .config_props    = config_props_output,
215
 
                                    .type            = AVMEDIA_TYPE_VIDEO, },
216
 
                                  { .name = NULL}},
 
229
    .inputs    = avfilter_vf_transpose_inputs,
 
230
    .outputs   = avfilter_vf_transpose_outputs,
217
231
};