Commit | Line | Data |
---|---|---|
ee0e9146 JZ |
1 | /* |
2 | * Copyright (c) 2010, Google, Inc. | |
3 | * | |
2912e87a | 4 | * This file is part of Libav. |
ee0e9146 | 5 | * |
2912e87a | 6 | * Libav is free software; you can redistribute it and/or |
ee0e9146 JZ |
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 | * | |
2912e87a | 11 | * Libav is distributed in the hope that it will be useful, |
ee0e9146 JZ |
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 | |
2912e87a | 17 | * License along with Libav; if not, write to the Free Software |
ee0e9146 JZ |
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" | |
e3eb015b | 32 | #include "internal.h" |
9aa053ce | 33 | #include "libvpx.h" |
ee0e9146 | 34 | #include "libavutil/base64.h" |
1d9c2dc8 | 35 | #include "libavutil/common.h" |
954a6532 | 36 | #include "libavutil/mathematics.h" |
e3eb015b | 37 | #include "libavutil/opt.h" |
ee0e9146 JZ |
38 | |
39 | /** | |
40 | * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h. | |
41 | * One encoded frame returned from the library. | |
42 | */ | |
43 | struct FrameListData { | |
1aa15491 BF |
44 | void *buf; /**< compressed data buffer */ |
45 | size_t sz; /**< length of compressed data */ | |
46 | int64_t pts; /**< time stamp to show frame | |
ee0e9146 | 47 | (in timebase units) */ |
1aa15491 | 48 | unsigned long duration; /**< duration to show frame |
ee0e9146 | 49 | (in timebase units) */ |
1aa15491 | 50 | uint32_t flags; /**< flags for this frame */ |
ee0e9146 JZ |
51 | struct FrameListData *next; |
52 | }; | |
53 | ||
54 | typedef struct VP8EncoderContext { | |
e3eb015b | 55 | AVClass *class; |
ee0e9146 JZ |
56 | struct vpx_codec_ctx encoder; |
57 | struct vpx_image rawimg; | |
58 | struct vpx_fixed_buf twopass_stats; | |
59 | unsigned long deadline; //i.e., RT/GOOD/BEST | |
60 | struct FrameListData *coded_frame_list; | |
e3eb015b LB |
61 | int cpu_used; |
62 | int auto_alt_ref; | |
63 | int arnr_max_frames; | |
64 | int arnr_strength; | |
65 | int arnr_type; | |
66 | int lag_in_frames; | |
67 | int error_resilient; | |
12776d5d | 68 | int crf; |
685be3d1 | 69 | int static_thresh; |
ee0e9146 JZ |
70 | } VP8Context; |
71 | ||
72 | /** String mappings for enum vp8e_enc_control_id */ | |
b0f29db5 | 73 | static const char *const ctlidstr[] = { |
4d05e939 JZ |
74 | [VP8E_SET_ARNR_MAXFRAMES] = "VP8E_SET_ARNR_MAXFRAMES", |
75 | [VP8E_SET_ARNR_STRENGTH] = "VP8E_SET_ARNR_STRENGTH", | |
76 | [VP8E_SET_ARNR_TYPE] = "VP8E_SET_ARNR_TYPE", | |
ee0e9146 | 77 | [VP8E_SET_CPUUSED] = "VP8E_SET_CPUUSED", |
4d05e939 | 78 | [VP8E_SET_CQ_LEVEL] = "VP8E_SET_CQ_LEVEL", |
ee0e9146 JZ |
79 | [VP8E_SET_ENABLEAUTOALTREF] = "VP8E_SET_ENABLEAUTOALTREF", |
80 | [VP8E_SET_NOISE_SENSITIVITY] = "VP8E_SET_NOISE_SENSITIVITY", | |
ee0e9146 JZ |
81 | [VP8E_SET_STATIC_THRESHOLD] = "VP8E_SET_STATIC_THRESHOLD", |
82 | [VP8E_SET_TOKEN_PARTITIONS] = "VP8E_SET_TOKEN_PARTITIONS", | |
ee0e9146 JZ |
83 | }; |
84 | ||
85 | static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) | |
86 | { | |
87 | VP8Context *ctx = avctx->priv_data; | |
88 | const char *error = vpx_codec_error(&ctx->encoder); | |
89 | const char *detail = vpx_codec_error_detail(&ctx->encoder); | |
90 | ||
91 | av_log(avctx, AV_LOG_ERROR, "%s: %s\n", desc, error); | |
92 | if (detail) | |
93 | av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", detail); | |
94 | } | |
95 | ||
96 | static av_cold void dump_enc_cfg(AVCodecContext *avctx, | |
97 | const struct vpx_codec_enc_cfg *cfg) | |
98 | { | |
99 | int width = -30; | |
100 | int level = AV_LOG_DEBUG; | |
101 | ||
102 | av_log(avctx, level, "vpx_codec_enc_cfg\n"); | |
103 | av_log(avctx, level, "generic settings\n" | |
104 | " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n" | |
105 | " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n", | |
106 | width, "g_usage:", cfg->g_usage, | |
107 | width, "g_threads:", cfg->g_threads, | |
108 | width, "g_profile:", cfg->g_profile, | |
109 | width, "g_w:", cfg->g_w, | |
110 | width, "g_h:", cfg->g_h, | |
111 | width, "g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den, | |
112 | width, "g_error_resilient:", cfg->g_error_resilient, | |
113 | width, "g_pass:", cfg->g_pass, | |
114 | width, "g_lag_in_frames:", cfg->g_lag_in_frames); | |
115 | av_log(avctx, level, "rate control settings\n" | |
116 | " %*s%u\n %*s%u\n %*s%u\n %*s%u\n" | |
117 | " %*s%d\n %*s%p(%zu)\n %*s%u\n", | |
118 | width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh, | |
119 | width, "rc_resize_allowed:", cfg->rc_resize_allowed, | |
120 | width, "rc_resize_up_thresh:", cfg->rc_resize_up_thresh, | |
121 | width, "rc_resize_down_thresh:", cfg->rc_resize_down_thresh, | |
122 | width, "rc_end_usage:", cfg->rc_end_usage, | |
123 | width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz, | |
124 | width, "rc_target_bitrate:", cfg->rc_target_bitrate); | |
125 | av_log(avctx, level, "quantizer settings\n" | |
126 | " %*s%u\n %*s%u\n", | |
127 | width, "rc_min_quantizer:", cfg->rc_min_quantizer, | |
128 | width, "rc_max_quantizer:", cfg->rc_max_quantizer); | |
129 | av_log(avctx, level, "bitrate tolerance\n" | |
130 | " %*s%u\n %*s%u\n", | |
131 | width, "rc_undershoot_pct:", cfg->rc_undershoot_pct, | |
132 | width, "rc_overshoot_pct:", cfg->rc_overshoot_pct); | |
133 | av_log(avctx, level, "decoder buffer model\n" | |
134 | " %*s%u\n %*s%u\n %*s%u\n", | |
135 | width, "rc_buf_sz:", cfg->rc_buf_sz, | |
136 | width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz, | |
137 | width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz); | |
138 | av_log(avctx, level, "2 pass rate control settings\n" | |
139 | " %*s%u\n %*s%u\n %*s%u\n", | |
140 | width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct, | |
141 | width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct, | |
142 | width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct); | |
143 | av_log(avctx, level, "keyframing settings\n" | |
144 | " %*s%d\n %*s%u\n %*s%u\n", | |
145 | width, "kf_mode:", cfg->kf_mode, | |
146 | width, "kf_min_dist:", cfg->kf_min_dist, | |
147 | width, "kf_max_dist:", cfg->kf_max_dist); | |
148 | av_log(avctx, level, "\n"); | |
149 | } | |
150 | ||
151 | static void coded_frame_add(void *list, struct FrameListData *cx_frame) | |
152 | { | |
153 | struct FrameListData **p = list; | |
154 | ||
4b1f5e50 | 155 | while (*p) |
ee0e9146 JZ |
156 | p = &(*p)->next; |
157 | *p = cx_frame; | |
158 | cx_frame->next = NULL; | |
159 | } | |
160 | ||
161 | static av_cold void free_coded_frame(struct FrameListData *cx_frame) | |
162 | { | |
163 | av_freep(&cx_frame->buf); | |
164 | av_freep(&cx_frame); | |
165 | } | |
166 | ||
167 | static av_cold void free_frame_list(struct FrameListData *list) | |
168 | { | |
169 | struct FrameListData *p = list; | |
170 | ||
171 | while (p) { | |
172 | list = list->next; | |
173 | free_coded_frame(p); | |
174 | p = list; | |
175 | } | |
176 | } | |
177 | ||
178 | static av_cold int codecctl_int(AVCodecContext *avctx, | |
179 | enum vp8e_enc_control_id id, int val) | |
180 | { | |
181 | VP8Context *ctx = avctx->priv_data; | |
182 | char buf[80]; | |
183 | int width = -30; | |
184 | int res; | |
185 | ||
186 | snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); | |
187 | av_log(avctx, AV_LOG_DEBUG, " %*s%d\n", width, buf, val); | |
188 | ||
189 | res = vpx_codec_control(&ctx->encoder, id, val); | |
190 | if (res != VPX_CODEC_OK) { | |
191 | snprintf(buf, sizeof(buf), "Failed to set %s codec control", | |
192 | ctlidstr[id]); | |
193 | log_encoder_error(avctx, buf); | |
194 | } | |
195 | ||
196 | return res == VPX_CODEC_OK ? 0 : AVERROR(EINVAL); | |
197 | } | |
198 | ||
199 | static av_cold int vp8_free(AVCodecContext *avctx) | |
200 | { | |
201 | VP8Context *ctx = avctx->priv_data; | |
202 | ||
203 | vpx_codec_destroy(&ctx->encoder); | |
204 | av_freep(&ctx->twopass_stats.buf); | |
ee0e9146 JZ |
205 | av_freep(&avctx->stats_out); |
206 | free_frame_list(ctx->coded_frame_list); | |
207 | return 0; | |
208 | } | |
209 | ||
dab1f543 LB |
210 | static av_cold int vpx_init(AVCodecContext *avctx, |
211 | const struct vpx_codec_iface *iface) | |
ee0e9146 JZ |
212 | { |
213 | VP8Context *ctx = avctx->priv_data; | |
8655c541 | 214 | struct vpx_codec_enc_cfg enccfg = { 0 }; |
03afb62e | 215 | AVCPBProperties *cpb_props; |
ee0e9146 JZ |
216 | int res; |
217 | ||
218 | av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); | |
219 | av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); | |
220 | ||
221 | if ((res = vpx_codec_enc_config_default(iface, &enccfg, 0)) != VPX_CODEC_OK) { | |
222 | av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n", | |
223 | vpx_codec_err_to_string(res)); | |
224 | return AVERROR(EINVAL); | |
225 | } | |
226 | dump_enc_cfg(avctx, &enccfg); | |
227 | ||
228 | enccfg.g_w = avctx->width; | |
229 | enccfg.g_h = avctx->height; | |
230 | enccfg.g_timebase.num = avctx->time_base.num; | |
231 | enccfg.g_timebase.den = avctx->time_base.den; | |
232 | enccfg.g_threads = avctx->thread_count; | |
233 | ||
e3eb015b LB |
234 | if (ctx->lag_in_frames >= 0) |
235 | enccfg.g_lag_in_frames = ctx->lag_in_frames; | |
236 | ||
7c6eb0a1 | 237 | if (avctx->flags & AV_CODEC_FLAG_PASS1) |
ee0e9146 | 238 | enccfg.g_pass = VPX_RC_FIRST_PASS; |
7c6eb0a1 | 239 | else if (avctx->flags & AV_CODEC_FLAG_PASS2) |
ee0e9146 JZ |
240 | enccfg.g_pass = VPX_RC_LAST_PASS; |
241 | else | |
242 | enccfg.g_pass = VPX_RC_ONE_PASS; | |
243 | ||
4aa3d7b3 LB |
244 | if (!avctx->bit_rate) |
245 | avctx->bit_rate = enccfg.rc_target_bitrate * 1000; | |
246 | else | |
247 | enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, | |
248 | AV_ROUND_NEAR_INF); | |
249 | ||
12776d5d JZ |
250 | if (ctx->crf) |
251 | enccfg.rc_end_usage = VPX_CQ; | |
252 | else if (avctx->rc_min_rate == avctx->rc_max_rate && | |
253 | avctx->rc_min_rate == avctx->bit_rate) | |
ee0e9146 | 254 | enccfg.rc_end_usage = VPX_CBR; |
4aa3d7b3 | 255 | |
6450f26c LB |
256 | if (avctx->qmin > 0) |
257 | enccfg.rc_min_quantizer = avctx->qmin; | |
258 | if (avctx->qmax > 0) | |
259 | enccfg.rc_max_quantizer = avctx->qmax; | |
00ce2cbe | 260 | enccfg.rc_dropframe_thresh = avctx->frame_skip_threshold; |
ee0e9146 | 261 | |
7eb185e0 JZ |
262 | //0-100 (0 => CBR, 100 => VBR) |
263 | enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100); | |
264 | enccfg.rc_2pass_vbr_minsection_pct = | |
9d845ca4 | 265 | avctx->rc_min_rate * 100LL / avctx->bit_rate; |
7eb185e0 JZ |
266 | if (avctx->rc_max_rate) |
267 | enccfg.rc_2pass_vbr_maxsection_pct = | |
9d845ca4 | 268 | avctx->rc_max_rate * 100LL / avctx->bit_rate; |
7eb185e0 | 269 | |
53cf4782 JZ |
270 | if (avctx->rc_buffer_size) |
271 | enccfg.rc_buf_sz = | |
9d845ca4 | 272 | avctx->rc_buffer_size * 1000LL / avctx->bit_rate; |
53cf4782 JZ |
273 | if (avctx->rc_initial_buffer_occupancy) |
274 | enccfg.rc_buf_initial_sz = | |
9d845ca4 | 275 | avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate; |
53cf4782 JZ |
276 | enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6; |
277 | ||
07777c2d | 278 | //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO |
6450f26c | 279 | if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size) |
ee0e9146 | 280 | enccfg.kf_min_dist = avctx->keyint_min; |
6450f26c LB |
281 | if (avctx->gop_size >= 0) |
282 | enccfg.kf_max_dist = avctx->gop_size; | |
ee0e9146 JZ |
283 | |
284 | if (enccfg.g_pass == VPX_RC_FIRST_PASS) | |
285 | enccfg.g_lag_in_frames = 0; | |
286 | else if (enccfg.g_pass == VPX_RC_LAST_PASS) { | |
93f79481 | 287 | int decode_size, ret; |
ee0e9146 JZ |
288 | |
289 | if (!avctx->stats_in) { | |
290 | av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n"); | |
291 | return AVERROR_INVALIDDATA; | |
292 | } | |
293 | ||
294 | ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4; | |
93f79481 VG |
295 | ret = av_reallocp(&ctx->twopass_stats.buf, ctx->twopass_stats.sz); |
296 | if (ret < 0) { | |
ee0e9146 JZ |
297 | av_log(avctx, AV_LOG_ERROR, |
298 | "Stat buffer alloc (%zu bytes) failed\n", | |
299 | ctx->twopass_stats.sz); | |
93f79481 | 300 | return ret; |
ee0e9146 JZ |
301 | } |
302 | decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in, | |
303 | ctx->twopass_stats.sz); | |
304 | if (decode_size < 0) { | |
305 | av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n"); | |
306 | return AVERROR_INVALIDDATA; | |
307 | } | |
308 | ||
309 | ctx->twopass_stats.sz = decode_size; | |
310 | enccfg.rc_twopass_stats_in = ctx->twopass_stats; | |
311 | } | |
312 | ||
83a68cd6 JZ |
313 | /* 0-3: For non-zero values the encoder increasingly optimizes for reduced |
314 | complexity playback on low powered devices at the expense of encode | |
315 | quality. */ | |
8655c541 LB |
316 | if (avctx->profile != FF_PROFILE_UNKNOWN) |
317 | enccfg.g_profile = avctx->profile; | |
318 | else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) | |
319 | avctx->profile = enccfg.g_profile = FF_PROFILE_VP9_0; | |
320 | else | |
321 | avctx->profile = enccfg.g_profile = FF_PROFILE_VP9_1; | |
ee0e9146 | 322 | |
e3eb015b LB |
323 | enccfg.g_error_resilient = ctx->error_resilient; |
324 | ||
ee0e9146 JZ |
325 | dump_enc_cfg(avctx, &enccfg); |
326 | /* Construct Encoder Context */ | |
327 | res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, 0); | |
328 | if (res != VPX_CODEC_OK) { | |
329 | log_encoder_error(avctx, "Failed to initialize encoder"); | |
330 | return AVERROR(EINVAL); | |
331 | } | |
332 | ||
333 | //codec control failures are currently treated only as warnings | |
334 | av_log(avctx, AV_LOG_DEBUG, "vpx_codec_control\n"); | |
e3eb015b LB |
335 | if (ctx->cpu_used != INT_MIN) |
336 | codecctl_int(avctx, VP8E_SET_CPUUSED, ctx->cpu_used); | |
337 | if (ctx->auto_alt_ref >= 0) | |
338 | codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF, ctx->auto_alt_ref); | |
339 | if (ctx->arnr_max_frames >= 0) | |
340 | codecctl_int(avctx, VP8E_SET_ARNR_MAXFRAMES, ctx->arnr_max_frames); | |
341 | if (ctx->arnr_strength >= 0) | |
342 | codecctl_int(avctx, VP8E_SET_ARNR_STRENGTH, ctx->arnr_strength); | |
343 | if (ctx->arnr_type >= 0) | |
344 | codecctl_int(avctx, VP8E_SET_ARNR_TYPE, ctx->arnr_type); | |
05bf3f54 LB |
345 | |
346 | if (CONFIG_LIBVPX_VP8_ENCODER && iface == &vpx_codec_vp8_cx_algo) { | |
347 | codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, avctx->noise_reduction); | |
348 | codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices)); | |
349 | } | |
685be3d1 AK |
350 | #if FF_API_MPV_OPT |
351 | FF_DISABLE_DEPRECATION_WARNINGS | |
352 | if (avctx->mb_threshold) { | |
353 | av_log(avctx, AV_LOG_WARNING, "The mb_threshold option is deprecated, " | |
354 | "use the static-thresh private option instead.\n"); | |
355 | ctx->static_thresh = avctx->mb_threshold; | |
356 | } | |
357 | FF_ENABLE_DEPRECATION_WARNINGS | |
358 | #endif | |
359 | codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, ctx->static_thresh); | |
12776d5d | 360 | codecctl_int(avctx, VP8E_SET_CQ_LEVEL, ctx->crf); |
ee0e9146 JZ |
361 | |
362 | //provide dummy value to initialize wrapper, values will be updated each _encode() | |
8655c541 LB |
363 | vpx_img_wrap(&ctx->rawimg, ff_vpx_pixfmt_to_imgfmt(avctx->pix_fmt), |
364 | avctx->width, avctx->height, 1, (unsigned char *)1); | |
ee0e9146 | 365 | |
03afb62e AK |
366 | cpb_props = ff_add_cpb_side_data(avctx); |
367 | if (!cpb_props) | |
368 | return AVERROR(ENOMEM); | |
369 | ||
370 | if (enccfg.rc_end_usage == VPX_CBR || | |
371 | enccfg.g_pass != VPX_RC_ONE_PASS) { | |
372 | cpb_props->max_bitrate = avctx->rc_max_rate; | |
373 | cpb_props->min_bitrate = avctx->rc_min_rate; | |
374 | cpb_props->avg_bitrate = avctx->bit_rate; | |
375 | } | |
376 | cpb_props->buffer_size = avctx->rc_buffer_size; | |
377 | ||
ee0e9146 JZ |
378 | return 0; |
379 | } | |
380 | ||
381 | static inline void cx_pktcpy(struct FrameListData *dst, | |
382 | const struct vpx_codec_cx_pkt *src) | |
383 | { | |
384 | dst->pts = src->data.frame.pts; | |
385 | dst->duration = src->data.frame.duration; | |
386 | dst->flags = src->data.frame.flags; | |
387 | dst->sz = src->data.frame.sz; | |
388 | dst->buf = src->data.frame.buf; | |
389 | } | |
390 | ||
391 | /** | |
d8f3365f | 392 | * Store coded frame information in format suitable for return from encode2(). |
ee0e9146 | 393 | * |
d8f3365f AK |
394 | * Write information from @a cx_frame to @a pkt |
395 | * @return packet data size on success | |
396 | * @return a negative AVERROR on error | |
ee0e9146 JZ |
397 | */ |
398 | static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, | |
d6006dd9 | 399 | AVPacket *pkt) |
ee0e9146 | 400 | { |
d8f3365f AK |
401 | int ret = ff_alloc_packet(pkt, cx_frame->sz); |
402 | if (ret >= 0) { | |
403 | memcpy(pkt->data, cx_frame->buf, pkt->size); | |
d6006dd9 | 404 | pkt->pts = pkt->dts = cx_frame->pts; |
40cf1bba VG |
405 | #if FF_API_CODED_FRAME |
406 | FF_DISABLE_DEPRECATION_WARNINGS | |
d6006dd9 VG |
407 | avctx->coded_frame->pts = cx_frame->pts; |
408 | avctx->coded_frame->key_frame = !!(cx_frame->flags & VPX_FRAME_IS_KEY); | |
40cf1bba VG |
409 | FF_ENABLE_DEPRECATION_WARNINGS |
410 | #endif | |
d6006dd9 VG |
411 | |
412 | if (!!(cx_frame->flags & VPX_FRAME_IS_KEY)) { | |
40cf1bba VG |
413 | #if FF_API_CODED_FRAME |
414 | FF_DISABLE_DEPRECATION_WARNINGS | |
d6006dd9 | 415 | avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; |
40cf1bba VG |
416 | FF_ENABLE_DEPRECATION_WARNINGS |
417 | #endif | |
d6006dd9 VG |
418 | pkt->flags |= AV_PKT_FLAG_KEY; |
419 | } else { | |
40cf1bba VG |
420 | #if FF_API_CODED_FRAME |
421 | FF_DISABLE_DEPRECATION_WARNINGS | |
d6006dd9 | 422 | avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; |
40cf1bba VG |
423 | FF_ENABLE_DEPRECATION_WARNINGS |
424 | #endif | |
d6006dd9 | 425 | } |
ee0e9146 JZ |
426 | } else { |
427 | av_log(avctx, AV_LOG_ERROR, | |
d8f3365f AK |
428 | "Error getting output packet of size %zu.\n", cx_frame->sz); |
429 | return ret; | |
ee0e9146 | 430 | } |
d8f3365f | 431 | return pkt->size; |
ee0e9146 JZ |
432 | } |
433 | ||
434 | /** | |
435 | * Queue multiple output frames from the encoder, returning the front-most. | |
436 | * In cases where vpx_codec_get_cx_data() returns more than 1 frame append | |
437 | * the frame queue. Return the head frame if available. | |
438 | * @return Stored frame size | |
439 | * @return AVERROR(EINVAL) on output size error | |
440 | * @return AVERROR(ENOMEM) on coded frame queue data allocation error | |
441 | */ | |
d6006dd9 | 442 | static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) |
ee0e9146 JZ |
443 | { |
444 | VP8Context *ctx = avctx->priv_data; | |
445 | const struct vpx_codec_cx_pkt *pkt; | |
446 | const void *iter = NULL; | |
447 | int size = 0; | |
448 | ||
449 | if (ctx->coded_frame_list) { | |
450 | struct FrameListData *cx_frame = ctx->coded_frame_list; | |
451 | /* return the leading frame if we've already begun queueing */ | |
d6006dd9 | 452 | size = storeframe(avctx, cx_frame, pkt_out); |
ee0e9146 | 453 | if (size < 0) |
d8f3365f | 454 | return size; |
ee0e9146 JZ |
455 | ctx->coded_frame_list = cx_frame->next; |
456 | free_coded_frame(cx_frame); | |
457 | } | |
458 | ||
459 | /* consume all available output from the encoder before returning. buffers | |
460 | are only good through the next vpx_codec call */ | |
461 | while ((pkt = vpx_codec_get_cx_data(&ctx->encoder, &iter))) { | |
462 | switch (pkt->kind) { | |
463 | case VPX_CODEC_CX_FRAME_PKT: | |
464 | if (!size) { | |
465 | struct FrameListData cx_frame; | |
466 | ||
467 | /* avoid storing the frame when the list is empty and we haven't yet | |
468 | provided a frame for output */ | |
469 | assert(!ctx->coded_frame_list); | |
470 | cx_pktcpy(&cx_frame, pkt); | |
d6006dd9 | 471 | size = storeframe(avctx, &cx_frame, pkt_out); |
ee0e9146 | 472 | if (size < 0) |
d8f3365f | 473 | return size; |
ee0e9146 JZ |
474 | } else { |
475 | struct FrameListData *cx_frame = | |
476 | av_malloc(sizeof(struct FrameListData)); | |
477 | ||
478 | if (!cx_frame) { | |
479 | av_log(avctx, AV_LOG_ERROR, | |
480 | "Frame queue element alloc failed\n"); | |
481 | return AVERROR(ENOMEM); | |
482 | } | |
483 | cx_pktcpy(cx_frame, pkt); | |
484 | cx_frame->buf = av_malloc(cx_frame->sz); | |
485 | ||
486 | if (!cx_frame->buf) { | |
487 | av_log(avctx, AV_LOG_ERROR, | |
488 | "Data buffer alloc (%zu bytes) failed\n", | |
489 | cx_frame->sz); | |
771656bd | 490 | av_freep(&cx_frame); |
ee0e9146 JZ |
491 | return AVERROR(ENOMEM); |
492 | } | |
493 | memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz); | |
494 | coded_frame_add(&ctx->coded_frame_list, cx_frame); | |
495 | } | |
496 | break; | |
497 | case VPX_CODEC_STATS_PKT: { | |
498 | struct vpx_fixed_buf *stats = &ctx->twopass_stats; | |
9b8d11a7 AK |
499 | int err; |
500 | if ((err = av_reallocp(&stats->buf, | |
501 | stats->sz + | |
502 | pkt->data.twopass_stats.sz)) < 0) { | |
503 | stats->sz = 0; | |
ee0e9146 | 504 | av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n"); |
9b8d11a7 | 505 | return err; |
ee0e9146 JZ |
506 | } |
507 | memcpy((uint8_t*)stats->buf + stats->sz, | |
508 | pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz); | |
509 | stats->sz += pkt->data.twopass_stats.sz; | |
510 | break; | |
511 | } | |
7c6eb0a1 | 512 | case VPX_CODEC_PSNR_PKT: //FIXME add support for AV_CODEC_FLAG_PSNR |
ee0e9146 JZ |
513 | case VPX_CODEC_CUSTOM_PKT: |
514 | //ignore unsupported/unrecognized packet types | |
515 | break; | |
516 | } | |
517 | } | |
518 | ||
519 | return size; | |
520 | } | |
521 | ||
d8f3365f AK |
522 | static int vp8_encode(AVCodecContext *avctx, AVPacket *pkt, |
523 | const AVFrame *frame, int *got_packet) | |
ee0e9146 JZ |
524 | { |
525 | VP8Context *ctx = avctx->priv_data; | |
ee0e9146 JZ |
526 | struct vpx_image *rawimg = NULL; |
527 | int64_t timestamp = 0; | |
528 | int res, coded_size; | |
774e6fc9 | 529 | vpx_enc_frame_flags_t flags = 0; |
ee0e9146 JZ |
530 | |
531 | if (frame) { | |
532 | rawimg = &ctx->rawimg; | |
533 | rawimg->planes[VPX_PLANE_Y] = frame->data[0]; | |
534 | rawimg->planes[VPX_PLANE_U] = frame->data[1]; | |
535 | rawimg->planes[VPX_PLANE_V] = frame->data[2]; | |
536 | rawimg->stride[VPX_PLANE_Y] = frame->linesize[0]; | |
537 | rawimg->stride[VPX_PLANE_U] = frame->linesize[1]; | |
538 | rawimg->stride[VPX_PLANE_V] = frame->linesize[2]; | |
539 | timestamp = frame->pts; | |
774e6fc9 MS |
540 | if (frame->pict_type == AV_PICTURE_TYPE_I) |
541 | flags |= VPX_EFLAG_FORCE_KF; | |
ee0e9146 JZ |
542 | } |
543 | ||
544 | res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp, | |
774e6fc9 | 545 | avctx->ticks_per_frame, flags, ctx->deadline); |
ee0e9146 JZ |
546 | if (res != VPX_CODEC_OK) { |
547 | log_encoder_error(avctx, "Error encoding frame"); | |
548 | return AVERROR_INVALIDDATA; | |
549 | } | |
d6006dd9 | 550 | coded_size = queue_frames(avctx, pkt); |
ee0e9146 | 551 | |
7c6eb0a1 | 552 | if (!frame && avctx->flags & AV_CODEC_FLAG_PASS1) { |
082a0a33 | 553 | unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz); |
ee0e9146 JZ |
554 | |
555 | avctx->stats_out = av_malloc(b64_size); | |
556 | if (!avctx->stats_out) { | |
557 | av_log(avctx, AV_LOG_ERROR, "Stat buffer alloc (%d bytes) failed\n", | |
558 | b64_size); | |
559 | return AVERROR(ENOMEM); | |
560 | } | |
561 | av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, | |
562 | ctx->twopass_stats.sz); | |
563 | } | |
d8f3365f AK |
564 | |
565 | *got_packet = !!coded_size; | |
566 | return 0; | |
ee0e9146 JZ |
567 | } |
568 | ||
e3eb015b LB |
569 | #define OFFSET(x) offsetof(VP8Context, x) |
570 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM | |
571 | static const AVOption options[] = { | |
9affa784 | 572 | { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, INT_MIN, INT_MAX, VE}, |
e3eb015b | 573 | { "auto-alt-ref", "Enable use of alternate reference " |
e6153f17 | 574 | "frames (2-pass only)", OFFSET(auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE}, |
e3eb015b | 575 | { "lag-in-frames", "Number of frames to look ahead for " |
e6153f17 MS |
576 | "alternate reference frame selection", OFFSET(lag_in_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, |
577 | { "arnr-maxframes", "altref noise reduction max frame count", OFFSET(arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, | |
578 | { "arnr-strength", "altref noise reduction filter strength", OFFSET(arnr_strength), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE}, | |
579 | { "arnr-type", "altref noise reduction filter type", OFFSET(arnr_type), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE, "arnr_type"}, | |
124134e4 MS |
580 | { "backward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE, "arnr_type" }, |
581 | { "forward", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "arnr_type" }, | |
582 | { "centered", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE, "arnr_type" }, | |
e6153f17 | 583 | { "deadline", "Time to spend encoding, in microseconds.", OFFSET(deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"}, |
124134e4 MS |
584 | { "best", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_BEST_QUALITY}, 0, 0, VE, "quality"}, |
585 | { "good", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_GOOD_QUALITY}, 0, 0, VE, "quality"}, | |
586 | { "realtime", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_REALTIME}, 0, 0, VE, "quality"}, | |
d58dd4b5 | 587 | { "error-resilient", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"}, |
24ec9ac4 | 588 | #ifdef VPX_ERROR_RESILIENT_DEFAULT |
124134e4 | 589 | { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"}, |
e3eb015b LB |
590 | { "partitions", "The frame partitions are independently decodable " |
591 | "by the bool decoder, meaning that partitions can be decoded even " | |
592 | "though earlier partitions have been lost. Note that intra predicition" | |
124134e4 | 593 | " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"}, |
24ec9ac4 | 594 | #endif |
12776d5d | 595 | { "crf", "Select the quality for constant quality mode", offsetof(VP8Context, crf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, VE }, |
685be3d1 | 596 | { "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 }, |
e3eb015b LB |
597 | { NULL } |
598 | }; | |
599 | ||
6450f26c LB |
600 | static const AVCodecDefault defaults[] = { |
601 | { "qmin", "-1" }, | |
602 | { "qmax", "-1" }, | |
603 | { "g", "-1" }, | |
604 | { "keyint_min", "-1" }, | |
605 | { NULL }, | |
606 | }; | |
607 | ||
3f111804 LB |
608 | #if CONFIG_LIBVPX_VP8_ENCODER |
609 | static av_cold int vp8_init(AVCodecContext *avctx) | |
610 | { | |
611 | return vpx_init(avctx, &vpx_codec_vp8_cx_algo); | |
612 | } | |
613 | ||
614 | static const AVClass class_vp8 = { | |
615 | .class_name = "libvpx encoder", | |
616 | .item_name = av_default_item_name, | |
617 | .option = options, | |
618 | .version = LIBAVUTIL_VERSION_INT, | |
619 | }; | |
620 | ||
621 | AVCodec ff_libvpx_vp8_encoder = { | |
ec6402b7 | 622 | .name = "libvpx", |
b2bed932 | 623 | .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), |
ec6402b7 | 624 | .type = AVMEDIA_TYPE_VIDEO, |
36ef5369 | 625 | .id = AV_CODEC_ID_VP8, |
ec6402b7 AK |
626 | .priv_data_size = sizeof(VP8Context), |
627 | .init = vp8_init, | |
d8f3365f | 628 | .encode2 = vp8_encode, |
ec6402b7 | 629 | .close = vp8_free, |
def97856 | 630 | .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, |
716d413c | 631 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, |
3f111804 | 632 | .priv_class = &class_vp8, |
6450f26c | 633 | .defaults = defaults, |
ee0e9146 | 634 | }; |
3f111804 | 635 | #endif /* CONFIG_LIBVPX_VP8_ENCODER */ |
dab1f543 | 636 | |
3f111804 | 637 | #if CONFIG_LIBVPX_VP9_ENCODER |
dab1f543 LB |
638 | static av_cold int vp9_init(AVCodecContext *avctx) |
639 | { | |
640 | return vpx_init(avctx, &vpx_codec_vp9_cx_algo); | |
641 | } | |
642 | ||
643 | static const AVClass class_vp9 = { | |
644 | .class_name = "libvpx encoder", | |
645 | .item_name = av_default_item_name, | |
646 | .option = options, | |
647 | .version = LIBAVUTIL_VERSION_INT, | |
648 | }; | |
649 | ||
8655c541 LB |
650 | static const AVProfile profiles[] = { |
651 | { FF_PROFILE_VP9_0, "Profile 0" }, | |
652 | { FF_PROFILE_VP9_1, "Profile 1" }, | |
653 | { FF_PROFILE_VP9_2, "Profile 2" }, | |
654 | { FF_PROFILE_VP9_3, "Profile 3" }, | |
655 | { FF_PROFILE_UNKNOWN }, | |
656 | }; | |
657 | ||
dab1f543 LB |
658 | AVCodec ff_libvpx_vp9_encoder = { |
659 | .name = "libvpx-vp9", | |
b2bed932 | 660 | .long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), |
dab1f543 LB |
661 | .type = AVMEDIA_TYPE_VIDEO, |
662 | .id = AV_CODEC_ID_VP9, | |
663 | .priv_data_size = sizeof(VP8Context), | |
664 | .init = vp9_init, | |
665 | .encode2 = vp8_encode, | |
666 | .close = vp8_free, | |
def97856 | 667 | .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, |
8655c541 LB |
668 | .pix_fmts = (const enum AVPixelFormat[]) { |
669 | AV_PIX_FMT_YUV420P, | |
670 | #if VPX_IMAGE_ABI_VERSION >= 3 | |
671 | AV_PIX_FMT_YUV422P, | |
672 | AV_PIX_FMT_YUV444P, | |
673 | AV_PIX_FMT_YUV440P, | |
674 | #endif | |
675 | AV_PIX_FMT_NONE, | |
676 | }, | |
677 | .profiles = NULL_IF_CONFIG_SMALL(profiles), | |
dab1f543 LB |
678 | .priv_class = &class_vp9, |
679 | .defaults = defaults, | |
680 | }; | |
3f111804 | 681 | #endif /* CONFIG_LIBVPX_VP9_ENCODER */ |