diff mbox

[FFmpeg-devel,v12,1/2] lavc/svt_hevc: add libsvt hevc encoder wrapper

Message ID 1557463319-17439-1-git-send-email-jing.a.sun@intel.com
State Superseded
Headers show

Commit Message

Jing SUN May 10, 2019, 4:41 a.m. UTC
Signed-off-by: Zhengxu Huang <zhengxu.huang@intel.com>
Signed-off-by: Hassene Tmar <hassene.tmar@intel.com>
Signed-off-by: Jun Zhao <jun.zhao@intel.com>
Signed-off-by: Jing Sun <jing.a.sun@intel.com>
---
 configure                |   4 +
 libavcodec/Makefile      |   1 +
 libavcodec/allcodecs.c   |   1 +
 libavcodec/libsvt_hevc.c | 518 +++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/version.h     |   4 +-
 5 files changed, 526 insertions(+), 2 deletions(-)
 create mode 100644 libavcodec/libsvt_hevc.c

Comments

James Almer May 10, 2019, 4:04 a.m. UTC | #1
On 5/10/2019 1:41 AM, Jing Sun wrote:
> +    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
> +        EB_BUFFERHEADERTYPE *header_ptr = NULL;
> +
> +        svt_ret = EbH265EncStreamHeader(svt_enc->svt_handle, &header_ptr);
> +        if (svt_ret != EB_ErrorNone) {
> +            av_log(avctx, AV_LOG_ERROR, "Error when build stream header.\n");
> +            goto failed_init_enc;
> +        }
> +
> +        avctx->extradata_size = header_ptr->nFilledLen;
> +        avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
> +        if (!avctx->extradata) {
> +            av_log(avctx, AV_LOG_ERROR,
> +                   "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size);
> +            svt_ret = EB_ErrorInsufficientResources;
> +            goto failed_init_enc;
> +        }
> +        memset(avctx->extradata, 0x0, avctx->extradata_size+AV_INPUT_BUFFER_PADDING_SIZE);

You used av_mallocz() to allocate the buffer, so it's already fully zeroed.

In any case, it would be faster to instead use av_malloc() above, then
only zero the padding bytes here. Since you're copying the actual data
in the line below, nothing will remain uninitialized.

> +        memcpy(avctx->extradata, header_ptr->pBuffer, avctx->extradata_size);
> +    }
Jing SUN May 10, 2019, 5:18 a.m. UTC | #2
-----Original Message-----
From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of James Almer

Sent: Friday, May 10, 2019 12:05 PM
To: ffmpeg-devel@ffmpeg.org
Subject: Re: [FFmpeg-devel] [PATCH v12 1/2] lavc/svt_hevc: add libsvt hevc encoder wrapper

>You used av_mallocz() to allocate the buffer, so it's already fully zeroed.

>In any case, it would be faster to instead use av_malloc() above, then only zero the padding bytes here. Since you're copying the actual data in the line below, nothing will remain uninitialized.


Hi Almer,

Thanks for the review! Indeed the explicit memset() is redundant and I have removed that.

void *av_mallocz(size_t size)
{
    void *ptr = av_malloc(size);
    if (ptr)
        memset(ptr, 0, size);
    return ptr;
}

-Jing
Zhong Li May 10, 2019, 5:23 a.m. UTC | #3
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf

> Of James Almer

> Sent: Friday, May 10, 2019 12:05 PM

> To: ffmpeg-devel@ffmpeg.org

> Subject: Re: [FFmpeg-devel] [PATCH v12 1/2] lavc/svt_hevc: add libsvt hevc

> encoder wrapper

> 

> >You used av_mallocz() to allocate the buffer, so it's already fully zeroed.

> >In any case, it would be faster to instead use av_malloc() above, then only

> zero the padding bytes here. Since you're copying the actual data in the line

> below, nothing will remain uninitialized.

> 

> Hi Almer,

> 

> Thanks for the review! Indeed the explicit memset() is redundant and I have

> removed that.

> 

> void *av_mallocz(size_t size)

> {

>     void *ptr = av_malloc(size);

>     if (ptr)

>         memset(ptr, 0, size);

>     return ptr;

> }

> 

> -Jing

The better solution should be: use av_malloc and just memset the padding bytes.
Jing SUN May 10, 2019, 5:29 a.m. UTC | #4
-----Original Message-----
From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of Li, Zhong

Sent: Friday, May 10, 2019 1:23 PM
To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Subject: Re: [FFmpeg-devel] [PATCH v12 1/2] lavc/svt_hevc: add libsvt hevc encoder wrapper

>The better solution should be: use av_malloc and just memset the padding bytes.


The memset inside av_mallocv sets the whole buffer of the size "avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE" to zero.

        avctx->extradata_size = header_ptr->nFilledLen;
        avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);

-Jing
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Zhong Li May 10, 2019, 5:35 a.m. UTC | #5
> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf

> Of Sun, Jing A

> Sent: Friday, May 10, 2019 1:30 PM

> To: FFmpeg development discussions and patches

> <ffmpeg-devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH v12 1/2] lavc/svt_hevc: add libsvt hevc

> encoder wrapper

> 

> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf

> Of Li, Zhong

> Sent: Friday, May 10, 2019 1:23 PM

> To: FFmpeg development discussions and patches

> <ffmpeg-devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH v12 1/2] lavc/svt_hevc: add libsvt hevc

> encoder wrapper

> 

> >The better solution should be: use av_malloc and just memset the padding

> bytes.

> 

> The memset inside av_mallocv sets the whole buffer of the size

> "avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE" to zero.


That is low efficiency and slow as James mentioned. You don't need to set the whole buffer to be zero, only padding bytes needed.

> 

>         avctx->extradata_size = header_ptr->nFilledLen;

>         avctx->extradata = av_mallocz(avctx->extradata_size +

> AV_INPUT_BUFFER_PADDING_SIZE);

> 

> -Jing
diff mbox

Patch

diff --git a/configure b/configure
index d644a5b..2bc93a6 100755
--- a/configure
+++ b/configure
@@ -264,6 +264,7 @@  External library support:
   --enable-libspeex        enable Speex de/encoding via libspeex [no]
   --enable-libsrt          enable Haivision SRT protocol via libsrt [no]
   --enable-libssh          enable SFTP protocol via libssh [no]
+  --enable-libsvthevc      enable HEVC encoding via svt [no]
   --enable-libtensorflow   enable TensorFlow as a DNN module backend
                            for DNN based filters like sr [no]
   --enable-libtesseract    enable Tesseract, needed for ocr filter [no]
@@ -1782,6 +1783,7 @@  EXTERNAL_LIBRARY_LIST="
     libspeex
     libsrt
     libssh
+    libsvthevc
     libtensorflow
     libtesseract
     libtheora
@@ -3174,6 +3176,7 @@  libshine_encoder_select="audio_frame_queue"
 libspeex_decoder_deps="libspeex"
 libspeex_encoder_deps="libspeex"
 libspeex_encoder_select="audio_frame_queue"
+libsvt_hevc_encoder_deps="libsvthevc"
 libtheora_encoder_deps="libtheora"
 libtwolame_encoder_deps="libtwolame"
 libvo_amrwbenc_encoder_deps="libvo_amrwbenc"
@@ -6203,6 +6206,7 @@  enabled libsoxr           && require libsoxr soxr.h soxr_create -lsoxr
 enabled libssh            && require_pkg_config libssh libssh libssh/sftp.h sftp_init
 enabled libspeex          && require_pkg_config libspeex speex speex/speex.h speex_decoder_init
 enabled libsrt            && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket
+enabled libsvthevc        && require_pkg_config libsvthevc SvtHevcEnc EbApi.h EbInitHandle
 enabled libtensorflow     && require libtensorflow tensorflow/c/c_api.h TF_Version -ltensorflow
 enabled libtesseract      && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate
 enabled libtheora         && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index f37135f..8e031d3 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -991,6 +991,7 @@  OBJS-$(CONFIG_LIBOPUS_ENCODER)            += libopusenc.o libopus.o     \
 OBJS-$(CONFIG_LIBSHINE_ENCODER)           += libshine.o
 OBJS-$(CONFIG_LIBSPEEX_DECODER)           += libspeexdec.o
 OBJS-$(CONFIG_LIBSPEEX_ENCODER)           += libspeexenc.o
+OBJS-$(CONFIG_LIBSVT_HEVC_ENCODER)        += libsvt_hevc.o
 OBJS-$(CONFIG_LIBTHEORA_ENCODER)          += libtheoraenc.o
 OBJS-$(CONFIG_LIBTWOLAME_ENCODER)         += libtwolame.o
 OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER)     += libvo-amrwbenc.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 6178d31..e27a7b6 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -706,6 +706,7 @@  extern AVCodec ff_librsvg_decoder;
 extern AVCodec ff_libshine_encoder;
 extern AVCodec ff_libspeex_encoder;
 extern AVCodec ff_libspeex_decoder;
+extern AVCodec ff_libsvt_hevc_encoder;
 extern AVCodec ff_libtheora_encoder;
 extern AVCodec ff_libtwolame_encoder;
 extern AVCodec ff_libvo_amrwbenc_encoder;
diff --git a/libavcodec/libsvt_hevc.c b/libavcodec/libsvt_hevc.c
new file mode 100644
index 0000000..1dd1659
--- /dev/null
+++ b/libavcodec/libsvt_hevc.c
@@ -0,0 +1,518 @@ 
+/*
+* Scalable Video Technology for HEVC encoder library plugin
+*
+* Copyright (c) 2019 Intel Corporation
+*
+* This file is part of FFmpeg.
+*
+* 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.
+*
+* 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 this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "EbErrorCodes.h"
+#include "EbTime.h"
+#include "EbApi.h"
+
+#include "libavutil/common.h"
+#include "libavutil/frame.h"
+#include "libavutil/opt.h"
+
+#include "internal.h"
+#include "avcodec.h"
+
+typedef enum eos_status {
+    EOS_NOT_REACHED = 0,
+    EOS_REACHED,
+    EOS_TOTRIGGER
+} EOS_STATUS;
+
+typedef struct SvtContext {
+    AVClass *class;
+
+    EB_H265_ENC_CONFIGURATION enc_params;
+    EB_COMPONENTTYPE *svt_handle;
+    EB_BUFFERHEADERTYPE in_buf;
+    EOS_STATUS eos_flag;
+
+    // User options.
+    int hierarchical_level;
+    int la_depth;
+    int enc_mode;
+    int rc_mode;
+    int scd;
+    int tune;
+    int qp;
+
+    int forced_idr;
+
+    int aud;
+
+    int profile;
+    int tier;
+    int level;
+
+    int base_layer_switch_mode;
+} SvtContext;
+
+static int error_mapping(EB_ERRORTYPE svt_ret)
+{
+    int err;
+
+    switch (svt_ret) {
+    case EB_ErrorInsufficientResources:
+        err = AVERROR(ENOMEM);
+        break;
+
+    case EB_ErrorUndefined:
+    case EB_ErrorInvalidComponent:
+    case EB_ErrorBadParameter:
+        err = AVERROR(EINVAL);
+        break;
+
+    case EB_ErrorDestroyThreadFailed:
+    case EB_ErrorSemaphoreUnresponsive:
+    case EB_ErrorDestroySemaphoreFailed:
+    case EB_ErrorCreateMutexFailed:
+    case EB_ErrorMutexUnresponsive:
+    case EB_ErrorDestroyMutexFailed:
+        err = AVERROR_EXTERNAL;
+        break;
+
+    case EB_NoErrorEmptyQueue:
+        err = AVERROR(EAGAIN);
+
+    case EB_ErrorNone:
+        err = 0;
+        break;
+
+    default:
+        err = AVERROR_UNKNOWN;
+    }
+
+    return err;
+}
+
+static void free_buffer(SvtContext *svt_enc)
+{
+    uint8_t *in_data = svt_enc->in_buf.pBuffer;
+
+    av_freep(&in_data);
+}
+
+static int alloc_buffer(EB_H265_ENC_CONFIGURATION *config, SvtContext *svt_enc)
+{
+    EB_H265_ENC_INPUT *in_data;
+
+    // allocate buffer for in and out
+    in_data  = av_mallocz(sizeof(*in_data));
+    if (!in_data)
+        goto failed;
+    svt_enc->in_buf.pBuffer  = (unsigned char *)in_data;
+
+    svt_enc->in_buf.nSize        = sizeof(svt_enc->in_buf);
+    svt_enc->in_buf.pAppPrivate  = NULL;
+
+    return 0;
+
+failed:
+    free_buffer(svt_enc);
+    return AVERROR(ENOMEM);
+}
+
+static int config_enc_params(EB_H265_ENC_CONFIGURATION *param,
+                             AVCodecContext *avctx)
+{
+    SvtContext *svt_enc = avctx->priv_data;
+    int ret;
+
+    param->sourceWidth = avctx->width;
+    param->sourceHeight = avctx->height;
+    param->encoderBitDepth = 8;
+
+    if (avctx->pix_fmt == AV_PIX_FMT_YUV420P10) {
+        av_log(avctx, AV_LOG_DEBUG, "Encoder 10 bits depth input\n");
+
+        param->encoderBitDepth = 10;
+    }
+
+    if ((avctx->pix_fmt == AV_PIX_FMT_YUV420P) ||
+        (avctx->pix_fmt == AV_PIX_FMT_YUV420P10))
+        param->encoderColorFormat = EB_YUV420;
+    else if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P) ||
+             (avctx->pix_fmt == AV_PIX_FMT_YUV422P10))
+        param->encoderColorFormat = EB_YUV422;
+    else
+        param->encoderColorFormat = EB_YUV444;
+
+    // Update param from options
+    param->hierarchicalLevels   = svt_enc->hierarchical_level - 1;
+    param->encMode              = svt_enc->enc_mode;
+    param->profile              = svt_enc->profile;
+    param->tier                 = svt_enc->tier;
+    param->level                = svt_enc->level;
+    param->rateControlMode      = svt_enc->rc_mode;
+    param->sceneChangeDetection = svt_enc->scd;
+    param->tune                 = svt_enc->tune;
+    param->baseLayerSwitchMode  = svt_enc->base_layer_switch_mode;
+    param->qp                   = svt_enc->qp;
+    param->accessUnitDelimiter  = svt_enc->aud;
+
+    if (param->profile == FF_PROFILE_HEVC_MAIN_STILL_PICTURE) {
+        av_log(avctx, AV_LOG_ERROR, "Main Still Picture Profile not supported!\n");
+        return EB_ErrorBadParameter;
+    }
+
+    if ((param->encoderColorFormat >= EB_YUV422) &&
+        (param->profile != FF_PROFILE_HEVC_REXT)) {
+        av_log(avctx, AV_LOG_WARNING, "Rext Profile forced for 422 or 444!\n");
+        param->profile = FF_PROFILE_HEVC_REXT;
+    }
+
+    if ((param->profile == FF_PROFILE_HEVC_MAIN) &&
+        (param->encoderBitDepth > 8)) {
+        av_log(avctx, AV_LOG_WARNING, "Main10 Profile forced for 10 bits!\n");
+        param->profile = FF_PROFILE_HEVC_MAIN_10;
+    }
+
+    param->targetBitRate = avctx->bit_rate;
+    if (avctx->gop_size > 0)
+        param->intraPeriodLength = avctx->gop_size - 1;
+
+    if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
+        param->frameRateNumerator = avctx->framerate.num;
+        param->frameRateDenominator =
+            avctx->framerate.den * avctx->ticks_per_frame;
+    } else {
+        param->frameRateNumerator = avctx->time_base.den;
+        param->frameRateDenominator =
+            avctx->time_base.num * avctx->ticks_per_frame;
+    }
+
+    if (param->rateControlMode) {
+        param->maxQpAllowed = avctx->qmax;
+        param->minQpAllowed = avctx->qmin;
+    }
+
+    param->intraRefreshType =
+        !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) + 1;
+
+    // is it repeat headers for MP4 or Annex-b
+    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)
+        param->codeVpsSpsPps = 0;
+    else
+        param->codeVpsSpsPps = 1;
+
+    param->codeEosNal = 1;
+
+    if (svt_enc->la_depth != -1)
+        param->lookAheadDistance = svt_enc->la_depth;
+
+    ret = alloc_buffer(param, svt_enc);
+
+    return ret;
+}
+
+static void read_in_data(EB_H265_ENC_CONFIGURATION *config,
+                         const AVFrame *frame,
+                         EB_BUFFERHEADERTYPE *header_ptr)
+{
+    uint8_t is16bit = config->encoderBitDepth > 8;
+    uint64_t luma_size =
+        (uint64_t)config->sourceWidth * config->sourceHeight<< is16bit;
+    EB_H265_ENC_INPUT *in_data = (EB_H265_ENC_INPUT *)header_ptr->pBuffer;
+
+    in_data->luma = frame->data[0];
+    in_data->cb   = frame->data[1];
+    in_data->cr   = frame->data[2];
+
+    // stride info
+    in_data->yStride  = frame->linesize[0] >> is16bit;
+    in_data->cbStride = frame->linesize[1] >> is16bit;
+    in_data->crStride = frame->linesize[2] >> is16bit;
+
+    if (config->encoderColorFormat == EB_YUV420)
+        luma_size *= 3/2u;
+    else if (config->encoderColorFormat == EB_YUV422)
+        luma_size *= 2u;
+    else
+        luma_size *= 3u;
+
+    header_ptr->nFilledLen += luma_size;
+}
+
+static av_cold int eb_enc_init(AVCodecContext *avctx)
+{
+    SvtContext   *svt_enc = avctx->priv_data;
+    EB_ERRORTYPE svt_ret;
+
+    svt_enc->eos_flag = EOS_NOT_REACHED;
+
+    svt_ret = EbInitHandle(&svt_enc->svt_handle, svt_enc, &svt_enc->enc_params);
+    if (svt_ret != EB_ErrorNone) {
+        av_log(avctx, AV_LOG_ERROR, "Error init encoder handle\n");
+        goto failed;
+    }
+
+    svt_ret = config_enc_params(&svt_enc->enc_params, avctx);
+    if (svt_ret != EB_ErrorNone) {
+        av_log(avctx, AV_LOG_ERROR, "Error configure encoder parameters\n");
+        goto failed_init_handle;
+    }
+
+    svt_ret = EbH265EncSetParameter(svt_enc->svt_handle, &svt_enc->enc_params);
+    if (svt_ret != EB_ErrorNone) {
+        av_log(avctx, AV_LOG_ERROR, "Error setting encoder parameters\n");
+        goto failed_init_handle;
+    }
+
+    svt_ret = EbInitEncoder(svt_enc->svt_handle);
+    if (svt_ret != EB_ErrorNone) {
+        av_log(avctx, AV_LOG_ERROR, "Error init encoder\n");
+        goto failed_init_handle;
+    }
+
+    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+        EB_BUFFERHEADERTYPE *header_ptr = NULL;
+
+        svt_ret = EbH265EncStreamHeader(svt_enc->svt_handle, &header_ptr);
+        if (svt_ret != EB_ErrorNone) {
+            av_log(avctx, AV_LOG_ERROR, "Error when build stream header.\n");
+            goto failed_init_enc;
+        }
+
+        avctx->extradata_size = header_ptr->nFilledLen;
+        avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+        if (!avctx->extradata) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size);
+            svt_ret = EB_ErrorInsufficientResources;
+            goto failed_init_enc;
+        }
+        memset(avctx->extradata, 0x0, avctx->extradata_size+AV_INPUT_BUFFER_PADDING_SIZE);
+        memcpy(avctx->extradata, header_ptr->pBuffer, avctx->extradata_size);
+    }
+
+    return 0;
+
+failed_init_enc:
+    EbDeinitEncoder(svt_enc->svt_handle);
+failed_init_handle:
+    EbDeinitHandle(svt_enc->svt_handle);
+failed:
+    free_buffer(svt_enc);
+    svt_enc->svt_handle = NULL;
+    svt_enc = NULL;
+    return error_mapping(svt_ret);
+}
+
+static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame)
+{
+    SvtContext           *svt_enc = avctx->priv_data;
+    EB_BUFFERHEADERTYPE  *header_ptr = &svt_enc->in_buf;
+
+    if (!frame) {
+        EB_BUFFERHEADERTYPE header_ptr_last;
+        header_ptr_last.nAllocLen   = 0;
+        header_ptr_last.nFilledLen  = 0;
+        header_ptr_last.nTickCount  = 0;
+        header_ptr_last.pAppPrivate = NULL;
+        header_ptr_last.pBuffer     = NULL;
+        header_ptr_last.nFlags      = EB_BUFFERFLAG_EOS;
+
+        EbH265EncSendPicture(svt_enc->svt_handle, &header_ptr_last);
+        svt_enc->eos_flag = EOS_REACHED;
+        av_log(avctx, AV_LOG_DEBUG, "Finish sending frames!!!\n");
+        return 0;
+    }
+
+    read_in_data(&svt_enc->enc_params, frame, header_ptr);
+
+    header_ptr->nFlags       = 0;
+    header_ptr->pAppPrivate  = NULL;
+    header_ptr->pts          = frame->pts;
+    switch (frame->pict_type) {
+    case AV_PICTURE_TYPE_I:
+        header_ptr->sliceType = svt_enc->forced_idr > 0 ? EB_IDR_PICTURE : EB_I_PICTURE;
+        break;
+    case AV_PICTURE_TYPE_P:
+        header_ptr->sliceType = EB_P_PICTURE;
+        break;
+    case AV_PICTURE_TYPE_B:
+        header_ptr->sliceType = EB_B_PICTURE;
+        break;
+    default:
+        header_ptr->sliceType = EB_INVALID_PICTURE;
+        break;
+    }
+    EbH265EncSendPicture(svt_enc->svt_handle, header_ptr);
+
+    return 0;
+}
+
+static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
+{
+    SvtContext  *svt_enc = avctx->priv_data;
+    EB_BUFFERHEADERTYPE   *header_ptr = NULL;
+    EB_ERRORTYPE          svt_ret;
+    int ret = 0;
+
+    if (EOS_TOTRIGGER == svt_enc->eos_flag) {
+        pkt = NULL;
+        return AVERROR_EOF;
+    }
+
+    svt_ret = EbH265GetPacket(svt_enc->svt_handle, &header_ptr, svt_enc->eos_flag);
+    if (svt_ret == EB_NoErrorEmptyQueue)
+        return AVERROR(EAGAIN);
+
+    if ((ret = ff_alloc_packet2(avctx, pkt, header_ptr->nFilledLen, 0)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n");
+        EbH265ReleaseOutBuffer(&header_ptr);
+        return ret;
+    }
+
+    memcpy(pkt->data, header_ptr->pBuffer, header_ptr->nFilledLen);
+
+    pkt->size = header_ptr->nFilledLen;
+    pkt->pts  = header_ptr->pts;
+    pkt->dts  = header_ptr->dts;
+    if ((header_ptr->sliceType == EB_IDR_PICTURE) ||
+        (header_ptr->sliceType == EB_I_PICTURE))
+        pkt->flags |= AV_PKT_FLAG_KEY;
+    if (header_ptr->sliceType == EB_NON_REF_PICTURE)
+        pkt->flags |= AV_PKT_FLAG_DISPOSABLE;
+
+    EbH265ReleaseOutBuffer(&header_ptr);
+
+    if (EB_BUFFERFLAG_EOS == header_ptr->nFlags)
+        svt_enc->eos_flag = EOS_TOTRIGGER;
+
+    return 0;
+}
+
+static av_cold int eb_enc_close(AVCodecContext *avctx)
+{
+    SvtContext *svt_enc = avctx->priv_data;
+
+    if (svt_enc) {
+        if (svt_enc->svt_handle) {
+            EbDeinitEncoder(svt_enc->svt_handle);
+            EbDeinitHandle(svt_enc->svt_handle);
+            svt_enc->svt_handle = NULL;
+        }
+
+        free_buffer(svt_enc);
+        svt_enc = NULL;
+    }
+
+    return 0;
+}
+
+#define OFFSET(x) offsetof(SvtContext, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "aud", "Include Access Unit Delimiter", OFFSET(aud),
+      AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+
+    { "hielevel", "Hierarchical prediction levels setting", OFFSET(hierarchical_level),
+      AV_OPT_TYPE_INT, { .i64 = 4 }, 1, 4, VE , "hielevel"},
+        { "flat",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 },  INT_MIN, INT_MAX, VE, "hielevel" },
+        { "2level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 },  INT_MIN, INT_MAX, VE, "hielevel" },
+        { "3level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 },  INT_MIN, INT_MAX, VE, "hielevel" },
+        { "4level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 4 },  INT_MIN, INT_MAX, VE, "hielevel" },
+
+    { "la_depth", "Look ahead distance [0, 256]", OFFSET(la_depth),
+      AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 256, VE },
+
+    { "preset", "Encoding preset [0, 12] (e,g, for subjective quality tuning mode and >=4k resolution), [0, 10] (for >= 1080p resolution), [0, 9] (for all resolution and modes)",
+      OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = 9 }, 0, 12, VE },
+
+    { "profile", "Profile setting, Main Still Picture Profile not supported", OFFSET(profile),
+      AV_OPT_TYPE_INT, { .i64 = FF_PROFILE_HEVC_MAIN }, FF_PROFILE_HEVC_MAIN, FF_PROFILE_HEVC_REXT, VE, "profile"},
+
+    { "tier", "Set tier (general_tier_flag)", OFFSET(tier),
+      AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, "tier" },
+        { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "tier" },
+        { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "tier" },
+
+    { "level", "Set level (level_idc)", OFFSET(level),
+      AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xff, VE, "level" },
+
+    { "rc", "Bit rate control mode", OFFSET(rc_mode),
+      AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE , "rc"},
+        { "cqp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 },  INT_MIN, INT_MAX, VE, "rc" },
+        { "vbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 },  INT_MIN, INT_MAX, VE, "rc" },
+
+    { "qp", "QP value for intra frames", OFFSET(qp),
+      AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 51, VE },
+
+    { "sc_detection", "Scene change detection", OFFSET(scd),
+      AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
+
+    { "tune", "Quality tuning mode", OFFSET(tune), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 2, VE, "tune" },
+        { "sq", "Visually optimized mode", 0,
+          AV_OPT_TYPE_CONST, { .i64 = 0 },  INT_MIN, INT_MAX, VE, "tune" },
+        { "oq",  "PSNR / SSIM optimized mode",  0,
+          AV_OPT_TYPE_CONST, { .i64 = 1 },  INT_MIN, INT_MAX, VE, "tune" },
+        { "vmaf", "VMAF optimized mode", 0,
+          AV_OPT_TYPE_CONST, { .i64 = 2 },  INT_MIN, INT_MAX, VE, "tune" },
+
+    { "bl_mode", "Random Access Prediction Structure type setting", OFFSET(base_layer_switch_mode),
+      AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+
+    { "forced-idr", "If forcing keyframes, force them as IDR frames.", OFFSET(forced_idr),
+      AV_OPT_TYPE_BOOL,   { .i64 = 0 }, -1, 1, VE },
+
+    { NULL },
+};
+
+static const AVClass class = {
+    .class_name = "libsvt_hevc",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static const AVCodecDefault eb_enc_defaults[] = {
+    { "b",         "7M"    },
+    { "flags",     "+cgop" },
+    { "qmin",      "10"    },
+    { "qmax",      "48"    },
+    { "g",         "-2"    },
+    { NULL },
+};
+
+AVCodec ff_libsvt_hevc_encoder = {
+    .name           = "libsvt_hevc",
+    .long_name      = NULL_IF_CONFIG_SMALL("SVT-HEVC(Scalable Video Technology for HEVC) encoder"),
+    .priv_data_size = sizeof(SvtContext),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_HEVC,
+    .init           = eb_enc_init,
+    .send_frame     = eb_send_frame,
+    .receive_packet = eb_receive_packet,
+    .close          = eb_enc_close,
+    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,
+    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P,
+                                                    AV_PIX_FMT_YUV420P10,
+                                                    AV_PIX_FMT_YUV422P,
+                                                    AV_PIX_FMT_YUV420P10,
+                                                    AV_PIX_FMT_YUV444P,
+                                                    AV_PIX_FMT_YUV444P10,
+                                                    AV_PIX_FMT_NONE },
+    .priv_class     = &class,
+    .defaults       = eb_enc_defaults,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .wrapper_name   = "libsvt_hevc",
+};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index d11beb7..2709163 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -28,8 +28,8 @@ 
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR  58
-#define LIBAVCODEC_VERSION_MINOR  52
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MINOR  53
+#define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \