|
|
|
@@ -20,7 +20,7 @@ |
|
|
|
|
|
|
|
/** |
|
|
|
* @file |
|
|
|
* VP8 encoder support via libvpx |
|
|
|
* VP8/9 encoder support via libvpx |
|
|
|
*/ |
|
|
|
|
|
|
|
#define VPX_DISABLE_CTRL_TYPECHECKS 1 |
|
|
|
@@ -60,7 +60,7 @@ struct FrameListData { |
|
|
|
struct FrameListData *next; |
|
|
|
}; |
|
|
|
|
|
|
|
typedef struct VP8EncoderContext { |
|
|
|
typedef struct VPxEncoderContext { |
|
|
|
AVClass *class; |
|
|
|
struct vpx_codec_ctx encoder; |
|
|
|
struct vpx_image rawimg; |
|
|
|
@@ -107,7 +107,7 @@ typedef struct VP8EncoderContext { |
|
|
|
int drop_threshold; |
|
|
|
int noise_sensitivity; |
|
|
|
int vpx_cs; |
|
|
|
} VP8Context; |
|
|
|
} VPxContext; |
|
|
|
|
|
|
|
/** String mappings for enum vp8e_enc_control_id */ |
|
|
|
static const char *const ctlidstr[] = { |
|
|
|
@@ -139,7 +139,7 @@ static const char *const ctlidstr[] = { |
|
|
|
|
|
|
|
static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) |
|
|
|
{ |
|
|
|
VP8Context *ctx = avctx->priv_data; |
|
|
|
VPxContext *ctx = avctx->priv_data; |
|
|
|
const char *error = vpx_codec_error(&ctx->encoder); |
|
|
|
const char *detail = vpx_codec_error_detail(&ctx->encoder); |
|
|
|
|
|
|
|
@@ -242,7 +242,7 @@ static av_cold void free_frame_list(struct FrameListData *list) |
|
|
|
static av_cold int codecctl_int(AVCodecContext *avctx, |
|
|
|
enum vp8e_enc_control_id id, int val) |
|
|
|
{ |
|
|
|
VP8Context *ctx = avctx->priv_data; |
|
|
|
VPxContext *ctx = avctx->priv_data; |
|
|
|
char buf[80]; |
|
|
|
int width = -30; |
|
|
|
int res; |
|
|
|
@@ -260,9 +260,9 @@ static av_cold int codecctl_int(AVCodecContext *avctx, |
|
|
|
return res == VPX_CODEC_OK ? 0 : AVERROR(EINVAL); |
|
|
|
} |
|
|
|
|
|
|
|
static av_cold int vp8_free(AVCodecContext *avctx) |
|
|
|
static av_cold int vpx_free(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
VP8Context *ctx = avctx->priv_data; |
|
|
|
VPxContext *ctx = avctx->priv_data; |
|
|
|
|
|
|
|
vpx_codec_destroy(&ctx->encoder); |
|
|
|
if (ctx->is_alpha) |
|
|
|
@@ -278,7 +278,7 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, |
|
|
|
struct vpx_codec_enc_cfg *enccfg, vpx_codec_flags_t *flags, |
|
|
|
vpx_img_fmt_t *img_fmt) |
|
|
|
{ |
|
|
|
VP8Context av_unused *ctx = avctx->priv_data; |
|
|
|
VPxContext av_unused *ctx = avctx->priv_data; |
|
|
|
#ifdef VPX_IMG_FMT_HIGHBITDEPTH |
|
|
|
enccfg->g_bit_depth = enccfg->g_input_bit_depth = 8; |
|
|
|
#endif |
|
|
|
@@ -367,7 +367,7 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, |
|
|
|
static void set_colorspace(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
enum vpx_color_space vpx_cs; |
|
|
|
VP8Context *ctx = avctx->priv_data; |
|
|
|
VPxContext *ctx = avctx->priv_data; |
|
|
|
|
|
|
|
if (ctx->vpx_cs) { |
|
|
|
vpx_cs = ctx->vpx_cs; |
|
|
|
@@ -413,7 +413,7 @@ static void set_color_range(AVCodecContext *avctx) |
|
|
|
static av_cold int vpx_init(AVCodecContext *avctx, |
|
|
|
const struct vpx_codec_iface *iface) |
|
|
|
{ |
|
|
|
VP8Context *ctx = avctx->priv_data; |
|
|
|
VPxContext *ctx = avctx->priv_data; |
|
|
|
struct vpx_codec_enc_cfg enccfg = { 0 }; |
|
|
|
struct vpx_codec_enc_cfg enccfg_alpha; |
|
|
|
vpx_codec_flags_t flags = (avctx->flags & AV_CODEC_FLAG_PSNR) ? VPX_CODEC_USE_PSNR : 0; |
|
|
|
@@ -709,7 +709,7 @@ FF_ENABLE_DEPRECATION_WARNINGS |
|
|
|
static inline void cx_pktcpy(struct FrameListData *dst, |
|
|
|
const struct vpx_codec_cx_pkt *src, |
|
|
|
const struct vpx_codec_cx_pkt *src_alpha, |
|
|
|
VP8Context *ctx) |
|
|
|
VPxContext *ctx) |
|
|
|
{ |
|
|
|
dst->pts = src->data.frame.pts; |
|
|
|
dst->duration = src->data.frame.duration; |
|
|
|
@@ -828,7 +828,7 @@ FF_ENABLE_DEPRECATION_WARNINGS |
|
|
|
*/ |
|
|
|
static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) |
|
|
|
{ |
|
|
|
VP8Context *ctx = avctx->priv_data; |
|
|
|
VPxContext *ctx = avctx->priv_data; |
|
|
|
const struct vpx_codec_cx_pkt *pkt; |
|
|
|
const struct vpx_codec_cx_pkt *pkt_alpha = NULL; |
|
|
|
const void *iter = NULL; |
|
|
|
@@ -928,10 +928,10 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) |
|
|
|
return size; |
|
|
|
} |
|
|
|
|
|
|
|
static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt, |
|
|
|
static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, |
|
|
|
const AVFrame *frame, int *got_packet) |
|
|
|
{ |
|
|
|
VP8Context *ctx = avctx->priv_data; |
|
|
|
VPxContext *ctx = avctx->priv_data; |
|
|
|
struct vpx_image *rawimg = NULL; |
|
|
|
struct vpx_image *rawimg_alpha = NULL; |
|
|
|
int64_t timestamp = 0; |
|
|
|
@@ -1010,7 +1010,7 @@ static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt, |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
#define OFFSET(x) offsetof(VP8Context, x) |
|
|
|
#define OFFSET(x) offsetof(VPxContext, x) |
|
|
|
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
|
|
|
|
|
|
|
#ifndef VPX_ERROR_RESILIENT_DEFAULT |
|
|
|
@@ -1043,23 +1043,23 @@ static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt, |
|
|
|
"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, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"}, \ |
|
|
|
{ "crf", "Select the quality for constant quality mode", offsetof(VP8Context, crf), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, VE }, \ |
|
|
|
{ "crf", "Select the quality for constant quality mode", offsetof(VPxContext, crf), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, VE }, \ |
|
|
|
{ "static-thresh", "A change threshold on blocks below which they will be skipped by the encoder", OFFSET(static_thresh), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, \ |
|
|
|
{ "drop-threshold", "Frame drop threshold", offsetof(VP8Context, drop_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, VE }, \ |
|
|
|
{ "drop-threshold", "Frame drop threshold", offsetof(VPxContext, drop_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, VE }, \ |
|
|
|
{ "noise-sensitivity", "Noise sensitivity", OFFSET(noise_sensitivity), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 4, VE}, \ |
|
|
|
{ "undershoot-pct", "Datarate undershoot (min) target (%)", OFFSET(rc_undershoot_pct), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 100, VE }, \ |
|
|
|
{ "overshoot-pct", "Datarate overshoot (max) target (%)", OFFSET(rc_overshoot_pct), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE }, \ |
|
|
|
|
|
|
|
#define LEGACY_OPTIONS \ |
|
|
|
{"speed", "", offsetof(VP8Context, cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE}, \ |
|
|
|
{"quality", "", offsetof(VP8Context, deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"}, \ |
|
|
|
{"vp8flags", "", offsetof(VP8Context, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, UINT_MAX, VE, "flags"}, \ |
|
|
|
{"speed", "", offsetof(VPxContext, cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE}, \ |
|
|
|
{"quality", "", offsetof(VPxContext, deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"}, \ |
|
|
|
{"vp8flags", "", offsetof(VPxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, UINT_MAX, VE, "flags"}, \ |
|
|
|
{"error_resilient", "enable error resilience", 0, AV_OPT_TYPE_CONST, {.i64 = VP8F_ERROR_RESILIENT}, INT_MIN, INT_MAX, VE, "flags"}, \ |
|
|
|
{"altref", "enable use of alternate reference frames (VP8/2-pass only)", 0, AV_OPT_TYPE_CONST, {.i64 = VP8F_AUTO_ALT_REF}, INT_MIN, INT_MAX, VE, "flags"}, \ |
|
|
|
{"arnr_max_frames", "altref noise reduction max frame count", offsetof(VP8Context, arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 15, VE}, \ |
|
|
|
{"arnr_strength", "altref noise reduction filter strength", offsetof(VP8Context, arnr_strength), AV_OPT_TYPE_INT, {.i64 = 3}, 0, 6, VE}, \ |
|
|
|
{"arnr_type", "altref noise reduction filter type", offsetof(VP8Context, arnr_type), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 3, VE}, \ |
|
|
|
{"rc_lookahead", "Number of frames to look ahead for alternate reference frame selection", offsetof(VP8Context, lag_in_frames), AV_OPT_TYPE_INT, {.i64 = 25}, 0, 25, VE}, \ |
|
|
|
{"arnr_max_frames", "altref noise reduction max frame count", offsetof(VPxContext, arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 15, VE}, \ |
|
|
|
{"arnr_strength", "altref noise reduction filter strength", offsetof(VPxContext, arnr_strength), AV_OPT_TYPE_INT, {.i64 = 3}, 0, 6, VE}, \ |
|
|
|
{"arnr_type", "altref noise reduction filter type", offsetof(VPxContext, arnr_type), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 3, VE}, \ |
|
|
|
{"rc_lookahead", "Number of frames to look ahead for alternate reference frame selection", offsetof(VPxContext, lag_in_frames), AV_OPT_TYPE_INT, {.i64 = 25}, 0, 25, VE}, \ |
|
|
|
|
|
|
|
#if CONFIG_LIBVPX_VP8_ENCODER |
|
|
|
static const AVOption vp8_options[] = { |
|
|
|
@@ -1117,10 +1117,10 @@ AVCodec ff_libvpx_vp8_encoder = { |
|
|
|
.long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), |
|
|
|
.type = AVMEDIA_TYPE_VIDEO, |
|
|
|
.id = AV_CODEC_ID_VP8, |
|
|
|
.priv_data_size = sizeof(VP8Context), |
|
|
|
.priv_data_size = sizeof(VPxContext), |
|
|
|
.init = vp8_init, |
|
|
|
.encode2 = vp8_encode, |
|
|
|
.close = vp8_free, |
|
|
|
.encode2 = vpx_encode, |
|
|
|
.close = vpx_free, |
|
|
|
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, |
|
|
|
.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }, |
|
|
|
.priv_class = &class_vp8, |
|
|
|
@@ -1146,10 +1146,10 @@ AVCodec ff_libvpx_vp9_encoder = { |
|
|
|
.long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), |
|
|
|
.type = AVMEDIA_TYPE_VIDEO, |
|
|
|
.id = AV_CODEC_ID_VP9, |
|
|
|
.priv_data_size = sizeof(VP8Context), |
|
|
|
.priv_data_size = sizeof(VPxContext), |
|
|
|
.init = vp9_init, |
|
|
|
.encode2 = vp8_encode, |
|
|
|
.close = vp8_free, |
|
|
|
.encode2 = vpx_encode, |
|
|
|
.close = vpx_free, |
|
|
|
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, |
|
|
|
.profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), |
|
|
|
.priv_class = &class_vp9, |
|
|
|
|