1From c39ca2bf72f7b83d5810c142beba97abcfbc7147 Mon Sep 17 00:00:00 2001
2From: hassene <hassene.tmar@intel.com>
3Date: Fri, 15 Feb 2019 17:43:54 -0800
4Subject: [PATCH] Add ability for ffmpeg to run svt vp9
5
6Signed-off-by: hassene <hassene.tmar@intel.com>
7Signed-off-by: Jing Sun <jing.a.sun@intel.com>
8Signed-off-by: Austin Hu <austin.hu@intel.com>
9Signed-off-by: Guo Jiansheng <jiansheng.guo@intel.com>
10---
11 configure                 |   4 +
12 libavcodec/Makefile       |   1 +
13 libavcodec/allcodecs.c    |   1 +
14 libavcodec/avcodec.h      |   2 +
15 libavcodec/libsvt_vp9.c   | 481 ++++++++++++++++++++++++++++++++++++++
16 libavformat/dashenc.c     |  49 +++-
17 libavformat/ivfenc.c      |  34 ++-
18 libavformat/matroskaenc.c | 108 ++++++++-
19 libavformat/movenc.c      |  42 +++-
20 9 files changed, 712 insertions(+), 10 deletions(-)
21 create mode 100644 libavcodec/libsvt_vp9.c
22
23diff --git a/configure b/configure
24index 34c2adb4a4..ea125e68ae 100755
25--- a/configure
26+++ b/configure
27@@ -278,6 +278,7 @@ External library support:
28   --enable-libvorbis       enable Vorbis en/decoding via libvorbis,
29                            native implementation exists [no]
30   --enable-libvpx          enable VP8 and VP9 de/encoding via libvpx [no]
31+  --enable-libsvtvp9       enable VP9 encoding via svt [no]
32   --enable-libwavpack      enable wavpack encoding via libwavpack [no]
33   --enable-libwebp         enable WebP encoding via libwebp [no]
34   --enable-libx264         enable H.264 encoding via x264 [no]
35@@ -1800,6 +1801,7 @@ EXTERNAL_LIBRARY_LIST="
36     libv4l2
37     libvorbis
38     libvpx
39+    libsvtvp9
40     libwavpack
41     libwebp
42     libxml2
43@@ -3201,6 +3203,7 @@ libvpx_vp8_decoder_deps="libvpx"
44 libvpx_vp8_encoder_deps="libvpx"
45 libvpx_vp9_decoder_deps="libvpx"
46 libvpx_vp9_encoder_deps="libvpx"
47+libsvt_vp9_encoder_deps="libsvtvp9"
48 libwavpack_encoder_deps="libwavpack"
49 libwavpack_encoder_select="audio_frame_queue"
50 libwebp_encoder_deps="libwebp"
51@@ -6299,6 +6302,7 @@ enabled libvpx            && {
52     fi
53 }
54
55+enabled libsvtvp9         && require_pkg_config libsvtvp9 SvtVp9Enc EbSvtVp9Enc.h eb_vp9_svt_init_handle
56 enabled libwavpack        && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput  -lwavpack
57 enabled libwebp           && {
58     enabled libwebp_encoder      && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion
59diff --git a/libavcodec/Makefile b/libavcodec/Makefile
60index 3cd73fbcc6..cc756acfe7 100644
61--- a/libavcodec/Makefile
62+++ b/libavcodec/Makefile
63@@ -1001,6 +1001,7 @@ OBJS-$(CONFIG_LIBVPX_VP8_DECODER)         += libvpxdec.o
64 OBJS-$(CONFIG_LIBVPX_VP8_ENCODER)         += libvpxenc.o
65 OBJS-$(CONFIG_LIBVPX_VP9_DECODER)         += libvpxdec.o libvpx.o
66 OBJS-$(CONFIG_LIBVPX_VP9_ENCODER)         += libvpxenc.o libvpx.o
67+OBJS-$(CONFIG_LIBSVT_VP9_ENCODER)         += libsvt_vp9.o
68 OBJS-$(CONFIG_LIBWAVPACK_ENCODER)         += libwavpackenc.o
69 OBJS-$(CONFIG_LIBWEBP_ENCODER)            += libwebpenc_common.o libwebpenc.o
70 OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER)       += libwebpenc_common.o libwebpenc_animencoder.o
71diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
72index d2f9a39ce5..205333db96 100644
73--- a/libavcodec/allcodecs.c
74+++ b/libavcodec/allcodecs.c
75@@ -716,6 +716,7 @@ extern AVCodec ff_libvpx_vp8_encoder;
76 extern AVCodec ff_libvpx_vp8_decoder;
77 extern AVCodec ff_libvpx_vp9_encoder;
78 extern AVCodec ff_libvpx_vp9_decoder;
79+extern AVCodec ff_libsvt_vp9_encoder;
80 extern AVCodec ff_libwavpack_encoder;
81 /* preferred over libwebp */
82 extern AVCodec ff_libwebp_anim_encoder;
83diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
84index d234271c5b..0d903571b3 100644
85--- a/libavcodec/avcodec.h
86+++ b/libavcodec/avcodec.h
87@@ -1527,6 +1527,8 @@ typedef struct AVPacket {
88  */
89 #define AV_PKT_FLAG_DISPOSABLE 0x0010
90
91+#define AV_PKT_FLAG_SVT_VP9_EXT_ON  0x10000 // Indicating SVT VP9 frame header ext on
92+#define AV_PKT_FLAG_SVT_VP9_EXT_OFF 0x20000 // Indicating SVT VP9 frame header ext off
93
94 enum AVSideDataParamChangeFlags {
95     AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT  = 0x0001,
96diff --git a/libavcodec/libsvt_vp9.c b/libavcodec/libsvt_vp9.c
97new file mode 100644
98index 0000000000..037467366e
99--- /dev/null
100+++ b/libavcodec/libsvt_vp9.c
101@@ -0,0 +1,481 @@
102+/*
103+* Scalable Video Technology for VP9 encoder library plugin
104+*
105+* Copyright (c) 2018 Intel Corporation
106+*
107+* This file is part of FFmpeg.
108+*
109+* FFmpeg is free software; you can redistribute it and/or
110+* modify it under the terms of the GNU Lesser General Public
111+* License as published by the Free Software Foundation; either
112+* version 2.1 of the License, or (at your option) any later version.
113+*
114+* FFmpeg is distributed in the hope that it will be useful,
115+* but WITHOUT ANY WARRANTY; without even the implied warranty of
116+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
117+* Lesser General Public License for more details.
118+*
119+* You should have received a copy of the GNU Lesser General Public
120+* License along with this program; if not, write to the Free Software
121+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
122+*/
123+
124+#include <stdint.h>
125+#include "EbSvtVp9ErrorCodes.h"
126+#include "EbSvtVp9Enc.h"
127+
128+#include "libavutil/common.h"
129+#include "libavutil/frame.h"
130+#include "libavutil/opt.h"
131+
132+#include "internal.h"
133+#include "avcodec.h"
134+
135+typedef enum eos_status {
136+    EOS_NOT_REACHED = 0,
137+    EOS_REACHED,
138+    EOS_TOTRIGGER
139+}EOS_STATUS;
140+
141+typedef struct SvtContext {
142+    AVClass     *class;
143+
144+    EbSvtVp9EncConfiguration    enc_params;
145+    EbComponentType            *svt_handle;
146+
147+    EbBufferHeaderType         *in_buf;
148+    int                         raw_size;
149+
150+    AVBufferPool* pool;
151+
152+    EOS_STATUS eos_flag;
153+
154+    // User options.
155+    int enc_mode;
156+    int rc_mode;
157+    int tune;
158+    int qp;
159+
160+    int forced_idr;
161+
162+    int level;
163+
164+    int base_layer_switch_mode;
165+} SvtContext;
166+
167+static int error_mapping(EbErrorType svt_ret)
168+{
169+    int err;
170+
171+    switch (svt_ret) {
172+    case EB_ErrorInsufficientResources:
173+        err = AVERROR(ENOMEM);
174+        break;
175+
176+    case EB_ErrorUndefined:
177+    case EB_ErrorInvalidComponent:
178+    case EB_ErrorBadParameter:
179+        err = AVERROR(EINVAL);
180+        break;
181+
182+    case EB_ErrorDestroyThreadFailed:
183+    case EB_ErrorSemaphoreUnresponsive:
184+    case EB_ErrorDestroySemaphoreFailed:
185+    case EB_ErrorCreateMutexFailed:
186+    case EB_ErrorMutexUnresponsive:
187+    case EB_ErrorDestroyMutexFailed:
188+        err = AVERROR_EXTERNAL;
189+            break;
190+
191+    case EB_NoErrorEmptyQueue:
192+        err = AVERROR(EAGAIN);
193+
194+    case EB_ErrorNone:
195+        err = 0;
196+        break;
197+
198+    default:
199+        err = AVERROR_UNKNOWN;
200+    }
201+
202+    return err;
203+}
204+
205+static void free_buffer(SvtContext *svt_enc)
206+{
207+    if (svt_enc->in_buf) {
208+        EbSvtEncInput *in_data = (EbSvtEncInput *)svt_enc->in_buf->p_buffer;
209+        av_freep(&in_data);
210+        av_freep(&svt_enc->in_buf);
211+    }
212+    av_buffer_pool_uninit(&svt_enc->pool);
213+}
214+
215+static int alloc_buffer(EbSvtVp9EncConfiguration *config, SvtContext *svt_enc)
216+{
217+    const size_t luma_size_8bit    =
218+        config->source_width * config->source_height;
219+    const size_t luma_size_10bit   =
220+        (config->encoder_bit_depth > 8) ? luma_size_8bit : 0;
221+
222+    EbSvtEncInput *in_data;
223+
224+    svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3 / 2;
225+
226+    // allocate buffer for in and out
227+    svt_enc->in_buf           = av_mallocz(sizeof(*svt_enc->in_buf));
228+    if (!svt_enc->in_buf)
229+        goto failed;
230+
231+
232+    svt_enc->in_buf->p_buffer = (unsigned char *)av_mallocz(sizeof(*in_data));
233+    if (!svt_enc->in_buf->p_buffer)
234+        goto failed;
235+
236+    svt_enc->in_buf->size        = sizeof(*svt_enc->in_buf);
237+    svt_enc->in_buf->p_app_private  = NULL;
238+
239+    svt_enc->pool = av_buffer_pool_init(svt_enc->raw_size, NULL);
240+    if (!svt_enc->pool)
241+        goto failed;
242+
243+    return 0;
244+
245+failed:
246+    free_buffer(svt_enc);
247+    return AVERROR(ENOMEM);
248+}
249+
250+static int config_enc_params(EbSvtVp9EncConfiguration *param,
251+                             AVCodecContext *avctx)
252+{
253+    SvtContext *svt_enc = avctx->priv_data;
254+    int             ret;
255+    int        ten_bits = 0;
256+
257+    param->source_width     = avctx->width;
258+    param->source_height    = avctx->height;
259+
260+    if (avctx->pix_fmt == AV_PIX_FMT_YUV420P10LE) {
261+        av_log(avctx, AV_LOG_DEBUG , "Encoder 10 bits depth input\n");
262+        // Disable Compressed 10-bit format default
263+        ten_bits = 1;
264+    }
265+
266+    // Update param from options
267+    param->enc_mode                 = svt_enc->enc_mode;
268+    param->level                    = svt_enc->level;
269+    param->rate_control_mode        = svt_enc->rc_mode;
270+    param->tune                     = svt_enc->tune;
271+    param->base_layer_switch_mode   = svt_enc->base_layer_switch_mode;
272+    param->qp                       = svt_enc->qp;
273+
274+    param->target_bit_rate          = avctx->bit_rate;
275+    if (avctx->gop_size > 0)
276+        param->intra_period  = avctx->gop_size - 1;
277+
278+    if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
279+        param->frame_rate_numerator     = avctx->framerate.num;
280+        param->frame_rate_denominator   = avctx->framerate.den * avctx->ticks_per_frame;
281+    } else {
282+        param->frame_rate_numerator     = avctx->time_base.den;
283+        param->frame_rate_denominator   = avctx->time_base.num * avctx->ticks_per_frame;
284+    }
285+
286+    if (param->rate_control_mode) {
287+        param->max_qp_allowed       = avctx->qmax;
288+        param->min_qp_allowed       = avctx->qmin;
289+    }
290+
291+    if (ten_bits) {
292+        param->encoder_bit_depth        = 10;
293+    }
294+
295+    ret = alloc_buffer(param, svt_enc);
296+
297+    return ret;
298+}
299+
300+static void read_in_data(EbSvtVp9EncConfiguration *config,
301+                         const AVFrame *frame,
302+                         EbBufferHeaderType *headerPtr)
303+{
304+    uint8_t is16bit = config->encoder_bit_depth > 8;
305+    uint64_t luma_size =
306+        (uint64_t)config->source_width * config->source_height<< is16bit;
307+    EbSvtEncInput *in_data = (EbSvtEncInput *)headerPtr->p_buffer;
308+
309+    // support yuv420p and yuv420p010
310+    in_data->luma = frame->data[0];
311+    in_data->cb   = frame->data[1];
312+    in_data->cr   = frame->data[2];
313+
314+    // stride info
315+    in_data->y_stride  = frame->linesize[0] >> is16bit;
316+    in_data->cb_stride = frame->linesize[1] >> is16bit;
317+    in_data->cr_stride = frame->linesize[2] >> is16bit;
318+
319+    headerPtr->n_filled_len   += luma_size * 3/2u;
320+}
321+
322+static av_cold int eb_enc_init(AVCodecContext *avctx)
323+{
324+    SvtContext   *svt_enc = avctx->priv_data;
325+    EbErrorType svt_ret;
326+
327+    svt_enc->eos_flag = EOS_NOT_REACHED;
328+
329+    svt_ret = eb_vp9_svt_init_handle(&svt_enc->svt_handle, svt_enc, &svt_enc->enc_params);
330+    if (svt_ret != EB_ErrorNone) {
331+        av_log(avctx, AV_LOG_ERROR, "Error init encoder handle\n");
332+        goto failed;
333+    }
334+
335+    svt_ret = config_enc_params(&svt_enc->enc_params, avctx);
336+    if (svt_ret != EB_ErrorNone) {
337+        av_log(avctx, AV_LOG_ERROR, "Error configure encoder parameters\n");
338+        goto failed_init_handle;
339+    }
340+
341+    svt_ret = eb_vp9_svt_enc_set_parameter(svt_enc->svt_handle, &svt_enc->enc_params);
342+    if (svt_ret != EB_ErrorNone) {
343+        av_log(avctx, AV_LOG_ERROR, "Error setting encoder parameters\n");
344+        goto failed_init_handle;
345+    }
346+
347+    svt_ret = eb_vp9_init_encoder(svt_enc->svt_handle);
348+    if (svt_ret != EB_ErrorNone) {
349+        av_log(avctx, AV_LOG_ERROR, "Error init encoder\n");
350+        goto failed_init_handle;
351+    }
352+
353+ //   if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
354+ //       EbBufferHeaderType* headerPtr;
355+ //       headerPtr->size       = sizeof(headerPtr);
356+ //       headerPtr->n_filled_len  = 0; /* in/out */
357+ //       headerPtr->p_buffer     = av_malloc(10 * 1024 * 1024);
358+ //       headerPtr->n_alloc_len   = (10 * 1024 * 1024);
359+ //
360+ //       if (!headerPtr->p_buffer) {
361+ //           av_log(avctx, AV_LOG_ERROR,
362+ //                  "Cannot allocate buffer size %d.\n", headerPtr->n_alloc_len);
363+ //           svt_ret = EB_ErrorInsufficientResources;
364+ //           goto failed_init_enc;
365+ //       }
366+ //
367+ //       svt_ret = eb_svt_enc_stream_header(svt_enc->svt_handle, &headerPtr);
368+ //       if (svt_ret != EB_ErrorNone) {
369+ //           av_log(avctx, AV_LOG_ERROR, "Error when build stream header.\n");
370+ //           av_freep(&headerPtr->p_buffer);
371+ //           goto failed_init_enc;
372+ //       }
373+ //
374+ //       avctx->extradata_size = headerPtr->n_filled_len;
375+ //       avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
376+ //       if (!avctx->extradata) {
377+ //           av_log(avctx, AV_LOG_ERROR,
378+ //                  "Cannot allocate VP9 header of size %d.\n", avctx->extradata_size);
379+ //           av_freep(&headerPtr->p_buffer);
380+ //           svt_ret = EB_ErrorInsufficientResources;
381+ //           goto failed_init_enc;
382+ //       }
383+ //       memcpy(avctx->extradata, headerPtr->p_buffer, avctx->extradata_size);
384+ //
385+ //       av_freep(&headerPtr->p_buffer);
386+ //   }
387+    return 0;
388+
389+//failed_init_enc:
390+//    eb_deinit_encoder(svt_enc->svt_handle);
391+failed_init_handle:
392+    eb_vp9_deinit_handle(svt_enc->svt_handle);
393+failed:
394+    free_buffer(svt_enc);
395+    return error_mapping(svt_ret);
396+}
397+
398+static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame)
399+{
400+    SvtContext           *svt_enc = avctx->priv_data;
401+    EbBufferHeaderType  *headerPtr = svt_enc->in_buf;
402+
403+    if (!frame) {
404+        EbBufferHeaderType headerPtrLast;
405+        headerPtrLast.n_alloc_len   = 0;
406+        headerPtrLast.n_filled_len  = 0;
407+        headerPtrLast.n_tick_count  = 0;
408+        headerPtrLast.p_app_private = NULL;
409+        headerPtrLast.p_buffer     = NULL;
410+        headerPtrLast.flags      = EB_BUFFERFLAG_EOS;
411+
412+        eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, &headerPtrLast);
413+        svt_enc->eos_flag = EOS_REACHED;
414+        av_log(avctx, AV_LOG_DEBUG, "Finish sending frames!!!\n");
415+        return 0;
416+    }
417+
418+    read_in_data(&svt_enc->enc_params, frame, headerPtr);
419+
420+    headerPtr->flags         = 0;
421+    headerPtr->p_app_private = NULL;
422+    headerPtr->pts           = frame->pts;
423+    switch (frame->pict_type) {
424+    case AV_PICTURE_TYPE_I:
425+        headerPtr->pic_type = svt_enc->forced_idr > 0 ? EB_IDR_PICTURE : EB_I_PICTURE;
426+        break;
427+    case AV_PICTURE_TYPE_P:
428+        headerPtr->pic_type = EB_P_PICTURE;
429+        break;
430+    case AV_PICTURE_TYPE_B:
431+        headerPtr->pic_type = EB_B_PICTURE;
432+        break;
433+    default:
434+        headerPtr->pic_type = EB_INVALID_PICTURE;
435+        break;
436+    }
437+    eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, headerPtr);
438+
439+    return 0;
440+}
441+
442+static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
443+{
444+    SvtContext  *svt_enc = avctx->priv_data;
445+    EbBufferHeaderType   *headerPtr;
446+    EbErrorType          svt_ret;
447+    AVBufferRef *ref;
448+
449+    if (EOS_TOTRIGGER == svt_enc->eos_flag) {
450+        pkt = NULL;
451+        return AVERROR_EOF;
452+    }
453+
454+    svt_ret = eb_vp9_svt_get_packet(svt_enc->svt_handle, &headerPtr, svt_enc->eos_flag);
455+    if (svt_ret == EB_NoErrorEmptyQueue)
456+        return AVERROR(EAGAIN);
457+
458+    ref = av_buffer_pool_get(svt_enc->pool);
459+    if (!ref) {
460+        av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n");
461+        eb_vp9_svt_release_out_buffer(&headerPtr);
462+        return AVERROR(ENOMEM);
463+    }
464+    pkt->buf = ref;
465+    pkt->data = ref->data;
466+
467+    memcpy(pkt->data, headerPtr->p_buffer, headerPtr->n_filled_len);
468+    pkt->size = headerPtr->n_filled_len;
469+    pkt->pts  = headerPtr->pts;
470+    pkt->dts  = headerPtr->dts;
471+    if (headerPtr->pic_type == EB_IDR_PICTURE)
472+        pkt->flags |= AV_PKT_FLAG_KEY;
473+    if (headerPtr->pic_type == EB_NON_REF_PICTURE)
474+        pkt->flags |= AV_PKT_FLAG_DISPOSABLE;
475+
476+    if (headerPtr->flags & EB_BUFFERFLAG_SHOW_EXT)
477+        pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_ON;
478+    else
479+        pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_OFF;
480+
481+    if (EB_BUFFERFLAG_EOS & headerPtr->flags)
482+        svt_enc->eos_flag = EOS_TOTRIGGER;
483+
484+    eb_vp9_svt_release_out_buffer(&headerPtr);
485+    return 0;
486+}
487+
488+static av_cold int eb_enc_close(AVCodecContext *avctx)
489+{
490+    SvtContext *svt_enc = avctx->priv_data;
491+
492+    eb_vp9_deinit_encoder(svt_enc->svt_handle);
493+    eb_vp9_deinit_handle(svt_enc->svt_handle);
494+
495+    free_buffer(svt_enc);
496+
497+    return 0;
498+}
499+
500+#define OFFSET(x) offsetof(SvtContext, x)
501+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
502+static const AVOption options[] = {
503+    { "preset", "Encoding preset [1, 1]",
504+      OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = 9 }, 0, 9, VE },
505+
506+    { "level", "Set level (level_idc)", OFFSET(level),
507+      AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xff, VE, "level" },
508+
509+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
510+      { .i64 = value }, 0, 0, VE, "level"
511+        { LEVEL("1",   10) },
512+        { LEVEL("2",   20) },
513+        { LEVEL("2.1", 21) },
514+        { LEVEL("3",   30) },
515+        { LEVEL("3.1", 31) },
516+        { LEVEL("4",   40) },
517+        { LEVEL("4.1", 41) },
518+        { LEVEL("5",   50) },
519+        { LEVEL("5.1", 51) },
520+        { LEVEL("5.2", 52) },
521+        { LEVEL("6",   60) },
522+        { LEVEL("6.1", 61) },
523+        { LEVEL("6.2", 62) },
524+#undef LEVEL
525+
526+    { "tune", "Tune mode", OFFSET(tune),
527+      AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE , "tune"},
528+        { "vq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 },  INT_MIN, INT_MAX, VE, "tune" },
529+        { "ssim", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 },  INT_MIN, INT_MAX, VE, "tune" },
530+        { "vmaf", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 },  INT_MIN, INT_MAX, VE, "tune" },
531+
532+    { "rc", "Bit rate control mode", OFFSET(rc_mode),
533+      AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE , "rc"},
534+        { "cqp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 },  INT_MIN, INT_MAX, VE, "rc" },
535+        { "vbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 },  INT_MIN, INT_MAX, VE, "rc" },
536+        { "cbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 },  INT_MIN, INT_MAX, VE, "rc" },
537+
538+    { "qp", "QP value for intra frames", OFFSET(qp),
539+      AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 51, VE },
540+
541+    { "bl_mode", "Random Access Prediction Structure type setting", OFFSET(base_layer_switch_mode),
542+      AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
543+
544+    { "forced-idr", "If forcing keyframes, force them as IDR frames.", OFFSET(forced_idr),
545+      AV_OPT_TYPE_BOOL,   { .i64 = 0 }, -1, 1, VE },
546+
547+    {NULL},
548+};
549+
550+static const AVClass class = {
551+    .class_name = "libsvt_vp9",
552+    .item_name  = av_default_item_name,
553+    .option     = options,
554+    .version    = LIBAVUTIL_VERSION_INT,
555+};
556+
557+static const AVCodecDefault eb_enc_defaults[] = {
558+    { "b",         "7M"    },
559+    { "flags",     "-cgop" },
560+    { "qmin",      "10"    },
561+    { "qmax",      "48"    },
562+    { NULL },
563+};
564+
565+AVCodec ff_libsvt_vp9_encoder = {
566+    .name           = "libsvt_vp9",
567+    .long_name      = NULL_IF_CONFIG_SMALL("SVT-VP9(Scalable Video Technology for VP9) encoder"),
568+    .priv_data_size = sizeof(SvtContext),
569+    .type           = AVMEDIA_TYPE_VIDEO,
570+    .id             = AV_CODEC_ID_VP9,
571+    .init           = eb_enc_init,
572+    .send_frame     = eb_send_frame,
573+    .receive_packet = eb_receive_packet,
574+    .close          = eb_enc_close,
575+    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,
576+    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P,
577+                                                    AV_PIX_FMT_NONE },
578+    .priv_class     = &class,
579+    .defaults       = eb_enc_defaults,
580+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
581+    .wrapper_name   = "libsvt_vp9",
582+};
583diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
584index 24d43c34ea..ba47bd6413 100644
585--- a/libavformat/dashenc.c
586+++ b/libavformat/dashenc.c
587@@ -1823,6 +1823,48 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
588     return ret;
589 }
590
591+static int dash_write_packet_vp9(AVFormatContext *s, AVPacket *pkt)
592+{
593+    int ret;
594+    if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) {
595+        uint8_t *saved_data = pkt->data;
596+        int      saved_size = pkt->size;
597+        int64_t  saved_pts  = pkt->pts;
598+
599+        // Main frame
600+        pkt->data = saved_data;
601+        pkt->size = saved_size - 4;
602+        pkt->pts = saved_pts;
603+        ret = dash_write_packet(s, pkt);
604+
605+        // Latter 4 one-byte repeated frames
606+        pkt->data = saved_data + saved_size - 4;
607+        pkt->size = 1;
608+        pkt->pts = saved_pts - 2;
609+        ret = dash_write_packet(s, pkt);
610+
611+        pkt->data = saved_data + saved_size - 3;
612+        pkt->size = 1;
613+        pkt->pts = saved_pts - 1;
614+        ret = dash_write_packet(s, pkt);
615+
616+        pkt->data = saved_data + saved_size - 2;
617+        pkt->size = 1;
618+        pkt->pts = saved_pts;
619+        ret = dash_write_packet(s, pkt);
620+
621+        pkt->data = saved_data + saved_size - 1;
622+        pkt->size = 1;
623+        pkt->pts = saved_pts + 1;
624+        ret = dash_write_packet(s, pkt);
625+    }
626+    else{
627+        ret = dash_write_packet(s, pkt);
628+    }
629+
630+    return ret;
631+}
632+
633 static int dash_write_trailer(AVFormatContext *s)
634 {
635     DASHContext *c = s->priv_data;
636@@ -1870,6 +1912,11 @@ static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt
637     DASHContext *c = s->priv_data;
638     OutputStream *os = &c->streams[avpkt->stream_index];
639     AVFormatContext *oc = os->ctx;
640+
641+    if ((avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) ||
642+        (avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF))
643+        return 0;
644+
645     if (oc->oformat->check_bitstream) {
646         int ret;
647         AVPacket pkt = *avpkt;
648@@ -1942,7 +1989,7 @@ AVOutputFormat ff_dash_muxer = {
649     .flags          = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE,
650     .init           = dash_init,
651     .write_header   = dash_write_header,
652-    .write_packet   = dash_write_packet,
653+    .write_packet   = dash_write_packet_vp9,
654     .write_trailer  = dash_write_trailer,
655     .deinit         = dash_free,
656     .check_bitstream = dash_check_bitstream,
657diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c
658index adf72117e9..05f08131a6 100644
659--- a/libavformat/ivfenc.c
660+++ b/libavformat/ivfenc.c
661@@ -63,9 +63,33 @@ static int ivf_write_packet(AVFormatContext *s, AVPacket *pkt)
662     AVIOContext *pb = s->pb;
663     IVFEncContext *ctx = s->priv_data;
664
665-    avio_wl32(pb, pkt->size);
666-    avio_wl64(pb, pkt->pts);
667-    avio_write(pb, pkt->data, pkt->size);
668+    if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) {
669+        avio_wl32(pb, pkt->size - 4);
670+        avio_wl64(pb, pkt->pts);
671+        avio_write(pb, pkt->data, pkt->size - 4);
672+
673+        avio_wl32(pb, 1);
674+        avio_wl64(pb, pkt->pts - 2);
675+        avio_write(pb, pkt->data + pkt->size - 4, 1);
676+
677+        avio_wl32(pb, 1);
678+        avio_wl64(pb, pkt->pts - 1);
679+        avio_write(pb, pkt->data + pkt->size - 3, 1);
680+
681+        avio_wl32(pb, 1);
682+        avio_wl64(pb, pkt->pts);
683+        avio_write(pb, pkt->data + pkt->size - 2, 1);
684+
685+        avio_wl32(pb, 1);
686+        avio_wl64(pb, pkt->pts + 1);
687+        avio_write(pb, pkt->data + pkt->size - 1, 1);
688+    }
689+    else {
690+        avio_wl32(pb, pkt->size);
691+        avio_wl64(pb, pkt->pts);
692+        avio_write(pb, pkt->data, pkt->size);
693+    }
694+
695     if (ctx->frame_cnt)
696         ctx->sum_delta_pts += pkt->pts - ctx->last_pts;
697     ctx->frame_cnt++;
698@@ -95,6 +119,10 @@ static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
699     int ret = 1;
700     AVStream *st = s->streams[pkt->stream_index];
701
702+    if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) ||
703+       (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF))
704+        return 0;
705+
706     if (st->codecpar->codec_id == AV_CODEC_ID_VP9)
707         ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
708     else if (st->codecpar->codec_id == AV_CODEC_ID_AV1)
709diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
710index cef504fa05..de8e3872c1 100644
711--- a/libavformat/matroskaenc.c
712+++ b/libavformat/matroskaenc.c
713@@ -161,6 +161,9 @@ typedef struct MatroskaMuxContext {
714     int64_t *stream_duration_offsets;
715
716     int allow_raw_vfw;
717+
718+    int simple_block_timecode;
719+    int accumulated_cluster_timecode;
720 } MatroskaMuxContext;
721
722 /** 2 bytes * 7 for EBML IDs, 7 1-byte EBML lengths, 6 1-byte uint,
723@@ -2180,7 +2183,13 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
724     put_ebml_num(pb, size + 4, 0);
725     // this assumes stream_index is less than 126
726     avio_w8(pb, 0x80 | track_number);
727-    avio_wb16(pb, ts - mkv->cluster_pts);
728+
729+    if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) ||
730+            (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF))
731+        avio_wb16(pb, mkv->simple_block_timecode);
732+    else
733+        avio_wb16(pb, ts - mkv->cluster_pts);
734+
735     avio_w8(pb, (blockid == MATROSKA_ID_SIMPLEBLOCK && keyframe) ? (1 << 7) : 0);
736     avio_write(pb, data + offset, size);
737     if (data != pkt->data)
738@@ -2386,6 +2395,8 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_
739     int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
740     int64_t relative_packet_pos;
741     int dash_tracknum = mkv->is_dash ? mkv->dash_track_number : pkt->stream_index + 1;
742+    double fps = 0;
743+    int pts_interval = 0;
744
745     if (ts == AV_NOPTS_VALUE) {
746         av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n");
747@@ -2401,12 +2412,23 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_
748         }
749     }
750
751+    if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) {
752+        fps = av_q2d(s->streams[pkt->stream_index]->avg_frame_rate);
753+        pts_interval = 1000 / fps;
754+    }
755+
756     if (mkv->cluster_pos == -1) {
757         mkv->cluster_pos = avio_tell(s->pb);
758         ret = start_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER);
759         if (ret < 0)
760             return ret;
761-        put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts));
762+
763+        if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF))
764+            put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE,
765+                    mkv->accumulated_cluster_timecode + pts_interval);
766+        else
767+            put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts));
768+
769         mkv->cluster_pts = FFMAX(0, ts);
770     }
771     pb = mkv->cluster_bc;
772@@ -2414,7 +2436,67 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_
773     relative_packet_pos = avio_tell(pb);
774
775     if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) {
776-        mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
777+        if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) {
778+            uint8_t *saved_data = pkt->data;
779+            int saved_size = pkt->size;
780+            int64_t saved_pts = pkt->pts;
781+            // Main frame
782+            pkt->data = saved_data;
783+            pkt->size = saved_size - 4;
784+            pkt->pts = saved_pts;
785+            mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
786+
787+            // Latter 4 one-byte repeated frames
788+            pkt->data = saved_data + saved_size - 4;
789+            pkt->size = 1;
790+            pkt->pts = saved_pts - 2;
791+            mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
792+            mkv->simple_block_timecode += pts_interval;
793+
794+            pkt->data = saved_data + saved_size - 3;
795+            pkt->size = 1;
796+            pkt->pts = saved_pts - 1;
797+            mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
798+            mkv->simple_block_timecode += pts_interval;
799+
800+            pkt->data = saved_data + saved_size - 2;
801+            pkt->size = 1;
802+            pkt->pts = saved_pts;
803+            mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
804+            mkv->simple_block_timecode += pts_interval;
805+
806+            pkt->data = saved_data + saved_size - 1;
807+            pkt->size = 1;
808+            pkt->pts = saved_pts + 1;
809+            mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
810+            mkv->simple_block_timecode += pts_interval;
811+        } else {
812+            mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
813+
814+            if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF) {
815+                GetBitContext gb;
816+                int invisible, profile;
817+
818+                if ((ret = init_get_bits8(&gb, pkt->data, pkt->size)) < 0)
819+                    return ret;
820+
821+                get_bits(&gb, 2); // frame marker
822+                profile  = get_bits1(&gb);
823+                profile |= get_bits1(&gb) << 1;
824+                if (profile == 3) profile += get_bits1(&gb);
825+
826+                if (get_bits1(&gb)) {
827+                    invisible = 0;
828+                } else {
829+                    get_bits1(&gb); // keyframe
830+                    invisible = !get_bits1(&gb);
831+                }
832+
833+                if (!invisible)
834+                    mkv->simple_block_timecode += pts_interval;
835+            }
836+        }
837+
838         if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && (par->codec_type == AVMEDIA_TYPE_VIDEO && keyframe || add_cue)) {
839             ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, -1);
840             if (ret < 0) return ret;
841@@ -2473,8 +2555,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
842
843     if (mkv->tracks[pkt->stream_index].write_dts)
844         cluster_time = pkt->dts - mkv->cluster_pts;
845-    else
846-        cluster_time = pkt->pts - mkv->cluster_pts;
847+    else {
848+        if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) ||
849+                (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF))
850+            cluster_time = mkv->accumulated_cluster_timecode - mkv->cluster_pts;
851+        else
852+            cluster_time = pkt->pts - mkv->cluster_pts;
853+    }
854     cluster_time += mkv->tracks[pkt->stream_index].ts_offset;
855
856     // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or
857@@ -2502,6 +2589,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
858     }
859
860     if (mkv->cluster_pos != -1 && start_new_cluster) {
861+        if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) ||
862+                (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) {
863+            // Reset Timecode for new cluster.
864+            mkv->accumulated_cluster_timecode += mkv->simple_block_timecode;
865+            mkv->simple_block_timecode = 0;
866+        }
867+
868         mkv_start_new_cluster(s, pkt);
869     }
870
871@@ -2736,6 +2830,10 @@ static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
872     int ret = 1;
873     AVStream *st = s->streams[pkt->stream_index];
874
875+    if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) ||
876+       (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF))
877+        return 0;
878+
879     if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
880         if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
881             ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
882diff --git a/libavformat/movenc.c b/libavformat/movenc.c
883index 4d4d0cd024..eeebf10147 100644
884--- a/libavformat/movenc.c
885+++ b/libavformat/movenc.c
886@@ -5624,7 +5624,43 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
887             }
888         }
889
890-        return ff_mov_write_packet(s, pkt);
891+        if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) {
892+            uint8_t *saved_data = pkt->data;
893+            int      saved_size = pkt->size;
894+            int64_t  saved_pts  = pkt->pts;
895+
896+            // Main frame
897+            pkt->data = saved_data;
898+            pkt->size = saved_size - 4;
899+            pkt->pts = saved_pts;
900+            ret = ff_mov_write_packet(s, pkt);
901+
902+            // Latter 4 one-byte repeated frames
903+            pkt->data = saved_data + saved_size - 4;
904+            pkt->size = 1;
905+            pkt->pts = saved_pts - 2;
906+            ret = ff_mov_write_packet(s, pkt);
907+
908+            pkt->data = saved_data + saved_size - 3;
909+            pkt->size = 1;
910+            pkt->pts = saved_pts - 1;
911+            ret = ff_mov_write_packet(s, pkt);
912+
913+            pkt->data = saved_data + saved_size - 2;
914+            pkt->size = 1;
915+            pkt->pts = saved_pts;
916+            ret = ff_mov_write_packet(s, pkt);
917+
918+            pkt->data = saved_data + saved_size - 1;
919+            pkt->size = 1;
920+            pkt->pts = saved_pts + 1;
921+            ret = ff_mov_write_packet(s, pkt);
922+        }
923+        else{
924+            ret = ff_mov_write_packet(s, pkt);
925+        }
926+
927+        return ret;
928 }
929
930 static int mov_write_subtitle_end_packet(AVFormatContext *s,
931@@ -6763,6 +6799,10 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
932     int ret = 1;
933     AVStream *st = s->streams[pkt->stream_index];
934
935+    if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) ||
936+        (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF))
937+        return 0;
938+
939     if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
940         if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
941             ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
942--
9432.25.1
944