avfilter: add areverse filter
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
0b159e3b65
commit
591741b51d
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user