summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-01-14 22:15:56 +0100
committerwm4 <wm4@nowhere>2015-01-14 22:15:56 +0100
commit5d972491bbfc38d9fd9031de2841eed7feeea422 (patch)
tree795e599fbbb9fc86a598e9b0b38e486a0c44e088
parent9c974b2a1b65317d27cde792aef6cb7bf55fcbc9 (diff)
downloadmpv-5d972491bbfc38d9fd9031de2841eed7feeea422.tar.bz2
mpv-5d972491bbfc38d9fd9031de2841eed7feeea422.tar.xz
af_lavfi: use refcounted frames
-rw-r--r--audio/filter/af_lavfi.c101
1 files changed, 57 insertions, 44 deletions
diff --git a/audio/filter/af_lavfi.c b/audio/filter/af_lavfi.c
index bf49d9a311..902fe76e3a 100644
--- a/audio/filter/af_lavfi.c
+++ b/audio/filter/af_lavfi.c
@@ -207,74 +207,86 @@ static int control(struct af_instance *af, int cmd, void *arg)
return AF_UNKNOWN;
}
-static int filter(struct af_instance *af, struct mp_audio *data, int flags)
+static int filter_frame(struct af_instance *af, struct mp_audio *data)
{
struct priv *p = af->priv;
- struct mp_audio *r = af->data;
- bool eof = data->samples == 0 && (flags & AF_FILTER_FLAG_EOF);
AVFilterLink *l_in = p->in->outputs[0];
- AVFrame *frame = av_frame_alloc();
- frame->nb_samples = data->samples;
- frame->format = l_in->format;
+ AVFrame *frame = NULL;
+ if (data) {
+ frame = av_frame_alloc();
+ if (!frame)
+ goto error;
+
+ frame->nb_samples = data->samples;
+ frame->format = l_in->format;
- // Timebase is 1/sample_rate
- frame->pts = p->samples_in;
+ // Timebase is 1/sample_rate
+ frame->pts = p->samples_in;
- frame->channel_layout = l_in->channel_layout;
- frame->sample_rate = l_in->sample_rate;
+ frame->channel_layout = l_in->channel_layout;
+ frame->sample_rate = l_in->sample_rate;
#if LIBAVFILTER_VERSION_MICRO >= 100
- // FFmpeg being a stupid POS
- frame->channels = l_in->channels;
+ // FFmpeg being a stupid POS
+ frame->channels = l_in->channels;
#endif
- frame->extended_data = frame->data;
- for (int n = 0; n < data->num_planes; n++)
- frame->data[n] = data->planes[n];
- frame->linesize[0] = frame->nb_samples * data->sstride;
+ frame->extended_data = frame->data;
+ for (int n = 0; n < data->num_planes; n++)
+ frame->data[n] = data->planes[n];
+ frame->linesize[0] = frame->nb_samples * data->sstride;
- if (av_buffersrc_add_frame(p->in, eof ? NULL : frame) < 0) {
- av_frame_free(&frame);
- return -1;
+ p->samples_in += data->samples;
}
- av_frame_free(&frame);
- int64_t out_pts = AV_NOPTS_VALUE;
- r->samples = 0;
- for (;;) {
- frame = av_frame_alloc();
- if (av_buffersink_get_frame(p->out, frame) < 0) {
- // Not an error situation - no more output buffers in queue.
- av_frame_free(&frame);
- break;
- }
+ if (av_buffersrc_add_frame(p->in, frame) < 0)
+ goto error;
- mp_audio_realloc_min(r, r->samples + frame->nb_samples);
- for (int n = 0; n < r->num_planes; n++) {
- memcpy((char *)r->planes[n] + r->samples * r->sstride,
- frame->extended_data[n], frame->nb_samples * r->sstride);
- }
- r->samples += frame->nb_samples;
+ av_frame_free(&frame);
+ talloc_free(data);
+ return 0;
+error:
+ av_frame_free(&frame);
+ talloc_free(data);
+ return -1;
+}
+
+static int filter_out(struct af_instance *af)
+{
+ struct priv *p = af->priv;
- if (out_pts == AV_NOPTS_VALUE)
- out_pts = frame->pts;
+ AVFrame *frame = av_frame_alloc();
+ if (!frame)
+ goto error;
+ int err = av_buffersink_get_frame(p->out, frame);
+ if (err == AVERROR(EAGAIN) || err == AVERROR_EOF) {
+ // Not an error situation - no more output buffers in queue.
av_frame_free(&frame);
+ return 0;
}
- p->samples_in += data->samples;
+ struct mp_audio *out = mp_audio_from_avframe(frame);
+ if (!out)
+ goto error;
+
+ mp_audio_copy_config(out, af->data);
- if (out_pts != AV_NOPTS_VALUE) {
- double in_time = p->samples_in / (double)data->rate;
- double out_time = out_pts * av_q2d(p->timebase_out);
+ if (frame->pts != AV_NOPTS_VALUE) {
+ double in_time = p->samples_in / (double)af->fmt_in.rate;
+ double out_time = frame->pts * av_q2d(p->timebase_out);
// Need pts past the last output sample.
- out_time += r->samples / (double)r->rate;
+ out_time += out->samples / (double)out->rate;
af->delay = in_time - out_time;
}
- *data = *r;
+ af_add_output_frame(af, out);
+ av_frame_free(&frame);
return 0;
+error:
+ av_frame_free(&frame);
+ return -1;
}
static void uninit(struct af_instance *af)
@@ -286,7 +298,8 @@ static int af_open(struct af_instance *af)
{
af->control = control;
af->uninit = uninit;
- af->filter = filter;
+ af->filter_frame = filter_frame;
+ af->filter_out = filter_out;
// Removing this requires fixing AVFrame.data vs. AVFrame.extended_data
assert(MP_NUM_CHANNELS <= AV_NUM_DATA_POINTERS);
return AF_OK;