Browse code

Merge commit '66acb76bb0492b263215ca9b4d927a7be39ace02'

* commit '66acb76bb0492b263215ca9b4d927a7be39ace02':
lavc: add Intel libmfx-based HEVC encoder

Conflicts:
Changelog
configure
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/qsv.c
libavcodec/qsvenc.c
libavcodec/version.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2015/07/09 18:52:05
Showing 13 changed files
... ...
@@ -14,7 +14,7 @@ version <next>:
14 14
 - Go2Meeting decoding support
15 15
 - adrawgraph audio and drawgraph video filter
16 16
 - removegrain video filter
17
-- Intel QSV-accelerated MPEG-2 video encoding
17
+- Intel QSV-accelerated MPEG-2 video and HEVC encoding
18 18
 
19 19
 
20 20
 version 2.7:
... ...
@@ -2214,6 +2214,7 @@ hap_decoder_select="snappy texturedsp"
2214 2214
 hap_encoder_deps="libsnappy"
2215 2215
 hap_encoder_select="texturedspenc"
2216 2216
 hevc_decoder_select="bswapdsp cabac golomb videodsp"
2217
+hevc_qsv_encoder_select="qsvenc"
2217 2218
 huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp"
2218 2219
 huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llviddsp"
2219 2220
 iac_decoder_select="imc_decoder"
... ...
@@ -286,6 +286,7 @@ OBJS-$(CONFIG_HAP_ENCODER)             += hapenc.o
286 286
 OBJS-$(CONFIG_HEVC_DECODER)            += hevc.o hevc_mvs.o hevc_ps.o hevc_sei.o \
287 287
                                           hevc_cabac.o hevc_refs.o hevcpred.o    \
288 288
                                           hevcdsp.o hevc_filter.o hevc_parse.o
289
+OBJS-$(CONFIG_HEVC_QSV_ENCODER)        += qsvenc_hevc.o hevc_ps_enc.o hevc_parse.o
289 290
 OBJS-$(CONFIG_HNM4_VIDEO_DECODER)      += hnm4video.o
290 291
 OBJS-$(CONFIG_HQ_HQA_DECODER)          += hq_hqa.o hq_hqadata.o hq_hqadsp.o \
291 292
                                           canopus.o
... ...
@@ -569,6 +569,7 @@ void avcodec_register_all(void)
569 569
     REGISTER_ENCODER(NVENC,             nvenc);
570 570
     REGISTER_ENCODER(NVENC_H264,        nvenc_h264);
571 571
     REGISTER_ENCODER(NVENC_HEVC,        nvenc_hevc);
572
+    REGISTER_ENCODER(HEVC_QSV,          hevc_qsv);
572 573
     REGISTER_ENCODER(MPEG2_QSV,         mpeg2_qsv);
573 574
 
574 575
     /* parsers */
... ...
@@ -1054,6 +1054,9 @@ void ff_hevc_hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size);
1054 1054
 int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length,
1055 1055
                          HEVCNAL *nal);
1056 1056
 
1057
+int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id,
1058
+                           uint8_t *buf, int buf_size);
1059
+
1057 1060
 extern const uint8_t ff_hevc_qpel_extra_before[4];
1058 1061
 extern const uint8_t ff_hevc_qpel_extra_after[4];
1059 1062
 extern const uint8_t ff_hevc_qpel_extra[4];
1060 1063
new file mode 100644
... ...
@@ -0,0 +1,116 @@
0
+/*
1
+ * HEVC Parameter Set encoding
2
+ *
3
+ * This file is part of FFmpeg.
4
+ *
5
+ * FFmpeg is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * FFmpeg is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with FFmpeg; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+#include "golomb.h"
21
+#include "hevc.h"
22
+#include "put_bits.h"
23
+
24
+static void write_ptl_layer(PutBitContext *pb, PTLCommon *ptl)
25
+{
26
+    int i;
27
+
28
+    put_bits(pb, 2, ptl->profile_space);
29
+    put_bits(pb, 1, ptl->tier_flag);
30
+    put_bits(pb, 5, ptl->profile_idc);
31
+    for (i = 0; i < 32; i++)
32
+        put_bits(pb, 1, ptl->profile_compatibility_flag[i]);
33
+    put_bits(pb, 1, ptl->progressive_source_flag);
34
+    put_bits(pb, 1, ptl->interlaced_source_flag);
35
+    put_bits(pb, 1, ptl->non_packed_constraint_flag);
36
+    put_bits(pb, 1, ptl->frame_only_constraint_flag);
37
+    put_bits32(pb, 0);   // reserved
38
+    put_bits(pb, 12, 0); // reserved
39
+}
40
+
41
+static void write_ptl(PutBitContext *pb, PTL *ptl, int max_num_sub_layers)
42
+{
43
+    int i;
44
+
45
+    write_ptl_layer(pb, &ptl->general_ptl);
46
+    put_bits(pb, 8, ptl->general_ptl.level_idc);
47
+
48
+    for (i = 0; i < max_num_sub_layers - 1; i++) {
49
+        put_bits(pb, 1, ptl->sub_layer_profile_present_flag[i]);
50
+        put_bits(pb, 1, ptl->sub_layer_level_present_flag[i]);
51
+    }
52
+
53
+    if (max_num_sub_layers > 1)
54
+        for (i = max_num_sub_layers - 1; i < 8; i++)
55
+            put_bits(pb, 2, 0); // reserved
56
+
57
+    for (i = 0; i < max_num_sub_layers - 1; i++) {
58
+        if (ptl->sub_layer_profile_present_flag[i])
59
+            write_ptl_layer(pb, &ptl->sub_layer_ptl[i]);
60
+        if (ptl->sub_layer_level_present_flag[i])
61
+            put_bits(pb, 8, ptl->sub_layer_ptl[i].level_idc);
62
+    }
63
+}
64
+
65
+int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id,
66
+                           uint8_t *buf, int buf_size)
67
+{
68
+    PutBitContext pb;
69
+    int i;
70
+
71
+    init_put_bits(&pb, buf, buf_size);
72
+    put_bits(&pb,  4, id);
73
+    put_bits(&pb,  2, 3);                               // reserved
74
+    put_bits(&pb,  6, vps->vps_max_layers - 1);
75
+    put_bits(&pb,  3, vps->vps_max_sub_layers - 1);
76
+    put_bits(&pb,  1, vps->vps_temporal_id_nesting_flag);
77
+    put_bits(&pb, 16, 0xffff);                          // reserved
78
+
79
+    write_ptl(&pb, &vps->ptl, vps->vps_max_sub_layers);
80
+
81
+    put_bits(&pb, 1, vps->vps_sub_layer_ordering_info_present_flag);
82
+    for (i = vps->vps_sub_layer_ordering_info_present_flag ? 0 : vps->vps_max_layers - 1;
83
+         i < vps->vps_max_sub_layers; i++) {
84
+        set_ue_golomb(&pb, vps->vps_max_dec_pic_buffering[i] - 1);
85
+        set_ue_golomb(&pb, vps->vps_num_reorder_pics[i]);
86
+        set_ue_golomb(&pb, vps->vps_max_latency_increase[i] + 1);
87
+    }
88
+
89
+    put_bits(&pb, 6, vps->vps_max_layer_id);
90
+    set_ue_golomb(&pb, vps->vps_num_layer_sets - 1);
91
+
92
+    // writing layer_id_included_flag not supported
93
+    if (vps->vps_num_layer_sets > 1)
94
+        return AVERROR_PATCHWELCOME;
95
+
96
+    put_bits(&pb, 1, vps->vps_timing_info_present_flag);
97
+    if (vps->vps_timing_info_present_flag) {
98
+        put_bits32(&pb, vps->vps_num_units_in_tick);
99
+        put_bits32(&pb, vps->vps_time_scale);
100
+        put_bits(&pb, 1, vps->vps_poc_proportional_to_timing_flag);
101
+        if (vps->vps_poc_proportional_to_timing_flag)
102
+            set_ue_golomb(&pb, vps->vps_num_ticks_poc_diff_one - 1);
103
+
104
+        // writing HRD parameters not supported
105
+        if (vps->vps_num_hrd_parameters)
106
+            return AVERROR_PATCHWELCOME;
107
+    }
108
+
109
+    put_bits(&pb, 1, 0);    // extension flag
110
+
111
+    put_bits(&pb, 1, 1);    // stop bit
112
+    avpriv_align_put_bits(&pb);
113
+
114
+    return put_bits_count(&pb) / 8;
115
+}
... ...
@@ -19,7 +19,12 @@
19 19
  */
20 20
 
21 21
 #include <mfx/mfxvideo.h>
22
+#include <mfx/mfxplugin.h>
22 23
 
24
+#include <stdio.h>
25
+#include <string.h>
26
+
27
+#include "libavutil/avstring.h"
23 28
 #include "libavutil/error.h"
24 29
 
25 30
 #include "avcodec.h"
... ...
@@ -30,6 +35,10 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id)
30 30
     switch (codec_id) {
31 31
     case AV_CODEC_ID_H264:
32 32
         return MFX_CODEC_AVC;
33
+#if QSV_VERSION_ATLEAST(1, 8)
34
+    case AV_CODEC_ID_HEVC:
35
+        return MFX_CODEC_HEVC;
36
+#endif
33 37
     case AV_CODEC_ID_MPEG1VIDEO:
34 38
     case AV_CODEC_ID_MPEG2VIDEO:
35 39
         return MFX_CODEC_MPEG2;
... ...
@@ -154,7 +163,8 @@ static int ff_qsv_set_display_handle(AVCodecContext *avctx, mfxSession session)
154 154
  * @param avctx    ffmpeg metadata for this codec context
155 155
  * @param session  the MSDK session used
156 156
  */
157
-int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session)
157
+int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
158
+                                 const char *load_plugins)
158 159
 {
159 160
     mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
160 161
     mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
... ...
@@ -188,6 +198,45 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session)
188 188
         desc = "unknown";
189 189
     }
190 190
 
191
+    if (load_plugins && *load_plugins) {
192
+        while (*load_plugins) {
193
+            mfxPluginUID uid;
194
+            int i, err = 0;
195
+
196
+            char *plugin = av_get_token(&load_plugins, ":");
197
+            if (!plugin)
198
+                return AVERROR(ENOMEM);
199
+            if (strlen(plugin) != 2 * sizeof(uid.Data)) {
200
+                av_log(avctx, AV_LOG_ERROR, "Invalid plugin UID length\n");
201
+                err = AVERROR(EINVAL);
202
+                goto load_plugin_fail;
203
+            }
204
+
205
+            for (i = 0; i < sizeof(uid.Data); i++) {
206
+                err = sscanf(plugin + 2 * i, "%2hhx", uid.Data + i);
207
+                if (err != 1) {
208
+                    av_log(avctx, AV_LOG_ERROR, "Invalid plugin UID\n");
209
+                    err = AVERROR(EINVAL);
210
+                    goto load_plugin_fail;
211
+                }
212
+
213
+            }
214
+
215
+            ret = MFXVideoUSER_Load(*session, &uid, 1);
216
+            if (ret < 0) {
217
+                av_log(avctx, AV_LOG_ERROR, "Could not load the requested plugin: %s\n",
218
+                       plugin);
219
+                err = ff_qsv_error(ret);
220
+                goto load_plugin_fail;
221
+            }
222
+
223
+load_plugin_fail:
224
+            av_freep(&plugin);
225
+            if (err < 0)
226
+                return err;
227
+        }
228
+    }
229
+
191 230
     av_log(avctx, AV_LOG_VERBOSE,
192 231
            "Initialized an internal MFX session using %s implementation\n",
193 232
            desc);
... ...
@@ -45,6 +45,10 @@
45 45
 
46 46
 #define ASYNC_DEPTH_DEFAULT 4       // internal parallelism
47 47
 
48
+#define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
49
+    (MFX_VERSION_MAJOR > (MAJOR) ||         \
50
+     MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
51
+
48 52
 typedef struct QSVFrame {
49 53
     AVFrame *frame;
50 54
     mfxFrameSurface1 *surface;
... ...
@@ -61,6 +65,7 @@ int ff_qsv_error(int mfx_err);
61 61
 
62 62
 int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id);
63 63
 
64
-int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session);
64
+int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
65
+                                 const char *load_plugins);
65 66
 
66 67
 #endif /* AVCODEC_QSV_INTERNAL_H */
... ...
@@ -52,7 +52,7 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses
52 52
 {
53 53
     if (!session) {
54 54
         if (!q->internal_session) {
55
-            int ret = ff_qsv_init_internal_session(avctx, &q->internal_session);
55
+            int ret = ff_qsv_init_internal_session(avctx, &q->internal_session, NULL);
56 56
             if (ret < 0)
57 57
                 return ret;
58 58
         }
... ...
@@ -49,6 +49,8 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
49 49
         return AVERROR_BUG;
50 50
     q->param.mfx.CodecId = ret;
51 51
 
52
+    q->width_align = avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16;
53
+
52 54
     if (avctx->level > 0)
53 55
         q->param.mfx.CodecLevel = avctx->level;
54 56
 
... ...
@@ -74,7 +76,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
74 74
     q->param.mfx.FrameInfo.ChromaFormat   = MFX_CHROMAFORMAT_YUV420;
75 75
     q->param.mfx.FrameInfo.BitDepthLuma   = 8;
76 76
     q->param.mfx.FrameInfo.BitDepthChroma = 8;
77
-    q->param.mfx.FrameInfo.Width          = FFALIGN(avctx->width, 16);
77
+    q->param.mfx.FrameInfo.Width          = FFALIGN(avctx->width, q->width_align);
78 78
 
79 79
     if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) {
80 80
        /* A true field layout (TFF or BFF) is not important here,
... ...
@@ -86,7 +88,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
86 86
         q->param.mfx.FrameInfo.Height    = FFALIGN(avctx->height, 32);
87 87
     } else {
88 88
         q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
89
-        q->param.mfx.FrameInfo.Height    = FFALIGN(avctx->height, 16);
89
+        q->param.mfx.FrameInfo.Height    = FFALIGN(avctx->height, avctx->codec_id == AV_CODEC_ID_HEVC ? 32 : 16);
90 90
     }
91 91
 
92 92
     if (avctx->framerate.den > 0 && avctx->framerate.num > 0) {
... ...
@@ -135,15 +137,19 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
135 135
         break;
136 136
     }
137 137
 
138
-    q->extco.Header.BufferId      = MFX_EXTBUFF_CODING_OPTION;
139
-    q->extco.Header.BufferSz      = sizeof(q->extco);
140
-    q->extco.CAVLC                = avctx->coder_type == FF_CODER_TYPE_VLC ?
141
-                                    MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
138
+    // the HEVC encoder plugin currently fails if coding options
139
+    // are provided
140
+    if (avctx->codec_id != AV_CODEC_ID_HEVC) {
141
+        q->extco.Header.BufferId      = MFX_EXTBUFF_CODING_OPTION;
142
+        q->extco.Header.BufferSz      = sizeof(q->extco);
143
+        q->extco.CAVLC                = avctx->coder_type == FF_CODER_TYPE_VLC ?
144
+                                        MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
142 145
 
143
-    q->extparam[0] = (mfxExtBuffer *)&q->extco;
146
+        q->extparam[0] = (mfxExtBuffer *)&q->extco;
144 147
 
145
-    q->param.ExtParam    = q->extparam;
146
-    q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam);
148
+        q->param.ExtParam    = q->extparam;
149
+        q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam);
150
+    }
147 151
 
148 152
     return 0;
149 153
 }
... ...
@@ -210,7 +216,8 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
210 210
     }
211 211
 
212 212
     if (!q->session) {
213
-        ret = ff_qsv_init_internal_session(avctx, &q->internal_session);
213
+        ret = ff_qsv_init_internal_session(avctx, &q->internal_session,
214
+                                           q->load_plugins);
214 215
         if (ret < 0)
215 216
             return ret;
216 217
 
... ...
@@ -316,9 +323,9 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame,
316 316
     }
317 317
 
318 318
     /* make a copy if the input is not padded as libmfx requires */
319
-    if (frame->height & 31 || frame->linesize[0] & 15) {
319
+    if (frame->height & 31 || frame->linesize[0] & (q->width_align - 1)) {
320 320
         qf->frame->height = FFALIGN(frame->height, 32);
321
-        qf->frame->width  = FFALIGN(frame->width, 16);
321
+        qf->frame->width  = FFALIGN(frame->width, q->width_align);
322 322
 
323 323
         ret = ff_get_buffer(q->avctx, qf->frame, AV_GET_BUFFER_FLAG_REF);
324 324
         if (ret < 0)
... ...
@@ -42,6 +42,7 @@ typedef struct QSVEncContext {
42 42
     mfxSession internal_session;
43 43
 
44 44
     int packet_size;
45
+    int width_align;
45 46
 
46 47
     mfxVideoParam param;
47 48
     mfxFrameAllocRequest req;
... ...
@@ -56,6 +57,8 @@ typedef struct QSVEncContext {
56 56
     int preset;
57 57
     int avbr_accuracy;
58 58
     int avbr_convergence;
59
+
60
+    char *load_plugins;
59 61
 } QSVEncContext;
60 62
 
61 63
 int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q);
62 64
new file mode 100644
... ...
@@ -0,0 +1,272 @@
0
+/*
1
+ * Intel MediaSDK QSV based HEVC encoder
2
+ *
3
+ * This file is part of FFmpeg.
4
+ *
5
+ * FFmpeg is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * FFmpeg is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with FFmpeg; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+
21
+#include <stdint.h>
22
+#include <sys/types.h>
23
+
24
+#include <mfx/mfxvideo.h>
25
+
26
+#include "libavutil/common.h"
27
+#include "libavutil/opt.h"
28
+
29
+#include "avcodec.h"
30
+#include "bytestream.h"
31
+#include "get_bits.h"
32
+#include "hevc.h"
33
+#include "internal.h"
34
+#include "qsv.h"
35
+#include "qsv_internal.h"
36
+#include "qsvenc.h"
37
+
38
+enum {
39
+    LOAD_PLUGIN_NONE,
40
+    LOAD_PLUGIN_HEVC_SW,
41
+    LOAD_PLUGIN_HEVC_HW,
42
+} LoadPlugin;
43
+
44
+typedef struct QSVHEVCEncContext {
45
+    AVClass *class;
46
+    QSVEncContext qsv;
47
+    int load_plugin;
48
+} QSVHEVCEncContext;
49
+
50
+static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx)
51
+{
52
+    GetByteContext gbc;
53
+    PutByteContext pbc;
54
+
55
+    GetBitContext gb;
56
+    HEVCNAL sps_nal = { NULL };
57
+    HEVCSPS sps = { 0 };
58
+    HEVCVPS vps = { 0 };
59
+    uint8_t vps_buf[128], vps_rbsp_buf[128];
60
+    uint8_t *new_extradata;
61
+    unsigned int sps_id;
62
+    int ret, i, type, vps_size;
63
+
64
+    if (!avctx->extradata_size) {
65
+        av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx\n");
66
+        return AVERROR_UNKNOWN;
67
+    }
68
+
69
+    /* parse the SPS */
70
+    ret = ff_hevc_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, &sps_nal);
71
+    if (ret < 0) {
72
+        av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n");
73
+        return ret;
74
+    }
75
+
76
+    ret = init_get_bits8(&gb, sps_nal.data, sps_nal.size);
77
+    if (ret < 0) {
78
+        av_freep(&sps_nal.rbsp_buffer);
79
+        return ret;
80
+    }
81
+
82
+    get_bits(&gb, 1);
83
+    type = get_bits(&gb, 6);
84
+    if (type != NAL_SPS) {
85
+        av_log(avctx, AV_LOG_ERROR, "Unexpected NAL type in the extradata: %d\n",
86
+               type);
87
+        av_freep(&sps_nal.rbsp_buffer);
88
+        return AVERROR_INVALIDDATA;
89
+    }
90
+    get_bits(&gb, 9);
91
+
92
+    ret = ff_hevc_parse_sps(&sps, &gb, &sps_id, 0, NULL, avctx);
93
+    av_freep(&sps_nal.rbsp_buffer);
94
+    if (ret < 0) {
95
+        av_log(avctx, AV_LOG_ERROR, "Error parsing the SPS\n");
96
+        return ret;
97
+    }
98
+
99
+    /* generate the VPS */
100
+    vps.vps_max_layers     = 1;
101
+    vps.vps_max_sub_layers = sps.max_sub_layers;
102
+    memcpy(&vps.ptl, &sps.ptl, sizeof(vps.ptl));
103
+    vps.vps_sub_layer_ordering_info_present_flag = 1;
104
+    for (i = 0; i < MAX_SUB_LAYERS; i++) {
105
+        vps.vps_max_dec_pic_buffering[i] = sps.temporal_layer[i].max_dec_pic_buffering;
106
+        vps.vps_num_reorder_pics[i]      = sps.temporal_layer[i].num_reorder_pics;
107
+        vps.vps_max_latency_increase[i]  = sps.temporal_layer[i].max_latency_increase;
108
+    }
109
+
110
+    vps.vps_num_layer_sets                  = 1;
111
+    vps.vps_timing_info_present_flag        = sps.vui.vui_timing_info_present_flag;
112
+    vps.vps_num_units_in_tick               = sps.vui.vui_num_units_in_tick;
113
+    vps.vps_time_scale                      = sps.vui.vui_time_scale;
114
+    vps.vps_poc_proportional_to_timing_flag = sps.vui.vui_poc_proportional_to_timing_flag;
115
+    vps.vps_num_ticks_poc_diff_one          = sps.vui.vui_num_ticks_poc_diff_one_minus1 + 1;
116
+
117
+    /* generate the encoded RBSP form of the VPS */
118
+    ret = ff_hevc_encode_nal_vps(&vps, sps.vps_id, vps_rbsp_buf, sizeof(vps_rbsp_buf));
119
+    if (ret < 0) {
120
+        av_log(avctx, AV_LOG_ERROR, "Error writing the VPS\n");
121
+        return ret;
122
+    }
123
+
124
+    /* escape and add the startcode */
125
+    bytestream2_init(&gbc, vps_rbsp_buf, ret);
126
+    bytestream2_init_writer(&pbc, vps_buf, sizeof(vps_buf));
127
+
128
+    bytestream2_put_be32(&pbc, 1);              // startcode
129
+    bytestream2_put_byte(&pbc, NAL_VPS << 1);   // NAL
130
+    bytestream2_put_byte(&pbc, 1);              // header
131
+
132
+    while (bytestream2_get_bytes_left(&gbc)) {
133
+        uint32_t b = bytestream2_peek_be24(&gbc);
134
+        if (b <= 3) {
135
+            bytestream2_put_be24(&pbc, 3);
136
+            bytestream2_skip(&gbc, 2);
137
+        } else
138
+            bytestream2_put_byte(&pbc, bytestream2_get_byte(&gbc));
139
+    }
140
+
141
+    vps_size = bytestream2_tell_p(&pbc);
142
+    new_extradata = av_mallocz(vps_size + avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
143
+    if (!new_extradata)
144
+        return AVERROR(ENOMEM);
145
+    memcpy(new_extradata, vps_buf, vps_size);
146
+    memcpy(new_extradata + vps_size, avctx->extradata, avctx->extradata_size);
147
+
148
+    av_freep(&avctx->extradata);
149
+    avctx->extradata       = new_extradata;
150
+    avctx->extradata_size += vps_size;
151
+
152
+    return 0;
153
+}
154
+
155
+static av_cold int qsv_enc_init(AVCodecContext *avctx)
156
+{
157
+    QSVHEVCEncContext *q = avctx->priv_data;
158
+    int ret;
159
+
160
+    if (q->load_plugin != LOAD_PLUGIN_NONE) {
161
+        static const char *uid_hevcenc_sw = "2fca99749fdb49aeb121a5b63ef568f7";
162
+        static const char *uid_hevcenc_hw = "e5400a06c74d41f5b12d430bbaa23d0b";
163
+
164
+        if (q->qsv.load_plugins[0]) {
165
+            av_log(avctx, AV_LOG_WARNING,
166
+                   "load_plugins is not empty, but load_plugin is not set to 'none'."
167
+                   "The load_plugin value will be ignored.\n");
168
+        } else {
169
+            av_freep(&q->qsv.load_plugins);
170
+
171
+            if (q->load_plugin == LOAD_PLUGIN_HEVC_SW)
172
+                q->qsv.load_plugins = av_strdup(uid_hevcenc_sw);
173
+            else
174
+                q->qsv.load_plugins = av_strdup(uid_hevcenc_hw);
175
+
176
+            if (!q->qsv.load_plugins)
177
+                return AVERROR(ENOMEM);
178
+        }
179
+    }
180
+
181
+    ret = ff_qsv_enc_init(avctx, &q->qsv);
182
+    if (ret < 0)
183
+        return ret;
184
+
185
+    ret = generate_fake_vps(&q->qsv, avctx);
186
+    if (ret < 0) {
187
+        ff_qsv_enc_close(avctx, &q->qsv);
188
+        return ret;
189
+    }
190
+
191
+    return 0;
192
+}
193
+
194
+static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt,
195
+                         const AVFrame *frame, int *got_packet)
196
+{
197
+    QSVHEVCEncContext *q = avctx->priv_data;
198
+
199
+    return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet);
200
+}
201
+
202
+static av_cold int qsv_enc_close(AVCodecContext *avctx)
203
+{
204
+    QSVHEVCEncContext *q = avctx->priv_data;
205
+
206
+    return ff_qsv_enc_close(avctx, &q->qsv);
207
+}
208
+
209
+#define OFFSET(x) offsetof(QSVHEVCEncContext, x)
210
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
211
+static const AVOption options[] = {
212
+    { "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VE },
213
+    { "avbr_accuracy",    "Accuracy of the AVBR ratecontrol",    OFFSET(qsv.avbr_accuracy),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
214
+    { "avbr_convergence", "Convergence of the AVBR ratecontrol", OFFSET(qsv.avbr_convergence), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
215
+
216
+    { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_SW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VE, "load_plugin" },
217
+    { "none",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE },    0, 0, VE, "load_plugin" },
218
+    { "hevc_sw",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VE, "load_plugin" },
219
+    { "hevc_hw",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VE, "load_plugin" },
220
+
221
+    { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session",
222
+        OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VE },
223
+
224
+    { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" },
225
+    { "unknown", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN      }, INT_MIN, INT_MAX,     VE, "profile" },
226
+    { "main",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN    }, INT_MIN, INT_MAX,     VE, "profile" },
227
+    { "main10",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN10  }, INT_MIN, INT_MAX,     VE, "profile" },
228
+    { "mainsp",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAINSP  }, INT_MIN, INT_MAX,     VE, "profile" },
229
+
230
+    { "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_BALANCED }, 0, 7,   VE, "preset" },
231
+    { "fast",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_SPEED  },   INT_MIN, INT_MAX, VE, "preset" },
232
+    { "medium", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BALANCED  },     INT_MIN, INT_MAX, VE, "preset" },
233
+    { "slow",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY  }, INT_MIN, INT_MAX, VE, "preset" },
234
+
235
+    { NULL },
236
+};
237
+
238
+static const AVClass class = {
239
+    .class_name = "hevc_qsv encoder",
240
+    .item_name  = av_default_item_name,
241
+    .option     = options,
242
+    .version    = LIBAVUTIL_VERSION_INT,
243
+};
244
+
245
+static const AVCodecDefault qsv_enc_defaults[] = {
246
+    { "b",         "1M"    },
247
+    { "refs",      "0"     },
248
+    // same as the x264 default
249
+    { "g",         "250"   },
250
+    { "bf",        "3"     },
251
+
252
+    { "flags",     "+cgop" },
253
+    { NULL },
254
+};
255
+
256
+AVCodec ff_hevc_qsv_encoder = {
257
+    .name           = "hevc_qsv",
258
+    .long_name      = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"),
259
+    .priv_data_size = sizeof(QSVHEVCEncContext),
260
+    .type           = AVMEDIA_TYPE_VIDEO,
261
+    .id             = AV_CODEC_ID_HEVC,
262
+    .init           = qsv_enc_init,
263
+    .encode2        = qsv_enc_frame,
264
+    .close          = qsv_enc_close,
265
+    .capabilities   = CODEC_CAP_DELAY,
266
+    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
267
+                                                    AV_PIX_FMT_QSV,
268
+                                                    AV_PIX_FMT_NONE },
269
+    .priv_class     = &class,
270
+    .defaults       = qsv_enc_defaults,
271
+};
... ...
@@ -29,8 +29,8 @@
29 29
 #include "libavutil/version.h"
30 30
 
31 31
 #define LIBAVCODEC_VERSION_MAJOR 56
32
-#define LIBAVCODEC_VERSION_MINOR  46
33
-#define LIBAVCODEC_VERSION_MICRO 102
32
+#define LIBAVCODEC_VERSION_MINOR  47
33
+#define LIBAVCODEC_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
36 36
                                                LIBAVCODEC_VERSION_MINOR, \