summaryrefslogtreecommitdiffstats
path: root/filters
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-05-23 04:04:46 +0200
committerwm4 <wm4@nowhere>2020-05-23 04:04:46 +0200
commitab4e0c42fbb11f2e7459fe9fe98265e0323b1ef4 (patch)
tree8d202d9a8d7aecf3f305c0311d5115b46ba009d9 /filters
parent43a67970b6c17f8d0525f90fac25923cd4a989bf (diff)
downloadmpv-ab4e0c42fbb11f2e7459fe9fe98265e0323b1ef4.tar.bz2
mpv-ab4e0c42fbb11f2e7459fe9fe98265e0323b1ef4.tar.xz
audio: redo video-sync=display-adrop
This mode drops or repeats audio data to adapt to video speed, instead of resampling it or such. It was added to deal with SPDIF. The implementation was part of fill_audio_out_buffers() - the entire function is something whose complexity exploded in my face, and which I want to clean up, and this is hopefully a first step. Put it in a filter, and mess with the shitty glue code. It's all sort of roundabout and illogical, but that can be rectified later. The important part is that it works much like the resample or scaletempo filters. For PCM audio, this does not work on samples anymore. This makes it much worse. But for PCM you can use saner mechanisms that sound better. Also, something about PTS tracking is wrong. But not wasting more time on this.
Diffstat (limited to 'filters')
-rw-r--r--filters/f_auto_filters.c55
-rw-r--r--filters/f_output_chain.c20
-rw-r--r--filters/f_output_chain.h2
-rw-r--r--filters/filter.h1
-rw-r--r--filters/user_filters.c1
-rw-r--r--filters/user_filters.h1
6 files changed, 60 insertions, 20 deletions
diff --git a/filters/f_auto_filters.c b/filters/f_auto_filters.c
index 944fe89eab..a5394dd35a 100644
--- a/filters/f_auto_filters.c
+++ b/filters/f_auto_filters.c
@@ -1,5 +1,7 @@
#include <math.h>
+#include "audio/aframe.h"
+#include "audio/format.h"
#include "common/common.h"
#include "common/msg.h"
#include "options/m_config.h"
@@ -295,7 +297,8 @@ struct mp_filter *mp_autorotate_create(struct mp_filter *parent)
struct aspeed_priv {
struct mp_subfilter sub;
- double cur_speed;
+ double cur_speed, cur_speed_drop;
+ int current_filter;
};
static void aspeed_process(struct mp_filter *f)
@@ -305,26 +308,48 @@ static void aspeed_process(struct mp_filter *f)
if (!mp_subfilter_read(&p->sub))
return;
- if (fabs(p->cur_speed - 1.0) < 1e-8) {
+ if (!p->sub.filter)
+ p->current_filter = 0;
+
+ double speed = p->cur_speed * p->cur_speed_drop;
+
+ int req_filter = 0;
+ if (fabs(speed - 1.0) >= 1e-8) {
+ req_filter = p->cur_speed_drop == 1.0 ? 1 : 2;
+ if (p->sub.frame.type == MP_FRAME_AUDIO &&
+ !af_fmt_is_pcm(mp_aframe_get_format(p->sub.frame.data)))
+ req_filter = 2;
+ }
+
+ if (req_filter != p->current_filter) {
if (p->sub.filter)
- MP_VERBOSE(f, "removing scaletempo\n");
+ MP_VERBOSE(f, "removing audio speed filter\n");
if (!mp_subfilter_drain_destroy(&p->sub))
return;
- } else if (!p->sub.filter) {
- MP_VERBOSE(f, "adding scaletempo\n");
- p->sub.filter =
- mp_create_user_filter(f, MP_OUTPUT_CHAIN_AUDIO, "scaletempo", NULL);
- if (!p->sub.filter) {
- MP_ERR(f, "could not create scaletempo filter\n");
- mp_subfilter_continue(&p->sub);
- return;
+
+ if (req_filter) {
+ if (req_filter == 1) {
+ MP_VERBOSE(f, "adding scaletempo\n");
+ p->sub.filter = mp_create_user_filter(f, MP_OUTPUT_CHAIN_AUDIO,
+ "scaletempo", NULL);
+ } else if (req_filter == 2) {
+ MP_VERBOSE(f, "adding drop\n");
+ p->sub.filter = mp_create_user_filter(f, MP_OUTPUT_CHAIN_AUDIO,
+ "drop", NULL);
+ }
+ if (!p->sub.filter) {
+ MP_ERR(f, "could not create filter\n");
+ mp_subfilter_continue(&p->sub);
+ return;
+ }
+ p->current_filter = req_filter;
}
}
if (p->sub.filter) {
struct mp_filter_command cmd = {
.type = MP_FILTER_COMMAND_SET_SPEED,
- .speed = p->cur_speed,
+ .speed = speed,
};
mp_filter_command(p->sub.filter, &cmd);
}
@@ -341,6 +366,11 @@ static bool aspeed_command(struct mp_filter *f, struct mp_filter_command *cmd)
return true;
}
+ if (cmd->type == MP_FILTER_COMMAND_SET_SPEED_DROP) {
+ p->cur_speed_drop = cmd->speed;
+ return true;
+ }
+
if (cmd->type == MP_FILTER_COMMAND_IS_ACTIVE) {
cmd->is_active = !!p->sub.filter;
return true;
@@ -381,6 +411,7 @@ struct mp_filter *mp_autoaspeed_create(struct mp_filter *parent)
struct aspeed_priv *p = f->priv;
p->cur_speed = 1.0;
+ p->cur_speed_drop = 1.0;
p->sub.in = mp_filter_add_pin(f, MP_PIN_IN, "in");
p->sub.out = mp_filter_add_pin(f, MP_PIN_OUT, "out");
diff --git a/filters/f_output_chain.c b/filters/f_output_chain.c
index cf16dcbf47..468bfe6466 100644
--- a/filters/f_output_chain.c
+++ b/filters/f_output_chain.c
@@ -454,13 +454,12 @@ bool mp_output_chain_command(struct mp_output_chain *c, const char *target,
// supports it, reset *speed, then keep setting the speed on the other filters.
// The purpose of this is to make sure only 1 filter changes speed.
static void set_speed_any(struct mp_user_filter **filters, int num_filters,
- bool resample, double *speed)
+ int command, double *speed)
{
for (int n = num_filters - 1; n >= 0; n--) {
assert(*speed);
struct mp_filter_command cmd = {
- .type = resample ? MP_FILTER_COMMAND_SET_SPEED_RESAMPLE
- : MP_FILTER_COMMAND_SET_SPEED,
+ .type = command,
.speed = *speed,
};
if (mp_filter_command(filters[n]->f, &cmd))
@@ -469,17 +468,24 @@ static void set_speed_any(struct mp_user_filter **filters, int num_filters,
}
void mp_output_chain_set_audio_speed(struct mp_output_chain *c,
- double speed, double resample)
+ double speed, double resample, double drop)
{
struct chain *p = c->f->priv;
// We always resample with the final libavresample instance.
- set_speed_any(p->post_filters, p->num_post_filters, true, &resample);
+ set_speed_any(p->post_filters, p->num_post_filters,
+ MP_FILTER_COMMAND_SET_SPEED_RESAMPLE, &resample);
// If users have filters like "scaletempo" insert anywhere, use that,
// otherwise use the builtin ones.
- set_speed_any(p->user_filters, p->num_user_filters, false, &speed);
- set_speed_any(p->post_filters, p->num_post_filters, false, &speed);
+ set_speed_any(p->user_filters, p->num_user_filters,
+ MP_FILTER_COMMAND_SET_SPEED, &speed);
+ set_speed_any(p->post_filters, p->num_post_filters,
+ MP_FILTER_COMMAND_SET_SPEED, &speed);
+ set_speed_any(p->user_filters, p->num_user_filters,
+ MP_FILTER_COMMAND_SET_SPEED_DROP, &drop);
+ set_speed_any(p->post_filters, p->num_post_filters,
+ MP_FILTER_COMMAND_SET_SPEED_DROP, &drop);
}
double mp_output_get_measured_total_delay(struct mp_output_chain *c)
diff --git a/filters/f_output_chain.h b/filters/f_output_chain.h
index 980b117d00..f06769cdd9 100644
--- a/filters/f_output_chain.h
+++ b/filters/f_output_chain.h
@@ -77,7 +77,7 @@ bool mp_output_chain_update_filters(struct mp_output_chain *p,
// Desired audio speed, with resample being strict resampling.
void mp_output_chain_set_audio_speed(struct mp_output_chain *p,
- double speed, double resample);
+ double speed, double resample, double drop);
// Total delay incurred by the filter chain, as measured by the recent filtered
// frames. The intention is that this sums the measured delays for each filter,
diff --git a/filters/filter.h b/filters/filter.h
index ddd3f27c3c..34cfcf0f54 100644
--- a/filters/filter.h
+++ b/filters/filter.h
@@ -364,6 +364,7 @@ enum mp_filter_command_type {
MP_FILTER_COMMAND_GET_META,
MP_FILTER_COMMAND_SET_SPEED,
MP_FILTER_COMMAND_SET_SPEED_RESAMPLE,
+ MP_FILTER_COMMAND_SET_SPEED_DROP,
MP_FILTER_COMMAND_IS_ACTIVE,
};
diff --git a/filters/user_filters.c b/filters/user_filters.c
index 72a2ab892c..57021adc7c 100644
--- a/filters/user_filters.c
+++ b/filters/user_filters.c
@@ -39,6 +39,7 @@ const struct mp_user_filter_entry *af_list[] = {
&af_rubberband,
#endif
&af_lavcac3enc,
+ &af_drop,
};
static bool get_af_desc(struct m_obj_desc *dst, int index)
diff --git a/filters/user_filters.h b/filters/user_filters.h
index a79e17030b..cecf0b52cd 100644
--- a/filters/user_filters.h
+++ b/filters/user_filters.h
@@ -24,6 +24,7 @@ extern const struct mp_user_filter_entry af_scaletempo;
extern const struct mp_user_filter_entry af_format;
extern const struct mp_user_filter_entry af_rubberband;
extern const struct mp_user_filter_entry af_lavcac3enc;
+extern const struct mp_user_filter_entry af_drop;
extern const struct mp_user_filter_entry vf_lavfi;
extern const struct mp_user_filter_entry vf_lavfi_bridge;