2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
14 #include "vpx/vpx_codec.h"
15 #include "vpx/internal/vpx_codec_internal.h"
16 #include "./vpx_version.h"
17 #include "vp9/encoder/vp9_onyx_int.h"
18 #include "vpx/vp8cx.h"
19 #include "vp9/encoder/vp9_firstpass.h"
20 #include "vp9/common/vp9_onyx.h"
21 #include "vp9/vp9_iface_common.h"
24 struct vpx_codec_pkt_list *pkt_list;
25 int cpu_used; /* available cpu percentage in 1/16 */
26 unsigned int enable_auto_alt_ref;
27 unsigned int noise_sensitivity;
28 unsigned int sharpness;
29 unsigned int static_thresh;
30 unsigned int tile_columns;
31 unsigned int tile_rows;
32 unsigned int arnr_max_frames;
33 unsigned int arnr_strength;
34 unsigned int arnr_type;
36 unsigned int cq_level; /* constrained quality level */
37 unsigned int rc_max_intra_bitrate_pct;
38 unsigned int lossless;
39 unsigned int frame_parallel_decoding_mode;
43 struct extraconfig_map {
45 struct vp9_extracfg cfg;
48 static const struct extraconfig_map extracfg_map[] = {
54 1, /* enable_auto_alt_ref */
55 0, /* noise_sensitivity */
57 0, /* static_thresh */
60 7, /* arnr_max_frames */
61 5, /* arnr_strength */
65 0, /* rc_max_intra_bitrate_pct */
67 0, /* frame_parallel_decoding_mode */
73 struct vpx_codec_alg_priv {
74 vpx_codec_priv_t base;
75 vpx_codec_enc_cfg_t cfg;
76 struct vp9_extracfg vp8_cfg;
79 unsigned char *cx_data;
81 unsigned char *pending_cx_data;
82 size_t pending_cx_data_sz;
83 int pending_frame_count;
84 size_t pending_frame_sizes[8];
85 size_t pending_frame_magnitude;
86 vpx_image_t preview_img;
87 vp8_postproc_cfg_t preview_ppcfg;
88 vpx_codec_pkt_list_decl(64) pkt_list;
89 unsigned int fixed_kf_cntr;
92 static VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) {
101 assert(0 && "Invalid Reference Frame");
102 return VP9_LAST_FLAG;
105 static vpx_codec_err_t
106 update_error_state(vpx_codec_alg_priv_t *ctx,
107 const struct vpx_internal_error_info *error) {
110 if ((res = error->error_code))
111 ctx->base.err_detail = error->has_detail
120 #define ERROR(str) do {\
121 ctx->base.err_detail = str;\
122 return VPX_CODEC_INVALID_PARAM;\
125 #define RANGE_CHECK(p, memb, lo, hi) do {\
126 if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
127 ERROR(#memb " out of range ["#lo".."#hi"]");\
130 #define RANGE_CHECK_HI(p, memb, hi) do {\
131 if (!((p)->memb <= (hi))) \
132 ERROR(#memb " out of range [.."#hi"]");\
135 #define RANGE_CHECK_LO(p, memb, lo) do {\
136 if (!((p)->memb >= (lo))) \
137 ERROR(#memb " out of range ["#lo"..]");\
140 #define RANGE_CHECK_BOOL(p, memb) do {\
141 if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
144 static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
145 const vpx_codec_enc_cfg_t *cfg,
146 const struct vp9_extracfg *vp8_cfg) {
147 RANGE_CHECK(cfg, g_w, 1, 65535); /* 16 bits available */
148 RANGE_CHECK(cfg, g_h, 1, 65535); /* 16 bits available */
149 RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
150 RANGE_CHECK(cfg, g_timebase.num, 1, cfg->g_timebase.den);
151 RANGE_CHECK_HI(cfg, g_profile, 3);
153 RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
154 RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
155 RANGE_CHECK_BOOL(vp8_cfg, lossless);
156 if (vp8_cfg->lossless) {
157 RANGE_CHECK_HI(cfg, rc_max_quantizer, 0);
158 RANGE_CHECK_HI(cfg, rc_min_quantizer, 0);
160 RANGE_CHECK(vp8_cfg, aq_mode, 0, AQ_MODES_COUNT - 1);
162 RANGE_CHECK_HI(cfg, g_threads, 64);
163 RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
164 RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q);
165 RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000);
166 RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000);
167 RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
168 RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO);
169 // RANGE_CHECK_BOOL(cfg, g_delete_firstpassfile);
170 RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
171 RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
172 RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
173 RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
174 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
176 RANGE_CHECK(cfg, ss_number_layers, 1,
177 VPX_SS_MAX_LAYERS); /*Spatial layers max */
179 RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
180 if (cfg->ts_number_layers > 1) {
182 for (i = 1; i < cfg->ts_number_layers; ++i) {
183 if (cfg->ts_target_bitrate[i] < cfg->ts_target_bitrate[i-1]) {
184 ERROR("ts_target_bitrate entries are not increasing");
187 RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1);
188 for (i = cfg->ts_number_layers-2; i > 0; --i) {
189 if (cfg->ts_rate_decimator[i-1] != 2*cfg->ts_rate_decimator[i]) {
190 ERROR("ts_rate_decimator factors are not powers of 2");
195 /* VP8 does not support a lower bound on the keyframe interval in
196 * automatic keyframe placement mode.
198 if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist
199 && cfg->kf_min_dist > 0)
200 ERROR("kf_min_dist not supported in auto mode, use 0 "
201 "or kf_max_dist instead.");
203 RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref);
204 RANGE_CHECK(vp8_cfg, cpu_used, -16, 16);
206 RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6);
208 RANGE_CHECK(vp8_cfg, tile_columns, 0, 6);
209 RANGE_CHECK(vp8_cfg, tile_rows, 0, 2);
210 RANGE_CHECK_HI(vp8_cfg, sharpness, 7);
211 RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
212 RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6);
213 RANGE_CHECK(vp8_cfg, arnr_type, 1, 3);
214 RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
216 // TODO(yaowu): remove this when ssim tuning is implemented for vp9
217 if (vp8_cfg->tuning == VP8_TUNE_SSIM)
218 ERROR("Option --tune=ssim is not currently supported in VP9.");
220 if (cfg->g_pass == VPX_RC_LAST_PASS) {
221 size_t packet_sz = sizeof(FIRSTPASS_STATS);
222 int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
223 FIRSTPASS_STATS *stats;
225 if (cfg->rc_twopass_stats_in.buf == NULL)
226 ERROR("rc_twopass_stats_in.buf not set.");
228 if (cfg->rc_twopass_stats_in.sz % packet_sz)
229 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
231 if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
232 ERROR("rc_twopass_stats_in requires at least two packets.");
234 stats = (void *)((char *)cfg->rc_twopass_stats_in.buf
235 + (n_packets - 1) * packet_sz);
237 if ((int)(stats->count + 0.5) != n_packets - 1)
238 ERROR("rc_twopass_stats_in missing EOS stats packet");
245 static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
246 const vpx_image_t *img) {
248 case VPX_IMG_FMT_YV12:
249 case VPX_IMG_FMT_I420:
250 case VPX_IMG_FMT_I422:
251 case VPX_IMG_FMT_I444:
254 ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
258 if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
259 ERROR("Image size must match encoder init configuration size");
265 static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
266 vpx_codec_enc_cfg_t cfg,
267 struct vp9_extracfg vp8_cfg) {
268 oxcf->version = cfg.g_profile;
269 oxcf->width = cfg.g_w;
270 oxcf->height = cfg.g_h;
271 /* guess a frame rate if out of whack, use 30 */
272 oxcf->framerate = (double)(cfg.g_timebase.den)
273 / (double)(cfg.g_timebase.num);
275 if (oxcf->framerate > 180) {
276 oxcf->framerate = 30;
279 switch (cfg.g_pass) {
280 case VPX_RC_ONE_PASS:
281 oxcf->mode = MODE_GOODQUALITY;
283 case VPX_RC_FIRST_PASS:
284 oxcf->mode = MODE_FIRSTPASS;
286 case VPX_RC_LAST_PASS:
287 oxcf->mode = MODE_SECONDPASS_BEST;
291 if (cfg.g_pass == VPX_RC_FIRST_PASS) {
293 oxcf->lag_in_frames = 0;
295 oxcf->allow_lag = (cfg.g_lag_in_frames) > 0;
296 oxcf->lag_in_frames = cfg.g_lag_in_frames;
299 oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
300 if (cfg.rc_end_usage == VPX_CQ)
301 oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
302 else if (cfg.rc_end_usage == VPX_Q)
303 oxcf->end_usage = USAGE_CONSTANT_QUALITY;
304 else if (cfg.rc_end_usage == VPX_CBR)
305 oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
307 oxcf->target_bandwidth = cfg.rc_target_bitrate;
308 oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
310 oxcf->best_allowed_q = cfg.rc_min_quantizer;
311 oxcf->worst_allowed_q = cfg.rc_max_quantizer;
312 oxcf->cq_level = vp8_cfg.cq_level;
315 oxcf->under_shoot_pct = cfg.rc_undershoot_pct;
316 oxcf->over_shoot_pct = cfg.rc_overshoot_pct;
318 oxcf->maximum_buffer_size = cfg.rc_buf_sz;
319 oxcf->starting_buffer_level = cfg.rc_buf_initial_sz;
320 oxcf->optimal_buffer_level = cfg.rc_buf_optimal_sz;
322 oxcf->drop_frames_water_mark = cfg.rc_dropframe_thresh;
324 oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct;
325 oxcf->two_pass_vbrmin_section = cfg.rc_2pass_vbr_minsection_pct;
326 oxcf->two_pass_vbrmax_section = cfg.rc_2pass_vbr_maxsection_pct;
328 oxcf->auto_key = cfg.kf_mode == VPX_KF_AUTO
329 && cfg.kf_min_dist != cfg.kf_max_dist;
330 // oxcf->kf_min_dist = cfg.kf_min_dis;
331 oxcf->key_freq = cfg.kf_max_dist;
333 oxcf->cpu_used = vp8_cfg.cpu_used;
334 oxcf->encode_breakout = vp8_cfg.static_thresh;
335 oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
336 oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity;
337 oxcf->sharpness = vp8_cfg.sharpness;
339 oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in;
340 oxcf->output_pkt_list = vp8_cfg.pkt_list;
342 oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
343 oxcf->arnr_strength = vp8_cfg.arnr_strength;
344 oxcf->arnr_type = vp8_cfg.arnr_type;
346 oxcf->tuning = vp8_cfg.tuning;
348 oxcf->tile_columns = vp8_cfg.tile_columns;
349 oxcf->tile_rows = vp8_cfg.tile_rows;
351 oxcf->lossless = vp8_cfg.lossless;
353 oxcf->error_resilient_mode = cfg.g_error_resilient;
354 oxcf->frame_parallel_decoding_mode = vp8_cfg.frame_parallel_decoding_mode;
356 oxcf->aq_mode = vp8_cfg.aq_mode;
358 oxcf->ss_number_layers = cfg.ss_number_layers;
360 oxcf->ts_number_layers = cfg.ts_number_layers;
362 if (oxcf->ts_number_layers > 1) {
363 memcpy(oxcf->ts_target_bitrate, cfg.ts_target_bitrate,
364 sizeof(cfg.ts_target_bitrate));
365 memcpy(oxcf->ts_rate_decimator, cfg.ts_rate_decimator,
366 sizeof(cfg.ts_rate_decimator));
367 } else if (oxcf->ts_number_layers == 1) {
368 oxcf->ts_target_bitrate[0] = oxcf->target_bandwidth;
369 oxcf->ts_rate_decimator[0] = 1;
373 printf("Current VP9 Settings: \n");
374 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
375 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
376 printf("sharpness: %d\n", oxcf->sharpness);
377 printf("cpu_used: %d\n", oxcf->cpu_used);
378 printf("Mode: %d\n", oxcf->mode);
379 printf("auto_key: %d\n", oxcf->auto_key);
380 printf("key_freq: %d\n", oxcf->key_freq);
381 printf("end_usage: %d\n", oxcf->end_usage);
382 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
383 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
384 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
385 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
386 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
387 printf("fixed_q: %d\n", oxcf->fixed_q);
388 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
389 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
390 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
391 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
392 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
393 printf("allow_lag: %d\n", oxcf->allow_lag);
394 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
395 printf("play_alternate: %d\n", oxcf->play_alternate);
396 printf("Version: %d\n", oxcf->Version);
397 printf("encode_breakout: %d\n", oxcf->encode_breakout);
398 printf("error resilient: %d\n", oxcf->error_resilient_mode);
399 printf("frame parallel detokenization: %d\n",
400 oxcf->frame_parallel_decoding_mode);
405 static vpx_codec_err_t vp9e_set_config(vpx_codec_alg_priv_t *ctx,
406 const vpx_codec_enc_cfg_t *cfg) {
409 if ((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h))
410 ERROR("Cannot change width or height after initialization");
412 /* Prevent increasing lag_in_frames. This check is stricter than it needs
413 * to be -- the limit is not increasing past the first lag_in_frames
414 * value, but we don't track the initial config, only the last successful
417 if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames))
418 ERROR("Cannot increase lag_in_frames");
420 res = validate_config(ctx, cfg, &ctx->vp8_cfg);
422 if (res == VPX_CODEC_OK) {
424 set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
425 vp9_change_config(ctx->cpi, &ctx->oxcf);
432 int vp9_reverse_trans(int q);
435 static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx,
438 void *arg = va_arg(args, void *);
440 #define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
442 if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
445 MAP(VP8E_GET_LAST_QUANTIZER, vp9_get_quantizer(ctx->cpi));
446 MAP(VP8E_GET_LAST_QUANTIZER_64,
447 vp9_reverse_trans(vp9_get_quantizer(ctx->cpi)));
455 static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
458 vpx_codec_err_t res = VPX_CODEC_OK;
459 struct vp9_extracfg xcfg = ctx->vp8_cfg;
461 #define MAP(id, var) case id: var = CAST(id, args); break;
464 MAP(VP8E_SET_CPUUSED, xcfg.cpu_used);
465 MAP(VP8E_SET_ENABLEAUTOALTREF, xcfg.enable_auto_alt_ref);
466 MAP(VP8E_SET_NOISE_SENSITIVITY, xcfg.noise_sensitivity);
467 MAP(VP8E_SET_SHARPNESS, xcfg.sharpness);
468 MAP(VP8E_SET_STATIC_THRESHOLD, xcfg.static_thresh);
469 MAP(VP9E_SET_TILE_COLUMNS, xcfg.tile_columns);
470 MAP(VP9E_SET_TILE_ROWS, xcfg.tile_rows);
471 MAP(VP8E_SET_ARNR_MAXFRAMES, xcfg.arnr_max_frames);
472 MAP(VP8E_SET_ARNR_STRENGTH, xcfg.arnr_strength);
473 MAP(VP8E_SET_ARNR_TYPE, xcfg.arnr_type);
474 MAP(VP8E_SET_TUNING, xcfg.tuning);
475 MAP(VP8E_SET_CQ_LEVEL, xcfg.cq_level);
476 MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT, xcfg.rc_max_intra_bitrate_pct);
477 MAP(VP9E_SET_LOSSLESS, xcfg.lossless);
478 MAP(VP9E_SET_FRAME_PARALLEL_DECODING, xcfg.frame_parallel_decoding_mode);
479 MAP(VP9E_SET_AQ_MODE, xcfg.aq_mode);
482 res = validate_config(ctx, &ctx->cfg, &xcfg);
484 if (res == VPX_CODEC_OK) {
486 set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
487 vp9_change_config(ctx->cpi, &ctx->oxcf);
495 static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx) {
496 vpx_codec_err_t res = VPX_CODEC_OK;
497 struct vpx_codec_alg_priv *priv;
498 vpx_codec_enc_cfg_t *cfg;
503 if (ctx->priv == NULL) {
504 priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
506 if (priv == NULL) return VPX_CODEC_MEM_ERROR;
508 ctx->priv = &priv->base;
509 ctx->priv->sz = sizeof(*ctx->priv);
510 ctx->priv->iface = ctx->iface;
511 ctx->priv->alg_priv = priv;
512 ctx->priv->init_flags = ctx->init_flags;
513 ctx->priv->enc.total_encoders = 1;
515 if (ctx->config.enc) {
516 /* Update the reference to the config structure to an
519 ctx->priv->alg_priv->cfg = *ctx->config.enc;
520 ctx->config.enc = &ctx->priv->alg_priv->cfg;
523 cfg = &ctx->priv->alg_priv->cfg;
525 /* Select the extra vp6 configuration table based on the current
526 * usage value. If the current usage value isn't found, use the
527 * values for usage case 0.
530 extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage;
533 priv->vp8_cfg = extracfg_map[i].cfg;
534 priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
536 // Maximum buffer size approximated based on having multiple ARF.
537 priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8;
539 if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096;
541 priv->cx_data = malloc(priv->cx_data_sz);
543 if (priv->cx_data == NULL) return VPX_CODEC_MEM_ERROR;
545 vp9_initialize_enc();
547 res = validate_config(priv, &priv->cfg, &priv->vp8_cfg);
549 if (res == VPX_CODEC_OK) {
550 set_vp9e_config(&ctx->priv->alg_priv->oxcf,
551 ctx->priv->alg_priv->cfg,
552 ctx->priv->alg_priv->vp8_cfg);
553 optr = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
556 res = VPX_CODEC_MEM_ERROR;
558 ctx->priv->alg_priv->cpi = optr;
566 static vpx_codec_err_t vp9e_init(vpx_codec_ctx_t *ctx,
567 vpx_codec_priv_enc_mr_cfg_t *data) {
568 return vp9e_common_init(ctx);
571 static vpx_codec_err_t vp9e_destroy(vpx_codec_alg_priv_t *ctx) {
573 vp9_remove_compressor(&ctx->cpi);
578 static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
579 unsigned long duration,
580 unsigned long deadline) {
583 /* Use best quality mode if no deadline is given. */
584 new_qc = MODE_BESTQUALITY;
587 uint64_t duration_us;
589 /* Convert duration parameter from stream timebase to microseconds */
590 duration_us = (uint64_t)duration * 1000000
591 * (uint64_t)ctx->cfg.g_timebase.num
592 / (uint64_t)ctx->cfg.g_timebase.den;
594 /* If the deadline is more that the duration this frame is to be shown,
595 * use good quality mode. Otherwise use realtime mode.
597 new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
600 if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
601 new_qc = MODE_FIRSTPASS;
602 else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
603 new_qc = (new_qc == MODE_BESTQUALITY)
604 ? MODE_SECONDPASS_BEST
607 if (ctx->oxcf.mode != new_qc) {
608 ctx->oxcf.mode = new_qc;
609 vp9_change_config(ctx->cpi, &ctx->oxcf);
614 static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
615 uint8_t marker = 0xc0;
619 assert(ctx->pending_frame_count);
620 assert(ctx->pending_frame_count <= 8);
622 /* Add the number of frames to the marker byte */
623 marker |= ctx->pending_frame_count - 1;
625 /* Choose the magnitude */
626 for (mag = 0, mask = 0xff; mag < 4; mag++) {
627 if (ctx->pending_frame_magnitude < mask)
634 /* Write the index */
635 index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
636 if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
637 uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
641 for (i = 0; i < ctx->pending_frame_count; i++) {
642 int this_sz = ctx->pending_frame_sizes[i];
644 for (j = 0; j <= mag; j++) {
645 *x++ = this_sz & 0xff;
650 ctx->pending_cx_data_sz += index_sz;
655 static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t *ctx,
656 const vpx_image_t *img,
658 unsigned long duration,
659 vpx_enc_frame_flags_t flags,
660 unsigned long deadline) {
661 vpx_codec_err_t res = VPX_CODEC_OK;
664 res = validate_img(ctx, img);
666 pick_quickcompress_mode(ctx, duration, deadline);
667 vpx_codec_pkt_list_init(&ctx->pkt_list);
670 if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF))
671 || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
672 ctx->base.err_detail = "Conflicting flags.";
673 return VPX_CODEC_INVALID_PARAM;
676 if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF
677 | VP8_EFLAG_NO_REF_ARF)) {
680 if (flags & VP8_EFLAG_NO_REF_LAST)
681 ref ^= VP9_LAST_FLAG;
683 if (flags & VP8_EFLAG_NO_REF_GF)
684 ref ^= VP9_GOLD_FLAG;
686 if (flags & VP8_EFLAG_NO_REF_ARF)
689 vp9_use_as_reference(ctx->cpi, ref);
692 if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF
693 | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF
694 | VP8_EFLAG_FORCE_ARF)) {
697 if (flags & VP8_EFLAG_NO_UPD_LAST)
698 upd ^= VP9_LAST_FLAG;
700 if (flags & VP8_EFLAG_NO_UPD_GF)
701 upd ^= VP9_GOLD_FLAG;
703 if (flags & VP8_EFLAG_NO_UPD_ARF)
706 vp9_update_reference(ctx->cpi, upd);
709 if (flags & VP8_EFLAG_NO_UPD_ENTROPY) {
710 vp9_update_entropy(ctx->cpi, 0);
713 /* Handle fixed keyframe intervals */
714 if (ctx->cfg.kf_mode == VPX_KF_AUTO
715 && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
716 if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
717 flags |= VPX_EFLAG_FORCE_KF;
718 ctx->fixed_kf_cntr = 1;
722 /* Initialize the encoder instance on the first frame. */
723 if (res == VPX_CODEC_OK && ctx->cpi != NULL) {
724 unsigned int lib_flags;
725 YV12_BUFFER_CONFIG sd;
726 int64_t dst_time_stamp, dst_end_time_stamp;
727 size_t size, cx_data_sz;
728 unsigned char *cx_data;
730 /* Set up internal flags */
731 if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
732 ((VP9_COMP *)ctx->cpi)->b_calculate_psnr = 1;
734 /* Convert API flags to internal codec lib flags */
735 lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
737 /* vp8 use 10,000,000 ticks/second as time stamp */
738 dst_time_stamp = pts * 10000000 * ctx->cfg.g_timebase.num
739 / ctx->cfg.g_timebase.den;
740 dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num /
741 ctx->cfg.g_timebase.den;
744 res = image2yuvconfig(img, &sd);
746 if (vp9_receive_raw_frame(ctx->cpi, lib_flags,
747 &sd, dst_time_stamp, dst_end_time_stamp)) {
748 VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
749 res = update_error_state(ctx, &cpi->common.error);
753 cx_data = ctx->cx_data;
754 cx_data_sz = ctx->cx_data_sz;
757 /* Any pending invisible frames? */
758 if (ctx->pending_cx_data) {
759 memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
760 ctx->pending_cx_data = cx_data;
761 cx_data += ctx->pending_cx_data_sz;
762 cx_data_sz -= ctx->pending_cx_data_sz;
764 /* TODO: this is a minimal check, the underlying codec doesn't respect
765 * the buffer size anyway.
767 if (cx_data_sz < ctx->cx_data_sz / 2) {
768 ctx->base.err_detail = "Compressed data buffer too small";
769 return VPX_CODEC_ERROR;
773 while (cx_data_sz >= ctx->cx_data_sz / 2 &&
774 -1 != vp9_get_compressed_data(ctx->cpi, &lib_flags, &size,
775 cx_data, &dst_time_stamp,
776 &dst_end_time_stamp, !img)) {
778 vpx_codec_pts_t round, delta;
779 vpx_codec_cx_pkt_t pkt;
780 VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
782 /* Pack invisible frames with the next visible frame */
783 if (cpi->common.show_frame == 0) {
784 if (ctx->pending_cx_data == 0)
785 ctx->pending_cx_data = cx_data;
786 ctx->pending_cx_data_sz += size;
787 ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
788 ctx->pending_frame_magnitude |= size;
794 /* Add the frame packet to the list of returned packets. */
795 round = (vpx_codec_pts_t)1000000 * ctx->cfg.g_timebase.num / 2 - 1;
796 delta = (dst_end_time_stamp - dst_time_stamp);
797 pkt.kind = VPX_CODEC_CX_FRAME_PKT;
799 (dst_time_stamp * ctx->cfg.g_timebase.den + round)
800 / ctx->cfg.g_timebase.num / 10000000;
801 pkt.data.frame.duration = (unsigned long)
802 ((delta * ctx->cfg.g_timebase.den + round)
803 / ctx->cfg.g_timebase.num / 10000000);
804 pkt.data.frame.flags = lib_flags << 16;
806 if (lib_flags & FRAMEFLAGS_KEY)
807 pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
809 if (cpi->common.show_frame == 0) {
810 pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
812 // This timestamp should be as close as possible to the
813 // prior PTS so that if a decoder uses pts to schedule when
814 // to do this, we start right after last frame was decoded.
815 // Invisible frames have no duration.
816 pkt.data.frame.pts = ((cpi->last_time_stamp_seen
817 * ctx->cfg.g_timebase.den + round)
818 / ctx->cfg.g_timebase.num / 10000000) + 1;
819 pkt.data.frame.duration = 0;
823 pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
825 /*if (cpi->output_partition)
828 const int num_partitions = 1;
830 pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
832 for (i = 0; i < num_partitions; ++i)
834 pkt.data.frame.buf = cx_data;
835 pkt.data.frame.sz = cpi->partition_sz[i];
836 pkt.data.frame.partition_id = i;
837 // don't set the fragment bit for the last partition
838 if (i == (num_partitions - 1))
839 pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
840 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
841 cx_data += cpi->partition_sz[i];
842 cx_data_sz -= cpi->partition_sz[i];
847 if (ctx->pending_cx_data) {
848 ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
849 ctx->pending_frame_magnitude |= size;
850 ctx->pending_cx_data_sz += size;
851 size += write_superframe_index(ctx);
852 pkt.data.frame.buf = ctx->pending_cx_data;
853 pkt.data.frame.sz = ctx->pending_cx_data_sz;
854 ctx->pending_cx_data = NULL;
855 ctx->pending_cx_data_sz = 0;
856 ctx->pending_frame_count = 0;
857 ctx->pending_frame_magnitude = 0;
859 pkt.data.frame.buf = cx_data;
860 pkt.data.frame.sz = size;
862 pkt.data.frame.partition_id = -1;
863 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
875 static const vpx_codec_cx_pkt_t *vp9e_get_cxdata(vpx_codec_alg_priv_t *ctx,
876 vpx_codec_iter_t *iter) {
877 return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
880 static vpx_codec_err_t vp9e_set_reference(vpx_codec_alg_priv_t *ctx,
883 vpx_ref_frame_t *frame = va_arg(args, vpx_ref_frame_t *);
886 YV12_BUFFER_CONFIG sd;
888 image2yuvconfig(&frame->img, &sd);
889 vp9_set_reference_enc(ctx->cpi, ref_frame_to_vp9_reframe(frame->frame_type),
893 return VPX_CODEC_INVALID_PARAM;
897 static vpx_codec_err_t vp9e_copy_reference(vpx_codec_alg_priv_t *ctx,
900 vpx_ref_frame_t *frame = va_arg(args, vpx_ref_frame_t *);
903 YV12_BUFFER_CONFIG sd;
905 image2yuvconfig(&frame->img, &sd);
906 vp9_copy_reference_enc(ctx->cpi,
907 ref_frame_to_vp9_reframe(frame->frame_type), &sd);
910 return VPX_CODEC_INVALID_PARAM;
914 static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx,
917 vp9_ref_frame_t *frame = va_arg(args, vp9_ref_frame_t *);
920 YV12_BUFFER_CONFIG* fb;
922 vp9_get_reference_enc(ctx->cpi, frame->idx, &fb);
923 yuvconfig2image(&frame->img, fb, NULL);
926 return VPX_CODEC_INVALID_PARAM;
930 static vpx_codec_err_t vp9e_set_previewpp(vpx_codec_alg_priv_t *ctx,
933 #if CONFIG_VP9_POSTPROC
934 vp8_postproc_cfg_t *config = va_arg(args, vp8_postproc_cfg_t *);
937 if (config != NULL) {
938 ctx->preview_ppcfg = *config;
941 return VPX_CODEC_INVALID_PARAM;
947 return VPX_CODEC_INCAPABLE;
952 static vpx_image_t *vp9e_get_preview(vpx_codec_alg_priv_t *ctx) {
953 YV12_BUFFER_CONFIG sd;
954 vp9_ppflags_t flags = {0};
956 if (ctx->preview_ppcfg.post_proc_flag) {
957 flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag;
958 flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
959 flags.noise_level = ctx->preview_ppcfg.noise_level;
962 if (0 == vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags)) {
963 yuvconfig2image(&ctx->preview_img, &sd, NULL);
964 return &ctx->preview_img;
970 static vpx_codec_err_t vp9e_update_entropy(vpx_codec_alg_priv_t *ctx,
973 int update = va_arg(args, int);
974 vp9_update_entropy(ctx->cpi, update);
978 static vpx_codec_err_t vp9e_update_reference(vpx_codec_alg_priv_t *ctx,
981 int update = va_arg(args, int);
982 vp9_update_reference(ctx->cpi, update);
986 static vpx_codec_err_t vp9e_use_reference(vpx_codec_alg_priv_t *ctx,
989 int reference_flag = va_arg(args, int);
990 vp9_use_as_reference(ctx->cpi, reference_flag);
994 static vpx_codec_err_t vp9e_set_roi_map(vpx_codec_alg_priv_t *ctx,
997 // TODO(yaowu): Need to re-implement and test for VP9.
998 return VPX_CODEC_INVALID_PARAM;
1002 static vpx_codec_err_t vp9e_set_activemap(vpx_codec_alg_priv_t *ctx,
1005 // TODO(yaowu): Need to re-implement and test for VP9.
1006 return VPX_CODEC_INVALID_PARAM;
1009 static vpx_codec_err_t vp9e_set_scalemode(vpx_codec_alg_priv_t *ctx,
1012 vpx_scaling_mode_t *scalemode = va_arg(args, vpx_scaling_mode_t *);
1014 if (scalemode != NULL) {
1016 res = vp9_set_internal_size(ctx->cpi,
1017 (VPX_SCALING)scalemode->h_scaling_mode,
1018 (VPX_SCALING)scalemode->v_scaling_mode);
1019 return (res == 0) ? VPX_CODEC_OK : VPX_CODEC_INVALID_PARAM;
1021 return VPX_CODEC_INVALID_PARAM;
1025 static vpx_codec_err_t vp9e_set_svc(vpx_codec_alg_priv_t *ctx, int ctr_id,
1027 int data = va_arg(args, int);
1028 vp9_set_svc(ctx->cpi, data);
1029 // CBR mode for SVC with both temporal and spatial layers not yet supported.
1031 ctx->cfg.rc_end_usage == VPX_CBR &&
1032 ctx->cfg.ss_number_layers > 1 &&
1033 ctx->cfg.ts_number_layers > 1) {
1034 return VPX_CODEC_INVALID_PARAM;
1036 return VPX_CODEC_OK;
1039 static vpx_codec_err_t vp9e_set_svc_layer_id(vpx_codec_alg_priv_t *ctx,
1042 vpx_svc_layer_id_t *data = va_arg(args, vpx_svc_layer_id_t *);
1043 VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
1044 cpi->svc.spatial_layer_id = data->spatial_layer_id;
1045 cpi->svc.temporal_layer_id = data->temporal_layer_id;
1046 // Checks on valid layer_id input.
1047 if (cpi->svc.temporal_layer_id < 0 ||
1048 cpi->svc.temporal_layer_id >= (int)ctx->cfg.ts_number_layers) {
1049 return VPX_CODEC_INVALID_PARAM;
1051 if (cpi->svc.spatial_layer_id < 0 ||
1052 cpi->svc.spatial_layer_id >= ctx->cfg.ss_number_layers) {
1053 return VPX_CODEC_INVALID_PARAM;
1055 return VPX_CODEC_OK;
1058 static vpx_codec_err_t vp9e_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
1059 int ctr_id, va_list args) {
1060 VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
1061 vpx_svc_parameters_t *params = va_arg(args, vpx_svc_parameters_t *);
1063 if (params == NULL) return VPX_CODEC_INVALID_PARAM;
1065 cpi->svc.spatial_layer_id = params->spatial_layer;
1066 cpi->svc.temporal_layer_id = params->temporal_layer;
1068 cpi->lst_fb_idx = params->lst_fb_idx;
1069 cpi->gld_fb_idx = params->gld_fb_idx;
1070 cpi->alt_fb_idx = params->alt_fb_idx;
1072 if (vp9_set_size_literal(ctx->cpi, params->width, params->height) != 0)
1073 return VPX_CODEC_INVALID_PARAM;
1075 ctx->cfg.rc_max_quantizer = params->max_quantizer;
1076 ctx->cfg.rc_min_quantizer = params->min_quantizer;
1078 set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
1079 vp9_change_config(ctx->cpi, &ctx->oxcf);
1081 return VPX_CODEC_OK;
1084 static vpx_codec_ctrl_fn_map_t vp9e_ctf_maps[] = {
1085 {VP8_SET_REFERENCE, vp9e_set_reference},
1086 {VP8_COPY_REFERENCE, vp9e_copy_reference},
1087 {VP8_SET_POSTPROC, vp9e_set_previewpp},
1088 {VP8E_UPD_ENTROPY, vp9e_update_entropy},
1089 {VP8E_UPD_REFERENCE, vp9e_update_reference},
1090 {VP8E_USE_REFERENCE, vp9e_use_reference},
1091 {VP8E_SET_ROI_MAP, vp9e_set_roi_map},
1092 {VP8E_SET_ACTIVEMAP, vp9e_set_activemap},
1093 {VP8E_SET_SCALEMODE, vp9e_set_scalemode},
1094 {VP8E_SET_CPUUSED, set_param},
1095 {VP8E_SET_NOISE_SENSITIVITY, set_param},
1096 {VP8E_SET_ENABLEAUTOALTREF, set_param},
1097 {VP8E_SET_SHARPNESS, set_param},
1098 {VP8E_SET_STATIC_THRESHOLD, set_param},
1099 {VP9E_SET_TILE_COLUMNS, set_param},
1100 {VP9E_SET_TILE_ROWS, set_param},
1101 {VP8E_GET_LAST_QUANTIZER, get_param},
1102 {VP8E_GET_LAST_QUANTIZER_64, get_param},
1103 {VP8E_SET_ARNR_MAXFRAMES, set_param},
1104 {VP8E_SET_ARNR_STRENGTH, set_param},
1105 {VP8E_SET_ARNR_TYPE, set_param},
1106 {VP8E_SET_TUNING, set_param},
1107 {VP8E_SET_CQ_LEVEL, set_param},
1108 {VP8E_SET_MAX_INTRA_BITRATE_PCT, set_param},
1109 {VP9E_SET_LOSSLESS, set_param},
1110 {VP9E_SET_FRAME_PARALLEL_DECODING, set_param},
1111 {VP9E_SET_AQ_MODE, set_param},
1112 {VP9_GET_REFERENCE, get_reference},
1113 {VP9E_SET_SVC, vp9e_set_svc},
1114 {VP9E_SET_SVC_PARAMETERS, vp9e_set_svc_parameters},
1115 {VP9E_SET_SVC_LAYER_ID, vp9e_set_svc_layer_id},
1119 static vpx_codec_enc_cfg_map_t vp9e_usage_cfg_map[] = {
1129 {1, 30}, /* g_timebase */
1131 0, /* g_error_resilient */
1133 VPX_RC_ONE_PASS, /* g_pass */
1135 25, /* g_lag_in_frames */
1137 0, /* rc_dropframe_thresh */
1138 0, /* rc_resize_allowed */
1139 60, /* rc_resize_down_thresold */
1140 30, /* rc_resize_up_thresold */
1142 VPX_VBR, /* rc_end_usage */
1143 #if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
1144 {0}, /* rc_twopass_stats_in */
1146 256, /* rc_target_bandwidth */
1147 0, /* rc_min_quantizer */
1148 63, /* rc_max_quantizer */
1149 100, /* rc_undershoot_pct */
1150 100, /* rc_overshoot_pct */
1152 6000, /* rc_max_buffer_size */
1153 4000, /* rc_buffer_initial_size; */
1154 5000, /* rc_buffer_optimal_size; */
1156 50, /* rc_two_pass_vbrbias */
1157 0, /* rc_two_pass_vbrmin_section */
1158 2000, /* rc_two_pass_vbrmax_section */
1160 /* keyframing settings (kf) */
1161 VPX_KF_AUTO, /* g_kfmode*/
1162 0, /* kf_min_dist */
1163 9999, /* kf_max_dist */
1165 VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */
1166 1, /* ts_number_layers */
1167 {0}, /* ts_target_bitrate */
1168 {0}, /* ts_rate_decimator */
1169 0, /* ts_periodicity */
1170 {0}, /* ts_layer_id */
1171 #if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
1172 "vp8.fpf" /* first pass filename */
1176 { -1, {NOT_IMPLEMENTED}}
1180 #ifndef VERSION_STRING
1181 #define VERSION_STRING
1183 CODEC_INTERFACE(vpx_codec_vp9_cx) = {
1184 "WebM Project VP9 Encoder" VERSION_STRING,
1185 VPX_CODEC_INTERNAL_ABI_VERSION,
1186 VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR |
1187 VPX_CODEC_CAP_OUTPUT_PARTITION,
1188 /* vpx_codec_caps_t caps; */
1189 vp9e_init, /* vpx_codec_init_fn_t init; */
1190 vp9e_destroy, /* vpx_codec_destroy_fn_t destroy; */
1191 vp9e_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1192 NOT_IMPLEMENTED, /* vpx_codec_get_mmap_fn_t get_mmap; */
1193 NOT_IMPLEMENTED, /* vpx_codec_set_mmap_fn_t set_mmap; */
1195 NOT_IMPLEMENTED, /* vpx_codec_peek_si_fn_t peek_si; */
1196 NOT_IMPLEMENTED, /* vpx_codec_get_si_fn_t get_si; */
1197 NOT_IMPLEMENTED, /* vpx_codec_decode_fn_t decode; */
1198 NOT_IMPLEMENTED, /* vpx_codec_frame_get_fn_t frame_get; */
1201 vp9e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t peek_si; */
1202 vp9e_encode, /* vpx_codec_encode_fn_t encode; */
1203 vp9e_get_cxdata, /* vpx_codec_get_cx_data_fn_t frame_get; */
1207 } /* encoder functions */