Re: [libav-devel] [PATCH v2] avcodec/qsv: fix async support

2018-07-27 Thread Maxym Dmytrychenko
thanks and will proceed with it

On Thu, Jul 26, 2018 at 9:06 PM Dmitry Rogozhkin <
dmitry.v.rogozh...@intel.com> wrote:

> Current implementations of qsv components incorrectly work with async
> level, they
> actually try to work in async+1 level stepping into MFX_WRN_DEVICE_BUSY
> and polling
> loop. This change address this misbehaviour.
>
> Signed-off-by: Dmitry Rogozhkin 
> Cc: Maxym Dmytrychenko 
> Cc: Zhong Li 
> ---
>  libavcodec/qsvdec.c   | 15 ---
>  libavcodec/qsvdec_h2645.c |  4 ++--
>  libavcodec/qsvdec_other.c |  2 +-
>  libavcodec/qsvenc.c   | 17 +
>  libavcodec/qsvenc.h   |  2 +-
>  5 files changed, 29 insertions(+), 11 deletions(-)
>
> diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
> index 32f1fe7..22e7a46 100644
> --- a/libavcodec/qsvdec.c
> +++ b/libavcodec/qsvdec.c
> @@ -110,6 +110,16 @@ static int qsv_init_session(AVCodecContext *avctx,
> QSVContext *q, mfxSession ses
>  return 0;
>  }
>
> +static inline unsigned int qsv_fifo_item_size(void)
> +{
> +return sizeof(mfxSyncPoint*) + sizeof(QSVFrame*);
> +}
> +
> +static inline unsigned int qsv_fifo_size(const AVFifoBuffer* fifo)
> +{
> +return av_fifo_size(fifo) / qsv_fifo_item_size();
> +}
> +
>  static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q)
>  {
>  const AVPixFmtDescriptor *desc;
> @@ -125,8 +135,7 @@ static int qsv_decode_init(AVCodecContext *avctx,
> QSVContext *q)
>  return AVERROR_BUG;
>
>  if (!q->async_fifo) {
> -q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
> -  (sizeof(mfxSyncPoint*) +
> sizeof(QSVFrame*)));
> +q->async_fifo = av_fifo_alloc(q->async_depth *
> qsv_fifo_item_size());
>  if (!q->async_fifo)
>  return AVERROR(ENOMEM);
>  }
> @@ -384,7 +393,7 @@ static int qsv_decode(AVCodecContext *avctx,
> QSVContext *q,
>  av_freep(&sync);
>  }
>
> -if (!av_fifo_space(q->async_fifo) ||
> +if ((qsv_fifo_size(q->async_fifo) >= q->async_depth) ||
>  (!avpkt->size && av_fifo_size(q->async_fifo))) {
>  AVFrame *src_frame;
>
> diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c
> index 831252f..d9d2318 100644
> --- a/libavcodec/qsvdec_h2645.c
> +++ b/libavcodec/qsvdec_h2645.c
> @@ -186,7 +186,7 @@ static void qsv_decode_flush(AVCodecContext *avctx)
>
>  #if CONFIG_HEVC_QSV_DECODER
>  static const AVOption hevc_options[] = {
> -{ "async_depth", "Internal parallelization depth, the higher the
> value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, {
> .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
> +{ "async_depth", "Internal parallelization depth, the higher the
> value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, {
> .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD },
>
>  { "load_plugin", "A user plugin to load in an internal session",
> OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_DEFAULT },
> LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" },
>  { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE
> },0, 0, VD, "load_plugin" },
> @@ -229,7 +229,7 @@ AVCodec ff_hevc_qsv_decoder = {
>
>  #if CONFIG_H264_QSV_DECODER
>  static const AVOption options[] = {
> -{ "async_depth", "Internal parallelization depth, the higher the
> value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, {
> .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
> +{ "async_depth", "Internal parallelization depth, the higher the
> value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, {
> .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD },
>  { NULL },
>  };
>
> diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c
> index 3c872dc..f6e08a2 100644
> --- a/libavcodec/qsvdec_other.c
> +++ b/libavcodec/qsvdec_other.c
> @@ -159,7 +159,7 @@ static void qsv_decode_flush(AVCodecContext *avctx)
>  #define OFFSET(x) offsetof(QSVOtherContext, x)
>  #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
>  static const AVOption options[] = {
> -{ "async_depth", "Internal parallelization depth, the higher the
> value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, {
> .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
> +{ "async_depth", "Internal parallelization depth, the higher the
> value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, {
> .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD },
>  { NULL },
>  };
>
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index 3ce5ffe..b08fa9d 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -777,7 +777,7 @@ static int qsv_init_opaque_alloc(AVCodecContext
> *avctx, QSVEncContext *q)
>  mfxFrameSurface1 *surfaces;
>  int nb_surfaces, i;
>
> -nb_surfaces = qsv->nb_opaque_surfaces + q->req.NumFrameSuggested +
> q->async_depth;
> +nb_surfaces = qsv->nb_opaque_surfaces 

[libav-devel] [PATCH v2] avcodec/qsv: fix async support

2018-07-26 Thread Dmitry Rogozhkin
Current implementations of qsv components incorrectly work with async level, 
they
actually try to work in async+1 level stepping into MFX_WRN_DEVICE_BUSY and 
polling
loop. This change address this misbehaviour.

Signed-off-by: Dmitry Rogozhkin 
Cc: Maxym Dmytrychenko 
Cc: Zhong Li 
---
 libavcodec/qsvdec.c   | 15 ---
 libavcodec/qsvdec_h2645.c |  4 ++--
 libavcodec/qsvdec_other.c |  2 +-
 libavcodec/qsvenc.c   | 17 +
 libavcodec/qsvenc.h   |  2 +-
 5 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 32f1fe7..22e7a46 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -110,6 +110,16 @@ static int qsv_init_session(AVCodecContext *avctx, 
QSVContext *q, mfxSession ses
 return 0;
 }
 
+static inline unsigned int qsv_fifo_item_size(void)
+{
+return sizeof(mfxSyncPoint*) + sizeof(QSVFrame*);
+}
+
+static inline unsigned int qsv_fifo_size(const AVFifoBuffer* fifo)
+{
+return av_fifo_size(fifo) / qsv_fifo_item_size();
+}
+
 static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q)
 {
 const AVPixFmtDescriptor *desc;
@@ -125,8 +135,7 @@ static int qsv_decode_init(AVCodecContext *avctx, 
QSVContext *q)
 return AVERROR_BUG;
 
 if (!q->async_fifo) {
-q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
-  (sizeof(mfxSyncPoint*) + 
sizeof(QSVFrame*)));
+q->async_fifo = av_fifo_alloc(q->async_depth * qsv_fifo_item_size());
 if (!q->async_fifo)
 return AVERROR(ENOMEM);
 }
@@ -384,7 +393,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q,
 av_freep(&sync);
 }
 
-if (!av_fifo_space(q->async_fifo) ||
+if ((qsv_fifo_size(q->async_fifo) >= q->async_depth) ||
 (!avpkt->size && av_fifo_size(q->async_fifo))) {
 AVFrame *src_frame;
 
diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c
index 831252f..d9d2318 100644
--- a/libavcodec/qsvdec_h2645.c
+++ b/libavcodec/qsvdec_h2645.c
@@ -186,7 +186,7 @@ static void qsv_decode_flush(AVCodecContext *avctx)
 
 #if CONFIG_HEVC_QSV_DECODER
 static const AVOption hevc_options[] = {
-{ "async_depth", "Internal parallelization depth, the higher the value the 
higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 
ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
+{ "async_depth", "Internal parallelization depth, the higher the value the 
higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 
ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD },
 
 { "load_plugin", "A user plugin to load in an internal session", 
OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_DEFAULT }, 
LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" },
 { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE },
0, 0, VD, "load_plugin" },
@@ -229,7 +229,7 @@ AVCodec ff_hevc_qsv_decoder = {
 
 #if CONFIG_H264_QSV_DECODER
 static const AVOption options[] = {
-{ "async_depth", "Internal parallelization depth, the higher the value the 
higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 
ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
+{ "async_depth", "Internal parallelization depth, the higher the value the 
higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 
ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD },
 { NULL },
 };
 
diff --git a/libavcodec/qsvdec_other.c b/libavcodec/qsvdec_other.c
index 3c872dc..f6e08a2 100644
--- a/libavcodec/qsvdec_other.c
+++ b/libavcodec/qsvdec_other.c
@@ -159,7 +159,7 @@ static void qsv_decode_flush(AVCodecContext *avctx)
 #define OFFSET(x) offsetof(QSVOtherContext, x)
 #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
 static const AVOption options[] = {
-{ "async_depth", "Internal parallelization depth, the higher the value the 
higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 
ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
+{ "async_depth", "Internal parallelization depth, the higher the value the 
higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = 
ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD },
 { NULL },
 };
 
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index 3ce5ffe..b08fa9d 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -777,7 +777,7 @@ static int qsv_init_opaque_alloc(AVCodecContext *avctx, 
QSVEncContext *q)
 mfxFrameSurface1 *surfaces;
 int nb_surfaces, i;
 
-nb_surfaces = qsv->nb_opaque_surfaces + q->req.NumFrameSuggested + 
q->async_depth;
+nb_surfaces = qsv->nb_opaque_surfaces + q->req.NumFrameSuggested;
 
 q->opaque_alloc_buf = av_buffer_allocz(sizeof(*surfaces) * nb_surfaces);
 if (!q->opaque_alloc_buf)
@@ -848,6 +848,16 @@ static int qsvenc_init_session(AVCodecContext *avctx, 
QSVEncContext *q)
 return 0;
 }
 
+static inline unsigned int qsv_fifo_item_size(void)
+{
+return sizeo