]> git.sesse.net Git - ffmpeg/commitdiff
Merge commit 'cca5e4f040971db6de0bfe6968f00c021d8a9c42'
authorJames Almer <jamrial@gmail.com>
Fri, 13 Apr 2018 23:34:23 +0000 (20:34 -0300)
committerJames Almer <jamrial@gmail.com>
Fri, 13 Apr 2018 23:34:23 +0000 (20:34 -0300)
* commit 'cca5e4f040971db6de0bfe6968f00c021d8a9c42':
  qsv: adding Multi Frame Encode support

Merged-by: James Almer <jamrial@gmail.com>
1  2 
libavcodec/qsv.c
libavcodec/qsv_internal.h
libavcodec/qsvenc.c
libavcodec/qsvenc.h
libavcodec/qsvenc_h264.c
libavfilter/qsvvpp.c
libavfilter/qsvvpp.h
libavfilter/vf_deinterlace_qsv.c
libavfilter/vf_scale_qsv.c
libavutil/hwcontext_qsv.c

diff --combined libavcodec/qsv.c
index 6d1fbde452ae0bb77fe57a7fbd443e234852b096,a9b3c59f3ae875e7deefd47d09995e3be2f2a7df..45e1c25c68f69daf862f6cd75c5a592b86dbfced
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Intel MediaSDK QSV encoder/decoder shared code
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -617,10 -617,12 +617,12 @@@ int ff_qsv_init_session_device(AVCodecC
                                        "Error setting a HW handle");
      }
  
-     err = MFXJoinSession(parent_session, session);
-     if (err != MFX_ERR_NONE)
-         return ff_qsv_print_error(avctx, err,
-                                   "Error joining session");
+     if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+         err = MFXJoinSession(parent_session, session);
+         if (err != MFX_ERR_NONE)
+             return ff_qsv_print_error(avctx, err,
+                                       "Error joining session");
+     }
  
      ret = qsv_load_plugins(session, load_plugins, avctx);
      if (ret < 0) {
index 5c33f187f401b3bb8a3e6babf7b132f254644889,3cd8f1872b2deb5f529a20060b698332d7f971aa..394c55888314ebd39ba87713267b5ad5078157d1
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Intel MediaSDK QSV encoder/decoder shared code
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  
  #define ASYNC_DEPTH_DEFAULT 4       // internal parallelism
  
 +#define QSV_MAX_ENC_PAYLOAD 2       // # of mfxEncodeCtrl payloads supported
 +
  #define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
      (MFX_VERSION_MAJOR > (MAJOR) ||         \
       MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
  
+ #define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \
+     (MFX_VERSION.Major > (MAJOR)) ||                           \
+     (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR))
  typedef struct QSVMid {
      AVBufferRef *hw_frames_ref;
      mfxHDL handle;
@@@ -50,7 -52,6 +54,7 @@@
  typedef struct QSVFrame {
      AVFrame *frame;
      mfxFrameSurface1 surface;
 +    mfxEncodeCtrl enc_ctrl;
      mfxExtDecodedFrameInfo dec_info;
      mfxExtBuffer *ext_param;
  
@@@ -74,7 -75,7 +78,7 @@@ typedef struct QSVFramesContext 
  } QSVFramesContext;
  
  /**
 - * Convert a libmfx error code into a libav error code.
 + * Convert a libmfx error code into an ffmpeg error code.
   */
  int ff_qsv_map_error(mfxStatus mfx_err, const char **desc);
  
diff --combined libavcodec/qsvenc.c
index afb953eb11645fae622f0da52cf5db8c01438b13,a8b446c5bd91136f1f36782b1f6451b2de900e82..3ce5ffecd5b8d21705d84e013b6be9e0a1a25510
@@@ -4,20 -4,20 +4,20 @@@
   * copyright (c) 2013 Yukinori Yamazoe
   * copyright (c) 2015 Anton Khirnov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -32,7 -32,6 +32,7 @@@
  #include "libavutil/log.h"
  #include "libavutil/time.h"
  #include "libavutil/imgutils.h"
 +#include "libavcodec/bytestream.h"
  
  #include "avcodec.h"
  #include "internal.h"
@@@ -136,6 -135,9 +136,6 @@@ static void dump_video_param(AVCodecCon
  #if QSV_HAVE_CO2
      mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1];
  #endif
 -#if QSV_HAVE_CO3 && QSV_HAVE_QVBR
 -    mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
 -#endif
  
      av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
             print_profile(info->CodecProfile), info->CodecLevel);
                 info->ICQQuality, co2->LookAheadDepth);
      }
  #endif
 -#if QSV_HAVE_QVBR
 -    else if (info->RateControlMethod == MFX_RATECONTROL_QVBR) {
 -        av_log(avctx, AV_LOG_VERBOSE, "QVBRQuality: %"PRIu16"\n",
 -               co3->QVBRQuality);
 -    }
 -#endif
  
      av_log(avctx, AV_LOG_VERBOSE, "NumSlice: %"PRIu16"; NumRefFrame: %"PRIu16"\n",
             info->NumSlice, info->NumRefFrame);
@@@ -270,7 -278,7 +270,7 @@@ static int select_rc_mode(AVCodecContex
      const char *rc_desc;
      mfxU16      rc_mode;
  
 -    int want_la     = q->la_depth >= 10;
 +    int want_la     = q->look_ahead;
      int want_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE);
      int want_vcm    = q->vcm;
  
@@@ -552,11 -560,11 +552,11 @@@ static int init_video_param(AVCodecCont
  #if QSV_HAVE_LA
      case MFX_RATECONTROL_LA:
          q->param.mfx.TargetKbps  = avctx->bit_rate / 1000;
 -        q->extco2.LookAheadDepth = q->la_depth;
 +        q->extco2.LookAheadDepth = q->look_ahead_depth;
          break;
  #if QSV_HAVE_ICQ
      case MFX_RATECONTROL_LA_ICQ:
 -        q->extco2.LookAheadDepth = q->la_depth;
 +        q->extco2.LookAheadDepth = q->look_ahead_depth;
      case MFX_RATECONTROL_ICQ:
          q->param.mfx.ICQQuality  = avctx->global_quality;
          break;
          q->extco.Header.BufferId      = MFX_EXTBUFF_CODING_OPTION;
          q->extco.Header.BufferSz      = sizeof(q->extco);
  
 +        q->extco.PicTimingSEI         = q->pic_timing_sei ?
 +                                        MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
 +
          if (q->rdo >= 0)
              q->extco.RateDistortionOpt = q->rdo > 0 ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF;
  
@@@ -631,7 -636,7 +631,7 @@@ FF_ENABLE_DEPRECATION_WARNING
  #endif
  
  #if QSV_HAVE_LA_DS
 -            q->extco2.LookAheadDS = q->la_ds;
 +            q->extco2.LookAheadDS = q->look_ahead_downsampling;
  #endif
  
  #if QSV_HAVE_BREF_TYPE
@@@ -651,6 -656,20 +651,20 @@@ FF_ENABLE_DEPRECATION_WARNING
  
              q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2;
          }
+ #endif
+ #if QSV_HAVE_MF
+         if (avctx->codec_id == AV_CODEC_ID_H264) {
+             mfxVersion    ver;
+             ret = MFXQueryVersion(q->session,&ver);
+             if (ret >= MFX_ERR_NONE && QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+                 q->extmfp.Header.BufferId     = MFX_EXTBUFF_MULTI_FRAME_PARAM;
+                 q->extmfp.Header.BufferSz     = sizeof(q->extmfp);
+                 q->extmfp.MFMode = q->mfmode;
+                 av_log(avctx,AV_LOG_VERBOSE,"MFMode:%d\n", q->extmfp.MFMode);
+                 q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extmfp;
+             }
+         }
  #endif
      }
  
@@@ -706,12 -725,21 +720,12 @@@ static int qsv_retrieve_enc_params(AVCo
          .Header.BufferSz = sizeof(co2),
      };
  #endif
 -#if QSV_HAVE_CO3
 -    mfxExtCodingOption3 co3 = {
 -        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3,
 -        .Header.BufferSz = sizeof(co3),
 -    };
 -#endif
  
      mfxExtBuffer *ext_buffers[] = {
          (mfxExtBuffer*)&extradata,
          (mfxExtBuffer*)&co,
  #if QSV_HAVE_CO2
          (mfxExtBuffer*)&co2,
 -#endif
 -#if QSV_HAVE_CO3
 -        (mfxExtBuffer*)&co3,
  #endif
      };
  
@@@ -961,23 -989,11 +975,23 @@@ int ff_qsv_enc_init(AVCodecContext *avc
      return 0;
  }
  
 +static void free_encoder_ctrl_payloads(mfxEncodeCtrl* enc_ctrl)
 +{
 +    if (enc_ctrl) {
 +        int i;
 +        for (i = 0; i < enc_ctrl->NumPayload && i < QSV_MAX_ENC_PAYLOAD; i++) {
 +            av_free(enc_ctrl->Payload[i]);
 +        }
 +        enc_ctrl->NumPayload = 0;
 +    }
 +}
 +
  static void clear_unused_frames(QSVEncContext *q)
  {
      QSVFrame *cur = q->work_frames;
      while (cur) {
          if (cur->used && !cur->surface.Data.Locked) {
 +            free_encoder_ctrl_payloads(&cur->enc_ctrl);
              av_frame_unref(cur->frame);
              cur->used = 0;
          }
@@@ -1012,11 -1028,6 +1026,11 @@@ static int get_free_frame(QSVEncContex
          av_freep(&frame);
          return AVERROR(ENOMEM);
      }
 +    frame->enc_ctrl.Payload = av_mallocz(sizeof(mfxPayload*) * QSV_MAX_ENC_PAYLOAD);
 +    if (!frame->enc_ctrl.Payload) {
 +        av_freep(&frame);
 +        return AVERROR(ENOMEM);
 +    }
      *last = frame;
  
      *f = frame;
  }
  
  static int submit_frame(QSVEncContext *q, const AVFrame *frame,
 -                        mfxFrameSurface1 **surface)
 +                        QSVFrame **new_frame)
  {
      QSVFrame *qf;
      int ret;
  
      qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000});
  
 -    *surface = &qf->surface;
 +    *new_frame = qf;
  
      return 0;
  }
@@@ -1117,21 -1128,15 +1131,21 @@@ static int encode_frame(AVCodecContext 
  
      mfxFrameSurface1 *surf = NULL;
      mfxSyncPoint *sync     = NULL;
 +    QSVFrame *qsv_frame = NULL;
 +    mfxEncodeCtrl* enc_ctrl = NULL;
      int ret;
  
      if (frame) {
 -        ret = submit_frame(q, frame, &surf);
 +        ret = submit_frame(q, frame, &qsv_frame);
          if (ret < 0) {
              av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n");
              return ret;
          }
      }
 +    if (qsv_frame) {
 +        surf = &qsv_frame->surface;
 +        enc_ctrl = &qsv_frame->enc_ctrl;
 +    }
  
      ret = av_new_packet(&new_pkt, q->packet_size);
      if (ret < 0) {
      bs->Data      = new_pkt.data;
      bs->MaxLength = new_pkt.size;
  
 +    if (q->set_encode_ctrl_cb) {
 +        q->set_encode_ctrl_cb(avctx, frame, &qsv_frame->enc_ctrl);
 +    }
 +
      sync = av_mallocz(sizeof(*sync));
      if (!sync) {
          av_freep(&bs);
      }
  
      do {
 -        ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf, bs, sync);
 +        ret = MFXVideoENCODE_EncodeFrameAsync(q->session, enc_ctrl, surf, bs, sync);
          if (ret == MFX_WRN_DEVICE_BUSY)
 -            av_usleep(1);
 +            av_usleep(500);
      } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_WRN_IN_EXECUTION);
  
      if (ret > 0)
@@@ -1278,7 -1279,6 +1292,7 @@@ int ff_qsv_enc_close(AVCodecContext *av
      while (cur) {
          q->work_frames = cur->next;
          av_frame_free(&cur->frame);
 +        av_free(cur->enc_ctrl.Payload);
          av_freep(&cur);
          cur = q->work_frames;
      }
diff --combined libavcodec/qsvenc.h
index 080f6f08d374a3eab37d00865eace8cdd5bb94b3,a7fc57bb48b851e2597c235a9d4a0736f6856609..d48272224c3b7cbc59d7daa26fd9bec3a57965ae
@@@ -3,20 -3,20 +3,20 @@@
   *
   * copyright (c) 2013 Yukinori Yamazoe
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #define QSV_HAVE_ICQ    QSV_VERSION_ATLEAST(1, 8)
  #define QSV_HAVE_VCM    QSV_VERSION_ATLEAST(1, 8)
  #define QSV_HAVE_QVBR   QSV_VERSION_ATLEAST(1, 11)
+ #define QSV_HAVE_MF     0
  #else
  #define QSV_HAVE_AVBR   0
  #define QSV_HAVE_ICQ    0
  #define QSV_HAVE_VCM    0
  #define QSV_HAVE_QVBR   0
+ #define QSV_HAVE_MF     QSV_VERSION_ATLEAST(1, 25)
  #endif
  
  #if !QSV_HAVE_LA_DS
 +#define MFX_LOOKAHEAD_DS_UNKNOWN 0
  #define MFX_LOOKAHEAD_DS_OFF 0
  #define MFX_LOOKAHEAD_DS_2x 0
  #define MFX_LOOKAHEAD_DS_4x 0
  #endif
  
  #define QSV_COMMON_OPTS \
 -{ "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VE },  \
 -{ "avbr_accuracy",    "Accuracy of the AVBR ratecontrol",    OFFSET(qsv.avbr_accuracy),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },     \
 -{ "avbr_convergence", "Convergence of the AVBR ratecontrol", OFFSET(qsv.avbr_convergence), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },     \
 -{ "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_BALANCED }, 0, 7,   VE, "preset" },                             \
 -{ "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" },                             \
 -{ "la_depth", "Number of frames to analyze before encoding.", OFFSET(qsv.la_depth), AV_OPT_TYPE_INT, { .i64 = 9 },   9, 100, VE, "la_depth" },  \
 -{ "unset", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 9 }, INT_MIN, INT_MAX,                                                       VE, "la_depth" },  \
 -{ "la_ds", "Downscaling factor for the frames saved for the lookahead analysis", OFFSET(qsv.la_ds), AV_OPT_TYPE_INT,                            \
 -                    { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, MFX_LOOKAHEAD_DS_UNKNOWN, MFX_LOOKAHEAD_DS_4x, VE, "la_ds" },                          \
 -{ "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, INT_MIN, INT_MAX,                                     VE, "la_ds" }, \
 -{ "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_OFF }, INT_MIN, INT_MAX,                                          VE, "la_ds" }, \
 -{ "2x", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_2x }, INT_MIN, INT_MAX,                                            VE, "la_ds" }, \
 -{ "4x", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_4x }, INT_MIN, INT_MAX,                                            VE, "la_ds" }, \
 -{ "vcm",      "Use the video conferencing mode ratecontrol",  OFFSET(qsv.vcm),      AV_OPT_TYPE_INT, { .i64 = 0  },  0, 1,         VE },        \
 -{ "rdo",            "Enable rate distortion optimization",    OFFSET(qsv.rdo),            AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE }, \
 -{ "max_frame_size", "Maximum encoded frame size in bytes",    OFFSET(qsv.max_frame_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, \
 -{ "max_slice_size", "Maximum encoded slice size in bytes",    OFFSET(qsv.max_slice_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, \
 -{ "bitrate_limit",  "Toggle bitrate limitations",             OFFSET(qsv.bitrate_limit),  AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE }, \
 -{ "mbbrc",          "MB level bitrate control",               OFFSET(qsv.mbbrc),          AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE }, \
 -{ "extbrc",         "Extended bitrate control",               OFFSET(qsv.extbrc),         AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE }, \
 -{ "adaptive_i",     "Adaptive I-frame placement",             OFFSET(qsv.adaptive_i),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE }, \
 -{ "adaptive_b",     "Adaptive B-frame placement",             OFFSET(qsv.adaptive_b),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE }, \
 -{ "b_strategy",     "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),    AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },
 -
 +{ "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VE },                          \
 +{ "avbr_accuracy",    "Accuracy of the AVBR ratecontrol",    OFFSET(qsv.avbr_accuracy),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },                             \
 +{ "avbr_convergence", "Convergence of the AVBR ratecontrol", OFFSET(qsv.avbr_convergence), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },                             \
 +{ "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_BALANCED }, MFX_TARGETUSAGE_BEST_QUALITY, MFX_TARGETUSAGE_BEST_SPEED,   VE, "preset" }, \
 +{ "veryfast",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_SPEED  },   INT_MIN, INT_MAX, VE, "preset" },                                                \
 +{ "faster",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_6  },            INT_MIN, INT_MAX, VE, "preset" },                                                \
 +{ "fast",        NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_5  },            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_3  },            INT_MIN, INT_MAX, VE, "preset" },                                                \
 +{ "slower",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_2  },            INT_MIN, INT_MAX, VE, "preset" },                                                \
 +{ "veryslow",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY  }, INT_MIN, INT_MAX, VE, "preset" },                                                \
 +{ "vcm",      "Use the video conferencing mode ratecontrol",  OFFSET(qsv.vcm),      AV_OPT_TYPE_INT, { .i64 = 0  },  0, 1,         VE },                                \
 +{ "rdo",            "Enable rate distortion optimization",    OFFSET(qsv.rdo),            AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 +{ "max_frame_size", "Maximum encoded frame size in bytes",    OFFSET(qsv.max_frame_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE },                         \
 +{ "max_slice_size", "Maximum encoded slice size in bytes",    OFFSET(qsv.max_slice_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE },                         \
 +{ "bitrate_limit",  "Toggle bitrate limitations",             OFFSET(qsv.bitrate_limit),  AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 +{ "mbbrc",          "MB level bitrate control",               OFFSET(qsv.mbbrc),          AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 +{ "extbrc",         "Extended bitrate control",               OFFSET(qsv.extbrc),         AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 +{ "adaptive_i",     "Adaptive I-frame placement",             OFFSET(qsv.adaptive_i),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 +{ "adaptive_b",     "Adaptive B-frame placement",             OFFSET(qsv.adaptive_b),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 +{ "b_strategy",     "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),    AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 +
 +typedef int SetEncodeCtrlCB (AVCodecContext *avctx,
 +                             const AVFrame *frame, mfxEncodeCtrl* enc_ctrl);
  typedef struct QSVEncContext {
      AVCodecContext *avctx;
  
  #if QSV_HAVE_CO2
      mfxExtCodingOption2 extco2;
  #endif
+ #if QSV_HAVE_MF
+     mfxExtMultiFrameParam   extmfp;
+     mfxExtMultiFrameControl extmfc;
+ #endif
      mfxExtOpaqueSurfaceAlloc opaque_alloc;
      mfxFrameSurface1       **opaque_surfaces;
      AVBufferRef             *opaque_alloc_buf;
  
-     mfxExtBuffer  *extparam_internal[2 + QSV_HAVE_CO2];
+     mfxExtBuffer  *extparam_internal[2 + QSV_HAVE_CO2 + (QSV_HAVE_MF * 2)];
      int         nb_extparam_internal;
  
      mfxExtBuffer **extparam;
      int preset;
      int avbr_accuracy;
      int avbr_convergence;
 -    int la_depth;
 -    int la_ds;
 +    int pic_timing_sei;
 +    int look_ahead;
 +    int look_ahead_depth;
 +    int look_ahead_downsampling;
      int vcm;
      int rdo;
      int max_frame_size;
      int int_ref_qp_delta;
      int recovery_point_sei;
  
 +    int a53_cc;
++
+ #if QSV_HAVE_MF
+     int mfmode;
+ #endif
      char *load_plugins;
 +    SetEncodeCtrlCB *set_encode_ctrl_cb;
  } QSVEncContext;
  
  int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q);
diff --combined libavcodec/qsvenc_h264.c
index 0fe29c27300a06629f17f3c0b07a014b4c8d5ec2,ae00ff8d54650ac8e6fd5bab1e5e8e6fc163340b..718bf9cb2165808396963dcb57c248ce2600c0ab
@@@ -3,20 -3,20 +3,20 @@@
   *
   * copyright (c) 2013 Yukinori Yamazoe
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -40,45 -40,10 +40,45 @@@ typedef struct QSVH264EncContext 
      QSVEncContext qsv;
  } QSVH264EncContext;
  
 +static int qsv_h264_set_encode_ctrl(AVCodecContext *avctx,
 +                                    const AVFrame *frame, mfxEncodeCtrl* enc_ctrl)
 +{
 +    QSVH264EncContext *qh264 = avctx->priv_data;
 +    QSVEncContext *q = &qh264->qsv;
 +
 +    if (q->a53_cc && frame) {
 +        mfxPayload* payload;
 +        mfxU8* sei_data;
 +        size_t sei_size;
 +        int res;
 +
 +        res = ff_alloc_a53_sei(frame, sizeof(mfxPayload) + 2, (void**)&payload, &sei_size);
 +        if (res < 0 || !payload)
 +            return res;
 +
 +        sei_data = (mfxU8*)(payload + 1);
 +        // SEI header
 +        sei_data[0] = 4;
 +        sei_data[1] = (mfxU8)sei_size; // size of SEI data
 +        // SEI data filled in by ff_alloc_a53_sei
 +
 +        payload->BufSize = sei_size + 2;
 +        payload->NumBit = payload->BufSize * 8;
 +        payload->Type = 4;
 +        payload->Data = sei_data;
 +
 +        enc_ctrl->NumExtParam = 0;
 +        enc_ctrl->NumPayload = 1;
 +        enc_ctrl->Payload[0] = payload;
 +    }
 +    return 0;
 +}
 +
  static av_cold int qsv_enc_init(AVCodecContext *avctx)
  {
      QSVH264EncContext *q = avctx->priv_data;
  
 +    q->qsv.set_encode_ctrl_cb = qsv_h264_set_encode_ctrl;
      return ff_qsv_enc_init(avctx, &q->qsv);
  }
  
@@@ -104,24 -69,9 +104,24 @@@ static const AVOption options[] = 
  
      { "cavlc",          "Enable CAVLC",                           OFFSET(qsv.cavlc),          AV_OPT_TYPE_INT, { .i64 = 0 },   0,          1, VE },
      { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
 +    { "pic_timing_sei",    "Insert picture timing SEI with pic_struct_syntax element", OFFSET(qsv.pic_timing_sei), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE },
      { "single_sei_nal_unit",    "Put all the SEI messages into one NALU",        OFFSET(qsv.single_sei_nal_unit),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },
      { "max_dec_frame_buffering", "Maximum number of frames buffered in the DPB", OFFSET(qsv.max_dec_frame_buffering), AV_OPT_TYPE_INT, { .i64 = 0 },   0, UINT16_MAX, VE },
  
 +#if QSV_HAVE_LA
 +    { "look_ahead",       "Use VBR algorithm with look ahead",    OFFSET(qsv.look_ahead),       AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
 +    { "look_ahead_depth", "Depth of look ahead in number frames", OFFSET(qsv.look_ahead_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, VE },
 +#endif
 +#if QSV_HAVE_LA_DS
 +    { "look_ahead_downsampling", "Downscaling factor for the frames saved for the lookahead analysis", OFFSET(qsv.look_ahead_downsampling),
 +                                          AV_OPT_TYPE_INT,   { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, MFX_LOOKAHEAD_DS_UNKNOWN, MFX_LOOKAHEAD_DS_2x, VE, "look_ahead_downsampling" },
 +    { "unknown"                , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, INT_MIN, INT_MAX,     VE, "look_ahead_downsampling" },
 +    { "auto"                   , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, INT_MIN, INT_MAX,     VE, "look_ahead_downsampling" },
 +    { "off"                    , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_OFF     }, INT_MIN, INT_MAX,     VE, "look_ahead_downsampling" },
 +    { "2x"                     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_2x      }, INT_MIN, INT_MAX,     VE, "look_ahead_downsampling" },
 +    { "4x"                     , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_4x      }, INT_MIN, INT_MAX,     VE, "look_ahead_downsampling" },
 +#endif
 +
      { "int_ref_type", "Intra refresh type",                                      OFFSET(qsv.int_ref_type),            AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" },
          { "none",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" },
          { "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" },
      { "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" },
  
 +    { "a53cc" , "Use A53 Closed Captions (if available)", OFFSET(qsv.a53_cc), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, VE},
 +
      { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE},
  
+ #if QSV_HAVE_MF
+     { "mfmode", "Multi-Frame Mode", OFFSET(qsv.mfmode), AV_OPT_TYPE_INT, { .i64 = MFX_MF_AUTO }, 0, INT_MAX, VE },
+ #endif
      { NULL },
  };
  
diff --combined libavfilter/qsvvpp.c
index f32b46dcc0875614d03c05b029cc3487aa2ae319,f704517aee10376323d9eab8cfc8958005476acb..732cf56a6acc68edaa16f0c471755a7503e7808b
@@@ -1,18 -1,18 +1,18 @@@
  /*
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -515,9 -515,12 +515,12 @@@ static int init_vpp_session(AVFilterCon
          if (ret != MFX_ERR_NONE)
              return AVERROR_UNKNOWN;
      }
-     ret = MFXJoinSession(device_hwctx->session, s->session);
-     if (ret != MFX_ERR_NONE)
-         return AVERROR_UNKNOWN;
+     if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+         ret = MFXJoinSession(device_hwctx->session, s->session);
+         if (ret != MFX_ERR_NONE)
+             return AVERROR_UNKNOWN;
+     }
  
      if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
          s->opaque_alloc.In.Surfaces   = s->surface_ptrs_in;
diff --combined libavfilter/qsvvpp.h
index d720c9ba425450f3b041169b211e9638890bf0f4,d25ea69e5c0eb46c53330fdda98801c8f61671e1..ff02b64c411a43c677a59054198b805bfed78721
@@@ -1,18 -1,18 +1,18 @@@
  /*
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #define FF_INLINK_IDX(link)  ((int)((link)->dstpad - (link)->dst->input_pads))
  #define FF_OUTLINK_IDX(link) ((int)((link)->srcpad - (link)->src->output_pads))
  
+ #define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
+     (MFX_VERSION_MAJOR > (MAJOR) ||         \
+      MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
+ #define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \
+     (MFX_VERSION.Major > (MAJOR)) ||                           \
+     (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR))
  typedef struct QSVVPPContext QSVVPPContext;
  
  typedef struct QSVVPPCrop {
index 897e6bd622135f52c1da8a2fb6e0f63bc247f349,bb26a4dbfef686e730e235acfb13d39a1de0074f..c9e76c6056a1a8157fc87ba8e48a2749563ebf46
@@@ -1,18 -1,18 +1,18 @@@
  /*
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -35,6 -35,7 +35,7 @@@
  #include "libavutil/opt.h"
  #include "libavutil/pixdesc.h"
  #include "libavutil/time.h"
+ #include "libavfilter/qsvvpp.h"
  
  #include "avfilter.h"
  #include "formats.h"
@@@ -76,6 -77,7 +77,6 @@@ typedef struct QSVDeintContext 
  
      int64_t last_pts;
  
 -    int got_output_frame;
      int eof;
  
      /* option for Deinterlacing algorithm to be used */
@@@ -114,10 -116,8 +115,10 @@@ static int qsvdeint_query_formats(AVFil
          AV_PIX_FMT_QSV, AV_PIX_FMT_NONE,
      };
      AVFilterFormats *pix_fmts  = ff_make_format_list(pixel_formats);
 +    int ret;
  
 -    ff_set_common_formats(ctx, pix_fmts);
 +    if ((ret = ff_set_common_formats(ctx, pix_fmts)) < 0)
 +        return ret;
  
      return 0;
  }
@@@ -215,6 -215,12 +216,12 @@@ static int init_out_session(AVFilterCon
              return AVERROR_UNKNOWN;
      }
  
+     if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+         err = MFXJoinSession(device_hwctx->session, s->session);
+         if (err != MFX_ERR_NONE)
+             return AVERROR_UNKNOWN;
+     }
      memset(&par, 0, sizeof(par));
  
      s->deint_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING;
@@@ -533,12 -539,18 +540,12 @@@ static int qsvdeint_filter_frame(AVFilt
  static int qsvdeint_request_frame(AVFilterLink *outlink)
  {
      AVFilterContext *ctx = outlink->src;
 -    QSVDeintContext   *s = ctx->priv;
 -    int ret = 0;
  
 -    s->got_output_frame = 0;
 -    while (ret >= 0 && !s->got_output_frame)
 -        ret = ff_request_frame(ctx->inputs[0]);
 -
 -    return ret;
 +    return ff_request_frame(ctx->inputs[0]);
  }
  
  #define OFFSET(x) offsetof(QSVDeintContext, x)
 -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
 +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  static const AVOption options[] = {
      { "mode", "set deinterlace mode", OFFSET(mode),   AV_OPT_TYPE_INT, {.i64 = MFX_DEINTERLACING_ADVANCED}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"},
      { "bob",   "bob algorithm",                  0, AV_OPT_TYPE_CONST,      {.i64 = MFX_DEINTERLACING_BOB}, MFX_DEINTERLACING_BOB, MFX_DEINTERLACING_ADVANCED, FLAGS, "mode"},
index c6f683e6fa396afd359a36c9f25e915d8bf24ba0,381844cdc4a73e9658b9134e30f549393ff24f91..d1189942d126c9de1b13f04974693ed82244433d
@@@ -1,18 -1,18 +1,18 @@@
  /*
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -36,6 -36,7 +36,7 @@@
  #include "libavutil/opt.h"
  #include "libavutil/pixdesc.h"
  #include "libavutil/time.h"
+ #include "libavfilter/qsvvpp.h"
  
  #include "avfilter.h"
  #include "formats.h"
@@@ -151,10 -152,8 +152,10 @@@ static int qsvscale_query_formats(AVFil
          AV_PIX_FMT_QSV, AV_PIX_FMT_NONE,
      };
      AVFilterFormats *pix_fmts  = ff_make_format_list(pixel_formats);
 +    int ret;
  
 -    ff_set_common_formats(ctx, pix_fmts);
 +    if ((ret = ff_set_common_formats(ctx, pix_fmts)) < 0)
 +        return ret;
  
      return 0;
  }
@@@ -315,6 -314,12 +316,12 @@@ static int init_out_session(AVFilterCon
              return AVERROR_UNKNOWN;
      }
  
+     if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+         err = MFXJoinSession(device_hwctx->session, s->session);
+             if (err != MFX_ERR_NONE)
+                 return AVERROR_UNKNOWN;
+     }
      memset(&par, 0, sizeof(par));
  
      if (opaque) {
@@@ -577,7 -582,7 +584,7 @@@ fail
  }
  
  #define OFFSET(x) offsetof(QSVScaleContext, x)
 -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
 +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  static const AVOption options[] = {
      { "w",      "Output video width",  OFFSET(w_expr),     AV_OPT_TYPE_STRING, { .str = "iw"   }, .flags = FLAGS },
      { "h",      "Output video height", OFFSET(h_expr),     AV_OPT_TYPE_STRING, { .str = "ih"   }, .flags = FLAGS },
index d58461b2264ab9e26625a0aad48436ec3918b757,b3eb4a3ea65805aabda403e50b442ead593ae210..250091c4e85a26b16d018663a12c35ae3f403216
@@@ -1,18 -1,18 +1,18 @@@
  /*
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg 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,
 + * FFmpeg 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
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -1058,6 -1058,11 +1058,11 @@@ static int qsv_device_derive_from_child
          goto fail;
      }
  
+     ret = MFXQueryVersion(hwctx->session,&ver);
+     if (ret == MFX_ERR_NONE) {
+         av_log(ctx, AV_LOG_VERBOSE, "MFX compile/runtime API: %d.%d/%d.%d\n",
+                MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor);
+     }
      return 0;
  
  fail: