| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2004 Ville Saari | ||
| 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 General Public | ||
| 8 | * License as published by the Free Software Foundation; either | ||
| 9 | * version 2 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 | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * 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 | #include "libavutil/avassert.h" | ||
| 22 | #include "libavutil/imgutils.h" | ||
| 23 | #include "libavutil/pixdesc.h" | ||
| 24 | #include "libavutil/opt.h" | ||
| 25 | #include "avfilter.h" | ||
| 26 | #include "filters.h" | ||
| 27 | #include "video.h" | ||
| 28 | |||
| 29 | enum PhaseMode { | ||
| 30 | PROGRESSIVE, | ||
| 31 | TOP_FIRST, | ||
| 32 | BOTTOM_FIRST, | ||
| 33 | TOP_FIRST_ANALYZE, | ||
| 34 | BOTTOM_FIRST_ANALYZE, | ||
| 35 | ANALYZE, | ||
| 36 | FULL_ANALYZE, | ||
| 37 | AUTO, | ||
| 38 | AUTO_ANALYZE | ||
| 39 | }; | ||
| 40 | |||
| 41 | #define DEPTH 8 | ||
| 42 | #include "phase_template.c" | ||
| 43 | |||
| 44 | #undef DEPTH | ||
| 45 | #define DEPTH 9 | ||
| 46 | #include "phase_template.c" | ||
| 47 | |||
| 48 | #undef DEPTH | ||
| 49 | #define DEPTH 10 | ||
| 50 | #include "phase_template.c" | ||
| 51 | |||
| 52 | #undef DEPTH | ||
| 53 | #define DEPTH 12 | ||
| 54 | #include "phase_template.c" | ||
| 55 | |||
| 56 | #undef DEPTH | ||
| 57 | #define DEPTH 14 | ||
| 58 | #include "phase_template.c" | ||
| 59 | |||
| 60 | #undef DEPTH | ||
| 61 | #define DEPTH 16 | ||
| 62 | #include "phase_template.c" | ||
| 63 | |||
| 64 | typedef struct PhaseContext { | ||
| 65 | const AVClass *class; | ||
| 66 | int mode; ///<PhaseMode | ||
| 67 | AVFrame *frame; /* previous frame */ | ||
| 68 | int nb_planes; | ||
| 69 | int planeheight[4]; | ||
| 70 | int linesize[4]; | ||
| 71 | |||
| 72 | enum PhaseMode (*analyze_plane)(void *ctx, enum PhaseMode mode, AVFrame *old, AVFrame *new); | ||
| 73 | } PhaseContext; | ||
| 74 | |||
| 75 | #define OFFSET(x) offsetof(PhaseContext, x) | ||
| 76 | #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM | ||
| 77 | #define CONST(name, help, val, u) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, 0, 0, FLAGS, .unit = u } | ||
| 78 | |||
| 79 | static const AVOption phase_options[] = { | ||
| 80 | { "mode", "set phase mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=AUTO_ANALYZE}, PROGRESSIVE, AUTO_ANALYZE, FLAGS, .unit = "mode" }, | ||
| 81 | CONST("p", "progressive", PROGRESSIVE, "mode"), | ||
| 82 | CONST("t", "top first", TOP_FIRST, "mode"), | ||
| 83 | CONST("b", "bottom first", BOTTOM_FIRST, "mode"), | ||
| 84 | CONST("T", "top first analyze", TOP_FIRST_ANALYZE, "mode"), | ||
| 85 | CONST("B", "bottom first analyze", BOTTOM_FIRST_ANALYZE, "mode"), | ||
| 86 | CONST("u", "analyze", ANALYZE, "mode"), | ||
| 87 | CONST("U", "full analyze", FULL_ANALYZE, "mode"), | ||
| 88 | CONST("a", "auto", AUTO, "mode"), | ||
| 89 | CONST("A", "auto analyze", AUTO_ANALYZE, "mode"), | ||
| 90 | { NULL } | ||
| 91 | }; | ||
| 92 | |||
| 93 | AVFILTER_DEFINE_CLASS(phase); | ||
| 94 | |||
| 95 | static const enum AVPixelFormat pix_fmts[] = { | ||
| 96 | AV_PIX_FMT_GRAY8, | ||
| 97 | AV_PIX_FMT_GRAY9, | ||
| 98 | AV_PIX_FMT_GRAY10, | ||
| 99 | AV_PIX_FMT_GRAY12, | ||
| 100 | AV_PIX_FMT_GRAY14, | ||
| 101 | AV_PIX_FMT_GRAY16, | ||
| 102 | AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, | ||
| 103 | AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, | ||
| 104 | AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, | ||
| 105 | AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, | ||
| 106 | AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, | ||
| 107 | AV_PIX_FMT_YUVJ411P, | ||
| 108 | AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, | ||
| 109 | AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, | ||
| 110 | AV_PIX_FMT_YUV440P10, | ||
| 111 | AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, | ||
| 112 | AV_PIX_FMT_YUV440P12, | ||
| 113 | AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, | ||
| 114 | AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, | ||
| 115 | AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, | ||
| 116 | AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, | ||
| 117 | AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, | ||
| 118 | AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, | ||
| 119 | AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, | ||
| 120 | AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, | ||
| 121 | AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, | ||
| 122 | AV_PIX_FMT_NONE | ||
| 123 | }; | ||
| 124 | |||
| 125 | 1 | static int config_input(AVFilterLink *inlink) | |
| 126 | { | ||
| 127 | 1 | PhaseContext *s = inlink->dst->priv; | |
| 128 | 1 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | |
| 129 | int ret; | ||
| 130 | |||
| 131 |
1/7✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
1 | switch (desc->comp[0].depth) { |
| 132 | 1 | case 8: s->analyze_plane = analyze_plane_8; break; | |
| 133 | ✗ | case 9: s->analyze_plane = analyze_plane_9; break; | |
| 134 | ✗ | case 10: s->analyze_plane = analyze_plane_10; break; | |
| 135 | ✗ | case 12: s->analyze_plane = analyze_plane_12; break; | |
| 136 | ✗ | case 14: s->analyze_plane = analyze_plane_14; break; | |
| 137 | ✗ | case 16: s->analyze_plane = analyze_plane_16; break; | |
| 138 | ✗ | default: av_assert0(0); | |
| 139 | }; | ||
| 140 | |||
| 141 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) |
| 142 | ✗ | return ret; | |
| 143 | |||
| 144 | 1 | s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); | |
| 145 | 1 | s->planeheight[0] = s->planeheight[3] = inlink->h; | |
| 146 | |||
| 147 | 1 | s->nb_planes = av_pix_fmt_count_planes(inlink->format); | |
| 148 | |||
| 149 | 1 | return 0; | |
| 150 | } | ||
| 151 | |||
| 152 | 50 | static int filter_frame(AVFilterLink *inlink, AVFrame *in) | |
| 153 | { | ||
| 154 | 50 | AVFilterContext *ctx = inlink->dst; | |
| 155 | 50 | AVFilterLink *outlink = ctx->outputs[0]; | |
| 156 | 50 | PhaseContext *s = ctx->priv; | |
| 157 | enum PhaseMode mode; | ||
| 158 | int plane, top, y; | ||
| 159 | AVFrame *out; | ||
| 160 | |||
| 161 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
|
50 | if (ctx->is_disabled) { |
| 162 | ✗ | av_frame_free(&s->frame); | |
| 163 | /* we keep a reference to the previous frame so the filter can start | ||
| 164 | * being useful as soon as it's not disabled, avoiding the 1-frame | ||
| 165 | * delay. */ | ||
| 166 | ✗ | s->frame = av_frame_clone(in); | |
| 167 | ✗ | return ff_filter_frame(outlink, in); | |
| 168 | } | ||
| 169 | |||
| 170 | 50 | out = ff_get_video_buffer(outlink, outlink->w, outlink->h); | |
| 171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
|
50 | if (!out) { |
| 172 | ✗ | av_frame_free(&in); | |
| 173 | ✗ | return AVERROR(ENOMEM); | |
| 174 | } | ||
| 175 | 50 | av_frame_copy_props(out, in); | |
| 176 | |||
| 177 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 49 times.
|
50 | if (!s->frame) { |
| 178 | 1 | s->frame = in; | |
| 179 | 1 | mode = PROGRESSIVE; | |
| 180 | } else { | ||
| 181 | 49 | mode = s->analyze_plane(ctx, s->mode, s->frame, in); | |
| 182 | } | ||
| 183 | |||
| 184 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 50 times.
|
200 | for (plane = 0; plane < s->nb_planes; plane++) { |
| 185 | 150 | const uint8_t *buf = s->frame->data[plane]; | |
| 186 | 150 | const uint8_t *from = in->data[plane]; | |
| 187 | 150 | uint8_t *to = out->data[plane]; | |
| 188 | |||
| 189 |
2/2✓ Branch 0 taken 28800 times.
✓ Branch 1 taken 150 times.
|
28950 | for (y = 0, top = 1; y < s->planeheight[plane]; y++, top ^= 1) { |
| 190 |
3/4✓ Branch 0 taken 14400 times.
✓ Branch 1 taken 14400 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28800 times.
|
28800 | memcpy(to, mode == (top ? BOTTOM_FIRST : TOP_FIRST) ? buf : from, s->linesize[plane]); |
| 191 | |||
| 192 | 28800 | buf += s->frame->linesize[plane]; | |
| 193 | 28800 | from += in->linesize[plane]; | |
| 194 | 28800 | to += out->linesize[plane]; | |
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 1 times.
|
50 | if (in != s->frame) |
| 199 | 49 | av_frame_free(&s->frame); | |
| 200 | 50 | s->frame = in; | |
| 201 | 50 | return ff_filter_frame(outlink, out); | |
| 202 | } | ||
| 203 | |||
| 204 | 2 | static av_cold void uninit(AVFilterContext *ctx) | |
| 205 | { | ||
| 206 | 2 | PhaseContext *s = ctx->priv; | |
| 207 | |||
| 208 | 2 | av_frame_free(&s->frame); | |
| 209 | 2 | } | |
| 210 | |||
| 211 | static const AVFilterPad phase_inputs[] = { | ||
| 212 | { | ||
| 213 | .name = "default", | ||
| 214 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 215 | .filter_frame = filter_frame, | ||
| 216 | .config_props = config_input, | ||
| 217 | }, | ||
| 218 | }; | ||
| 219 | |||
| 220 | const FFFilter ff_vf_phase = { | ||
| 221 | .p.name = "phase", | ||
| 222 | .p.description = NULL_IF_CONFIG_SMALL("Phase shift fields."), | ||
| 223 | .p.priv_class = &phase_class, | ||
| 224 | .p.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, | ||
| 225 | .priv_size = sizeof(PhaseContext), | ||
| 226 | .uninit = uninit, | ||
| 227 | FILTER_INPUTS(phase_inputs), | ||
| 228 | FILTER_OUTPUTS(ff_video_default_filterpad), | ||
| 229 | FILTER_PIXFMTS_ARRAY(pix_fmts), | ||
| 230 | .process_command = ff_filter_process_command, | ||
| 231 | }; | ||
| 232 |