Commit e3eb015b authored by Luca Barbato's avatar Luca Barbato Committed by Anton Khirnov

vpxenc: add private options

Make libvpx support close to the libx264 one. Thanks to
Jan Gerber <j@v2v.cc> for the support.
Signed-off-by: 's avatarAnton Khirnov <anton@khirnov.net>
parent 08bd22a6
...@@ -29,8 +29,10 @@ ...@@ -29,8 +29,10 @@
#include <vpx/vp8cx.h> #include <vpx/vp8cx.h>
#include "avcodec.h" #include "avcodec.h"
#include "internal.h"
#include "libavutil/base64.h" #include "libavutil/base64.h"
#include "libavutil/mathematics.h" #include "libavutil/mathematics.h"
#include "libavutil/opt.h"
/** /**
* Portion of struct vpx_codec_cx_pkt from vpx_encoder.h. * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h.
...@@ -48,11 +50,19 @@ struct FrameListData { ...@@ -48,11 +50,19 @@ struct FrameListData {
}; };
typedef struct VP8EncoderContext { typedef struct VP8EncoderContext {
AVClass *class;
struct vpx_codec_ctx encoder; struct vpx_codec_ctx encoder;
struct vpx_image rawimg; struct vpx_image rawimg;
struct vpx_fixed_buf twopass_stats; struct vpx_fixed_buf twopass_stats;
unsigned long deadline; //i.e., RT/GOOD/BEST unsigned long deadline; //i.e., RT/GOOD/BEST
struct FrameListData *coded_frame_list; struct FrameListData *coded_frame_list;
int cpu_used;
int auto_alt_ref;
int arnr_max_frames;
int arnr_strength;
int arnr_type;
int lag_in_frames;
int error_resilient;
} VP8Context; } VP8Context;
/** String mappings for enum vp8e_enc_control_id */ /** String mappings for enum vp8e_enc_control_id */
...@@ -205,7 +215,6 @@ static av_cold int vp8_init(AVCodecContext *avctx) ...@@ -205,7 +215,6 @@ static av_cold int vp8_init(AVCodecContext *avctx)
{ {
VP8Context *ctx = avctx->priv_data; VP8Context *ctx = avctx->priv_data;
const struct vpx_codec_iface *iface = &vpx_codec_vp8_cx_algo; const struct vpx_codec_iface *iface = &vpx_codec_vp8_cx_algo;
int cpuused = 3;
struct vpx_codec_enc_cfg enccfg; struct vpx_codec_enc_cfg enccfg;
int res; int res;
...@@ -225,6 +234,9 @@ static av_cold int vp8_init(AVCodecContext *avctx) ...@@ -225,6 +234,9 @@ static av_cold int vp8_init(AVCodecContext *avctx)
enccfg.g_timebase.den = avctx->time_base.den; enccfg.g_timebase.den = avctx->time_base.den;
enccfg.g_threads = avctx->thread_count; enccfg.g_threads = avctx->thread_count;
if (ctx->lag_in_frames >= 0)
enccfg.g_lag_in_frames = ctx->lag_in_frames;
if (avctx->flags & CODEC_FLAG_PASS1) if (avctx->flags & CODEC_FLAG_PASS1)
enccfg.g_pass = VPX_RC_FIRST_PASS; enccfg.g_pass = VPX_RC_FIRST_PASS;
else if (avctx->flags & CODEC_FLAG_PASS2) else if (avctx->flags & CODEC_FLAG_PASS2)
...@@ -292,13 +304,14 @@ static av_cold int vp8_init(AVCodecContext *avctx) ...@@ -292,13 +304,14 @@ static av_cold int vp8_init(AVCodecContext *avctx)
enccfg.rc_twopass_stats_in = ctx->twopass_stats; enccfg.rc_twopass_stats_in = ctx->twopass_stats;
} }
ctx->deadline = VPX_DL_GOOD_QUALITY;
/* 0-3: For non-zero values the encoder increasingly optimizes for reduced /* 0-3: For non-zero values the encoder increasingly optimizes for reduced
complexity playback on low powered devices at the expense of encode complexity playback on low powered devices at the expense of encode
quality. */ quality. */
if (avctx->profile != FF_PROFILE_UNKNOWN) if (avctx->profile != FF_PROFILE_UNKNOWN)
enccfg.g_profile = avctx->profile; enccfg.g_profile = avctx->profile;
enccfg.g_error_resilient = ctx->error_resilient;
dump_enc_cfg(avctx, &enccfg); dump_enc_cfg(avctx, &enccfg);
/* Construct Encoder Context */ /* Construct Encoder Context */
res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, 0); res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, 0);
...@@ -309,7 +322,16 @@ static av_cold int vp8_init(AVCodecContext *avctx) ...@@ -309,7 +322,16 @@ static av_cold int vp8_init(AVCodecContext *avctx)
//codec control failures are currently treated only as warnings //codec control failures are currently treated only as warnings
av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n"); av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n");
codecctl_int(avctx, VP8E_SET_CPUUSED, cpuused); if (ctx->cpu_used != INT_MIN)
codecctl_int(avctx, VP8E_SET_CPUUSED, ctx->cpu_used);
if (ctx->auto_alt_ref >= 0)
codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF, ctx->auto_alt_ref);
if (ctx->arnr_max_frames >= 0)
codecctl_int(avctx, VP8E_SET_ARNR_MAXFRAMES, ctx->arnr_max_frames);
if (ctx->arnr_strength >= 0)
codecctl_int(avctx, VP8E_SET_ARNR_STRENGTH, ctx->arnr_strength);
if (ctx->arnr_type >= 0)
codecctl_int(avctx, VP8E_SET_ARNR_TYPE, ctx->arnr_type);
codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction); codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction);
codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices)); codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices));
codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, avctx->mb_threshold); codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, avctx->mb_threshold);
...@@ -496,6 +518,40 @@ static int vp8_encode(AVCodecContext *avctx, uint8_t *buf, int buf_size, ...@@ -496,6 +518,40 @@ static int vp8_encode(AVCodecContext *avctx, uint8_t *buf, int buf_size,
return coded_size; return coded_size;
} }
#define OFFSET(x) offsetof(VP8Context, x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
{ "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), FF_OPT_TYPE_INT, {INT_MIN}, INT_MIN, INT_MAX, VE},
{ "auto-alt-ref", "Enable use of alternate reference "
"frames (2-pass only)", OFFSET(auto_alt_ref), FF_OPT_TYPE_INT, {-1}, -1, 1, VE},
{ "lag-in-frames", "Number of frames to look ahead for "
"alternate reference frame selection", OFFSET(lag_in_frames), FF_OPT_TYPE_INT, {-1}, -1, INT_MAX, VE},
{ "arnr-maxframes", "altref noise reduction max frame count", OFFSET(arnr_max_frames), FF_OPT_TYPE_INT, {-1}, -1, INT_MAX, VE},
{ "arnr-strength", "altref noise reduction filter strength", OFFSET(arnr_strength), FF_OPT_TYPE_INT, {-1}, -1, INT_MAX, VE},
{ "arnr-type", "altref noise reduction filter type", OFFSET(arnr_type), FF_OPT_TYPE_INT, {-1}, -1, INT_MAX, VE, "arnr_type"},
{ "backward", NULL, 0, FF_OPT_TYPE_CONST, {1}, 0, 0, VE, "arnr_type" },
{ "forward", NULL, 0, FF_OPT_TYPE_CONST, {2}, 0, 0, VE, "arnr_type" },
{ "centered", NULL, 0, FF_OPT_TYPE_CONST, {3}, 0, 0, VE, "arnr_type" },
{ "deadline", "Time to spend encoding, in microseconds.", OFFSET(deadline), FF_OPT_TYPE_INT, {VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"},
{ "best", NULL, 0, FF_OPT_TYPE_CONST, {VPX_DL_BEST_QUALITY}, 0, 0, VE, "quality"},
{ "good", NULL, 0, FF_OPT_TYPE_CONST, {VPX_DL_GOOD_QUALITY}, 0, 0, VE, "quality"},
{ "realtime", NULL, 0, FF_OPT_TYPE_CONST, {VPX_DL_REALTIME}, 0, 0, VE, "quality"},
{ "error-resilient", "Error resilience configuration", OFFSET(error_resilient), FF_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, VE, "er"},
{ "default", "Improve resiliency against losses of whole frames", 0, FF_OPT_TYPE_CONST, {VPX_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"},
{ "partitions", "The frame partitions are independently decodable "
"by the bool decoder, meaning that partitions can be decoded even "
"though earlier partitions have been lost. Note that intra predicition"
" is still done over the partition boundary.", 0, FF_OPT_TYPE_CONST, {VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"},
{ NULL }
};
static const AVClass class = {
.class_name = "libvpx encoder",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
AVCodec ff_libvpx_encoder = { AVCodec ff_libvpx_encoder = {
.name = "libvpx", .name = "libvpx",
.type = AVMEDIA_TYPE_VIDEO, .type = AVMEDIA_TYPE_VIDEO,
...@@ -507,4 +563,5 @@ AVCodec ff_libvpx_encoder = { ...@@ -507,4 +563,5 @@ AVCodec ff_libvpx_encoder = {
.capabilities = CODEC_CAP_DELAY, .capabilities = CODEC_CAP_DELAY,
.pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
.long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"),
.priv_class = &class,
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment