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