mirror of https://github.com/mpv-player/mpv
115 lines
2.8 KiB
C
115 lines
2.8 KiB
C
#include "audio/aframe.h"
|
|
#include "audio/format.h"
|
|
#include "common/common.h"
|
|
#include "filters/f_autoconvert.h"
|
|
#include "filters/filter_internal.h"
|
|
#include "filters/user_filters.h"
|
|
|
|
struct priv {
|
|
double speed;
|
|
double diff; // amount of too many additional samples in normal speed
|
|
struct mp_aframe *last; // for repeating
|
|
};
|
|
|
|
static void process(struct mp_filter *f)
|
|
{
|
|
struct priv *p = f->priv;
|
|
|
|
if (!mp_pin_in_needs_data(f->ppins[1]))
|
|
return;
|
|
|
|
struct mp_frame frame = {0};
|
|
|
|
double last_dur = p->last ? mp_aframe_duration(p->last) : 0;
|
|
if (p->last && p->diff < 0 && -p->diff > last_dur / 2) {
|
|
MP_VERBOSE(f, "repeat\n");
|
|
frame = MAKE_FRAME(MP_FRAME_AUDIO, p->last);
|
|
p->last = NULL;
|
|
} else {
|
|
frame = mp_pin_out_read(f->ppins[0]);
|
|
|
|
if (frame.type == MP_FRAME_AUDIO) {
|
|
last_dur = mp_aframe_duration(frame.data);
|
|
p->diff -= last_dur;
|
|
if (p->diff > last_dur / 2) {
|
|
MP_VERBOSE(f, "drop\n");
|
|
mp_frame_unref(&frame);
|
|
mp_filter_internal_mark_progress(f);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (frame.type == MP_FRAME_AUDIO) {
|
|
struct mp_aframe *fr = frame.data;
|
|
talloc_free(p->last);
|
|
p->last = mp_aframe_new_ref(fr);
|
|
mp_aframe_mul_speed(fr, p->speed);
|
|
p->diff += mp_aframe_duration(fr);
|
|
mp_aframe_set_pts(p->last, mp_aframe_end_pts(fr));
|
|
} else if (frame.type == MP_FRAME_EOF) {
|
|
TA_FREEP(&p->last);
|
|
}
|
|
mp_pin_in_write(f->ppins[1], frame);
|
|
}
|
|
|
|
static bool command(struct mp_filter *f, struct mp_filter_command *cmd)
|
|
{
|
|
struct priv *p = f->priv;
|
|
|
|
switch (cmd->type) {
|
|
case MP_FILTER_COMMAND_SET_SPEED:
|
|
p->speed = cmd->speed;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static void reset(struct mp_filter *f)
|
|
{
|
|
struct priv *p = f->priv;
|
|
|
|
TA_FREEP(&p->last);
|
|
p->diff = 0;
|
|
}
|
|
|
|
static void destroy(struct mp_filter *f)
|
|
{
|
|
reset(f);
|
|
}
|
|
|
|
static const struct mp_filter_info af_drop_filter = {
|
|
.name = "drop",
|
|
.priv_size = sizeof(struct priv),
|
|
.process = process,
|
|
.command = command,
|
|
.reset = reset,
|
|
.destroy = destroy,
|
|
};
|
|
|
|
static struct mp_filter *af_drop_create(struct mp_filter *parent, void *options)
|
|
{
|
|
struct mp_filter *f = mp_filter_create(parent, &af_drop_filter);
|
|
if (!f) {
|
|
talloc_free(options);
|
|
return NULL;
|
|
}
|
|
|
|
mp_filter_add_pin(f, MP_PIN_IN, "in");
|
|
mp_filter_add_pin(f, MP_PIN_OUT, "out");
|
|
|
|
struct priv *p = f->priv;
|
|
p->speed = 1.0;
|
|
|
|
return f;
|
|
}
|
|
|
|
const struct mp_user_filter_entry af_drop = {
|
|
.desc = {
|
|
.description = "Change audio speed by dropping/repeating frames",
|
|
.name = "drop",
|
|
.priv_size = sizeof(struct priv),
|
|
},
|
|
.create = af_drop_create,
|
|
};
|