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