diff options
author | wm4 <wm4@nowhere> | 2018-01-18 14:44:20 +0100 |
---|---|---|
committer | Kevin Mitchell <kevmitch@gmail.com> | 2018-01-30 03:10:27 -0800 |
commit | b9f804b566c4c528714e4ec5e63675ad7ba5fefd (patch) | |
tree | 49d6fcd42ce6597a67aa2af59b7f20beb21a2e14 /filters/f_utils.c | |
parent | 76276c92104c31ee936ba5c76a76072f09978c5f (diff) | |
download | mpv-b9f804b566c4c528714e4ec5e63675ad7ba5fefd.tar.bz2 mpv-b9f804b566c4c528714e4ec5e63675ad7ba5fefd.tar.xz |
audio: rewrite filtering glue code
Use the new filtering code for audio too.
Diffstat (limited to 'filters/f_utils.c')
-rw-r--r-- | filters/f_utils.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/filters/f_utils.c b/filters/f_utils.c index f984a3b33a..d15d063879 100644 --- a/filters/f_utils.c +++ b/filters/f_utils.c @@ -1,3 +1,4 @@ +#include "audio/aframe.h" #include "video/mp_image.h" #include "f_utils.h" @@ -173,3 +174,120 @@ struct mp_filter *mp_bidir_nop_filter_create(struct mp_filter *parent) return f; } + +struct fixed_aframe_size_priv { + int samples; + bool pad_silence; + struct mp_aframe *in; + struct mp_aframe *out; + int out_written; // valid samples in out + struct mp_aframe_pool *pool; +}; + +static void fixed_aframe_size_process(struct mp_filter *f) +{ + struct fixed_aframe_size_priv *p = f->priv; + + if (!mp_pin_in_needs_data(f->ppins[1])) + return; + + if (p->in && !mp_aframe_get_size(p->in)) + TA_FREEP(&p->in); + + if (!p->in) { + struct mp_frame frame = mp_pin_out_read(f->ppins[0]); + if (frame.type == MP_FRAME_EOF) { + if (!p->out) { + mp_pin_in_write(f->ppins[1], frame); + return; + } + mp_pin_out_repeat_eof(f->ppins[0]); + } else if (frame.type == MP_FRAME_AUDIO) { + p->in = frame.data; + if (p->out && !mp_aframe_config_equals(p->out, p->in)) { + mp_pin_out_unread(f->ppins[0], frame); + p->in = NULL; + } + } else if (frame.type) { + MP_ERR(f, "unsupported frame type\n"); + mp_filter_internal_mark_failed(f); + return; + } else { + return; // no new data yet + } + } + + if (p->in) { + if (!p->out) { + p->out = mp_aframe_create(); + mp_aframe_config_copy(p->out, p->in); + mp_aframe_copy_attributes(p->out, p->in); + if (mp_aframe_pool_allocate(p->pool, p->out, p->samples) < 0) { + mp_filter_internal_mark_failed(f); + return; + } + p->out_written = 0; + } + int in_samples = mp_aframe_get_size(p->in); + int copy = MPMIN(in_samples, p->samples - p->out_written); + if (!mp_aframe_copy_samples(p->out, p->out_written, p->in, 0, copy)) + assert(0); + mp_aframe_skip_samples(p->in, copy); + p->out_written += copy; + } + + // p->in not set means draining for EOF or format change + if ((!p->in && p->out_written) || p->out_written == p->samples) { + int missing = p->samples - p->out_written; + assert(missing >= 0); + if (missing) { + mp_aframe_set_silence(p->out, p->out_written, missing); + if (!p->pad_silence) + mp_aframe_set_size(p->out, p->out_written); + } + mp_pin_in_write(f->ppins[1], MAKE_FRAME(MP_FRAME_AUDIO, p->out)); + p->out = NULL; + p->out_written = 0; + } else { + if (mp_pin_out_request_data(f->ppins[0])) + mp_filter_internal_mark_progress(f); + } +} + +static void fixed_aframe_size_reset(struct mp_filter *f) +{ + struct fixed_aframe_size_priv *p = f->priv; + + TA_FREEP(&p->in); + TA_FREEP(&p->out); + p->out_written = 0; +} + +static const struct mp_filter_info fixed_aframe_size_filter = { + .name = "fixed_aframe_size", + .priv_size = sizeof(struct fixed_aframe_size_priv), + .process = fixed_aframe_size_process, + .reset = fixed_aframe_size_reset, + .destroy = fixed_aframe_size_reset, +}; + +struct mp_filter *mp_fixed_aframe_size_create(struct mp_filter *parent, + int samples, bool pad_silence) +{ + if (samples < 1) + return NULL; + + struct mp_filter *f = mp_filter_create(parent, &fixed_aframe_size_filter); + if (!f) + return NULL; + + mp_filter_add_pin(f, MP_PIN_IN, "in"); + mp_filter_add_pin(f, MP_PIN_OUT, "out"); + + struct fixed_aframe_size_priv *p = f->priv; + p->samples = samples; + p->pad_silence = pad_silence; + p->pool = mp_aframe_pool_create(p); + + return f; +} |