1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-01 20:32:13 +00:00

lavfi: slightly better disconnected output handling

If we have a disconnected output, read data only passively (and don't
cause input to be written). Otherwise, we're in danger of making
libavfilter queue too many frames on other outputs which are connected
to the same input, but don't read as quickly.

Also don't set pad->output_needed in this specific case, because it
would nonsensically make lavfi_process() return true, even if nothing is
going on.

This commit breaks if there is a simple filter chain with a connected
input, but a disconnected output, like

   --lavfi-complex='[aid1] copy [ao]'

and the audio output didn't initialize correctly. This will eventually
starve video as the audio packet queue get full (it will print a
warning, and then assume video EOF and exit).

But whatever.

Probably fixes #4118.
This commit is contained in:
wm4 2017-02-08 17:53:34 +01:00
parent e285e22143
commit 5085cf295f

View File

@ -43,6 +43,11 @@
#include "lavfi.h"
#if LIBAVFILTER_VERSION_MICRO < 100
#define av_buffersink_get_frame_flags(a, b, c) av_buffersink_get_frame(a, b)
#define AV_BUFFERSINK_FLAG_NO_REQUEST 0
#endif
struct lavfi {
struct mp_log *log;
char *graph_string;
@ -266,6 +271,10 @@ enum stream_type lavfi_pad_type(struct lavfi_pad *pad)
void lavfi_set_connected(struct lavfi_pad *pad, bool connected)
{
pad->connected = connected;
if (!pad->connected) {
pad->output_needed = false;
drop_pad_data(pad);
}
}
bool lavfi_get_connected(struct lavfi_pad *pad)
@ -545,19 +554,17 @@ static void read_output_pads(struct lavfi *c)
if (pad->dir != LAVFI_OUT)
continue;
// If disconnected, read and discard everything.
if (!pad->pending_v && !pad->pending_a && !pad->connected)
pad->output_needed = true;
if (!pad->output_needed)
// If disconnected, read and discard everything (passively).
if (pad->connected && !pad->output_needed)
continue;
assert(pad->buffer);
assert(!pad->pending_v && !pad->pending_a);
int flags = pad->output_needed ? 0 : AV_BUFFERSINK_FLAG_NO_REQUEST;
int r = AVERROR_EOF;
if (!pad->buffer_is_eof)
r = av_buffersink_get_frame(pad->buffer, pad->tmp_frame);
r = av_buffersink_get_frame_flags(pad->buffer, pad->tmp_frame, flags);
if (r >= 0) {
pad->output_needed = false;
double pts = mp_pts_from_av(pad->tmp_frame->pts, &pad->timebase);
@ -583,6 +590,7 @@ static void read_output_pads(struct lavfi *c)
// input pads (via av_buffersrc_get_nb_failed_requests()).
pad->output_eof = false;
} else if (r == AVERROR_EOF) {
pad->output_needed = false;
pad->buffer_is_eof = true;
if (!c->draining_recover_eof && !c->draining_new_format)
pad->output_eof = true;