Re: [libav-devel] [RFC PATCH 4/4] lavc: add Intel libmfx-based HEVC encoder

2015-07-05 Thread anton

On 2015-07-04 02:33, Tim W. wrote:
On Tue, Jun 30, 2015 at 8:24 PM, Anton Khirnov  
wrote:



---
 configure |   1 +
 libavcodec/Makefile   |   1 +
 libavcodec/allcodecs.c|   1 +
 libavcodec/hevc.h |   3 +
 libavcodec/qsv.c  |  14 +++
 libavcodec/qsv_internal.h |   4 +
 libavcodec/qsvenc.c   |  22 +++--
 libavcodec/qsvenc_hevc.c  | 236
++
 8 files changed, 273 insertions(+), 9 deletions(-)
 create mode 100644 libavcodec/qsvenc_hevc.c

diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h
index 8b06e1f..60377c2 100644
--- a/libavcodec/hevc.h
+++ b/libavcodec/hevc.h
@@ -113,5 +117,15 @@ int ff_qsv_init_internal_session(AVCodecContext
*avctx, mfxSession *session)
"Initialized an internal MFX session using %s
implementation\n",
desc);

+#if QSV_VERSION_ATLEAST(1, 8)



This will ensure MFXVideoUSER_Load is available, but 
MFX_PLUGINID_HEVCE_SW

was introduced in the dispatcher with MFX_VERSION_MINOR == 10; if you
really want to support building with older dispatchers/headers, you can
always hardcode it:

{{0x2f, 0xca, 0x99, 0x74, 0x9f, 0xdb, 0x49, 0xae, 0xb1, 0x21, 0xa5, 
0xb6,

0x3e, 0xf5, 0x68, 0xf7}}



+if (avctx->codec_id == AV_CODEC_ID_HEVC) {


+ret = MFXVideoUSER_Load(*session, &MFX_PLUGINID_HEVCE_SW, 1);




MFX_PLUGINID_HEVCE_SW is the plugin UID for the software-based HEVC
encoder. Loading it in a hardware-accelerated session appears to work 
(all

the way to MFXVideoENCODE_Init), so at least we're good there.

That being said, if the session is hardware-accelerated, we 
could/should
try loading MFX_PLUGINID_HEVCE_HW first? You'll need the latest 
dispatcher

to build it (MFX_VERSION_MINOR == 15), but you can also hardcode it:

{{0x6f, 0xad, 0xc7, 0x91, 0xa0, 0xc2, 0xeb, 0x47, 0x9a, 0xb6, 0xdc, 
0xd5,

0xea, 0x9d, 0xa3, 0x47}}

There is no way to test it directly, but if you ask nicely Maxym
(Dmytrychenko) may be able to do it for you.



The thing is, the HW plugin I have hangs for me (on Linux). Does it work 
for you in Handbrake?





+if (ret < 0) {
+av_log(avctx, AV_LOG_WARNING,
+   "Could not load the HEVC encoding plugin, encoding
will likely fail\n");



Have you seen a case where the plugin didn't load but encoding worked? 
Else

we may as well fail here.



As Luca said, there can be a theoretical future version that 
incorporates HEVC
encoding into the core. And failing here does not really give us any 
benefits

that I can see.




diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index d13848a..4b6d9c4 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -30,6 +30,10 @@

 #define ASYNC_DEPTH_DEFAULT 4   // internal parallelism

+#define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
+(MFX_VERSION_MAJOR > (MAJOR) || \
+ MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
+



This would be more useful if MFX_VERSION_* wasn't hardcoded, that way 
we
could check the API version exposed by the runtime (via 
MFXQueryVersion) if

the need were to arise in the future.



diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index 690d5aa..a724611 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -124,15 +124,19 @@ static int init_video_param(AVCodecContext 
*avctx,

QSVEncContext *q)
 break;
 }



FrameInfo.Width should be 32-aligned for (QSV-based) HEVC encoding,
according to Maxym. Makes sense, too.




Ok, first time I hear about it, but will fix.



-q->extco.Header.BufferId  = MFX_EXTBUFF_CODING_OPTION;
-q->extco.Header.BufferSz  = sizeof(q->extco);
-q->extco.CAVLC= avctx->coder_type ==
FF_CODER_TYPE_VLC ?
-MFX_CODINGOPTION_ON :
MFX_CODINGOPTION_UNKNOWN;
-
-q->extparam[0] = (mfxExtBuffer *)&q->extco;
-
-q->param.ExtParam= q->extparam;
-q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam);
+// the HEVC encoder plugin currently fails if coding options
+// are provided
+if (avctx->codec_id != AV_CODEC_ID_HEVC) {
+q->extco.Header.BufferId  = MFX_EXTBUFF_CODING_OPTION;
+q->extco.Header.BufferSz  = sizeof(q->extco);
+q->extco.CAVLC= avctx->coder_type ==
FF_CODER_TYPE_VLC ?
+MFX_CODINGOPTION_ON :
MFX_CODINGOPTION_UNKNOWN;
+
+q->extparam[0] = (mfxExtBuffer *)&q->extco;
+
+q->param.ExtParam= q->extparam;
+q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam);
+}



I guess this is OK for now, but using MFXVideoENCODE_Query would be 
better.

Probably outside the scope of this patch though.



diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
new file mode 100644
index 000..9934472
--- /dev/null
+++ b/libavcodec/qsvenc_hevc.c
@@ -0,0 +1,236 @@
+/*
+ * Intel MediaSDK QSV based H.264 enccoder
+ *
+ * This file is part of Libav.
+ *
+

Re: [libav-devel] [RFC PATCH 4/4] lavc: add Intel libmfx-based HEVC encoder

2015-07-04 Thread Tim W.
On Sat, Jul 4, 2015 at 10:09 AM, Luca Barbato  wrote:

> On 04/07/15 02:33, Tim W. wrote:
> > Have you seen a case where the plugin didn't load but encoding worked?
> Else
> > we may as well fail here.
>
> Hypothetical full hw implementation that does not have the plugin.
>
> lu


Fair enough (though all known hardware implementations will require loading
a plugin, as far as I can tell - e.g. MFX_PLUGINID_HEVCE_HW for
hardware-accelerated HEVC encoding using Intel Skylake's onboard graphics).

Tim
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel


Re: [libav-devel] [RFC PATCH 4/4] lavc: add Intel libmfx-based HEVC encoder

2015-07-04 Thread Luca Barbato
On 04/07/15 02:33, Tim W. wrote:
> Have you seen a case where the plugin didn't load but encoding worked? Else
> we may as well fail here.

Hypothetical full hw implementation that does not have the plugin.

lu
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel


Re: [libav-devel] [RFC PATCH 4/4] lavc: add Intel libmfx-based HEVC encoder

2015-07-03 Thread Tim W.
On Tue, Jun 30, 2015 at 8:24 PM, Anton Khirnov  wrote:

> ---
>  configure |   1 +
>  libavcodec/Makefile   |   1 +
>  libavcodec/allcodecs.c|   1 +
>  libavcodec/hevc.h |   3 +
>  libavcodec/qsv.c  |  14 +++
>  libavcodec/qsv_internal.h |   4 +
>  libavcodec/qsvenc.c   |  22 +++--
>  libavcodec/qsvenc_hevc.c  | 236
> ++
>  8 files changed, 273 insertions(+), 9 deletions(-)
>  create mode 100644 libavcodec/qsvenc_hevc.c
>
> diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h
> index 8b06e1f..60377c2 100644
> --- a/libavcodec/hevc.h
> +++ b/libavcodec/hevc.h
> @@ -113,5 +117,15 @@ int ff_qsv_init_internal_session(AVCodecContext
> *avctx, mfxSession *session)
> "Initialized an internal MFX session using %s
> implementation\n",
> desc);
>
> +#if QSV_VERSION_ATLEAST(1, 8)
>

This will ensure MFXVideoUSER_Load is available, but MFX_PLUGINID_HEVCE_SW
was introduced in the dispatcher with MFX_VERSION_MINOR == 10; if you
really want to support building with older dispatchers/headers, you can
always hardcode it:

{{0x2f, 0xca, 0x99, 0x74, 0x9f, 0xdb, 0x49, 0xae, 0xb1, 0x21, 0xa5, 0xb6,
0x3e, 0xf5, 0x68, 0xf7}}


> +if (avctx->codec_id == AV_CODEC_ID_HEVC) {

+ret = MFXVideoUSER_Load(*session, &MFX_PLUGINID_HEVCE_SW, 1);
>

MFX_PLUGINID_HEVCE_SW is the plugin UID for the software-based HEVC
encoder. Loading it in a hardware-accelerated session appears to work (all
the way to MFXVideoENCODE_Init), so at least we're good there.

That being said, if the session is hardware-accelerated, we could/should
try loading MFX_PLUGINID_HEVCE_HW first? You'll need the latest dispatcher
to build it (MFX_VERSION_MINOR == 15), but you can also hardcode it:

{{0x6f, 0xad, 0xc7, 0x91, 0xa0, 0xc2, 0xeb, 0x47, 0x9a, 0xb6, 0xdc, 0xd5,
0xea, 0x9d, 0xa3, 0x47}}

There is no way to test it directly, but if you ask nicely Maxym
(Dmytrychenko) may be able to do it for you.


> +if (ret < 0) {
> +av_log(avctx, AV_LOG_WARNING,
> +   "Could not load the HEVC encoding plugin, encoding
> will likely fail\n");
>

Have you seen a case where the plugin didn't load but encoding worked? Else
we may as well fail here.


> diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
> index d13848a..4b6d9c4 100644
> --- a/libavcodec/qsv_internal.h
> +++ b/libavcodec/qsv_internal.h
> @@ -30,6 +30,10 @@
>
>  #define ASYNC_DEPTH_DEFAULT 4   // internal parallelism
>
> +#define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
> +(MFX_VERSION_MAJOR > (MAJOR) || \
> + MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
> +
>

This would be more useful if MFX_VERSION_* wasn't hardcoded, that way we
could check the API version exposed by the runtime (via MFXQueryVersion) if
the need were to arise in the future.


> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index 690d5aa..a724611 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -124,15 +124,19 @@ static int init_video_param(AVCodecContext *avctx,
> QSVEncContext *q)
>  break;
>  }
>

FrameInfo.Width should be 32-aligned for (QSV-based) HEVC encoding,
according to Maxym. Makes sense, too.


>
> -q->extco.Header.BufferId  = MFX_EXTBUFF_CODING_OPTION;
> -q->extco.Header.BufferSz  = sizeof(q->extco);
> -q->extco.CAVLC= avctx->coder_type ==
> FF_CODER_TYPE_VLC ?
> -MFX_CODINGOPTION_ON :
> MFX_CODINGOPTION_UNKNOWN;
> -
> -q->extparam[0] = (mfxExtBuffer *)&q->extco;
> -
> -q->param.ExtParam= q->extparam;
> -q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam);
> +// the HEVC encoder plugin currently fails if coding options
> +// are provided
> +if (avctx->codec_id != AV_CODEC_ID_HEVC) {
> +q->extco.Header.BufferId  = MFX_EXTBUFF_CODING_OPTION;
> +q->extco.Header.BufferSz  = sizeof(q->extco);
> +q->extco.CAVLC= avctx->coder_type ==
> FF_CODER_TYPE_VLC ?
> +MFX_CODINGOPTION_ON :
> MFX_CODINGOPTION_UNKNOWN;
> +
> +q->extparam[0] = (mfxExtBuffer *)&q->extco;
> +
> +q->param.ExtParam= q->extparam;
> +q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam);
> +}
>

I guess this is OK for now, but using MFXVideoENCODE_Query would be better.
Probably outside the scope of this patch though.


> diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
> new file mode 100644
> index 000..9934472
> --- /dev/null
> +++ b/libavcodec/qsvenc_hevc.c
> @@ -0,0 +1,236 @@
> +/*
> + * Intel MediaSDK QSV based H.264 enccoder
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or

Re: [libav-devel] [RFC PATCH 4/4] lavc: add Intel libmfx-based HEVC encoder

2015-07-02 Thread Tim W.
On Tue, Jun 30, 2015 at 8:24 PM, Anton Khirnov  wrote:

> ---
>  configure |   1 +
>  libavcodec/Makefile   |   1 +
>  libavcodec/allcodecs.c|   1 +
>  libavcodec/hevc.h |   3 +
>  libavcodec/qsv.c  |  14 +++
>  libavcodec/qsv_internal.h |   4 +
>  libavcodec/qsvenc.c   |  22 +++--
>  libavcodec/qsvenc_hevc.c  | 236
> ++
>  8 files changed, 273 insertions(+), 9 deletions(-)
>  create mode 100644 libavcodec/qsvenc_hevc.c


I have several comments on this patch, but I'd rather wait a couple days
until I'm back home so I can check stuff more easily (and also do some
testing).

Regards,

Tim
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel


Re: [libav-devel] [RFC PATCH 4/4] lavc: add Intel libmfx-based HEVC encoder

2015-06-30 Thread Luca Barbato
On 30/06/15 20:24, Anton Khirnov wrote:
> ---
>  configure |   1 +
>  libavcodec/Makefile   |   1 +
>  libavcodec/allcodecs.c|   1 +
>  libavcodec/hevc.h |   3 +
>  libavcodec/qsv.c  |  14 +++
>  libavcodec/qsv_internal.h |   4 +
>  libavcodec/qsvenc.c   |  22 +++--
>  libavcodec/qsvenc_hevc.c  | 236 
> ++
>  8 files changed, 273 insertions(+), 9 deletions(-)
>  create mode 100644 libavcodec/qsvenc_hevc.c
> 
> diff --git a/configure b/configure
> index f9e46b4..a3aa62a 100755
> --- a/configure
> +++ b/configure
> @@ -1841,6 +1841,7 @@ h264_qsv_decoder_select="h264_mp4toannexb_bsf 
> h264_parser qsvdec h264_qsv_hwacce
>  h264_qsv_encoder_deps="libmfx"
>  h264_qsv_encoder_select="qsvenc"
>  hevc_decoder_select="bswapdsp cabac golomb videodsp"
> +hevc_qsv_encoder_select="qsvenc"
>  huffyuv_decoder_select="bswapdsp huffyuvdsp"
>  huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp"
>  iac_decoder_select="imc_decoder"
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index c751729..a560469 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -231,6 +231,7 @@ OBJS-$(CONFIG_H264_QSV_ENCODER)+= qsvenc_h264.o
>  OBJS-$(CONFIG_HEVC_DECODER)+= hevc.o hevc_mvs.o hevc_ps.o 
> hevc_sei.o \
>hevc_cabac.o hevc_refs.o 
> hevcpred.o\
>hevcdsp.o hevc_filter.o 
> hevc_parse.o
> +OBJS-$(CONFIG_HEVC_QSV_ENCODER)+= qsvenc_hevc.o hevc_ps_enc.o 
> hevc_parse.o
>  OBJS-$(CONFIG_HNM4_VIDEO_DECODER)  += hnm4video.o
>  OBJS-$(CONFIG_HQX_DECODER) += hqx.o hqxvlc.o
>  OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index 223c994..f0496b9 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -473,6 +473,7 @@ void avcodec_register_all(void)
>   * above is available */
>  REGISTER_ENCODER(LIBOPENH264,   libopenh264);
>  REGISTER_ENCODER(H264_QSV,  h264_qsv);
> +REGISTER_ENCODER(HEVC_QSV,  hevc_qsv);
>  REGISTER_ENCODER(MPEG2_QSV, mpeg2_qsv);
>  
>  /* parsers */
> diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h
> index 8b06e1f..60377c2 100644
> --- a/libavcodec/hevc.h
> +++ b/libavcodec/hevc.h
> @@ -1008,6 +1008,9 @@ void ff_hevc_pred_init(HEVCPredContext *hpc, int 
> bit_depth);
>  int ff_hevc_extract_rbsp(const uint8_t *src, int length,
>   HEVCNAL *nal);
>  
> +int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id,
> +   uint8_t *buf, int buf_size);
> +
>  extern const uint8_t ff_hevc_qpel_extra_before[4];
>  extern const uint8_t ff_hevc_qpel_extra_after[4];
>  extern const uint8_t ff_hevc_qpel_extra[4];
> diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
> index f563100..482b908 100644
> --- a/libavcodec/qsv.c
> +++ b/libavcodec/qsv.c
> @@ -32,6 +32,10 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
>  switch (codec_id) {
>  case AV_CODEC_ID_H264:
>  return MFX_CODEC_AVC;
> +#if QSV_VERSION_ATLEAST(1, 8)
> +case AV_CODEC_ID_HEVC:
> +return MFX_CODEC_HEVC;
> +#endif
>  case AV_CODEC_ID_MPEG1VIDEO:
>  case AV_CODEC_ID_MPEG2VIDEO:
>  return MFX_CODEC_MPEG2;
> @@ -113,5 +117,15 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, 
> mfxSession *session)
> "Initialized an internal MFX session using %s implementation\n",
> desc);
>  
> +#if QSV_VERSION_ATLEAST(1, 8)
> +if (avctx->codec_id == AV_CODEC_ID_HEVC) {
> +ret = MFXVideoUSER_Load(*session, &MFX_PLUGINID_HEVCE_SW, 1);
> +if (ret < 0) {
> +av_log(avctx, AV_LOG_WARNING,
> +   "Could not load the HEVC encoding plugin, encoding will 
> likely fail\n");
> +}
> +}
> +#endif
> +
>  return 0;
>  }
> diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
> index d13848a..4b6d9c4 100644
> --- a/libavcodec/qsv_internal.h
> +++ b/libavcodec/qsv_internal.h
> @@ -30,6 +30,10 @@
>  
>  #define ASYNC_DEPTH_DEFAULT 4   // internal parallelism
>  
> +#define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
> +(MFX_VERSION_MAJOR > (MAJOR) || \
> + MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
> +
>  typedef struct QSVFrame {
>  AVFrame *frame;
>  mfxFrameSurface1 *surface;
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index 690d5aa..a724611 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -124,15 +124,19 @@ static int init_video_param(AVCodecContext *avctx, 
> QSVEncContext *q)
>  break;
>  }
>  
> -q->extco.Header.BufferId  = MFX_EXTBUFF_CODING_OPTION;
> -q->extco.Header.BufferSz  = sizeof(q->extco);
> -q->extco.CAVLC= avctx->coder_type == FF_CODER_TYPE_VLC ?
> -  

[libav-devel] [RFC PATCH 4/4] lavc: add Intel libmfx-based HEVC encoder

2015-06-30 Thread Anton Khirnov
---
 configure |   1 +
 libavcodec/Makefile   |   1 +
 libavcodec/allcodecs.c|   1 +
 libavcodec/hevc.h |   3 +
 libavcodec/qsv.c  |  14 +++
 libavcodec/qsv_internal.h |   4 +
 libavcodec/qsvenc.c   |  22 +++--
 libavcodec/qsvenc_hevc.c  | 236 ++
 8 files changed, 273 insertions(+), 9 deletions(-)
 create mode 100644 libavcodec/qsvenc_hevc.c

diff --git a/configure b/configure
index f9e46b4..a3aa62a 100755
--- a/configure
+++ b/configure
@@ -1841,6 +1841,7 @@ h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser 
qsvdec h264_qsv_hwacce
 h264_qsv_encoder_deps="libmfx"
 h264_qsv_encoder_select="qsvenc"
 hevc_decoder_select="bswapdsp cabac golomb videodsp"
+hevc_qsv_encoder_select="qsvenc"
 huffyuv_decoder_select="bswapdsp huffyuvdsp"
 huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp"
 iac_decoder_select="imc_decoder"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index c751729..a560469 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -231,6 +231,7 @@ OBJS-$(CONFIG_H264_QSV_ENCODER)+= qsvenc_h264.o
 OBJS-$(CONFIG_HEVC_DECODER)+= hevc.o hevc_mvs.o hevc_ps.o 
hevc_sei.o \
   hevc_cabac.o hevc_refs.o hevcpred.o  
  \
   hevcdsp.o hevc_filter.o hevc_parse.o
+OBJS-$(CONFIG_HEVC_QSV_ENCODER)+= qsvenc_hevc.o hevc_ps_enc.o 
hevc_parse.o
 OBJS-$(CONFIG_HNM4_VIDEO_DECODER)  += hnm4video.o
 OBJS-$(CONFIG_HQX_DECODER) += hqx.o hqxvlc.o
 OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 223c994..f0496b9 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -473,6 +473,7 @@ void avcodec_register_all(void)
  * above is available */
 REGISTER_ENCODER(LIBOPENH264,   libopenh264);
 REGISTER_ENCODER(H264_QSV,  h264_qsv);
+REGISTER_ENCODER(HEVC_QSV,  hevc_qsv);
 REGISTER_ENCODER(MPEG2_QSV, mpeg2_qsv);
 
 /* parsers */
diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h
index 8b06e1f..60377c2 100644
--- a/libavcodec/hevc.h
+++ b/libavcodec/hevc.h
@@ -1008,6 +1008,9 @@ void ff_hevc_pred_init(HEVCPredContext *hpc, int 
bit_depth);
 int ff_hevc_extract_rbsp(const uint8_t *src, int length,
  HEVCNAL *nal);
 
+int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id,
+   uint8_t *buf, int buf_size);
+
 extern const uint8_t ff_hevc_qpel_extra_before[4];
 extern const uint8_t ff_hevc_qpel_extra_after[4];
 extern const uint8_t ff_hevc_qpel_extra[4];
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index f563100..482b908 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -32,6 +32,10 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
 switch (codec_id) {
 case AV_CODEC_ID_H264:
 return MFX_CODEC_AVC;
+#if QSV_VERSION_ATLEAST(1, 8)
+case AV_CODEC_ID_HEVC:
+return MFX_CODEC_HEVC;
+#endif
 case AV_CODEC_ID_MPEG1VIDEO:
 case AV_CODEC_ID_MPEG2VIDEO:
 return MFX_CODEC_MPEG2;
@@ -113,5 +117,15 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, 
mfxSession *session)
"Initialized an internal MFX session using %s implementation\n",
desc);
 
+#if QSV_VERSION_ATLEAST(1, 8)
+if (avctx->codec_id == AV_CODEC_ID_HEVC) {
+ret = MFXVideoUSER_Load(*session, &MFX_PLUGINID_HEVCE_SW, 1);
+if (ret < 0) {
+av_log(avctx, AV_LOG_WARNING,
+   "Could not load the HEVC encoding plugin, encoding will 
likely fail\n");
+}
+}
+#endif
+
 return 0;
 }
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index d13848a..4b6d9c4 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -30,6 +30,10 @@
 
 #define ASYNC_DEPTH_DEFAULT 4   // internal parallelism
 
+#define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
+(MFX_VERSION_MAJOR > (MAJOR) || \
+ MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
+
 typedef struct QSVFrame {
 AVFrame *frame;
 mfxFrameSurface1 *surface;
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index 690d5aa..a724611 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -124,15 +124,19 @@ static int init_video_param(AVCodecContext *avctx, 
QSVEncContext *q)
 break;
 }
 
-q->extco.Header.BufferId  = MFX_EXTBUFF_CODING_OPTION;
-q->extco.Header.BufferSz  = sizeof(q->extco);
-q->extco.CAVLC= avctx->coder_type == FF_CODER_TYPE_VLC ?
-MFX_CODINGOPTION_ON : 
MFX_CODINGOPTION_UNKNOWN;
-
-q->extparam[0] = (mfxExtBuffer *)&q->extco;
-
-q->param.ExtParam= q->extparam;
-q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam);
+// the HEVC encoder plugin currently fails if coding options
+// are provided
+