summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-10-25 21:50:10 +0200
committerwm4 <wm4@nowhere>2019-10-25 21:50:10 +0200
commit52536aaa7b2cd1b8fe6b0d197f13aeb907aa7bea (patch)
treeb30ca6e0b8d924ba02291935a1c1aa30c7c32d01
parentedc6075fa3c7cda678068c2068fc360f05412c9f (diff)
downloadmpv-52536aaa7b2cd1b8fe6b0d197f13aeb907aa7bea.tar.bz2
mpv-52536aaa7b2cd1b8fe6b0d197f13aeb907aa7bea.tar.xz
f_decoder_wapper: trust frame return over error code
lavc_process() calls the receive/send callbacks, which mirror libavcodec's send/receive API. The receive API in particular can return both a status code and a frame. Normally, libavcodec is pretty explicit that it can't return both a frame and an error. But the receive callback does more stuff in addition (vd_lavc does hardware decoding fallbacks etc.). The previous commit shows an instance where this happened, and where it leaked a frame in this case. For robustness, check whether the frame is set first, i.e. trust it over the status code. Before this, it checked for an EOF status first. Hopefully is of no consequence otherwise. I made this change after testing everything (can someone implement a test suite which tests this exhaustively).
-rw-r--r--filters/f_decoder_wrapper.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/filters/f_decoder_wrapper.c b/filters/f_decoder_wrapper.c
index 4347917152..3d7adca551 100644
--- a/filters/f_decoder_wrapper.c
+++ b/filters/f_decoder_wrapper.c
@@ -824,13 +824,13 @@ void lavc_process(struct mp_filter *f, struct lavc_state *state,
struct mp_frame frame = {0};
int ret_recv = receive(f, &frame);
- if (ret_recv == AVERROR_EOF) {
+ if (frame.type) {
+ state->eof_returned = false;
+ mp_pin_in_write(f->ppins[1], frame);
+ } else if (ret_recv == AVERROR_EOF) {
if (!state->eof_returned)
mp_pin_in_write(f->ppins[1], MP_EOF_FRAME);
state->eof_returned = true;
- } else if (frame.type) {
- state->eof_returned = false;
- mp_pin_in_write(f->ppins[1], frame);
} else if (ret_recv == AVERROR(EAGAIN)) {
// Need to feed a packet.
frame = mp_pin_out_read(f->ppins[0]);
@@ -856,7 +856,7 @@ void lavc_process(struct mp_filter *f, struct lavc_state *state,
talloc_free(pkt);
mp_filter_internal_mark_progress(f);
} else {
- // Just try again.
+ // Decoding error? Just try again.
mp_filter_internal_mark_progress(f);
}
}