[FFmpeg-devel] [PATCH] avcodec/qsv: polling free synchronization
Dmitry Rogozhkin
dmitry.v.rogozhkin at intel.com
Wed Oct 9 16:28:11 EEST 2019
From: Andrey Orlov <andrey.orlov at intel.com>
synchronization by sync point after DEVICE_BUSY
Fixes: CPU usage on AVC decode cases (18% -> 9%)
---
libavcodec/qsv.c | 17 +++++++++++++++++
libavcodec/qsv_internal.h | 2 ++
libavcodec/qsvdec.c | 12 ++++++++----
libavcodec/qsvdec.h | 2 ++
libavcodec/qsvenc.c | 13 +++++++++----
libavcodec/qsvenc.h | 2 ++
6 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index b00e427..4b5018b 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -32,6 +32,7 @@
#include "libavutil/hwcontext_qsv.h"
#include "libavutil/imgutils.h"
#include "libavutil/avassert.h"
+#include "libavutil/time.h"
#include "avcodec.h"
#include "qsv_internal.h"
@@ -852,3 +853,19 @@ int ff_qsv_close_internal_session(QSVSession *qs)
#endif
return 0;
}
+
+void ff_qsv_handle_device_busy(mfxSession *session, mfxSyncPoint *sync, mfxStatus *ret, unsigned sleep)
+{
+ int sync_ret;
+
+ if (*sync) {
+ sync_ret = MFXVideoCORE_SyncOperation(*session, *sync, MFX_INFINITE);
+ if (sync_ret == MFX_ERR_NONE) {
+ *sync = NULL;
+ } else {
+ *ret = MFX_ERR_ABORTED;
+ }
+ } else {
+ av_usleep(sleep);
+ }
+}
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index 3755927..01c98cc 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -141,4 +141,6 @@ int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *session,
int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame);
+void ff_qsv_handle_device_busy(mfxSession *session, mfxSyncPoint *sync, mfxStatus *ret, unsigned sleep);
+
#endif /* AVCODEC_QSV_INTERNAL_H */
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index ae50239..aa83272 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -457,8 +457,12 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL,
insurf, &outsurf, sync);
+
+ if (ret == MFX_ERR_NONE)
+ q->last_dec_sync = *sync;
+
if (ret == MFX_WRN_DEVICE_BUSY)
- av_usleep(500);
+ ff_qsv_handle_device_busy(&q->session, &q->last_dec_sync, &ret, 500);
} while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE);
@@ -510,9 +514,9 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
out_frame->queued = 0;
if (avctx->pix_fmt != AV_PIX_FMT_QSV) {
- do {
- ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000);
- } while (ret == MFX_WRN_IN_EXECUTION);
+ ret = MFXVideoCORE_SyncOperation(q->session, *sync, MFX_INFINITE);
+ if (ret < 0)
+ return ret;
}
av_freep(&sync);
diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h
index dec1f61..d27ea68 100644
--- a/libavcodec/qsvdec.h
+++ b/libavcodec/qsvdec.h
@@ -72,6 +72,8 @@ typedef struct QSVContext {
mfxExtBuffer **ext_buffers;
int nb_ext_buffers;
+
+ mfxSyncPoint last_dec_sync;
} QSVContext;
extern const AVCodecHWConfigInternal *ff_qsv_hw_configs[];
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index ba85d64..bd5dd75 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -1368,8 +1368,13 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
do {
ret = MFXVideoENCODE_EncodeFrameAsync(q->session, enc_ctrl, surf, bs, sync);
+
+ if (ret == MFX_ERR_NONE)
+ q->last_enc_sync = *sync;
+
if (ret == MFX_WRN_DEVICE_BUSY)
- av_usleep(500);
+ ff_qsv_handle_device_busy(&q->session, &q->last_enc_sync, &ret, 500);
+
} while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_WRN_IN_EXECUTION);
if (ret > 0)
@@ -1435,9 +1440,9 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL);
- do {
- ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000);
- } while (ret == MFX_WRN_IN_EXECUTION);
+ ret = MFXVideoCORE_SyncOperation(q->session, *sync, MFX_INFINITE);
+ if (ret < 0)
+ return ret;
new_pkt.dts = av_rescale_q(bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base);
new_pkt.pts = av_rescale_q(bs->TimeStamp, (AVRational){1, 90000}, avctx->time_base);
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index ec8b541..f1c22d7 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -185,6 +185,8 @@ typedef struct QSVEncContext {
char *load_plugins;
SetEncodeCtrlCB *set_encode_ctrl_cb;
int forced_idr;
+
+ mfxSyncPoint last_enc_sync;
} QSVEncContext;
int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q);
--
1.8.3.1
More information about the ffmpeg-devel
mailing list