diff options
author | Michael Niedermayer <michael@niedermayer.cc> | 2015-07-19 16:13:35 +0200 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2015-07-19 16:13:35 +0200 |
commit | f929081f2e64d979fd8c58b17705e9554f99baf9 (patch) | |
tree | 2d0ebbfdefb78f3921f4c4a425a80e3f548a1a3e /libavcodec | |
parent | 7093e215d02ed0dc9632f82ac8ccec432d29cd35 (diff) | |
parent | f5c4d38c78347b09478e21a661befff4b2d44643 (diff) | |
download | ffmpeg-f929081f2e64d979fd8c58b17705e9554f99baf9.tar.gz |
Merge commit 'f5c4d38c78347b09478e21a661befff4b2d44643'
* commit 'f5c4d38c78347b09478e21a661befff4b2d44643':
qsvdec: properly handle asynchronous decoding
Conflicts:
libavcodec/qsvdec.c
Merged-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/qsv_internal.h | 2 | ||||
-rw-r--r-- | libavcodec/qsvdec.c | 42 | ||||
-rw-r--r-- | libavcodec/qsvdec.h | 3 |
3 files changed, 39 insertions, 8 deletions
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index 3d949dc0fa..b9ad199e33 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -55,6 +55,8 @@ typedef struct QSVFrame { mfxFrameSurface1 surface_internal; + int queued; + struct QSVFrame *next; } QSVFrame; diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 996d8e8fef..c422529bc5 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -54,6 +54,11 @@ int ff_qsv_decode_init(AVCodecContext *avctx, QSVContext *q) mfxVideoParam param = { { 0 } }; int ret; + q->async_fifo = av_fifo_alloc((1 + q->async_depth) * + (sizeof(mfxSyncPoint) + sizeof(QSVFrame*))); + if (!q->async_fifo) + return AVERROR(ENOMEM); + q->iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; if (avctx->hwaccel_context) { @@ -134,7 +139,7 @@ static void qsv_clear_unused_frames(QSVContext *q) { QSVFrame *cur = q->work_frames; while (cur) { - if (cur->surface && !cur->surface->Data.Locked) { + if (cur->surface && !cur->surface->Data.Locked && !cur->queued) { cur->surface = NULL; av_frame_unref(cur->frame); } @@ -183,12 +188,12 @@ static int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 ** return 0; } -static AVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf) +static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf) { QSVFrame *cur = q->work_frames; while (cur) { if (surf == cur->surface) - return cur->frame; + return cur; cur = cur->next; } return NULL; @@ -198,6 +203,7 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, AVPacket *avpkt) { + QSVFrame *out_frame; mfxFrameSurface1 *insurf; mfxFrameSurface1 *outsurf; mfxSyncPoint sync; @@ -232,21 +238,37 @@ int ff_qsv_decode(AVCodecContext *avctx, QSVContext *q, } if (sync) { - AVFrame *src_frame; - - MFXVideoCORE_SyncOperation(q->session, sync, 60000); + QSVFrame *out_frame = find_frame(q, outsurf); - src_frame = find_frame(q, outsurf); - if (!src_frame) { + if (!out_frame) { av_log(avctx, AV_LOG_ERROR, "The returned surface does not correspond to any frame\n"); return AVERROR_BUG; } + out_frame->queued = 1; + av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL); + av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); + } + + if (!av_fifo_space(q->async_fifo) || + (!avpkt->size && av_fifo_size(q->async_fifo))) { + AVFrame *src_frame; + + av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL); + av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); + out_frame->queued = 0; + + MFXVideoCORE_SyncOperation(q->session, sync, 60000); + + src_frame = out_frame->frame; + ret = av_frame_ref(frame, src_frame); if (ret < 0) return ret; + outsurf = out_frame->surface; + frame->pkt_pts = frame->pts = outsurf->Data.TimeStamp; frame->repeat_pict = @@ -274,6 +296,10 @@ int ff_qsv_decode_close(QSVContext *q) av_freep(&cur); cur = q->work_frames; } + + av_fifo_free(q->async_fifo); + q->async_fifo = NULL; + ff_qsv_close_internal_session(&q->internal_qs); return 0; diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h index 4184d3391a..5b40bb1734 100644 --- a/libavcodec/qsvdec.h +++ b/libavcodec/qsvdec.h @@ -28,6 +28,7 @@ #include <mfx/mfxvideo.h> +#include "libavutil/fifo.h" #include "libavutil/frame.h" #include "libavutil/pixfmt.h" @@ -47,6 +48,8 @@ typedef struct QSVContext { */ QSVFrame *work_frames; + AVFifoBuffer *async_fifo; + // options set by the caller int async_depth; int iopattern; |