2 * Copyright (c) 2007 Benoit Fouet
3 * Copyright (c) 2010 Stefano Sabatini
5 * This file is part of FFmpeg.
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.
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.
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
24 * horizontal flip filter
33 #include "libavutil/pixdesc.h"
34 #include "libavutil/internal.h"
35 #include "libavutil/intreadwrite.h"
36 #include "libavutil/imgutils.h"
38 typedef struct FlipContext
{
39 int max_step
[4]; ///< max pixel step for each plane, expressed as a number of bytes
40 int planewidth
[4]; ///< width of each plane
41 int planeheight
[4]; ///< height of each plane
44 static int query_formats(AVFilterContext
*ctx
)
46 AVFilterFormats
*pix_fmts
= NULL
;
49 for (fmt
= 0; av_pix_fmt_desc_get(fmt
); fmt
++) {
50 const AVPixFmtDescriptor
*desc
= av_pix_fmt_desc_get(fmt
);
51 if (!(desc
->flags
& AV_PIX_FMT_FLAG_HWACCEL
||
52 desc
->flags
& AV_PIX_FMT_FLAG_BITSTREAM
||
53 (desc
->log2_chroma_w
!= desc
->log2_chroma_h
&&
54 desc
->comp
[0].plane
== desc
->comp
[1].plane
)))
55 ff_add_format(&pix_fmts
, fmt
);
58 ff_set_common_formats(ctx
, pix_fmts
);
62 static int config_props(AVFilterLink
*inlink
)
64 FlipContext
*s
= inlink
->dst
->priv
;
65 const AVPixFmtDescriptor
*pix_desc
= av_pix_fmt_desc_get(inlink
->format
);
66 const int hsub
= pix_desc
->log2_chroma_w
;
67 const int vsub
= pix_desc
->log2_chroma_h
;
69 av_image_fill_max_pixsteps(s
->max_step
, NULL
, pix_desc
);
70 s
->planewidth
[0] = s
->planewidth
[3] = inlink
->w
;
71 s
->planewidth
[1] = s
->planewidth
[2] = FF_CEIL_RSHIFT(inlink
->w
, hsub
);
72 s
->planeheight
[0] = s
->planeheight
[3] = inlink
->h
;
73 s
->planeheight
[1] = s
->planeheight
[2] = FF_CEIL_RSHIFT(inlink
->h
, vsub
);
78 typedef struct ThreadData
{
82 static int filter_slice(AVFilterContext
*ctx
, void *arg
, int job
, int nb_jobs
)
84 FlipContext
*s
= ctx
->priv
;
87 AVFrame
*out
= td
->out
;
88 uint8_t *inrow
, *outrow
;
89 int i
, j
, plane
, step
;
91 for (plane
= 0; plane
< 4 && in
->data
[plane
] && in
->linesize
[plane
]; plane
++) {
92 const int width
= s
->planewidth
[plane
];
93 const int height
= s
->planeheight
[plane
];
94 const int start
= (height
* job
) / nb_jobs
;
95 const int end
= (height
* (job
+1)) / nb_jobs
;
97 step
= s
->max_step
[plane
];
99 outrow
= out
->data
[plane
] + start
* out
->linesize
[plane
];
100 inrow
= in
->data
[plane
] + start
* in
->linesize
[plane
] + (width
- 1) * step
;
101 for (i
= start
; i
< end
; i
++) {
104 for (j
= 0; j
< width
; j
++)
105 outrow
[j
] = inrow
[-j
];
110 uint16_t *outrow16
= (uint16_t *)outrow
;
111 uint16_t * inrow16
= (uint16_t *) inrow
;
112 for (j
= 0; j
< width
; j
++)
113 outrow16
[j
] = inrow16
[-j
];
120 uint8_t *out
= outrow
;
121 for (j
= 0; j
< width
; j
++, out
+= 3, in
-= 3) {
122 int32_t v
= AV_RB24(in
);
130 uint32_t *outrow32
= (uint32_t *)outrow
;
131 uint32_t * inrow32
= (uint32_t *) inrow
;
132 for (j
= 0; j
< width
; j
++)
133 outrow32
[j
] = inrow32
[-j
];
138 for (j
= 0; j
< width
; j
++)
139 memcpy(outrow
+ j
*step
, inrow
- j
*step
, step
);
142 inrow
+= in
->linesize
[plane
];
143 outrow
+= out
->linesize
[plane
];
150 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*in
)
152 AVFilterContext
*ctx
= inlink
->dst
;
153 AVFilterLink
*outlink
= ctx
->outputs
[0];
157 out
= ff_get_video_buffer(outlink
, outlink
->w
, outlink
->h
);
160 return AVERROR(ENOMEM
);
162 av_frame_copy_props(out
, in
);
164 /* copy palette if required */
165 if (av_pix_fmt_desc_get(inlink
->format
)->flags
& AV_PIX_FMT_FLAG_PAL
)
166 memcpy(out
->data
[1], in
->data
[1], AVPALETTE_SIZE
);
168 td
.in
= in
, td
.out
= out
;
169 ctx
->internal
->execute(ctx
, filter_slice
, &td
, NULL
, FFMIN(outlink
->h
, ctx
->graph
->nb_threads
));
172 return ff_filter_frame(outlink
, out
);
175 static const AVFilterPad avfilter_vf_hflip_inputs
[] = {
178 .type
= AVMEDIA_TYPE_VIDEO
,
179 .filter_frame
= filter_frame
,
180 .config_props
= config_props
,
185 static const AVFilterPad avfilter_vf_hflip_outputs
[] = {
188 .type
= AVMEDIA_TYPE_VIDEO
,
193 AVFilter ff_vf_hflip
= {
195 .description
= NULL_IF_CONFIG_SMALL("Horizontally flip the input video."),
196 .priv_size
= sizeof(FlipContext
),
197 .query_formats
= query_formats
,
198 .inputs
= avfilter_vf_hflip_inputs
,
199 .outputs
= avfilter_vf_hflip_outputs
,
200 .flags
= AVFILTER_FLAG_SLICE_THREADS
,