Libav
libvpxenc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Google, Inc.
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
26 #define VPX_DISABLE_CTRL_TYPECHECKS 1
27 #define VPX_CODEC_DISABLE_COMPAT 1
28 #include <vpx/vpx_encoder.h>
29 #include <vpx/vp8cx.h>
30 
31 #include "avcodec.h"
32 #include "internal.h"
33 #include "libvpx.h"
34 #include "libavutil/base64.h"
35 #include "libavutil/common.h"
36 #include "libavutil/mathematics.h"
37 #include "libavutil/opt.h"
38 
43 struct FrameListData {
44  void *buf;
45  size_t sz;
46  int64_t pts;
48  unsigned long duration;
50  uint32_t flags;
52 };
53 
54 typedef struct VP8EncoderContext {
55  AVClass *class;
56  struct vpx_codec_ctx encoder;
57  struct vpx_image rawimg;
58  struct vpx_fixed_buf twopass_stats;
59  unsigned long deadline; //i.e., RT/GOOD/BEST
61  int cpu_used;
65  int arnr_type;
68  int crf;
69 } VP8Context;
70 
72 static const char *const ctlidstr[] = {
73  [VP8E_UPD_ENTROPY] = "VP8E_UPD_ENTROPY",
74  [VP8E_UPD_REFERENCE] = "VP8E_UPD_REFERENCE",
75  [VP8E_USE_REFERENCE] = "VP8E_USE_REFERENCE",
76  [VP8E_SET_ROI_MAP] = "VP8E_SET_ROI_MAP",
77  [VP8E_SET_ACTIVEMAP] = "VP8E_SET_ACTIVEMAP",
78  [VP8E_SET_SCALEMODE] = "VP8E_SET_SCALEMODE",
79  [VP8E_SET_CPUUSED] = "VP8E_SET_CPUUSED",
80  [VP8E_SET_ENABLEAUTOALTREF] = "VP8E_SET_ENABLEAUTOALTREF",
81  [VP8E_SET_NOISE_SENSITIVITY] = "VP8E_SET_NOISE_SENSITIVITY",
82  [VP8E_SET_SHARPNESS] = "VP8E_SET_SHARPNESS",
83  [VP8E_SET_STATIC_THRESHOLD] = "VP8E_SET_STATIC_THRESHOLD",
84  [VP8E_SET_TOKEN_PARTITIONS] = "VP8E_SET_TOKEN_PARTITIONS",
85  [VP8E_GET_LAST_QUANTIZER] = "VP8E_GET_LAST_QUANTIZER",
86  [VP8E_SET_ARNR_MAXFRAMES] = "VP8E_SET_ARNR_MAXFRAMES",
87  [VP8E_SET_ARNR_STRENGTH] = "VP8E_SET_ARNR_STRENGTH",
88  [VP8E_SET_ARNR_TYPE] = "VP8E_SET_ARNR_TYPE",
89  [VP8E_SET_CQ_LEVEL] = "VP8E_SET_CQ_LEVEL",
90 };
91 
92 static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc)
93 {
94  VP8Context *ctx = avctx->priv_data;
95  const char *error = vpx_codec_error(&ctx->encoder);
96  const char *detail = vpx_codec_error_detail(&ctx->encoder);
97 
98  av_log(avctx, AV_LOG_ERROR, "%s: %s\n", desc, error);
99  if (detail)
100  av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", detail);
101 }
102 
104  const struct vpx_codec_enc_cfg *cfg)
105 {
106  int width = -30;
107  int level = AV_LOG_DEBUG;
108 
109  av_log(avctx, level, "vpx_codec_enc_cfg\n");
110  av_log(avctx, level, "generic settings\n"
111  " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n"
112  " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n",
113  width, "g_usage:", cfg->g_usage,
114  width, "g_threads:", cfg->g_threads,
115  width, "g_profile:", cfg->g_profile,
116  width, "g_w:", cfg->g_w,
117  width, "g_h:", cfg->g_h,
118  width, "g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den,
119  width, "g_error_resilient:", cfg->g_error_resilient,
120  width, "g_pass:", cfg->g_pass,
121  width, "g_lag_in_frames:", cfg->g_lag_in_frames);
122  av_log(avctx, level, "rate control settings\n"
123  " %*s%u\n %*s%u\n %*s%u\n %*s%u\n"
124  " %*s%d\n %*s%p(%zu)\n %*s%u\n",
125  width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh,
126  width, "rc_resize_allowed:", cfg->rc_resize_allowed,
127  width, "rc_resize_up_thresh:", cfg->rc_resize_up_thresh,
128  width, "rc_resize_down_thresh:", cfg->rc_resize_down_thresh,
129  width, "rc_end_usage:", cfg->rc_end_usage,
130  width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz,
131  width, "rc_target_bitrate:", cfg->rc_target_bitrate);
132  av_log(avctx, level, "quantizer settings\n"
133  " %*s%u\n %*s%u\n",
134  width, "rc_min_quantizer:", cfg->rc_min_quantizer,
135  width, "rc_max_quantizer:", cfg->rc_max_quantizer);
136  av_log(avctx, level, "bitrate tolerance\n"
137  " %*s%u\n %*s%u\n",
138  width, "rc_undershoot_pct:", cfg->rc_undershoot_pct,
139  width, "rc_overshoot_pct:", cfg->rc_overshoot_pct);
140  av_log(avctx, level, "decoder buffer model\n"
141  " %*s%u\n %*s%u\n %*s%u\n",
142  width, "rc_buf_sz:", cfg->rc_buf_sz,
143  width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz,
144  width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz);
145  av_log(avctx, level, "2 pass rate control settings\n"
146  " %*s%u\n %*s%u\n %*s%u\n",
147  width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct,
148  width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct,
149  width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct);
150  av_log(avctx, level, "keyframing settings\n"
151  " %*s%d\n %*s%u\n %*s%u\n",
152  width, "kf_mode:", cfg->kf_mode,
153  width, "kf_min_dist:", cfg->kf_min_dist,
154  width, "kf_max_dist:", cfg->kf_max_dist);
155  av_log(avctx, level, "\n");
156 }
157 
158 static void coded_frame_add(void *list, struct FrameListData *cx_frame)
159 {
160  struct FrameListData **p = list;
161 
162  while (*p != NULL)
163  p = &(*p)->next;
164  *p = cx_frame;
165  cx_frame->next = NULL;
166 }
167 
168 static av_cold void free_coded_frame(struct FrameListData *cx_frame)
169 {
170  av_freep(&cx_frame->buf);
171  av_freep(&cx_frame);
172 }
173 
174 static av_cold void free_frame_list(struct FrameListData *list)
175 {
176  struct FrameListData *p = list;
177 
178  while (p) {
179  list = list->next;
180  free_coded_frame(p);
181  p = list;
182  }
183 }
184 
186  enum vp8e_enc_control_id id, int val)
187 {
188  VP8Context *ctx = avctx->priv_data;
189  char buf[80];
190  int width = -30;
191  int res;
192 
193  snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]);
194  av_log(avctx, AV_LOG_DEBUG, " %*s%d\n", width, buf, val);
195 
196  res = vpx_codec_control(&ctx->encoder, id, val);
197  if (res != VPX_CODEC_OK) {
198  snprintf(buf, sizeof(buf), "Failed to set %s codec control",
199  ctlidstr[id]);
200  log_encoder_error(avctx, buf);
201  }
202 
203  return res == VPX_CODEC_OK ? 0 : AVERROR(EINVAL);
204 }
205 
206 static av_cold int vp8_free(AVCodecContext *avctx)
207 {
208  VP8Context *ctx = avctx->priv_data;
209 
210  vpx_codec_destroy(&ctx->encoder);
211  av_freep(&ctx->twopass_stats.buf);
212  av_freep(&avctx->coded_frame);
213  av_freep(&avctx->stats_out);
215  return 0;
216 }
217 
218 static av_cold int vpx_init(AVCodecContext *avctx,
219  const struct vpx_codec_iface *iface)
220 {
221  VP8Context *ctx = avctx->priv_data;
222  struct vpx_codec_enc_cfg enccfg;
223  int res;
224 
225  av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str());
226  av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config());
227 
228  if ((res = vpx_codec_enc_config_default(iface, &enccfg, 0)) != VPX_CODEC_OK) {
229  av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n",
230  vpx_codec_err_to_string(res));
231  return AVERROR(EINVAL);
232  }
233  dump_enc_cfg(avctx, &enccfg);
234 
235  enccfg.g_w = avctx->width;
236  enccfg.g_h = avctx->height;
237  enccfg.g_timebase.num = avctx->time_base.num;
238  enccfg.g_timebase.den = avctx->time_base.den;
239  enccfg.g_threads = avctx->thread_count;
240 
241  if (ctx->lag_in_frames >= 0)
242  enccfg.g_lag_in_frames = ctx->lag_in_frames;
243 
244  if (avctx->flags & CODEC_FLAG_PASS1)
245  enccfg.g_pass = VPX_RC_FIRST_PASS;
246  else if (avctx->flags & CODEC_FLAG_PASS2)
247  enccfg.g_pass = VPX_RC_LAST_PASS;
248  else
249  enccfg.g_pass = VPX_RC_ONE_PASS;
250 
251  if (!avctx->bit_rate)
252  avctx->bit_rate = enccfg.rc_target_bitrate * 1000;
253  else
254  enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000,
256 
257  if (ctx->crf)
258  enccfg.rc_end_usage = VPX_CQ;
259  else if (avctx->rc_min_rate == avctx->rc_max_rate &&
260  avctx->rc_min_rate == avctx->bit_rate)
261  enccfg.rc_end_usage = VPX_CBR;
262 
263  if (avctx->qmin > 0)
264  enccfg.rc_min_quantizer = avctx->qmin;
265  if (avctx->qmax > 0)
266  enccfg.rc_max_quantizer = avctx->qmax;
267  enccfg.rc_dropframe_thresh = avctx->frame_skip_threshold;
268 
269  //0-100 (0 => CBR, 100 => VBR)
270  enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100);
271  enccfg.rc_2pass_vbr_minsection_pct =
272  avctx->rc_min_rate * 100LL / avctx->bit_rate;
273  if (avctx->rc_max_rate)
274  enccfg.rc_2pass_vbr_maxsection_pct =
275  avctx->rc_max_rate * 100LL / avctx->bit_rate;
276 
277  if (avctx->rc_buffer_size)
278  enccfg.rc_buf_sz =
279  avctx->rc_buffer_size * 1000LL / avctx->bit_rate;
280  if (avctx->rc_initial_buffer_occupancy)
281  enccfg.rc_buf_initial_sz =
282  avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate;
283  enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6;
284 
285  //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO
286  if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
287  enccfg.kf_min_dist = avctx->keyint_min;
288  if (avctx->gop_size >= 0)
289  enccfg.kf_max_dist = avctx->gop_size;
290 
291  if (enccfg.g_pass == VPX_RC_FIRST_PASS)
292  enccfg.g_lag_in_frames = 0;
293  else if (enccfg.g_pass == VPX_RC_LAST_PASS) {
294  int decode_size, ret;
295 
296  if (!avctx->stats_in) {
297  av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n");
298  return AVERROR_INVALIDDATA;
299  }
300 
301  ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4;
302  ret = av_reallocp(&ctx->twopass_stats.buf, ctx->twopass_stats.sz);
303  if (ret < 0) {
304  av_log(avctx, AV_LOG_ERROR,
305  "Stat buffer alloc (%zu bytes) failed\n",
306  ctx->twopass_stats.sz);
307  return ret;
308  }
309  decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in,
310  ctx->twopass_stats.sz);
311  if (decode_size < 0) {
312  av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n");
313  return AVERROR_INVALIDDATA;
314  }
315 
316  ctx->twopass_stats.sz = decode_size;
317  enccfg.rc_twopass_stats_in = ctx->twopass_stats;
318  }
319 
320  /* 0-3: For non-zero values the encoder increasingly optimizes for reduced
321  complexity playback on low powered devices at the expense of encode
322  quality. */
323  if (avctx->profile != FF_PROFILE_UNKNOWN)
324  enccfg.g_profile = avctx->profile;
325 
326  enccfg.g_error_resilient = ctx->error_resilient;
327 
328  dump_enc_cfg(avctx, &enccfg);
329  /* Construct Encoder Context */
330  res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, 0);
331  if (res != VPX_CODEC_OK) {
332  log_encoder_error(avctx, "Failed to initialize encoder");
333  return AVERROR(EINVAL);
334  }
335 
336  //codec control failures are currently treated only as warnings
337  av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n");
338  if (ctx->cpu_used != INT_MIN)
339  codecctl_int(avctx, VP8E_SET_CPUUSED, ctx->cpu_used);
340  if (ctx->auto_alt_ref >= 0)
341  codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF, ctx->auto_alt_ref);
342  if (ctx->arnr_max_frames >= 0)
343  codecctl_int(avctx, VP8E_SET_ARNR_MAXFRAMES, ctx->arnr_max_frames);
344  if (ctx->arnr_strength >= 0)
345  codecctl_int(avctx, VP8E_SET_ARNR_STRENGTH, ctx->arnr_strength);
346  if (ctx->arnr_type >= 0)
347  codecctl_int(avctx, VP8E_SET_ARNR_TYPE, ctx->arnr_type);
348  codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction);
349  codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices));
350  codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, avctx->mb_threshold);
351  codecctl_int(avctx, VP8E_SET_CQ_LEVEL, ctx->crf);
352 
353  //provide dummy value to initialize wrapper, values will be updated each _encode()
354  vpx_img_wrap(&ctx->rawimg, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1,
355  (unsigned char*)1);
356 
357  avctx->coded_frame = av_frame_alloc();
358  if (!avctx->coded_frame) {
359  av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n");
360  vp8_free(avctx);
361  return AVERROR(ENOMEM);
362  }
363  return 0;
364 }
365 
366 static inline void cx_pktcpy(struct FrameListData *dst,
367  const struct vpx_codec_cx_pkt *src)
368 {
369  dst->pts = src->data.frame.pts;
370  dst->duration = src->data.frame.duration;
371  dst->flags = src->data.frame.flags;
372  dst->sz = src->data.frame.sz;
373  dst->buf = src->data.frame.buf;
374 }
375 
383 static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
384  AVPacket *pkt, AVFrame *coded_frame)
385 {
386  int ret = ff_alloc_packet(pkt, cx_frame->sz);
387  if (ret >= 0) {
388  memcpy(pkt->data, cx_frame->buf, pkt->size);
389  pkt->pts = pkt->dts = cx_frame->pts;
390  coded_frame->pts = cx_frame->pts;
391  coded_frame->key_frame = !!(cx_frame->flags & VPX_FRAME_IS_KEY);
392 
393  if (coded_frame->key_frame) {
394  coded_frame->pict_type = AV_PICTURE_TYPE_I;
395  pkt->flags |= AV_PKT_FLAG_KEY;
396  } else
397  coded_frame->pict_type = AV_PICTURE_TYPE_P;
398  } else {
399  av_log(avctx, AV_LOG_ERROR,
400  "Error getting output packet of size %zu.\n", cx_frame->sz);
401  return ret;
402  }
403  return pkt->size;
404 }
405 
414 static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out,
415  AVFrame *coded_frame)
416 {
417  VP8Context *ctx = avctx->priv_data;
418  const struct vpx_codec_cx_pkt *pkt;
419  const void *iter = NULL;
420  int size = 0;
421 
422  if (ctx->coded_frame_list) {
423  struct FrameListData *cx_frame = ctx->coded_frame_list;
424  /* return the leading frame if we've already begun queueing */
425  size = storeframe(avctx, cx_frame, pkt_out, coded_frame);
426  if (size < 0)
427  return size;
428  ctx->coded_frame_list = cx_frame->next;
429  free_coded_frame(cx_frame);
430  }
431 
432  /* consume all available output from the encoder before returning. buffers
433  are only good through the next vpx_codec call */
434  while ((pkt = vpx_codec_get_cx_data(&ctx->encoder, &iter))) {
435  switch (pkt->kind) {
436  case VPX_CODEC_CX_FRAME_PKT:
437  if (!size) {
438  struct FrameListData cx_frame;
439 
440  /* avoid storing the frame when the list is empty and we haven't yet
441  provided a frame for output */
442  assert(!ctx->coded_frame_list);
443  cx_pktcpy(&cx_frame, pkt);
444  size = storeframe(avctx, &cx_frame, pkt_out, coded_frame);
445  if (size < 0)
446  return size;
447  } else {
448  struct FrameListData *cx_frame =
449  av_malloc(sizeof(struct FrameListData));
450 
451  if (!cx_frame) {
452  av_log(avctx, AV_LOG_ERROR,
453  "Frame queue element alloc failed\n");
454  return AVERROR(ENOMEM);
455  }
456  cx_pktcpy(cx_frame, pkt);
457  cx_frame->buf = av_malloc(cx_frame->sz);
458 
459  if (!cx_frame->buf) {
460  av_log(avctx, AV_LOG_ERROR,
461  "Data buffer alloc (%zu bytes) failed\n",
462  cx_frame->sz);
463  return AVERROR(ENOMEM);
464  }
465  memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz);
466  coded_frame_add(&ctx->coded_frame_list, cx_frame);
467  }
468  break;
469  case VPX_CODEC_STATS_PKT: {
470  struct vpx_fixed_buf *stats = &ctx->twopass_stats;
471  int err;
472  if ((err = av_reallocp(&stats->buf,
473  stats->sz +
474  pkt->data.twopass_stats.sz)) < 0) {
475  stats->sz = 0;
476  av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n");
477  return err;
478  }
479  memcpy((uint8_t*)stats->buf + stats->sz,
480  pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz);
481  stats->sz += pkt->data.twopass_stats.sz;
482  break;
483  }
484  case VPX_CODEC_PSNR_PKT: //FIXME add support for CODEC_FLAG_PSNR
485  case VPX_CODEC_CUSTOM_PKT:
486  //ignore unsupported/unrecognized packet types
487  break;
488  }
489  }
490 
491  return size;
492 }
493 
494 static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt,
495  const AVFrame *frame, int *got_packet)
496 {
497  VP8Context *ctx = avctx->priv_data;
498  struct vpx_image *rawimg = NULL;
499  int64_t timestamp = 0;
500  int res, coded_size;
501  vpx_enc_frame_flags_t flags = 0;
502 
503  if (frame) {
504  rawimg = &ctx->rawimg;
505  rawimg->planes[VPX_PLANE_Y] = frame->data[0];
506  rawimg->planes[VPX_PLANE_U] = frame->data[1];
507  rawimg->planes[VPX_PLANE_V] = frame->data[2];
508  rawimg->stride[VPX_PLANE_Y] = frame->linesize[0];
509  rawimg->stride[VPX_PLANE_U] = frame->linesize[1];
510  rawimg->stride[VPX_PLANE_V] = frame->linesize[2];
511  timestamp = frame->pts;
512  if (frame->pict_type == AV_PICTURE_TYPE_I)
513  flags |= VPX_EFLAG_FORCE_KF;
514  }
515 
516  res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp,
517  avctx->ticks_per_frame, flags, ctx->deadline);
518  if (res != VPX_CODEC_OK) {
519  log_encoder_error(avctx, "Error encoding frame");
520  return AVERROR_INVALIDDATA;
521  }
522  coded_size = queue_frames(avctx, pkt, avctx->coded_frame);
523 
524  if (!frame && avctx->flags & CODEC_FLAG_PASS1) {
525  unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz);
526 
527  avctx->stats_out = av_malloc(b64_size);
528  if (!avctx->stats_out) {
529  av_log(avctx, AV_LOG_ERROR, "Stat buffer alloc (%d bytes) failed\n",
530  b64_size);
531  return AVERROR(ENOMEM);
532  }
533  av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf,
534  ctx->twopass_stats.sz);
535  }
536 
537  *got_packet = !!coded_size;
538  return 0;
539 }
540 
541 #define OFFSET(x) offsetof(VP8Context, x)
542 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
543 static const AVOption options[] = {
544  { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), AV_OPT_TYPE_INT, {.i64 = INT_MIN}, INT_MIN, INT_MAX, VE},
545  { "auto-alt-ref", "Enable use of alternate reference "
546  "frames (2-pass only)", OFFSET(auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE},
547  { "lag-in-frames", "Number of frames to look ahead for "
548  "alternate reference frame selection", OFFSET(lag_in_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE},
549  { "arnr-maxframes", "altref noise reduction max frame count", OFFSET(arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE},
550  { "arnr-strength", "altref noise reduction filter strength", OFFSET(arnr_strength), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE},
551  { "arnr-type", "altref noise reduction filter type", OFFSET(arnr_type), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, "arnr_type"},
552  { "backward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE, "arnr_type" },
553  { "forward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "arnr_type" },
554  { "centered", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE, "arnr_type" },
555  { "deadline", "Time to spend encoding, in microseconds.", OFFSET(deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"},
556  { "best", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_BEST_QUALITY}, 0, 0, VE, "quality"},
557  { "good", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_GOOD_QUALITY}, 0, 0, VE, "quality"},
558  { "realtime", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_REALTIME}, 0, 0, VE, "quality"},
559  { "error-resilient", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"},
560 #ifdef VPX_ERROR_RESILIENT_DEFAULT
561  { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"},
562  { "partitions", "The frame partitions are independently decodable "
563  "by the bool decoder, meaning that partitions can be decoded even "
564  "though earlier partitions have been lost. Note that intra predicition"
565  " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"},
566 #endif
567  { "crf", "Select the quality for constant quality mode", offsetof(VP8Context, crf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, VE },
568  { NULL }
569 };
570 
571 static const AVCodecDefault defaults[] = {
572  { "qmin", "-1" },
573  { "qmax", "-1" },
574  { "g", "-1" },
575  { "keyint_min", "-1" },
576  { NULL },
577 };
578 
579 #if CONFIG_LIBVPX_VP8_ENCODER
580 static av_cold int vp8_init(AVCodecContext *avctx)
581 {
582  return vpx_init(avctx, &vpx_codec_vp8_cx_algo);
583 }
584 
585 static const AVClass class_vp8 = {
586  .class_name = "libvpx encoder",
587  .item_name = av_default_item_name,
588  .option = options,
589  .version = LIBAVUTIL_VERSION_INT,
590 };
591 
592 AVCodec ff_libvpx_vp8_encoder = {
593  .name = "libvpx",
594  .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"),
595  .type = AVMEDIA_TYPE_VIDEO,
596  .id = AV_CODEC_ID_VP8,
597  .priv_data_size = sizeof(VP8Context),
598  .init = vp8_init,
599  .encode2 = vp8_encode,
600  .close = vp8_free,
601  .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS,
602  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
603  .priv_class = &class_vp8,
604  .defaults = defaults,
605 };
606 #endif /* CONFIG_LIBVPX_VP8_ENCODER */
607 
608 #if CONFIG_LIBVPX_VP9_ENCODER
609 static av_cold int vp9_init(AVCodecContext *avctx)
610 {
611  int ret;
612  if ((ret = ff_vp9_check_experimental(avctx)))
613  return ret;
614  return vpx_init(avctx, &vpx_codec_vp9_cx_algo);
615 }
616 
617 static const AVClass class_vp9 = {
618  .class_name = "libvpx encoder",
619  .item_name = av_default_item_name,
620  .option = options,
621  .version = LIBAVUTIL_VERSION_INT,
622 };
623 
624 AVCodec ff_libvpx_vp9_encoder = {
625  .name = "libvpx-vp9",
626  .long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"),
627  .type = AVMEDIA_TYPE_VIDEO,
628  .id = AV_CODEC_ID_VP9,
629  .priv_data_size = sizeof(VP8Context),
630  .init = vp9_init,
631  .encode2 = vp8_encode,
632  .close = vp8_free,
633  .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS,
634  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
635  .priv_class = &class_vp9,
636  .defaults = defaults,
637 };
638 #endif /* CONFIG_LIBVPX_VP9_ENCODER */