Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * Copyright (c) 2010, Google, Inc. | |
3 | * | |
4 | * This file is part of FFmpeg. | |
5 | * | |
6 | * FFmpeg 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 | * FFmpeg 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 FFmpeg; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | */ | |
20 | ||
21 | /** | |
22 | * @file | |
23 | * VP8 encoder support via libvpx | |
24 | */ | |
25 | ||
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 "libavutil/avassert.h" | |
34 | #include "libvpx.h" | |
35 | #include "libavutil/base64.h" | |
36 | #include "libavutil/common.h" | |
37 | #include "libavutil/intreadwrite.h" | |
38 | #include "libavutil/mathematics.h" | |
39 | #include "libavutil/opt.h" | |
40 | ||
41 | /** | |
42 | * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h. | |
43 | * One encoded frame returned from the library. | |
44 | */ | |
45 | struct FrameListData { | |
46 | void *buf; /**< compressed data buffer */ | |
47 | size_t sz; /**< length of compressed data */ | |
48 | void *buf_alpha; | |
49 | size_t sz_alpha; | |
50 | int64_t pts; /**< time stamp to show frame | |
51 | (in timebase units) */ | |
52 | unsigned long duration; /**< duration to show frame | |
53 | (in timebase units) */ | |
54 | uint32_t flags; /**< flags for this frame */ | |
55 | uint64_t sse[4]; | |
56 | int have_sse; /**< true if we have pending sse[] */ | |
57 | uint64_t frame_number; | |
58 | struct FrameListData *next; | |
59 | }; | |
60 | ||
61 | typedef struct VP8EncoderContext { | |
62 | AVClass *class; | |
63 | struct vpx_codec_ctx encoder; | |
64 | struct vpx_image rawimg; | |
65 | struct vpx_codec_ctx encoder_alpha; | |
66 | struct vpx_image rawimg_alpha; | |
67 | uint8_t is_alpha; | |
68 | struct vpx_fixed_buf twopass_stats; | |
69 | int deadline; //i.e., RT/GOOD/BEST | |
70 | uint64_t sse[4]; | |
71 | int have_sse; /**< true if we have pending sse[] */ | |
72 | uint64_t frame_number; | |
73 | struct FrameListData *coded_frame_list; | |
74 | ||
75 | int cpu_used; | |
76 | /** | |
77 | * VP8 specific flags, see VP8F_* below. | |
78 | */ | |
79 | int flags; | |
80 | #define VP8F_ERROR_RESILIENT 0x00000001 ///< Enable measures appropriate for streaming over lossy links | |
81 | #define VP8F_AUTO_ALT_REF 0x00000002 ///< Enable automatic alternate reference frame generation | |
82 | ||
83 | int auto_alt_ref; | |
84 | ||
85 | int arnr_max_frames; | |
86 | int arnr_strength; | |
87 | int arnr_type; | |
88 | ||
89 | int lag_in_frames; | |
90 | int error_resilient; | |
91 | int crf; | |
92 | int max_intra_rate; | |
93 | ||
94 | // VP9-only | |
95 | int lossless; | |
96 | int tile_columns; | |
97 | int tile_rows; | |
98 | int frame_parallel; | |
99 | int aq_mode; | |
100 | } VP8Context; | |
101 | ||
102 | /** String mappings for enum vp8e_enc_control_id */ | |
103 | static const char *const ctlidstr[] = { | |
104 | [VP8E_UPD_ENTROPY] = "VP8E_UPD_ENTROPY", | |
105 | [VP8E_UPD_REFERENCE] = "VP8E_UPD_REFERENCE", | |
106 | [VP8E_USE_REFERENCE] = "VP8E_USE_REFERENCE", | |
107 | [VP8E_SET_ROI_MAP] = "VP8E_SET_ROI_MAP", | |
108 | [VP8E_SET_ACTIVEMAP] = "VP8E_SET_ACTIVEMAP", | |
109 | [VP8E_SET_SCALEMODE] = "VP8E_SET_SCALEMODE", | |
110 | [VP8E_SET_CPUUSED] = "VP8E_SET_CPUUSED", | |
111 | [VP8E_SET_ENABLEAUTOALTREF] = "VP8E_SET_ENABLEAUTOALTREF", | |
112 | [VP8E_SET_NOISE_SENSITIVITY] = "VP8E_SET_NOISE_SENSITIVITY", | |
113 | [VP8E_SET_SHARPNESS] = "VP8E_SET_SHARPNESS", | |
114 | [VP8E_SET_STATIC_THRESHOLD] = "VP8E_SET_STATIC_THRESHOLD", | |
115 | [VP8E_SET_TOKEN_PARTITIONS] = "VP8E_SET_TOKEN_PARTITIONS", | |
116 | [VP8E_GET_LAST_QUANTIZER] = "VP8E_GET_LAST_QUANTIZER", | |
117 | [VP8E_SET_ARNR_MAXFRAMES] = "VP8E_SET_ARNR_MAXFRAMES", | |
118 | [VP8E_SET_ARNR_STRENGTH] = "VP8E_SET_ARNR_STRENGTH", | |
119 | [VP8E_SET_ARNR_TYPE] = "VP8E_SET_ARNR_TYPE", | |
120 | [VP8E_SET_CQ_LEVEL] = "VP8E_SET_CQ_LEVEL", | |
121 | [VP8E_SET_MAX_INTRA_BITRATE_PCT] = "VP8E_SET_MAX_INTRA_BITRATE_PCT", | |
122 | #if CONFIG_LIBVPX_VP9_ENCODER | |
123 | [VP9E_SET_LOSSLESS] = "VP9E_SET_LOSSLESS", | |
124 | [VP9E_SET_TILE_COLUMNS] = "VP9E_SET_TILE_COLUMNS", | |
125 | [VP9E_SET_TILE_ROWS] = "VP9E_SET_TILE_ROWS", | |
126 | [VP9E_SET_FRAME_PARALLEL_DECODING] = "VP9E_SET_FRAME_PARALLEL_DECODING", | |
127 | [VP9E_SET_AQ_MODE] = "VP9E_SET_AQ_MODE", | |
128 | #endif | |
129 | }; | |
130 | ||
131 | static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) | |
132 | { | |
133 | VP8Context *ctx = avctx->priv_data; | |
134 | const char *error = vpx_codec_error(&ctx->encoder); | |
135 | const char *detail = vpx_codec_error_detail(&ctx->encoder); | |
136 | ||
137 | av_log(avctx, AV_LOG_ERROR, "%s: %s\n", desc, error); | |
138 | if (detail) | |
139 | av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", detail); | |
140 | } | |
141 | ||
142 | static av_cold void dump_enc_cfg(AVCodecContext *avctx, | |
143 | const struct vpx_codec_enc_cfg *cfg) | |
144 | { | |
145 | int width = -30; | |
146 | int level = AV_LOG_DEBUG; | |
147 | ||
148 | av_log(avctx, level, "vpx_codec_enc_cfg\n"); | |
149 | av_log(avctx, level, "generic settings\n" | |
150 | " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n" | |
151 | " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n", | |
152 | width, "g_usage:", cfg->g_usage, | |
153 | width, "g_threads:", cfg->g_threads, | |
154 | width, "g_profile:", cfg->g_profile, | |
155 | width, "g_w:", cfg->g_w, | |
156 | width, "g_h:", cfg->g_h, | |
157 | width, "g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den, | |
158 | width, "g_error_resilient:", cfg->g_error_resilient, | |
159 | width, "g_pass:", cfg->g_pass, | |
160 | width, "g_lag_in_frames:", cfg->g_lag_in_frames); | |
161 | av_log(avctx, level, "rate control settings\n" | |
162 | " %*s%u\n %*s%u\n %*s%u\n %*s%u\n" | |
163 | " %*s%d\n %*s%p(%"SIZE_SPECIFIER")\n %*s%u\n", | |
164 | width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh, | |
165 | width, "rc_resize_allowed:", cfg->rc_resize_allowed, | |
166 | width, "rc_resize_up_thresh:", cfg->rc_resize_up_thresh, | |
167 | width, "rc_resize_down_thresh:", cfg->rc_resize_down_thresh, | |
168 | width, "rc_end_usage:", cfg->rc_end_usage, | |
169 | width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz, | |
170 | width, "rc_target_bitrate:", cfg->rc_target_bitrate); | |
171 | av_log(avctx, level, "quantizer settings\n" | |
172 | " %*s%u\n %*s%u\n", | |
173 | width, "rc_min_quantizer:", cfg->rc_min_quantizer, | |
174 | width, "rc_max_quantizer:", cfg->rc_max_quantizer); | |
175 | av_log(avctx, level, "bitrate tolerance\n" | |
176 | " %*s%u\n %*s%u\n", | |
177 | width, "rc_undershoot_pct:", cfg->rc_undershoot_pct, | |
178 | width, "rc_overshoot_pct:", cfg->rc_overshoot_pct); | |
179 | av_log(avctx, level, "decoder buffer model\n" | |
180 | " %*s%u\n %*s%u\n %*s%u\n", | |
181 | width, "rc_buf_sz:", cfg->rc_buf_sz, | |
182 | width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz, | |
183 | width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz); | |
184 | av_log(avctx, level, "2 pass rate control settings\n" | |
185 | " %*s%u\n %*s%u\n %*s%u\n", | |
186 | width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct, | |
187 | width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct, | |
188 | width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct); | |
189 | av_log(avctx, level, "keyframing settings\n" | |
190 | " %*s%d\n %*s%u\n %*s%u\n", | |
191 | width, "kf_mode:", cfg->kf_mode, | |
192 | width, "kf_min_dist:", cfg->kf_min_dist, | |
193 | width, "kf_max_dist:", cfg->kf_max_dist); | |
194 | av_log(avctx, level, "\n"); | |
195 | } | |
196 | ||
197 | static void coded_frame_add(void *list, struct FrameListData *cx_frame) | |
198 | { | |
199 | struct FrameListData **p = list; | |
200 | ||
201 | while (*p) | |
202 | p = &(*p)->next; | |
203 | *p = cx_frame; | |
204 | cx_frame->next = NULL; | |
205 | } | |
206 | ||
207 | static av_cold void free_coded_frame(struct FrameListData *cx_frame) | |
208 | { | |
209 | av_freep(&cx_frame->buf); | |
210 | if (cx_frame->buf_alpha) | |
211 | av_freep(&cx_frame->buf_alpha); | |
212 | av_freep(&cx_frame); | |
213 | } | |
214 | ||
215 | static av_cold void free_frame_list(struct FrameListData *list) | |
216 | { | |
217 | struct FrameListData *p = list; | |
218 | ||
219 | while (p) { | |
220 | list = list->next; | |
221 | free_coded_frame(p); | |
222 | p = list; | |
223 | } | |
224 | } | |
225 | ||
226 | static av_cold int codecctl_int(AVCodecContext *avctx, | |
227 | enum vp8e_enc_control_id id, int val) | |
228 | { | |
229 | VP8Context *ctx = avctx->priv_data; | |
230 | char buf[80]; | |
231 | int width = -30; | |
232 | int res; | |
233 | ||
234 | snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); | |
235 | av_log(avctx, AV_LOG_DEBUG, " %*s%d\n", width, buf, val); | |
236 | ||
237 | res = vpx_codec_control(&ctx->encoder, id, val); | |
238 | if (res != VPX_CODEC_OK) { | |
239 | snprintf(buf, sizeof(buf), "Failed to set %s codec control", | |
240 | ctlidstr[id]); | |
241 | log_encoder_error(avctx, buf); | |
242 | } | |
243 | ||
244 | return res == VPX_CODEC_OK ? 0 : AVERROR(EINVAL); | |
245 | } | |
246 | ||
247 | static av_cold int vp8_free(AVCodecContext *avctx) | |
248 | { | |
249 | VP8Context *ctx = avctx->priv_data; | |
250 | ||
251 | vpx_codec_destroy(&ctx->encoder); | |
252 | if (ctx->is_alpha) | |
253 | vpx_codec_destroy(&ctx->encoder_alpha); | |
254 | av_freep(&ctx->twopass_stats.buf); | |
255 | av_freep(&avctx->coded_frame); | |
256 | av_freep(&avctx->stats_out); | |
257 | free_frame_list(ctx->coded_frame_list); | |
258 | return 0; | |
259 | } | |
260 | ||
261 | static av_cold int vpx_init(AVCodecContext *avctx, | |
262 | const struct vpx_codec_iface *iface) | |
263 | { | |
264 | VP8Context *ctx = avctx->priv_data; | |
265 | struct vpx_codec_enc_cfg enccfg; | |
266 | struct vpx_codec_enc_cfg enccfg_alpha; | |
267 | vpx_codec_flags_t flags = (avctx->flags & CODEC_FLAG_PSNR) ? VPX_CODEC_USE_PSNR : 0; | |
268 | int res; | |
269 | ||
270 | av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); | |
271 | av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); | |
272 | ||
273 | if (avctx->pix_fmt == AV_PIX_FMT_YUVA420P) | |
274 | ctx->is_alpha = 1; | |
275 | ||
276 | if ((res = vpx_codec_enc_config_default(iface, &enccfg, 0)) != VPX_CODEC_OK) { | |
277 | av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n", | |
278 | vpx_codec_err_to_string(res)); | |
279 | return AVERROR(EINVAL); | |
280 | } | |
281 | ||
282 | if(!avctx->bit_rate) | |
283 | if(avctx->rc_max_rate || avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) { | |
284 | av_log( avctx, AV_LOG_ERROR, "Rate control parameters set without a bitrate\n"); | |
285 | return AVERROR(EINVAL); | |
286 | } | |
287 | ||
288 | dump_enc_cfg(avctx, &enccfg); | |
289 | ||
290 | enccfg.g_w = avctx->width; | |
291 | enccfg.g_h = avctx->height; | |
292 | enccfg.g_timebase.num = avctx->time_base.num; | |
293 | enccfg.g_timebase.den = avctx->time_base.den; | |
294 | enccfg.g_threads = avctx->thread_count; | |
295 | enccfg.g_lag_in_frames= ctx->lag_in_frames; | |
296 | ||
297 | if (avctx->flags & CODEC_FLAG_PASS1) | |
298 | enccfg.g_pass = VPX_RC_FIRST_PASS; | |
299 | else if (avctx->flags & CODEC_FLAG_PASS2) | |
300 | enccfg.g_pass = VPX_RC_LAST_PASS; | |
301 | else | |
302 | enccfg.g_pass = VPX_RC_ONE_PASS; | |
303 | ||
304 | if (avctx->rc_min_rate == avctx->rc_max_rate && | |
305 | avctx->rc_min_rate == avctx->bit_rate && avctx->bit_rate) { | |
306 | enccfg.rc_end_usage = VPX_CBR; | |
307 | } else if (ctx->crf >= 0) { | |
308 | enccfg.rc_end_usage = VPX_CQ; | |
309 | #if CONFIG_LIBVPX_VP9_ENCODER | |
310 | if (!avctx->bit_rate && avctx->codec_id == AV_CODEC_ID_VP9) | |
311 | enccfg.rc_end_usage = VPX_Q; | |
312 | #endif | |
313 | } | |
314 | ||
315 | if (avctx->bit_rate) { | |
316 | enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, | |
317 | AV_ROUND_NEAR_INF); | |
318 | #if CONFIG_LIBVPX_VP9_ENCODER | |
319 | } else if (enccfg.rc_end_usage == VPX_Q) { | |
320 | #endif | |
321 | } else { | |
322 | if (enccfg.rc_end_usage == VPX_CQ) { | |
323 | enccfg.rc_target_bitrate = 1000000; | |
324 | } else { | |
325 | avctx->bit_rate = enccfg.rc_target_bitrate * 1000; | |
326 | av_log(avctx, AV_LOG_WARNING, | |
327 | "Neither bitrate nor constrained quality specified, using default bitrate of %dkbit/sec\n", | |
328 | enccfg.rc_target_bitrate); | |
329 | } | |
330 | } | |
331 | ||
332 | if (avctx->qmin >= 0) | |
333 | enccfg.rc_min_quantizer = avctx->qmin; | |
334 | if (avctx->qmax >= 0) | |
335 | enccfg.rc_max_quantizer = avctx->qmax; | |
336 | ||
337 | if (enccfg.rc_end_usage == VPX_CQ | |
338 | #if CONFIG_LIBVPX_VP9_ENCODER | |
339 | || enccfg.rc_end_usage == VPX_Q | |
340 | #endif | |
341 | ) { | |
342 | if (ctx->crf < enccfg.rc_min_quantizer || ctx->crf > enccfg.rc_max_quantizer) { | |
343 | av_log(avctx, AV_LOG_ERROR, | |
344 | "CQ level %d must be between minimum and maximum quantizer value (%d-%d)\n", | |
345 | ctx->crf, enccfg.rc_min_quantizer, enccfg.rc_max_quantizer); | |
346 | return AVERROR(EINVAL); | |
347 | } | |
348 | } | |
349 | ||
350 | enccfg.rc_dropframe_thresh = avctx->frame_skip_threshold; | |
351 | ||
352 | //0-100 (0 => CBR, 100 => VBR) | |
353 | enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100); | |
354 | if (avctx->bit_rate) | |
355 | enccfg.rc_2pass_vbr_minsection_pct = | |
356 | avctx->rc_min_rate * 100LL / avctx->bit_rate; | |
357 | if (avctx->rc_max_rate) | |
358 | enccfg.rc_2pass_vbr_maxsection_pct = | |
359 | avctx->rc_max_rate * 100LL / avctx->bit_rate; | |
360 | ||
361 | if (avctx->rc_buffer_size) | |
362 | enccfg.rc_buf_sz = | |
363 | avctx->rc_buffer_size * 1000LL / avctx->bit_rate; | |
364 | if (avctx->rc_initial_buffer_occupancy) | |
365 | enccfg.rc_buf_initial_sz = | |
366 | avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate; | |
367 | enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6; | |
368 | enccfg.rc_undershoot_pct = round(avctx->rc_buffer_aggressivity * 100); | |
369 | ||
370 | //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO | |
371 | if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size) | |
372 | enccfg.kf_min_dist = avctx->keyint_min; | |
373 | if (avctx->gop_size >= 0) | |
374 | enccfg.kf_max_dist = avctx->gop_size; | |
375 | ||
376 | if (enccfg.g_pass == VPX_RC_FIRST_PASS) | |
377 | enccfg.g_lag_in_frames = 0; | |
378 | else if (enccfg.g_pass == VPX_RC_LAST_PASS) { | |
379 | int decode_size; | |
380 | ||
381 | if (!avctx->stats_in) { | |
382 | av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n"); | |
383 | return AVERROR_INVALIDDATA; | |
384 | } | |
385 | ||
386 | ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4; | |
387 | ctx->twopass_stats.buf = av_malloc(ctx->twopass_stats.sz); | |
388 | if (!ctx->twopass_stats.buf) { | |
389 | av_log(avctx, AV_LOG_ERROR, | |
390 | "Stat buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n", | |
391 | ctx->twopass_stats.sz); | |
392 | return AVERROR(ENOMEM); | |
393 | } | |
394 | decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in, | |
395 | ctx->twopass_stats.sz); | |
396 | if (decode_size < 0) { | |
397 | av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n"); | |
398 | return AVERROR_INVALIDDATA; | |
399 | } | |
400 | ||
401 | ctx->twopass_stats.sz = decode_size; | |
402 | enccfg.rc_twopass_stats_in = ctx->twopass_stats; | |
403 | } | |
404 | ||
405 | /* 0-3: For non-zero values the encoder increasingly optimizes for reduced | |
406 | complexity playback on low powered devices at the expense of encode | |
407 | quality. */ | |
408 | if (avctx->profile != FF_PROFILE_UNKNOWN) | |
409 | enccfg.g_profile = avctx->profile; | |
410 | ||
411 | enccfg.g_error_resilient = ctx->error_resilient || ctx->flags & VP8F_ERROR_RESILIENT; | |
412 | ||
413 | dump_enc_cfg(avctx, &enccfg); | |
414 | /* Construct Encoder Context */ | |
415 | res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, flags); | |
416 | if (res != VPX_CODEC_OK) { | |
417 | log_encoder_error(avctx, "Failed to initialize encoder"); | |
418 | return AVERROR(EINVAL); | |
419 | } | |
420 | ||
421 | if (ctx->is_alpha) { | |
422 | enccfg_alpha = enccfg; | |
423 | res = vpx_codec_enc_init(&ctx->encoder_alpha, iface, &enccfg_alpha, flags); | |
424 | if (res != VPX_CODEC_OK) { | |
425 | log_encoder_error(avctx, "Failed to initialize alpha encoder"); | |
426 | return AVERROR(EINVAL); | |
427 | } | |
428 | } | |
429 | ||
430 | //codec control failures are currently treated only as warnings | |
431 | av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n"); | |
432 | codecctl_int(avctx, VP8E_SET_CPUUSED, ctx->cpu_used); | |
433 | if (ctx->flags & VP8F_AUTO_ALT_REF) | |
434 | ctx->auto_alt_ref = 1; | |
435 | if (ctx->auto_alt_ref >= 0) | |
436 | codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF, ctx->auto_alt_ref); | |
437 | if (ctx->arnr_max_frames >= 0) | |
438 | codecctl_int(avctx, VP8E_SET_ARNR_MAXFRAMES, ctx->arnr_max_frames); | |
439 | if (ctx->arnr_strength >= 0) | |
440 | codecctl_int(avctx, VP8E_SET_ARNR_STRENGTH, ctx->arnr_strength); | |
441 | if (ctx->arnr_type >= 0) | |
442 | codecctl_int(avctx, VP8E_SET_ARNR_TYPE, ctx->arnr_type); | |
443 | codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction); | |
444 | if (avctx->codec_id == AV_CODEC_ID_VP8) | |
445 | codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices)); | |
446 | codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, avctx->mb_threshold); | |
447 | if (ctx->crf >= 0) | |
448 | codecctl_int(avctx, VP8E_SET_CQ_LEVEL, ctx->crf); | |
449 | if (ctx->max_intra_rate >= 0) | |
450 | codecctl_int(avctx, VP8E_SET_MAX_INTRA_BITRATE_PCT, ctx->max_intra_rate); | |
451 | ||
452 | #if CONFIG_LIBVPX_VP9_ENCODER | |
453 | if (avctx->codec_id == AV_CODEC_ID_VP9) { | |
454 | if (ctx->lossless >= 0) | |
455 | codecctl_int(avctx, VP9E_SET_LOSSLESS, ctx->lossless); | |
456 | if (ctx->tile_columns >= 0) | |
457 | codecctl_int(avctx, VP9E_SET_TILE_COLUMNS, ctx->tile_columns); | |
458 | if (ctx->tile_rows >= 0) | |
459 | codecctl_int(avctx, VP9E_SET_TILE_ROWS, ctx->tile_rows); | |
460 | if (ctx->frame_parallel >= 0) | |
461 | codecctl_int(avctx, VP9E_SET_FRAME_PARALLEL_DECODING, ctx->frame_parallel); | |
462 | if (ctx->aq_mode >= 0) | |
463 | codecctl_int(avctx, VP9E_SET_AQ_MODE, ctx->aq_mode); | |
464 | } | |
465 | #endif | |
466 | ||
467 | av_log(avctx, AV_LOG_DEBUG, "Using deadline: %d\n", ctx->deadline); | |
468 | ||
469 | //provide dummy value to initialize wrapper, values will be updated each _encode() | |
470 | vpx_img_wrap(&ctx->rawimg, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1, | |
471 | (unsigned char*)1); | |
472 | ||
473 | if (ctx->is_alpha) | |
474 | vpx_img_wrap(&ctx->rawimg_alpha, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1, | |
475 | (unsigned char*)1); | |
476 | ||
477 | avctx->coded_frame = av_frame_alloc(); | |
478 | if (!avctx->coded_frame) { | |
479 | av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n"); | |
480 | vp8_free(avctx); | |
481 | return AVERROR(ENOMEM); | |
482 | } | |
483 | return 0; | |
484 | } | |
485 | ||
486 | static inline void cx_pktcpy(struct FrameListData *dst, | |
487 | const struct vpx_codec_cx_pkt *src, | |
488 | const struct vpx_codec_cx_pkt *src_alpha, | |
489 | VP8Context *ctx) | |
490 | { | |
491 | dst->pts = src->data.frame.pts; | |
492 | dst->duration = src->data.frame.duration; | |
493 | dst->flags = src->data.frame.flags; | |
494 | dst->sz = src->data.frame.sz; | |
495 | dst->buf = src->data.frame.buf; | |
496 | dst->have_sse = 0; | |
497 | /* For alt-ref frame, don't store PSNR or increment frame_number */ | |
498 | if (!(dst->flags & VPX_FRAME_IS_INVISIBLE)) { | |
499 | dst->frame_number = ++ctx->frame_number; | |
500 | dst->have_sse = ctx->have_sse; | |
501 | if (ctx->have_sse) { | |
502 | /* associate last-seen SSE to the frame. */ | |
503 | /* Transfers ownership from ctx to dst. */ | |
504 | /* WARNING! This makes the assumption that PSNR_PKT comes | |
505 | just before the frame it refers to! */ | |
506 | memcpy(dst->sse, ctx->sse, sizeof(dst->sse)); | |
507 | ctx->have_sse = 0; | |
508 | } | |
509 | } else { | |
510 | dst->frame_number = -1; /* sanity marker */ | |
511 | } | |
512 | if (src_alpha) { | |
513 | dst->buf_alpha = src_alpha->data.frame.buf; | |
514 | dst->sz_alpha = src_alpha->data.frame.sz; | |
515 | } | |
516 | else { | |
517 | dst->buf_alpha = NULL; | |
518 | dst->sz_alpha = 0; | |
519 | } | |
520 | } | |
521 | ||
522 | /** | |
523 | * Store coded frame information in format suitable for return from encode2(). | |
524 | * | |
525 | * Write information from @a cx_frame to @a pkt | |
526 | * @return packet data size on success | |
527 | * @return a negative AVERROR on error | |
528 | */ | |
529 | static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, | |
530 | AVPacket *pkt, AVFrame *coded_frame) | |
531 | { | |
532 | int ret = ff_alloc_packet2(avctx, pkt, cx_frame->sz); | |
533 | uint8_t *side_data; | |
534 | if (ret >= 0) { | |
535 | memcpy(pkt->data, cx_frame->buf, pkt->size); | |
536 | pkt->pts = pkt->dts = cx_frame->pts; | |
537 | coded_frame->pts = cx_frame->pts; | |
538 | coded_frame->key_frame = !!(cx_frame->flags & VPX_FRAME_IS_KEY); | |
539 | ||
540 | if (coded_frame->key_frame) { | |
541 | coded_frame->pict_type = AV_PICTURE_TYPE_I; | |
542 | pkt->flags |= AV_PKT_FLAG_KEY; | |
543 | } else | |
544 | coded_frame->pict_type = AV_PICTURE_TYPE_P; | |
545 | ||
546 | if (cx_frame->have_sse) { | |
547 | int i; | |
548 | /* Beware of the Y/U/V/all order! */ | |
549 | coded_frame->error[0] = cx_frame->sse[1]; | |
550 | coded_frame->error[1] = cx_frame->sse[2]; | |
551 | coded_frame->error[2] = cx_frame->sse[3]; | |
552 | coded_frame->error[3] = 0; // alpha | |
553 | for (i = 0; i < 4; ++i) { | |
554 | avctx->error[i] += coded_frame->error[i]; | |
555 | } | |
556 | cx_frame->have_sse = 0; | |
557 | } | |
558 | if (cx_frame->sz_alpha > 0) { | |
559 | side_data = av_packet_new_side_data(pkt, | |
560 | AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, | |
561 | cx_frame->sz_alpha + 8); | |
562 | if(!side_data) { | |
563 | av_free_packet(pkt); | |
564 | av_free(pkt); | |
565 | return AVERROR(ENOMEM); | |
566 | } | |
567 | AV_WB64(side_data, 1); | |
568 | memcpy(side_data + 8, cx_frame->buf_alpha, cx_frame->sz_alpha); | |
569 | } | |
570 | } else { | |
571 | return ret; | |
572 | } | |
573 | return pkt->size; | |
574 | } | |
575 | ||
576 | /** | |
577 | * Queue multiple output frames from the encoder, returning the front-most. | |
578 | * In cases where vpx_codec_get_cx_data() returns more than 1 frame append | |
579 | * the frame queue. Return the head frame if available. | |
580 | * @return Stored frame size | |
581 | * @return AVERROR(EINVAL) on output size error | |
582 | * @return AVERROR(ENOMEM) on coded frame queue data allocation error | |
583 | */ | |
584 | static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, | |
585 | AVFrame *coded_frame) | |
586 | { | |
587 | VP8Context *ctx = avctx->priv_data; | |
588 | const struct vpx_codec_cx_pkt *pkt; | |
589 | const struct vpx_codec_cx_pkt *pkt_alpha = NULL; | |
590 | const void *iter = NULL; | |
591 | const void *iter_alpha = NULL; | |
592 | int size = 0; | |
593 | ||
594 | if (ctx->coded_frame_list) { | |
595 | struct FrameListData *cx_frame = ctx->coded_frame_list; | |
596 | /* return the leading frame if we've already begun queueing */ | |
597 | size = storeframe(avctx, cx_frame, pkt_out, coded_frame); | |
598 | if (size < 0) | |
599 | return size; | |
600 | ctx->coded_frame_list = cx_frame->next; | |
601 | free_coded_frame(cx_frame); | |
602 | } | |
603 | ||
604 | /* consume all available output from the encoder before returning. buffers | |
605 | are only good through the next vpx_codec call */ | |
606 | while ((pkt = vpx_codec_get_cx_data(&ctx->encoder, &iter)) && | |
607 | (!ctx->is_alpha || | |
608 | (ctx->is_alpha && (pkt_alpha = vpx_codec_get_cx_data(&ctx->encoder_alpha, &iter_alpha))))) { | |
609 | switch (pkt->kind) { | |
610 | case VPX_CODEC_CX_FRAME_PKT: | |
611 | if (!size) { | |
612 | struct FrameListData cx_frame; | |
613 | ||
614 | /* avoid storing the frame when the list is empty and we haven't yet | |
615 | provided a frame for output */ | |
616 | av_assert0(!ctx->coded_frame_list); | |
617 | cx_pktcpy(&cx_frame, pkt, pkt_alpha, ctx); | |
618 | size = storeframe(avctx, &cx_frame, pkt_out, coded_frame); | |
619 | if (size < 0) | |
620 | return size; | |
621 | } else { | |
622 | struct FrameListData *cx_frame = | |
623 | av_malloc(sizeof(struct FrameListData)); | |
624 | ||
625 | if (!cx_frame) { | |
626 | av_log(avctx, AV_LOG_ERROR, | |
627 | "Frame queue element alloc failed\n"); | |
628 | return AVERROR(ENOMEM); | |
629 | } | |
630 | cx_pktcpy(cx_frame, pkt, pkt_alpha, ctx); | |
631 | cx_frame->buf = av_malloc(cx_frame->sz); | |
632 | ||
633 | if (!cx_frame->buf) { | |
634 | av_log(avctx, AV_LOG_ERROR, | |
635 | "Data buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n", | |
636 | cx_frame->sz); | |
637 | av_free(cx_frame); | |
638 | return AVERROR(ENOMEM); | |
639 | } | |
640 | memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz); | |
641 | if (ctx->is_alpha) { | |
642 | cx_frame->buf_alpha = av_malloc(cx_frame->sz_alpha); | |
643 | if (!cx_frame->buf_alpha) { | |
644 | av_log(avctx, AV_LOG_ERROR, | |
645 | "Data buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n", | |
646 | cx_frame->sz_alpha); | |
647 | av_free(cx_frame); | |
648 | return AVERROR(ENOMEM); | |
649 | } | |
650 | memcpy(cx_frame->buf_alpha, pkt_alpha->data.frame.buf, pkt_alpha->data.frame.sz); | |
651 | } | |
652 | coded_frame_add(&ctx->coded_frame_list, cx_frame); | |
653 | } | |
654 | break; | |
655 | case VPX_CODEC_STATS_PKT: { | |
656 | struct vpx_fixed_buf *stats = &ctx->twopass_stats; | |
657 | int err; | |
658 | if ((err = av_reallocp(&stats->buf, | |
659 | stats->sz + | |
660 | pkt->data.twopass_stats.sz)) < 0) { | |
661 | stats->sz = 0; | |
662 | av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n"); | |
663 | return err; | |
664 | } | |
665 | memcpy((uint8_t*)stats->buf + stats->sz, | |
666 | pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz); | |
667 | stats->sz += pkt->data.twopass_stats.sz; | |
668 | break; | |
669 | } | |
670 | case VPX_CODEC_PSNR_PKT: | |
671 | av_assert0(!ctx->have_sse); | |
672 | ctx->sse[0] = pkt->data.psnr.sse[0]; | |
673 | ctx->sse[1] = pkt->data.psnr.sse[1]; | |
674 | ctx->sse[2] = pkt->data.psnr.sse[2]; | |
675 | ctx->sse[3] = pkt->data.psnr.sse[3]; | |
676 | ctx->have_sse = 1; | |
677 | break; | |
678 | case VPX_CODEC_CUSTOM_PKT: | |
679 | //ignore unsupported/unrecognized packet types | |
680 | break; | |
681 | } | |
682 | } | |
683 | ||
684 | return size; | |
685 | } | |
686 | ||
687 | static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt, | |
688 | const AVFrame *frame, int *got_packet) | |
689 | { | |
690 | VP8Context *ctx = avctx->priv_data; | |
691 | struct vpx_image *rawimg = NULL; | |
692 | struct vpx_image *rawimg_alpha = NULL; | |
693 | int64_t timestamp = 0; | |
694 | int res, coded_size; | |
695 | vpx_enc_frame_flags_t flags = 0; | |
696 | ||
697 | if (frame) { | |
698 | rawimg = &ctx->rawimg; | |
699 | rawimg->planes[VPX_PLANE_Y] = frame->data[0]; | |
700 | rawimg->planes[VPX_PLANE_U] = frame->data[1]; | |
701 | rawimg->planes[VPX_PLANE_V] = frame->data[2]; | |
702 | rawimg->stride[VPX_PLANE_Y] = frame->linesize[0]; | |
703 | rawimg->stride[VPX_PLANE_U] = frame->linesize[1]; | |
704 | rawimg->stride[VPX_PLANE_V] = frame->linesize[2]; | |
705 | if (ctx->is_alpha) { | |
706 | uint8_t *u_plane, *v_plane; | |
707 | rawimg_alpha = &ctx->rawimg_alpha; | |
708 | rawimg_alpha->planes[VPX_PLANE_Y] = frame->data[3]; | |
709 | u_plane = av_malloc(frame->linesize[1] * frame->height); | |
710 | memset(u_plane, 0x80, frame->linesize[1] * frame->height); | |
711 | rawimg_alpha->planes[VPX_PLANE_U] = u_plane; | |
712 | v_plane = av_malloc(frame->linesize[2] * frame->height); | |
713 | memset(v_plane, 0x80, frame->linesize[2] * frame->height); | |
714 | rawimg_alpha->planes[VPX_PLANE_V] = v_plane; | |
715 | rawimg_alpha->stride[VPX_PLANE_Y] = frame->linesize[0]; | |
716 | rawimg_alpha->stride[VPX_PLANE_U] = frame->linesize[1]; | |
717 | rawimg_alpha->stride[VPX_PLANE_V] = frame->linesize[2]; | |
718 | } | |
719 | timestamp = frame->pts; | |
720 | if (frame->pict_type == AV_PICTURE_TYPE_I) | |
721 | flags |= VPX_EFLAG_FORCE_KF; | |
722 | } | |
723 | ||
724 | res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp, | |
725 | avctx->ticks_per_frame, flags, ctx->deadline); | |
726 | if (res != VPX_CODEC_OK) { | |
727 | log_encoder_error(avctx, "Error encoding frame"); | |
728 | return AVERROR_INVALIDDATA; | |
729 | } | |
730 | ||
731 | if (ctx->is_alpha) { | |
732 | res = vpx_codec_encode(&ctx->encoder_alpha, rawimg_alpha, timestamp, | |
733 | avctx->ticks_per_frame, flags, ctx->deadline); | |
734 | if (res != VPX_CODEC_OK) { | |
735 | log_encoder_error(avctx, "Error encoding alpha frame"); | |
736 | return AVERROR_INVALIDDATA; | |
737 | } | |
738 | } | |
739 | ||
740 | coded_size = queue_frames(avctx, pkt, avctx->coded_frame); | |
741 | ||
742 | if (!frame && avctx->flags & CODEC_FLAG_PASS1) { | |
743 | unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz); | |
744 | ||
745 | avctx->stats_out = av_malloc(b64_size); | |
746 | if (!avctx->stats_out) { | |
747 | av_log(avctx, AV_LOG_ERROR, "Stat buffer alloc (%d bytes) failed\n", | |
748 | b64_size); | |
749 | return AVERROR(ENOMEM); | |
750 | } | |
751 | av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, | |
752 | ctx->twopass_stats.sz); | |
753 | } | |
754 | ||
755 | if (rawimg_alpha) { | |
756 | av_free(rawimg_alpha->planes[VPX_PLANE_U]); | |
757 | av_free(rawimg_alpha->planes[VPX_PLANE_V]); | |
758 | } | |
759 | ||
760 | *got_packet = !!coded_size; | |
761 | return 0; | |
762 | } | |
763 | ||
764 | #define OFFSET(x) offsetof(VP8Context, x) | |
765 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM | |
766 | ||
767 | #ifndef VPX_ERROR_RESILIENT_DEFAULT | |
768 | #define VPX_ERROR_RESILIENT_DEFAULT 1 | |
769 | #define VPX_ERROR_RESILIENT_PARTITIONS 2 | |
770 | #endif | |
771 | ||
772 | #define COMMON_OPTIONS \ | |
773 | { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE}, \ | |
774 | { "auto-alt-ref", "Enable use of alternate reference " \ | |
775 | "frames (2-pass only)", OFFSET(auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE}, \ | |
776 | { "lag-in-frames", "Number of frames to look ahead for " \ | |
777 | "alternate reference frame selection", OFFSET(lag_in_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, \ | |
778 | { "arnr-maxframes", "altref noise reduction max frame count", OFFSET(arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, \ | |
779 | { "arnr-strength", "altref noise reduction filter strength", OFFSET(arnr_strength), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, \ | |
780 | { "arnr-type", "altref noise reduction filter type", OFFSET(arnr_type), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, "arnr_type"}, \ | |
781 | { "backward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE, "arnr_type" }, \ | |
782 | { "forward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "arnr_type" }, \ | |
783 | { "centered", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE, "arnr_type" }, \ | |
784 | { "deadline", "Time to spend encoding, in microseconds.", OFFSET(deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"}, \ | |
785 | { "best", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_BEST_QUALITY}, 0, 0, VE, "quality"}, \ | |
786 | { "good", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_GOOD_QUALITY}, 0, 0, VE, "quality"}, \ | |
787 | { "realtime", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_REALTIME}, 0, 0, VE, "quality"}, \ | |
788 | { "error-resilient", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"}, \ | |
789 | { "max-intra-rate", "Maximum I-frame bitrate (pct) 0=unlimited", OFFSET(max_intra_rate), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, \ | |
790 | { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"}, \ | |
791 | { "partitions", "The frame partitions are independently decodable " \ | |
792 | "by the bool decoder, meaning that partitions can be decoded even " \ | |
793 | "though earlier partitions have been lost. Note that intra predicition" \ | |
794 | " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"}, \ | |
795 | { "crf", "Select the quality for constant quality mode", offsetof(VP8Context, crf), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, VE }, \ | |
796 | ||
797 | #define LEGACY_OPTIONS \ | |
798 | {"speed", "", offsetof(VP8Context, cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE}, \ | |
799 | {"quality", "", offsetof(VP8Context, deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"}, \ | |
800 | {"vp8flags", "", offsetof(VP8Context, flags), FF_OPT_TYPE_FLAGS, {.i64 = 0}, 0, UINT_MAX, VE, "flags"}, \ | |
801 | {"error_resilient", "enable error resilience", 0, FF_OPT_TYPE_CONST, {.dbl = VP8F_ERROR_RESILIENT}, INT_MIN, INT_MAX, VE, "flags"}, \ | |
802 | {"altref", "enable use of alternate reference frames (VP8/2-pass only)", 0, FF_OPT_TYPE_CONST, {.dbl = VP8F_AUTO_ALT_REF}, INT_MIN, INT_MAX, VE, "flags"}, \ | |
803 | {"arnr_max_frames", "altref noise reduction max frame count", offsetof(VP8Context, arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 15, VE}, \ | |
804 | {"arnr_strength", "altref noise reduction filter strength", offsetof(VP8Context, arnr_strength), AV_OPT_TYPE_INT, {.i64 = 3}, 0, 6, VE}, \ | |
805 | {"arnr_type", "altref noise reduction filter type", offsetof(VP8Context, arnr_type), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 3, VE}, \ | |
806 | {"rc_lookahead", "Number of frames to look ahead for alternate reference frame selection", offsetof(VP8Context, lag_in_frames), AV_OPT_TYPE_INT, {.i64 = 25}, 0, 25, VE}, \ | |
807 | ||
808 | #if CONFIG_LIBVPX_VP8_ENCODER | |
809 | static const AVOption vp8_options[] = { | |
810 | COMMON_OPTIONS | |
811 | LEGACY_OPTIONS | |
812 | { NULL } | |
813 | }; | |
814 | #endif | |
815 | ||
816 | #if CONFIG_LIBVPX_VP9_ENCODER | |
817 | static const AVOption vp9_options[] = { | |
818 | COMMON_OPTIONS | |
819 | { "lossless", "Lossless mode", OFFSET(lossless), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE}, | |
820 | { "tile-columns", "Number of tile columns to use, log2", OFFSET(tile_columns), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE}, | |
821 | { "tile-rows", "Number of tile rows to use, log2", OFFSET(tile_rows), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE}, | |
822 | { "frame-parallel", "Enable frame parallel decodability features", OFFSET(frame_parallel), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE}, | |
823 | { "aq-mode", "adaptive quantization mode", OFFSET(aq_mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 3, VE, "aq_mode"}, | |
824 | { "none", "Aq not used", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, VE, "aq_mode" }, \ | |
825 | { "variance", "Variance based Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE, "aq_mode" }, \ | |
826 | { "complexity", "Complexity based Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "aq_mode" }, \ | |
827 | { "cyclic", "Cyclic Refresh Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE, "aq_mode" }, \ | |
828 | LEGACY_OPTIONS | |
829 | { NULL } | |
830 | }; | |
831 | #endif | |
832 | ||
833 | #undef COMMON_OPTIONS | |
834 | #undef LEGACY_OPTIONS | |
835 | ||
836 | static const AVCodecDefault defaults[] = { | |
837 | { "qmin", "-1" }, | |
838 | { "qmax", "-1" }, | |
839 | { "g", "-1" }, | |
840 | { "keyint_min", "-1" }, | |
841 | { NULL }, | |
842 | }; | |
843 | ||
844 | #if CONFIG_LIBVPX_VP8_ENCODER | |
845 | static av_cold int vp8_init(AVCodecContext *avctx) | |
846 | { | |
847 | return vpx_init(avctx, &vpx_codec_vp8_cx_algo); | |
848 | } | |
849 | ||
850 | static const AVClass class_vp8 = { | |
851 | .class_name = "libvpx-vp8 encoder", | |
852 | .item_name = av_default_item_name, | |
853 | .option = vp8_options, | |
854 | .version = LIBAVUTIL_VERSION_INT, | |
855 | }; | |
856 | ||
857 | AVCodec ff_libvpx_vp8_encoder = { | |
858 | .name = "libvpx", | |
859 | .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), | |
860 | .type = AVMEDIA_TYPE_VIDEO, | |
861 | .id = AV_CODEC_ID_VP8, | |
862 | .priv_data_size = sizeof(VP8Context), | |
863 | .init = vp8_init, | |
864 | .encode2 = vp8_encode, | |
865 | .close = vp8_free, | |
866 | .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, | |
867 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }, | |
868 | .priv_class = &class_vp8, | |
869 | .defaults = defaults, | |
870 | }; | |
871 | #endif /* CONFIG_LIBVPX_VP8_ENCODER */ | |
872 | ||
873 | #if CONFIG_LIBVPX_VP9_ENCODER | |
874 | static av_cold int vp9_init(AVCodecContext *avctx) | |
875 | { | |
876 | return vpx_init(avctx, &vpx_codec_vp9_cx_algo); | |
877 | } | |
878 | ||
879 | static const AVClass class_vp9 = { | |
880 | .class_name = "libvpx-vp9 encoder", | |
881 | .item_name = av_default_item_name, | |
882 | .option = vp9_options, | |
883 | .version = LIBAVUTIL_VERSION_INT, | |
884 | }; | |
885 | ||
886 | AVCodec ff_libvpx_vp9_encoder = { | |
887 | .name = "libvpx-vp9", | |
888 | .long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), | |
889 | .type = AVMEDIA_TYPE_VIDEO, | |
890 | .id = AV_CODEC_ID_VP9, | |
891 | .priv_data_size = sizeof(VP8Context), | |
892 | .init = vp9_init, | |
893 | .encode2 = vp8_encode, | |
894 | .close = vp8_free, | |
895 | .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS, | |
896 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, | |
897 | .priv_class = &class_vp9, | |
898 | .defaults = defaults, | |
899 | .init_static_data = ff_vp9_init_static, | |
900 | }; | |
901 | #endif /* CONFIG_LIBVPX_VP9_ENCODER */ |