summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-11-02 22:37:14 +0100
committerwm4 <wm4@nowhere>2019-11-02 22:37:14 +0100
commit1bb726dedce9ab0cd096bd524e869cf1899697cf (patch)
tree2ae313eef14f78938d9d40e2e29fc339dccb7e62
parentdab588a4a255c7a30ef84ecacc92fe8815e402ee (diff)
downloadmpv-1bb726dedce9ab0cd096bd524e869cf1899697cf.tar.bz2
mpv-1bb726dedce9ab0cd096bd524e869cf1899697cf.tar.xz
vd_lavc: simplify fallback handling for full stream hw decoder
Shovel the code around to make the data flow slightly simpler (?). At least there's only one send_packet function now. The old code had the problem that send_packet() could be called even if there were queued packets; due to sending the queued packets in the receive_frame function, this should not happen anymore (the code checking for this case in send_packet should normally never be called). Untested with actual full stream hw decoders (none available here); I created a test case by making hwaccel decoding fail.
-rw-r--r--filters/f_decoder_wrapper.c2
-rw-r--r--video/decode/vd_lavc.c38
2 files changed, 19 insertions, 21 deletions
diff --git a/filters/f_decoder_wrapper.c b/filters/f_decoder_wrapper.c
index 846a0912ed..0462bf2424 100644
--- a/filters/f_decoder_wrapper.c
+++ b/filters/f_decoder_wrapper.c
@@ -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 {
- // Decoding error? Just try again.
+ // Decoding error, or hwdec fallback recovery. Just try again.
mp_filter_internal_mark_progress(f);
}
}
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 42b7b959cb..014b81b3b1 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -968,11 +968,14 @@ static void handle_err(struct mp_filter *vd)
}
}
-static int do_send_packet(struct mp_filter *vd, struct demux_packet *pkt)
+static int send_packet(struct mp_filter *vd, struct demux_packet *pkt)
{
vd_ffmpeg_ctx *ctx = vd->priv;
AVCodecContext *avctx = ctx->avctx;
+ if (ctx->num_requeue_packets && ctx->requeue_packets[0] != pkt)
+ return AVERROR(EAGAIN); // cannot consume the packet
+
if (!prepare_decoding(vd))
return AVERROR_UNKNOWN;
@@ -996,28 +999,17 @@ static int do_send_packet(struct mp_filter *vd, struct demux_packet *pkt)
return ret;
}
-static int send_queued(struct mp_filter *vd)
+static void send_queued_packet(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
- while (ctx->num_requeue_packets) {
- int ret = do_send_packet(vd, ctx->requeue_packets[0]);
- if (ret < 0)
- return ret;
+ assert(ctx->num_requeue_packets);
+ assert(!ctx->hw_probing);
+
+ if (send_packet(vd, ctx->requeue_packets[0]) != AVERROR(EAGAIN)) {
talloc_free(ctx->requeue_packets[0]);
MP_TARRAY_REMOVE_AT(ctx->requeue_packets, ctx->num_requeue_packets, 0);
}
-
- return 0;
-}
-
-static int send_packet(struct mp_filter *vd, struct demux_packet *pkt)
-{
- int ret = send_queued(vd);
- if (ret < 0)
- return false;
-
- return do_send_packet(vd, pkt);
}
// Returns whether decoder is still active (!EOF state).
@@ -1027,7 +1019,11 @@ static int decode_frame(struct mp_filter *vd)
AVCodecContext *avctx = ctx->avctx;
if (!prepare_decoding(vd))
- return AVERROR(EAGAIN);
+ return AVERROR_UNKNOWN;
+
+ // Re-send old packets (typically after a hwdec fallback during init).
+ if (ctx->num_requeue_packets)
+ send_queued_packet(vd);
int ret = avcodec_receive_frame(avctx, ctx->pic);
if (ret == AVERROR_EOF) {
@@ -1085,10 +1081,12 @@ static int receive_frame(struct mp_filter *vd, struct mp_frame *out_frame)
ctx->requeue_packets = pkts;
ctx->num_requeue_packets = num_pkts;
- send_queued(vd);
- ret = decode_frame(vd);
+ return 0; // force retry
}
+ if (ret == AVERROR(EAGAIN) && ctx->num_requeue_packets)
+ return 0; // force retry, so send_queued_packet() gets called
+
if (!ctx->num_delay_queue)
return ret;