2 * Copyright (c) 2010, Google, Inc.
4 * This file is part of Libav.
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.
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.
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
23 * VP8 encoder support via libvpx
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>
33 #include "libavutil/base64.h"
34 #include "libavutil/mathematics.h"
35 #include "libavutil/opt.h"
38 * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h.
39 * One encoded frame returned from the library.
41 struct FrameListData
{
42 void *buf
; /**< compressed data buffer */
43 size_t sz
; /**< length of compressed data */
44 int64_t pts
; /**< time stamp to show frame
45 (in timebase units) */
46 unsigned long duration
; /**< duration to show frame
47 (in timebase units) */
48 uint32_t flags
; /**< flags for this frame */
49 struct FrameListData
*next
;
52 typedef struct VP8EncoderContext
{
54 struct vpx_codec_ctx encoder
;
55 struct vpx_image rawimg
;
56 struct vpx_fixed_buf twopass_stats
;
57 unsigned long deadline
; //i.e., RT/GOOD/BEST
58 struct FrameListData
*coded_frame_list
;
68 /** String mappings for enum vp8e_enc_control_id */
69 static const char *const ctlidstr
[] = {
70 [VP8E_UPD_ENTROPY
] = "VP8E_UPD_ENTROPY",
71 [VP8E_UPD_REFERENCE
] = "VP8E_UPD_REFERENCE",
72 [VP8E_USE_REFERENCE
] = "VP8E_USE_REFERENCE",
73 [VP8E_SET_ROI_MAP
] = "VP8E_SET_ROI_MAP",
74 [VP8E_SET_ACTIVEMAP
] = "VP8E_SET_ACTIVEMAP",
75 [VP8E_SET_SCALEMODE
] = "VP8E_SET_SCALEMODE",
76 [VP8E_SET_CPUUSED
] = "VP8E_SET_CPUUSED",
77 [VP8E_SET_ENABLEAUTOALTREF
] = "VP8E_SET_ENABLEAUTOALTREF",
78 [VP8E_SET_NOISE_SENSITIVITY
] = "VP8E_SET_NOISE_SENSITIVITY",
79 [VP8E_SET_SHARPNESS
] = "VP8E_SET_SHARPNESS",
80 [VP8E_SET_STATIC_THRESHOLD
] = "VP8E_SET_STATIC_THRESHOLD",
81 [VP8E_SET_TOKEN_PARTITIONS
] = "VP8E_SET_TOKEN_PARTITIONS",
82 [VP8E_GET_LAST_QUANTIZER
] = "VP8E_GET_LAST_QUANTIZER",
83 [VP8E_SET_ARNR_MAXFRAMES
] = "VP8E_SET_ARNR_MAXFRAMES",
84 [VP8E_SET_ARNR_STRENGTH
] = "VP8E_SET_ARNR_STRENGTH",
85 [VP8E_SET_ARNR_TYPE
] = "VP8E_SET_ARNR_TYPE",
88 static av_cold
void log_encoder_error(AVCodecContext
*avctx
, const char *desc
)
90 VP8Context
*ctx
= avctx
->priv_data
;
91 const char *error
= vpx_codec_error(&ctx
->encoder
);
92 const char *detail
= vpx_codec_error_detail(&ctx
->encoder
);
94 av_log(avctx
, AV_LOG_ERROR
, "%s: %s\n", desc
, error
);
96 av_log(avctx
, AV_LOG_ERROR
, " Additional information: %s\n", detail
);
99 static av_cold
void dump_enc_cfg(AVCodecContext
*avctx
,
100 const struct vpx_codec_enc_cfg
*cfg
)
103 int level
= AV_LOG_DEBUG
;
105 av_log(avctx
, level
, "vpx_codec_enc_cfg\n");
106 av_log(avctx
, level
, "generic settings\n"
107 " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n"
108 " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n",
109 width
, "g_usage:", cfg
->g_usage
,
110 width
, "g_threads:", cfg
->g_threads
,
111 width
, "g_profile:", cfg
->g_profile
,
112 width
, "g_w:", cfg
->g_w
,
113 width
, "g_h:", cfg
->g_h
,
114 width
, "g_timebase:", cfg
->g_timebase
.num
, cfg
->g_timebase
.den
,
115 width
, "g_error_resilient:", cfg
->g_error_resilient
,
116 width
, "g_pass:", cfg
->g_pass
,
117 width
, "g_lag_in_frames:", cfg
->g_lag_in_frames
);
118 av_log(avctx
, level
, "rate control settings\n"
119 " %*s%u\n %*s%u\n %*s%u\n %*s%u\n"
120 " %*s%d\n %*s%p(%zu)\n %*s%u\n",
121 width
, "rc_dropframe_thresh:", cfg
->rc_dropframe_thresh
,
122 width
, "rc_resize_allowed:", cfg
->rc_resize_allowed
,
123 width
, "rc_resize_up_thresh:", cfg
->rc_resize_up_thresh
,
124 width
, "rc_resize_down_thresh:", cfg
->rc_resize_down_thresh
,
125 width
, "rc_end_usage:", cfg
->rc_end_usage
,
126 width
, "rc_twopass_stats_in:", cfg
->rc_twopass_stats_in
.buf
, cfg
->rc_twopass_stats_in
.sz
,
127 width
, "rc_target_bitrate:", cfg
->rc_target_bitrate
);
128 av_log(avctx
, level
, "quantizer settings\n"
130 width
, "rc_min_quantizer:", cfg
->rc_min_quantizer
,
131 width
, "rc_max_quantizer:", cfg
->rc_max_quantizer
);
132 av_log(avctx
, level
, "bitrate tolerance\n"
134 width
, "rc_undershoot_pct:", cfg
->rc_undershoot_pct
,
135 width
, "rc_overshoot_pct:", cfg
->rc_overshoot_pct
);
136 av_log(avctx
, level
, "decoder buffer model\n"
137 " %*s%u\n %*s%u\n %*s%u\n",
138 width
, "rc_buf_sz:", cfg
->rc_buf_sz
,
139 width
, "rc_buf_initial_sz:", cfg
->rc_buf_initial_sz
,
140 width
, "rc_buf_optimal_sz:", cfg
->rc_buf_optimal_sz
);
141 av_log(avctx
, level
, "2 pass rate control settings\n"
142 " %*s%u\n %*s%u\n %*s%u\n",
143 width
, "rc_2pass_vbr_bias_pct:", cfg
->rc_2pass_vbr_bias_pct
,
144 width
, "rc_2pass_vbr_minsection_pct:", cfg
->rc_2pass_vbr_minsection_pct
,
145 width
, "rc_2pass_vbr_maxsection_pct:", cfg
->rc_2pass_vbr_maxsection_pct
);
146 av_log(avctx
, level
, "keyframing settings\n"
147 " %*s%d\n %*s%u\n %*s%u\n",
148 width
, "kf_mode:", cfg
->kf_mode
,
149 width
, "kf_min_dist:", cfg
->kf_min_dist
,
150 width
, "kf_max_dist:", cfg
->kf_max_dist
);
151 av_log(avctx
, level
, "\n");
154 static void coded_frame_add(void *list
, struct FrameListData
*cx_frame
)
156 struct FrameListData
**p
= list
;
161 cx_frame
->next
= NULL
;
164 static av_cold
void free_coded_frame(struct FrameListData
*cx_frame
)
166 av_freep(&cx_frame
->buf
);
170 static av_cold
void free_frame_list(struct FrameListData
*list
)
172 struct FrameListData
*p
= list
;
181 static av_cold
int codecctl_int(AVCodecContext
*avctx
,
182 enum vp8e_enc_control_id id
, int val
)
184 VP8Context
*ctx
= avctx
->priv_data
;
189 snprintf(buf
, sizeof(buf
), "%s:", ctlidstr
[id
]);
190 av_log(avctx
, AV_LOG_DEBUG
, " %*s%d\n", width
, buf
, val
);
192 res
= vpx_codec_control(&ctx
->encoder
, id
, val
);
193 if (res
!= VPX_CODEC_OK
) {
194 snprintf(buf
, sizeof(buf
), "Failed to set %s codec control",
196 log_encoder_error(avctx
, buf
);
199 return res
== VPX_CODEC_OK
? 0 : AVERROR(EINVAL
);
202 static av_cold
int vp8_free(AVCodecContext
*avctx
)
204 VP8Context
*ctx
= avctx
->priv_data
;
206 vpx_codec_destroy(&ctx
->encoder
);
207 av_freep(&ctx
->twopass_stats
.buf
);
208 av_freep(&avctx
->coded_frame
);
209 av_freep(&avctx
->stats_out
);
210 free_frame_list(ctx
->coded_frame_list
);
214 static av_cold
int vp8_init(AVCodecContext
*avctx
)
216 VP8Context
*ctx
= avctx
->priv_data
;
217 const struct vpx_codec_iface
*iface
= &vpx_codec_vp8_cx_algo
;
218 struct vpx_codec_enc_cfg enccfg
;
221 av_log(avctx
, AV_LOG_INFO
, "%s\n", vpx_codec_version_str());
222 av_log(avctx
, AV_LOG_VERBOSE
, "%s\n", vpx_codec_build_config());
224 if ((res
= vpx_codec_enc_config_default(iface
, &enccfg
, 0)) != VPX_CODEC_OK
) {
225 av_log(avctx
, AV_LOG_ERROR
, "Failed to get config: %s\n",
226 vpx_codec_err_to_string(res
));
227 return AVERROR(EINVAL
);
229 dump_enc_cfg(avctx
, &enccfg
);
231 enccfg
.g_w
= avctx
->width
;
232 enccfg
.g_h
= avctx
->height
;
233 enccfg
.g_timebase
.num
= avctx
->time_base
.num
;
234 enccfg
.g_timebase
.den
= avctx
->time_base
.den
;
235 enccfg
.g_threads
= avctx
->thread_count
;
237 if (ctx
->lag_in_frames
>= 0)
238 enccfg
.g_lag_in_frames
= ctx
->lag_in_frames
;
240 if (avctx
->flags
& CODEC_FLAG_PASS1
)
241 enccfg
.g_pass
= VPX_RC_FIRST_PASS
;
242 else if (avctx
->flags
& CODEC_FLAG_PASS2
)
243 enccfg
.g_pass
= VPX_RC_LAST_PASS
;
245 enccfg
.g_pass
= VPX_RC_ONE_PASS
;
247 if (avctx
->rc_min_rate
== avctx
->rc_max_rate
&&
248 avctx
->rc_min_rate
== avctx
->bit_rate
)
249 enccfg
.rc_end_usage
= VPX_CBR
;
250 enccfg
.rc_target_bitrate
= av_rescale_rnd(avctx
->bit_rate
, 1, 1000,
253 enccfg
.rc_min_quantizer
= avctx
->qmin
;
255 enccfg
.rc_max_quantizer
= avctx
->qmax
;
256 enccfg
.rc_dropframe_thresh
= avctx
->frame_skip_threshold
;
258 //0-100 (0 => CBR, 100 => VBR)
259 enccfg
.rc_2pass_vbr_bias_pct
= round(avctx
->qcompress
* 100);
260 enccfg
.rc_2pass_vbr_minsection_pct
=
261 avctx
->rc_min_rate
* 100LL / avctx
->bit_rate
;
262 if (avctx
->rc_max_rate
)
263 enccfg
.rc_2pass_vbr_maxsection_pct
=
264 avctx
->rc_max_rate
* 100LL / avctx
->bit_rate
;
266 if (avctx
->rc_buffer_size
)
268 avctx
->rc_buffer_size
* 1000LL / avctx
->bit_rate
;
269 if (avctx
->rc_initial_buffer_occupancy
)
270 enccfg
.rc_buf_initial_sz
=
271 avctx
->rc_initial_buffer_occupancy
* 1000LL / avctx
->bit_rate
;
272 enccfg
.rc_buf_optimal_sz
= enccfg
.rc_buf_sz
* 5 / 6;
274 //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO
275 if (avctx
->keyint_min
>= 0 && avctx
->keyint_min
== avctx
->gop_size
)
276 enccfg
.kf_min_dist
= avctx
->keyint_min
;
277 if (avctx
->gop_size
>= 0)
278 enccfg
.kf_max_dist
= avctx
->gop_size
;
280 if (enccfg
.g_pass
== VPX_RC_FIRST_PASS
)
281 enccfg
.g_lag_in_frames
= 0;
282 else if (enccfg
.g_pass
== VPX_RC_LAST_PASS
) {
285 if (!avctx
->stats_in
) {
286 av_log(avctx
, AV_LOG_ERROR
, "No stats file for second pass\n");
287 return AVERROR_INVALIDDATA
;
290 ctx
->twopass_stats
.sz
= strlen(avctx
->stats_in
) * 3 / 4;
291 ctx
->twopass_stats
.buf
= av_malloc(ctx
->twopass_stats
.sz
);
292 if (!ctx
->twopass_stats
.buf
) {
293 av_log(avctx
, AV_LOG_ERROR
,
294 "Stat buffer alloc (%zu bytes) failed\n",
295 ctx
->twopass_stats
.sz
);
296 return AVERROR(ENOMEM
);
298 decode_size
= av_base64_decode(ctx
->twopass_stats
.buf
, avctx
->stats_in
,
299 ctx
->twopass_stats
.sz
);
300 if (decode_size
< 0) {
301 av_log(avctx
, AV_LOG_ERROR
, "Stat buffer decode failed\n");
302 return AVERROR_INVALIDDATA
;
305 ctx
->twopass_stats
.sz
= decode_size
;
306 enccfg
.rc_twopass_stats_in
= ctx
->twopass_stats
;
309 /* 0-3: For non-zero values the encoder increasingly optimizes for reduced
310 complexity playback on low powered devices at the expense of encode
312 if (avctx
->profile
!= FF_PROFILE_UNKNOWN
)
313 enccfg
.g_profile
= avctx
->profile
;
315 enccfg
.g_error_resilient
= ctx
->error_resilient
;
317 dump_enc_cfg(avctx
, &enccfg
);
318 /* Construct Encoder Context */
319 res
= vpx_codec_enc_init(&ctx
->encoder
, iface
, &enccfg
, 0);
320 if (res
!= VPX_CODEC_OK
) {
321 log_encoder_error(avctx
, "Failed to initialize encoder");
322 return AVERROR(EINVAL
);
325 //codec control failures are currently treated only as warnings
326 av_log(avctx
, AV_LOG_DEBUG
, "vpx_codec_control\n");
327 if (ctx
->cpu_used
!= INT_MIN
)
328 codecctl_int(avctx
, VP8E_SET_CPUUSED
, ctx
->cpu_used
);
329 if (ctx
->auto_alt_ref
>= 0)
330 codecctl_int(avctx
, VP8E_SET_ENABLEAUTOALTREF
, ctx
->auto_alt_ref
);
331 if (ctx
->arnr_max_frames
>= 0)
332 codecctl_int(avctx
, VP8E_SET_ARNR_MAXFRAMES
, ctx
->arnr_max_frames
);
333 if (ctx
->arnr_strength
>= 0)
334 codecctl_int(avctx
, VP8E_SET_ARNR_STRENGTH
, ctx
->arnr_strength
);
335 if (ctx
->arnr_type
>= 0)
336 codecctl_int(avctx
, VP8E_SET_ARNR_TYPE
, ctx
->arnr_type
);
337 codecctl_int(avctx
, VP8E_SET_NOISE_SENSITIVITY
, avctx
->noise_reduction
);
338 codecctl_int(avctx
, VP8E_SET_TOKEN_PARTITIONS
, av_log2(avctx
->slices
));
339 codecctl_int(avctx
, VP8E_SET_STATIC_THRESHOLD
, avctx
->mb_threshold
);
341 //provide dummy value to initialize wrapper, values will be updated each _encode()
342 vpx_img_wrap(&ctx
->rawimg
, VPX_IMG_FMT_I420
, avctx
->width
, avctx
->height
, 1,
345 avctx
->coded_frame
= avcodec_alloc_frame();
346 if (!avctx
->coded_frame
) {
347 av_log(avctx
, AV_LOG_ERROR
, "Error allocating coded frame\n");
349 return AVERROR(ENOMEM
);
354 static inline void cx_pktcpy(struct FrameListData
*dst
,
355 const struct vpx_codec_cx_pkt
*src
)
357 dst
->pts
= src
->data
.frame
.pts
;
358 dst
->duration
= src
->data
.frame
.duration
;
359 dst
->flags
= src
->data
.frame
.flags
;
360 dst
->sz
= src
->data
.frame
.sz
;
361 dst
->buf
= src
->data
.frame
.buf
;
365 * Store coded frame information in format suitable for return from encode2().
367 * Write information from @a cx_frame to @a pkt
368 * @return packet data size on success
369 * @return a negative AVERROR on error
371 static int storeframe(AVCodecContext
*avctx
, struct FrameListData
*cx_frame
,
372 AVPacket
*pkt
, AVFrame
*coded_frame
)
374 int ret
= ff_alloc_packet(pkt
, cx_frame
->sz
);
376 memcpy(pkt
->data
, cx_frame
->buf
, pkt
->size
);
377 pkt
->pts
= pkt
->dts
= cx_frame
->pts
;
378 coded_frame
->pts
= cx_frame
->pts
;
379 coded_frame
->key_frame
= !!(cx_frame
->flags
& VPX_FRAME_IS_KEY
);
381 if (coded_frame
->key_frame
) {
382 coded_frame
->pict_type
= AV_PICTURE_TYPE_I
;
383 pkt
->flags
|= AV_PKT_FLAG_KEY
;
385 coded_frame
->pict_type
= AV_PICTURE_TYPE_P
;
387 av_log(avctx
, AV_LOG_ERROR
,
388 "Error getting output packet of size %zu.\n", cx_frame
->sz
);
395 * Queue multiple output frames from the encoder, returning the front-most.
396 * In cases where vpx_codec_get_cx_data() returns more than 1 frame append
397 * the frame queue. Return the head frame if available.
398 * @return Stored frame size
399 * @return AVERROR(EINVAL) on output size error
400 * @return AVERROR(ENOMEM) on coded frame queue data allocation error
402 static int queue_frames(AVCodecContext
*avctx
, AVPacket
*pkt_out
,
403 AVFrame
*coded_frame
)
405 VP8Context
*ctx
= avctx
->priv_data
;
406 const struct vpx_codec_cx_pkt
*pkt
;
407 const void *iter
= NULL
;
410 if (ctx
->coded_frame_list
) {
411 struct FrameListData
*cx_frame
= ctx
->coded_frame_list
;
412 /* return the leading frame if we've already begun queueing */
413 size
= storeframe(avctx
, cx_frame
, pkt_out
, coded_frame
);
416 ctx
->coded_frame_list
= cx_frame
->next
;
417 free_coded_frame(cx_frame
);
420 /* consume all available output from the encoder before returning. buffers
421 are only good through the next vpx_codec call */
422 while ((pkt
= vpx_codec_get_cx_data(&ctx
->encoder
, &iter
))) {
424 case VPX_CODEC_CX_FRAME_PKT
:
426 struct FrameListData cx_frame
;
428 /* avoid storing the frame when the list is empty and we haven't yet
429 provided a frame for output */
430 assert(!ctx
->coded_frame_list
);
431 cx_pktcpy(&cx_frame
, pkt
);
432 size
= storeframe(avctx
, &cx_frame
, pkt_out
, coded_frame
);
436 struct FrameListData
*cx_frame
=
437 av_malloc(sizeof(struct FrameListData
));
440 av_log(avctx
, AV_LOG_ERROR
,
441 "Frame queue element alloc failed\n");
442 return AVERROR(ENOMEM
);
444 cx_pktcpy(cx_frame
, pkt
);
445 cx_frame
->buf
= av_malloc(cx_frame
->sz
);
447 if (!cx_frame
->buf
) {
448 av_log(avctx
, AV_LOG_ERROR
,
449 "Data buffer alloc (%zu bytes) failed\n",
451 return AVERROR(ENOMEM
);
453 memcpy(cx_frame
->buf
, pkt
->data
.frame
.buf
, pkt
->data
.frame
.sz
);
454 coded_frame_add(&ctx
->coded_frame_list
, cx_frame
);
457 case VPX_CODEC_STATS_PKT
: {
458 struct vpx_fixed_buf
*stats
= &ctx
->twopass_stats
;
459 stats
->buf
= av_realloc(stats
->buf
,
460 stats
->sz
+ pkt
->data
.twopass_stats
.sz
);
462 av_log(avctx
, AV_LOG_ERROR
, "Stat buffer realloc failed\n");
463 return AVERROR(ENOMEM
);
465 memcpy((uint8_t*)stats
->buf
+ stats
->sz
,
466 pkt
->data
.twopass_stats
.buf
, pkt
->data
.twopass_stats
.sz
);
467 stats
->sz
+= pkt
->data
.twopass_stats
.sz
;
470 case VPX_CODEC_PSNR_PKT
: //FIXME add support for CODEC_FLAG_PSNR
471 case VPX_CODEC_CUSTOM_PKT
:
472 //ignore unsupported/unrecognized packet types
480 static int vp8_encode(AVCodecContext
*avctx
, AVPacket
*pkt
,
481 const AVFrame
*frame
, int *got_packet
)
483 VP8Context
*ctx
= avctx
->priv_data
;
484 struct vpx_image
*rawimg
= NULL
;
485 int64_t timestamp
= 0;
489 rawimg
= &ctx
->rawimg
;
490 rawimg
->planes
[VPX_PLANE_Y
] = frame
->data
[0];
491 rawimg
->planes
[VPX_PLANE_U
] = frame
->data
[1];
492 rawimg
->planes
[VPX_PLANE_V
] = frame
->data
[2];
493 rawimg
->stride
[VPX_PLANE_Y
] = frame
->linesize
[0];
494 rawimg
->stride
[VPX_PLANE_U
] = frame
->linesize
[1];
495 rawimg
->stride
[VPX_PLANE_V
] = frame
->linesize
[2];
496 timestamp
= frame
->pts
;
499 res
= vpx_codec_encode(&ctx
->encoder
, rawimg
, timestamp
,
500 avctx
->ticks_per_frame
, 0, ctx
->deadline
);
501 if (res
!= VPX_CODEC_OK
) {
502 log_encoder_error(avctx
, "Error encoding frame");
503 return AVERROR_INVALIDDATA
;
505 coded_size
= queue_frames(avctx
, pkt
, avctx
->coded_frame
);
507 if (!frame
&& avctx
->flags
& CODEC_FLAG_PASS1
) {
508 unsigned int b64_size
= AV_BASE64_SIZE(ctx
->twopass_stats
.sz
);
510 avctx
->stats_out
= av_malloc(b64_size
);
511 if (!avctx
->stats_out
) {
512 av_log(avctx
, AV_LOG_ERROR
, "Stat buffer alloc (%d bytes) failed\n",
514 return AVERROR(ENOMEM
);
516 av_base64_encode(avctx
->stats_out
, b64_size
, ctx
->twopass_stats
.buf
,
517 ctx
->twopass_stats
.sz
);
520 *got_packet
= !!coded_size
;
524 #define OFFSET(x) offsetof(VP8Context, x)
525 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
526 static const AVOption options
[] = {
527 { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used
), AV_OPT_TYPE_INT
, {INT_MIN
}, INT_MIN
, INT_MAX
, VE
},
528 { "auto-alt-ref", "Enable use of alternate reference "
529 "frames (2-pass only)", OFFSET(auto_alt_ref
), AV_OPT_TYPE_INT
, {-1}, -1, 1, VE
},
530 { "lag-in-frames", "Number of frames to look ahead for "
531 "alternate reference frame selection", OFFSET(lag_in_frames
), AV_OPT_TYPE_INT
, {-1}, -1, INT_MAX
, VE
},
532 { "arnr-maxframes", "altref noise reduction max frame count", OFFSET(arnr_max_frames
), AV_OPT_TYPE_INT
, {-1}, -1, INT_MAX
, VE
},
533 { "arnr-strength", "altref noise reduction filter strength", OFFSET(arnr_strength
), AV_OPT_TYPE_INT
, {-1}, -1, INT_MAX
, VE
},
534 { "arnr-type", "altref noise reduction filter type", OFFSET(arnr_type
), AV_OPT_TYPE_INT
, {-1}, -1, INT_MAX
, VE
, "arnr_type"},
535 { "backward", NULL
, 0, AV_OPT_TYPE_CONST
, {1}, 0, 0, VE
, "arnr_type" },
536 { "forward", NULL
, 0, AV_OPT_TYPE_CONST
, {2}, 0, 0, VE
, "arnr_type" },
537 { "centered", NULL
, 0, AV_OPT_TYPE_CONST
, {3}, 0, 0, VE
, "arnr_type" },
538 { "deadline", "Time to spend encoding, in microseconds.", OFFSET(deadline
), AV_OPT_TYPE_INT
, {VPX_DL_GOOD_QUALITY
}, INT_MIN
, INT_MAX
, VE
, "quality"},
539 { "best", NULL
, 0, AV_OPT_TYPE_CONST
, {VPX_DL_BEST_QUALITY
}, 0, 0, VE
, "quality"},
540 { "good", NULL
, 0, AV_OPT_TYPE_CONST
, {VPX_DL_GOOD_QUALITY
}, 0, 0, VE
, "quality"},
541 { "realtime", NULL
, 0, AV_OPT_TYPE_CONST
, {VPX_DL_REALTIME
}, 0, 0, VE
, "quality"},
542 { "error-resilient", "Error resilience configuration", OFFSET(error_resilient
), AV_OPT_TYPE_FLAGS
, {0}, INT_MIN
, INT_MAX
, VE
, "er"},
543 #ifdef VPX_ERROR_RESILIENT_DEFAULT
544 { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST
, {VPX_ERROR_RESILIENT_DEFAULT
}, 0, 0, VE
, "er"},
545 { "partitions", "The frame partitions are independently decodable "
546 "by the bool decoder, meaning that partitions can be decoded even "
547 "though earlier partitions have been lost. Note that intra predicition"
548 " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST
, {VPX_ERROR_RESILIENT_PARTITIONS
}, 0, 0, VE
, "er"},
553 static const AVClass
class = {
554 .class_name
= "libvpx encoder",
555 .item_name
= av_default_item_name
,
557 .version
= LIBAVUTIL_VERSION_INT
,
560 static const AVCodecDefault defaults
[] = {
564 { "keyint_min", "-1" },
568 AVCodec ff_libvpx_encoder
= {
570 .type
= AVMEDIA_TYPE_VIDEO
,
572 .priv_data_size
= sizeof(VP8Context
),
574 .encode2
= vp8_encode
,
576 .capabilities
= CODEC_CAP_DELAY
| CODEC_CAP_AUTO_THREADS
,
577 .pix_fmts
= (const enum PixelFormat
[]){ PIX_FMT_YUV420P
, PIX_FMT_NONE
},
578 .long_name
= NULL_IF_CONFIG_SMALL("libvpx VP8"),
579 .priv_class
= &class,
580 .defaults
= defaults
,