diff --git a/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch b/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch deleted file mode 100644 index 21f287a..0000000 --- a/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch +++ /dev/null @@ -1,944 +0,0 @@ -From 581bbc49879407f88897c9db4051eb5266ca2696 Mon Sep 17 00:00:00 2001 -From: Jing Sun -Date: Mon, 1 Apr 2019 17:17:00 +0800 -Subject: [PATCH] Add ability for ffmpeg to run svt vp9 with hevc & av1 - -Signed-off-by: hassene -Signed-off-by: Jing Sun -Signed-off-by: Austin Hu -Signed-off-by: Guo Jiansheng ---- - configure | 4 + - libavcodec/Makefile | 1 + - libavcodec/allcodecs.c | 1 + - libavcodec/avcodec.h | 2 + - libavcodec/libsvt_vp9.c | 482 ++++++++++++++++++++++++++++++++++++++ - libavformat/dashenc.c | 49 +++- - libavformat/ivfenc.c | 34 ++- - libavformat/matroskaenc.c | 108 ++++++++- - libavformat/movenc.c | 42 +++- - 9 files changed, 713 insertions(+), 10 deletions(-) - create mode 100644 libavcodec/libsvt_vp9.c - -diff --git a/configure b/configure -index 20717c77a4..be74440bc4 100755 ---- a/configure -+++ b/configure -@@ -266,6 +266,7 @@ External library support: - --enable-libssh enable SFTP protocol via libssh [no] - --enable-libsvthevc enable HEVC encoding via svt [no] - --enable-libsvtav1 enable AV1 encoding via svt [no] -+ --enable-libsvtvp9 enable VP9 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] -@@ -1797,6 +1798,7 @@ EXTERNAL_LIBRARY_LIST=" - libssh - libsvthevc - libsvtav1 -+ libsvtvp9 - libtensorflow - libtesseract - libtheora -@@ -3197,6 +3199,7 @@ libspeex_encoder_deps="libspeex" - libspeex_encoder_select="audio_frame_queue" - libsvt_hevc_encoder_deps="libsvthevc" - libsvt_av1_encoder_deps="libsvtav1" -+libsvt_vp9_encoder_deps="libsvtvp9" - libtheora_encoder_deps="libtheora" - libtwolame_encoder_deps="libtwolame" - libvo_amrwbenc_encoder_deps="libvo_amrwbenc" -@@ -6271,6 +6274,7 @@ enabled libspeex && require_pkg_config libspeex speex speex/speex.h spe - 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 libsvtav1 && require_pkg_config libsvtav1 SvtAv1Enc EbSvtAv1Enc.h svt_av1_enc_init_handle -+enabled libsvtvp9 && require_pkg_config libsvtvp9 SvtVp9Enc EbSvtVp9Enc.h eb_vp9_svt_init_handle - 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 c500f3d274..2e8636496f 100644 ---- a/libavcodec/Makefile -+++ b/libavcodec/Makefile -@@ -993,6 +993,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o - OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o - OBJS-$(CONFIG_LIBSVT_HEVC_ENCODER) += libsvt_hevc.o - OBJS-$(CONFIG_LIBSVT_AV1_ENCODER) += libsvt_av1.o -+OBJS-$(CONFIG_LIBSVT_VP9_ENCODER) += libsvt_vp9.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 db1b1b2188..75248670db 100644 ---- a/libavcodec/allcodecs.c -+++ b/libavcodec/allcodecs.c -@@ -709,6 +709,7 @@ extern AVCodec ff_libspeex_encoder; - extern AVCodec ff_libspeex_decoder; - extern AVCodec ff_libsvt_hevc_encoder; - extern AVCodec ff_libsvt_av1_encoder; -+extern AVCodec ff_libsvt_vp9_encoder; - extern AVCodec ff_libtheora_encoder; - extern AVCodec ff_libtwolame_encoder; - extern AVCodec ff_libvo_amrwbenc_encoder; -diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h -index d234271c5b..0d903571b3 100644 ---- a/libavcodec/avcodec.h -+++ b/libavcodec/avcodec.h -@@ -1527,6 +1527,8 @@ typedef struct AVPacket { - */ - #define AV_PKT_FLAG_DISPOSABLE 0x0010 - -+#define AV_PKT_FLAG_SVT_VP9_EXT_ON 0x10000 // Indicating SVT VP9 frame header ext on -+#define AV_PKT_FLAG_SVT_VP9_EXT_OFF 0x20000 // Indicating SVT VP9 frame header ext off - - enum AVSideDataParamChangeFlags { - AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, -diff --git a/libavcodec/libsvt_vp9.c b/libavcodec/libsvt_vp9.c -new file mode 100644 -index 0000000000..d2c4740e5c ---- /dev/null -+++ b/libavcodec/libsvt_vp9.c -@@ -0,0 +1,482 @@ -+/* -+* Scalable Video Technology for VP9 encoder library plugin -+* -+* Copyright (c) 2018 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 -+#include "EbSvtVp9ErrorCodes.h" -+#include "EbSvtVp9Time.h" -+#include "EbSvtVp9Enc.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; -+ -+ EbSvtVp9EncConfiguration enc_params; -+ EbComponentType *svt_handle; -+ -+ EbBufferHeaderType *in_buf; -+ int raw_size; -+ -+ AVBufferPool* pool; -+ -+ EOS_STATUS eos_flag; -+ -+ // User options. -+ int enc_mode; -+ int rc_mode; -+ int tune; -+ int qp; -+ -+ int forced_idr; -+ -+ int level; -+ -+ int base_layer_switch_mode; -+} SvtContext; -+ -+static int error_mapping(EbErrorType 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) -+{ -+ if (svt_enc->in_buf) { -+ EbSvtEncInput *in_data = (EbSvtEncInput *)svt_enc->in_buf->p_buffer; -+ av_freep(&in_data); -+ av_freep(&svt_enc->in_buf); -+ } -+ av_buffer_pool_uninit(&svt_enc->pool); -+} -+ -+static int alloc_buffer(EbSvtVp9EncConfiguration *config, SvtContext *svt_enc) -+{ -+ const size_t luma_size_8bit = -+ config->source_width * config->source_height; -+ const size_t luma_size_10bit = -+ (config->encoder_bit_depth > 8) ? luma_size_8bit : 0; -+ -+ EbSvtEncInput *in_data; -+ -+ svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3 / 2; -+ -+ // allocate buffer for in and out -+ svt_enc->in_buf = av_mallocz(sizeof(*svt_enc->in_buf)); -+ if (!svt_enc->in_buf) -+ goto failed; -+ -+ -+ svt_enc->in_buf->p_buffer = (unsigned char *)av_mallocz(sizeof(*in_data)); -+ if (!svt_enc->in_buf->p_buffer) -+ goto failed; -+ -+ svt_enc->in_buf->size = sizeof(*svt_enc->in_buf); -+ svt_enc->in_buf->p_app_private = NULL; -+ -+ svt_enc->pool = av_buffer_pool_init(svt_enc->raw_size, NULL); -+ if (!svt_enc->pool) -+ goto failed; -+ -+ return 0; -+ -+failed: -+ free_buffer(svt_enc); -+ return AVERROR(ENOMEM); -+} -+ -+static int config_enc_params(EbSvtVp9EncConfiguration *param, -+ AVCodecContext *avctx) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ int ret; -+ int ten_bits = 0; -+ -+ param->source_width = avctx->width; -+ param->source_height = avctx->height; -+ -+ if (avctx->pix_fmt == AV_PIX_FMT_YUV420P10LE) { -+ av_log(avctx, AV_LOG_DEBUG , "Encoder 10 bits depth input\n"); -+ // Disable Compressed 10-bit format default -+ ten_bits = 1; -+ } -+ -+ // Update param from options -+ param->enc_mode = svt_enc->enc_mode; -+ param->level = svt_enc->level; -+ param->rate_control_mode = svt_enc->rc_mode; -+ param->tune = svt_enc->tune; -+ param->base_layer_switch_mode = svt_enc->base_layer_switch_mode; -+ param->qp = svt_enc->qp; -+ -+ param->target_bit_rate = avctx->bit_rate; -+ if (avctx->gop_size > 0) -+ param->intra_period = avctx->gop_size - 1; -+ -+ if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { -+ param->frame_rate_numerator = avctx->framerate.num; -+ param->frame_rate_denominator = avctx->framerate.den * avctx->ticks_per_frame; -+ } else { -+ param->frame_rate_numerator = avctx->time_base.den; -+ param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame; -+ } -+ -+ if (param->rate_control_mode) { -+ param->max_qp_allowed = avctx->qmax; -+ param->min_qp_allowed = avctx->qmin; -+ } -+ -+ if (ten_bits) { -+ param->encoder_bit_depth = 10; -+ } -+ -+ ret = alloc_buffer(param, svt_enc); -+ -+ return ret; -+} -+ -+static void read_in_data(EbSvtVp9EncConfiguration *config, -+ const AVFrame *frame, -+ EbBufferHeaderType *headerPtr) -+{ -+ uint8_t is16bit = config->encoder_bit_depth > 8; -+ uint64_t luma_size = -+ (uint64_t)config->source_width * config->source_height<< is16bit; -+ EbSvtEncInput *in_data = (EbSvtEncInput *)headerPtr->p_buffer; -+ -+ // support yuv420p and yuv420p010 -+ in_data->luma = frame->data[0]; -+ in_data->cb = frame->data[1]; -+ in_data->cr = frame->data[2]; -+ -+ // stride info -+ in_data->y_stride = frame->linesize[0] >> is16bit; -+ in_data->cb_stride = frame->linesize[1] >> is16bit; -+ in_data->cr_stride = frame->linesize[2] >> is16bit; -+ -+ headerPtr->n_filled_len += luma_size * 3/2u; -+} -+ -+static av_cold int eb_enc_init(AVCodecContext *avctx) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ EbErrorType svt_ret; -+ -+ svt_enc->eos_flag = EOS_NOT_REACHED; -+ -+ svt_ret = eb_vp9_svt_init_handle(&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 = eb_vp9_svt_enc_set_parameter(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 = eb_vp9_init_encoder(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) { -+ // EbBufferHeaderType* headerPtr; -+ // headerPtr->size = sizeof(headerPtr); -+ // headerPtr->n_filled_len = 0; /* in/out */ -+ // headerPtr->p_buffer = av_malloc(10 * 1024 * 1024); -+ // headerPtr->n_alloc_len = (10 * 1024 * 1024); -+ // -+ // if (!headerPtr->p_buffer) { -+ // av_log(avctx, AV_LOG_ERROR, -+ // "Cannot allocate buffer size %d.\n", headerPtr->n_alloc_len); -+ // svt_ret = EB_ErrorInsufficientResources; -+ // goto failed_init_enc; -+ // } -+ // -+ // svt_ret = eb_svt_enc_stream_header(svt_enc->svt_handle, &headerPtr); -+ // if (svt_ret != EB_ErrorNone) { -+ // av_log(avctx, AV_LOG_ERROR, "Error when build stream header.\n"); -+ // av_freep(&headerPtr->p_buffer); -+ // goto failed_init_enc; -+ // } -+ // -+ // avctx->extradata_size = headerPtr->n_filled_len; -+ // avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); -+ // if (!avctx->extradata) { -+ // av_log(avctx, AV_LOG_ERROR, -+ // "Cannot allocate VP9 header of size %d.\n", avctx->extradata_size); -+ // av_freep(&headerPtr->p_buffer); -+ // svt_ret = EB_ErrorInsufficientResources; -+ // goto failed_init_enc; -+ // } -+ // memcpy(avctx->extradata, headerPtr->p_buffer, avctx->extradata_size); -+ // -+ // av_freep(&headerPtr->p_buffer); -+ // } -+ return 0; -+ -+//failed_init_enc: -+// eb_deinit_encoder(svt_enc->svt_handle); -+failed_init_handle: -+ eb_vp9_deinit_handle(svt_enc->svt_handle); -+failed: -+ free_buffer(svt_enc); -+ return error_mapping(svt_ret); -+} -+ -+static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ EbBufferHeaderType *headerPtr = svt_enc->in_buf; -+ -+ if (!frame) { -+ EbBufferHeaderType headerPtrLast; -+ headerPtrLast.n_alloc_len = 0; -+ headerPtrLast.n_filled_len = 0; -+ headerPtrLast.n_tick_count = 0; -+ headerPtrLast.p_app_private = NULL; -+ headerPtrLast.p_buffer = NULL; -+ headerPtrLast.flags = EB_BUFFERFLAG_EOS; -+ -+ eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, &headerPtrLast); -+ 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, headerPtr); -+ -+ headerPtr->flags = 0; -+ headerPtr->p_app_private = NULL; -+ headerPtr->pts = frame->pts; -+ switch (frame->pict_type) { -+ case AV_PICTURE_TYPE_I: -+ headerPtr->pic_type = svt_enc->forced_idr > 0 ? EB_IDR_PICTURE : EB_I_PICTURE; -+ break; -+ case AV_PICTURE_TYPE_P: -+ headerPtr->pic_type = EB_P_PICTURE; -+ break; -+ case AV_PICTURE_TYPE_B: -+ headerPtr->pic_type = EB_B_PICTURE; -+ break; -+ default: -+ headerPtr->pic_type = EB_INVALID_PICTURE; -+ break; -+ } -+ eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, headerPtr); -+ -+ return 0; -+} -+ -+static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ EbBufferHeaderType *headerPtr; -+ EbErrorType svt_ret; -+ AVBufferRef *ref; -+ -+ if (EOS_TOTRIGGER == svt_enc->eos_flag) { -+ pkt = NULL; -+ return AVERROR_EOF; -+ } -+ -+ svt_ret = eb_vp9_svt_get_packet(svt_enc->svt_handle, &headerPtr, svt_enc->eos_flag); -+ if (svt_ret == EB_NoErrorEmptyQueue) -+ return AVERROR(EAGAIN); -+ -+ ref = av_buffer_pool_get(svt_enc->pool); -+ if (!ref) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); -+ eb_vp9_svt_release_out_buffer(&headerPtr); -+ return AVERROR(ENOMEM); -+ } -+ pkt->buf = ref; -+ pkt->data = ref->data; -+ -+ memcpy(pkt->data, headerPtr->p_buffer, headerPtr->n_filled_len); -+ pkt->size = headerPtr->n_filled_len; -+ pkt->pts = headerPtr->pts; -+ pkt->dts = headerPtr->dts; -+ if (headerPtr->pic_type == EB_IDR_PICTURE) -+ pkt->flags |= AV_PKT_FLAG_KEY; -+ if (headerPtr->pic_type == EB_NON_REF_PICTURE) -+ pkt->flags |= AV_PKT_FLAG_DISPOSABLE; -+ -+ if (headerPtr->flags & EB_BUFFERFLAG_SHOW_EXT) -+ pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_ON; -+ else -+ pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_OFF; -+ -+ if (EB_BUFFERFLAG_EOS & headerPtr->flags) -+ svt_enc->eos_flag = EOS_TOTRIGGER; -+ -+ eb_vp9_svt_release_out_buffer(&headerPtr); -+ return 0; -+} -+ -+static av_cold int eb_enc_close(AVCodecContext *avctx) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ -+ eb_vp9_deinit_encoder(svt_enc->svt_handle); -+ eb_vp9_deinit_handle(svt_enc->svt_handle); -+ -+ free_buffer(svt_enc); -+ -+ return 0; -+} -+ -+#define OFFSET(x) offsetof(SvtContext, x) -+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -+static const AVOption options[] = { -+ { "preset", "Encoding preset [1, 1]", -+ OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = 9 }, 0, 9, VE }, -+ -+ { "level", "Set level (level_idc)", OFFSET(level), -+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xff, VE, "level" }, -+ -+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ -+ { .i64 = value }, 0, 0, VE, "level" -+ { LEVEL("1", 10) }, -+ { LEVEL("2", 20) }, -+ { LEVEL("2.1", 21) }, -+ { LEVEL("3", 30) }, -+ { LEVEL("3.1", 31) }, -+ { LEVEL("4", 40) }, -+ { LEVEL("4.1", 41) }, -+ { LEVEL("5", 50) }, -+ { LEVEL("5.1", 51) }, -+ { LEVEL("5.2", 52) }, -+ { LEVEL("6", 60) }, -+ { LEVEL("6.1", 61) }, -+ { LEVEL("6.2", 62) }, -+#undef LEVEL -+ -+ { "tune", "Tune mode", OFFSET(tune), -+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE , "tune"}, -+ { "vq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "tune" }, -+ { "ssim", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "tune" }, -+ { "vmaf", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "tune" }, -+ -+ { "rc", "Bit rate control mode", OFFSET(rc_mode), -+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, 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" }, -+ { "cbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "rc" }, -+ -+ { "qp", "QP value for intra frames", OFFSET(qp), -+ AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 51, VE }, -+ -+ { "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_vp9", -+ .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" }, -+ { NULL }, -+}; -+ -+AVCodec ff_libsvt_vp9_encoder = { -+ .name = "libsvt_vp9", -+ .long_name = NULL_IF_CONFIG_SMALL("SVT-VP9(Scalable Video Technology for VP9) encoder"), -+ .priv_data_size = sizeof(SvtContext), -+ .type = AVMEDIA_TYPE_VIDEO, -+ .id = AV_CODEC_ID_VP9, -+ .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_NONE }, -+ .priv_class = &class, -+ .defaults = eb_enc_defaults, -+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, -+ .wrapper_name = "libsvt_vp9", -+}; -diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c -index 24d43c34ea..ba47bd6413 100644 ---- a/libavformat/dashenc.c -+++ b/libavformat/dashenc.c -@@ -1823,6 +1823,48 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) - return ret; - } - -+static int dash_write_packet_vp9(AVFormatContext *s, AVPacket *pkt) -+{ -+ int ret; -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ uint8_t *saved_data = pkt->data; -+ int saved_size = pkt->size; -+ int64_t saved_pts = pkt->pts; -+ -+ // Main frame -+ pkt->data = saved_data; -+ pkt->size = saved_size - 4; -+ pkt->pts = saved_pts; -+ ret = dash_write_packet(s, pkt); -+ -+ // Latter 4 one-byte repeated frames -+ pkt->data = saved_data + saved_size - 4; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 2; -+ ret = dash_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 3; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 1; -+ ret = dash_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 2; -+ pkt->size = 1; -+ pkt->pts = saved_pts; -+ ret = dash_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 1; -+ pkt->size = 1; -+ pkt->pts = saved_pts + 1; -+ ret = dash_write_packet(s, pkt); -+ } -+ else{ -+ ret = dash_write_packet(s, pkt); -+ } -+ -+ return ret; -+} -+ - static int dash_write_trailer(AVFormatContext *s) - { - DASHContext *c = s->priv_data; -@@ -1870,6 +1912,11 @@ static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt - DASHContext *c = s->priv_data; - OutputStream *os = &c->streams[avpkt->stream_index]; - AVFormatContext *oc = os->ctx; -+ -+ if ((avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (oc->oformat->check_bitstream) { - int ret; - AVPacket pkt = *avpkt; -@@ -1942,7 +1989,7 @@ AVOutputFormat ff_dash_muxer = { - .flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE, - .init = dash_init, - .write_header = dash_write_header, -- .write_packet = dash_write_packet, -+ .write_packet = dash_write_packet_vp9, - .write_trailer = dash_write_trailer, - .deinit = dash_free, - .check_bitstream = dash_check_bitstream, -diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c -index adf72117e9..05f08131a6 100644 ---- a/libavformat/ivfenc.c -+++ b/libavformat/ivfenc.c -@@ -63,9 +63,33 @@ static int ivf_write_packet(AVFormatContext *s, AVPacket *pkt) - AVIOContext *pb = s->pb; - IVFEncContext *ctx = s->priv_data; - -- avio_wl32(pb, pkt->size); -- avio_wl64(pb, pkt->pts); -- avio_write(pb, pkt->data, pkt->size); -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ avio_wl32(pb, pkt->size - 4); -+ avio_wl64(pb, pkt->pts); -+ avio_write(pb, pkt->data, pkt->size - 4); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts - 2); -+ avio_write(pb, pkt->data + pkt->size - 4, 1); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts - 1); -+ avio_write(pb, pkt->data + pkt->size - 3, 1); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts); -+ avio_write(pb, pkt->data + pkt->size - 2, 1); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts + 1); -+ avio_write(pb, pkt->data + pkt->size - 1, 1); -+ } -+ else { -+ avio_wl32(pb, pkt->size); -+ avio_wl64(pb, pkt->pts); -+ avio_write(pb, pkt->data, pkt->size); -+ } -+ - if (ctx->frame_cnt) - ctx->sum_delta_pts += pkt->pts - ctx->last_pts; - ctx->frame_cnt++; -@@ -95,6 +119,10 @@ static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) - int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (st->codecpar->codec_id == AV_CODEC_ID_VP9) - ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL); - else if (st->codecpar->codec_id == AV_CODEC_ID_AV1) -diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c -index cef504fa05..de8e3872c1 100644 ---- a/libavformat/matroskaenc.c -+++ b/libavformat/matroskaenc.c -@@ -161,6 +161,9 @@ typedef struct MatroskaMuxContext { - int64_t *stream_duration_offsets; - - int allow_raw_vfw; -+ -+ int simple_block_timecode; -+ int accumulated_cluster_timecode; - } MatroskaMuxContext; - - /** 2 bytes * 7 for EBML IDs, 7 1-byte EBML lengths, 6 1-byte uint, -@@ -2180,7 +2183,13 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, - put_ebml_num(pb, size + 4, 0); - // this assumes stream_index is less than 126 - avio_w8(pb, 0x80 | track_number); -- avio_wb16(pb, ts - mkv->cluster_pts); -+ -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ avio_wb16(pb, mkv->simple_block_timecode); -+ else -+ avio_wb16(pb, ts - mkv->cluster_pts); -+ - avio_w8(pb, (blockid == MATROSKA_ID_SIMPLEBLOCK && keyframe) ? (1 << 7) : 0); - avio_write(pb, data + offset, size); - if (data != pkt->data) -@@ -2386,6 +2395,8 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ - int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; - int64_t relative_packet_pos; - int dash_tracknum = mkv->is_dash ? mkv->dash_track_number : pkt->stream_index + 1; -+ double fps = 0; -+ int pts_interval = 0; - - if (ts == AV_NOPTS_VALUE) { - av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); -@@ -2401,12 +2412,23 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ - } - } - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { -+ fps = av_q2d(s->streams[pkt->stream_index]->avg_frame_rate); -+ pts_interval = 1000 / fps; -+ } -+ - if (mkv->cluster_pos == -1) { - mkv->cluster_pos = avio_tell(s->pb); - ret = start_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER); - if (ret < 0) - return ret; -- put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); -+ -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, -+ mkv->accumulated_cluster_timecode + pts_interval); -+ else -+ put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); -+ - mkv->cluster_pts = FFMAX(0, ts); - } - pb = mkv->cluster_bc; -@@ -2414,7 +2436,67 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ - relative_packet_pos = avio_tell(pb); - - if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { -- mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ uint8_t *saved_data = pkt->data; -+ int saved_size = pkt->size; -+ int64_t saved_pts = pkt->pts; -+ // Main frame -+ pkt->data = saved_data; -+ pkt->size = saved_size - 4; -+ pkt->pts = saved_pts; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ -+ // Latter 4 one-byte repeated frames -+ pkt->data = saved_data + saved_size - 4; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 2; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ -+ pkt->data = saved_data + saved_size - 3; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 1; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ -+ pkt->data = saved_data + saved_size - 2; -+ pkt->size = 1; -+ pkt->pts = saved_pts; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ -+ pkt->data = saved_data + saved_size - 1; -+ pkt->size = 1; -+ pkt->pts = saved_pts + 1; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ } else { -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF) { -+ GetBitContext gb; -+ int invisible, profile; -+ -+ if ((ret = init_get_bits8(&gb, pkt->data, pkt->size)) < 0) -+ return ret; -+ -+ get_bits(&gb, 2); // frame marker -+ profile = get_bits1(&gb); -+ profile |= get_bits1(&gb) << 1; -+ if (profile == 3) profile += get_bits1(&gb); -+ -+ if (get_bits1(&gb)) { -+ invisible = 0; -+ } else { -+ get_bits1(&gb); // keyframe -+ invisible = !get_bits1(&gb); -+ } -+ -+ if (!invisible) -+ mkv->simple_block_timecode += pts_interval; -+ } -+ } -+ - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && (par->codec_type == AVMEDIA_TYPE_VIDEO && keyframe || add_cue)) { - ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, -1); - if (ret < 0) return ret; -@@ -2473,8 +2555,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) - - if (mkv->tracks[pkt->stream_index].write_dts) - cluster_time = pkt->dts - mkv->cluster_pts; -- else -- cluster_time = pkt->pts - mkv->cluster_pts; -+ else { -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ cluster_time = mkv->accumulated_cluster_timecode - mkv->cluster_pts; -+ else -+ cluster_time = pkt->pts - mkv->cluster_pts; -+ } - cluster_time += mkv->tracks[pkt->stream_index].ts_offset; - - // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or -@@ -2502,6 +2589,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) - } - - if (mkv->cluster_pos != -1 && start_new_cluster) { -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { -+ // Reset Timecode for new cluster. -+ mkv->accumulated_cluster_timecode += mkv->simple_block_timecode; -+ mkv->simple_block_timecode = 0; -+ } -+ - mkv_start_new_cluster(s, pkt); - } - -@@ -2736,6 +2830,10 @@ static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) - int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { - if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) - ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); -diff --git a/libavformat/movenc.c b/libavformat/movenc.c -index 4d4d0cd024..eeebf10147 100644 ---- a/libavformat/movenc.c -+++ b/libavformat/movenc.c -@@ -5624,7 +5624,43 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) - } - } - -- return ff_mov_write_packet(s, pkt); -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ uint8_t *saved_data = pkt->data; -+ int saved_size = pkt->size; -+ int64_t saved_pts = pkt->pts; -+ -+ // Main frame -+ pkt->data = saved_data; -+ pkt->size = saved_size - 4; -+ pkt->pts = saved_pts; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ // Latter 4 one-byte repeated frames -+ pkt->data = saved_data + saved_size - 4; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 2; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 3; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 1; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 2; -+ pkt->size = 1; -+ pkt->pts = saved_pts; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 1; -+ pkt->size = 1; -+ pkt->pts = saved_pts + 1; -+ ret = ff_mov_write_packet(s, pkt); -+ } -+ else{ -+ ret = ff_mov_write_packet(s, pkt); -+ } -+ -+ return ret; - } - - static int mov_write_subtitle_end_packet(AVFormatContext *s, -@@ -6763,6 +6799,10 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) - int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { - if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) - ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); --- -2.20.1 diff --git a/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch b/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch index e7a8693..e095c21 100644 --- a/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch +++ b/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch @@ -1,4 +1,4 @@ -From 3eb3aa5e26fb0f0f2724ce8ec50b8a54d206cb25 Mon Sep 17 00:00:00 2001 +From c39ca2bf72f7b83d5810c142beba97abcfbc7147 Mon Sep 17 00:00:00 2001 From: hassene Date: Fri, 15 Feb 2019 17:43:54 -0800 Subject: [PATCH] Add ability for ffmpeg to run svt vp9 @@ -12,74 +12,74 @@ Signed-off-by: Guo Jiansheng libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 2 + - libavcodec/libsvt_vp9.c | 482 ++++++++++++++++++++++++++++++++++++++ + libavcodec/libsvt_vp9.c | 481 ++++++++++++++++++++++++++++++++++++++ libavformat/dashenc.c | 49 +++- libavformat/ivfenc.c | 34 ++- libavformat/matroskaenc.c | 108 ++++++++- libavformat/movenc.c | 42 +++- - 9 files changed, 713 insertions(+), 10 deletions(-) + 9 files changed, 712 insertions(+), 10 deletions(-) create mode 100644 libavcodec/libsvt_vp9.c diff --git a/configure b/configure -index 34c2adb4a4..1391970576 100755 +index 34c2adb4a4..ea125e68ae 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] +@@ -278,6 +278,7 @@ External library support: + --enable-libvorbis enable Vorbis en/decoding via libvorbis, + native implementation exists [no] + --enable-libvpx enable VP8 and VP9 de/encoding via libvpx [no] + --enable-libsvtvp9 enable VP9 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] -@@ -1793,6 +1794,7 @@ EXTERNAL_LIBRARY_LIST=" - libspeex - libsrt - libssh + --enable-libwavpack enable wavpack encoding via libwavpack [no] + --enable-libwebp enable WebP encoding via libwebp [no] + --enable-libx264 enable H.264 encoding via x264 [no] +@@ -1800,6 +1801,7 @@ EXTERNAL_LIBRARY_LIST=" + libv4l2 + libvorbis + libvpx + libsvtvp9 - libtensorflow - libtesseract - libtheora -@@ -3191,6 +3193,7 @@ libshine_encoder_select="audio_frame_queue" - libspeex_decoder_deps="libspeex" - libspeex_encoder_deps="libspeex" - libspeex_encoder_select="audio_frame_queue" + libwavpack + libwebp + libxml2 +@@ -3201,6 +3203,7 @@ libvpx_vp8_decoder_deps="libvpx" + libvpx_vp8_encoder_deps="libvpx" + libvpx_vp9_decoder_deps="libvpx" + libvpx_vp9_encoder_deps="libvpx" +libsvt_vp9_encoder_deps="libsvtvp9" - libtheora_encoder_deps="libtheora" - libtwolame_encoder_deps="libtwolame" - libvo_amrwbenc_encoder_deps="libvo_amrwbenc" -@@ -6263,6 +6266,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 + libwavpack_encoder_deps="libwavpack" + libwavpack_encoder_select="audio_frame_queue" + libwebp_encoder_deps="libwebp" +@@ -6299,6 +6302,7 @@ enabled libvpx && { + fi + } + +enabled libsvtvp9 && require_pkg_config libsvtvp9 SvtVp9Enc EbSvtVp9Enc.h eb_vp9_svt_init_handle - 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 + enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput -lwavpack + enabled libwebp && { + enabled libwebp_encoder && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion diff --git a/libavcodec/Makefile b/libavcodec/Makefile -index 3cd73fbcc6..eb138776b7 100644 +index 3cd73fbcc6..cc756acfe7 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 +@@ -1001,6 +1001,7 @@ OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o + OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o + OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o + OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o +OBJS-$(CONFIG_LIBSVT_VP9_ENCODER) += libsvt_vp9.o - OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o - OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o - OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o + OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o + OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o + OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c -index d2f9a39ce5..9849fc1875 100644 +index d2f9a39ce5..205333db96 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c -@@ -707,6 +707,7 @@ extern AVCodec ff_librsvg_decoder; - extern AVCodec ff_libshine_encoder; - extern AVCodec ff_libspeex_encoder; - extern AVCodec ff_libspeex_decoder; +@@ -716,6 +716,7 @@ extern AVCodec ff_libvpx_vp8_encoder; + extern AVCodec ff_libvpx_vp8_decoder; + extern AVCodec ff_libvpx_vp9_encoder; + extern AVCodec ff_libvpx_vp9_decoder; +extern AVCodec ff_libsvt_vp9_encoder; - extern AVCodec ff_libtheora_encoder; - extern AVCodec ff_libtwolame_encoder; - extern AVCodec ff_libvo_amrwbenc_encoder; + extern AVCodec ff_libwavpack_encoder; + /* preferred over libwebp */ + extern AVCodec ff_libwebp_anim_encoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index d234271c5b..0d903571b3 100644 --- a/libavcodec/avcodec.h @@ -87,18 +87,18 @@ index d234271c5b..0d903571b3 100644 @@ -1527,6 +1527,8 @@ typedef struct AVPacket { */ #define AV_PKT_FLAG_DISPOSABLE 0x0010 - + +#define AV_PKT_FLAG_SVT_VP9_EXT_ON 0x10000 // Indicating SVT VP9 frame header ext on +#define AV_PKT_FLAG_SVT_VP9_EXT_OFF 0x20000 // Indicating SVT VP9 frame header ext off - + enum AVSideDataParamChangeFlags { AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, diff --git a/libavcodec/libsvt_vp9.c b/libavcodec/libsvt_vp9.c new file mode 100644 -index 0000000000..d2c4740e5c +index 0000000000..037467366e --- /dev/null +++ b/libavcodec/libsvt_vp9.c -@@ -0,0 +1,482 @@ +@@ -0,0 +1,481 @@ +/* +* Scalable Video Technology for VP9 encoder library plugin +* @@ -123,7 +123,6 @@ index 0000000000..d2c4740e5c + +#include +#include "EbSvtVp9ErrorCodes.h" -+#include "EbSvtVp9Time.h" +#include "EbSvtVp9Enc.h" + +#include "libavutil/common.h" @@ -588,7 +587,7 @@ index 24d43c34ea..ba47bd6413 100644 @@ -1823,6 +1823,48 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; } - + +static int dash_write_packet_vp9(AVFormatContext *s, AVPacket *pkt) +{ + int ret; @@ -662,7 +661,7 @@ index adf72117e9..05f08131a6 100644 @@ -63,9 +63,33 @@ static int ivf_write_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; IVFEncContext *ctx = s->priv_data; - + - avio_wl32(pb, pkt->size); - avio_wl64(pb, pkt->pts); - avio_write(pb, pkt->data, pkt->size); @@ -699,7 +698,7 @@ index adf72117e9..05f08131a6 100644 @@ -95,6 +119,10 @@ static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) int ret = 1; AVStream *st = s->streams[pkt->stream_index]; - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) + return 0; @@ -713,13 +712,13 @@ index cef504fa05..de8e3872c1 100644 +++ b/libavformat/matroskaenc.c @@ -161,6 +161,9 @@ typedef struct MatroskaMuxContext { int64_t *stream_duration_offsets; - + int allow_raw_vfw; + + int simple_block_timecode; + int accumulated_cluster_timecode; } MatroskaMuxContext; - + /** 2 bytes * 7 for EBML IDs, 7 1-byte EBML lengths, 6 1-byte uint, @@ -2180,7 +2183,13 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, put_ebml_num(pb, size + 4, 0); @@ -742,13 +741,13 @@ index cef504fa05..de8e3872c1 100644 int dash_tracknum = mkv->is_dash ? mkv->dash_track_number : pkt->stream_index + 1; + double fps = 0; + int pts_interval = 0; - + if (ts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); @@ -2401,12 +2412,23 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ } } - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { + fps = av_q2d(s->streams[pkt->stream_index]->avg_frame_rate); + pts_interval = 1000 / fps; @@ -772,7 +771,7 @@ index cef504fa05..de8e3872c1 100644 pb = mkv->cluster_bc; @@ -2414,7 +2436,67 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ relative_packet_pos = avio_tell(pb); - + if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { - mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); + if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { @@ -840,7 +839,7 @@ index cef504fa05..de8e3872c1 100644 ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, -1); if (ret < 0) return ret; @@ -2473,8 +2555,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) - + if (mkv->tracks[pkt->stream_index].write_dts) cluster_time = pkt->dts - mkv->cluster_pts; - else @@ -853,11 +852,11 @@ index cef504fa05..de8e3872c1 100644 + cluster_time = pkt->pts - mkv->cluster_pts; + } cluster_time += mkv->tracks[pkt->stream_index].ts_offset; - + // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or @@ -2502,6 +2589,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) } - + if (mkv->cluster_pos != -1 && start_new_cluster) { + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { @@ -868,11 +867,11 @@ index cef504fa05..de8e3872c1 100644 + mkv_start_new_cluster(s, pkt); } - + @@ -2736,6 +2830,10 @@ static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) int ret = 1; AVStream *st = s->streams[pkt->stream_index]; - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) + return 0; @@ -887,7 +886,7 @@ index 4d4d0cd024..eeebf10147 100644 @@ -5624,7 +5624,43 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) } } - + - return ff_mov_write_packet(s, pkt); + if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { + uint8_t *saved_data = pkt->data; @@ -927,12 +926,12 @@ index 4d4d0cd024..eeebf10147 100644 + + return ret; } - + static int mov_write_subtitle_end_packet(AVFormatContext *s, @@ -6763,6 +6799,10 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) int ret = 1; AVStream *st = s->streams[pkt->stream_index]; - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) + return 0; @@ -940,6 +939,5 @@ index 4d4d0cd024..eeebf10147 100644 if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); --- -2.23.0.windows.1 - +-- +2.25.1 diff --git a/ffmpeg_plugin/README.md b/ffmpeg_plugin/README.md index f1bf4df..6b98ac7 100644 --- a/ffmpeg_plugin/README.md +++ b/ffmpeg_plugin/README.md @@ -1,32 +1,77 @@ -# svt-vp9 ffmpeg plugin installation - -1. Build and install SVT-VP9 -- git clone https://github.com/OpenVisualCloud/SVT-VP9 -- cd SVT-VP9 -- cd Build && cmake .. && make -j `nproc` && sudo make install - -2. Apply SVT-VP9 plugin and enable libsvtvp9 to FFmpeg -- git clone https://github.com/FFmpeg/FFmpeg ffmpeg -- cd ffmpeg -- git checkout -b tag4.2.2 n4.2.2 -- export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib -- export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig -- SVT-VP9 alone: - - git apply SVT-VP9/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch - - ./configure --enable-libsvtvp9 -- Based on SVT-HEVC & SVT-AV1: - - git apply SVT-HEVC/ffmpeg_plugin/0001-lavc-svt_hevc-add-libsvt-hevc-encoder-wrapper.patch - - git apply SVT-AV1/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-av1-with-svt-hevc.patch - - git apply SVT-VP9/ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-svt-hevc-av1.patch - - ./configure --enable-libsvthevc --enable-libsvtav1 --enable-libsvtvp9 -- make -j $(nproc) - -- Note: patches for FFmpeg n4.2.3/master are alse provided: - - n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch - - n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch - - master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch - - master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch - -3. Verify -- ./ffmpeg -i input.mp4 -c:v libsvt_vp9 -rc 1 -b:v 10M -preset 1 -y test.ivf -- ./ffmpeg -i input.mp4 -vframes 1000 -c:v libsvt_vp9 -y test.mp4 +# SVT-VP9 ffmpeg plugin installation + +Assumes you have a bash (or similar) shell along with commands such as + +- git +- cmake +- make +- pkg-config +- cc + +If you do not have any of these, please consult your friendly web browser to determine what is the best way to get these on your system, else ask IT. + +If you are on windows, the recommended way to get these tools and build FFmpeg is through [msys2](https://www.msys2.org/). The way to get these specific tools will not be provided here though. + +If you are trying to compile FFmpeg using MSVC, please try to consult FFmpeg's [wiki page](https://trac.ffmpeg.org/wiki/CompilationGuide/MSVC) about it. + +## Build and install SVT-VP9 + +```bash +git clone https://github.com/OpenVisualCloud/SVT-VP9.git +cd SVT-VP9/Build +# Adjust this line to add any other cmake related options +cmake .. -DCMAKE_BUILD_TYPE=Release +make -j $(nproc) +sudo make install +cd .. +``` + +## Enable SVT-VP9 plugin + +```bash +# Adjust /usr/local to your chosen prefix +export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib +export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig +git clone https://github.com/FFmpeg/FFmpeg.git ffmpeg +cd ffmpeg +``` + +Which patch to apply will depend on which version of FFmpeg you are going to use. + +master: + +```bash +git apply ../ffmpeg_plugin/master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch +``` + +n4.2.3 tag: + +```bash +git checkout n4.2.3 +git apply ../ffmpeg_plugin/n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch +``` + +n4.2.2 tag: + +```bash +git checkout n4.2.2 +git apply ../ffmpeg_plugin/0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch +``` + +```bash +./configure --enable-libsvtvp9 +make -j $(nproc) +``` + +## Verify + +Run basic tests to check if `libsvt_vp9` works + +```bash +./ffmpeg -f lavfi -i testsrc=duration=1:size=1280x720:rate=30 -c:v libsvt_vp9 -rc 1 -b:v 10M -preset 1 -y test.ivf +./ffmpeg -f lavfi -i testsrc=duration=1:size=1280x720:rate=30 -vframes 1000 -c:v libsvt_vp9 -y test.mp4 +``` + +## Note + +These patches can be applied in any ordering permutation along with the other SVT encoders, there is no strict ordering diff --git a/ffmpeg_plugin/master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch b/ffmpeg_plugin/master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch deleted file mode 100644 index 66b88f0..0000000 --- a/ffmpeg_plugin/master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch +++ /dev/null @@ -1,974 +0,0 @@ -From 1b3939631a36826439a5ae759107ef40716473c0 Mon Sep 17 00:00:00 2001 -From: Jing Sun -Date: Mon, 1 Apr 2019 17:17:00 +0800 -Subject: [PATCH] Add ability for ffmpeg to run svt vp9 with hevc & av1 - -Signed-off-by: hassene -Signed-off-by: Jing Sun -Signed-off-by: Austin Hu -Signed-off-by: Guo Jiansheng ---- - configure | 4 + - libavcodec/Makefile | 1 + - libavcodec/allcodecs.c | 1 + - libavcodec/avcodec.h | 3 + - libavcodec/libsvt_vp9.c | 504 ++++++++++++++++++++++++++++++++++++++ - libavformat/dashenc.c | 49 +++- - libavformat/ivfenc.c | 30 ++- - libavformat/matroskaenc.c | 112 ++++++++- - libavformat/movenc.c | 41 +++- - 9 files changed, 732 insertions(+), 13 deletions(-) - create mode 100644 libavcodec/libsvt_vp9.c - -diff --git a/configure b/configure -index 8188f83660..d79c1aa0d7 100755 ---- a/configure -+++ b/configure -@@ -269,6 +269,7 @@ External library support: - --enable-libssh enable SFTP protocol via libssh [no] - --enable-libsvthevc enable HEVC encoding via svt [no] - --enable-libsvtav1 enable AV1 encoding via svt [no] -+ --enable-libsvtvp9 enable VP9 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] -@@ -1807,6 +1808,7 @@ EXTERNAL_LIBRARY_LIST=" - libssh - libsvthevc - libsvtav1 -+ libsvtvp9 - libtensorflow - libtesseract - libtheora -@@ -3246,6 +3248,7 @@ libspeex_encoder_deps="libspeex" - libspeex_encoder_select="audio_frame_queue" - libsvt_hevc_encoder_deps="libsvthevc" - libsvt_av1_encoder_deps="libsvtav1" -+libsvt_vp9_encoder_deps="libsvtvp9" - libtheora_encoder_deps="libtheora" - libtwolame_encoder_deps="libtwolame" - libvo_amrwbenc_encoder_deps="libvo_amrwbenc" -@@ -6380,6 +6383,7 @@ enabled libspeex && require_pkg_config libspeex speex speex/speex.h spe - 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 libsvtav1 && require_pkg_config libsvtav1 SvtAv1Enc EbSvtAv1Enc.h svt_av1_enc_init_handle -+enabled libsvtvp9 && require_pkg_config libsvtvp9 SvtVp9Enc EbSvtVp9Enc.h eb_vp9_svt_init_handle - 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 0dedc8a19c..a26dcb0ffa 100644 ---- a/libavcodec/Makefile -+++ b/libavcodec/Makefile -@@ -1026,6 +1026,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o - OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o - OBJS-$(CONFIG_LIBSVT_HEVC_ENCODER) += libsvt_hevc.o - OBJS-$(CONFIG_LIBSVT_AV1_ENCODER) += libsvt_av1.o -+OBJS-$(CONFIG_LIBSVT_VP9_ENCODER) += libsvt_vp9.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 7a6bd449fd..fa97a393ba 100644 ---- a/libavcodec/allcodecs.c -+++ b/libavcodec/allcodecs.c -@@ -730,6 +730,7 @@ extern AVCodec ff_libspeex_encoder; - extern AVCodec ff_libspeex_decoder; - extern AVCodec ff_libsvt_hevc_encoder; - extern AVCodec ff_libsvt_av1_encoder; -+extern AVCodec ff_libsvt_vp9_encoder; - extern AVCodec ff_libtheora_encoder; - extern AVCodec ff_libtwolame_encoder; - extern AVCodec ff_libvo_amrwbenc_encoder; -diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h -index c91b2fd169..ae4a8de889 100644 ---- a/libavcodec/avcodec.h -+++ b/libavcodec/avcodec.h -@@ -405,6 +405,9 @@ typedef struct RcOverride{ - * Export encoder Producer Reference Time through packet side data - */ - #define AV_CODEC_EXPORT_DATA_PRFT (1 << 1) -+ -+#define AV_PKT_FLAG_SVT_VP9_EXT_ON 0x10000 // Indicating SVT VP9 frame header ext on -+#define AV_PKT_FLAG_SVT_VP9_EXT_OFF 0x20000 // Indicating SVT VP9 frame header ext off - /** - * Decoding only. - * Export the AVVideoEncParams structure through frame side data. -diff --git a/libavcodec/libsvt_vp9.c b/libavcodec/libsvt_vp9.c -new file mode 100644 -index 0000000000..6bd6243de0 ---- /dev/null -+++ b/libavcodec/libsvt_vp9.c -@@ -0,0 +1,504 @@ -+/* -+* Scalable Video Technology for VP9 encoder library plugin -+* -+* Copyright (c) 2018 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 -+#include "EbSvtVp9ErrorCodes.h" -+#include "EbSvtVp9Time.h" -+#include "EbSvtVp9Enc.h" -+ -+#include "libavutil/common.h" -+#include "libavutil/frame.h" -+#include "libavutil/opt.h" -+ -+#include "internal.h" -+#include "encode.h" -+#include "avcodec.h" -+ -+typedef enum eos_status { -+ EOS_NOT_REACHED = 0, -+ EOS_REACHED, -+ EOS_TOTRIGGER -+}EOS_STATUS; -+ -+typedef struct SvtContext { -+ AVClass *class; -+ -+ EbSvtVp9EncConfiguration enc_params; -+ EbComponentType *svt_handle; -+ -+ EbBufferHeaderType *in_buf; -+ int raw_size; -+ -+ AVFrame *frame; -+ -+ AVBufferPool* pool; -+ -+ EOS_STATUS eos_flag; -+ -+ // User options. -+ int enc_mode; -+ int rc_mode; -+ int tune; -+ int qp; -+ -+ int forced_idr; -+ -+ int level; -+ -+ int base_layer_switch_mode; -+} SvtContext; -+ -+static int error_mapping(EbErrorType 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) -+{ -+ if (svt_enc->in_buf) { -+ EbSvtEncInput *in_data = (EbSvtEncInput *)svt_enc->in_buf->p_buffer; -+ av_freep(&in_data); -+ av_freep(&svt_enc->in_buf); -+ } -+ av_buffer_pool_uninit(&svt_enc->pool); -+} -+ -+static int alloc_buffer(EbSvtVp9EncConfiguration *config, SvtContext *svt_enc) -+{ -+ const size_t luma_size_8bit = -+ config->source_width * config->source_height; -+ const size_t luma_size_10bit = -+ (config->encoder_bit_depth > 8) ? luma_size_8bit : 0; -+ -+ EbSvtEncInput *in_data; -+ -+ svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3 / 2; -+ -+ // allocate buffer for in and out -+ svt_enc->in_buf = av_mallocz(sizeof(*svt_enc->in_buf)); -+ if (!svt_enc->in_buf) -+ goto failed; -+ -+ -+ svt_enc->in_buf->p_buffer = (unsigned char *)av_mallocz(sizeof(*in_data)); -+ if (!svt_enc->in_buf->p_buffer) -+ goto failed; -+ -+ svt_enc->in_buf->size = sizeof(*svt_enc->in_buf); -+ svt_enc->in_buf->p_app_private = NULL; -+ -+ svt_enc->pool = av_buffer_pool_init(svt_enc->raw_size, NULL); -+ if (!svt_enc->pool) -+ goto failed; -+ -+ return 0; -+ -+failed: -+ free_buffer(svt_enc); -+ return AVERROR(ENOMEM); -+} -+ -+static int config_enc_params(EbSvtVp9EncConfiguration *param, -+ AVCodecContext *avctx) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ int ret; -+ int ten_bits = 0; -+ -+ param->source_width = avctx->width; -+ param->source_height = avctx->height; -+ -+ if (avctx->pix_fmt == AV_PIX_FMT_YUV420P10LE) { -+ av_log(avctx, AV_LOG_DEBUG , "Encoder 10 bits depth input\n"); -+ // Disable Compressed 10-bit format default -+ ten_bits = 1; -+ } -+ -+ // Update param from options -+ param->enc_mode = svt_enc->enc_mode; -+ param->level = svt_enc->level; -+ param->rate_control_mode = svt_enc->rc_mode; -+ param->tune = svt_enc->tune; -+ param->base_layer_switch_mode = svt_enc->base_layer_switch_mode; -+ param->qp = svt_enc->qp; -+ -+ param->target_bit_rate = avctx->bit_rate; -+ if (avctx->gop_size > 0) -+ param->intra_period = avctx->gop_size - 1; -+ -+ if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { -+ param->frame_rate_numerator = avctx->framerate.num; -+ param->frame_rate_denominator = avctx->framerate.den * avctx->ticks_per_frame; -+ } else { -+ param->frame_rate_numerator = avctx->time_base.den; -+ param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame; -+ } -+ -+ if (param->rate_control_mode) { -+ param->max_qp_allowed = avctx->qmax; -+ param->min_qp_allowed = avctx->qmin; -+ } -+ -+ if (ten_bits) { -+ param->encoder_bit_depth = 10; -+ } -+ -+ ret = alloc_buffer(param, svt_enc); -+ -+ return ret; -+} -+ -+static void read_in_data(EbSvtVp9EncConfiguration *config, -+ const AVFrame *frame, -+ EbBufferHeaderType *headerPtr) -+{ -+ uint8_t is16bit = config->encoder_bit_depth > 8; -+ uint64_t luma_size = -+ (uint64_t)config->source_width * config->source_height<< is16bit; -+ EbSvtEncInput *in_data = (EbSvtEncInput *)headerPtr->p_buffer; -+ -+ // support yuv420p and yuv420p010 -+ in_data->luma = frame->data[0]; -+ in_data->cb = frame->data[1]; -+ in_data->cr = frame->data[2]; -+ -+ // stride info -+ in_data->y_stride = frame->linesize[0] >> is16bit; -+ in_data->cb_stride = frame->linesize[1] >> is16bit; -+ in_data->cr_stride = frame->linesize[2] >> is16bit; -+ -+ headerPtr->n_filled_len += luma_size * 3/2u; -+} -+ -+static av_cold int eb_enc_init(AVCodecContext *avctx) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ EbErrorType svt_ret; -+ -+ svt_enc->eos_flag = EOS_NOT_REACHED; -+ -+ svt_ret = eb_vp9_svt_init_handle(&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 = eb_vp9_svt_enc_set_parameter(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 = eb_vp9_init_encoder(svt_enc->svt_handle); -+ if (svt_ret != EB_ErrorNone) { -+ av_log(avctx, AV_LOG_ERROR, "Error init encoder\n"); -+ goto failed_init_handle; -+ } -+ -+ svt_enc->frame = av_frame_alloc(); -+ if (!svt_enc->frame) -+ return AVERROR(ENOMEM); -+ -+ // if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { -+ // EbBufferHeaderType* headerPtr; -+ // headerPtr->size = sizeof(headerPtr); -+ // headerPtr->n_filled_len = 0; /* in/out */ -+ // headerPtr->p_buffer = av_malloc(10 * 1024 * 1024); -+ // headerPtr->n_alloc_len = (10 * 1024 * 1024); -+ // -+ // if (!headerPtr->p_buffer) { -+ // av_log(avctx, AV_LOG_ERROR, -+ // "Cannot allocate buffer size %d.\n", headerPtr->n_alloc_len); -+ // svt_ret = EB_ErrorInsufficientResources; -+ // goto failed_init_enc; -+ // } -+ // -+ // svt_ret = eb_svt_enc_stream_header(svt_enc->svt_handle, &headerPtr); -+ // if (svt_ret != EB_ErrorNone) { -+ // av_log(avctx, AV_LOG_ERROR, "Error when build stream header.\n"); -+ // av_freep(&headerPtr->p_buffer); -+ // goto failed_init_enc; -+ // } -+ // -+ // avctx->extradata_size = headerPtr->n_filled_len; -+ // avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); -+ // if (!avctx->extradata) { -+ // av_log(avctx, AV_LOG_ERROR, -+ // "Cannot allocate VP9 header of size %d.\n", avctx->extradata_size); -+ // av_freep(&headerPtr->p_buffer); -+ // svt_ret = EB_ErrorInsufficientResources; -+ // goto failed_init_enc; -+ // } -+ // memcpy(avctx->extradata, headerPtr->p_buffer, avctx->extradata_size); -+ // -+ // av_freep(&headerPtr->p_buffer); -+ // } -+ return 0; -+ -+//failed_init_enc: -+// eb_deinit_encoder(svt_enc->svt_handle); -+failed_init_handle: -+ eb_vp9_deinit_handle(svt_enc->svt_handle); -+failed: -+ free_buffer(svt_enc); -+ return error_mapping(svt_ret); -+} -+ -+static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ EbBufferHeaderType *headerPtr = svt_enc->in_buf; -+ -+ if (!frame) { -+ if (svt_enc->eos_flag == EOS_REACHED) -+ return 0; -+ -+ EbBufferHeaderType headerPtrLast; -+ headerPtrLast.n_alloc_len = 0; -+ headerPtrLast.n_filled_len = 0; -+ headerPtrLast.n_tick_count = 0; -+ headerPtrLast.p_app_private = NULL; -+ headerPtrLast.p_buffer = NULL; -+ headerPtrLast.flags = EB_BUFFERFLAG_EOS; -+ -+ eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, &headerPtrLast); -+ 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, headerPtr); -+ -+ headerPtr->flags = 0; -+ headerPtr->p_app_private = NULL; -+ headerPtr->pts = frame->pts; -+ switch (frame->pict_type) { -+ case AV_PICTURE_TYPE_I: -+ headerPtr->pic_type = svt_enc->forced_idr > 0 ? EB_IDR_PICTURE : EB_I_PICTURE; -+ break; -+ case AV_PICTURE_TYPE_P: -+ headerPtr->pic_type = EB_P_PICTURE; -+ break; -+ case AV_PICTURE_TYPE_B: -+ headerPtr->pic_type = EB_B_PICTURE; -+ break; -+ default: -+ headerPtr->pic_type = EB_INVALID_PICTURE; -+ break; -+ } -+ eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, headerPtr); -+ -+ return 0; -+} -+ -+static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ EbBufferHeaderType *headerPtr; -+ EbErrorType svt_ret; -+ AVFrame *frame = svt_enc->frame; -+ AVBufferRef *ref; -+ int ret; -+ -+ if (EOS_TOTRIGGER == svt_enc->eos_flag) { -+ pkt = NULL; -+ return AVERROR_EOF; -+ } -+ -+ ret = ff_encode_get_frame(avctx, frame); -+ if (ret < 0 && ret != AVERROR_EOF) -+ return ret; -+ if (ret == AVERROR_EOF) -+ frame = NULL; -+ -+ eb_send_frame(avctx, frame); -+ av_frame_unref(svt_enc->frame); -+ -+ svt_ret = eb_vp9_svt_get_packet(svt_enc->svt_handle, &headerPtr, svt_enc->eos_flag); -+ if (svt_ret == EB_NoErrorEmptyQueue) -+ return AVERROR(EAGAIN); -+ -+ ref = av_buffer_pool_get(svt_enc->pool); -+ if (!ref) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); -+ eb_vp9_svt_release_out_buffer(&headerPtr); -+ return AVERROR(ENOMEM); -+ } -+ pkt->buf = ref; -+ pkt->data = ref->data; -+ -+ memcpy(pkt->data, headerPtr->p_buffer, headerPtr->n_filled_len); -+ pkt->size = headerPtr->n_filled_len; -+ pkt->pts = headerPtr->pts; -+ pkt->dts = headerPtr->dts; -+ if (headerPtr->pic_type == EB_IDR_PICTURE) -+ pkt->flags |= AV_PKT_FLAG_KEY; -+ if (headerPtr->pic_type == EB_NON_REF_PICTURE) -+ pkt->flags |= AV_PKT_FLAG_DISPOSABLE; -+ -+ if (headerPtr->flags & EB_BUFFERFLAG_SHOW_EXT) -+ pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_ON; -+ else -+ pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_OFF; -+ -+ if (EB_BUFFERFLAG_EOS & headerPtr->flags) -+ svt_enc->eos_flag = EOS_TOTRIGGER; -+ -+ eb_vp9_svt_release_out_buffer(&headerPtr); -+ return 0; -+} -+ -+static av_cold int eb_enc_close(AVCodecContext *avctx) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ -+ eb_vp9_deinit_encoder(svt_enc->svt_handle); -+ eb_vp9_deinit_handle(svt_enc->svt_handle); -+ -+ av_frame_free(&svt_enc->frame); -+ -+ free_buffer(svt_enc); -+ -+ return 0; -+} -+ -+#define OFFSET(x) offsetof(SvtContext, x) -+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -+static const AVOption options[] = { -+ { "preset", "Encoding preset [1, 1]", -+ OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = 9 }, 0, 9, VE }, -+ -+ { "level", "Set level (level_idc)", OFFSET(level), -+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xff, VE, "level" }, -+ -+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ -+ { .i64 = value }, 0, 0, VE, "level" -+ { LEVEL("1", 10) }, -+ { LEVEL("2", 20) }, -+ { LEVEL("2.1", 21) }, -+ { LEVEL("3", 30) }, -+ { LEVEL("3.1", 31) }, -+ { LEVEL("4", 40) }, -+ { LEVEL("4.1", 41) }, -+ { LEVEL("5", 50) }, -+ { LEVEL("5.1", 51) }, -+ { LEVEL("5.2", 52) }, -+ { LEVEL("6", 60) }, -+ { LEVEL("6.1", 61) }, -+ { LEVEL("6.2", 62) }, -+#undef LEVEL -+ -+ { "tune", "Tune mode", OFFSET(tune), -+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE , "tune"}, -+ { "vq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "tune" }, -+ { "ssim", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "tune" }, -+ { "vmaf", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "tune" }, -+ -+ { "rc", "Bit rate control mode", OFFSET(rc_mode), -+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, 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" }, -+ { "cbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "rc" }, -+ -+ { "qp", "QP value for intra frames", OFFSET(qp), -+ AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 51, VE }, -+ -+ { "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_vp9", -+ .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" }, -+ { NULL }, -+}; -+ -+AVCodec ff_libsvt_vp9_encoder = { -+ .name = "libsvt_vp9", -+ .long_name = NULL_IF_CONFIG_SMALL("SVT-VP9(Scalable Video Technology for VP9) encoder"), -+ .priv_data_size = sizeof(SvtContext), -+ .type = AVMEDIA_TYPE_VIDEO, -+ .id = AV_CODEC_ID_VP9, -+ .init = eb_enc_init, -+ .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_NONE }, -+ .priv_class = &class, -+ .defaults = eb_enc_defaults, -+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, -+ .wrapper_name = "libsvt_vp9", -+}; -diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c -index 62193058d7..36c8e29250 100644 ---- a/libavformat/dashenc.c -+++ b/libavformat/dashenc.c -@@ -2267,6 +2267,48 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) - return ret; - } - -+static int dash_write_packet_vp9(AVFormatContext *s, AVPacket *pkt) -+{ -+ int ret; -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ uint8_t *saved_data = pkt->data; -+ int saved_size = pkt->size; -+ int64_t saved_pts = pkt->pts; -+ -+ // Main frame -+ pkt->data = saved_data; -+ pkt->size = saved_size - 4; -+ pkt->pts = saved_pts; -+ ret = dash_write_packet(s, pkt); -+ -+ // Latter 4 one-byte repeated frames -+ pkt->data = saved_data + saved_size - 4; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 2; -+ ret = dash_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 3; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 1; -+ ret = dash_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 2; -+ pkt->size = 1; -+ pkt->pts = saved_pts; -+ ret = dash_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 1; -+ pkt->size = 1; -+ pkt->pts = saved_pts + 1; -+ ret = dash_write_packet(s, pkt); -+ } -+ else{ -+ ret = dash_write_packet(s, pkt); -+ } -+ -+ return ret; -+} -+ - static int dash_write_trailer(AVFormatContext *s) - { - DASHContext *c = s->priv_data; -@@ -2314,6 +2356,11 @@ static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt - DASHContext *c = s->priv_data; - OutputStream *os = &c->streams[avpkt->stream_index]; - AVFormatContext *oc = os->ctx; -+ -+ if ((avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (oc->oformat->check_bitstream) { - int ret; - AVPacket pkt = *avpkt; -@@ -2400,7 +2447,7 @@ AVOutputFormat ff_dash_muxer = { - .flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE, - .init = dash_init, - .write_header = dash_write_header, -- .write_packet = dash_write_packet, -+ .write_packet = dash_write_packet_vp9, - .write_trailer = dash_write_trailer, - .deinit = dash_free, - .check_bitstream = dash_check_bitstream, -diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c -index 0951f56c92..3a49097e9a 100644 ---- a/libavformat/ivfenc.c -+++ b/libavformat/ivfenc.c -@@ -81,9 +81,33 @@ static int ivf_write_packet(AVFormatContext *s, AVPacket *pkt) - AVIOContext *pb = s->pb; - IVFEncContext *ctx = s->priv_data; - -- avio_wl32(pb, pkt->size); -- avio_wl64(pb, pkt->pts); -- avio_write(pb, pkt->data, pkt->size); -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ avio_wl32(pb, pkt->size - 4); -+ avio_wl64(pb, pkt->pts); -+ avio_write(pb, pkt->data, pkt->size - 4); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts - 2); -+ avio_write(pb, pkt->data + pkt->size - 4, 1); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts - 1); -+ avio_write(pb, pkt->data + pkt->size - 3, 1); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts); -+ avio_write(pb, pkt->data + pkt->size - 2, 1); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts + 1); -+ avio_write(pb, pkt->data + pkt->size - 1, 1); -+ } -+ else { -+ avio_wl32(pb, pkt->size); -+ avio_wl64(pb, pkt->pts); -+ avio_write(pb, pkt->data, pkt->size); -+ } -+ - if (ctx->frame_cnt) - ctx->sum_delta_pts += pkt->pts - ctx->last_pts; - ctx->frame_cnt++; -diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c -index 105ed5197e..e4870227ab 100644 ---- a/libavformat/matroskaenc.c -+++ b/libavformat/matroskaenc.c -@@ -154,6 +154,8 @@ typedef struct MatroskaMuxContext { - int is_dash; - int dash_track_number; - int allow_raw_vfw; -+ int simple_block_timecode; -+ int accumulated_cluster_timecode; - int default_mode; - - uint32_t segment_uid[4]; -@@ -2082,7 +2084,13 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, - put_ebml_id(pb, blockid); - put_ebml_length(pb, size + track->track_num_size + 3, 0); - put_ebml_num(pb, track_number, track->track_num_size); -- avio_wb16(pb, ts - mkv->cluster_pts); -+ -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ avio_wb16(pb, mkv->simple_block_timecode); -+ else -+ avio_wb16(pb, ts - mkv->cluster_pts); -+ - avio_w8(pb, (blockid == MATROSKA_ID_SIMPLEBLOCK && keyframe) ? (1 << 7) : 0); - avio_write(pb, data + offset, size); - if (data != pkt->data) -@@ -2266,7 +2274,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) - return 0; - } - --static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) -+static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) - { - MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *pb; -@@ -2277,6 +2285,8 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) - int ret; - int64_t ts = track->write_dts ? pkt->dts : pkt->pts; - int64_t relative_packet_pos; -+ double fps = 0; -+ int pts_interval = 0; - - if (ts == AV_NOPTS_VALUE) { - av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); -@@ -2294,12 +2304,23 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) - } - } - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { -+ fps = av_q2d(s->streams[pkt->stream_index]->avg_frame_rate); -+ pts_interval = 1000 / fps; -+ } -+ - if (mkv->cluster_pos == -1) { - ret = start_ebml_master_crc32(&mkv->cluster_bc, mkv); - if (ret < 0) - return ret; - mkv->cluster_pos = avio_tell(s->pb); -- put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); -+ -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, -+ mkv->accumulated_cluster_timecode + pts_interval); -+ else -+ put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); -+ - mkv->cluster_pts = FFMAX(0, ts); - av_log(s, AV_LOG_DEBUG, - "Starting new cluster with timestamp " -@@ -2311,8 +2332,68 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) - relative_packet_pos = avio_tell(pb); - - if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { -- ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -- if (ret < 0) -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ uint8_t *saved_data = pkt->data; -+ int saved_size = pkt->size; -+ int64_t saved_pts = pkt->pts; -+ // Main frame -+ pkt->data = saved_data; -+ pkt->size = saved_size - 4; -+ pkt->pts = saved_pts; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ -+ // Latter 4 one-byte repeated frames -+ pkt->data = saved_data + saved_size - 4; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 2; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ -+ pkt->data = saved_data + saved_size - 3; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 1; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ -+ pkt->data = saved_data + saved_size - 2; -+ pkt->size = 1; -+ pkt->pts = saved_pts; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ -+ pkt->data = saved_data + saved_size - 1; -+ pkt->size = 1; -+ pkt->pts = saved_pts + 1; -+ mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ } else { -+ ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ if (ret < 0) return ret; -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF) { -+ GetBitContext gb; -+ int invisible, profile; -+ -+ if ((ret = init_get_bits8(&gb, pkt->data, pkt->size)) < 0) -+ return ret; -+ -+ get_bits(&gb, 2); // frame marker -+ profile = get_bits1(&gb); -+ profile |= get_bits1(&gb) << 1; -+ if (profile == 3) profile += get_bits1(&gb); -+ -+ if (get_bits1(&gb)) { -+ invisible = 0; -+ } else { -+ get_bits1(&gb); // keyframe -+ invisible = !get_bits1(&gb); -+ } -+ -+ if (!invisible) -+ mkv->simple_block_timecode += pts_interval; -+ } -+ } -+ -+ if (ret < 0) - return ret; - if (keyframe && IS_SEEKABLE(s->pb, mkv) && - (par->codec_type == AVMEDIA_TYPE_VIDEO || !mkv->have_video && !track->has_cue)) { -@@ -2358,7 +2439,7 @@ FF_ENABLE_DEPRECATION_WARNINGS - return 0; - } - --static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt) -+static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) - { - MatroskaMuxContext *mkv = s->priv_data; - int codec_type = s->streams[pkt->stream_index]->codecpar->codec_type; -@@ -2375,8 +2456,13 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt) - if (mkv->cluster_pos != -1) { - if (mkv->tracks[pkt->stream_index].write_dts) - cluster_time = pkt->dts - mkv->cluster_pts; -- else -- cluster_time = pkt->pts - mkv->cluster_pts; -+ else { -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ cluster_time = mkv->accumulated_cluster_timecode - mkv->cluster_pts; -+ else -+ cluster_time = pkt->pts - mkv->cluster_pts; -+ } - cluster_time += mkv->tracks[pkt->stream_index].ts_offset; - - cluster_size = avio_tell(mkv->cluster_bc); -@@ -2400,6 +2486,12 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt) - start_new_cluster = 0; - - if (start_new_cluster) { -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { -+ // Reset Timecode for new cluster. -+ mkv->accumulated_cluster_timecode += mkv->simple_block_timecode; -+ mkv->simple_block_timecode = 0; -+ } - ret = mkv_end_cluster(s); - if (ret < 0) - return ret; -@@ -2737,6 +2829,10 @@ static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) - int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { - if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) - ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); -diff --git a/libavformat/movenc.c b/libavformat/movenc.c -index b8e45760ee..20f4c01293 100644 ---- a/libavformat/movenc.c -+++ b/libavformat/movenc.c -@@ -5841,7 +5841,42 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) - } - } - -- return ff_mov_write_packet(s, pkt); -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ uint8_t *saved_data = pkt->data; -+ int saved_size = pkt->size; -+ int64_t saved_pts = pkt->pts; -+ -+ // Main frame -+ pkt->data = saved_data; -+ pkt->size = saved_size - 4; -+ pkt->pts = saved_pts; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ // Latter 4 one-byte repeated frames -+ pkt->data = saved_data + saved_size - 4; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 2; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 3; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 1; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 2; -+ pkt->size = 1; -+ pkt->pts = saved_pts; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 1; -+ pkt->size = 1; -+ pkt->pts = saved_pts + 1; -+ ret = ff_mov_write_packet(s, pkt); -+ } else { -+ ret = ff_mov_write_packet(s, pkt); -+ } -+ -+ return ret; - } - - static int mov_write_subtitle_end_packet(AVFormatContext *s, -@@ -6999,6 +7034,10 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) - int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { - if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) - ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); --- -2.17.1 - diff --git a/ffmpeg_plugin/master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch b/ffmpeg_plugin/master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch index bc9f609..32049ba 100644 --- a/ffmpeg_plugin/master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch +++ b/ffmpeg_plugin/master-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch @@ -1,7 +1,7 @@ -From 0bae1a68db540821974e35595f909fb9b8f08e9d Mon Sep 17 00:00:00 2001 +From 8f40b8b8417403e2d1d99d3c885a6c9e0c196f1d Mon Sep 17 00:00:00 2001 From: hassene Date: Fri, 15 Feb 2019 17:43:54 -0800 -Subject: [PATCH 1/1] Add ability for ffmpeg to run svt vp9 +Subject: [PATCH] Add ability for ffmpeg to run svt vp9 Signed-off-by: hassene Signed-off-by: Jing Sun @@ -12,74 +12,74 @@ Signed-off-by: Guo Jiansheng libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 4 + - libavcodec/libsvt_vp9.c | 504 ++++++++++++++++++++++++++++++++++++++ + libavcodec/libsvt_vp9.c | 503 ++++++++++++++++++++++++++++++++++++++ libavformat/dashenc.c | 49 +++- libavformat/ivfenc.c | 30 ++- libavformat/matroskaenc.c | 103 +++++++- libavformat/movenc.c | 42 +++- - 9 files changed, 727 insertions(+), 11 deletions(-) + 9 files changed, 726 insertions(+), 11 deletions(-) create mode 100644 libavcodec/libsvt_vp9.c diff --git a/configure b/configure -index 7495f35faa..e4894ef9e8 100755 +index 7495f35faa..5fa3685e97 100755 --- a/configure +++ b/configure -@@ -267,6 +267,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] +@@ -281,6 +281,7 @@ External library support: + --enable-libvorbis enable Vorbis en/decoding via libvorbis, + native implementation exists [no] + --enable-libvpx enable VP8 and VP9 de/encoding via libvpx [no] + --enable-libsvtvp9 enable VP9 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] -@@ -1803,6 +1804,7 @@ EXTERNAL_LIBRARY_LIST=" - libspeex - libsrt - libssh + --enable-libwavpack enable wavpack encoding via libwavpack [no] + --enable-libwebp enable WebP encoding via libwebp [no] + --enable-libx264 enable H.264 encoding via x264 [no] +@@ -1810,6 +1811,7 @@ EXTERNAL_LIBRARY_LIST=" + libv4l2 + libvorbis + libvpx + libsvtvp9 - libtensorflow - libtesseract - libtheora -@@ -3240,6 +3242,7 @@ libshine_encoder_select="audio_frame_queue" - libspeex_decoder_deps="libspeex" - libspeex_encoder_deps="libspeex" - libspeex_encoder_select="audio_frame_queue" + libwavpack + libwebp + libxml2 +@@ -3250,6 +3252,7 @@ libvpx_vp8_decoder_deps="libvpx" + libvpx_vp8_encoder_deps="libvpx" + libvpx_vp9_decoder_deps="libvpx" + libvpx_vp9_encoder_deps="libvpx" +libsvt_vp9_encoder_deps="libsvtvp9" - libtheora_encoder_deps="libtheora" - libtwolame_encoder_deps="libtwolame" - libvo_amrwbenc_encoder_deps="libvo_amrwbenc" -@@ -6372,6 +6375,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 + libwavpack_encoder_deps="libwavpack" + libwavpack_encoder_select="audio_frame_queue" + libwebp_encoder_deps="libwebp" +@@ -6408,6 +6411,7 @@ enabled libvpx && { + fi + } + +enabled libsvtvp9 && require_pkg_config libsvtvp9 SvtVp9Enc EbSvtVp9Enc.h eb_vp9_svt_init_handle - 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 + enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput -lwavpack + enabled libwebp && { + enabled libwebp_encoder && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion diff --git a/libavcodec/Makefile b/libavcodec/Makefile -index 5a6ea59715..8146ed696a 100644 +index 5a6ea59715..7a31fbcb6a 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile -@@ -1024,6 +1024,7 @@ OBJS-$(CONFIG_LIBRAV1E_ENCODER) += librav1e.o - OBJS-$(CONFIG_LIBSHINE_ENCODER) += libshine.o - OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o - OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o +@@ -1034,6 +1034,7 @@ OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o + OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o + OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o + OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o +OBJS-$(CONFIG_LIBSVT_VP9_ENCODER) += libsvt_vp9.o - OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o - OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o - OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o + OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o + OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o + OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c -index 80f128cade..4af230682d 100644 +index fa0c08d42e..7e9aca5082 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c -@@ -728,6 +728,7 @@ extern AVCodec ff_librsvg_decoder; - extern AVCodec ff_libshine_encoder; - extern AVCodec ff_libspeex_encoder; - extern AVCodec ff_libspeex_decoder; +@@ -734,6 +734,7 @@ extern AVCodec ff_libvpx_vp8_encoder; + extern AVCodec ff_libvpx_vp8_decoder; + extern AVCodec ff_libvpx_vp9_encoder; + extern AVCodec ff_libvpx_vp9_decoder; +extern AVCodec ff_libsvt_vp9_encoder; - extern AVCodec ff_libtheora_encoder; - extern AVCodec ff_libtwolame_encoder; - extern AVCodec ff_libvo_amrwbenc_encoder; + extern AVCodec ff_libwavpack_encoder; + /* preferred over libwebp */ + extern AVCodec ff_libwebp_anim_encoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c91b2fd169..10cdb7b0d9 100644 --- a/libavcodec/avcodec.h @@ -97,10 +97,10 @@ index c91b2fd169..10cdb7b0d9 100644 * Export the AVVideoEncParams structure through frame side data. diff --git a/libavcodec/libsvt_vp9.c b/libavcodec/libsvt_vp9.c new file mode 100644 -index 0000000000..6bd6243de0 +index 0000000000..dfe765e665 --- /dev/null +++ b/libavcodec/libsvt_vp9.c -@@ -0,0 +1,504 @@ +@@ -0,0 +1,503 @@ +/* +* Scalable Video Technology for VP9 encoder library plugin +* @@ -125,7 +125,6 @@ index 0000000000..6bd6243de0 + +#include +#include "EbSvtVp9ErrorCodes.h" -+#include "EbSvtVp9Time.h" +#include "EbSvtVp9Enc.h" + +#include "libavutil/common.h" @@ -612,7 +611,7 @@ index 62193058d7..36c8e29250 100644 @@ -2267,6 +2267,48 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; } - + +static int dash_write_packet_vp9(AVFormatContext *s, AVPacket *pkt) +{ + int ret; @@ -686,7 +685,7 @@ index 0951f56c92..3a49097e9a 100644 @@ -81,9 +81,33 @@ static int ivf_write_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; IVFEncContext *ctx = s->priv_data; - + - avio_wl32(pb, pkt->size); - avio_wl64(pb, pkt->pts); - avio_write(pb, pkt->data, pkt->size); @@ -731,7 +730,7 @@ index 105ed5197e..b625d405a6 100644 + int simple_block_timecode; + int accumulated_cluster_timecode; int default_mode; - + uint32_t segment_uid[4]; @@ -2082,7 +2084,13 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, put_ebml_id(pb, blockid); @@ -751,7 +750,7 @@ index 105ed5197e..b625d405a6 100644 @@ -2266,7 +2274,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) return 0; } - + -static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) +static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) { @@ -763,13 +762,13 @@ index 105ed5197e..b625d405a6 100644 int64_t relative_packet_pos; + double fps = 0; + int pts_interval = 0; - + if (ts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); @@ -2294,6 +2304,11 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) } } - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { + fps = av_q2d(s->streams[pkt->stream_index]->avg_frame_rate); + pts_interval = 1000 / fps; @@ -780,7 +779,7 @@ index 105ed5197e..b625d405a6 100644 if (ret < 0) @@ -2311,7 +2326,67 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) relative_packet_pos = avio_tell(pb); - + if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { - ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); + if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { @@ -862,11 +861,11 @@ index 105ed5197e..b625d405a6 100644 + } + cluster_time += mkv->tracks[pkt->stream_index].ts_offset; - + cluster_size = avio_tell(mkv->cluster_bc); @@ -2400,7 +2481,13 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt) start_new_cluster = 0; - + if (start_new_cluster) { - ret = mkv_end_cluster(s); + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || @@ -882,7 +881,7 @@ index 105ed5197e..b625d405a6 100644 @@ -2737,6 +2824,10 @@ static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) int ret = 1; AVStream *st = s->streams[pkt->stream_index]; - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) + return 0; @@ -891,13 +890,13 @@ index 105ed5197e..b625d405a6 100644 if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); diff --git a/libavformat/movenc.c b/libavformat/movenc.c -index b8e45760ee..fcc77a46a2 100644 +index 7db2e28840..a1f0b3a943 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c -@@ -5841,7 +5841,43 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) +@@ -5853,7 +5853,43 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) } } - + - return ff_mov_write_packet(s, pkt); + if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { + uint8_t *saved_data = pkt->data; @@ -937,12 +936,12 @@ index b8e45760ee..fcc77a46a2 100644 + + return ret; } - + static int mov_write_subtitle_end_packet(AVFormatContext *s, -@@ -6999,6 +7035,10 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +@@ -7013,6 +7049,10 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) int ret = 1; AVStream *st = s->streams[pkt->stream_index]; - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) + return 0; @@ -950,6 +949,5 @@ index b8e45760ee..fcc77a46a2 100644 if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); --- -2.17.1 - +-- +2.25.1 diff --git a/ffmpeg_plugin/n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch b/ffmpeg_plugin/n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch deleted file mode 100644 index 0317d35..0000000 --- a/ffmpeg_plugin/n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9-with-hevc-av1.patch +++ /dev/null @@ -1,946 +0,0 @@ -From 5c4b4bed1e7a2d090e2fbb2c901aaec05fccce2c Mon Sep 17 00:00:00 2001 -From: Jing Sun -Date: Mon, 1 Apr 2019 17:17:00 +0800 -Subject: [PATCH] Add ability for ffmpeg to run svt vp9 with hevc & av1 - -Signed-off-by: hassene -Signed-off-by: Jing Sun -Signed-off-by: Austin Hu -Signed-off-by: Guo Jiansheng ---- - configure | 4 + - libavcodec/Makefile | 1 + - libavcodec/allcodecs.c | 1 + - libavcodec/avcodec.h | 2 + - libavcodec/libsvt_vp9.c | 482 ++++++++++++++++++++++++++++++++++++++ - libavformat/dashenc.c | 49 +++- - libavformat/ivfenc.c | 34 ++- - libavformat/matroskaenc.c | 109 ++++++++- - libavformat/movenc.c | 42 +++- - 9 files changed, 712 insertions(+), 12 deletions(-) - create mode 100644 libavcodec/libsvt_vp9.c - -diff --git a/configure b/configure -index 75eca3f693..a4d156f512 100755 ---- a/configure -+++ b/configure -@@ -266,6 +266,7 @@ External library support: - --enable-libssh enable SFTP protocol via libssh [no] - --enable-libsvthevc enable HEVC encoding via svt [no] - --enable-libsvtav1 enable AV1 encoding via svt [no] -+ --enable-libsvtvp9 enable VP9 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] -@@ -1797,6 +1798,7 @@ EXTERNAL_LIBRARY_LIST=" - libssh - libsvthevc - libsvtav1 -+ libsvtvp9 - libtensorflow - libtesseract - libtheora -@@ -3197,6 +3199,7 @@ libspeex_encoder_deps="libspeex" - libspeex_encoder_select="audio_frame_queue" - libsvt_hevc_encoder_deps="libsvthevc" - libsvt_av1_encoder_deps="libsvtav1" -+libsvt_vp9_encoder_deps="libsvtvp9" - libtheora_encoder_deps="libtheora" - libtwolame_encoder_deps="libtwolame" - libvo_amrwbenc_encoder_deps="libvo_amrwbenc" -@@ -6271,6 +6274,7 @@ enabled libspeex && require_pkg_config libspeex speex speex/speex.h spe - 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 libsvtav1 && require_pkg_config libsvtav1 SvtAv1Enc EbSvtAv1Enc.h svt_av1_enc_init_handle -+enabled libsvtvp9 && require_pkg_config libsvtvp9 SvtVp9Enc EbSvtVp9Enc.h eb_vp9_svt_init_handle - 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 c500f3d274..2e8636496f 100644 ---- a/libavcodec/Makefile -+++ b/libavcodec/Makefile -@@ -993,6 +993,7 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER) += libspeexdec.o - OBJS-$(CONFIG_LIBSPEEX_ENCODER) += libspeexenc.o - OBJS-$(CONFIG_LIBSVT_HEVC_ENCODER) += libsvt_hevc.o - OBJS-$(CONFIG_LIBSVT_AV1_ENCODER) += libsvt_av1.o -+OBJS-$(CONFIG_LIBSVT_VP9_ENCODER) += libsvt_vp9.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 db1b1b2188..75248670db 100644 ---- a/libavcodec/allcodecs.c -+++ b/libavcodec/allcodecs.c -@@ -709,6 +709,7 @@ extern AVCodec ff_libspeex_encoder; - extern AVCodec ff_libspeex_decoder; - extern AVCodec ff_libsvt_hevc_encoder; - extern AVCodec ff_libsvt_av1_encoder; -+extern AVCodec ff_libsvt_vp9_encoder; - extern AVCodec ff_libtheora_encoder; - extern AVCodec ff_libtwolame_encoder; - extern AVCodec ff_libvo_amrwbenc_encoder; -diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h -index d234271c5b..0d903571b3 100644 ---- a/libavcodec/avcodec.h -+++ b/libavcodec/avcodec.h -@@ -1527,6 +1527,8 @@ typedef struct AVPacket { - */ - #define AV_PKT_FLAG_DISPOSABLE 0x0010 - -+#define AV_PKT_FLAG_SVT_VP9_EXT_ON 0x10000 // Indicating SVT VP9 frame header ext on -+#define AV_PKT_FLAG_SVT_VP9_EXT_OFF 0x20000 // Indicating SVT VP9 frame header ext off - - enum AVSideDataParamChangeFlags { - AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, -diff --git a/libavcodec/libsvt_vp9.c b/libavcodec/libsvt_vp9.c -new file mode 100644 -index 0000000000..d2c4740e5c ---- /dev/null -+++ b/libavcodec/libsvt_vp9.c -@@ -0,0 +1,482 @@ -+/* -+* Scalable Video Technology for VP9 encoder library plugin -+* -+* Copyright (c) 2018 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 -+#include "EbSvtVp9ErrorCodes.h" -+#include "EbSvtVp9Time.h" -+#include "EbSvtVp9Enc.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; -+ -+ EbSvtVp9EncConfiguration enc_params; -+ EbComponentType *svt_handle; -+ -+ EbBufferHeaderType *in_buf; -+ int raw_size; -+ -+ AVBufferPool* pool; -+ -+ EOS_STATUS eos_flag; -+ -+ // User options. -+ int enc_mode; -+ int rc_mode; -+ int tune; -+ int qp; -+ -+ int forced_idr; -+ -+ int level; -+ -+ int base_layer_switch_mode; -+} SvtContext; -+ -+static int error_mapping(EbErrorType 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) -+{ -+ if (svt_enc->in_buf) { -+ EbSvtEncInput *in_data = (EbSvtEncInput *)svt_enc->in_buf->p_buffer; -+ av_freep(&in_data); -+ av_freep(&svt_enc->in_buf); -+ } -+ av_buffer_pool_uninit(&svt_enc->pool); -+} -+ -+static int alloc_buffer(EbSvtVp9EncConfiguration *config, SvtContext *svt_enc) -+{ -+ const size_t luma_size_8bit = -+ config->source_width * config->source_height; -+ const size_t luma_size_10bit = -+ (config->encoder_bit_depth > 8) ? luma_size_8bit : 0; -+ -+ EbSvtEncInput *in_data; -+ -+ svt_enc->raw_size = (luma_size_8bit + luma_size_10bit) * 3 / 2; -+ -+ // allocate buffer for in and out -+ svt_enc->in_buf = av_mallocz(sizeof(*svt_enc->in_buf)); -+ if (!svt_enc->in_buf) -+ goto failed; -+ -+ -+ svt_enc->in_buf->p_buffer = (unsigned char *)av_mallocz(sizeof(*in_data)); -+ if (!svt_enc->in_buf->p_buffer) -+ goto failed; -+ -+ svt_enc->in_buf->size = sizeof(*svt_enc->in_buf); -+ svt_enc->in_buf->p_app_private = NULL; -+ -+ svt_enc->pool = av_buffer_pool_init(svt_enc->raw_size, NULL); -+ if (!svt_enc->pool) -+ goto failed; -+ -+ return 0; -+ -+failed: -+ free_buffer(svt_enc); -+ return AVERROR(ENOMEM); -+} -+ -+static int config_enc_params(EbSvtVp9EncConfiguration *param, -+ AVCodecContext *avctx) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ int ret; -+ int ten_bits = 0; -+ -+ param->source_width = avctx->width; -+ param->source_height = avctx->height; -+ -+ if (avctx->pix_fmt == AV_PIX_FMT_YUV420P10LE) { -+ av_log(avctx, AV_LOG_DEBUG , "Encoder 10 bits depth input\n"); -+ // Disable Compressed 10-bit format default -+ ten_bits = 1; -+ } -+ -+ // Update param from options -+ param->enc_mode = svt_enc->enc_mode; -+ param->level = svt_enc->level; -+ param->rate_control_mode = svt_enc->rc_mode; -+ param->tune = svt_enc->tune; -+ param->base_layer_switch_mode = svt_enc->base_layer_switch_mode; -+ param->qp = svt_enc->qp; -+ -+ param->target_bit_rate = avctx->bit_rate; -+ if (avctx->gop_size > 0) -+ param->intra_period = avctx->gop_size - 1; -+ -+ if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { -+ param->frame_rate_numerator = avctx->framerate.num; -+ param->frame_rate_denominator = avctx->framerate.den * avctx->ticks_per_frame; -+ } else { -+ param->frame_rate_numerator = avctx->time_base.den; -+ param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame; -+ } -+ -+ if (param->rate_control_mode) { -+ param->max_qp_allowed = avctx->qmax; -+ param->min_qp_allowed = avctx->qmin; -+ } -+ -+ if (ten_bits) { -+ param->encoder_bit_depth = 10; -+ } -+ -+ ret = alloc_buffer(param, svt_enc); -+ -+ return ret; -+} -+ -+static void read_in_data(EbSvtVp9EncConfiguration *config, -+ const AVFrame *frame, -+ EbBufferHeaderType *headerPtr) -+{ -+ uint8_t is16bit = config->encoder_bit_depth > 8; -+ uint64_t luma_size = -+ (uint64_t)config->source_width * config->source_height<< is16bit; -+ EbSvtEncInput *in_data = (EbSvtEncInput *)headerPtr->p_buffer; -+ -+ // support yuv420p and yuv420p010 -+ in_data->luma = frame->data[0]; -+ in_data->cb = frame->data[1]; -+ in_data->cr = frame->data[2]; -+ -+ // stride info -+ in_data->y_stride = frame->linesize[0] >> is16bit; -+ in_data->cb_stride = frame->linesize[1] >> is16bit; -+ in_data->cr_stride = frame->linesize[2] >> is16bit; -+ -+ headerPtr->n_filled_len += luma_size * 3/2u; -+} -+ -+static av_cold int eb_enc_init(AVCodecContext *avctx) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ EbErrorType svt_ret; -+ -+ svt_enc->eos_flag = EOS_NOT_REACHED; -+ -+ svt_ret = eb_vp9_svt_init_handle(&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 = eb_vp9_svt_enc_set_parameter(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 = eb_vp9_init_encoder(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) { -+ // EbBufferHeaderType* headerPtr; -+ // headerPtr->size = sizeof(headerPtr); -+ // headerPtr->n_filled_len = 0; /* in/out */ -+ // headerPtr->p_buffer = av_malloc(10 * 1024 * 1024); -+ // headerPtr->n_alloc_len = (10 * 1024 * 1024); -+ // -+ // if (!headerPtr->p_buffer) { -+ // av_log(avctx, AV_LOG_ERROR, -+ // "Cannot allocate buffer size %d.\n", headerPtr->n_alloc_len); -+ // svt_ret = EB_ErrorInsufficientResources; -+ // goto failed_init_enc; -+ // } -+ // -+ // svt_ret = eb_svt_enc_stream_header(svt_enc->svt_handle, &headerPtr); -+ // if (svt_ret != EB_ErrorNone) { -+ // av_log(avctx, AV_LOG_ERROR, "Error when build stream header.\n"); -+ // av_freep(&headerPtr->p_buffer); -+ // goto failed_init_enc; -+ // } -+ // -+ // avctx->extradata_size = headerPtr->n_filled_len; -+ // avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); -+ // if (!avctx->extradata) { -+ // av_log(avctx, AV_LOG_ERROR, -+ // "Cannot allocate VP9 header of size %d.\n", avctx->extradata_size); -+ // av_freep(&headerPtr->p_buffer); -+ // svt_ret = EB_ErrorInsufficientResources; -+ // goto failed_init_enc; -+ // } -+ // memcpy(avctx->extradata, headerPtr->p_buffer, avctx->extradata_size); -+ // -+ // av_freep(&headerPtr->p_buffer); -+ // } -+ return 0; -+ -+//failed_init_enc: -+// eb_deinit_encoder(svt_enc->svt_handle); -+failed_init_handle: -+ eb_vp9_deinit_handle(svt_enc->svt_handle); -+failed: -+ free_buffer(svt_enc); -+ return error_mapping(svt_ret); -+} -+ -+static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ EbBufferHeaderType *headerPtr = svt_enc->in_buf; -+ -+ if (!frame) { -+ EbBufferHeaderType headerPtrLast; -+ headerPtrLast.n_alloc_len = 0; -+ headerPtrLast.n_filled_len = 0; -+ headerPtrLast.n_tick_count = 0; -+ headerPtrLast.p_app_private = NULL; -+ headerPtrLast.p_buffer = NULL; -+ headerPtrLast.flags = EB_BUFFERFLAG_EOS; -+ -+ eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, &headerPtrLast); -+ 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, headerPtr); -+ -+ headerPtr->flags = 0; -+ headerPtr->p_app_private = NULL; -+ headerPtr->pts = frame->pts; -+ switch (frame->pict_type) { -+ case AV_PICTURE_TYPE_I: -+ headerPtr->pic_type = svt_enc->forced_idr > 0 ? EB_IDR_PICTURE : EB_I_PICTURE; -+ break; -+ case AV_PICTURE_TYPE_P: -+ headerPtr->pic_type = EB_P_PICTURE; -+ break; -+ case AV_PICTURE_TYPE_B: -+ headerPtr->pic_type = EB_B_PICTURE; -+ break; -+ default: -+ headerPtr->pic_type = EB_INVALID_PICTURE; -+ break; -+ } -+ eb_vp9_svt_enc_send_picture(svt_enc->svt_handle, headerPtr); -+ -+ return 0; -+} -+ -+static int eb_receive_packet(AVCodecContext *avctx, AVPacket *pkt) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ EbBufferHeaderType *headerPtr; -+ EbErrorType svt_ret; -+ AVBufferRef *ref; -+ -+ if (EOS_TOTRIGGER == svt_enc->eos_flag) { -+ pkt = NULL; -+ return AVERROR_EOF; -+ } -+ -+ svt_ret = eb_vp9_svt_get_packet(svt_enc->svt_handle, &headerPtr, svt_enc->eos_flag); -+ if (svt_ret == EB_NoErrorEmptyQueue) -+ return AVERROR(EAGAIN); -+ -+ ref = av_buffer_pool_get(svt_enc->pool); -+ if (!ref) { -+ av_log(avctx, AV_LOG_ERROR, "Failed to allocate output packet.\n"); -+ eb_vp9_svt_release_out_buffer(&headerPtr); -+ return AVERROR(ENOMEM); -+ } -+ pkt->buf = ref; -+ pkt->data = ref->data; -+ -+ memcpy(pkt->data, headerPtr->p_buffer, headerPtr->n_filled_len); -+ pkt->size = headerPtr->n_filled_len; -+ pkt->pts = headerPtr->pts; -+ pkt->dts = headerPtr->dts; -+ if (headerPtr->pic_type == EB_IDR_PICTURE) -+ pkt->flags |= AV_PKT_FLAG_KEY; -+ if (headerPtr->pic_type == EB_NON_REF_PICTURE) -+ pkt->flags |= AV_PKT_FLAG_DISPOSABLE; -+ -+ if (headerPtr->flags & EB_BUFFERFLAG_SHOW_EXT) -+ pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_ON; -+ else -+ pkt->flags |= AV_PKT_FLAG_SVT_VP9_EXT_OFF; -+ -+ if (EB_BUFFERFLAG_EOS & headerPtr->flags) -+ svt_enc->eos_flag = EOS_TOTRIGGER; -+ -+ eb_vp9_svt_release_out_buffer(&headerPtr); -+ return 0; -+} -+ -+static av_cold int eb_enc_close(AVCodecContext *avctx) -+{ -+ SvtContext *svt_enc = avctx->priv_data; -+ -+ eb_vp9_deinit_encoder(svt_enc->svt_handle); -+ eb_vp9_deinit_handle(svt_enc->svt_handle); -+ -+ free_buffer(svt_enc); -+ -+ return 0; -+} -+ -+#define OFFSET(x) offsetof(SvtContext, x) -+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -+static const AVOption options[] = { -+ { "preset", "Encoding preset [1, 1]", -+ OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = 9 }, 0, 9, VE }, -+ -+ { "level", "Set level (level_idc)", OFFSET(level), -+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0xff, VE, "level" }, -+ -+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \ -+ { .i64 = value }, 0, 0, VE, "level" -+ { LEVEL("1", 10) }, -+ { LEVEL("2", 20) }, -+ { LEVEL("2.1", 21) }, -+ { LEVEL("3", 30) }, -+ { LEVEL("3.1", 31) }, -+ { LEVEL("4", 40) }, -+ { LEVEL("4.1", 41) }, -+ { LEVEL("5", 50) }, -+ { LEVEL("5.1", 51) }, -+ { LEVEL("5.2", 52) }, -+ { LEVEL("6", 60) }, -+ { LEVEL("6.1", 61) }, -+ { LEVEL("6.2", 62) }, -+#undef LEVEL -+ -+ { "tune", "Tune mode", OFFSET(tune), -+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE , "tune"}, -+ { "vq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "tune" }, -+ { "ssim", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "tune" }, -+ { "vmaf", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "tune" }, -+ -+ { "rc", "Bit rate control mode", OFFSET(rc_mode), -+ AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, 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" }, -+ { "cbr", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "rc" }, -+ -+ { "qp", "QP value for intra frames", OFFSET(qp), -+ AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 51, VE }, -+ -+ { "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_vp9", -+ .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" }, -+ { NULL }, -+}; -+ -+AVCodec ff_libsvt_vp9_encoder = { -+ .name = "libsvt_vp9", -+ .long_name = NULL_IF_CONFIG_SMALL("SVT-VP9(Scalable Video Technology for VP9) encoder"), -+ .priv_data_size = sizeof(SvtContext), -+ .type = AVMEDIA_TYPE_VIDEO, -+ .id = AV_CODEC_ID_VP9, -+ .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_NONE }, -+ .priv_class = &class, -+ .defaults = eb_enc_defaults, -+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, -+ .wrapper_name = "libsvt_vp9", -+}; -diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c -index f0e45da89a..fdd3eb0cb0 100644 ---- a/libavformat/dashenc.c -+++ b/libavformat/dashenc.c -@@ -1822,6 +1822,48 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) - return ret; - } - -+static int dash_write_packet_vp9(AVFormatContext *s, AVPacket *pkt) -+{ -+ int ret; -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ uint8_t *saved_data = pkt->data; -+ int saved_size = pkt->size; -+ int64_t saved_pts = pkt->pts; -+ -+ // Main frame -+ pkt->data = saved_data; -+ pkt->size = saved_size - 4; -+ pkt->pts = saved_pts; -+ ret = dash_write_packet(s, pkt); -+ -+ // Latter 4 one-byte repeated frames -+ pkt->data = saved_data + saved_size - 4; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 2; -+ ret = dash_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 3; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 1; -+ ret = dash_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 2; -+ pkt->size = 1; -+ pkt->pts = saved_pts; -+ ret = dash_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 1; -+ pkt->size = 1; -+ pkt->pts = saved_pts + 1; -+ ret = dash_write_packet(s, pkt); -+ } -+ else{ -+ ret = dash_write_packet(s, pkt); -+ } -+ -+ return ret; -+} -+ - static int dash_write_trailer(AVFormatContext *s) - { - DASHContext *c = s->priv_data; -@@ -1869,6 +1911,11 @@ static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt - DASHContext *c = s->priv_data; - OutputStream *os = &c->streams[avpkt->stream_index]; - AVFormatContext *oc = os->ctx; -+ -+ if ((avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (avpkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (oc->oformat->check_bitstream) { - int ret; - AVPacket pkt = *avpkt; -@@ -1941,7 +1988,7 @@ AVOutputFormat ff_dash_muxer = { - .flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE, - .init = dash_init, - .write_header = dash_write_header, -- .write_packet = dash_write_packet, -+ .write_packet = dash_write_packet_vp9, - .write_trailer = dash_write_trailer, - .deinit = dash_free, - .check_bitstream = dash_check_bitstream, -diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c -index adf72117e9..05f08131a6 100644 ---- a/libavformat/ivfenc.c -+++ b/libavformat/ivfenc.c -@@ -63,9 +63,33 @@ static int ivf_write_packet(AVFormatContext *s, AVPacket *pkt) - AVIOContext *pb = s->pb; - IVFEncContext *ctx = s->priv_data; - -- avio_wl32(pb, pkt->size); -- avio_wl64(pb, pkt->pts); -- avio_write(pb, pkt->data, pkt->size); -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ avio_wl32(pb, pkt->size - 4); -+ avio_wl64(pb, pkt->pts); -+ avio_write(pb, pkt->data, pkt->size - 4); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts - 2); -+ avio_write(pb, pkt->data + pkt->size - 4, 1); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts - 1); -+ avio_write(pb, pkt->data + pkt->size - 3, 1); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts); -+ avio_write(pb, pkt->data + pkt->size - 2, 1); -+ -+ avio_wl32(pb, 1); -+ avio_wl64(pb, pkt->pts + 1); -+ avio_write(pb, pkt->data + pkt->size - 1, 1); -+ } -+ else { -+ avio_wl32(pb, pkt->size); -+ avio_wl64(pb, pkt->pts); -+ avio_write(pb, pkt->data, pkt->size); -+ } -+ - if (ctx->frame_cnt) - ctx->sum_delta_pts += pkt->pts - ctx->last_pts; - ctx->frame_cnt++; -@@ -95,6 +119,10 @@ static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) - int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (st->codecpar->codec_id == AV_CODEC_ID_VP9) - ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL); - else if (st->codecpar->codec_id == AV_CODEC_ID_AV1) -diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c -index 0f535f61d4..8a4f3f17b4 100644 ---- a/libavformat/matroskaenc.c -+++ b/libavformat/matroskaenc.c -@@ -161,6 +161,9 @@ typedef struct MatroskaMuxContext { - int64_t *stream_duration_offsets; - - int allow_raw_vfw; -+ -+ int simple_block_timecode; -+ int accumulated_cluster_timecode; - } MatroskaMuxContext; - - /** 2 bytes * 7 for EBML IDs, 7 1-byte EBML lengths, 6 1-byte uint, -@@ -2198,7 +2201,13 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, - put_ebml_num(pb, size + 4, 0); - // this assumes stream_index is less than 126 - avio_w8(pb, 0x80 | track_number); -- avio_wb16(pb, ts - mkv->cluster_pts); -+ -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ avio_wb16(pb, mkv->simple_block_timecode); -+ else -+ avio_wb16(pb, ts - mkv->cluster_pts); -+ - avio_w8(pb, (blockid == MATROSKA_ID_SIMPLEBLOCK && keyframe) ? (1 << 7) : 0); - avio_write(pb, data + offset, size); - if (data != pkt->data) -@@ -2405,6 +2414,8 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ - int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; - int64_t relative_packet_pos; - int dash_tracknum = mkv->is_dash ? mkv->dash_track_number : pkt->stream_index + 1; -+ double fps = 0; -+ int pts_interval = 0; - - if (ts == AV_NOPTS_VALUE) { - av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); -@@ -2420,12 +2431,23 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ - } - } - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { -+ fps = av_q2d(s->streams[pkt->stream_index]->avg_frame_rate); -+ pts_interval = 1000 / fps; -+ } -+ - if (mkv->cluster_pos == -1) { - mkv->cluster_pos = avio_tell(s->pb); - ret = start_ebml_master_crc32(&mkv->cluster_bc, mkv); - if (ret < 0) - return ret; -- put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); -+ -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, -+ mkv->accumulated_cluster_timecode + pts_interval); -+ else -+ put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); -+ - mkv->cluster_pts = FFMAX(0, ts); - } - pb = mkv->cluster_bc; -@@ -2433,9 +2455,66 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ - relative_packet_pos = avio_tell(pb); - - if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { -- ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -- if (ret < 0) -- return ret; -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ uint8_t *saved_data = pkt->data; -+ int saved_size = pkt->size; -+ int64_t saved_pts = pkt->pts; -+ // Main frame -+ pkt->data = saved_data; -+ pkt->size = saved_size - 4; -+ pkt->pts = saved_pts; -+ ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ -+ // Latter 4 one-byte repeated frames -+ pkt->data = saved_data + saved_size - 4; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 2; -+ ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ -+ pkt->data = saved_data + saved_size - 3; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 1; -+ ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ -+ pkt->data = saved_data + saved_size - 2; -+ pkt->size = 1; -+ pkt->pts = saved_pts; -+ ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ -+ pkt->data = saved_data + saved_size - 1; -+ pkt->size = 1; -+ pkt->pts = saved_pts + 1; -+ ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ mkv->simple_block_timecode += pts_interval; -+ } else { -+ ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); -+ if (ret < 0) return ret; -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF) { -+ GetBitContext gb; -+ int invisible, profile; -+ -+ if ((ret = init_get_bits8(&gb, pkt->data, pkt->size)) < 0) -+ return ret; -+ -+ get_bits(&gb, 2); // frame marker -+ profile = get_bits1(&gb); -+ profile |= get_bits1(&gb) << 1; -+ if (profile == 3) profile += get_bits1(&gb); -+ -+ if (get_bits1(&gb)) { -+ invisible = 0; -+ } else { -+ get_bits1(&gb); // keyframe -+ invisible = !get_bits1(&gb); -+ } -+ -+ if (!invisible) -+ mkv->simple_block_timecode += pts_interval; -+ } -+ } - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && (par->codec_type == AVMEDIA_TYPE_VIDEO && keyframe || add_cue)) { - ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, -1); - if (ret < 0) return ret; -@@ -2494,8 +2573,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) - - if (mkv->tracks[pkt->stream_index].write_dts) - cluster_time = pkt->dts - mkv->cluster_pts; -- else -- cluster_time = pkt->pts - mkv->cluster_pts; -+ else { -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ cluster_time = mkv->accumulated_cluster_timecode - mkv->cluster_pts; -+ else -+ cluster_time = pkt->pts - mkv->cluster_pts; -+ } - cluster_time += mkv->tracks[pkt->stream_index].ts_offset; - - // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or -@@ -2523,6 +2607,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) - } - - if (mkv->cluster_pos != -1 && start_new_cluster) { -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { -+ // Reset Timecode for new cluster. -+ mkv->accumulated_cluster_timecode += mkv->simple_block_timecode; -+ mkv->simple_block_timecode = 0; -+ } -+ - mkv_start_new_cluster(s, pkt); - } - -@@ -2762,6 +2853,10 @@ static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) - int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { - if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) - ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); -diff --git a/libavformat/movenc.c b/libavformat/movenc.c -index d0bd1824e1..62e306c0a8 100644 ---- a/libavformat/movenc.c -+++ b/libavformat/movenc.c -@@ -5625,7 +5625,43 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) - } - } - -- return ff_mov_write_packet(s, pkt); -+ if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { -+ uint8_t *saved_data = pkt->data; -+ int saved_size = pkt->size; -+ int64_t saved_pts = pkt->pts; -+ -+ // Main frame -+ pkt->data = saved_data; -+ pkt->size = saved_size - 4; -+ pkt->pts = saved_pts; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ // Latter 4 one-byte repeated frames -+ pkt->data = saved_data + saved_size - 4; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 2; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 3; -+ pkt->size = 1; -+ pkt->pts = saved_pts - 1; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 2; -+ pkt->size = 1; -+ pkt->pts = saved_pts; -+ ret = ff_mov_write_packet(s, pkt); -+ -+ pkt->data = saved_data + saved_size - 1; -+ pkt->size = 1; -+ pkt->pts = saved_pts + 1; -+ ret = ff_mov_write_packet(s, pkt); -+ } -+ else{ -+ ret = ff_mov_write_packet(s, pkt); -+ } -+ -+ return ret; - } - - static int mov_write_subtitle_end_packet(AVFormatContext *s, -@@ -6764,6 +6800,10 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) - int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - -+ if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || -+ (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) -+ return 0; -+ - if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { - if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) - ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); --- -2.17.1 - diff --git a/ffmpeg_plugin/n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch b/ffmpeg_plugin/n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch index d019408..f8d1387 100644 --- a/ffmpeg_plugin/n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch +++ b/ffmpeg_plugin/n4.2.3-0001-Add-ability-for-ffmpeg-to-run-svt-vp9.patch @@ -1,4 +1,4 @@ -From c0d860c06bb5b01ef73a7ffa722d166a1575ed0d Mon Sep 17 00:00:00 2001 +From c2cd7ee28a9e5ae280db22f9cfb2efb59342fcda Mon Sep 17 00:00:00 2001 From: hassene Date: Fri, 15 Feb 2019 17:43:54 -0800 Subject: [PATCH] Add ability for ffmpeg to run svt vp9 @@ -12,74 +12,74 @@ Signed-off-by: Guo Jiansheng libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 2 + - libavcodec/libsvt_vp9.c | 482 ++++++++++++++++++++++++++++++++++++++ + libavcodec/libsvt_vp9.c | 481 ++++++++++++++++++++++++++++++++++++++ libavformat/dashenc.c | 49 +++- libavformat/ivfenc.c | 34 ++- libavformat/matroskaenc.c | 112 ++++++++- libavformat/movenc.c | 42 +++- - 9 files changed, 714 insertions(+), 13 deletions(-) + 9 files changed, 713 insertions(+), 13 deletions(-) create mode 100644 libavcodec/libsvt_vp9.c diff --git a/configure b/configure -index 6a7a85cbb9..07017c5cad 100755 +index 6a7a85cbb9..4367647a22 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] +@@ -278,6 +278,7 @@ External library support: + --enable-libvorbis enable Vorbis en/decoding via libvorbis, + native implementation exists [no] + --enable-libvpx enable VP8 and VP9 de/encoding via libvpx [no] + --enable-libsvtvp9 enable VP9 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] -@@ -1793,6 +1794,7 @@ EXTERNAL_LIBRARY_LIST=" - libspeex - libsrt - libssh + --enable-libwavpack enable wavpack encoding via libwavpack [no] + --enable-libwebp enable WebP encoding via libwebp [no] + --enable-libx264 enable H.264 encoding via x264 [no] +@@ -1800,6 +1801,7 @@ EXTERNAL_LIBRARY_LIST=" + libv4l2 + libvorbis + libvpx + libsvtvp9 - libtensorflow - libtesseract - libtheora -@@ -3191,6 +3193,7 @@ libshine_encoder_select="audio_frame_queue" - libspeex_decoder_deps="libspeex" - libspeex_encoder_deps="libspeex" - libspeex_encoder_select="audio_frame_queue" + libwavpack + libwebp + libxml2 +@@ -3201,6 +3203,7 @@ libvpx_vp8_decoder_deps="libvpx" + libvpx_vp8_encoder_deps="libvpx" + libvpx_vp9_decoder_deps="libvpx" + libvpx_vp9_encoder_deps="libvpx" +libsvt_vp9_encoder_deps="libsvtvp9" - libtheora_encoder_deps="libtheora" - libtwolame_encoder_deps="libtwolame" - libvo_amrwbenc_encoder_deps="libvo_amrwbenc" -@@ -6263,6 +6266,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 + libwavpack_encoder_deps="libwavpack" + libwavpack_encoder_select="audio_frame_queue" + libwebp_encoder_deps="libwebp" +@@ -6299,6 +6302,7 @@ enabled libvpx && { + fi + } + +enabled libsvtvp9 && require_pkg_config libsvtvp9 SvtVp9Enc EbSvtVp9Enc.h eb_vp9_svt_init_handle - 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 + enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput -lwavpack + enabled libwebp && { + enabled libwebp_encoder && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion diff --git a/libavcodec/Makefile b/libavcodec/Makefile -index 3cd73fbcc6..eb138776b7 100644 +index 3cd73fbcc6..cc756acfe7 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 +@@ -1001,6 +1001,7 @@ OBJS-$(CONFIG_LIBVPX_VP8_DECODER) += libvpxdec.o + OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o + OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o + OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o +OBJS-$(CONFIG_LIBSVT_VP9_ENCODER) += libsvt_vp9.o - OBJS-$(CONFIG_LIBTHEORA_ENCODER) += libtheoraenc.o - OBJS-$(CONFIG_LIBTWOLAME_ENCODER) += libtwolame.o - OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o + OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o + OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o + OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c -index d2f9a39ce5..9849fc1875 100644 +index d2f9a39ce5..205333db96 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c -@@ -707,6 +707,7 @@ extern AVCodec ff_librsvg_decoder; - extern AVCodec ff_libshine_encoder; - extern AVCodec ff_libspeex_encoder; - extern AVCodec ff_libspeex_decoder; +@@ -716,6 +716,7 @@ extern AVCodec ff_libvpx_vp8_encoder; + extern AVCodec ff_libvpx_vp8_decoder; + extern AVCodec ff_libvpx_vp9_encoder; + extern AVCodec ff_libvpx_vp9_decoder; +extern AVCodec ff_libsvt_vp9_encoder; - extern AVCodec ff_libtheora_encoder; - extern AVCodec ff_libtwolame_encoder; - extern AVCodec ff_libvo_amrwbenc_encoder; + extern AVCodec ff_libwavpack_encoder; + /* preferred over libwebp */ + extern AVCodec ff_libwebp_anim_encoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index d234271c5b..0d903571b3 100644 --- a/libavcodec/avcodec.h @@ -87,18 +87,18 @@ index d234271c5b..0d903571b3 100644 @@ -1527,6 +1527,8 @@ typedef struct AVPacket { */ #define AV_PKT_FLAG_DISPOSABLE 0x0010 - + +#define AV_PKT_FLAG_SVT_VP9_EXT_ON 0x10000 // Indicating SVT VP9 frame header ext on +#define AV_PKT_FLAG_SVT_VP9_EXT_OFF 0x20000 // Indicating SVT VP9 frame header ext off - + enum AVSideDataParamChangeFlags { AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, diff --git a/libavcodec/libsvt_vp9.c b/libavcodec/libsvt_vp9.c new file mode 100644 -index 0000000000..d2c4740e5c +index 0000000000..037467366e --- /dev/null +++ b/libavcodec/libsvt_vp9.c -@@ -0,0 +1,482 @@ +@@ -0,0 +1,481 @@ +/* +* Scalable Video Technology for VP9 encoder library plugin +* @@ -123,7 +123,6 @@ index 0000000000..d2c4740e5c + +#include +#include "EbSvtVp9ErrorCodes.h" -+#include "EbSvtVp9Time.h" +#include "EbSvtVp9Enc.h" + +#include "libavutil/common.h" @@ -588,7 +587,7 @@ index f0e45da89a..fdd3eb0cb0 100644 @@ -1822,6 +1822,48 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; } - + +static int dash_write_packet_vp9(AVFormatContext *s, AVPacket *pkt) +{ + int ret; @@ -662,7 +661,7 @@ index adf72117e9..05f08131a6 100644 @@ -63,9 +63,33 @@ static int ivf_write_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; IVFEncContext *ctx = s->priv_data; - + - avio_wl32(pb, pkt->size); - avio_wl64(pb, pkt->pts); - avio_write(pb, pkt->data, pkt->size); @@ -699,7 +698,7 @@ index adf72117e9..05f08131a6 100644 @@ -95,6 +119,10 @@ static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) int ret = 1; AVStream *st = s->streams[pkt->stream_index]; - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) + return 0; @@ -713,13 +712,13 @@ index 0f535f61d4..b8638848d1 100644 +++ b/libavformat/matroskaenc.c @@ -161,6 +161,9 @@ typedef struct MatroskaMuxContext { int64_t *stream_duration_offsets; - + int allow_raw_vfw; + + int simple_block_timecode; + int accumulated_cluster_timecode; } MatroskaMuxContext; - + /** 2 bytes * 7 for EBML IDs, 7 1-byte EBML lengths, 6 1-byte uint, @@ -2198,7 +2201,13 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, put_ebml_num(pb, size + 4, 0); @@ -742,13 +741,13 @@ index 0f535f61d4..b8638848d1 100644 int dash_tracknum = mkv->is_dash ? mkv->dash_track_number : pkt->stream_index + 1; + double fps = 0; + int pts_interval = 0; - + if (ts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); @@ -2420,12 +2431,23 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ } } - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { + fps = av_q2d(s->streams[pkt->stream_index]->avg_frame_rate); + pts_interval = 1000 / fps; @@ -772,7 +771,7 @@ index 0f535f61d4..b8638848d1 100644 pb = mkv->cluster_bc; @@ -2433,10 +2455,68 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_ relative_packet_pos = avio_tell(pb); - + if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { - ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); - if (ret < 0) @@ -844,7 +843,7 @@ index 0f535f61d4..b8638848d1 100644 if (ret < 0) return ret; } @@ -2494,8 +2574,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) - + if (mkv->tracks[pkt->stream_index].write_dts) cluster_time = pkt->dts - mkv->cluster_pts; - else @@ -857,11 +856,11 @@ index 0f535f61d4..b8638848d1 100644 + cluster_time = pkt->pts - mkv->cluster_pts; + } cluster_time += mkv->tracks[pkt->stream_index].ts_offset; - + // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or @@ -2523,6 +2608,13 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) } - + if (mkv->cluster_pos != -1 && start_new_cluster) { + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) { @@ -872,11 +871,11 @@ index 0f535f61d4..b8638848d1 100644 + mkv_start_new_cluster(s, pkt); } - + @@ -2762,6 +2854,10 @@ static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) int ret = 1; AVStream *st = s->streams[pkt->stream_index]; - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) + return 0; @@ -891,7 +890,7 @@ index d0bd1824e1..62e306c0a8 100644 @@ -5625,7 +5625,43 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) } } - + - return ff_mov_write_packet(s, pkt); + if (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) { + uint8_t *saved_data = pkt->data; @@ -931,12 +930,12 @@ index d0bd1824e1..62e306c0a8 100644 + + return ret; } - + static int mov_write_subtitle_end_packet(AVFormatContext *s, @@ -6764,6 +6800,10 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) int ret = 1; AVStream *st = s->streams[pkt->stream_index]; - + + if ((pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_ON) || + (pkt->flags & AV_PKT_FLAG_SVT_VP9_EXT_OFF)) + return 0; @@ -944,6 +943,5 @@ index d0bd1824e1..62e306c0a8 100644 if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); --- -2.17.1 - +-- +2.25.1