Removed unnecessary xd->mode_info_context assignment
[aom.git] / vp9 / vp9_cx_iface.c
blobe5b50894c9a9abccd6c9ef8861861724cb93d70f
1 /*
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.
9 */
12 #include "vpx/vpx_codec.h"
13 #include "vpx/internal/vpx_codec_internal.h"
14 #include "vpx_version.h"
15 #include "vp9/encoder/vp9_onyx_int.h"
16 #include "vpx/vp8cx.h"
17 #include "vp9/encoder/vp9_firstpass.h"
18 #include "vp9/common/vp9_onyx.h"
19 #include "vp9/vp9_iface_common.h"
20 #include <stdlib.h>
21 #include <string.h>
23 struct vp9_extracfg {
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; /** if encoder decides to uses alternate reference frame */
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; /* alt_ref Noise Reduction Max Frame Count */
33 unsigned int arnr_strength; /* alt_ref Noise Reduction Strength */
34 unsigned int arnr_type; /* alt_ref filter type */
35 unsigned int experimental;
36 vp8e_tuning tuning;
37 unsigned int cq_level; /* constrained quality level */
38 unsigned int rc_max_intra_bitrate_pct;
39 unsigned int lossless;
40 unsigned int frame_parallel_decoding_mode;
43 struct extraconfig_map {
44 int usage;
45 struct vp9_extracfg cfg;
48 static const struct extraconfig_map extracfg_map[] = {
52 NULL,
53 0, /* cpu_used */
54 0, /* enable_auto_alt_ref */
55 0, /* noise_sensitivity */
56 0, /* Sharpness */
57 0, /* static_thresh */
58 0, /* tile_columns */
59 0, /* tile_rows */
60 0, /* arnr_max_frames */
61 3, /* arnr_strength */
62 3, /* arnr_type*/
63 0, /* experimental mode */
64 0, /* tuning*/
65 10, /* cq_level */
66 0, /* rc_max_intra_bitrate_pct */
67 0, /* lossless */
68 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;
77 VP9_CONFIG oxcf;
78 VP9_PTR cpi;
79 unsigned char *cx_data;
80 unsigned int cx_data_sz;
81 unsigned char *pending_cx_data;
82 unsigned int pending_cx_data_sz;
83 int pending_frame_count;
84 uint32_t pending_frame_sizes[8];
85 uint32_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; // changed to accomendate the maximum number of lagged frames allowed
89 unsigned int fixed_kf_cntr;
93 static vpx_codec_err_t
94 update_error_state(vpx_codec_alg_priv_t *ctx,
95 const struct vpx_internal_error_info *error) {
96 vpx_codec_err_t res;
98 if ((res = error->error_code))
99 ctx->base.err_detail = error->has_detail
100 ? error->detail
101 : NULL;
103 return res;
107 #undef ERROR
108 #define ERROR(str) do {\
109 ctx->base.err_detail = str;\
110 return VPX_CODEC_INVALID_PARAM;\
111 } while(0)
113 #define RANGE_CHECK(p,memb,lo,hi) do {\
114 if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
115 ERROR(#memb " out of range ["#lo".."#hi"]");\
116 } while(0)
118 #define RANGE_CHECK_HI(p,memb,hi) do {\
119 if(!((p)->memb <= (hi))) \
120 ERROR(#memb " out of range [.."#hi"]");\
121 } while(0)
123 #define RANGE_CHECK_LO(p,memb,lo) do {\
124 if(!((p)->memb >= (lo))) \
125 ERROR(#memb " out of range ["#lo"..]");\
126 } while(0)
128 #define RANGE_CHECK_BOOL(p,memb) do {\
129 if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
130 } while(0)
132 static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
133 const vpx_codec_enc_cfg_t *cfg,
134 const struct vp9_extracfg *vp8_cfg) {
135 RANGE_CHECK(cfg, g_w, 1, 65535); /* 16 bits available */
136 RANGE_CHECK(cfg, g_h, 1, 65535); /* 16 bits available */
137 RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
138 RANGE_CHECK(cfg, g_timebase.num, 1, cfg->g_timebase.den);
139 RANGE_CHECK_HI(cfg, g_profile, 3);
141 RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
142 RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
143 RANGE_CHECK_BOOL(vp8_cfg, lossless);
144 if (vp8_cfg->lossless) {
145 RANGE_CHECK_HI(cfg, rc_max_quantizer, 0);
146 RANGE_CHECK_HI(cfg, rc_min_quantizer, 0);
149 RANGE_CHECK_HI(cfg, g_threads, 64);
150 RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
151 RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_CQ);
152 RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000);
153 RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000);
154 RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
155 RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO);
156 // RANGE_CHECK_BOOL(cfg, g_delete_firstpassfile);
157 RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
158 RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
159 RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
160 RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
161 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
163 /* VP8 does not support a lower bound on the keyframe interval in
164 * automatic keyframe placement mode.
166 if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist
167 && cfg->kf_min_dist > 0)
168 ERROR("kf_min_dist not supported in auto mode, use 0 "
169 "or kf_max_dist instead.");
171 RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref);
172 RANGE_CHECK(vp8_cfg, cpu_used, -16, 16);
174 RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6);
176 RANGE_CHECK(vp8_cfg, tile_columns, 0, 6);
177 RANGE_CHECK(vp8_cfg, tile_rows, 0, 2);
178 RANGE_CHECK_HI(vp8_cfg, Sharpness, 7);
179 RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
180 RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6);
181 RANGE_CHECK(vp8_cfg, arnr_type, 1, 3);
182 RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
184 if (cfg->g_pass == VPX_RC_LAST_PASS) {
185 size_t packet_sz = sizeof(FIRSTPASS_STATS);
186 int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
187 FIRSTPASS_STATS *stats;
189 if (!cfg->rc_twopass_stats_in.buf)
190 ERROR("rc_twopass_stats_in.buf not set.");
192 if (cfg->rc_twopass_stats_in.sz % packet_sz)
193 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
195 if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
196 ERROR("rc_twopass_stats_in requires at least two packets.");
198 stats = (void *)((char *)cfg->rc_twopass_stats_in.buf
199 + (n_packets - 1) * packet_sz);
201 if ((int)(stats->count + 0.5) != n_packets - 1)
202 ERROR("rc_twopass_stats_in missing EOS stats packet");
205 return VPX_CODEC_OK;
209 static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
210 const vpx_image_t *img) {
211 switch (img->fmt) {
212 case VPX_IMG_FMT_YV12:
213 case VPX_IMG_FMT_I420:
214 case VPX_IMG_FMT_I422:
215 case VPX_IMG_FMT_I444:
216 break;
217 default:
218 ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
219 "supported.");
222 if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
223 ERROR("Image size must match encoder init configuration size");
225 return VPX_CODEC_OK;
229 static vpx_codec_err_t set_vp9e_config(VP9_CONFIG *oxcf,
230 vpx_codec_enc_cfg_t cfg,
231 struct vp9_extracfg vp8_cfg) {
232 oxcf->version = cfg.g_profile | (vp8_cfg.experimental ? 0x4 : 0);
233 oxcf->width = cfg.g_w;
234 oxcf->height = cfg.g_h;
235 /* guess a frame rate if out of whack, use 30 */
236 oxcf->frame_rate = (double)(cfg.g_timebase.den) / (double)(cfg.g_timebase.num);
238 if (oxcf->frame_rate > 180) {
239 oxcf->frame_rate = 30;
242 switch (cfg.g_pass) {
243 case VPX_RC_ONE_PASS:
244 oxcf->Mode = MODE_BESTQUALITY;
245 break;
246 case VPX_RC_FIRST_PASS:
247 oxcf->Mode = MODE_FIRSTPASS;
248 break;
249 case VPX_RC_LAST_PASS:
250 oxcf->Mode = MODE_SECONDPASS_BEST;
251 break;
254 if (cfg.g_pass == VPX_RC_FIRST_PASS) {
255 oxcf->allow_lag = 0;
256 oxcf->lag_in_frames = 0;
257 } else {
258 oxcf->allow_lag = (cfg.g_lag_in_frames) > 0;
259 oxcf->lag_in_frames = cfg.g_lag_in_frames;
262 // VBR only supported for now.
263 // CBR code has been deprectated for experimental phase.
264 // CQ mode not yet tested
265 oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
266 /*if (cfg.rc_end_usage == VPX_CQ)
267 oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
268 else
269 oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;*/
271 oxcf->target_bandwidth = cfg.rc_target_bitrate;
272 oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
274 oxcf->best_allowed_q = cfg.rc_min_quantizer;
275 oxcf->worst_allowed_q = cfg.rc_max_quantizer;
276 oxcf->cq_level = vp8_cfg.cq_level;
277 oxcf->fixed_q = -1;
279 oxcf->under_shoot_pct = cfg.rc_undershoot_pct;
280 oxcf->over_shoot_pct = cfg.rc_overshoot_pct;
282 oxcf->maximum_buffer_size = cfg.rc_buf_sz;
283 oxcf->starting_buffer_level = cfg.rc_buf_initial_sz;
284 oxcf->optimal_buffer_level = cfg.rc_buf_optimal_sz;
286 oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct;
287 oxcf->two_pass_vbrmin_section = cfg.rc_2pass_vbr_minsection_pct;
288 oxcf->two_pass_vbrmax_section = cfg.rc_2pass_vbr_maxsection_pct;
290 oxcf->auto_key = cfg.kf_mode == VPX_KF_AUTO
291 && cfg.kf_min_dist != cfg.kf_max_dist;
292 // oxcf->kf_min_dist = cfg.kf_min_dis;
293 oxcf->key_freq = cfg.kf_max_dist;
295 // oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
296 // strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
298 oxcf->cpu_used = vp8_cfg.cpu_used;
299 oxcf->encode_breakout = vp8_cfg.static_thresh;
300 oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
301 oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity;
302 oxcf->Sharpness = vp8_cfg.Sharpness;
304 oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in;
305 oxcf->output_pkt_list = vp8_cfg.pkt_list;
307 oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
308 oxcf->arnr_strength = vp8_cfg.arnr_strength;
309 oxcf->arnr_type = vp8_cfg.arnr_type;
311 oxcf->tuning = vp8_cfg.tuning;
313 oxcf->tile_columns = vp8_cfg.tile_columns;
314 oxcf->tile_rows = vp8_cfg.tile_rows;
316 oxcf->lossless = vp8_cfg.lossless;
318 oxcf->error_resilient_mode = cfg.g_error_resilient;
319 oxcf->frame_parallel_decoding_mode = vp8_cfg.frame_parallel_decoding_mode;
321 printf("Current VP9 Settings: \n");
322 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
323 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
324 printf("Sharpness: %d\n", oxcf->Sharpness);
325 printf("cpu_used: %d\n", oxcf->cpu_used);
326 printf("Mode: %d\n", oxcf->Mode);
327 // printf("delete_first_pass_file: %d\n", oxcf->delete_first_pass_file);
328 printf("auto_key: %d\n", oxcf->auto_key);
329 printf("key_freq: %d\n", oxcf->key_freq);
330 printf("end_usage: %d\n", oxcf->end_usage);
331 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
332 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
333 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
334 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
335 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
336 printf("fixed_q: %d\n", oxcf->fixed_q);
337 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
338 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
339 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
340 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
341 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
342 printf("allow_lag: %d\n", oxcf->allow_lag);
343 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
344 printf("play_alternate: %d\n", oxcf->play_alternate);
345 printf("Version: %d\n", oxcf->Version);
346 printf("encode_breakout: %d\n", oxcf->encode_breakout);
347 printf("error resilient: %d\n", oxcf->error_resilient_mode);
348 printf("frame parallel detokenization: %d\n",
349 oxcf->frame_parallel_decoding_mode);
351 return VPX_CODEC_OK;
354 static vpx_codec_err_t vp9e_set_config(vpx_codec_alg_priv_t *ctx,
355 const vpx_codec_enc_cfg_t *cfg) {
356 vpx_codec_err_t res;
358 if ((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h))
359 ERROR("Cannot change width or height after initialization");
361 /* Prevent increasing lag_in_frames. This check is stricter than it needs
362 * to be -- the limit is not increasing past the first lag_in_frames
363 * value, but we don't track the initial config, only the last successful
364 * config.
366 if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames))
367 ERROR("Cannot increase lag_in_frames");
369 res = validate_config(ctx, cfg, &ctx->vp8_cfg);
371 if (!res) {
372 ctx->cfg = *cfg;
373 set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
374 vp9_change_config(ctx->cpi, &ctx->oxcf);
377 return res;
381 int vp9_reverse_trans(int q);
384 static vpx_codec_err_t get_param(vpx_codec_alg_priv_t *ctx,
385 int ctrl_id,
386 va_list args) {
387 void *arg = va_arg(args, void *);
389 #define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
391 if (!arg)
392 return VPX_CODEC_INVALID_PARAM;
394 switch (ctrl_id) {
395 MAP(VP8E_GET_LAST_QUANTIZER, vp9_get_quantizer(ctx->cpi));
396 MAP(VP8E_GET_LAST_QUANTIZER_64,
397 vp9_reverse_trans(vp9_get_quantizer(ctx->cpi)));
400 return VPX_CODEC_OK;
401 #undef MAP
405 static vpx_codec_err_t set_param(vpx_codec_alg_priv_t *ctx,
406 int ctrl_id,
407 va_list args) {
408 vpx_codec_err_t res = VPX_CODEC_OK;
409 struct vp9_extracfg xcfg = ctx->vp8_cfg;
411 #define MAP(id, var) case id: var = CAST(id, args); break;
413 switch (ctrl_id) {
414 MAP(VP8E_SET_CPUUSED, xcfg.cpu_used);
415 MAP(VP8E_SET_ENABLEAUTOALTREF, xcfg.enable_auto_alt_ref);
416 MAP(VP8E_SET_NOISE_SENSITIVITY, xcfg.noise_sensitivity);
417 MAP(VP8E_SET_SHARPNESS, xcfg.Sharpness);
418 MAP(VP8E_SET_STATIC_THRESHOLD, xcfg.static_thresh);
419 MAP(VP9E_SET_TILE_COLUMNS, xcfg.tile_columns);
420 MAP(VP9E_SET_TILE_ROWS, xcfg.tile_rows);
422 MAP(VP8E_SET_ARNR_MAXFRAMES, xcfg.arnr_max_frames);
423 MAP(VP8E_SET_ARNR_STRENGTH, xcfg.arnr_strength);
424 MAP(VP8E_SET_ARNR_TYPE, xcfg.arnr_type);
425 MAP(VP8E_SET_TUNING, xcfg.tuning);
426 MAP(VP8E_SET_CQ_LEVEL, xcfg.cq_level);
427 MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT, xcfg.rc_max_intra_bitrate_pct);
428 MAP(VP9E_SET_LOSSLESS, xcfg.lossless);
429 MAP(VP9E_SET_FRAME_PARALLEL_DECODING, xcfg.frame_parallel_decoding_mode);
432 res = validate_config(ctx, &ctx->cfg, &xcfg);
434 if (!res) {
435 ctx->vp8_cfg = xcfg;
436 set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
437 vp9_change_config(ctx->cpi, &ctx->oxcf);
440 return res;
441 #undef MAP
445 static vpx_codec_err_t vp9e_common_init(vpx_codec_ctx_t *ctx,
446 int experimental) {
447 vpx_codec_err_t res = VPX_CODEC_OK;
448 struct vpx_codec_alg_priv *priv;
449 vpx_codec_enc_cfg_t *cfg;
450 unsigned int i;
452 VP9_PTR optr;
454 if (!ctx->priv) {
455 priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
457 if (!priv) {
458 return VPX_CODEC_MEM_ERROR;
461 ctx->priv = &priv->base;
462 ctx->priv->sz = sizeof(*ctx->priv);
463 ctx->priv->iface = ctx->iface;
464 ctx->priv->alg_priv = priv;
465 ctx->priv->init_flags = ctx->init_flags;
466 ctx->priv->enc.total_encoders = 1;
468 if (ctx->config.enc) {
469 /* Update the reference to the config structure to an
470 * internal copy.
472 ctx->priv->alg_priv->cfg = *ctx->config.enc;
473 ctx->config.enc = &ctx->priv->alg_priv->cfg;
476 cfg = &ctx->priv->alg_priv->cfg;
478 /* Select the extra vp6 configuration table based on the current
479 * usage value. If the current usage value isn't found, use the
480 * values for usage case 0.
482 for (i = 0;
483 extracfg_map[i].usage && extracfg_map[i].usage != cfg->g_usage;
484 i++);
486 priv->vp8_cfg = extracfg_map[i].cfg;
487 priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
488 priv->vp8_cfg.experimental = experimental;
490 // TODO(agrange) Check the limits set on this buffer, or the check that is
491 // applied in vp9e_encode.
492 priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8;
493 // priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
495 if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096;
497 priv->cx_data = malloc(priv->cx_data_sz);
499 if (!priv->cx_data) {
500 return VPX_CODEC_MEM_ERROR;
503 vp9_initialize_enc();
505 res = validate_config(priv, &priv->cfg, &priv->vp8_cfg);
507 if (!res) {
508 set_vp9e_config(&ctx->priv->alg_priv->oxcf,
509 ctx->priv->alg_priv->cfg,
510 ctx->priv->alg_priv->vp8_cfg);
511 optr = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
513 if (!optr)
514 res = VPX_CODEC_MEM_ERROR;
515 else
516 ctx->priv->alg_priv->cpi = optr;
520 return res;
524 static vpx_codec_err_t vp9e_init(vpx_codec_ctx_t *ctx,
525 vpx_codec_priv_enc_mr_cfg_t *data) {
526 return vp9e_common_init(ctx, 0);
530 #if CONFIG_EXPERIMENTAL
531 static vpx_codec_err_t vp9e_exp_init(vpx_codec_ctx_t *ctx,
532 vpx_codec_priv_enc_mr_cfg_t *data) {
533 return vp9e_common_init(ctx, 1);
535 #endif
538 static vpx_codec_err_t vp9e_destroy(vpx_codec_alg_priv_t *ctx) {
540 free(ctx->cx_data);
541 vp9_remove_compressor(&ctx->cpi);
542 free(ctx);
543 return VPX_CODEC_OK;
546 static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
547 unsigned long duration,
548 unsigned long deadline) {
549 unsigned int new_qc;
551 /* Use best quality mode if no deadline is given. */
552 if (deadline)
553 new_qc = MODE_GOODQUALITY;
554 else
555 new_qc = MODE_BESTQUALITY;
557 if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
558 new_qc = MODE_FIRSTPASS;
559 else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
560 new_qc = (new_qc == MODE_BESTQUALITY)
561 ? MODE_SECONDPASS_BEST
562 : MODE_SECONDPASS;
564 if (ctx->oxcf.Mode != new_qc) {
565 ctx->oxcf.Mode = new_qc;
566 vp9_change_config(ctx->cpi, &ctx->oxcf);
571 static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
572 uint8_t marker = 0xc0;
573 int mag, mask, index_sz;
575 assert(ctx->pending_frame_count);
576 assert(ctx->pending_frame_count <= 8);
578 /* Add the number of frames to the marker byte */
579 marker |= ctx->pending_frame_count - 1;
581 /* Choose the magnitude */
582 for (mag = 0, mask = 0xff; mag < 4; mag++) {
583 if (ctx->pending_frame_magnitude < mask)
584 break;
585 mask <<= 8;
586 mask |= 0xff;
588 marker |= mag << 3;
590 /* Write the index */
591 index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
592 if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
593 uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
594 int i, j;
596 *x++ = marker;
597 for (i = 0; i < ctx->pending_frame_count; i++) {
598 int this_sz = ctx->pending_frame_sizes[i];
600 for (j = 0; j <= mag; j++) {
601 *x++ = this_sz & 0xff;
602 this_sz >>= 8;
605 *x++ = marker;
606 ctx->pending_cx_data_sz += index_sz;
608 return index_sz;
611 static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t *ctx,
612 const vpx_image_t *img,
613 vpx_codec_pts_t pts,
614 unsigned long duration,
615 vpx_enc_frame_flags_t flags,
616 unsigned long deadline) {
617 vpx_codec_err_t res = VPX_CODEC_OK;
619 if (img)
620 res = validate_img(ctx, img);
622 pick_quickcompress_mode(ctx, duration, deadline);
623 vpx_codec_pkt_list_init(&ctx->pkt_list);
625 /* Handle Flags */
626 if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF))
627 || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
628 ctx->base.err_detail = "Conflicting flags.";
629 return VPX_CODEC_INVALID_PARAM;
632 if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF
633 | VP8_EFLAG_NO_REF_ARF)) {
634 int ref = 7;
636 if (flags & VP8_EFLAG_NO_REF_LAST)
637 ref ^= VP9_LAST_FLAG;
639 if (flags & VP8_EFLAG_NO_REF_GF)
640 ref ^= VP9_GOLD_FLAG;
642 if (flags & VP8_EFLAG_NO_REF_ARF)
643 ref ^= VP9_ALT_FLAG;
645 vp9_use_as_reference(ctx->cpi, ref);
648 if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF
649 | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF
650 | VP8_EFLAG_FORCE_ARF)) {
651 int upd = 7;
653 if (flags & VP8_EFLAG_NO_UPD_LAST)
654 upd ^= VP9_LAST_FLAG;
656 if (flags & VP8_EFLAG_NO_UPD_GF)
657 upd ^= VP9_GOLD_FLAG;
659 if (flags & VP8_EFLAG_NO_UPD_ARF)
660 upd ^= VP9_ALT_FLAG;
662 vp9_update_reference(ctx->cpi, upd);
665 if (flags & VP8_EFLAG_NO_UPD_ENTROPY) {
666 vp9_update_entropy(ctx->cpi, 0);
669 /* Handle fixed keyframe intervals */
670 if (ctx->cfg.kf_mode == VPX_KF_AUTO
671 && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
672 if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
673 flags |= VPX_EFLAG_FORCE_KF;
674 ctx->fixed_kf_cntr = 1;
678 /* Initialize the encoder instance on the first frame*/
679 if (!res && ctx->cpi) {
680 unsigned int lib_flags;
681 YV12_BUFFER_CONFIG sd;
682 int64_t dst_time_stamp, dst_end_time_stamp;
683 unsigned long size, cx_data_sz;
684 unsigned char *cx_data;
686 /* Set up internal flags */
687 if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
688 ((VP9_COMP *)ctx->cpi)->b_calculate_psnr = 1;
690 // if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
691 // ((VP9_COMP *)ctx->cpi)->output_partition = 1;
693 /* Convert API flags to internal codec lib flags */
694 lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
696 /* vp8 use 10,000,000 ticks/second as time stamp */
697 dst_time_stamp = pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
698 dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
700 if (img != NULL) {
701 res = image2yuvconfig(img, &sd);
703 if (vp9_receive_raw_frame(ctx->cpi, lib_flags,
704 &sd, dst_time_stamp, dst_end_time_stamp)) {
705 VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
706 res = update_error_state(ctx, &cpi->common.error);
710 cx_data = ctx->cx_data;
711 cx_data_sz = ctx->cx_data_sz;
712 lib_flags = 0;
714 /* Any pending invisible frames? */
715 if (ctx->pending_cx_data) {
716 memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
717 ctx->pending_cx_data = cx_data;
718 cx_data += ctx->pending_cx_data_sz;
719 cx_data_sz -= ctx->pending_cx_data_sz;
721 /* TODO: this is a minimal check, the underlying codec doesn't respect
722 * the buffer size anyway.
724 if (cx_data_sz < ctx->cx_data_sz / 2) {
725 ctx->base.err_detail = "Compressed data buffer too small";
726 return VPX_CODEC_ERROR;
730 while (cx_data_sz >= ctx->cx_data_sz / 2 &&
731 -1 != vp9_get_compressed_data(ctx->cpi, &lib_flags, &size,
732 cx_data, &dst_time_stamp,
733 &dst_end_time_stamp, !img)) {
734 if (size) {
735 vpx_codec_pts_t round, delta;
736 vpx_codec_cx_pkt_t pkt;
737 VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
739 /* Pack invisible frames with the next visible frame */
740 if (!cpi->common.show_frame) {
741 if (!ctx->pending_cx_data)
742 ctx->pending_cx_data = cx_data;
743 ctx->pending_cx_data_sz += size;
744 ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
745 ctx->pending_frame_magnitude |= size;
746 cx_data += size;
747 cx_data_sz -= size;
748 continue;
751 /* Add the frame packet to the list of returned packets. */
752 round = 1000000 * ctx->cfg.g_timebase.num / 2 - 1;
753 delta = (dst_end_time_stamp - dst_time_stamp);
754 pkt.kind = VPX_CODEC_CX_FRAME_PKT;
755 pkt.data.frame.pts =
756 (dst_time_stamp * ctx->cfg.g_timebase.den + round)
757 / ctx->cfg.g_timebase.num / 10000000;
758 pkt.data.frame.duration = (unsigned long)
759 ((delta * ctx->cfg.g_timebase.den + round)
760 / ctx->cfg.g_timebase.num / 10000000);
761 pkt.data.frame.flags = lib_flags << 16;
763 if (lib_flags & FRAMEFLAGS_KEY)
764 pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
766 if (!cpi->common.show_frame) {
767 pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
769 // This timestamp should be as close as possible to the
770 // prior PTS so that if a decoder uses pts to schedule when
771 // to do this, we start right after last frame was decoded.
772 // Invisible frames have no duration.
773 pkt.data.frame.pts = ((cpi->last_time_stamp_seen
774 * ctx->cfg.g_timebase.den + round)
775 / ctx->cfg.g_timebase.num / 10000000) + 1;
776 pkt.data.frame.duration = 0;
779 if (cpi->droppable)
780 pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
782 /*if (cpi->output_partition)
784 int i;
785 const int num_partitions = 1;
787 pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
789 for (i = 0; i < num_partitions; ++i)
791 pkt.data.frame.buf = cx_data;
792 pkt.data.frame.sz = cpi->partition_sz[i];
793 pkt.data.frame.partition_id = i;
794 // don't set the fragment bit for the last partition
795 if (i == (num_partitions - 1))
796 pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
797 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
798 cx_data += cpi->partition_sz[i];
799 cx_data_sz -= cpi->partition_sz[i];
802 else*/
804 if (ctx->pending_cx_data) {
805 ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
806 ctx->pending_frame_magnitude |= size;
807 ctx->pending_cx_data_sz += size;
808 size += write_superframe_index(ctx);
809 pkt.data.frame.buf = ctx->pending_cx_data;
810 pkt.data.frame.sz = ctx->pending_cx_data_sz;
811 ctx->pending_cx_data = NULL;
812 ctx->pending_cx_data_sz = 0;
813 ctx->pending_frame_count = 0;
814 ctx->pending_frame_magnitude = 0;
815 } else {
816 pkt.data.frame.buf = cx_data;
817 pkt.data.frame.sz = size;
819 pkt.data.frame.partition_id = -1;
820 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
821 cx_data += size;
822 cx_data_sz -= size;
825 // printf("timestamp: %lld, duration: %d\n", pkt->data.frame.pts, pkt->data.frame.duration);
830 return res;
834 static const vpx_codec_cx_pkt_t *vp9e_get_cxdata(vpx_codec_alg_priv_t *ctx,
835 vpx_codec_iter_t *iter) {
836 return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
839 static vpx_codec_err_t vp9e_set_reference(vpx_codec_alg_priv_t *ctx,
840 int ctr_id,
841 va_list args) {
842 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
844 if (data) {
845 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
846 YV12_BUFFER_CONFIG sd;
848 image2yuvconfig(&frame->img, &sd);
849 vp9_set_reference_enc(ctx->cpi, frame->frame_type, &sd);
850 return VPX_CODEC_OK;
851 } else
852 return VPX_CODEC_INVALID_PARAM;
856 static vpx_codec_err_t vp9e_copy_reference(vpx_codec_alg_priv_t *ctx,
857 int ctr_id,
858 va_list args) {
860 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
862 if (data) {
863 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
864 YV12_BUFFER_CONFIG sd;
866 image2yuvconfig(&frame->img, &sd);
867 vp9_copy_reference_enc(ctx->cpi, frame->frame_type, &sd);
868 return VPX_CODEC_OK;
869 } else
870 return VPX_CODEC_INVALID_PARAM;
873 static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx,
874 int ctr_id,
875 va_list args) {
876 vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
878 if (data) {
879 YV12_BUFFER_CONFIG* fb;
881 vp9_get_reference_enc(ctx->cpi, data->idx, &fb);
882 yuvconfig2image(&data->img, fb, NULL);
883 return VPX_CODEC_OK;
884 } else {
885 return VPX_CODEC_INVALID_PARAM;
889 static vpx_codec_err_t vp9e_set_previewpp(vpx_codec_alg_priv_t *ctx,
890 int ctr_id,
891 va_list args) {
892 #if CONFIG_POSTPROC
893 vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
894 (void)ctr_id;
896 if (data) {
897 ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
898 return VPX_CODEC_OK;
899 } else
900 return VPX_CODEC_INVALID_PARAM;
901 #else
902 (void)ctx;
903 (void)ctr_id;
904 (void)args;
905 return VPX_CODEC_INCAPABLE;
906 #endif
910 static vpx_image_t *vp9e_get_preview(vpx_codec_alg_priv_t *ctx) {
912 YV12_BUFFER_CONFIG sd;
913 vp9_ppflags_t flags = {0};
915 if (ctx->preview_ppcfg.post_proc_flag) {
916 flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag;
917 flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
918 flags.noise_level = ctx->preview_ppcfg.noise_level;
921 if (0 == vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags)) {
922 yuvconfig2image(&ctx->preview_img, &sd, NULL);
923 return &ctx->preview_img;
924 } else
925 return NULL;
928 static vpx_codec_err_t vp9e_update_entropy(vpx_codec_alg_priv_t *ctx,
929 int ctr_id,
930 va_list args) {
931 int update = va_arg(args, int);
932 vp9_update_entropy(ctx->cpi, update);
933 return VPX_CODEC_OK;
937 static vpx_codec_err_t vp9e_update_reference(vpx_codec_alg_priv_t *ctx,
938 int ctr_id,
939 va_list args) {
940 int update = va_arg(args, int);
941 vp9_update_reference(ctx->cpi, update);
942 return VPX_CODEC_OK;
945 static vpx_codec_err_t vp9e_use_reference(vpx_codec_alg_priv_t *ctx,
946 int ctr_id,
947 va_list args) {
948 int reference_flag = va_arg(args, int);
949 vp9_use_as_reference(ctx->cpi, reference_flag);
950 return VPX_CODEC_OK;
953 static vpx_codec_err_t vp9e_set_roi_map(vpx_codec_alg_priv_t *ctx,
954 int ctr_id,
955 va_list args) {
956 vpx_roi_map_t *data = va_arg(args, vpx_roi_map_t *);
958 if (data) {
959 vpx_roi_map_t *roi = (vpx_roi_map_t *)data;
961 if (!vp9_set_roimap(ctx->cpi, roi->roi_map, roi->rows, roi->cols,
962 roi->delta_q, roi->delta_lf, roi->static_threshold))
963 return VPX_CODEC_OK;
964 else
965 return VPX_CODEC_INVALID_PARAM;
966 } else
967 return VPX_CODEC_INVALID_PARAM;
971 static vpx_codec_err_t vp9e_set_activemap(vpx_codec_alg_priv_t *ctx,
972 int ctr_id,
973 va_list args) {
974 vpx_active_map_t *data = va_arg(args, vpx_active_map_t *);
976 if (data) {
978 vpx_active_map_t *map = (vpx_active_map_t *)data;
980 if (!vp9_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols))
981 return VPX_CODEC_OK;
982 else
983 return VPX_CODEC_INVALID_PARAM;
984 } else
985 return VPX_CODEC_INVALID_PARAM;
988 static vpx_codec_err_t vp9e_set_scalemode(vpx_codec_alg_priv_t *ctx,
989 int ctr_id,
990 va_list args) {
992 vpx_scaling_mode_t *data = va_arg(args, vpx_scaling_mode_t *);
994 if (data) {
995 int res;
996 vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data;
997 res = vp9_set_internal_size(ctx->cpi, scalemode.h_scaling_mode,
998 scalemode.v_scaling_mode);
1000 if (!res) {
1001 return VPX_CODEC_OK;
1002 } else
1003 return VPX_CODEC_INVALID_PARAM;
1004 } else
1005 return VPX_CODEC_INVALID_PARAM;
1009 static vpx_codec_ctrl_fn_map_t vp9e_ctf_maps[] = {
1010 {VP8_SET_REFERENCE, vp9e_set_reference},
1011 {VP8_COPY_REFERENCE, vp9e_copy_reference},
1012 {VP8_SET_POSTPROC, vp9e_set_previewpp},
1013 {VP8E_UPD_ENTROPY, vp9e_update_entropy},
1014 {VP8E_UPD_REFERENCE, vp9e_update_reference},
1015 {VP8E_USE_REFERENCE, vp9e_use_reference},
1016 {VP8E_SET_ROI_MAP, vp9e_set_roi_map},
1017 {VP8E_SET_ACTIVEMAP, vp9e_set_activemap},
1018 {VP8E_SET_SCALEMODE, vp9e_set_scalemode},
1019 {VP8E_SET_CPUUSED, set_param},
1020 {VP8E_SET_NOISE_SENSITIVITY, set_param},
1021 {VP8E_SET_ENABLEAUTOALTREF, set_param},
1022 {VP8E_SET_SHARPNESS, set_param},
1023 {VP8E_SET_STATIC_THRESHOLD, set_param},
1024 {VP9E_SET_TILE_COLUMNS, set_param},
1025 {VP9E_SET_TILE_ROWS, set_param},
1026 {VP8E_GET_LAST_QUANTIZER, get_param},
1027 {VP8E_GET_LAST_QUANTIZER_64, get_param},
1028 {VP8E_SET_ARNR_MAXFRAMES, set_param},
1029 {VP8E_SET_ARNR_STRENGTH, set_param},
1030 {VP8E_SET_ARNR_TYPE, set_param},
1031 {VP8E_SET_TUNING, set_param},
1032 {VP8E_SET_CQ_LEVEL, set_param},
1033 {VP8E_SET_MAX_INTRA_BITRATE_PCT, set_param},
1034 {VP9E_SET_LOSSLESS, set_param},
1035 {VP9_GET_REFERENCE, get_reference},
1036 { -1, NULL},
1039 static vpx_codec_enc_cfg_map_t vp9e_usage_cfg_map[] = {
1043 0, /* g_usage */
1044 0, /* g_threads */
1045 0, /* g_profile */
1047 320, /* g_width */
1048 240, /* g_height */
1049 {1, 30}, /* g_timebase */
1051 0, /* g_error_resilient */
1053 VPX_RC_ONE_PASS, /* g_pass */
1055 0, /* g_lag_in_frames */
1057 0, /* rc_dropframe_thresh */
1058 0, /* rc_resize_allowed */
1059 60, /* rc_resize_down_thresold */
1060 30, /* rc_resize_up_thresold */
1062 VPX_VBR, /* rc_end_usage */
1063 #if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
1064 {0}, /* rc_twopass_stats_in */
1065 #endif
1066 256, /* rc_target_bandwidth */
1067 4, /* rc_min_quantizer */
1068 63, /* rc_max_quantizer */
1069 100, /* rc_undershoot_pct */
1070 100, /* rc_overshoot_pct */
1072 6000, /* rc_max_buffer_size */
1073 4000, /* rc_buffer_initial_size; */
1074 5000, /* rc_buffer_optimal_size; */
1076 50, /* rc_two_pass_vbrbias */
1077 0, /* rc_two_pass_vbrmin_section */
1078 400, /* rc_two_pass_vbrmax_section */
1080 /* keyframing settings (kf) */
1081 VPX_KF_AUTO, /* g_kfmode*/
1082 0, /* kf_min_dist */
1083 9999, /* kf_max_dist */
1085 #if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
1086 1, /* g_delete_first_pass_file */
1087 "vp8.fpf" /* first pass filename */
1088 #endif
1091 { -1, {NOT_IMPLEMENTED}}
1095 #ifndef VERSION_STRING
1096 #define VERSION_STRING
1097 #endif
1098 CODEC_INTERFACE(vpx_codec_vp9_cx) = {
1099 "WebM Project VP9 Encoder" VERSION_STRING,
1100 VPX_CODEC_INTERNAL_ABI_VERSION,
1101 VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR |
1102 VPX_CODEC_CAP_OUTPUT_PARTITION,
1103 /* vpx_codec_caps_t caps; */
1104 vp9e_init, /* vpx_codec_init_fn_t init; */
1105 vp9e_destroy, /* vpx_codec_destroy_fn_t destroy; */
1106 vp9e_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1107 NOT_IMPLEMENTED, /* vpx_codec_get_mmap_fn_t get_mmap; */
1108 NOT_IMPLEMENTED, /* vpx_codec_set_mmap_fn_t set_mmap; */
1110 NOT_IMPLEMENTED, /* vpx_codec_peek_si_fn_t peek_si; */
1111 NOT_IMPLEMENTED, /* vpx_codec_get_si_fn_t get_si; */
1112 NOT_IMPLEMENTED, /* vpx_codec_decode_fn_t decode; */
1113 NOT_IMPLEMENTED, /* vpx_codec_frame_get_fn_t frame_get; */
1116 vp9e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t peek_si; */
1117 vp9e_encode, /* vpx_codec_encode_fn_t encode; */
1118 vp9e_get_cxdata, /* vpx_codec_get_cx_data_fn_t frame_get; */
1119 vp9e_set_config,
1120 NOT_IMPLEMENTED,
1121 vp9e_get_preview,
1122 } /* encoder functions */
1126 #if CONFIG_EXPERIMENTAL
1128 CODEC_INTERFACE(vpx_codec_vp9x_cx) = {
1129 "VP8 Experimental Encoder" VERSION_STRING,
1130 VPX_CODEC_INTERNAL_ABI_VERSION,
1131 VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,
1132 /* vpx_codec_caps_t caps; */
1133 vp9e_exp_init, /* vpx_codec_init_fn_t init; */
1134 vp9e_destroy, /* vpx_codec_destroy_fn_t destroy; */
1135 vp9e_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1136 NOT_IMPLEMENTED, /* vpx_codec_get_mmap_fn_t get_mmap; */
1137 NOT_IMPLEMENTED, /* vpx_codec_set_mmap_fn_t set_mmap; */
1139 NOT_IMPLEMENTED, /* vpx_codec_peek_si_fn_t peek_si; */
1140 NOT_IMPLEMENTED, /* vpx_codec_get_si_fn_t get_si; */
1141 NOT_IMPLEMENTED, /* vpx_codec_decode_fn_t decode; */
1142 NOT_IMPLEMENTED, /* vpx_codec_frame_get_fn_t frame_get; */
1145 vp9e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t peek_si; */
1146 vp9e_encode, /* vpx_codec_encode_fn_t encode; */
1147 vp9e_get_cxdata, /* vpx_codec_get_cx_data_fn_t frame_get; */
1148 vp9e_set_config,
1149 NOT_IMPLEMENTED,
1150 vp9e_get_preview,
1151 } /* encoder functions */
1153 #endif