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 * format and noformat video filters
24 */
25
26#include "libavutil/pixdesc.h"
27#include "avfilter.h"
28
29typedef struct {
30    /**
31     * List of flags telling if a given image format has been listed
32     * as argument to the filter.
33     */
34    int listed_pix_fmt_flags[PIX_FMT_NB];
35} FormatContext;
36
37#define PIX_FMT_NAME_MAXSIZE 32
38
39static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
40{
41    FormatContext *format = ctx->priv;
42    const char *cur, *sep;
43    char             pix_fmt_name[PIX_FMT_NAME_MAXSIZE];
44    int              pix_fmt_name_len;
45    enum PixelFormat pix_fmt;
46
47    /* parse the list of formats */
48    for (cur = args; cur; cur = sep ? sep+1 : NULL) {
49        if (!(sep = strchr(cur, ':')))
50            pix_fmt_name_len = strlen(cur);
51        else
52            pix_fmt_name_len = sep - cur;
53        if (pix_fmt_name_len >= PIX_FMT_NAME_MAXSIZE) {
54            av_log(ctx, AV_LOG_ERROR, "Format name too long\n");
55            return -1;
56        }
57
58        memcpy(pix_fmt_name, cur, pix_fmt_name_len);
59        pix_fmt_name[pix_fmt_name_len] = 0;
60        pix_fmt = av_get_pix_fmt(pix_fmt_name);
61
62        if (pix_fmt == PIX_FMT_NONE) {
63            av_log(ctx, AV_LOG_ERROR, "Unknown pixel format: %s\n", pix_fmt_name);
64            return -1;
65        }
66
67        format->listed_pix_fmt_flags[pix_fmt] = 1;
68    }
69
70    return 0;
71}
72
73static AVFilterFormats *make_format_list(FormatContext *format, int flag)
74{
75    AVFilterFormats *formats;
76    enum PixelFormat pix_fmt;
77
78    formats = av_mallocz(sizeof(AVFilterFormats));
79    formats->formats = av_malloc(sizeof(enum PixelFormat) * PIX_FMT_NB);
80
81    for (pix_fmt = 0; pix_fmt < PIX_FMT_NB; pix_fmt++)
82        if (format->listed_pix_fmt_flags[pix_fmt] == flag)
83            formats->formats[formats->format_count++] = pix_fmt;
84
85    return formats;
86}
87
88#if CONFIG_FORMAT_FILTER
89static int query_formats_format(AVFilterContext *ctx)
90{
91    avfilter_set_common_formats(ctx, make_format_list(ctx->priv, 1));
92    return 0;
93}
94
95AVFilter avfilter_vf_format = {
96    .name      = "format",
97    .description = "Convert the input video to one of the specified pixel formats.",
98
99    .init      = init,
100
101    .query_formats = query_formats_format,
102
103    .priv_size = sizeof(FormatContext),
104
105    .inputs    = (AVFilterPad[]) {{ .name            = "default",
106                                    .type            = AVMEDIA_TYPE_VIDEO,
107                                    .get_video_buffer= avfilter_null_get_video_buffer,
108                                    .start_frame     = avfilter_null_start_frame,
109                                    .draw_slice      = avfilter_null_draw_slice,
110                                    .end_frame       = avfilter_null_end_frame, },
111                                  { .name = NULL}},
112    .outputs   = (AVFilterPad[]) {{ .name            = "default",
113                                    .type            = AVMEDIA_TYPE_VIDEO },
114                                  { .name = NULL}},
115};
116#endif /* CONFIG_FORMAT_FILTER */
117
118#if CONFIG_NOFORMAT_FILTER
119static int query_formats_noformat(AVFilterContext *ctx)
120{
121    avfilter_set_common_formats(ctx, make_format_list(ctx->priv, 0));
122    return 0;
123}
124
125AVFilter avfilter_vf_noformat = {
126    .name      = "noformat",
127    .description = "Force libavfilter not to use any of the specified pixel formats for the input to the next filter.",
128
129    .init      = init,
130
131    .query_formats = query_formats_noformat,
132
133    .priv_size = sizeof(FormatContext),
134
135    .inputs    = (AVFilterPad[]) {{ .name            = "default",
136                                    .type            = AVMEDIA_TYPE_VIDEO,
137                                    .get_video_buffer= avfilter_null_get_video_buffer,
138                                    .start_frame     = avfilter_null_start_frame,
139                                    .draw_slice      = avfilter_null_draw_slice,
140                                    .end_frame       = avfilter_null_end_frame, },
141                                  { .name = NULL}},
142    .outputs   = (AVFilterPad[]) {{ .name            = "default",
143                                    .type            = AVMEDIA_TYPE_VIDEO },
144                                  { .name = NULL}},
145};
146#endif /* CONFIG_NOFORMAT_FILTER */
147
148