mirror of
https://github.com/mpv-player/mpv
synced 2024-12-20 13:52:10 +00:00
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.
This commit is contained in:
parent
dab588a4a2
commit
1bb726dedc
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user