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
|
- libkvazaar HEVC encoder
|
||||||
- erosion, dilation, deflate and inflate video filters
|
- erosion, dilation, deflate and inflate video filters
|
||||||
- Dynamic Audio Normalizer as dynaudnorm filter
|
- Dynamic Audio Normalizer as dynaudnorm filter
|
||||||
- Reverse filter
|
- Reverse video and areverse audio filter
|
||||||
- Random filter
|
- Random filter
|
||||||
- deband filter
|
- deband filter
|
||||||
- AAC fixed-point decoding
|
- 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
|
This filter uses the repeat_field flag from the Video ES headers and hard repeats
|
||||||
fields based on its value.
|
fields based on its value.
|
||||||
|
|
||||||
@section reverse
|
@section reverse, areverse
|
||||||
|
|
||||||
Reverse a clip.
|
Reverse a clip.
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ OBJS-$(CONFIG_APAD_FILTER) += af_apad.o
|
|||||||
OBJS-$(CONFIG_APERMS_FILTER) += f_perms.o
|
OBJS-$(CONFIG_APERMS_FILTER) += f_perms.o
|
||||||
OBJS-$(CONFIG_APHASER_FILTER) += af_aphaser.o generate_wave_table.o
|
OBJS-$(CONFIG_APHASER_FILTER) += af_aphaser.o generate_wave_table.o
|
||||||
OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o
|
OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o
|
||||||
|
OBJS-$(CONFIG_AREVERSE_FILTER) += vf_reverse.o
|
||||||
OBJS-$(CONFIG_ASELECT_FILTER) += f_select.o
|
OBJS-$(CONFIG_ASELECT_FILTER) += f_select.o
|
||||||
OBJS-$(CONFIG_ASENDCMD_FILTER) += f_sendcmd.o
|
OBJS-$(CONFIG_ASENDCMD_FILTER) += f_sendcmd.o
|
||||||
OBJS-$(CONFIG_ASETNSAMPLES_FILTER) += af_asetnsamples.o
|
OBJS-$(CONFIG_ASETNSAMPLES_FILTER) += af_asetnsamples.o
|
||||||
|
@ -59,6 +59,7 @@ void avfilter_register_all(void)
|
|||||||
REGISTER_FILTER(APERMS, aperms, af);
|
REGISTER_FILTER(APERMS, aperms, af);
|
||||||
REGISTER_FILTER(APHASER, aphaser, af);
|
REGISTER_FILTER(APHASER, aphaser, af);
|
||||||
REGISTER_FILTER(ARESAMPLE, aresample, af);
|
REGISTER_FILTER(ARESAMPLE, aresample, af);
|
||||||
|
REGISTER_FILTER(AREVERSE, areverse, af);
|
||||||
REGISTER_FILTER(ASELECT, aselect, af);
|
REGISTER_FILTER(ASELECT, aselect, af);
|
||||||
REGISTER_FILTER(ASENDCMD, asendcmd, af);
|
REGISTER_FILTER(ASENDCMD, asendcmd, af);
|
||||||
REGISTER_FILTER(ASETNSAMPLES, asetnsamples, af);
|
REGISTER_FILTER(ASETNSAMPLES, asetnsamples, af);
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "libavutil/version.h"
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
#define LIBAVFILTER_VERSION_MAJOR 5
|
#define LIBAVFILTER_VERSION_MAJOR 5
|
||||||
#define LIBAVFILTER_VERSION_MINOR 27
|
#define LIBAVFILTER_VERSION_MINOR 28
|
||||||
#define LIBAVFILTER_VERSION_MICRO 100
|
#define LIBAVFILTER_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
|
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
|
||||||
|
@ -95,6 +95,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_REVERSE_FILTER
|
||||||
|
|
||||||
static int request_frame(AVFilterLink *outlink)
|
static int request_frame(AVFilterLink *outlink)
|
||||||
{
|
{
|
||||||
AVFilterContext *ctx = outlink->src;
|
AVFilterContext *ctx = outlink->src;
|
||||||
@ -141,3 +143,117 @@ AVFilter ff_vf_reverse = {
|
|||||||
.inputs = reverse_inputs,
|
.inputs = reverse_inputs,
|
||||||
.outputs = reverse_outputs,
|
.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