[FFmpeg-devel] [PATCH v7 1/2] lavc, doc, configure: add libxavs2 video encoder wrapper
Mark Thompson
sw at jkqxz.net
Sun Sep 9 21:01:32 EEST 2018
On 06/09/18 14:58, hwren wrote:
> Signed-off-by: hwren <hwrenx at 126.com>
> ---
> Changelog | 1 +
> configure | 4 +
> doc/encoders.texi | 41 +++++++
> doc/general.texi | 14 +++
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/libxavs2.c | 303 +++++++++++++++++++++++++++++++++++++++++++++++++
> libavcodec/version.h | 4 +-
> 8 files changed, 367 insertions(+), 2 deletions(-)
> create mode 100644 libavcodec/libxavs2.c
>
> ...
> diff --git a/doc/encoders.texi b/doc/encoders.texi
> index 7b09575..2547acd 100644
> --- a/doc/encoders.texi
> +++ b/doc/encoders.texi
> @@ -2726,6 +2726,47 @@ Reduces detail but attempts to preserve color at extremely low bitrates.
>
> @end table
>
> + at section libxavs2
> +
> +xavs2 AVS2-P2/IEEE1857.4 encoder wrapper.
> +
> +This encoder requires the presence of the libxavs2 headers and library
> +during configuration. You need to explicitly configure the build with
> + at option{--enable-libxavs2}.
> +
> + at subsection Options
> +
> + at table @option
> + at item lcu_row_threads
> +Set the number of parallel threads for rows from 1 to 8 (default 5).
> +
> + at item initial_qp
> +Set the xavs2 quantization parameter from 1 to 63 (default 34). This is
> +used to set the initial qp for the first frame.
> +
> + at item max_qp
> +Set the max qp for rate control from 1 to 63 (default 55).
> +
> + at item min_qp
> +Set the min qp for rate control from 1 to 63 (default 20).
> +
> + at item speed_level
> +Set the Speed level from 0 to 9 (default 0). Higer is better but slower.
Typo: higher.
> +
> + at item hierarchical_ref
> +Set the hierarchical reference or not (default true).
> +
> + at item xavs2-params
> +Set xavs2 options using a list of @var{key}=@var{value} couples separated
> +by ":".
> +
> +For example to specify libxavs2 encoding options with @option{-xavs2-params}:
> +
> + at example
> +ffmpeg -i input -c:v libxavs2 -xavs2-params speed_level=5 output.avs2
> + at end example
> + at end table
> +
> @c man end VIDEO ENCODERS
>
> @chapter Subtitles Encoders
> ...
> diff --git a/libavcodec/libxavs2.c b/libavcodec/libxavs2.c
> new file mode 100644
> index 0000000..3b0244d
> --- /dev/null
> +++ b/libavcodec/libxavs2.c
> @@ -0,0 +1,303 @@
> +/*
> + * AVS2 encoding using the xavs2 library
> + *
> + * Copyright (C) 2018 Yiqun Xu, <yiqun.xu at vipl.ict.ac.cn>
> + * Falei Luo, <falei.luo at gmail.com>
> + * Huiwen Ren, <hwrenx at gmail.com>
> + *
> + * 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 FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include <ctype.h>
This header is never used.
> +
> +#include "xavs2.h"
> +#include "avcodec.h"
> +#include "mpeg12.h"
> +#include "internal.h"
> +#include "libavutil/internal.h"
> +#include "libavutil/mem.h"
> +#include "libavutil/opt.h"
> +#include "libavutil/imgutils.h"
> +#include "libavutil/avassert.h"
> +#include "libavutil/avstring.h"
> +#include "libavutil/common.h"
> +#include "libavutil/avutil.h"
And some of these? At least avassert and imgutils aren't used, possibly some others.
> +
> ...
> +
> +static av_cold int xavs2_init(AVCodecContext *avctx)
> +{
> + XAVS2EContext *cae= avctx->priv_data;
> + int bit_depth, code;
> +
> + bit_depth = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 8 : 10;
> +
> + /* get API handler */
> + cae->api = xavs2_api_get(bit_depth);
> +
> + if (!cae->api) {
> + av_log(avctx, AV_LOG_ERROR, "api get failed\n");
> + return AVERROR_EXTERNAL;
> + }
> +
> + cae->param = cae->api->opt_alloc();
> +
> + if (!cae->param) {
> + av_log(avctx, AV_LOG_ERROR, "param alloc failed\n");
> + return AVERROR(ENOMEM);
> + }
> +
> + xavs2_opt_set2("rec", "%d", 0);
> + xavs2_opt_set2("log", "%d", 0);
> +
> + xavs2_opt_set2("width", "%d", avctx->width);
> + xavs2_opt_set2("height", "%d", avctx->height);
> + xavs2_opt_set2("bframes", "%d", avctx->max_b_frames);
> + xavs2_opt_set2("bitdepth", "%d", bit_depth);
> + xavs2_opt_set2("preset", "%d", cae->preset_level);
> +
> + /* not the same parameter as the IntraPeriod in xavs2 log */
> + xavs2_opt_set2("intraperiod", "%d", avctx->gop_size);
> +
> + xavs2_opt_set2("thread_frames", "%d", avctx->thread_count);
> + xavs2_opt_set2("thread_rows", "%d", cae->lcu_row_threads);
> + xavs2_opt_set2("initial_qp", "%d", cae->initial_qp);
> + xavs2_opt_set2("hierarchical_ref", "%d", cae->hierarchical_reference);
> +
> + if (cae->xavs2_opts) {
> + AVDictionary *dict = NULL;
> + AVDictionaryEntry *en = NULL;
> +
> + if (!av_dict_parse_string(&dict, cae->xavs2_opts, "=", ":", 0)) {
> + while ((en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX))) {
> + xavs2_opt_set2(en->key, "%s", en->value);
> + }
> + av_dict_free(&dict);
> + }
> + }
> +
> + /* Rate control */
> + if (avctx->bit_rate > 0) {
> + xavs2_opt_set2("RateControl", "%d", 1);
> + xavs2_opt_set2("max_qp", "%d", cae->max_qp);
> + xavs2_opt_set2("min_qp", "%d", cae->min_qp);
> + xavs2_opt_set2("TargetBitRate", "%d", avctx->bit_rate);
bit_rate is an int64_t, use "%"PRId64.
> + }
> +
> +
> + ff_mpeg12_find_best_frame_rate(avctx->framerate, &code, NULL, NULL, 0);
> +
> + xavs2_opt_set2("FrameRate", "%d", code);
> +
> + cae->encoder = cae->api->encoder_create(cae->param);
> +
> + if (!cae->encoder) {
> + av_log(avctx,AV_LOG_ERROR, "Can not create encoder. Null pointer returned\n");
> + return AVERROR(EINVAL);
> + }
> +
> + return 0;
> +}
> +
> +static void xavs2_copy_frame_with_shift(xavs2_picture_t *pic, AVFrame *frame, const int shift_in)
The AVFrame needs to be const, because that's what the encode function received from the caller.
> +{
> + int j, k;
> + for (k = 0; k < 3; k++) {
> + int i_stride = pic->img.i_stride[k];
> + for (j = 0; j < pic->img.i_lines[k]; j++) {
> + uint16_t *p_plane = (uint16_t *)&pic->img.img_planes[k][j * i_stride];
> + int i;
> + uint8_t *p_buffer = frame->data[k] + frame->linesize[k] * j;
> + memset(p_plane, 0, i_stride);
> + for (i = 0; i < pic->img.i_width[k]; i++) {
> + p_plane[i] = p_buffer[i] << shift_in;
> + }
> + }
> + }
> +}
> +
> +static void xavs2_copy_frame(xavs2_picture_t *pic, AVFrame *frame)
Also here.
> +{
> + int j, k;
> + for (k = 0; k < 3; k++) {
> + for (j = 0; j < pic->img.i_lines[k]; j++) {
> + memcpy( pic->img.img_planes[k] + pic->img.i_stride[k] * j,
> + frame->data[k]+frame->linesize[k] * j,
> + pic->img.i_width[k] * pic->img.in_sample_size);
> + }
> + }
> +}
> +
> ...
> +
> +static const AVOption options[] = {
> + { "lcu_row_threads" , "number of parallel threads for rows" , OFFSET(lcu_row_threads) , AV_OPT_TYPE_INT, {.i64 = 5 }, 0, INT_MAX, VE },
Did you explain what the reason for the default of five was? If you did I might have missed it. (In particular, I'm wondering what happens if you run it on a processor with fewer than five real threads.)
> + { "initial_qp" , "Quantization parameter" , OFFSET(initial_qp) , AV_OPT_TYPE_INT, {.i64 = 34 }, 1, 63, VE },
> + { "max_qp" , "max qp for rate control" , OFFSET(max_qp) , AV_OPT_TYPE_INT, {.i64 = 55 }, 0, 63, VE },
> + { "min_qp" , "min qp for rate control" , OFFSET(min_qp) , AV_OPT_TYPE_INT, {.i64 = 20 }, 0, 63, VE },
> + { "speed_level" , "Speed level, higher is better but slower", OFFSET(preset_level) , AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 9, VE },
> + { "hierarchical_ref", "hierarchical reference" , OFFSET(hierarchical_reference) , AV_OPT_TYPE_BOOL, {.i64 = 1 }, 0, 1, VE },
> + { "xavs2-params" , "set the xavs2 configuration using a :-separated list of key=value parameters", OFFSET(xavs2_opts), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE },
> + { NULL },
> +};
> +
> ...
Thanks,
- Mark
More information about the ffmpeg-devel
mailing list