summaryrefslogtreecommitdiffstats
path: root/filters/f_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'filters/f_utils.c')
-rw-r--r--filters/f_utils.c118
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;
+}