summaryrefslogtreecommitdiffstats
path: root/video/decode
diff options
context:
space:
mode:
Diffstat (limited to 'video/decode')
-rw-r--r--video/decode/vd_lavc.c59
1 files changed, 31 insertions, 28 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 6c356e2e01..93cb261766 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -172,7 +172,7 @@ typedef struct lavc_ctx {
AVRational codec_timebase;
enum AVDiscard skip_frame;
bool flushing;
- bool eof_returned;
+ struct lavc_state state;
const char *decoder;
bool hwdec_requested;
bool hwdec_failed;
@@ -974,17 +974,17 @@ static bool do_send_packet(struct mp_filter *vd, struct demux_packet *pkt)
AVCodecContext *avctx = ctx->avctx;
if (!prepare_decoding(vd))
- return false;
+ return AVERROR_UNKNOWN;
if (avctx->skip_frame == AVDISCARD_ALL)
- return true;
+ return AVERROR(EAGAIN);
AVPacket avpkt;
mp_set_av_packet(&avpkt, pkt, &ctx->codec_timebase);
int ret = avcodec_send_packet(avctx, pkt ? &avpkt : NULL);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
- return false;
+ return ret;
if (ctx->hw_probing && ctx->num_sent_packets < 32) {
pkt = pkt ? demux_copy_packet(pkt) : NULL;
@@ -993,38 +993,41 @@ static bool do_send_packet(struct mp_filter *vd, struct demux_packet *pkt)
if (ret < 0)
handle_err(vd);
- return true;
+ return ret;
}
-static bool send_queued(struct mp_filter *vd)
+static int send_queued(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
- while (ctx->num_requeue_packets && do_send_packet(vd, ctx->requeue_packets[0]))
- {
+ while (ctx->num_requeue_packets) {
+ int ret = do_send_packet(vd, ctx->requeue_packets[0]);
+ if (ret < 0)
+ return ret;
talloc_free(ctx->requeue_packets[0]);
MP_TARRAY_REMOVE_AT(ctx->requeue_packets, ctx->num_requeue_packets, 0);
}
- return ctx->num_requeue_packets == 0;
+ return 0;
}
-static bool send_packet(struct mp_filter *vd, struct demux_packet *pkt)
+static int send_packet(struct mp_filter *vd, struct demux_packet *pkt)
{
- if (!send_queued(vd))
+ int ret = send_queued(vd);
+ if (ret < 0)
return false;
return do_send_packet(vd, pkt);
}
// Returns whether decoder is still active (!EOF state).
-static bool decode_frame(struct mp_filter *vd)
+static int decode_frame(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
AVCodecContext *avctx = ctx->avctx;
if (!prepare_decoding(vd))
- return true;
+ return AVERROR(EAGAIN);
int ret = avcodec_receive_frame(avctx, ctx->pic);
if (ret == AVERROR_EOF) {
@@ -1034,20 +1037,20 @@ static bool decode_frame(struct mp_filter *vd)
// the delay queue has been drained.
if (!ctx->num_delay_queue)
reset_avctx(vd);
- return false;
+ return ret;
} else if (ret < 0 && ret != AVERROR(EAGAIN)) {
handle_err(vd);
}
if (!ctx->pic->buf[0])
- return true;
+ return ret;
ctx->hwdec_fail_count = 0;
struct mp_image *mpi = mp_image_from_av_frame(ctx->pic);
if (!mpi) {
av_frame_unref(ctx->pic);
- return true;
+ return ret;
}
assert(mpi->planes[0] || mpi->planes[3]);
mpi->pts = mp_pts_from_av(ctx->pic->pts, &ctx->codec_timebase);
@@ -1061,14 +1064,14 @@ static bool decode_frame(struct mp_filter *vd)
av_frame_unref(ctx->pic);
MP_TARRAY_APPEND(ctx, ctx->delay_queue, ctx->num_delay_queue, mpi);
- return true;
+ return ret;
}
-static bool receive_frame(struct mp_filter *vd, struct mp_frame *out_frame)
+static int receive_frame(struct mp_filter *vd, struct mp_frame *out_frame)
{
vd_ffmpeg_ctx *ctx = vd->priv;
- bool progress = decode_frame(vd);
+ int ret = decode_frame(vd);
if (ctx->hwdec_failed) {
// Failed hardware decoding? Try again in software.
@@ -1083,21 +1086,21 @@ static bool receive_frame(struct mp_filter *vd, struct mp_frame *out_frame)
ctx->num_requeue_packets = num_pkts;
send_queued(vd);
- progress = decode_frame(vd);
+ ret = decode_frame(vd);
}
if (!ctx->num_delay_queue)
- return progress;
+ return ret;
- if (ctx->num_delay_queue <= ctx->max_delay_queue && progress)
- return true;
+ if (ctx->num_delay_queue <= ctx->max_delay_queue && ret >= 0)
+ return AVERROR(EAGAIN);
struct mp_image *res = ctx->delay_queue[0];
MP_TARRAY_REMOVE_AT(ctx->delay_queue, ctx->num_delay_queue, 0);
res = res ? mp_img_swap_to_native(res) : NULL;
if (!res)
- return progress;
+ return ret;
if (ctx->use_hwdec && ctx->hwdec.copying && res->hwctx) {
struct mp_image *sw = mp_image_hw_download(res, ctx->hwdec_swpool);
@@ -1107,7 +1110,7 @@ static bool receive_frame(struct mp_filter *vd, struct mp_frame *out_frame)
MP_ERR(vd, "Could not copy back hardware decoded frame.\n");
ctx->hwdec_fail_count = INT_MAX - 1; // force fallback
handle_err(vd);
- return true;
+ return ret;
}
}
@@ -1129,7 +1132,7 @@ static bool receive_frame(struct mp_filter *vd, struct mp_frame *out_frame)
}
*out_frame = MAKE_FRAME(MP_FRAME_VIDEO, res);
- return true;
+ return ret;
}
static int control(struct mp_filter *vd, enum dec_ctrl cmd, void *arg)
@@ -1169,7 +1172,7 @@ static void process(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
- lavc_process(vd, &ctx->eof_returned, send_packet, receive_frame);
+ lavc_process(vd, &ctx->state, send_packet, receive_frame);
}
static void reset(struct mp_filter *vd)
@@ -1178,7 +1181,7 @@ static void reset(struct mp_filter *vd)
flush_all(vd);
- ctx->eof_returned = false;
+ ctx->state = (struct lavc_state){0};
ctx->framedrop_flags = 0;
}