00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "libavutil/audioconvert.h"
00027 #include "libavutil/avstring.h"
00028 #include "libavutil/opt.h"
00029
00030 #include "audio.h"
00031 #include "avfilter.h"
00032 #include "formats.h"
00033 #include "internal.h"
00034
00035 typedef struct AFormatContext {
00036 const AVClass *class;
00037
00038 AVFilterFormats *formats;
00039 AVFilterFormats *sample_rates;
00040 AVFilterChannelLayouts *channel_layouts;
00041
00042 char *formats_str;
00043 char *sample_rates_str;
00044 char *channel_layouts_str;
00045 } AFormatContext;
00046
00047 #define OFFSET(x) offsetof(AFormatContext, x)
00048 #define A AV_OPT_FLAG_AUDIO_PARAM
00049 static const AVOption options[] = {
00050 { "sample_fmts", "A comma-separated list of sample formats.", OFFSET(formats_str), AV_OPT_TYPE_STRING, .flags = A },
00051 { "sample_rates", "A comma-separated list of sample rates.", OFFSET(sample_rates_str), AV_OPT_TYPE_STRING, .flags = A },
00052 { "channel_layouts", "A comma-separated list of channel layouts.", OFFSET(channel_layouts_str), AV_OPT_TYPE_STRING, .flags = A },
00053 { NULL },
00054 };
00055
00056 static const AVClass aformat_class = {
00057 .class_name = "aformat filter",
00058 .item_name = av_default_item_name,
00059 .option = options,
00060 .version = LIBAVUTIL_VERSION_INT,
00061 };
00062
00063 #define PARSE_FORMATS(str, type, list, add_to_list, get_fmt, none, desc) \
00064 do { \
00065 char *next, *cur = str; \
00066 while (cur) { \
00067 type fmt; \
00068 next = strchr(cur, ','); \
00069 if (next) \
00070 *next++ = 0; \
00071 \
00072 if ((fmt = get_fmt(cur)) == none) { \
00073 av_log(ctx, AV_LOG_ERROR, "Error parsing " desc ": %s.\n", cur);\
00074 ret = AVERROR(EINVAL); \
00075 goto fail; \
00076 } \
00077 add_to_list(&list, fmt); \
00078 \
00079 cur = next; \
00080 } \
00081 } while (0)
00082
00083 static int get_sample_rate(const char *samplerate)
00084 {
00085 int ret = strtol(samplerate, NULL, 0);
00086 return FFMAX(ret, 0);
00087 }
00088
00089 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
00090 {
00091 AFormatContext *s = ctx->priv;
00092 int ret;
00093
00094 if (!args) {
00095 av_log(ctx, AV_LOG_ERROR, "No parameters supplied.\n");
00096 return AVERROR(EINVAL);
00097 }
00098
00099 s->class = &aformat_class;
00100 av_opt_set_defaults(s);
00101
00102 if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
00103 av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
00104 return ret;
00105 }
00106
00107 PARSE_FORMATS(s->formats_str, enum AVSampleFormat, s->formats,
00108 avfilter_add_format, av_get_sample_fmt, AV_SAMPLE_FMT_NONE, "sample format");
00109 PARSE_FORMATS(s->sample_rates_str, int, s->sample_rates, avfilter_add_format,
00110 get_sample_rate, 0, "sample rate");
00111 PARSE_FORMATS(s->channel_layouts_str, uint64_t, s->channel_layouts,
00112 ff_add_channel_layout, av_get_channel_layout, 0,
00113 "channel layout");
00114
00115 fail:
00116 av_opt_free(s);
00117 return ret;
00118 }
00119
00120 static int query_formats(AVFilterContext *ctx)
00121 {
00122 AFormatContext *s = ctx->priv;
00123
00124 avfilter_set_common_formats(ctx, s->formats ? s->formats :
00125 avfilter_all_formats(AVMEDIA_TYPE_AUDIO));
00126 ff_set_common_samplerates(ctx, s->sample_rates ? s->sample_rates :
00127 ff_all_samplerates());
00128 ff_set_common_channel_layouts(ctx, s->channel_layouts ? s->channel_layouts :
00129 ff_all_channel_layouts());
00130
00131 return 0;
00132 }
00133
00134 AVFilter avfilter_af_aformat = {
00135 .name = "aformat",
00136 .description = NULL_IF_CONFIG_SMALL("Convert the input audio to one of the specified formats."),
00137 .init = init,
00138 .query_formats = query_formats,
00139 .priv_size = sizeof(AFormatContext),
00140
00141 .inputs = (AVFilterPad[]) {{ .name = "default",
00142 .type = AVMEDIA_TYPE_AUDIO,
00143 .filter_samples = ff_null_filter_samples },
00144 { .name = NULL}},
00145 .outputs = (AVFilterPad[]) {{ .name = "default",
00146 .type = AVMEDIA_TYPE_AUDIO},
00147 { .name = NULL}},
00148 };