summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michael@niedermayer.cc>2015-07-19 16:13:35 +0200
committerMichael Niedermayer <michael@niedermayer.cc>2015-07-19 16:13:35 +0200
commitf929081f2e64d979fd8c58b17705e9554f99baf9 (patch)
tree2d0ebbfdefb78f3921f4c4a425a80e3f548a1a3e
parent7093e215d02ed0dc9632f82ac8ccec432d29cd35 (diff)
parentf5c4d38c78347b09478e21a661befff4b2d44643 (diff)
Merge commit 'f5c4d38c78347b09478e21a661befff4b2d44643'
* commit 'f5c4d38c78347b09478e21a661befff4b2d44643': qsvdec: properly handle asynchronous decoding Conflicts: libavcodec/qsvdec.c Merged-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r--libavcodec/qsv_internal.h2
-rw-r--r--libavcodec/qsvdec.c42
-rw-r--r--libavcodec/qsvdec.h3
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;