From: Yukinori Yamazoe <[email protected]>

Originally written by Yukinori Yamazoe <[email protected]>.
Further contributions by Luca Barbato <[email protected]>.
---

Here a wip patch, the current problems with it:
 - The memory management could be simplified
 - The rate control requires a framerate, avconv feeds it with the container
   timebase and that causes problems.

For the rest it works fine, I'll update with the 2014 MediaSDK soon.

Linux users should use my mfx_dispatch since it does the vaapi setup required
to access the hardware.

Help in sorting out what to do with avconv welcome.

 configure                |   6 +
 libavcodec/Makefile      |   2 +
 libavcodec/allcodecs.c   |   1 +
 libavcodec/qsv.c         |  85 ++++++
 libavcodec/qsv.h         |  37 +++
 libavcodec/qsvenc.c      | 689 +++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/qsvenc.h      |  86 ++++++
 libavcodec/qsvenc_h264.c | 134 +++++++++
 8 files changed, 1040 insertions(+)
 create mode 100644 libavcodec/qsv.c
 create mode 100644 libavcodec/qsv.h
 create mode 100644 libavcodec/qsvenc.c
 create mode 100644 libavcodec/qsvenc.h
 create mode 100644 libavcodec/qsvenc_h264.c

diff --git a/configure b/configure
index 3c49d9c..0ba9120 100755
--- a/configure
+++ b/configure
@@ -186,6 +186,7 @@ External library support:
   --enable-libfreetype     enable libfreetype [no]
   --enable-libgsm          enable GSM de/encoding via libgsm [no]
   --enable-libilbc         enable iLBC de/encoding via libilbc [no]
+  --enable-libmfx          enable hardware encoding via libmfx [no]
   --enable-libmp3lame      enable MP3 encoding via libmp3lame [no]
   --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb 
[no]
   --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no]
@@ -1131,6 +1132,7 @@ EXTERNAL_LIBRARY_LIST="
     libfreetype
     libgsm
     libilbc
+    libmfx
     libmp3lame
     libopencore_amrnb
     libopencore_amrwb
@@ -1921,6 +1923,7 @@ mpegvideo_parser_select="error_resilience mpegvideo"
 vc1_parser_select="mpegvideo"

 # external libraries
+h264_qsv_encoder_deps="libmfx"
 libfaac_encoder_deps="libfaac"
 libfaac_encoder_select="audio_frame_queue"
 libfdk_aac_decoder_deps="libfdk_aac"
@@ -3958,6 +3961,7 @@ check_header dxva2api.h
 check_header io.h
 check_header mach/mach_time.h
 check_header malloc.h
+check_header mfx/mfxvideo.h
 check_header poll.h
 check_header sys/mman.h
 check_header sys/param.h
@@ -4067,6 +4071,8 @@ enabled openssl           && { check_lib openssl/ssl.h 
SSL_library_init -lssl -l
                                check_lib openssl/ssl.h SSL_library_init -lssl 
-lcrypto -lws2_32 -lgdi32 ||
                                die "ERROR: openssl not found"; }

+enabled libmfx            && require_pkg_config libmfx "mfx/mfxvideo.h" MFXInit
+
 if enabled gnutls; then
     { check_lib nettle/bignum.h nettle_mpz_get_str_256 -lnettle -lhogweed 
-lgmp && enable nettle; } ||
     { check_lib gcrypt.h gcry_mpi_new -lgcrypt && enable gcrypt; }
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 5bd9778..b51fe09 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -203,6 +203,7 @@ OBJS-$(CONFIG_H264_DECODER)            += h264.o 
h264_cabac.o h264_cavlc.o \
                                           h264_direct.o h264_loopfilter.o  \
                                           h264_mb.o h264_picture.o h264_ps.o \
                                           h264_refs.o h264_sei.o h264_slice.o
+OBJS-$(CONFIG_H264_QSV_ENCODER)        += qsvenc_h264.o qsvenc.o qsv.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
@@ -689,6 +690,7 @@ SKIPHEADERS                            += %_tablegen.h      
            \
 SKIPHEADERS-$(CONFIG_DXVA2)            += dxva2.h dxva2_internal.h
 SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER)  += libschroedinger.h
 SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h
+SKIPHEADERS-$(CONFIG_QSVENC)           += qsvenc.h
 SKIPHEADERS-$(CONFIG_VAAPI)            += vaapi_internal.h
 SKIPHEADERS-$(CONFIG_VDA)              += vda.h
 SKIPHEADERS-$(CONFIG_VDPAU)            += vdpau.h vdpau_internal.h
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 47bbef5..bcae879 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -158,6 +158,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(H263I,             h263i);
     REGISTER_ENCODER(H263P,             h263p);
     REGISTER_DECODER(H264,              h264);
+    REGISTER_ENCODER(H264_QSV,          h264_qsv);
     REGISTER_DECODER(HEVC,              hevc);
     REGISTER_DECODER(HNM4_VIDEO,        hnm4_video);
     REGISTER_ENCDEC (HUFFYUV,           huffyuv);
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
new file mode 100644
index 0000000..cfdd653
--- /dev/null
+++ b/libavcodec/qsv.c
@@ -0,0 +1,85 @@
+/*
+ * Intel MediaSDK QSV utility functions
+ *
+ * copyright (c) 2013 Luca Barbato
+ *
+ * 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 (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <sys/types.h>
+#include <mfx/mfxvideo.h>
+
+#include "libavutil/common.h"
+#include "libavutil/mem.h"
+#include "libavutil/log.h"
+#include "libavutil/time.h"
+#include "internal.h"
+#include "avcodec.h"
+#include "qsv.h"
+
+int ff_qsv_error(int mfx_err)
+{
+    switch (mfx_err) {
+    case MFX_ERR_NONE:
+        return 0;
+    case MFX_ERR_MEMORY_ALLOC:
+    case MFX_ERR_NOT_ENOUGH_BUFFER:
+        return AVERROR(ENOMEM);
+    case MFX_ERR_INVALID_HANDLE:
+        return AVERROR(EINVAL);
+    case MFX_ERR_DEVICE_FAILED:
+    case MFX_ERR_DEVICE_LOST:
+    case MFX_ERR_LOCK_MEMORY:
+        return AVERROR(EIO);
+    case MFX_ERR_NULL_PTR:
+    case MFX_ERR_UNDEFINED_BEHAVIOR:
+    case MFX_ERR_NOT_INITIALIZED:
+        return AVERROR_BUG;
+    case MFX_ERR_UNSUPPORTED:
+    case MFX_ERR_NOT_FOUND:
+        return AVERROR(ENOSYS);
+    case MFX_ERR_MORE_DATA:
+    case MFX_ERR_MORE_SURFACE:
+    case MFX_ERR_MORE_BITSTREAM:
+        return AVERROR(EAGAIN);
+    case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM:
+    case MFX_ERR_INVALID_VIDEO_PARAM:
+        return AVERROR(EINVAL);
+    case MFX_ERR_ABORTED:
+    case MFX_ERR_UNKNOWN:
+    default:
+        return AVERROR_UNKNOWN;
+    }
+}
+
+int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
+{
+    switch (codec_id) {
+    case AV_CODEC_ID_H264:
+        return MFX_CODEC_AVC;
+    case AV_CODEC_ID_MPEG1VIDEO:
+    case AV_CODEC_ID_MPEG2VIDEO:
+        return MFX_CODEC_MPEG2;
+    case AV_CODEC_ID_VC1:
+        return MFX_CODEC_VC1;
+    default:
+        break;
+    }
+
+    return AVERROR(ENOSYS);
+}
diff --git a/libavcodec/qsv.h b/libavcodec/qsv.h
new file mode 100644
index 0000000..e5b7766
--- /dev/null
+++ b/libavcodec/qsv.h
@@ -0,0 +1,37 @@
+/*
+ * Intel MediaSDK QSV utility functions
+ *
+ * copyright (c) 2013 Luca Barbato
+ *
+ * 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 (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_QSV_H
+#define AVCODEC_QSV_H
+
+#define QSV_VERSION_MAJOR 1
+#define QSV_VERSION_MINOR 6
+
+#define ASYNC_DEPTH_DEFAULT 4       // internal parallelism
+#define SYNC_TIME_DEFAULT   60000
+
+int ff_qsv_error(int mfx_err);
+
+int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id);
+
+
+#endif /* AVCODEC_QSV_H */
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
new file mode 100644
index 0000000..d24073d
--- /dev/null
+++ b/libavcodec/qsvenc.c
@@ -0,0 +1,689 @@
+/*
+ * Intel MediaSDK QSV encoder utility functions
+ *
+ * copyright (c) 2013 Yukinori Yamazoe
+ *
+ * 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 (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <sys/types.h>
+#include <mfx/mfxvideo.h>
+
+#include "libavutil/common.h"
+#include "libavutil/mem.h"
+#include "libavutil/log.h"
+#include "libavutil/time.h"
+#include "libavutil/imgutils.h"
+
+#include "avcodec.h"
+#include "internal.h"
+#include "qsv.h"
+#include "qsvenc.h"
+
+static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
+{
+    float quant;
+    int ret;
+
+    if ((ret = ff_qsv_codec_id_to_mfx(avctx->codec_id)) < 0)
+        return ret;
+    q->param.mfx.CodecId            = ret;
+    q->param.mfx.CodecProfile       = q->profile;
+    q->param.mfx.CodecLevel         = q->level;
+    q->param.mfx.TargetUsage        = q->preset;
+    q->param.mfx.GopPicSize         = avctx->gop_size < 0 ? 0 : 
avctx->gop_size;
+    q->param.mfx.GopRefDist         = av_clip(avctx->max_b_frames, -1, 16) + 1;
+    q->param.mfx.GopOptFlag         = avctx->flags & CODEC_FLAG_CLOSED_GOP ?
+                                      MFX_GOP_CLOSED :
+                                      0;
+    q->param.mfx.IdrInterval        = q->idr_interval;
+    q->param.mfx.NumSlice           = avctx->slices;
+    q->param.mfx.NumRefFrame        = avctx->refs < 0 ? 0 : avctx->refs;
+    q->param.mfx.EncodedOrder       = 0;
+    q->param.mfx.BufferSizeInKB     = 0;
+  //q->param.mfx.TimeStampCalc      = 0; // API 1.3
+  //q->param.mfx.ExtendedPicStruct  = 0; // API 1.3
+  //q->param.mfx.BRCParamMultiplier = 0; // API 1.3
+  //q->param.mfx.SliceGroupsPresent = 0; // API 1.6
+    q->param.mfx.RateControlMethod =
+        (q->qpi >= 0 && q->qpp >= 0 && q->qpb >= 0) ||
+        avctx->flags & CODEC_FLAG_QSCALE      ? MFX_RATECONTROL_CQP :
+        avctx->rc_max_rate &&
+        avctx->rc_max_rate == avctx->bit_rate ? MFX_RATECONTROL_CBR :
+                                                MFX_RATECONTROL_VBR;
+
+    if (ret == MFX_CODEC_AVC)
+        av_log(avctx, AV_LOG_VERBOSE, "Codec:AVC\n");
+    else if (ret == MFX_CODEC_MPEG2)
+        av_log(avctx, AV_LOG_VERBOSE, "Codec:MPEG2\n");
+    if (q->param.mfx.GopPicSize)
+        av_log(avctx, AV_LOG_VERBOSE, "GopPicSize:%d\n", 
q->param.mfx.GopPicSize);
+    if (q->param.mfx.GopRefDist)
+        av_log(avctx, AV_LOG_VERBOSE, "GopRefDist:%d\n", 
q->param.mfx.GopRefDist);
+    if (q->param.mfx.NumSlice)
+        av_log(avctx, AV_LOG_VERBOSE, "NumSlice:%d\n", q->param.mfx.NumSlice);
+    if (q->param.mfx.NumRefFrame)
+        av_log(avctx, AV_LOG_VERBOSE, "NumRefFrame:%d\n", 
q->param.mfx.NumRefFrame);
+
+    switch (q->param.mfx.RateControlMethod) {
+    case MFX_RATECONTROL_CBR: // API 1.0
+        av_log(avctx, AV_LOG_VERBOSE, "RateControlMethod:CBR\n");
+      //q->param.mfx.InitialDelayInKB;
+        q->param.mfx.TargetKbps = avctx->bit_rate / 1000;
+        q->param.mfx.MaxKbps    = avctx->bit_rate / 1000;
+        av_log(avctx, AV_LOG_VERBOSE, "TargetKbps:%d\n", 
q->param.mfx.TargetKbps);
+        break;
+    case MFX_RATECONTROL_VBR: // API 1.0
+        av_log(avctx, AV_LOG_VERBOSE, "RateControlMethod:VBR\n");
+      //q->param.mfx.InitialDelayInKB;
+        q->param.mfx.TargetKbps = avctx->bit_rate / 1000; // >1072
+        q->param.mfx.MaxKbps    = avctx->rc_max_rate / 1000;
+        av_log(avctx, AV_LOG_VERBOSE, "TargetKbps:%d\n", 
q->param.mfx.TargetKbps);
+        if (q->param.mfx.MaxKbps)
+            av_log(avctx, AV_LOG_VERBOSE, "MaxKbps:%d\n", 
q->param.mfx.MaxKbps);
+        break;
+    case MFX_RATECONTROL_CQP: // API 1.1
+        av_log(avctx, AV_LOG_VERBOSE, "RateControlMethod:CQP\n");
+        if (q->qpi >= 0) {
+            q->param.mfx.QPI = q->qpi;
+        } else {
+            quant = avctx->global_quality / FF_QP2LAMBDA;
+            if (avctx->i_quant_factor)
+                quant *= fabs(avctx->i_quant_factor);
+            quant += avctx->i_quant_offset;
+            q->param.mfx.QPI = av_clip(quant, 0, 51);
+        }
+
+        if (q->qpp >= 0) {
+            q->param.mfx.QPP = q->qpp;
+        } else {
+            quant = avctx->global_quality / FF_QP2LAMBDA;
+            q->param.mfx.QPP = av_clip(quant, 0, 51);
+        }
+
+        if (q->qpb >= 0) {
+            q->param.mfx.QPB = q->qpb;
+        } else {
+            quant = avctx->global_quality / FF_QP2LAMBDA;
+            if (avctx->b_quant_factor)
+                quant *= fabs(avctx->b_quant_factor);
+            quant += avctx->b_quant_offset;
+            q->param.mfx.QPB = av_clip(quant, 0, 51);
+        }
+
+        av_log(avctx, AV_LOG_VERBOSE, "QPI:%d, QPP:%d, QPB:%d\n",
+               q->param.mfx.QPI, q->param.mfx.QPP, q->param.mfx.QPB);
+        break;
+    case MFX_RATECONTROL_AVBR: // API 1.3
+        av_log(avctx, AV_LOG_ERROR,
+               "RateControlMethod:AVBR is unimplemented.\n");
+        /*
+        q->param.mfx.TargetKbps;
+        q->param.mfx.Accuracy;    // API 1.3
+        q->param.mfx.Convergence; // API 1.3
+        */
+        return AVERROR(EINVAL);
+#if 0
+    case MFX_RATECONTROL_LA: // API 1.7
+        av_log(avctx, AV_LOG_ERROR,
+               "RateControlMethod:LA is unimplemented.\n");
+        /*
+        q->param.mfx.InitialDelayInKB;
+        q->param.mfx.TargetKbps;
+        q->param.mfx.MaxKbps;
+        q->extco2.LookAheadDepth; // API 1.7
+        q->extco2.Trellis;        // API 1.6
+        */
+        return AVERROR(EINVAL);
+#endif
+    default:
+        av_log(avctx, AV_LOG_ERROR,
+               "RateControlMethod:%d is undefined.\n",
+               q->param.mfx.RateControlMethod);
+        return AVERROR(EINVAL);
+    }
+
+    q->param.mfx.FrameInfo.FourCC        = MFX_FOURCC_NV12;
+    q->param.mfx.FrameInfo.Width         = FFALIGN(avctx->width, 16);
+    q->param.mfx.FrameInfo.Height        = FFALIGN(avctx->height, 32);
+    q->param.mfx.FrameInfo.CropX         = 0;
+    q->param.mfx.FrameInfo.CropY         = 0;
+    q->param.mfx.FrameInfo.CropW         = avctx->width;
+    q->param.mfx.FrameInfo.CropH         = avctx->height;
+    q->param.mfx.FrameInfo.FrameRateExtN = avctx->time_base.den;
+    q->param.mfx.FrameInfo.FrameRateExtD = avctx->time_base.num;
+    q->param.mfx.FrameInfo.AspectRatioW  = avctx->sample_aspect_ratio.num;
+    q->param.mfx.FrameInfo.AspectRatioH  = avctx->sample_aspect_ratio.den;
+    q->param.mfx.FrameInfo.PicStruct     = MFX_PICSTRUCT_PROGRESSIVE;
+    q->param.mfx.FrameInfo.ChromaFormat  = MFX_CHROMAFORMAT_YUV420;
+
+    av_log(avctx, AV_LOG_VERBOSE, "FrameRate:%d/%d\n",
+           q->param.mfx.FrameInfo.FrameRateExtN,
+           q->param.mfx.FrameInfo.FrameRateExtD);
+
+    q->extco.Header.BufferId      = MFX_EXTBUFF_CODING_OPTION;
+    q->extco.Header.BufferSz      = sizeof(q->extco);
+    q->extco.RateDistortionOpt    = MFX_CODINGOPTION_UNKNOWN;
+    q->extco.EndOfSequence        = MFX_CODINGOPTION_UNKNOWN;
+    q->extco.CAVLC                = avctx->coder_type == FF_CODER_TYPE_VLC ?
+                                    MFX_CODINGOPTION_ON :
+                                    MFX_CODINGOPTION_UNKNOWN;
+  //q->extco.NalHrdConformance    = MFX_CODINGOPTION_UNKNOWN; // API 1.3
+  //q->extco.SingleSeiNalUnit     = MFX_CODINGOPTION_UNKNOWN; // API 1.3
+  //q->extco.VuiVclHrdParameters  = MFX_CODINGOPTION_UNKNOWN; // API 1.3
+    q->extco.ResetRefList         = MFX_CODINGOPTION_UNKNOWN;
+  //q->extco.RefPicMarkRep        = MFX_CODINGOPTION_UNKNOWN; // API 1.3
+  //q->extco.FieldOutput          = MFX_CODINGOPTION_UNKNOWN; // API 1.3
+  //q->extco.ViewOutput           = MFX_CODINGOPTION_UNKNOWN; // API 1.4
+    q->extco.MaxDecFrameBuffering = MFX_CODINGOPTION_UNKNOWN;
+    q->extco.AUDelimiter          = MFX_CODINGOPTION_UNKNOWN; // or OFF
+    q->extco.EndOfStream          = MFX_CODINGOPTION_UNKNOWN;
+    q->extco.PicTimingSEI         = MFX_CODINGOPTION_UNKNOWN; // or OFF
+    q->extco.VuiNalHrdParameters  = MFX_CODINGOPTION_UNKNOWN;
+    q->extco.FramePicture         = MFX_CODINGOPTION_ON;
+  //q->extco.RecoveryPointSEI     = MFX_CODINGOPTION_UNKNOWN; // API 1.6
+
+    if (q->extco.CAVLC == MFX_CODINGOPTION_ON)
+        av_log(avctx, AV_LOG_VERBOSE, "CAVLC:ON\n");
+
+    q->extparam[q->param.NumExtParam] = (mfxExtBuffer *)&q->extco;
+    q->param.ExtParam = q->extparam;
+    q->param.NumExtParam++;
+
+/*
+    q->extcospspps.Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS;
+    q->extcospspps.Header.BufferSz = sizeof(q->extcospspps);
+    q->extcospspps.SPSBuffer       = q->spspps[0];
+    q->extcospspps.SPSBufSize      = sizeof(q->spspps[0]);
+    q->extcospspps.PPSBuffer       = q->spspps[1];
+    q->extcospspps.PPSBufSize      = sizeof(q->spspps[1]);
+
+    q->extparam[q->param.NumExtParam] = (mfxExtBuffer *)&q->extcospspps;
+    q->param.ExtParam = q->extparam;
+    q->param.NumExtParam++;
+*/
+
+    return 0;
+}
+
+int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
+{
+    mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
+    mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+    int ret;
+
+    if ((ret = MFXInit(impl, &ver, &q->session)) < 0) {
+        return ff_qsv_error(ret);
+    }
+
+    MFXQueryIMPL(q->session, &impl);
+
+    if (impl & MFX_IMPL_SOFTWARE)
+        av_log(avctx, AV_LOG_VERBOSE,
+               "Using Intel QuickSync encoder software implementation.\n");
+    else if (impl & MFX_IMPL_HARDWARE)
+        av_log(avctx, AV_LOG_VERBOSE,
+               "Using Intel QuickSync encoder hardware accelerated 
implementation.\n");
+    else
+        av_log(avctx, AV_LOG_VERBOSE,
+               "Unknown Intel QuickSync encoder implementation %d.\n", impl);
+
+    q->param.IOPattern  = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
+    q->param.AsyncDepth = q->async_depth;
+
+    if ((ret = init_video_param(avctx, q)) < 0)
+        return ret;
+
+    ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR, "MFXVideoENCODE_QueryIOSurf():%d\n", ret);
+        return ff_qsv_error(ret);
+    }
+
+    if (ret = MFXVideoENCODE_Init(q->session, &q->param)) {
+        av_log(avctx, AV_LOG_ERROR, "MFXVideoENCODE_Init():%d\n", ret);
+        return ff_qsv_error(ret);
+    }
+
+    MFXVideoENCODE_GetVideoParam(q->session, &q->param);
+
+    q->first_pts = AV_NOPTS_VALUE;
+    q->pts_delay = AV_NOPTS_VALUE;
+
+    return ret;
+}
+
+static QSVEncSurfaceList *get_surface_pool(QSVEncContext *q)
+{
+    QSVEncSurfaceList **pool = &q->surf_pool;
+    QSVEncSurfaceList *list;
+
+    while (*pool && ((*pool)->surface.Data.Locked ||
+            (*pool)->prev || (*pool)->next))
+        pool = &(*pool)->pool;
+
+    if (!(*pool))
+        if (!(*pool = av_mallocz(sizeof(QSVEncSurfaceList))))
+            return NULL;
+
+    list = *pool;
+    if (list->surface.Data.MemId)
+        av_frame_free((AVFrame **)(&list->surface.Data.MemId));
+
+    return list;
+}
+
+static void free_surface_pool(QSVEncContext *q)
+{
+    QSVEncSurfaceList **pool = &q->surf_pool;
+    QSVEncSurfaceList *list;
+
+    while (*pool) {
+        list = *pool;
+        *pool = list->pool;
+        av_frame_free((AVFrame **)(&list->surface.Data.MemId));
+        av_freep(&list);
+    }
+}
+
+static AVFrame *clone_aligned_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+    int width    = frame->linesize[0];
+    int height   = FFALIGN(frame->height, 32);
+    int size     = width * height;
+    AVFrame *ret = NULL;
+
+    // check AVFrame buffer alignment for QSV
+    if (!(width % 16) && frame->buf[0] && (frame->buf[0]->size >= size)) {
+        if (!(ret = av_frame_clone(frame))) {
+            av_log(avctx, AV_LOG_ERROR, "av_frame_clone() failed\n");
+            goto fail;
+        }
+    } else {
+        if (!(ret = av_frame_alloc())) {
+            av_log(avctx, AV_LOG_ERROR, "av_frame_alloc() failed\n");
+            goto fail;
+        }
+        if (ff_get_buffer(avctx, ret, 0) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "ff_get_buffer() failed\n");
+            goto fail;
+        }
+        if (av_frame_copy_props(ret, frame) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "av_frame_copy_props() failed\n");
+            goto fail;
+        }
+        av_image_copy(ret->data, ret->linesize, frame->data, frame->linesize,
+                      frame->format, frame->width, frame->height);
+    }
+
+    return ret;
+
+fail:
+    if (ret)
+        av_frame_free(&ret);
+
+    return NULL;
+}
+
+static void set_surface_param(QSVEncContext *q, mfxFrameSurface1 *surf,
+                              AVFrame *frame)
+{
+    surf->Info = q->param.mfx.FrameInfo;
+
+    surf->Info.PicStruct =
+        !frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
+        frame->top_field_first   ? MFX_PICSTRUCT_FIELD_TFF :
+                                   MFX_PICSTRUCT_FIELD_BFF;
+    if (frame->repeat_pict == 1)
+        surf->Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
+    else if (frame->repeat_pict == 2)
+        surf->Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
+    else if (frame->repeat_pict == 4)
+        surf->Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
+
+    surf->Data.MemId     = frame;
+    surf->Data.Y         = frame->data[0];
+    surf->Data.UV        = frame->data[1];
+    surf->Data.Pitch     = frame->linesize[0];
+    surf->Data.TimeStamp = frame->pts;
+}
+
+static int put_surface_from_frame(AVCodecContext *avctx, QSVEncContext *q, 
AVFrame *frame)
+{
+    QSVEncSurfaceList *list;
+    AVFrame *clone;
+
+    if (!(list = get_surface_pool(q)))
+        return AVERROR(ENOMEM);
+
+    if (!(clone = clone_aligned_frame(avctx, frame)))
+        return AVERROR(ENOMEM);
+
+    set_surface_param(q, &list->surface, clone);
+
+    list->prev = q->pending_enc_end;
+    list->next = NULL;
+
+    if (q->pending_enc_end)
+        q->pending_enc_end->next = list;
+    else
+        q->pending_enc = list;
+
+    q->pending_enc_end = list;
+
+    return 0;
+}
+
+static mfxFrameSurface1 *get_surface(QSVEncContext *q)
+{
+    QSVEncSurfaceList *list = q->pending_enc;
+
+    q->pending_enc = list->next;
+
+    if (q->pending_enc)
+        q->pending_enc->prev = NULL;
+    else
+        q->pending_enc_end = NULL;
+
+    list->prev = list->next = NULL;
+
+    return &list->surface;
+}
+
+static QSVEncBuffer *alloc_buffer(QSVEncContext *q)
+{
+    QSVEncBuffer *buf = NULL;
+    uint8_t *data     = NULL;
+    int size          = q->param.mfx.BufferSizeInKB * 1000;
+
+    if (!(buf = av_mallocz(sizeof(*buf)))) {
+        av_log(q, AV_LOG_ERROR, "av_mallocz() failed\n");
+        goto fail;
+    }
+    if (!(data = av_mallocz(size))) {
+        av_log(q, AV_LOG_ERROR, "av_mallocz() failed\n");
+        goto fail;
+    }
+
+    buf->bs.Data      = buf->data = data;
+    buf->bs.MaxLength = size;
+
+    return buf;
+
+fail:
+    av_freep(&buf);
+    av_freep(&data);
+
+    return NULL;
+}
+
+static QSVEncBuffer *get_buffer(QSVEncContext *q)
+{
+    QSVEncBuffer **pool = &q->buf_pool;
+    QSVEncBuffer *buf;
+
+    while (*pool && (*pool)->sync)
+        pool = &(*pool)->pool;
+
+    if (!(*pool))
+        if (!(*pool = alloc_buffer(q)))
+            return NULL;
+
+    buf = *pool;
+    buf->bs.DataOffset = 0;
+    buf->bs.DataLength = 0;
+    buf->prev = NULL;
+    buf->next = NULL;
+
+    return buf;
+}
+
+static void release_buffer(QSVEncBuffer *buf)
+{
+    buf->sync = 0;
+}
+
+static void free_buffer_pool(QSVEncContext *q)
+{
+    QSVEncBuffer **pool = &q->buf_pool;
+    QSVEncBuffer *buf;
+
+    while (*pool) {
+        buf = *pool;
+        *pool = buf->pool;
+        av_freep(&buf->data);
+        av_freep(&buf);
+    }
+}
+
+static void enqueue_buffer(QSVEncBuffer **head, QSVEncBuffer **tail, int *nb,
+                           QSVEncBuffer *list)
+{
+    list->prev = *tail;
+    list->next = NULL;
+
+    if (*tail)
+        (*tail)->next = list;
+    else
+        *head = list;
+
+    *tail = list;
+
+    if (nb)
+        (*nb)++;
+}
+
+static QSVEncBuffer *dequeue_buffer(QSVEncBuffer **head, QSVEncBuffer **tail,
+                                    int *nb)
+{
+    QSVEncBuffer *list = *head;
+
+    *head = (*head)->next;
+
+    if (*head)
+        (*head)->prev = NULL;
+    else
+        *tail = NULL;
+
+    if (nb)
+        (*nb)--;
+
+    list->prev = list->next = NULL;
+
+    return list;
+}
+
+static void fill_buffer_dts(QSVEncContext *q, QSVEncBuffer *list,
+                            int64_t base_dts)
+{
+    QSVEncBuffer *prev = list;
+    int64_t dts        = base_dts - q->pts_delay;
+
+    while (prev && prev->dts == AV_NOPTS_VALUE) {
+        prev->dts = dts;
+        prev = prev->prev;
+        dts -= q->pts_delay;
+    }
+}
+
+static void print_frametype(AVCodecContext *avctx, QSVEncContext *q,
+                            mfxBitstream *bs, int indent)
+{
+    char buf[1024];
+
+    buf[0] = '\0';
+
+    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+             "TimeStamp:%"PRId64", ", bs->TimeStamp);
+    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "FrameType:");
+
+    if (bs->FrameType & MFX_FRAMETYPE_I)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " I");
+    if (bs->FrameType & MFX_FRAMETYPE_P)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " P");
+    if (bs->FrameType & MFX_FRAMETYPE_B)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " B");
+    if (bs->FrameType & MFX_FRAMETYPE_S)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " S");
+    if (bs->FrameType & MFX_FRAMETYPE_REF)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " REF");
+    if (bs->FrameType & MFX_FRAMETYPE_IDR)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " IDR");
+    if (bs->FrameType & MFX_FRAMETYPE_xI)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " xI");
+    if (bs->FrameType & MFX_FRAMETYPE_xP)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " xP");
+    if (bs->FrameType & MFX_FRAMETYPE_xB)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " xB");
+    if (bs->FrameType & MFX_FRAMETYPE_xS)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " xS");
+    if (bs->FrameType & MFX_FRAMETYPE_xREF)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " xREF");
+    if (bs->FrameType & MFX_FRAMETYPE_xIDR)
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " xIDR");
+
+    av_log(q, AV_LOG_DEBUG, "%*s%s\n", 4 * indent, "", buf);
+}
+
+static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q)
+{
+    if (q->param.mfx.CodecId == MFX_CODEC_AVC) {
+        if (q->param.mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE ||
+            q->param.mfx.CodecLevel < MFX_LEVEL_AVC_21 ||
+            q->param.mfx.CodecLevel > MFX_LEVEL_AVC_41)
+            av_log(avctx, AV_LOG_WARNING,
+                   "Interlaced coding is supported"
+                   " at Main/High Profile Level 2.1-4.1\n");
+    }
+}
+
+int ff_qsv_enc_frame(AVCodecContext *avctx, QSVEncContext *q,
+                     AVPacket *pkt, const AVFrame *frame, int *got_packet)
+{
+    mfxFrameSurface1 *surf = NULL;
+    QSVEncBuffer *outbuf   = NULL;
+    int ret;
+
+    *got_packet = 0;
+
+    if (frame) {
+        if (q->first_pts == AV_NOPTS_VALUE)
+            q->first_pts = frame->pts;
+        else if (q->pts_delay == AV_NOPTS_VALUE)
+            q->pts_delay = frame->pts - q->first_pts;
+
+        if ((ret = put_surface_from_frame(avctx, q, frame)) < 0)
+            return ret;
+
+        ret = MFX_ERR_MORE_DATA;
+    } else {
+        ret = MFX_ERR_NONE;
+    }
+
+    do {
+        if (ret == MFX_ERR_MORE_DATA) {
+            if (q->pending_enc)
+                surf = get_surface(q);
+            else
+                break;
+        }
+
+        outbuf = get_buffer(q);
+
+        ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf,
+                                              &outbuf->bs, &outbuf->sync);
+
+        if (ret == MFX_WRN_DEVICE_BUSY) {
+            av_usleep(1000);
+            return 0;
+        }
+    } while (ret == MFX_ERR_MORE_DATA || ret == MFX_WRN_DEVICE_BUSY);
+
+    if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM && frame->interlaced_frame)
+        print_interlace_msg(avctx, q);
+
+    ret = ret == MFX_ERR_MORE_DATA ? 0 : ff_qsv_error(ret);
+
+    if (outbuf->sync)
+        enqueue_buffer(&q->pending_sync, &q->pending_sync_end, &q->nb_sync,
+                       outbuf);
+
+    if (q->pending_sync &&
+        (q->nb_sync >= q->req.NumFrameMin || !frame)) {
+        outbuf = dequeue_buffer(&q->pending_sync, &q->pending_sync_end,
+                                &q->nb_sync);
+
+        ret = MFXVideoCORE_SyncOperation(q->session, outbuf->sync,
+                                         SYNC_TIME_DEFAULT);
+        if ((ret = ff_qsv_error(ret)) < 0)
+            return ret;
+
+        if (outbuf->bs.FrameType & MFX_FRAMETYPE_REF ||
+            outbuf->bs.FrameType & MFX_FRAMETYPE_xREF) {
+            outbuf->dts = AV_NOPTS_VALUE;
+        } else {
+            outbuf->dts = outbuf->bs.TimeStamp;
+            fill_buffer_dts(q, q->pending_dts_end, outbuf->dts);
+        }
+
+        enqueue_buffer(&q->pending_dts, &q->pending_dts_end, NULL, outbuf);
+    }
+
+    if (q->pending_dts && q->pending_dts->dts != AV_NOPTS_VALUE) {
+        outbuf = dequeue_buffer(&q->pending_dts, &q->pending_dts_end, NULL);
+
+//        print_frametype(avctx, q, &outbuf->bs, 12);
+
+        if ((ret = ff_alloc_packet(pkt, outbuf->bs.DataLength)) < 0) {
+            release_buffer(outbuf);
+            return ret;
+        }
+
+//        pkt->dts  = outbuf->dts;
+        pkt->pts  = outbuf->bs.TimeStamp;
+        pkt->size = outbuf->bs.DataLength;
+
+        if (outbuf->bs.FrameType & MFX_FRAMETYPE_I ||
+            outbuf->bs.FrameType & MFX_FRAMETYPE_xI ||
+            outbuf->bs.FrameType & MFX_FRAMETYPE_IDR ||
+            outbuf->bs.FrameType & MFX_FRAMETYPE_xIDR)
+            pkt->flags |= AV_PKT_FLAG_KEY;
+
+        memcpy(pkt->data, outbuf->bs.Data + outbuf->bs.DataOffset,
+               outbuf->bs.DataLength);
+
+        release_buffer(outbuf);
+
+        *got_packet = 1;
+    }
+
+    return ret;
+}
+
+int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
+{
+    MFXVideoENCODE_Close(q->session);
+
+    MFXClose(q->session);
+
+    free_surface_pool(q);
+
+    free_buffer_pool(q);
+
+    return 0;
+}
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
new file mode 100644
index 0000000..7520268
--- /dev/null
+++ b/libavcodec/qsvenc.h
@@ -0,0 +1,86 @@
+/*
+ * Intel MediaSDK QSV encoder utility functions
+ *
+ * copyright (c) 2013 Yukinori Yamazoe
+ *
+ * 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 (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_QSVENC_H
+#define AVCODEC_QSVENC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <mfx/mfxvideo.h>
+
+#include "libavutil/avutil.h"
+
+
+typedef struct QSVEncSurfaceList {
+    mfxFrameSurface1 surface;
+    struct QSVEncSurfaceList *prev;
+    struct QSVEncSurfaceList *next;
+    struct QSVEncSurfaceList *pool;
+} QSVEncSurfaceList;
+
+typedef struct QSVEncBuffer {
+    uint8_t *data;
+    mfxBitstream bs;
+    mfxSyncPoint sync;
+    int64_t dts;
+    struct QSVEncBuffer *prev;
+    struct QSVEncBuffer *next;
+    struct QSVEncBuffer *pool;
+} QSVEncBuffer;
+
+typedef struct QSVEncContext {
+    AVClass *class;
+    mfxSession session;
+    mfxVideoParam param;
+    mfxFrameAllocRequest req;
+    mfxExtCodingOption extco;
+    mfxExtCodingOption2 extco2;
+    mfxExtCodingOptionSPSPPS extcospspps;
+    mfxExtBuffer *extparam[3];
+    uint8_t spspps[2][256];
+    int64_t first_pts;
+    int64_t pts_delay;
+    int async_depth;
+    int qpi;
+    int qpp;
+    int qpb;
+    int idr_interval;
+    int profile;
+    int level;
+    int preset;
+    int open_gop;
+    QSVEncSurfaceList *surf_pool;
+    QSVEncSurfaceList *pending_enc, *pending_enc_end;
+    QSVEncBuffer *buf_pool;
+    QSVEncBuffer *pending_sync, *pending_sync_end;
+    int nb_sync;
+    QSVEncBuffer *pending_dts, *pending_dts_end;
+} QSVEncContext;
+
+int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q);
+
+int ff_qsv_enc_frame(AVCodecContext *avctx, QSVEncContext *q,
+                     AVPacket *pkt, const AVFrame *frame, int *got_packet);
+
+int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q);
+
+#endif /* AVCODEC_QSVENC_H */
diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c
new file mode 100644
index 0000000..4912ed8
--- /dev/null
+++ b/libavcodec/qsvenc_h264.c
@@ -0,0 +1,134 @@
+/*
+ * Intel MediaSDK QSV based H.264 enccoder
+ *
+ * copyright (c) 2013 Yukinori Yamazoe
+ *
+ * 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 (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <mfx/mfxvideo.h>
+
+#include "avcodec.h"
+#include "internal.h"
+#include "h264.h"
+#include "qsv.h"
+#include "qsvenc.h"
+
+typedef struct QSVH264EncContext {
+    AVClass *class;
+    QSVEncContext qsv;
+} QSVH264EncContext;
+
+static av_cold int qsv_enc_init(AVCodecContext *avctx)
+{
+    QSVH264EncContext *q = avctx->priv_data;
+
+    return ff_qsv_enc_init(avctx, &q->qsv);
+}
+
+static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt,
+                         const AVFrame *frame, int *got_packet)
+{
+    QSVH264EncContext *q = avctx->priv_data;
+
+    return ff_qsv_enc_frame(avctx, &q->qsv, pkt, frame, got_packet);
+}
+
+static av_cold int qsv_enc_close(AVCodecContext *avctx)
+{
+    QSVH264EncContext *q = avctx->priv_data;
+
+    return ff_qsv_enc_close(avctx, &q->qsv);
+}
+
+#define OFFSET(x) offsetof(QSVH264EncContext, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "async_depth", "Maximum processing parallelism", 
OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, 
INT_MAX, VE },
+    { "qpi", NULL, OFFSET(qsv.qpi), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE 
},
+    { "qpp", NULL, OFFSET(qsv.qpp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE 
},
+    { "qpb", NULL, OFFSET(qsv.qpb), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE 
},
+    { "idr_interval", NULL, OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 
= 0 }, 0, INT_MAX, VE },
+    { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = 
MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" },
+    { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN     
 }, INT_MIN, INT_MAX, VE, "profile" },
+    { "baseline", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 
MFX_PROFILE_AVC_BASELINE }, INT_MIN, INT_MAX, VE, "profile" },
+    { "main"    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_MAIN    
 }, INT_MIN, INT_MAX, VE, "profile" },
+    { "high"    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_HIGH    
 }, INT_MIN, INT_MAX, VE, "profile" },
+    { "level", NULL, OFFSET(qsv.level), AV_OPT_TYPE_INT, { .i64 = 
MFX_LEVEL_UNKNOWN }, 0, INT_MAX, VE, "level" },
+    { "unknown", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_UNKNOWN }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "1"      , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_1   }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "1b"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_1b  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "11"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_11  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "12"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_12  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "13"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_13  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "2"      , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_2   }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "21"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_21  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "22"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_22  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "3"      , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_3   }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "31"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_31  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "32"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_32  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "4"      , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_4   }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "41"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_41  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "42"     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_42  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "5"      , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_5   }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "51",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_51  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "52",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LEVEL_AVC_52  }, 
INT_MIN, INT_MAX, VE, "level" },
+    { "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = 
MFX_TARGETUSAGE_BALANCED }, 0, 7, VE },
+    { "fast",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 
MFX_TARGETUSAGE_BEST_SPEED  },   INT_MIN, INT_MAX, VE, "preset" },
+    { "medium", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BALANCED  
},     INT_MIN, INT_MAX, VE, "preset" },
+    { "slow",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 
MFX_TARGETUSAGE_BEST_QUALITY  }, INT_MIN, INT_MAX, VE, "preset" },
+    { NULL },
+};
+
+static const AVClass class = {
+    .class_name = "h264_qsv encoder",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static const AVCodecDefault qsv_enc_defaults[] = {
+    { "i_qfactor", "-0.96" },
+    { "i_qoffset", "-1.0" },
+    { "b_qfactor", "1.04" },
+    { "b_qoffset", "1.0" },
+    { "coder",     "-1" },
+    { "b",         "0" },
+    { "g",         "-1" },
+    { "bf",        "-1" },
+    { "refs",      "-1" },
+    { "flags",     "+cgop" },
+    { NULL },
+};
+
+AVCodec ff_h264_qsv_encoder = {
+    .name           = "h264_qsv",
+    .long_name      = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 
part 10 (Intel Quick Sync Video acceleration)"),
+    .priv_data_size = sizeof(QSVH264EncContext),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .init           = qsv_enc_init,
+    .encode2        = qsv_enc_frame,
+    .close          = qsv_enc_close,
+    .capabilities   = CODEC_CAP_DELAY,
+    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, 
AV_PIX_FMT_NONE },
+    .priv_class     = &class,
+    .defaults       = qsv_enc_defaults,
+};
--
1.8.5.1


_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to