FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/vf_vflip.c
Date: 2024-09-07 18:49:03
Exec Total Coverage
Lines: 27 50 54.0%
Functions: 3 4 75.0%
Branches: 18 26 69.2%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2007 Bobby Bingham
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * video vertical flip filter
24 */
25
26 #include "libavutil/internal.h"
27 #include "libavutil/pixdesc.h"
28 #include "avfilter.h"
29 #include "filters.h"
30 #include "video.h"
31
32 typedef struct FlipContext {
33 int vsub; ///< vertical chroma subsampling
34 int bayer;
35 } FlipContext;
36
37 193 static int config_input(AVFilterLink *link)
38 {
39 193 FlipContext *flip = link->dst->priv;
40 193 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
41
42 193 flip->vsub = desc->log2_chroma_h;
43 193 flip->bayer = !!(desc->flags & AV_PIX_FMT_FLAG_BAYER);
44
45 193 return 0;
46 }
47
48 193 static AVFrame *get_video_buffer(AVFilterLink *link, int w, int h)
49 {
50 193 FlipContext *flip = link->dst->priv;
51 AVFrame *frame;
52 int i;
53
54 193 frame = ff_get_video_buffer(link->dst->outputs[0], w, h);
55
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193 times.
193 if (!frame)
56 return NULL;
57
58
2/2
✓ Branch 0 taken 772 times.
✓ Branch 1 taken 193 times.
965 for (i = 0; i < 4; i ++) {
59
4/4
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 193 times.
✓ Branch 2 taken 193 times.
✓ Branch 3 taken 386 times.
772 int vsub = i == 1 || i == 2 ? flip->vsub : 0;
60 772 int height = AV_CEIL_RSHIFT(h, vsub);
61
62
2/2
✓ Branch 0 taken 459 times.
✓ Branch 1 taken 313 times.
772 if (frame->data[i]) {
63 459 frame->data[i] += (height - 1) * frame->linesize[i];
64 459 frame->linesize[i] = -frame->linesize[i];
65 }
66 }
67
68 193 return frame;
69 }
70
71 static int flip_bayer(AVFilterLink *link, AVFrame *in)
72 {
73 AVFilterContext *ctx = link->dst;
74 AVFilterLink *outlink = ctx->outputs[0];
75 AVFrame *out;
76 uint8_t *inrow = in->data[0], *outrow;
77 int i, width = outlink->w << (av_pix_fmt_desc_get(link->format)->comp[0].step > 1);
78 if (outlink->h & 1) {
79 av_log(ctx, AV_LOG_ERROR, "Bayer vertical flip needs even height\n");
80 return AVERROR_INVALIDDATA;
81 }
82
83 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
84 if (!out) {
85 av_frame_free(&in);
86 return AVERROR(ENOMEM);
87 }
88 av_frame_copy_props(out, in);
89 outrow = out->data[0] + out->linesize[0] * (outlink->h - 2);
90 for (i = 0; i < outlink->h >> 1; i++) {
91 memcpy(outrow, inrow, width);
92 memcpy(outrow + out->linesize[0], inrow + in->linesize[0], width);
93 inrow += 2 * in->linesize[0];
94 outrow -= 2 * out->linesize[0];
95 }
96 av_frame_free(&in);
97 return ff_filter_frame(outlink, out);
98 }
99
100 229 static int filter_frame(AVFilterLink *link, AVFrame *frame)
101 {
102 229 FlipContext *flip = link->dst->priv;
103 int i;
104
105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 229 times.
229 if (flip->bayer)
106 return flip_bayer(link, frame);
107
108
2/2
✓ Branch 0 taken 916 times.
✓ Branch 1 taken 229 times.
1145 for (i = 0; i < 4; i ++) {
109
4/4
✓ Branch 0 taken 687 times.
✓ Branch 1 taken 229 times.
✓ Branch 2 taken 229 times.
✓ Branch 3 taken 458 times.
916 int vsub = i == 1 || i == 2 ? flip->vsub : 0;
110 916 int height = AV_CEIL_RSHIFT(link->h, vsub);
111
112
2/2
✓ Branch 0 taken 567 times.
✓ Branch 1 taken 349 times.
916 if (frame->data[i]) {
113 567 frame->data[i] += (height - 1) * frame->linesize[i];
114 567 frame->linesize[i] = -frame->linesize[i];
115 }
116 }
117
118 229 return ff_filter_frame(link->dst->outputs[0], frame);
119 }
120 static const AVFilterPad avfilter_vf_vflip_inputs[] = {
121 {
122 .name = "default",
123 .type = AVMEDIA_TYPE_VIDEO,
124 .get_buffer.video = get_video_buffer,
125 .filter_frame = filter_frame,
126 .config_props = config_input,
127 },
128 };
129
130 const AVFilter ff_vf_vflip = {
131 .name = "vflip",
132 .description = NULL_IF_CONFIG_SMALL("Flip the input video vertically."),
133 .priv_size = sizeof(FlipContext),
134 FILTER_INPUTS(avfilter_vf_vflip_inputs),
135 FILTER_OUTPUTS(ff_video_default_filterpad),
136 .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
137 };
138