libvpxenc.c 48.1 KB
Newer Older
James Zern's avatar
James Zern committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * Copyright (c) 2010, Google, Inc.
 *
 * 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
 */

/**
 * @file
23
 * VP8/9 encoder support via libvpx
James Zern's avatar
James Zern committed
24 25 26 27 28 29 30 31
 */

#define VPX_DISABLE_CTRL_TYPECHECKS 1
#define VPX_CODEC_DISABLE_COMPAT    1
#include <vpx/vpx_encoder.h>
#include <vpx/vp8cx.h>

#include "avcodec.h"
32
#include "internal.h"
33
#include "libavutil/avassert.h"
34
#include "libvpx.h"
35
#include "profiles.h"
James Zern's avatar
James Zern committed
36
#include "libavutil/base64.h"
37
#include "libavutil/common.h"
38
#include "libavutil/internal.h"
39
#include "libavutil/intreadwrite.h"
40
#include "libavutil/mathematics.h"
41
#include "libavutil/opt.h"
James Zern's avatar
James Zern committed
42 43 44 45 46 47

/**
 * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h.
 * One encoded frame returned from the library.
 */
struct FrameListData {
Benoit Fouet's avatar
Benoit Fouet committed
48 49
    void *buf;                       /**< compressed data buffer */
    size_t sz;                       /**< length of compressed data */
50 51
    void *buf_alpha;
    size_t sz_alpha;
Benoit Fouet's avatar
Benoit Fouet committed
52
    int64_t pts;                     /**< time stamp to show frame
James Zern's avatar
James Zern committed
53
                                          (in timebase units) */
Benoit Fouet's avatar
Benoit Fouet committed
54
    unsigned long duration;          /**< duration to show frame
James Zern's avatar
James Zern committed
55
                                          (in timebase units) */
Benoit Fouet's avatar
Benoit Fouet committed
56
    uint32_t flags;                  /**< flags for this frame */
57 58 59
    uint64_t sse[4];
    int have_sse;                    /**< true if we have pending sse[] */
    uint64_t frame_number;
James Zern's avatar
James Zern committed
60 61 62
    struct FrameListData *next;
};

63
typedef struct VPxEncoderContext {
64
    AVClass *class;
James Zern's avatar
James Zern committed
65 66
    struct vpx_codec_ctx encoder;
    struct vpx_image rawimg;
67 68 69
    struct vpx_codec_ctx encoder_alpha;
    struct vpx_image rawimg_alpha;
    uint8_t is_alpha;
James Zern's avatar
James Zern committed
70
    struct vpx_fixed_buf twopass_stats;
71
    int deadline; //i.e., RT/GOOD/BEST
72 73 74
    uint64_t sse[4];
    int have_sse; /**< true if we have pending sse[] */
    uint64_t frame_number;
James Zern's avatar
James Zern committed
75
    struct FrameListData *coded_frame_list;
76

77
    int cpu_used;
78 79 80 81 82 83 84
    /**
     * VP8 specific flags, see VP8F_* below.
     */
    int flags;
#define VP8F_ERROR_RESILIENT 0x00000001 ///< Enable measures appropriate for streaming over lossy links
#define VP8F_AUTO_ALT_REF    0x00000002 ///< Enable automatic alternate reference frame generation

85
    int auto_alt_ref;
86 87 88 89

    int arnr_max_frames;
    int arnr_strength;
    int arnr_type;
90

91 92
    int tune;

93
    int lag_in_frames;
94
    int error_resilient;
95
    int crf;
96
    int static_thresh;
97
    int max_intra_rate;
98
    int rc_undershoot_pct;
99
    int rc_overshoot_pct;
James Zern's avatar
James Zern committed
100 101 102 103 104 105

    // VP9-only
    int lossless;
    int tile_columns;
    int tile_rows;
    int frame_parallel;
106
    int aq_mode;
107
    int drop_threshold;
108
    int noise_sensitivity;
109
    int vpx_cs;
110
    float level;
111
    int row_mt;
112
} VPxContext;
James Zern's avatar
James Zern committed
113 114

/** String mappings for enum vp8e_enc_control_id */
115
static const char *const ctlidstr[] = {
James Zern's avatar
James Zern committed
116 117 118 119 120 121 122 123
    [VP8E_SET_CPUUSED]           = "VP8E_SET_CPUUSED",
    [VP8E_SET_ENABLEAUTOALTREF]  = "VP8E_SET_ENABLEAUTOALTREF",
    [VP8E_SET_NOISE_SENSITIVITY] = "VP8E_SET_NOISE_SENSITIVITY",
    [VP8E_SET_STATIC_THRESHOLD]  = "VP8E_SET_STATIC_THRESHOLD",
    [VP8E_SET_TOKEN_PARTITIONS]  = "VP8E_SET_TOKEN_PARTITIONS",
    [VP8E_SET_ARNR_MAXFRAMES]    = "VP8E_SET_ARNR_MAXFRAMES",
    [VP8E_SET_ARNR_STRENGTH]     = "VP8E_SET_ARNR_STRENGTH",
    [VP8E_SET_ARNR_TYPE]         = "VP8E_SET_ARNR_TYPE",
124
    [VP8E_SET_TUNING]            = "VP8E_SET_TUNING",
125
    [VP8E_SET_CQ_LEVEL]          = "VP8E_SET_CQ_LEVEL",
126
    [VP8E_SET_MAX_INTRA_BITRATE_PCT] = "VP8E_SET_MAX_INTRA_BITRATE_PCT",
James Zern's avatar
James Zern committed
127 128 129 130 131
#if CONFIG_LIBVPX_VP9_ENCODER
    [VP9E_SET_LOSSLESS]                = "VP9E_SET_LOSSLESS",
    [VP9E_SET_TILE_COLUMNS]            = "VP9E_SET_TILE_COLUMNS",
    [VP9E_SET_TILE_ROWS]               = "VP9E_SET_TILE_ROWS",
    [VP9E_SET_FRAME_PARALLEL_DECODING] = "VP9E_SET_FRAME_PARALLEL_DECODING",
132
    [VP9E_SET_AQ_MODE]                 = "VP9E_SET_AQ_MODE",
133 134 135
#if VPX_ENCODER_ABI_VERSION > 8
    [VP9E_SET_COLOR_SPACE]             = "VP9E_SET_COLOR_SPACE",
#endif
136 137 138
#if VPX_ENCODER_ABI_VERSION >= 11
    [VP9E_SET_COLOR_RANGE]             = "VP9E_SET_COLOR_RANGE",
#endif
139 140
#if VPX_ENCODER_ABI_VERSION >= 12
    [VP9E_SET_TARGET_LEVEL]            = "VP9E_SET_TARGET_LEVEL",
141
    [VP9E_GET_LEVEL]                   = "VP9E_GET_LEVEL",
142
#endif
143 144 145
#ifdef VPX_CTRL_VP9E_SET_ROW_MT
    [VP9E_SET_ROW_MT]                  = "VP9E_SET_ROW_MT",
#endif
James Zern's avatar
James Zern committed
146
#endif
James Zern's avatar
James Zern committed
147 148 149 150
};

static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc)
{
151
    VPxContext *ctx = avctx->priv_data;
James Zern's avatar
James Zern committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
    const char *error  = vpx_codec_error(&ctx->encoder);
    const char *detail = vpx_codec_error_detail(&ctx->encoder);

    av_log(avctx, AV_LOG_ERROR, "%s: %s\n", desc, error);
    if (detail)
        av_log(avctx, AV_LOG_ERROR, "  Additional information: %s\n", detail);
}

static av_cold void dump_enc_cfg(AVCodecContext *avctx,
                                 const struct vpx_codec_enc_cfg *cfg)
{
    int width = -30;
    int level = AV_LOG_DEBUG;

    av_log(avctx, level, "vpx_codec_enc_cfg\n");
    av_log(avctx, level, "generic settings\n"
           "  %*s%u\n  %*s%u\n  %*s%u\n  %*s%u\n  %*s%u\n"
169 170 171
#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_IMG_FMT_HIGHBITDEPTH)
           "  %*s%u\n  %*s%u\n"
#endif
James Zern's avatar
James Zern committed
172 173 174 175 176 177
           "  %*s{%u/%u}\n  %*s%u\n  %*s%d\n  %*s%u\n",
           width, "g_usage:",           cfg->g_usage,
           width, "g_threads:",         cfg->g_threads,
           width, "g_profile:",         cfg->g_profile,
           width, "g_w:",               cfg->g_w,
           width, "g_h:",               cfg->g_h,
178 179 180 181
#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_IMG_FMT_HIGHBITDEPTH)
           width, "g_bit_depth:",       cfg->g_bit_depth,
           width, "g_input_bit_depth:", cfg->g_input_bit_depth,
#endif
James Zern's avatar
James Zern committed
182 183 184 185 186 187
           width, "g_timebase:",        cfg->g_timebase.num, cfg->g_timebase.den,
           width, "g_error_resilient:", cfg->g_error_resilient,
           width, "g_pass:",            cfg->g_pass,
           width, "g_lag_in_frames:",   cfg->g_lag_in_frames);
    av_log(avctx, level, "rate control settings\n"
           "  %*s%u\n  %*s%u\n  %*s%u\n  %*s%u\n"
188
           "  %*s%d\n  %*s%p(%"SIZE_SPECIFIER")\n  %*s%u\n",
James Zern's avatar
James Zern committed
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
           width, "rc_dropframe_thresh:",   cfg->rc_dropframe_thresh,
           width, "rc_resize_allowed:",     cfg->rc_resize_allowed,
           width, "rc_resize_up_thresh:",   cfg->rc_resize_up_thresh,
           width, "rc_resize_down_thresh:", cfg->rc_resize_down_thresh,
           width, "rc_end_usage:",          cfg->rc_end_usage,
           width, "rc_twopass_stats_in:",   cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz,
           width, "rc_target_bitrate:",     cfg->rc_target_bitrate);
    av_log(avctx, level, "quantizer settings\n"
           "  %*s%u\n  %*s%u\n",
           width, "rc_min_quantizer:", cfg->rc_min_quantizer,
           width, "rc_max_quantizer:", cfg->rc_max_quantizer);
    av_log(avctx, level, "bitrate tolerance\n"
           "  %*s%u\n  %*s%u\n",
           width, "rc_undershoot_pct:", cfg->rc_undershoot_pct,
           width, "rc_overshoot_pct:",  cfg->rc_overshoot_pct);
    av_log(avctx, level, "decoder buffer model\n"
            "  %*s%u\n  %*s%u\n  %*s%u\n",
            width, "rc_buf_sz:",         cfg->rc_buf_sz,
            width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz,
            width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz);
    av_log(avctx, level, "2 pass rate control settings\n"
           "  %*s%u\n  %*s%u\n  %*s%u\n",
           width, "rc_2pass_vbr_bias_pct:",       cfg->rc_2pass_vbr_bias_pct,
           width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct,
           width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct);
    av_log(avctx, level, "keyframing settings\n"
           "  %*s%d\n  %*s%u\n  %*s%u\n",
           width, "kf_mode:",     cfg->kf_mode,
           width, "kf_min_dist:", cfg->kf_min_dist,
           width, "kf_max_dist:", cfg->kf_max_dist);
    av_log(avctx, level, "\n");
}

static void coded_frame_add(void *list, struct FrameListData *cx_frame)
{
    struct FrameListData **p = list;

226
    while (*p)
James Zern's avatar
James Zern committed
227 228 229 230 231 232 233 234
        p = &(*p)->next;
    *p = cx_frame;
    cx_frame->next = NULL;
}

static av_cold void free_coded_frame(struct FrameListData *cx_frame)
{
    av_freep(&cx_frame->buf);
235 236
    if (cx_frame->buf_alpha)
        av_freep(&cx_frame->buf_alpha);
James Zern's avatar
James Zern committed
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
    av_freep(&cx_frame);
}

static av_cold void free_frame_list(struct FrameListData *list)
{
    struct FrameListData *p = list;

    while (p) {
        list = list->next;
        free_coded_frame(p);
        p = list;
    }
}

static av_cold int codecctl_int(AVCodecContext *avctx,
                                enum vp8e_enc_control_id id, int val)
{
254
    VPxContext *ctx = avctx->priv_data;
James Zern's avatar
James Zern committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
    char buf[80];
    int width = -30;
    int res;

    snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]);
    av_log(avctx, AV_LOG_DEBUG, "  %*s%d\n", width, buf, val);

    res = vpx_codec_control(&ctx->encoder, id, val);
    if (res != VPX_CODEC_OK) {
        snprintf(buf, sizeof(buf), "Failed to set %s codec control",
                 ctlidstr[id]);
        log_encoder_error(avctx, buf);
    }

    return res == VPX_CODEC_OK ? 0 : AVERROR(EINVAL);
}

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
#if VPX_ENCODER_ABI_VERSION >= 12
static av_cold int codecctl_intp(AVCodecContext *avctx,
                                 enum vp8e_enc_control_id id, int *val)
{
    VPxContext *ctx = avctx->priv_data;
    char buf[80];
    int width = -30;
    int res;

    snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]);
    av_log(avctx, AV_LOG_DEBUG, "  %*s%d\n", width, buf, *val);

    res = vpx_codec_control(&ctx->encoder, id, val);
    if (res != VPX_CODEC_OK) {
        snprintf(buf, sizeof(buf), "Failed to set %s codec control",
                 ctlidstr[id]);
        log_encoder_error(avctx, buf);
    }

    return res == VPX_CODEC_OK ? 0 : AVERROR(EINVAL);
}
#endif

295
static av_cold int vpx_free(AVCodecContext *avctx)
James Zern's avatar
James Zern committed
296
{
297
    VPxContext *ctx = avctx->priv_data;
James Zern's avatar
James Zern committed
298

299
#if VPX_ENCODER_ABI_VERSION >= 12
300 301
    if (avctx->codec_id == AV_CODEC_ID_VP9 && ctx->level >= 0 &&
        !(avctx->flags & AV_CODEC_FLAG_PASS1)) {
302 303 304 305 306 307
        int level_out = 0;
        if (!codecctl_intp(avctx, VP9E_GET_LEVEL, &level_out))
            av_log(avctx, AV_LOG_INFO, "Encoded level %.1f\n", level_out * 0.1);
    }
#endif

James Zern's avatar
James Zern committed
308
    vpx_codec_destroy(&ctx->encoder);
309 310
    if (ctx->is_alpha)
        vpx_codec_destroy(&ctx->encoder_alpha);
James Zern's avatar
James Zern committed
311 312 313 314 315 316
    av_freep(&ctx->twopass_stats.buf);
    av_freep(&avctx->stats_out);
    free_frame_list(ctx->coded_frame_list);
    return 0;
}

317 318 319
#if CONFIG_LIBVPX_VP9_ENCODER
static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps,
                       struct vpx_codec_enc_cfg *enccfg, vpx_codec_flags_t *flags,
320 321
                       vpx_img_fmt_t *img_fmt)
{
322
    VPxContext av_unused *ctx = avctx->priv_data;
323 324 325 326 327
#ifdef VPX_IMG_FMT_HIGHBITDEPTH
    enccfg->g_bit_depth = enccfg->g_input_bit_depth = 8;
#endif
    switch (avctx->pix_fmt) {
    case AV_PIX_FMT_YUV420P:
328
    case AV_PIX_FMT_YUVA420P:
329 330 331 332
        enccfg->g_profile = 0;
        *img_fmt = VPX_IMG_FMT_I420;
        return 0;
    case AV_PIX_FMT_YUV422P:
333 334 335 336 337 338 339 340
        enccfg->g_profile = 1;
        *img_fmt = VPX_IMG_FMT_I422;
        return 0;
#if VPX_IMAGE_ABI_VERSION >= 3
    case AV_PIX_FMT_YUV440P:
        enccfg->g_profile = 1;
        *img_fmt = VPX_IMG_FMT_I440;
        return 0;
341 342
    case AV_PIX_FMT_GBRP:
        ctx->vpx_cs = VPX_CS_SRGB;
343
#endif
344 345
    case AV_PIX_FMT_YUV444P:
        enccfg->g_profile = 1;
346
        *img_fmt = VPX_IMG_FMT_I444;
347 348
        return 0;
#ifdef VPX_IMG_FMT_HIGHBITDEPTH
349 350
    case AV_PIX_FMT_YUV420P10:
    case AV_PIX_FMT_YUV420P12:
351 352
        if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) {
            enccfg->g_bit_depth = enccfg->g_input_bit_depth =
353
                avctx->pix_fmt == AV_PIX_FMT_YUV420P10 ? 10 : 12;
354 355 356 357 358 359
            enccfg->g_profile = 2;
            *img_fmt = VPX_IMG_FMT_I42016;
            *flags |= VPX_CODEC_USE_HIGHBITDEPTH;
            return 0;
        }
        break;
360 361
    case AV_PIX_FMT_YUV422P10:
    case AV_PIX_FMT_YUV422P12:
362 363
        if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) {
            enccfg->g_bit_depth = enccfg->g_input_bit_depth =
364
                avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 10 : 12;
365 366 367 368 369 370
            enccfg->g_profile = 3;
            *img_fmt = VPX_IMG_FMT_I42216;
            *flags |= VPX_CODEC_USE_HIGHBITDEPTH;
            return 0;
        }
        break;
371
#if VPX_IMAGE_ABI_VERSION >= 3
372 373
    case AV_PIX_FMT_YUV440P10:
    case AV_PIX_FMT_YUV440P12:
374 375
        if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) {
            enccfg->g_bit_depth = enccfg->g_input_bit_depth =
376
                avctx->pix_fmt == AV_PIX_FMT_YUV440P10 ? 10 : 12;
377 378 379 380 381 382
            enccfg->g_profile = 3;
            *img_fmt = VPX_IMG_FMT_I44016;
            *flags |= VPX_CODEC_USE_HIGHBITDEPTH;
            return 0;
        }
        break;
383 384 385
    case AV_PIX_FMT_GBRP10:
    case AV_PIX_FMT_GBRP12:
        ctx->vpx_cs = VPX_CS_SRGB;
386
#endif
387 388
    case AV_PIX_FMT_YUV444P10:
    case AV_PIX_FMT_YUV444P12:
389 390
        if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) {
            enccfg->g_bit_depth = enccfg->g_input_bit_depth =
391 392
                avctx->pix_fmt == AV_PIX_FMT_YUV444P10 ||
                avctx->pix_fmt == AV_PIX_FMT_GBRP10 ? 10 : 12;
393 394 395 396 397 398 399 400 401 402 403 404 405
            enccfg->g_profile = 3;
            *img_fmt = VPX_IMG_FMT_I44416;
            *flags |= VPX_CODEC_USE_HIGHBITDEPTH;
            return 0;
        }
        break;
#endif
    default:
        break;
    }
    av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n");
    return AVERROR_INVALIDDATA;
}
406 407 408 409 410

#if VPX_ENCODER_ABI_VERSION > 8
static void set_colorspace(AVCodecContext *avctx)
{
    enum vpx_color_space vpx_cs;
411
    VPxContext *ctx = avctx->priv_data;
412

413 414 415
    if (ctx->vpx_cs) {
        vpx_cs = ctx->vpx_cs;
    } else {
416 417 418 419 420 421 422 423 424 425 426 427 428 429
        switch (avctx->colorspace) {
        case AVCOL_SPC_RGB:         vpx_cs = VPX_CS_SRGB;      break;
        case AVCOL_SPC_BT709:       vpx_cs = VPX_CS_BT_709;    break;
        case AVCOL_SPC_UNSPECIFIED: vpx_cs = VPX_CS_UNKNOWN;   break;
        case AVCOL_SPC_RESERVED:    vpx_cs = VPX_CS_RESERVED;  break;
        case AVCOL_SPC_BT470BG:     vpx_cs = VPX_CS_BT_601;    break;
        case AVCOL_SPC_SMPTE170M:   vpx_cs = VPX_CS_SMPTE_170; break;
        case AVCOL_SPC_SMPTE240M:   vpx_cs = VPX_CS_SMPTE_240; break;
        case AVCOL_SPC_BT2020_NCL:  vpx_cs = VPX_CS_BT_2020;   break;
        default:
            av_log(avctx, AV_LOG_WARNING, "Unsupported colorspace (%d)\n",
                   avctx->colorspace);
            return;
        }
430
    }
431 432 433
    codecctl_int(avctx, VP9E_SET_COLOR_SPACE, vpx_cs);
}
#endif
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451

#if VPX_ENCODER_ABI_VERSION >= 11
static void set_color_range(AVCodecContext *avctx)
{
    enum vpx_color_range vpx_cr;
    switch (avctx->color_range) {
    case AVCOL_RANGE_UNSPECIFIED:
    case AVCOL_RANGE_MPEG:       vpx_cr = VPX_CR_STUDIO_RANGE; break;
    case AVCOL_RANGE_JPEG:       vpx_cr = VPX_CR_FULL_RANGE;   break;
    default:
        av_log(avctx, AV_LOG_WARNING, "Unsupported color range (%d)\n",
               avctx->color_range);
        return;
    }

    codecctl_int(avctx, VP9E_SET_COLOR_RANGE, vpx_cr);
}
#endif
452 453
#endif

Luca Barbato's avatar
Luca Barbato committed
454 455
static av_cold int vpx_init(AVCodecContext *avctx,
                            const struct vpx_codec_iface *iface)
James Zern's avatar
James Zern committed
456
{
457
    VPxContext *ctx = avctx->priv_data;
458
    struct vpx_codec_enc_cfg enccfg = { 0 };
459
    struct vpx_codec_enc_cfg enccfg_alpha;
460
    vpx_codec_flags_t flags = (avctx->flags & AV_CODEC_FLAG_PSNR) ? VPX_CODEC_USE_PSNR : 0;
461
    AVCPBProperties *cpb_props;
James Zern's avatar
James Zern committed
462
    int res;
463 464 465 466
    vpx_img_fmt_t img_fmt = VPX_IMG_FMT_I420;
#if CONFIG_LIBVPX_VP9_ENCODER
    vpx_codec_caps_t codec_caps = vpx_codec_get_caps(iface);
#endif
James Zern's avatar
James Zern committed
467 468 469 470

    av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str());
    av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config());

471 472 473
    if (avctx->pix_fmt == AV_PIX_FMT_YUVA420P)
        ctx->is_alpha = 1;

James Zern's avatar
James Zern committed
474 475 476 477 478
    if ((res = vpx_codec_enc_config_default(iface, &enccfg, 0)) != VPX_CODEC_OK) {
        av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n",
               vpx_codec_err_to_string(res));
        return AVERROR(EINVAL);
    }
479

480 481 482 483 484 485 486
#if CONFIG_LIBVPX_VP9_ENCODER
    if (avctx->codec_id == AV_CODEC_ID_VP9) {
        if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt))
            return AVERROR(EINVAL);
    }
#endif

487 488 489 490 491 492
    if(!avctx->bit_rate)
        if(avctx->rc_max_rate || avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) {
            av_log( avctx, AV_LOG_ERROR, "Rate control parameters set without a bitrate\n");
            return AVERROR(EINVAL);
        }

James Zern's avatar
James Zern committed
493 494 495 496 497 498 499
    dump_enc_cfg(avctx, &enccfg);

    enccfg.g_w            = avctx->width;
    enccfg.g_h            = avctx->height;
    enccfg.g_timebase.num = avctx->time_base.num;
    enccfg.g_timebase.den = avctx->time_base.den;
    enccfg.g_threads      = avctx->thread_count;
500
    enccfg.g_lag_in_frames= ctx->lag_in_frames;
James Zern's avatar
James Zern committed
501

502
    if (avctx->flags & AV_CODEC_FLAG_PASS1)
James Zern's avatar
James Zern committed
503
        enccfg.g_pass = VPX_RC_FIRST_PASS;
504
    else if (avctx->flags & AV_CODEC_FLAG_PASS2)
James Zern's avatar
James Zern committed
505 506 507 508 509
        enccfg.g_pass = VPX_RC_LAST_PASS;
    else
        enccfg.g_pass = VPX_RC_ONE_PASS;

    if (avctx->rc_min_rate == avctx->rc_max_rate &&
510
        avctx->rc_min_rate == avctx->bit_rate && avctx->bit_rate) {
James Zern's avatar
James Zern committed
511
        enccfg.rc_end_usage = VPX_CBR;
512
    } else if (ctx->crf >= 0) {
513
        enccfg.rc_end_usage = VPX_CQ;
514 515 516 517 518
#if CONFIG_LIBVPX_VP9_ENCODER
        if (!avctx->bit_rate && avctx->codec_id == AV_CODEC_ID_VP9)
            enccfg.rc_end_usage = VPX_Q;
#endif
    }
519 520 521

    if (avctx->bit_rate) {
        enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000,
522 523 524 525
                                                  AV_ROUND_NEAR_INF);
#if CONFIG_LIBVPX_VP9_ENCODER
    } else if (enccfg.rc_end_usage == VPX_Q) {
#endif
526 527 528 529 530 531 532 533 534 535 536
    } else {
        if (enccfg.rc_end_usage == VPX_CQ) {
            enccfg.rc_target_bitrate = 1000000;
        } else {
            avctx->bit_rate = enccfg.rc_target_bitrate * 1000;
            av_log(avctx, AV_LOG_WARNING,
                   "Neither bitrate nor constrained quality specified, using default bitrate of %dkbit/sec\n",
                   enccfg.rc_target_bitrate);
        }
    }

537 538 539 540 541 542 543 544 545
    if (avctx->codec_id == AV_CODEC_ID_VP9 && ctx->lossless == 1) {
        enccfg.rc_min_quantizer =
        enccfg.rc_max_quantizer = 0;
    } else {
        if (avctx->qmin >= 0)
            enccfg.rc_min_quantizer = avctx->qmin;
        if (avctx->qmax >= 0)
            enccfg.rc_max_quantizer = avctx->qmax;
    }
546

547 548 549 550
    if (enccfg.rc_end_usage == VPX_CQ
#if CONFIG_LIBVPX_VP9_ENCODER
        || enccfg.rc_end_usage == VPX_Q
#endif
551
       ) {
552
        if (ctx->crf < enccfg.rc_min_quantizer || ctx->crf > enccfg.rc_max_quantizer) {
553 554 555 556
            av_log(avctx, AV_LOG_ERROR,
                   "CQ level %d must be between minimum and maximum quantizer value (%d-%d)\n",
                   ctx->crf, enccfg.rc_min_quantizer, enccfg.rc_max_quantizer);
            return AVERROR(EINVAL);
557 558 559
        }
    }

560 561 562 563 564 565 566
#if FF_API_PRIVATE_OPT
FF_DISABLE_DEPRECATION_WARNINGS
    if (avctx->frame_skip_threshold)
        ctx->drop_threshold = avctx->frame_skip_threshold;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
    enccfg.rc_dropframe_thresh = ctx->drop_threshold;
James Zern's avatar
James Zern committed
567

568
    //0-100 (0 => CBR, 100 => VBR)
569
    enccfg.rc_2pass_vbr_bias_pct           = lrint(avctx->qcompress * 100);
570
    if (avctx->bit_rate)
571
        enccfg.rc_2pass_vbr_minsection_pct =
572
            avctx->rc_min_rate * 100LL / avctx->bit_rate;
573 574
    if (avctx->rc_max_rate)
        enccfg.rc_2pass_vbr_maxsection_pct =
575
            avctx->rc_max_rate * 100LL / avctx->bit_rate;
576

577 578
    if (avctx->rc_buffer_size)
        enccfg.rc_buf_sz         =
579
            avctx->rc_buffer_size * 1000LL / avctx->bit_rate;
580 581
    if (avctx->rc_initial_buffer_occupancy)
        enccfg.rc_buf_initial_sz =
582
            avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate;
583
    enccfg.rc_buf_optimal_sz     = enccfg.rc_buf_sz * 5 / 6;
584 585 586 587 588
#if FF_API_MPV_OPT
    FF_DISABLE_DEPRECATION_WARNINGS
    if (avctx->rc_buffer_aggressivity != 1.0) {
        av_log(avctx, AV_LOG_WARNING, "The rc_buffer_aggressivity option is "
               "deprecated, use the undershoot-pct private option instead.\n");
589
        enccfg.rc_undershoot_pct = lrint(avctx->rc_buffer_aggressivity * 100);
590 591 592 593 594
    }
    FF_ENABLE_DEPRECATION_WARNINGS
#endif
    if (ctx->rc_undershoot_pct >= 0)
        enccfg.rc_undershoot_pct = ctx->rc_undershoot_pct;
595 596
    if (ctx->rc_overshoot_pct >= 0)
        enccfg.rc_overshoot_pct = ctx->rc_overshoot_pct;
597

598
    //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO
599
    if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
James Zern's avatar
James Zern committed
600
        enccfg.kf_min_dist = avctx->keyint_min;
601 602
    if (avctx->gop_size >= 0)
        enccfg.kf_max_dist = avctx->gop_size;
James Zern's avatar
James Zern committed
603 604 605 606

    if (enccfg.g_pass == VPX_RC_FIRST_PASS)
        enccfg.g_lag_in_frames = 0;
    else if (enccfg.g_pass == VPX_RC_LAST_PASS) {
607
        int decode_size, ret;
James Zern's avatar
James Zern committed
608 609 610 611 612 613 614

        if (!avctx->stats_in) {
            av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n");
            return AVERROR_INVALIDDATA;
        }

        ctx->twopass_stats.sz  = strlen(avctx->stats_in) * 3 / 4;
615 616
        ret = av_reallocp(&ctx->twopass_stats.buf, ctx->twopass_stats.sz);
        if (ret < 0) {
James Zern's avatar
James Zern committed
617
            av_log(avctx, AV_LOG_ERROR,
618
                   "Stat buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n",
James Zern's avatar
James Zern committed
619
                   ctx->twopass_stats.sz);
620
            ctx->twopass_stats.sz = 0;
621
            return ret;
James Zern's avatar
James Zern committed
622 623 624 625 626 627 628 629 630 631 632 633
        }
        decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in,
                                       ctx->twopass_stats.sz);
        if (decode_size < 0) {
            av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n");
            return AVERROR_INVALIDDATA;
        }

        ctx->twopass_stats.sz      = decode_size;
        enccfg.rc_twopass_stats_in = ctx->twopass_stats;
    }

634 635 636
    /* 0-3: For non-zero values the encoder increasingly optimizes for reduced
       complexity playback on low powered devices at the expense of encode
       quality. */
637 638
    if (avctx->profile != FF_PROFILE_UNKNOWN)
        enccfg.g_profile = avctx->profile;
James Zern's avatar
James Zern committed
639

640
    enccfg.g_error_resilient = ctx->error_resilient || ctx->flags & VP8F_ERROR_RESILIENT;
641

James Zern's avatar
James Zern committed
642 643
    dump_enc_cfg(avctx, &enccfg);
    /* Construct Encoder Context */
644
    res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, flags);
James Zern's avatar
James Zern committed
645 646 647 648 649
    if (res != VPX_CODEC_OK) {
        log_encoder_error(avctx, "Failed to initialize encoder");
        return AVERROR(EINVAL);
    }

650 651 652 653 654 655 656 657 658
    if (ctx->is_alpha) {
        enccfg_alpha = enccfg;
        res = vpx_codec_enc_init(&ctx->encoder_alpha, iface, &enccfg_alpha, flags);
        if (res != VPX_CODEC_OK) {
            log_encoder_error(avctx, "Failed to initialize alpha encoder");
            return AVERROR(EINVAL);
        }
    }

James Zern's avatar
James Zern committed
659 660
    //codec control failures are currently treated only as warnings
    av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n");
661
    codecctl_int(avctx, VP8E_SET_CPUUSED,          ctx->cpu_used);
662 663
    if (ctx->flags & VP8F_AUTO_ALT_REF)
        ctx->auto_alt_ref = 1;
664
    if (ctx->auto_alt_ref >= 0)
665 666
        codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF,
                     avctx->codec_id == AV_CODEC_ID_VP8 ? !!ctx->auto_alt_ref : ctx->auto_alt_ref);
667 668 669 670 671 672
    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);
673 674
    if (ctx->tune >= 0)
        codecctl_int(avctx, VP8E_SET_TUNING,           ctx->tune);
675

676 677 678 679 680
    if (ctx->auto_alt_ref && ctx->is_alpha && avctx->codec_id == AV_CODEC_ID_VP8) {
        av_log(avctx, AV_LOG_ERROR, "Transparency encoding with auto_alt_ref does not work\n");
        return AVERROR(EINVAL);
    }

681
    if (CONFIG_LIBVPX_VP8_ENCODER && avctx->codec_id == AV_CODEC_ID_VP8) {
682 683 684 685 686 687 688
#if FF_API_PRIVATE_OPT
FF_DISABLE_DEPRECATION_WARNINGS
        if (avctx->noise_reduction)
            ctx->noise_sensitivity = avctx->noise_reduction;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
        codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, ctx->noise_sensitivity);
689
        codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS,  av_log2(avctx->slices));
690
    }
691 692 693 694 695 696 697 698 699 700
#if FF_API_MPV_OPT
    FF_DISABLE_DEPRECATION_WARNINGS
    if (avctx->mb_threshold) {
        av_log(avctx, AV_LOG_WARNING, "The mb_threshold option is deprecated, "
               "use the static-thresh private option instead.\n");
        ctx->static_thresh = avctx->mb_threshold;
    }
    FF_ENABLE_DEPRECATION_WARNINGS
#endif
    codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD,  ctx->static_thresh);
701 702
    if (ctx->crf >= 0)
        codecctl_int(avctx, VP8E_SET_CQ_LEVEL,          ctx->crf);
703 704
    if (ctx->max_intra_rate >= 0)
        codecctl_int(avctx, VP8E_SET_MAX_INTRA_BITRATE_PCT, ctx->max_intra_rate);
705

James Zern's avatar
James Zern committed
706 707 708 709 710 711 712 713 714 715
#if CONFIG_LIBVPX_VP9_ENCODER
    if (avctx->codec_id == AV_CODEC_ID_VP9) {
        if (ctx->lossless >= 0)
            codecctl_int(avctx, VP9E_SET_LOSSLESS, ctx->lossless);
        if (ctx->tile_columns >= 0)
            codecctl_int(avctx, VP9E_SET_TILE_COLUMNS, ctx->tile_columns);
        if (ctx->tile_rows >= 0)
            codecctl_int(avctx, VP9E_SET_TILE_ROWS, ctx->tile_rows);
        if (ctx->frame_parallel >= 0)
            codecctl_int(avctx, VP9E_SET_FRAME_PARALLEL_DECODING, ctx->frame_parallel);
716 717
        if (ctx->aq_mode >= 0)
            codecctl_int(avctx, VP9E_SET_AQ_MODE, ctx->aq_mode);
718 719
#if VPX_ENCODER_ABI_VERSION > 8
        set_colorspace(avctx);
720 721 722
#endif
#if VPX_ENCODER_ABI_VERSION >= 11
        set_color_range(avctx);
723 724 725
#endif
#if VPX_ENCODER_ABI_VERSION >= 12
        codecctl_int(avctx, VP9E_SET_TARGET_LEVEL, ctx->level < 0 ? 255 : lrint(ctx->level * 10));
726 727 728 729
#endif
#ifdef VPX_CTRL_VP9E_SET_ROW_MT
        if (ctx->row_mt >= 0)
            codecctl_int(avctx, VP9E_SET_ROW_MT, ctx->row_mt);
730
#endif
James Zern's avatar
James Zern committed
731 732 733
    }
#endif

734
    av_log(avctx, AV_LOG_DEBUG, "Using deadline: %d\n", ctx->deadline);
James Zern's avatar
James Zern committed
735 736

    //provide dummy value to initialize wrapper, values will be updated each _encode()
737
    vpx_img_wrap(&ctx->rawimg, img_fmt, avctx->width, avctx->height, 1,
James Zern's avatar
James Zern committed
738
                 (unsigned char*)1);
739 740 741 742
#if CONFIG_LIBVPX_VP9_ENCODER && defined(VPX_IMG_FMT_HIGHBITDEPTH)
    if (avctx->codec_id == AV_CODEC_ID_VP9 && (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH))
        ctx->rawimg.bit_depth = enccfg.g_bit_depth;
#endif
James Zern's avatar
James Zern committed
743

744 745 746 747
    if (ctx->is_alpha)
        vpx_img_wrap(&ctx->rawimg_alpha, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1,
                     (unsigned char*)1);

748 749 750 751 752 753 754 755 756 757 758 759
    cpb_props = ff_add_cpb_side_data(avctx);
    if (!cpb_props)
        return AVERROR(ENOMEM);

    if (enccfg.rc_end_usage == VPX_CBR ||
        enccfg.g_pass != VPX_RC_ONE_PASS) {
        cpb_props->max_bitrate = avctx->rc_max_rate;
        cpb_props->min_bitrate = avctx->rc_min_rate;
        cpb_props->avg_bitrate = avctx->bit_rate;
    }
    cpb_props->buffer_size = avctx->rc_buffer_size;

James Zern's avatar
James Zern committed
760 761 762 763
    return 0;
}

static inline void cx_pktcpy(struct FrameListData *dst,
764
                             const struct vpx_codec_cx_pkt *src,
765
                             const struct vpx_codec_cx_pkt *src_alpha,
766
                             VPxContext *ctx)
James Zern's avatar
James Zern committed
767 768 769 770 771 772
{
    dst->pts      = src->data.frame.pts;
    dst->duration = src->data.frame.duration;
    dst->flags    = src->data.frame.flags;
    dst->sz       = src->data.frame.sz;
    dst->buf      = src->data.frame.buf;
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
    dst->have_sse = 0;
    /* For alt-ref frame, don't store PSNR or increment frame_number */
    if (!(dst->flags & VPX_FRAME_IS_INVISIBLE)) {
        dst->frame_number = ++ctx->frame_number;
        dst->have_sse = ctx->have_sse;
        if (ctx->have_sse) {
            /* associate last-seen SSE to the frame. */
            /* Transfers ownership from ctx to dst. */
            /* WARNING! This makes the assumption that PSNR_PKT comes
               just before the frame it refers to! */
            memcpy(dst->sse, ctx->sse, sizeof(dst->sse));
            ctx->have_sse = 0;
        }
    } else {
        dst->frame_number = -1;   /* sanity marker */
    }
789 790 791
    if (src_alpha) {
        dst->buf_alpha = src_alpha->data.frame.buf;
        dst->sz_alpha = src_alpha->data.frame.sz;
792
    } else {
793 794 795
        dst->buf_alpha = NULL;
        dst->sz_alpha = 0;
    }
James Zern's avatar
James Zern committed
796 797 798
}

/**
799
 * Store coded frame information in format suitable for return from encode2().
James Zern's avatar
James Zern committed
800
 *
801 802 803
 * Write information from @a cx_frame to @a pkt
 * @return packet data size on success
 * @return a negative AVERROR on error
James Zern's avatar
James Zern committed
804 805
 */
static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
806
                      AVPacket *pkt)
James Zern's avatar
James Zern committed
807
{
808
    int ret = ff_alloc_packet2(avctx, pkt, cx_frame->sz, 0);
809
    uint8_t *side_data;
810
    if (ret >= 0) {
811
        int pict_type;
812
        memcpy(pkt->data, cx_frame->buf, pkt->size);
813
        pkt->pts = pkt->dts = cx_frame->pts;
814 815
#if FF_API_CODED_FRAME
FF_DISABLE_DEPRECATION_WARNINGS
816 817
        avctx->coded_frame->pts       = cx_frame->pts;
        avctx->coded_frame->key_frame = !!(cx_frame->flags & VPX_FRAME_IS_KEY);
818 819
FF_ENABLE_DEPRECATION_WARNINGS
#endif
James Zern's avatar
James Zern committed
820

821
        if (!!(cx_frame->flags & VPX_FRAME_IS_KEY)) {
822
            pict_type = AV_PICTURE_TYPE_I;
823 824
#if FF_API_CODED_FRAME
FF_DISABLE_DEPRECATION_WARNINGS
825
            avctx->coded_frame->pict_type = pict_type;
826 827
FF_ENABLE_DEPRECATION_WARNINGS
#endif
828 829
            pkt->flags |= AV_PKT_FLAG_KEY;
        } else {
830
            pict_type = AV_PICTURE_TYPE_P;
831 832
#if FF_API_CODED_FRAME
FF_DISABLE_DEPRECATION_WARNINGS
833
            avctx->coded_frame->pict_type = pict_type;
834 835
FF_ENABLE_DEPRECATION_WARNINGS
#endif
836
        }
837

838 839 840
        ff_side_data_set_encoder_stats(pkt, 0, cx_frame->sse + 1,
                                       cx_frame->have_sse ? 3 : 0, pict_type);

841 842 843
        if (cx_frame->have_sse) {
            int i;
            /* Beware of the Y/U/V/all order! */
844 845
#if FF_API_CODED_FRAME
FF_DISABLE_DEPRECATION_WARNINGS
846 847 848 849
            avctx->coded_frame->error[0] = cx_frame->sse[1];
            avctx->coded_frame->error[1] = cx_frame->sse[2];
            avctx->coded_frame->error[2] = cx_frame->sse[3];
            avctx->coded_frame->error[3] = 0;    // alpha
850 851 852 853
FF_ENABLE_DEPRECATION_WARNINGS
#endif
            for (i = 0; i < 3; ++i) {
                avctx->error[i] += cx_frame->sse[i + 1];
854 855 856
            }
            cx_frame->have_sse = 0;
        }
857 858 859 860
        if (cx_frame->sz_alpha > 0) {
            side_data = av_packet_new_side_data(pkt,
                                                AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
                                                cx_frame->sz_alpha + 8);
861
            if(!side_data) {
862
                av_packet_unref(pkt);
863 864 865 866 867 868
                av_free(pkt);
                return AVERROR(ENOMEM);
            }
            AV_WB64(side_data, 1);
            memcpy(side_data + 8, cx_frame->buf_alpha, cx_frame->sz_alpha);
        }
James Zern's avatar
James Zern committed
869
    } else {
870
        return ret;
James Zern's avatar
James Zern committed
871
    }
872
    return pkt->size;
James Zern's avatar
James Zern committed
873 874 875 876 877 878 879 880 881 882
}

/**
 * Queue multiple output frames from the encoder, returning the front-most.
 * In cases where vpx_codec_get_cx_data() returns more than 1 frame append
 * the frame queue. Return the head frame if available.
 * @return Stored frame size
 * @return AVERROR(EINVAL) on output size error
 * @return AVERROR(ENOMEM) on coded frame queue data allocation error
 */
883
static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out)
James Zern's avatar
James Zern committed
884
{
885
    VPxContext *ctx = avctx->priv_data;
James Zern's avatar
James Zern committed
886
    const struct vpx_codec_cx_pkt *pkt;
887
    const struct vpx_codec_cx_pkt *pkt_alpha = NULL;
James Zern's avatar
James Zern committed
888
    const void *iter = NULL;
889
    const void *iter_alpha = NULL;
James Zern's avatar
James Zern committed
890 891 892 893 894
    int size = 0;

    if (ctx->coded_frame_list) {
        struct FrameListData *cx_frame = ctx->coded_frame_list;
        /* return the leading frame if we've already begun queueing */
895
        size = storeframe(avctx, cx_frame, pkt_out);
James Zern's avatar
James Zern committed
896
        if (size < 0)
897
            return size;
James Zern's avatar
James Zern committed
898 899 900 901 902 903
        ctx->coded_frame_list = cx_frame->next;
        free_coded_frame(cx_frame);
    }

    /* consume all available output from the encoder before returning. buffers
       are only good through the next vpx_codec call */
904
    while ((pkt = vpx_codec_get_cx_data(&ctx->encoder, &iter)) &&
905 906
           (!ctx->is_alpha ||
            (ctx->is_alpha && (pkt_alpha = vpx_codec_get_cx_data(&ctx->encoder_alpha, &iter_alpha))))) {
James Zern's avatar
James Zern committed
907 908 909 910 911 912 913
        switch (pkt->kind) {
        case VPX_CODEC_CX_FRAME_PKT:
            if (!size) {
                struct FrameListData cx_frame;

                /* avoid storing the frame when the list is empty and we haven't yet
                   provided a frame for output */
914
                av_assert0(!ctx->coded_frame_list);
915
                cx_pktcpy(&cx_frame, pkt, pkt_alpha, ctx);
916
                size = storeframe(avctx, &cx_frame, pkt_out);
James Zern's avatar
James Zern committed
917
                if (size < 0)
918
                    return size;
James Zern's avatar
James Zern committed
919 920 921 922 923 924 925 926 927
            } else {
                struct FrameListData *cx_frame =
                    av_malloc(sizeof(struct FrameListData));

                if (!cx_frame) {
                    av_log(avctx, AV_LOG_ERROR,
                           "Frame queue element alloc failed\n");
                    return AVERROR(ENOMEM);
                }
928
                cx_pktcpy(cx_frame, pkt, pkt_alpha, ctx);
James Zern's avatar
James Zern committed
929 930 931 932
                cx_frame->buf = av_malloc(cx_frame->sz);

                if (!cx_frame->buf) {
                    av_log(avctx, AV_LOG_ERROR,
933
                           "Data buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n",
James Zern's avatar
James Zern committed
934
                           cx_frame->sz);
935
                    av_freep(&cx_frame);
James Zern's avatar
James Zern committed
936 937 938
                    return AVERROR(ENOMEM);
                }
                memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz);
939 940 941 942
                if (ctx->is_alpha) {
                    cx_frame->buf_alpha = av_malloc(cx_frame->sz_alpha);
                    if (!cx_frame->buf_alpha) {
                        av_log(avctx, AV_LOG_ERROR,
943
                               "Data buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n",
944 945 946 947 948 949
                               cx_frame->sz_alpha);
                        av_free(cx_frame);
                        return AVERROR(ENOMEM);
                    }
                    memcpy(cx_frame->buf_alpha, pkt_alpha->data.frame.buf, pkt_alpha->data.frame.sz);
                }
James Zern's avatar
James Zern committed
950 951 952 953 954
                coded_frame_add(&ctx->coded_frame_list, cx_frame);
            }
            break;
        case VPX_CODEC_STATS_PKT: {
            struct vpx_fixed_buf *stats = &ctx->twopass_stats;
955 956 957 958 959
            int err;
            if ((err = av_reallocp(&stats->buf,
                                   stats->sz +
                                   pkt->data.twopass_stats.sz)) < 0) {
                stats->sz = 0;
James Zern's avatar
James Zern committed
960
                av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n");
961
                return err;
James Zern's avatar
James Zern committed
962 963 964 965 966 967
            }
            memcpy((uint8_t*)stats->buf + stats->sz,
                   pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz);
            stats->sz += pkt->data.twopass_stats.sz;
            break;
        }
968 969 970 971 972 973 974 975
        case VPX_CODEC_PSNR_PKT:
            av_assert0(!ctx->have_sse);
            ctx->sse[0] = pkt->data.psnr.sse[0];
            ctx->sse[1] = pkt->data.psnr.sse[1];
            ctx->sse[2] = pkt->data.psnr.sse[2];
            ctx->sse[3] = pkt->data.psnr.sse[3];
            ctx->have_sse = 1;
            break;
James Zern's avatar
James Zern committed
976 977 978 979 980 981 982 983 984
        case VPX_CODEC_CUSTOM_PKT:
            //ignore unsupported/unrecognized packet types
            break;
        }
    }

    return size;
}

985
static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt,
986
                      const AVFrame *frame, int *got_packet)
James Zern's avatar
James Zern committed
987
{
988
    VPxContext *ctx = avctx->priv_data;
James Zern's avatar
James Zern committed
989
    struct vpx_image *rawimg = NULL;
990
    struct vpx_image *rawimg_alpha = NULL;
James Zern's avatar
James Zern committed
991 992
    int64_t timestamp = 0;
    int res, coded_size;
993
    vpx_enc_frame_flags_t flags = 0;
James Zern's avatar
James Zern committed
994 995 996 997 998 999 1000 1001 1002

    if (frame) {
        rawimg                      = &ctx->rawimg;
        rawimg->planes[VPX_PLANE_Y] = frame->data[0];
        rawimg->planes[VPX_PLANE_U] = frame->data[1];
        rawimg->planes[VPX_PLANE_V] = frame->data[2];
        rawimg->stride[VPX_PLANE_Y] = frame->linesize[0];
        rawimg->stride[VPX_PLANE_U] = frame->linesize[1];
        rawimg->stride[VPX_PLANE_V] = frame->linesize[2];
1003 1004 1005 1006 1007
        if (ctx->is_alpha) {
            uint8_t *u_plane, *v_plane;
            rawimg_alpha = &ctx->rawimg_alpha;
            rawimg_alpha->planes[VPX_PLANE_Y] = frame->data[3];
            u_plane = av_malloc(frame->linesize[1] * frame->height);
1008 1009 1010 1011 1012 1013
            v_plane = av_malloc(frame->linesize[2] * frame->height);
            if (!u_plane || !v_plane) {
                av_free(u_plane);
                av_free(v_plane);
                return AVERROR(ENOMEM);
            }
1014 1015 1016 1017
            memset(u_plane, 0x80, frame->linesize[1] * frame->height);
            rawimg_alpha->planes[VPX_PLANE_U] = u_plane;
            memset(v_plane, 0x80, frame->linesize[2] * frame->height);
            rawimg_alpha->planes[VPX_PLANE_V] = v_plane;
1018 1019 1020
            rawimg_alpha->stride[VPX_PLANE_Y] = frame->linesize[0];
            rawimg_alpha->stride[VPX_PLANE_U] = frame->linesize[1];
            rawimg_alpha->stride[VPX_PLANE_V] = frame->linesize[2];
1021
        }
James Zern's avatar
James Zern committed
1022
        timestamp                   = frame->pts;
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
#if VPX_IMAGE_ABI_VERSION >= 4
        switch (frame->color_range) {
        case AVCOL_RANGE_MPEG:
            rawimg->range = VPX_CR_STUDIO_RANGE;
            break;
        case AVCOL_RANGE_JPEG:
            rawimg->range = VPX_CR_FULL_RANGE;
            break;
        }
#endif
1033 1034
        if (frame->pict_type == AV_PICTURE_TYPE_I)
            flags |= VPX_EFLAG_FORCE_KF;
James Zern's avatar
James Zern committed
1035 1036 1037
    }

    res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp,
1038
                           avctx->ticks_per_frame, flags, ctx->deadline);
James Zern's avatar
James Zern committed
1039 1040 1041 1042
    if (res != VPX_CODEC_OK) {
        log_encoder_error(avctx, "Error encoding frame");
        return AVERROR_INVALIDDATA;
    }
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052

    if (ctx->is_alpha) {
        res = vpx_codec_encode(&ctx->encoder_alpha, rawimg_alpha, timestamp,
                               avctx->ticks_per_frame, flags, ctx->deadline);
        if (res != VPX_CODEC_OK) {
            log_encoder_error(avctx, "Error encoding alpha frame");
            return AVERROR_INVALIDDATA;
        }
    }

1053
    coded_size = queue_frames(avctx, pkt);
James Zern's avatar
James Zern committed
1054

1055
    if (!frame && avctx->flags & AV_CODEC_FLAG_PASS1) {
1056
        unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz);
James Zern's avatar
James Zern committed
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066

        avctx->stats_out = av_malloc(b64_size);
        if (!avctx->stats_out) {
            av_log(avctx, AV_LOG_ERROR, "Stat buffer alloc (%d bytes) failed\n",
                   b64_size);
            return AVERROR(ENOMEM);
        }
        av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf,
                         ctx->twopass_stats.sz);
    }
1067

1068
    if (rawimg_alpha) {
1069 1070
        av_freep(&rawimg_alpha->planes[VPX_PLANE_U]);
        av_freep(&rawimg_alpha->planes[VPX_PLANE_V]);
1071 1072
    }

1073 1074
    *got_packet = !!coded_size;
    return 0;
James Zern's avatar
James Zern committed
1075 1076
}

1077
#define OFFSET(x) offsetof(VPxContext, x)
1078
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1079 1080 1081 1082

#ifndef VPX_ERROR_RESILIENT_DEFAULT
#define VPX_ERROR_RESILIENT_DEFAULT 1
#define VPX_ERROR_RESILIENT_PARTITIONS 2
1083
#endif
1084 1085 1086

#define COMMON_OPTIONS \
    { "auto-alt-ref",    "Enable use of alternate reference " \
1087
                         "frames (2-pass only)",                   OFFSET(auto_alt_ref),    AV_OPT_TYPE_INT, {.i64 = -1},      -1,      2,       VE}, \
1088 1089 1090 1091 1092 1093 1094 1095
    { "lag-in-frames",   "Number of frames to look ahead for " \
                         "alternate reference frame selection",    OFFSET(lag_in_frames),   AV_OPT_TYPE_INT, {.i64 = -1},      -1,      INT_MAX, VE}, \
    { "arnr-maxframes",  "altref noise reduction max frame count", OFFSET(arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = -1},      -1,      INT_MAX, VE}, \
    { "arnr-strength",   "altref noise reduction filter strength", OFFSET(arnr_strength),   AV_OPT_TYPE_INT, {.i64 = -1},      -1,      INT_MAX, VE}, \
    { "arnr-type",       "altref noise reduction filter type",     OFFSET(arnr_type),       AV_OPT_TYPE_INT, {.i64 = -1},      -1,      INT_MAX, VE, "arnr_type"}, \
    { "backward",        NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE, "arnr_type" }, \
    { "forward",         NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "arnr_type" }, \
    { "centered",        NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE, "arnr_type" }, \
1096 1097 1098
    { "tune",            "Tune the encoding to a specific scenario", OFFSET(tune),          AV_OPT_TYPE_INT, {.i64 = -1},      -1,      INT_MAX, VE, "tune"}, \
    { "psnr",            NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VP8_TUNE_PSNR}, 0, 0, VE, "tune"}, \
    { "ssim",            NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VP8_TUNE_SSIM}, 0, 0, VE, "tune"}, \
1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
    { "deadline",        "Time to spend encoding, in microseconds.", OFFSET(deadline),      AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"}, \
    { "best",            NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_BEST_QUALITY}, 0, 0, VE, "quality"}, \
    { "good",            NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_GOOD_QUALITY}, 0, 0, VE, "quality"}, \
    { "realtime",        NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_REALTIME},     0, 0, VE, "quality"}, \
    { "error-resilient", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"}, \
    { "max-intra-rate",  "Maximum I-frame bitrate (pct) 0=unlimited",  OFFSET(max_intra_rate),  AV_OPT_TYPE_INT,  {.i64 = -1}, -1,      INT_MAX, VE}, \
    { "default",         "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = 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, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"}, \
1110
    { "crf",              "Select the quality for constant quality mode", offsetof(VPxContext, crf), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, VE }, \
1111
    { "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 }, \
1112
    { "drop-threshold",   "Frame drop threshold", offsetof(VPxContext, drop_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, VE }, \
1113
    { "noise-sensitivity", "Noise sensitivity", OFFSET(noise_sensitivity), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 4, VE}, \
1114
    { "undershoot-pct",  "Datarate undershoot (min) target (%)", OFFSET(rc_undershoot_pct), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 100, VE }, \
1115
    { "overshoot-pct",   "Datarate overshoot (max) target (%)", OFFSET(rc_overshoot_pct), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE }, \
1116 1117

#define LEGACY_OPTIONS \
1118 1119 1120
    {"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"}, \
1121 1122
    {"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"}, \
1123 1124 1125 1126
    {"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}, \
1127 1128 1129 1130

#if CONFIG_LIBVPX_VP8_ENCODER
static const AVOption vp8_options[] = {
    COMMON_OPTIONS
1131
    { "cpu-used",        "Quality/Speed ratio modifier",                OFFSET(cpu_used),        AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE},
1132
    LEGACY_OPTIONS
1133 1134
    { NULL }
};
1135 1136 1137 1138 1139
#endif

#if CONFIG_LIBVPX_VP9_ENCODER
static const AVOption vp9_options[] = {
    COMMON_OPTIONS
1140
    { "cpu-used",        "Quality/Speed ratio modifier",                OFFSET(cpu_used),        AV_OPT_TYPE_INT, {.i64 = 1},  -8, 8, VE},
James Zern's avatar
James Zern committed
1141 1142 1143
    { "lossless",        "Lossless mode",                               OFFSET(lossless),        AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE},
    { "tile-columns",    "Number of tile columns to use, log2",         OFFSET(tile_columns),    AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE},
    { "tile-rows",       "Number of tile rows to use, log2",            OFFSET(tile_rows),       AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE},
1144
    { "frame-parallel",  "Enable frame parallel decodability features", OFFSET(frame_parallel),  AV_OPT_TYPE_BOOL,{.i64 = -1}, -1, 1, VE},
1145 1146 1147
#if VPX_ENCODER_ABI_VERSION >= 12
    { "aq-mode",         "adaptive quantization mode",                  OFFSET(aq_mode),         AV_OPT_TYPE_INT, {.i64 = -1}, -1, 4, VE, "aq_mode"},
#else
1148
    { "aq-mode",         "adaptive quantization mode",                  OFFSET(aq_mode),         AV_OPT_TYPE_INT, {.i64 = -1}, -1, 3, VE, "aq_mode"},
1149
#endif
1150 1151 1152 1153
    { "none",            "Aq not used",         0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, VE, "aq_mode" },
    { "variance",        "Variance based Aq",   0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE, "aq_mode" },
    { "complexity",      "Complexity based Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "aq_mode" },
    { "cyclic",          "Cyclic Refresh Aq",   0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE, "aq_mode" },
1154
#if VPX_ENCODER_ABI_VERSION >= 12
1155
    { "equator360",      "360 video Aq",        0, AV_OPT_TYPE_CONST, {.i64 = 4}, 0, 0, VE, "aq_mode" },
1156
    {"level", "Specify level", OFFSET(level), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 6.2, VE},
1157 1158 1159
#endif
#ifdef VPX_CTRL_VP9E_SET_ROW_MT
    {"row-mt", "Row based multi-threading", OFFSET(row_mt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1160
#endif
1161 1162 1163 1164 1165 1166 1167
    LEGACY_OPTIONS
    { NULL }
};
#endif

#undef COMMON_OPTIONS
#undef LEGACY_OPTIONS
1168

1169 1170 1171 1172 1173 1174 1175 1176
static const AVCodecDefault defaults[] = {
    { "qmin",             "-1" },
    { "qmax",             "-1" },
    { "g",                "-1" },
    { "keyint_min",       "-1" },
    { NULL },
};

1177 1178 1179
#if CONFIG_LIBVPX_VP8_ENCODER
static av_cold int vp8_init(AVCodecContext *avctx)
{
1180
    return vpx_init(avctx, vpx_codec_vp8_cx());
1181 1182 1183
}

static const AVClass class_vp8 = {
1184
    .class_name = "libvpx-vp8 encoder",
1185
    .item_name  = av_default_item_name,
1186
    .option     = vp8_options,
1187 1188 1189 1190
    .version    = LIBAVUTIL_VERSION_INT,
};

AVCodec ff_libvpx_vp8_encoder = {
1191
    .name           = "libvpx",
1192
    .long_name      = NULL_IF_CONFIG_SMALL("libvpx VP8"),
1193
    .type           = AVMEDIA_TYPE_VIDEO,
1194
    .id             = AV_CODEC_ID_VP8,
1195
    .priv_data_size = sizeof(VPxContext),
1196
    .init           = vp8_init,
1197 1198
    .encode2        = vpx_encode,
    .close          = vpx_free,
1199
    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,
1200
    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE },
1201
    .priv_class     = &class_vp8,
1202
    .defaults       = defaults,
James Zern's avatar
James Zern committed
1203
};
1204
#endif /* CONFIG_LIBVPX_VP8_ENCODER */
Luca Barbato's avatar
Luca Barbato committed
1205

1206
#if CONFIG_LIBVPX_VP9_ENCODER
Luca Barbato's avatar
Luca Barbato committed
1207 1208
static av_cold int vp9_init(AVCodecContext *avctx)
{
1209
    return vpx_init(avctx, vpx_codec_vp9_cx());
Luca Barbato's avatar
Luca Barbato committed
1210 1211 1212
}

static const AVClass class_vp9 = {
1213
    .class_name = "libvpx-vp9 encoder",
Luca Barbato's avatar
Luca Barbato committed
1214
    .item_name  = av_default_item_name,
1215
    .option     = vp9_options,
Luca Barbato's avatar
Luca Barbato committed
1216 1217 1218 1219 1220
    .version    = LIBAVUTIL_VERSION_INT,
};

AVCodec ff_libvpx_vp9_encoder = {
    .name           = "libvpx-vp9",
1221
    .long_name      = NULL_IF_CONFIG_SMALL("libvpx VP9"),
Luca Barbato's avatar
Luca Barbato committed
1222 1223
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = AV_CODEC_ID_VP9,
1224
    .priv_data_size = sizeof(VPxContext),
Luca Barbato's avatar
Luca Barbato committed
1225
    .init           = vp9_init,
1226 1227
    .encode2        = vpx_encode,
    .close          = vpx_free,
1228
    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,
1229
    .profiles       = NULL_IF_CONFIG_SMALL(ff_vp9_profiles),
Luca Barbato's avatar
Luca Barbato committed
1230
    .priv_class     = &class_vp9,
1231
    .defaults       = defaults,
1232
    .init_static_data = ff_vp9_init_static,
James Zern's avatar
James Zern committed
1233
};
1234
#endif /* CONFIG_LIBVPX_VP9_ENCODER */