Commit 591741b5 authored by Paul B Mahol's avatar Paul B Mahol

avfilter: add areverse filter

Signed-off-by: 's avatarPaul B Mahol <onemda@gmail.com>
parent 0b159e3b
......@@ -18,7 +18,7 @@ version <next>:
- libkvazaar HEVC encoder
- erosion, dilation, deflate and inflate video filters
- Dynamic Audio Normalizer as dynaudnorm filter
- Reverse filter
- Reverse video and areverse audio filter
- Random filter
- deband filter
- AAC fixed-point decoding
......
......@@ -8489,7 +8489,7 @@ pixels will slow things down on a large logo.
This filter uses the repeat_field flag from the Video ES headers and hard repeats
fields based on its value.
@section reverse
@section reverse, areverse
Reverse a clip.
......
......@@ -43,6 +43,7 @@ OBJS-$(CONFIG_APAD_FILTER) += af_apad.o
OBJS-$(CONFIG_APERMS_FILTER) += f_perms.o
OBJS-$(CONFIG_APHASER_FILTER) += af_aphaser.o generate_wave_table.o
OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o
OBJS-$(CONFIG_AREVERSE_FILTER) += vf_reverse.o
OBJS-$(CONFIG_ASELECT_FILTER) += f_select.o
OBJS-$(CONFIG_ASENDCMD_FILTER) += f_sendcmd.o
OBJS-$(CONFIG_ASETNSAMPLES_FILTER) += af_asetnsamples.o
......
......@@ -59,6 +59,7 @@ void avfilter_register_all(void)
REGISTER_FILTER(APERMS, aperms, af);
REGISTER_FILTER(APHASER, aphaser, af);
REGISTER_FILTER(ARESAMPLE, aresample, af);
REGISTER_FILTER(AREVERSE, areverse, af);
REGISTER_FILTER(ASELECT, aselect, af);
REGISTER_FILTER(ASENDCMD, asendcmd, af);
REGISTER_FILTER(ASETNSAMPLES, asetnsamples, af);
......
......@@ -30,7 +30,7 @@
#include "libavutil/version.h"
#define LIBAVFILTER_VERSION_MAJOR 5
#define LIBAVFILTER_VERSION_MINOR 27
#define LIBAVFILTER_VERSION_MINOR 28
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
......
......@@ -95,6 +95,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
return 0;
}
#if CONFIG_REVERSE_FILTER
static int request_frame(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
......@@ -141,3 +143,117 @@ AVFilter ff_vf_reverse = {
.inputs = reverse_inputs,
.outputs = reverse_outputs,
};
#endif /* CONFIG_REVERSE_FILTER */
#if CONFIG_AREVERSE_FILTER
static int query_formats(AVFilterContext *ctx)
{
AVFilterFormats *formats;
AVFilterChannelLayouts *layouts;
int ret;
layouts = ff_all_channel_layouts();
if (!layouts)
return AVERROR(ENOMEM);
ret = ff_set_common_channel_layouts(ctx, layouts);
if (ret < 0)
return ret;
ret = ff_set_common_formats(ctx, ff_planar_sample_fmts());
if (ret < 0)
return ret;
formats = ff_all_samplerates();
if (!formats)
return AVERROR(ENOMEM);
return ff_set_common_samplerates(ctx, formats);
}
static int areverse_request_frame(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
ReverseContext *s = ctx->priv;
int ret, p, i, j;
ret = ff_request_frame(ctx->inputs[0]);
if (ret == AVERROR_EOF && s->nb_frames > 0) {
AVFrame *out = s->frames[s->nb_frames - 1];
out->pts = s->pts[s->flush_idx++];
for (p = 0; p < outlink->channels; p++) {
switch (outlink->format) {
case AV_SAMPLE_FMT_U8P: {
uint8_t *dst = (uint8_t *)out->extended_data[p];
for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
FFSWAP(uint8_t, dst[i], dst[j]);
}
break;
case AV_SAMPLE_FMT_S16P: {
int16_t *dst = (int16_t *)out->extended_data[p];
for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
FFSWAP(int16_t, dst[i], dst[j]);
}
break;
case AV_SAMPLE_FMT_S32P: {
int32_t *dst = (int32_t *)out->extended_data[p];
for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
FFSWAP(int32_t, dst[i], dst[j]);
}
break;
case AV_SAMPLE_FMT_FLTP: {
float *dst = (float *)out->extended_data[p];
for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
FFSWAP(float, dst[i], dst[j]);
}
break;
case AV_SAMPLE_FMT_DBLP: {
double *dst = (double *)out->extended_data[p];
for (i = 0, j = out->nb_samples - 1; i < j; i++, j--)
FFSWAP(double, dst[i], dst[j]);
}
break;
}
}
ret = ff_filter_frame(outlink, out);
s->nb_frames--;
}
return ret;
}
static const AVFilterPad areverse_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.filter_frame = filter_frame,
.needs_writable = 1,
},
{ NULL }
};
static const AVFilterPad areverse_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.request_frame = areverse_request_frame,
.config_props = config_output,
},
{ NULL }
};
AVFilter ff_af_areverse = {
.name = "areverse",
.description = NULL_IF_CONFIG_SMALL("Reverse an audio clip."),
.query_formats = query_formats,
.priv_size = sizeof(ReverseContext),
.init = init,
.uninit = uninit,
.inputs = areverse_inputs,
.outputs = areverse_outputs,
};
#endif /* CONFIG_AREVERSE_FILTER */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment