Home | History | Annotate | Download | only in vp8
      1 /*
      2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
      3  *
      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  */
     10 
     11 #include "./vpx_config.h"
     12 #include "./vp8_rtcd.h"
     13 #include "./vpx_dsp_rtcd.h"
     14 #include "./vpx_scale_rtcd.h"
     15 #include "vpx/vpx_codec.h"
     16 #include "vpx/internal/vpx_codec_internal.h"
     17 #include "vpx_version.h"
     18 #include "vpx_mem/vpx_mem.h"
     19 #include "vpx_ports/vpx_once.h"
     20 #include "vp8/encoder/onyx_int.h"
     21 #include "vpx/vp8cx.h"
     22 #include "vp8/encoder/firstpass.h"
     23 #include "vp8/common/onyx.h"
     24 #include "vp8/common/common.h"
     25 #include <stdlib.h>
     26 #include <string.h>
     27 
     28 struct vp8_extracfg {
     29   struct vpx_codec_pkt_list *pkt_list;
     30   int cpu_used; /** available cpu percentage in 1/16*/
     31   /** if encoder decides to uses alternate reference frame */
     32   unsigned int enable_auto_alt_ref;
     33   unsigned int noise_sensitivity;
     34   unsigned int Sharpness;
     35   unsigned int static_thresh;
     36   unsigned int token_partitions;
     37   unsigned int arnr_max_frames; /* alt_ref Noise Reduction Max Frame Count */
     38   unsigned int arnr_strength;   /* alt_ref Noise Reduction Strength */
     39   unsigned int arnr_type;       /* alt_ref filter type */
     40   vp8e_tuning tuning;
     41   unsigned int cq_level; /* constrained quality level */
     42   unsigned int rc_max_intra_bitrate_pct;
     43   unsigned int gf_cbr_boost_pct;
     44   unsigned int screen_content_mode;
     45 };
     46 
     47 static struct vp8_extracfg default_extracfg = {
     48   NULL,
     49 #if !(CONFIG_REALTIME_ONLY)
     50   0, /* cpu_used      */
     51 #else
     52   4, /* cpu_used      */
     53 #endif
     54   0, /* enable_auto_alt_ref */
     55   0, /* noise_sensitivity */
     56   0, /* Sharpness */
     57   0, /* static_thresh */
     58 #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
     59   VP8_EIGHT_TOKENPARTITION,
     60 #else
     61   VP8_ONE_TOKENPARTITION, /* token_partitions */
     62 #endif
     63   0,  /* arnr_max_frames */
     64   3,  /* arnr_strength */
     65   3,  /* arnr_type*/
     66   0,  /* tuning*/
     67   10, /* cq_level */
     68   0,  /* rc_max_intra_bitrate_pct */
     69   0,  /* gf_cbr_boost_pct */
     70   0,  /* screen_content_mode */
     71 };
     72 
     73 struct vpx_codec_alg_priv {
     74   vpx_codec_priv_t base;
     75   vpx_codec_enc_cfg_t cfg;
     76   struct vp8_extracfg vp8_cfg;
     77   VP8_CONFIG oxcf;
     78   struct VP8_COMP *cpi;
     79   unsigned char *cx_data;
     80   unsigned int cx_data_sz;
     81   vpx_image_t preview_img;
     82   unsigned int next_frame_flag;
     83   vp8_postproc_cfg_t preview_ppcfg;
     84   /* pkt_list size depends on the maximum number of lagged frames allowed. */
     85   vpx_codec_pkt_list_decl(64) pkt_list;
     86   unsigned int fixed_kf_cntr;
     87   vpx_enc_frame_flags_t control_frame_flags;
     88 };
     89 
     90 static vpx_codec_err_t update_error_state(
     91     vpx_codec_alg_priv_t *ctx, const struct vpx_internal_error_info *error) {
     92   vpx_codec_err_t res;
     93 
     94   if ((res = error->error_code)) {
     95     ctx->base.err_detail = error->has_detail ? error->detail : NULL;
     96   }
     97 
     98   return res;
     99 }
    100 
    101 #undef ERROR
    102 #define ERROR(str)                  \
    103   do {                              \
    104     ctx->base.err_detail = str;     \
    105     return VPX_CODEC_INVALID_PARAM; \
    106   } while (0)
    107 
    108 #define RANGE_CHECK(p, memb, lo, hi)                                 \
    109   do {                                                               \
    110     if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
    111       ERROR(#memb " out of range [" #lo ".." #hi "]");               \
    112   } while (0)
    113 
    114 #define RANGE_CHECK_HI(p, memb, hi)                                     \
    115   do {                                                                  \
    116     if (!((p)->memb <= (hi))) ERROR(#memb " out of range [.." #hi "]"); \
    117   } while (0)
    118 
    119 #define RANGE_CHECK_LO(p, memb, lo)                                     \
    120   do {                                                                  \
    121     if (!((p)->memb >= (lo))) ERROR(#memb " out of range [" #lo "..]"); \
    122   } while (0)
    123 
    124 #define RANGE_CHECK_BOOL(p, memb)                                     \
    125   do {                                                                \
    126     if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
    127   } while (0)
    128 
    129 static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
    130                                        const vpx_codec_enc_cfg_t *cfg,
    131                                        const struct vp8_extracfg *vp8_cfg,
    132                                        int finalize) {
    133   RANGE_CHECK(cfg, g_w, 1, 16383); /* 14 bits available */
    134   RANGE_CHECK(cfg, g_h, 1, 16383); /* 14 bits available */
    135   RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
    136   RANGE_CHECK(cfg, g_timebase.num, 1, 1000000000);
    137   RANGE_CHECK_HI(cfg, g_profile, 3);
    138   RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
    139   RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
    140   RANGE_CHECK_HI(cfg, g_threads, 64);
    141 #if CONFIG_REALTIME_ONLY
    142   RANGE_CHECK_HI(cfg, g_lag_in_frames, 0);
    143 #elif CONFIG_MULTI_RES_ENCODING
    144   if (ctx->base.enc.total_encoders > 1) RANGE_CHECK_HI(cfg, g_lag_in_frames, 0);
    145 #else
    146   RANGE_CHECK_HI(cfg, g_lag_in_frames, 25);
    147 #endif
    148   RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q);
    149   RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000);
    150   RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000);
    151   RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
    152   RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO);
    153 
    154 /* TODO: add spatial re-sampling support and frame dropping in
    155  * multi-res-encoder.*/
    156 #if CONFIG_MULTI_RES_ENCODING
    157   if (ctx->base.enc.total_encoders > 1)
    158     RANGE_CHECK_HI(cfg, rc_resize_allowed, 0);
    159 #else
    160   RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
    161 #endif
    162   RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
    163   RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
    164   RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
    165 
    166 #if CONFIG_REALTIME_ONLY
    167   RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
    168 #elif CONFIG_MULTI_RES_ENCODING
    169   if (ctx->base.enc.total_encoders > 1)
    170     RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
    171 #else
    172   RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
    173 #endif
    174 
    175   /* VP8 does not support a lower bound on the keyframe interval in
    176    * automatic keyframe placement mode.
    177    */
    178   if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist &&
    179       cfg->kf_min_dist > 0)
    180     ERROR(
    181         "kf_min_dist not supported in auto mode, use 0 "
    182         "or kf_max_dist instead.");
    183 
    184   RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref);
    185   RANGE_CHECK(vp8_cfg, cpu_used, -16, 16);
    186 
    187 #if CONFIG_REALTIME_ONLY && !CONFIG_TEMPORAL_DENOISING
    188   RANGE_CHECK(vp8_cfg, noise_sensitivity, 0, 0);
    189 #else
    190   RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6);
    191 #endif
    192 
    193   RANGE_CHECK(vp8_cfg, token_partitions, VP8_ONE_TOKENPARTITION,
    194               VP8_EIGHT_TOKENPARTITION);
    195   RANGE_CHECK_HI(vp8_cfg, Sharpness, 7);
    196   RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
    197   RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6);
    198   RANGE_CHECK(vp8_cfg, arnr_type, 1, 3);
    199   RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
    200   RANGE_CHECK_HI(vp8_cfg, screen_content_mode, 2);
    201   if (finalize && (cfg->rc_end_usage == VPX_CQ || cfg->rc_end_usage == VPX_Q))
    202     RANGE_CHECK(vp8_cfg, cq_level, cfg->rc_min_quantizer,
    203                 cfg->rc_max_quantizer);
    204 
    205 #if !(CONFIG_REALTIME_ONLY)
    206   if (cfg->g_pass == VPX_RC_LAST_PASS) {
    207     size_t packet_sz = sizeof(FIRSTPASS_STATS);
    208     int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
    209     FIRSTPASS_STATS *stats;
    210 
    211     if (!cfg->rc_twopass_stats_in.buf)
    212       ERROR("rc_twopass_stats_in.buf not set.");
    213 
    214     if (cfg->rc_twopass_stats_in.sz % packet_sz)
    215       ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
    216 
    217     if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
    218       ERROR("rc_twopass_stats_in requires at least two packets.");
    219 
    220     stats = (void *)((char *)cfg->rc_twopass_stats_in.buf +
    221                      (n_packets - 1) * packet_sz);
    222 
    223     if ((int)(stats->count + 0.5) != n_packets - 1)
    224       ERROR("rc_twopass_stats_in missing EOS stats packet");
    225   }
    226 #endif
    227 
    228   RANGE_CHECK(cfg, ts_number_layers, 1, 5);
    229 
    230   if (cfg->ts_number_layers > 1) {
    231     unsigned int i;
    232     RANGE_CHECK_HI(cfg, ts_periodicity, 16);
    233 
    234     for (i = 1; i < cfg->ts_number_layers; ++i) {
    235       if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i - 1] &&
    236           cfg->rc_target_bitrate > 0)
    237         ERROR("ts_target_bitrate entries are not strictly increasing");
    238     }
    239 
    240     RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
    241     for (i = cfg->ts_number_layers - 2; i > 0; i--) {
    242       if (cfg->ts_rate_decimator[i - 1] != 2 * cfg->ts_rate_decimator[i])
    243         ERROR("ts_rate_decimator factors are not powers of 2");
    244     }
    245 
    246     RANGE_CHECK_HI(cfg, ts_layer_id[i], cfg->ts_number_layers - 1);
    247   }
    248 
    249 #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
    250   if (cfg->g_threads > (1 << vp8_cfg->token_partitions))
    251     ERROR("g_threads cannot be bigger than number of token partitions");
    252 #endif
    253 
    254   return VPX_CODEC_OK;
    255 }
    256 
    257 static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
    258                                     const vpx_image_t *img) {
    259   switch (img->fmt) {
    260     case VPX_IMG_FMT_YV12:
    261     case VPX_IMG_FMT_I420:
    262     case VPX_IMG_FMT_VPXI420:
    263     case VPX_IMG_FMT_VPXYV12: break;
    264     default:
    265       ERROR("Invalid image format. Only YV12 and I420 images are supported");
    266   }
    267 
    268   if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
    269     ERROR("Image size must match encoder init configuration size");
    270 
    271   return VPX_CODEC_OK;
    272 }
    273 
    274 static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
    275                                        vpx_codec_enc_cfg_t cfg,
    276                                        struct vp8_extracfg vp8_cfg,
    277                                        vpx_codec_priv_enc_mr_cfg_t *mr_cfg) {
    278   oxcf->multi_threaded = cfg.g_threads;
    279   oxcf->Version = cfg.g_profile;
    280 
    281   oxcf->Width = cfg.g_w;
    282   oxcf->Height = cfg.g_h;
    283   oxcf->timebase = cfg.g_timebase;
    284 
    285   oxcf->error_resilient_mode = cfg.g_error_resilient;
    286 
    287   switch (cfg.g_pass) {
    288     case VPX_RC_ONE_PASS: oxcf->Mode = MODE_BESTQUALITY; break;
    289     case VPX_RC_FIRST_PASS: oxcf->Mode = MODE_FIRSTPASS; break;
    290     case VPX_RC_LAST_PASS: oxcf->Mode = MODE_SECONDPASS_BEST; break;
    291   }
    292 
    293   if (cfg.g_pass == VPX_RC_FIRST_PASS || cfg.g_pass == VPX_RC_ONE_PASS) {
    294     oxcf->allow_lag = 0;
    295     oxcf->lag_in_frames = 0;
    296   } else {
    297     oxcf->allow_lag = (cfg.g_lag_in_frames) > 0;
    298     oxcf->lag_in_frames = cfg.g_lag_in_frames;
    299   }
    300 
    301   oxcf->allow_df = (cfg.rc_dropframe_thresh > 0);
    302   oxcf->drop_frames_water_mark = cfg.rc_dropframe_thresh;
    303 
    304   oxcf->allow_spatial_resampling = cfg.rc_resize_allowed;
    305   oxcf->resample_up_water_mark = cfg.rc_resize_up_thresh;
    306   oxcf->resample_down_water_mark = cfg.rc_resize_down_thresh;
    307 
    308   if (cfg.rc_end_usage == VPX_VBR) {
    309     oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
    310   } else if (cfg.rc_end_usage == VPX_CBR) {
    311     oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
    312   } else if (cfg.rc_end_usage == VPX_CQ) {
    313     oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
    314   } else if (cfg.rc_end_usage == VPX_Q) {
    315     oxcf->end_usage = USAGE_CONSTANT_QUALITY;
    316   }
    317 
    318   oxcf->target_bandwidth = cfg.rc_target_bitrate;
    319   oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
    320   oxcf->gf_cbr_boost_pct = vp8_cfg.gf_cbr_boost_pct;
    321 
    322   oxcf->best_allowed_q = cfg.rc_min_quantizer;
    323   oxcf->worst_allowed_q = cfg.rc_max_quantizer;
    324   oxcf->cq_level = vp8_cfg.cq_level;
    325   oxcf->fixed_q = -1;
    326 
    327   oxcf->under_shoot_pct = cfg.rc_undershoot_pct;
    328   oxcf->over_shoot_pct = cfg.rc_overshoot_pct;
    329 
    330   oxcf->maximum_buffer_size_in_ms = cfg.rc_buf_sz;
    331   oxcf->starting_buffer_level_in_ms = cfg.rc_buf_initial_sz;
    332   oxcf->optimal_buffer_level_in_ms = cfg.rc_buf_optimal_sz;
    333 
    334   oxcf->maximum_buffer_size = cfg.rc_buf_sz;
    335   oxcf->starting_buffer_level = cfg.rc_buf_initial_sz;
    336   oxcf->optimal_buffer_level = cfg.rc_buf_optimal_sz;
    337 
    338   oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct;
    339   oxcf->two_pass_vbrmin_section = cfg.rc_2pass_vbr_minsection_pct;
    340   oxcf->two_pass_vbrmax_section = cfg.rc_2pass_vbr_maxsection_pct;
    341 
    342   oxcf->auto_key =
    343       cfg.kf_mode == VPX_KF_AUTO && cfg.kf_min_dist != cfg.kf_max_dist;
    344   oxcf->key_freq = cfg.kf_max_dist;
    345 
    346   oxcf->number_of_layers = cfg.ts_number_layers;
    347   oxcf->periodicity = cfg.ts_periodicity;
    348 
    349   if (oxcf->number_of_layers > 1) {
    350     memcpy(oxcf->target_bitrate, cfg.ts_target_bitrate,
    351            sizeof(cfg.ts_target_bitrate));
    352     memcpy(oxcf->rate_decimator, cfg.ts_rate_decimator,
    353            sizeof(cfg.ts_rate_decimator));
    354     memcpy(oxcf->layer_id, cfg.ts_layer_id, sizeof(cfg.ts_layer_id));
    355   }
    356 
    357 #if CONFIG_MULTI_RES_ENCODING
    358   /* When mr_cfg is NULL, oxcf->mr_total_resolutions and oxcf->mr_encoder_id
    359    * are both memset to 0, which ensures the correct logic under this
    360    * situation.
    361    */
    362   if (mr_cfg) {
    363     oxcf->mr_total_resolutions = mr_cfg->mr_total_resolutions;
    364     oxcf->mr_encoder_id = mr_cfg->mr_encoder_id;
    365     oxcf->mr_down_sampling_factor.num = mr_cfg->mr_down_sampling_factor.num;
    366     oxcf->mr_down_sampling_factor.den = mr_cfg->mr_down_sampling_factor.den;
    367     oxcf->mr_low_res_mode_info = mr_cfg->mr_low_res_mode_info;
    368   }
    369 #else
    370   (void)mr_cfg;
    371 #endif
    372 
    373   oxcf->cpu_used = vp8_cfg.cpu_used;
    374   oxcf->encode_breakout = vp8_cfg.static_thresh;
    375   oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
    376   oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity;
    377   oxcf->Sharpness = vp8_cfg.Sharpness;
    378   oxcf->token_partitions = vp8_cfg.token_partitions;
    379 
    380   oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in;
    381   oxcf->output_pkt_list = vp8_cfg.pkt_list;
    382 
    383   oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
    384   oxcf->arnr_strength = vp8_cfg.arnr_strength;
    385   oxcf->arnr_type = vp8_cfg.arnr_type;
    386 
    387   oxcf->tuning = vp8_cfg.tuning;
    388 
    389   oxcf->screen_content_mode = vp8_cfg.screen_content_mode;
    390 
    391   /*
    392       printf("Current VP8 Settings: \n");
    393       printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
    394       printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
    395       printf("Sharpness: %d\n",    oxcf->Sharpness);
    396       printf("cpu_used: %d\n",  oxcf->cpu_used);
    397       printf("Mode: %d\n",     oxcf->Mode);
    398       printf("auto_key: %d\n",  oxcf->auto_key);
    399       printf("key_freq: %d\n", oxcf->key_freq);
    400       printf("end_usage: %d\n", oxcf->end_usage);
    401       printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
    402       printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
    403       printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
    404       printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
    405       printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
    406       printf("fixed_q: %d\n",  oxcf->fixed_q);
    407       printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
    408       printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
    409       printf("allow_spatial_resampling: %d\n",  oxcf->allow_spatial_resampling);
    410       printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark);
    411       printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark);
    412       printf("allow_df: %d\n", oxcf->allow_df);
    413       printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark);
    414       printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
    415       printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
    416       printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
    417       printf("allow_lag: %d\n", oxcf->allow_lag);
    418       printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
    419       printf("play_alternate: %d\n", oxcf->play_alternate);
    420       printf("Version: %d\n", oxcf->Version);
    421       printf("multi_threaded: %d\n",   oxcf->multi_threaded);
    422       printf("encode_breakout: %d\n", oxcf->encode_breakout);
    423   */
    424   return VPX_CODEC_OK;
    425 }
    426 
    427 static vpx_codec_err_t vp8e_set_config(vpx_codec_alg_priv_t *ctx,
    428                                        const vpx_codec_enc_cfg_t *cfg) {
    429   vpx_codec_err_t res;
    430 
    431   if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h) {
    432     if (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS)
    433       ERROR("Cannot change width or height after initialization");
    434     if ((ctx->cpi->initial_width && (int)cfg->g_w > ctx->cpi->initial_width) ||
    435         (ctx->cpi->initial_height && (int)cfg->g_h > ctx->cpi->initial_height))
    436       ERROR("Cannot increase width or height larger than their initial values");
    437   }
    438 
    439   /* Prevent increasing lag_in_frames. This check is stricter than it needs
    440    * to be -- the limit is not increasing past the first lag_in_frames
    441    * value, but we don't track the initial config, only the last successful
    442    * config.
    443    */
    444   if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames))
    445     ERROR("Cannot increase lag_in_frames");
    446 
    447   res = validate_config(ctx, cfg, &ctx->vp8_cfg, 0);
    448 
    449   if (!res) {
    450     ctx->cfg = *cfg;
    451     set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
    452     vp8_change_config(ctx->cpi, &ctx->oxcf);
    453   }
    454 
    455   return res;
    456 }
    457 
    458 static vpx_codec_err_t get_quantizer(vpx_codec_alg_priv_t *ctx, va_list args) {
    459   int *const arg = va_arg(args, int *);
    460   if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
    461   *arg = vp8_get_quantizer(ctx->cpi);
    462   return VPX_CODEC_OK;
    463 }
    464 
    465 static vpx_codec_err_t get_quantizer64(vpx_codec_alg_priv_t *ctx,
    466                                        va_list args) {
    467   int *const arg = va_arg(args, int *);
    468   if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
    469   *arg = vp8_reverse_trans(vp8_get_quantizer(ctx->cpi));
    470   return VPX_CODEC_OK;
    471 }
    472 
    473 static vpx_codec_err_t update_extracfg(vpx_codec_alg_priv_t *ctx,
    474                                        const struct vp8_extracfg *extra_cfg) {
    475   const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg, 0);
    476   if (res == VPX_CODEC_OK) {
    477     ctx->vp8_cfg = *extra_cfg;
    478     set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
    479     vp8_change_config(ctx->cpi, &ctx->oxcf);
    480   }
    481   return res;
    482 }
    483 
    484 static vpx_codec_err_t set_cpu_used(vpx_codec_alg_priv_t *ctx, va_list args) {
    485   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    486   extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args);
    487   return update_extracfg(ctx, &extra_cfg);
    488 }
    489 
    490 static vpx_codec_err_t set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx,
    491                                                va_list args) {
    492   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    493   extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args);
    494   return update_extracfg(ctx, &extra_cfg);
    495 }
    496 
    497 static vpx_codec_err_t set_noise_sensitivity(vpx_codec_alg_priv_t *ctx,
    498                                              va_list args) {
    499   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    500   extra_cfg.noise_sensitivity = CAST(VP8E_SET_NOISE_SENSITIVITY, args);
    501   return update_extracfg(ctx, &extra_cfg);
    502 }
    503 
    504 static vpx_codec_err_t set_sharpness(vpx_codec_alg_priv_t *ctx, va_list args) {
    505   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    506   extra_cfg.Sharpness = CAST(VP8E_SET_SHARPNESS, args);
    507   return update_extracfg(ctx, &extra_cfg);
    508 }
    509 
    510 static vpx_codec_err_t set_static_thresh(vpx_codec_alg_priv_t *ctx,
    511                                          va_list args) {
    512   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    513   extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args);
    514   return update_extracfg(ctx, &extra_cfg);
    515 }
    516 
    517 static vpx_codec_err_t set_token_partitions(vpx_codec_alg_priv_t *ctx,
    518                                             va_list args) {
    519   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    520   extra_cfg.token_partitions = CAST(VP8E_SET_TOKEN_PARTITIONS, args);
    521   return update_extracfg(ctx, &extra_cfg);
    522 }
    523 
    524 static vpx_codec_err_t set_arnr_max_frames(vpx_codec_alg_priv_t *ctx,
    525                                            va_list args) {
    526   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    527   extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args);
    528   return update_extracfg(ctx, &extra_cfg);
    529 }
    530 
    531 static vpx_codec_err_t set_arnr_strength(vpx_codec_alg_priv_t *ctx,
    532                                          va_list args) {
    533   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    534   extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args);
    535   return update_extracfg(ctx, &extra_cfg);
    536 }
    537 
    538 static vpx_codec_err_t set_arnr_type(vpx_codec_alg_priv_t *ctx, va_list args) {
    539   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    540   extra_cfg.arnr_type = CAST(VP8E_SET_ARNR_TYPE, args);
    541   return update_extracfg(ctx, &extra_cfg);
    542 }
    543 
    544 static vpx_codec_err_t set_tuning(vpx_codec_alg_priv_t *ctx, va_list args) {
    545   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    546   extra_cfg.tuning = CAST(VP8E_SET_TUNING, args);
    547   return update_extracfg(ctx, &extra_cfg);
    548 }
    549 
    550 static vpx_codec_err_t set_cq_level(vpx_codec_alg_priv_t *ctx, va_list args) {
    551   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    552   extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args);
    553   return update_extracfg(ctx, &extra_cfg);
    554 }
    555 
    556 static vpx_codec_err_t set_rc_max_intra_bitrate_pct(vpx_codec_alg_priv_t *ctx,
    557                                                     va_list args) {
    558   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    559   extra_cfg.rc_max_intra_bitrate_pct =
    560       CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args);
    561   return update_extracfg(ctx, &extra_cfg);
    562 }
    563 
    564 static vpx_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(vpx_codec_alg_priv_t *ctx,
    565                                                     va_list args) {
    566   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    567   extra_cfg.gf_cbr_boost_pct = CAST(VP8E_SET_GF_CBR_BOOST_PCT, args);
    568   return update_extracfg(ctx, &extra_cfg);
    569 }
    570 
    571 static vpx_codec_err_t set_screen_content_mode(vpx_codec_alg_priv_t *ctx,
    572                                                va_list args) {
    573   struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
    574   extra_cfg.screen_content_mode = CAST(VP8E_SET_SCREEN_CONTENT_MODE, args);
    575   return update_extracfg(ctx, &extra_cfg);
    576 }
    577 
    578 static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg,
    579                                          void **mem_loc) {
    580   vpx_codec_err_t res = 0;
    581 
    582 #if CONFIG_MULTI_RES_ENCODING
    583   LOWER_RES_FRAME_INFO *shared_mem_loc;
    584   int mb_rows = ((cfg->g_w + 15) >> 4);
    585   int mb_cols = ((cfg->g_h + 15) >> 4);
    586 
    587   shared_mem_loc = calloc(1, sizeof(LOWER_RES_FRAME_INFO));
    588   if (!shared_mem_loc) {
    589     res = VPX_CODEC_MEM_ERROR;
    590   }
    591 
    592   shared_mem_loc->mb_info =
    593       calloc(mb_rows * mb_cols, sizeof(LOWER_RES_MB_INFO));
    594   if (!(shared_mem_loc->mb_info)) {
    595     res = VPX_CODEC_MEM_ERROR;
    596   } else {
    597     *mem_loc = (void *)shared_mem_loc;
    598     res = VPX_CODEC_OK;
    599   }
    600 #else
    601   (void)cfg;
    602   (void)mem_loc;
    603 #endif
    604   return res;
    605 }
    606 
    607 static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx,
    608                                  vpx_codec_priv_enc_mr_cfg_t *mr_cfg) {
    609   vpx_codec_err_t res = VPX_CODEC_OK;
    610 
    611   vp8_rtcd();
    612   vpx_dsp_rtcd();
    613   vpx_scale_rtcd();
    614 
    615   if (!ctx->priv) {
    616     struct vpx_codec_alg_priv *priv =
    617         (struct vpx_codec_alg_priv *)vpx_calloc(1, sizeof(*priv));
    618 
    619     if (!priv) {
    620       return VPX_CODEC_MEM_ERROR;
    621     }
    622 
    623     ctx->priv = (vpx_codec_priv_t *)priv;
    624     ctx->priv->init_flags = ctx->init_flags;
    625 
    626     if (ctx->config.enc) {
    627       /* Update the reference to the config structure to an
    628        * internal copy.
    629        */
    630       priv->cfg = *ctx->config.enc;
    631       ctx->config.enc = &priv->cfg;
    632     }
    633 
    634     priv->vp8_cfg = default_extracfg;
    635     priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
    636 
    637     priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
    638 
    639     if (priv->cx_data_sz < 32768) priv->cx_data_sz = 32768;
    640 
    641     priv->cx_data = malloc(priv->cx_data_sz);
    642 
    643     if (!priv->cx_data) {
    644       return VPX_CODEC_MEM_ERROR;
    645     }
    646 
    647     if (mr_cfg) {
    648       ctx->priv->enc.total_encoders = mr_cfg->mr_total_resolutions;
    649     } else {
    650       ctx->priv->enc.total_encoders = 1;
    651     }
    652 
    653     once(vp8_initialize_enc);
    654 
    655     res = validate_config(priv, &priv->cfg, &priv->vp8_cfg, 0);
    656 
    657     if (!res) {
    658       set_vp8e_config(&priv->oxcf, priv->cfg, priv->vp8_cfg, mr_cfg);
    659       priv->cpi = vp8_create_compressor(&priv->oxcf);
    660       if (!priv->cpi) res = VPX_CODEC_MEM_ERROR;
    661     }
    662   }
    663 
    664   return res;
    665 }
    666 
    667 static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx) {
    668 #if CONFIG_MULTI_RES_ENCODING
    669   /* Free multi-encoder shared memory */
    670   if (ctx->oxcf.mr_total_resolutions > 0 &&
    671       (ctx->oxcf.mr_encoder_id == ctx->oxcf.mr_total_resolutions - 1)) {
    672     LOWER_RES_FRAME_INFO *shared_mem_loc =
    673         (LOWER_RES_FRAME_INFO *)ctx->oxcf.mr_low_res_mode_info;
    674     free(shared_mem_loc->mb_info);
    675     free(ctx->oxcf.mr_low_res_mode_info);
    676   }
    677 #endif
    678 
    679   free(ctx->cx_data);
    680   vp8_remove_compressor(&ctx->cpi);
    681   vpx_free(ctx);
    682   return VPX_CODEC_OK;
    683 }
    684 
    685 static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
    686                                        YV12_BUFFER_CONFIG *yv12) {
    687   const int y_w = img->d_w;
    688   const int y_h = img->d_h;
    689   const int uv_w = (img->d_w + 1) / 2;
    690   const int uv_h = (img->d_h + 1) / 2;
    691   vpx_codec_err_t res = VPX_CODEC_OK;
    692   yv12->y_buffer = img->planes[VPX_PLANE_Y];
    693   yv12->u_buffer = img->planes[VPX_PLANE_U];
    694   yv12->v_buffer = img->planes[VPX_PLANE_V];
    695 
    696   yv12->y_crop_width = y_w;
    697   yv12->y_crop_height = y_h;
    698   yv12->y_width = y_w;
    699   yv12->y_height = y_h;
    700   yv12->uv_crop_width = uv_w;
    701   yv12->uv_crop_height = uv_h;
    702   yv12->uv_width = uv_w;
    703   yv12->uv_height = uv_h;
    704 
    705   yv12->y_stride = img->stride[VPX_PLANE_Y];
    706   yv12->uv_stride = img->stride[VPX_PLANE_U];
    707 
    708   yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2;
    709   return res;
    710 }
    711 
    712 static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
    713                                     unsigned long duration,
    714                                     unsigned long deadline) {
    715   int new_qc;
    716 
    717 #if !(CONFIG_REALTIME_ONLY)
    718   /* Use best quality mode if no deadline is given. */
    719   new_qc = MODE_BESTQUALITY;
    720 
    721   if (deadline) {
    722     uint64_t duration_us;
    723 
    724     /* Convert duration parameter from stream timebase to microseconds */
    725     duration_us = (uint64_t)duration * 1000000 *
    726                   (uint64_t)ctx->cfg.g_timebase.num /
    727                   (uint64_t)ctx->cfg.g_timebase.den;
    728 
    729     /* If the deadline is more that the duration this frame is to be shown,
    730      * use good quality mode. Otherwise use realtime mode.
    731      */
    732     new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
    733   }
    734 
    735 #else
    736   (void)duration;
    737   new_qc = MODE_REALTIME;
    738 #endif
    739 
    740   if (deadline == VPX_DL_REALTIME) {
    741     new_qc = MODE_REALTIME;
    742   } else if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS) {
    743     new_qc = MODE_FIRSTPASS;
    744   } else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS) {
    745     new_qc =
    746         (new_qc == MODE_BESTQUALITY) ? MODE_SECONDPASS_BEST : MODE_SECONDPASS;
    747   }
    748 
    749   if (ctx->oxcf.Mode != new_qc) {
    750     ctx->oxcf.Mode = new_qc;
    751     vp8_change_config(ctx->cpi, &ctx->oxcf);
    752   }
    753 }
    754 
    755 static vpx_codec_err_t set_reference_and_update(vpx_codec_alg_priv_t *ctx,
    756                                                 vpx_enc_frame_flags_t flags) {
    757   /* Handle Flags */
    758   if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) ||
    759       ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
    760     ctx->base.err_detail = "Conflicting flags.";
    761     return VPX_CODEC_INVALID_PARAM;
    762   }
    763 
    764   if (flags &
    765       (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF)) {
    766     int ref = 7;
    767 
    768     if (flags & VP8_EFLAG_NO_REF_LAST) ref ^= VP8_LAST_FRAME;
    769 
    770     if (flags & VP8_EFLAG_NO_REF_GF) ref ^= VP8_GOLD_FRAME;
    771 
    772     if (flags & VP8_EFLAG_NO_REF_ARF) ref ^= VP8_ALTR_FRAME;
    773 
    774     vp8_use_as_reference(ctx->cpi, ref);
    775   }
    776 
    777   if (flags &
    778       (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
    779        VP8_EFLAG_FORCE_GF | VP8_EFLAG_FORCE_ARF)) {
    780     int upd = 7;
    781 
    782     if (flags & VP8_EFLAG_NO_UPD_LAST) upd ^= VP8_LAST_FRAME;
    783 
    784     if (flags & VP8_EFLAG_NO_UPD_GF) upd ^= VP8_GOLD_FRAME;
    785 
    786     if (flags & VP8_EFLAG_NO_UPD_ARF) upd ^= VP8_ALTR_FRAME;
    787 
    788     vp8_update_reference(ctx->cpi, upd);
    789   }
    790 
    791   if (flags & VP8_EFLAG_NO_UPD_ENTROPY) {
    792     vp8_update_entropy(ctx->cpi, 0);
    793   }
    794 
    795   return VPX_CODEC_OK;
    796 }
    797 
    798 static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
    799                                    const vpx_image_t *img, vpx_codec_pts_t pts,
    800                                    unsigned long duration,
    801                                    vpx_enc_frame_flags_t flags,
    802                                    unsigned long deadline) {
    803   vpx_codec_err_t res = VPX_CODEC_OK;
    804 
    805   if (!ctx->cfg.rc_target_bitrate) return res;
    806 
    807   if (img) res = validate_img(ctx, img);
    808 
    809   if (!res) res = validate_config(ctx, &ctx->cfg, &ctx->vp8_cfg, 1);
    810 
    811   pick_quickcompress_mode(ctx, duration, deadline);
    812   vpx_codec_pkt_list_init(&ctx->pkt_list);
    813 
    814   // If no flags are set in the encode call, then use the frame flags as
    815   // defined via the control function: vp8e_set_frame_flags.
    816   if (!flags) {
    817     flags = ctx->control_frame_flags;
    818   }
    819   ctx->control_frame_flags = 0;
    820 
    821   if (!res) res = set_reference_and_update(ctx, flags);
    822 
    823   /* Handle fixed keyframe intervals */
    824   if (ctx->cfg.kf_mode == VPX_KF_AUTO &&
    825       ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
    826     if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
    827       flags |= VPX_EFLAG_FORCE_KF;
    828       ctx->fixed_kf_cntr = 1;
    829     }
    830   }
    831 
    832   /* Initialize the encoder instance on the first frame*/
    833   if (!res && ctx->cpi) {
    834     unsigned int lib_flags;
    835     YV12_BUFFER_CONFIG sd;
    836     int64_t dst_time_stamp, dst_end_time_stamp;
    837     size_t size, cx_data_sz;
    838     unsigned char *cx_data;
    839     unsigned char *cx_data_end;
    840     int comp_data_state = 0;
    841 
    842     /* Set up internal flags */
    843     if (ctx->base.init_flags & VPX_CODEC_USE_PSNR) {
    844       ((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 1;
    845     }
    846 
    847     if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION) {
    848       ((VP8_COMP *)ctx->cpi)->output_partition = 1;
    849     }
    850 
    851     /* Convert API flags to internal codec lib flags */
    852     lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
    853 
    854     /* vp8 use 10,000,000 ticks/second as time stamp */
    855     dst_time_stamp =
    856         pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
    857     dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num /
    858                          ctx->cfg.g_timebase.den;
    859 
    860     if (img != NULL) {
    861       res = image2yuvconfig(img, &sd);
    862 
    863       if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags, &sd,
    864                                 dst_time_stamp, dst_end_time_stamp)) {
    865         VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
    866         res = update_error_state(ctx, &cpi->common.error);
    867       }
    868 
    869       /* reset for next frame */
    870       ctx->next_frame_flag = 0;
    871     }
    872 
    873     cx_data = ctx->cx_data;
    874     cx_data_sz = ctx->cx_data_sz;
    875     cx_data_end = ctx->cx_data + cx_data_sz;
    876     lib_flags = 0;
    877 
    878     while (cx_data_sz >= ctx->cx_data_sz / 2) {
    879       comp_data_state = vp8_get_compressed_data(
    880           ctx->cpi, &lib_flags, &size, cx_data, cx_data_end, &dst_time_stamp,
    881           &dst_end_time_stamp, !img);
    882 
    883       if (comp_data_state == VPX_CODEC_CORRUPT_FRAME) {
    884         return VPX_CODEC_CORRUPT_FRAME;
    885       } else if (comp_data_state == -1) {
    886         break;
    887       }
    888 
    889       if (size) {
    890         vpx_codec_pts_t round, delta;
    891         vpx_codec_cx_pkt_t pkt;
    892         VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
    893 
    894         /* Add the frame packet to the list of returned packets. */
    895         round = (vpx_codec_pts_t)10000000 * ctx->cfg.g_timebase.num / 2 - 1;
    896         delta = (dst_end_time_stamp - dst_time_stamp);
    897         pkt.kind = VPX_CODEC_CX_FRAME_PKT;
    898         pkt.data.frame.pts =
    899             (dst_time_stamp * ctx->cfg.g_timebase.den + round) /
    900             ctx->cfg.g_timebase.num / 10000000;
    901         pkt.data.frame.duration =
    902             (unsigned long)((delta * ctx->cfg.g_timebase.den + round) /
    903                             ctx->cfg.g_timebase.num / 10000000);
    904         pkt.data.frame.flags = lib_flags << 16;
    905 
    906         if (lib_flags & FRAMEFLAGS_KEY) {
    907           pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
    908         }
    909 
    910         if (!cpi->common.show_frame) {
    911           pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
    912 
    913           /* This timestamp should be as close as possible to the
    914            * prior PTS so that if a decoder uses pts to schedule when
    915            * to do this, we start right after last frame was decoded.
    916            * Invisible frames have no duration.
    917            */
    918           pkt.data.frame.pts =
    919               ((cpi->last_time_stamp_seen * ctx->cfg.g_timebase.den + round) /
    920                ctx->cfg.g_timebase.num / 10000000) +
    921               1;
    922           pkt.data.frame.duration = 0;
    923         }
    924 
    925         if (cpi->droppable) pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
    926 
    927         if (cpi->output_partition) {
    928           int i;
    929           const int num_partitions =
    930               (1 << cpi->common.multi_token_partition) + 1;
    931 
    932           pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
    933 
    934           for (i = 0; i < num_partitions; ++i) {
    935 #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
    936             pkt.data.frame.buf = cpi->partition_d[i];
    937 #else
    938             pkt.data.frame.buf = cx_data;
    939             cx_data += cpi->partition_sz[i];
    940             cx_data_sz -= cpi->partition_sz[i];
    941 #endif
    942             pkt.data.frame.sz = cpi->partition_sz[i];
    943             pkt.data.frame.partition_id = i;
    944             /* don't set the fragment bit for the last partition */
    945             if (i == (num_partitions - 1)) {
    946               pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
    947             }
    948             vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
    949           }
    950 #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
    951           /* In lagged mode the encoder can buffer multiple frames.
    952            * We don't want this in partitioned output because
    953            * partitions are spread all over the output buffer.
    954            * So, force an exit!
    955            */
    956           cx_data_sz -= ctx->cx_data_sz / 2;
    957 #endif
    958         } else {
    959           pkt.data.frame.buf = cx_data;
    960           pkt.data.frame.sz = size;
    961           pkt.data.frame.partition_id = -1;
    962           vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
    963           cx_data += size;
    964           cx_data_sz -= size;
    965         }
    966       }
    967     }
    968   }
    969 
    970   return res;
    971 }
    972 
    973 static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t *ctx,
    974                                                  vpx_codec_iter_t *iter) {
    975   return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
    976 }
    977 
    978 static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx,
    979                                           va_list args) {
    980   vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
    981 
    982   if (data) {
    983     vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    984     YV12_BUFFER_CONFIG sd;
    985 
    986     image2yuvconfig(&frame->img, &sd);
    987     vp8_set_reference(ctx->cpi, frame->frame_type, &sd);
    988     return VPX_CODEC_OK;
    989   } else {
    990     return VPX_CODEC_INVALID_PARAM;
    991   }
    992 }
    993 
    994 static vpx_codec_err_t vp8e_get_reference(vpx_codec_alg_priv_t *ctx,
    995                                           va_list args) {
    996   vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
    997 
    998   if (data) {
    999     vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
   1000     YV12_BUFFER_CONFIG sd;
   1001 
   1002     image2yuvconfig(&frame->img, &sd);
   1003     vp8_get_reference(ctx->cpi, frame->frame_type, &sd);
   1004     return VPX_CODEC_OK;
   1005   } else {
   1006     return VPX_CODEC_INVALID_PARAM;
   1007   }
   1008 }
   1009 
   1010 static vpx_codec_err_t vp8e_set_previewpp(vpx_codec_alg_priv_t *ctx,
   1011                                           va_list args) {
   1012 #if CONFIG_POSTPROC
   1013   vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
   1014 
   1015   if (data) {
   1016     ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
   1017     return VPX_CODEC_OK;
   1018   } else {
   1019     return VPX_CODEC_INVALID_PARAM;
   1020   }
   1021 #else
   1022   (void)ctx;
   1023   (void)args;
   1024   return VPX_CODEC_INCAPABLE;
   1025 #endif
   1026 }
   1027 
   1028 static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx) {
   1029   YV12_BUFFER_CONFIG sd;
   1030   vp8_ppflags_t flags;
   1031   vp8_zero(flags);
   1032 
   1033   if (ctx->preview_ppcfg.post_proc_flag) {
   1034     flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag;
   1035     flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
   1036     flags.noise_level = ctx->preview_ppcfg.noise_level;
   1037   }
   1038 
   1039   if (0 == vp8_get_preview_raw_frame(ctx->cpi, &sd, &flags)) {
   1040     /*
   1041     vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12,
   1042         sd.y_width + 2*VP8BORDERINPIXELS,
   1043         sd.y_height + 2*VP8BORDERINPIXELS,
   1044         1,
   1045         sd.buffer_alloc);
   1046     vpx_img_set_rect(&ctx->preview_img,
   1047         VP8BORDERINPIXELS, VP8BORDERINPIXELS,
   1048         sd.y_width, sd.y_height);
   1049         */
   1050 
   1051     ctx->preview_img.bps = 12;
   1052     ctx->preview_img.planes[VPX_PLANE_Y] = sd.y_buffer;
   1053     ctx->preview_img.planes[VPX_PLANE_U] = sd.u_buffer;
   1054     ctx->preview_img.planes[VPX_PLANE_V] = sd.v_buffer;
   1055 
   1056     ctx->preview_img.fmt = VPX_IMG_FMT_I420;
   1057     ctx->preview_img.x_chroma_shift = 1;
   1058     ctx->preview_img.y_chroma_shift = 1;
   1059 
   1060     ctx->preview_img.d_w = sd.y_width;
   1061     ctx->preview_img.d_h = sd.y_height;
   1062     ctx->preview_img.stride[VPX_PLANE_Y] = sd.y_stride;
   1063     ctx->preview_img.stride[VPX_PLANE_U] = sd.uv_stride;
   1064     ctx->preview_img.stride[VPX_PLANE_V] = sd.uv_stride;
   1065     ctx->preview_img.w = sd.y_width;
   1066     ctx->preview_img.h = sd.y_height;
   1067 
   1068     return &ctx->preview_img;
   1069   } else {
   1070     return NULL;
   1071   }
   1072 }
   1073 
   1074 static vpx_codec_err_t vp8e_set_frame_flags(vpx_codec_alg_priv_t *ctx,
   1075                                             va_list args) {
   1076   int frame_flags = va_arg(args, int);
   1077   ctx->control_frame_flags = frame_flags;
   1078   return set_reference_and_update(ctx, frame_flags);
   1079 }
   1080 
   1081 static vpx_codec_err_t vp8e_set_temporal_layer_id(vpx_codec_alg_priv_t *ctx,
   1082                                                   va_list args) {
   1083   int layer_id = va_arg(args, int);
   1084   if (layer_id < 0 || layer_id >= (int)ctx->cfg.ts_number_layers) {
   1085     return VPX_CODEC_INVALID_PARAM;
   1086   }
   1087   ctx->cpi->temporal_layer_id = layer_id;
   1088   return VPX_CODEC_OK;
   1089 }
   1090 
   1091 static vpx_codec_err_t vp8e_set_roi_map(vpx_codec_alg_priv_t *ctx,
   1092                                         va_list args) {
   1093   vpx_roi_map_t *data = va_arg(args, vpx_roi_map_t *);
   1094 
   1095   if (data) {
   1096     vpx_roi_map_t *roi = (vpx_roi_map_t *)data;
   1097 
   1098     if (!vp8_set_roimap(ctx->cpi, roi->roi_map, roi->rows, roi->cols,
   1099                         roi->delta_q, roi->delta_lf, roi->static_threshold)) {
   1100       return VPX_CODEC_OK;
   1101     } else {
   1102       return VPX_CODEC_INVALID_PARAM;
   1103     }
   1104   } else {
   1105     return VPX_CODEC_INVALID_PARAM;
   1106   }
   1107 }
   1108 
   1109 static vpx_codec_err_t vp8e_set_activemap(vpx_codec_alg_priv_t *ctx,
   1110                                           va_list args) {
   1111   vpx_active_map_t *data = va_arg(args, vpx_active_map_t *);
   1112 
   1113   if (data) {
   1114     vpx_active_map_t *map = (vpx_active_map_t *)data;
   1115 
   1116     if (!vp8_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols)) {
   1117       return VPX_CODEC_OK;
   1118     } else {
   1119       return VPX_CODEC_INVALID_PARAM;
   1120     }
   1121   } else {
   1122     return VPX_CODEC_INVALID_PARAM;
   1123   }
   1124 }
   1125 
   1126 static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx,
   1127                                           va_list args) {
   1128   vpx_scaling_mode_t *data = va_arg(args, vpx_scaling_mode_t *);
   1129 
   1130   if (data) {
   1131     int res;
   1132     vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data;
   1133     res = vp8_set_internal_size(ctx->cpi, (VPX_SCALING)scalemode.h_scaling_mode,
   1134                                 (VPX_SCALING)scalemode.v_scaling_mode);
   1135 
   1136     if (!res) {
   1137       /*force next frame a key frame to effect scaling mode */
   1138       ctx->next_frame_flag |= FRAMEFLAGS_KEY;
   1139       return VPX_CODEC_OK;
   1140     } else {
   1141       return VPX_CODEC_INVALID_PARAM;
   1142     }
   1143   } else {
   1144     return VPX_CODEC_INVALID_PARAM;
   1145   }
   1146 }
   1147 
   1148 static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] = {
   1149   { VP8_SET_REFERENCE, vp8e_set_reference },
   1150   { VP8_COPY_REFERENCE, vp8e_get_reference },
   1151   { VP8_SET_POSTPROC, vp8e_set_previewpp },
   1152   { VP8E_SET_FRAME_FLAGS, vp8e_set_frame_flags },
   1153   { VP8E_SET_TEMPORAL_LAYER_ID, vp8e_set_temporal_layer_id },
   1154   { VP8E_SET_ROI_MAP, vp8e_set_roi_map },
   1155   { VP8E_SET_ACTIVEMAP, vp8e_set_activemap },
   1156   { VP8E_SET_SCALEMODE, vp8e_set_scalemode },
   1157   { VP8E_SET_CPUUSED, set_cpu_used },
   1158   { VP8E_SET_NOISE_SENSITIVITY, set_noise_sensitivity },
   1159   { VP8E_SET_ENABLEAUTOALTREF, set_enable_auto_alt_ref },
   1160   { VP8E_SET_SHARPNESS, set_sharpness },
   1161   { VP8E_SET_STATIC_THRESHOLD, set_static_thresh },
   1162   { VP8E_SET_TOKEN_PARTITIONS, set_token_partitions },
   1163   { VP8E_GET_LAST_QUANTIZER, get_quantizer },
   1164   { VP8E_GET_LAST_QUANTIZER_64, get_quantizer64 },
   1165   { VP8E_SET_ARNR_MAXFRAMES, set_arnr_max_frames },
   1166   { VP8E_SET_ARNR_STRENGTH, set_arnr_strength },
   1167   { VP8E_SET_ARNR_TYPE, set_arnr_type },
   1168   { VP8E_SET_TUNING, set_tuning },
   1169   { VP8E_SET_CQ_LEVEL, set_cq_level },
   1170   { VP8E_SET_MAX_INTRA_BITRATE_PCT, set_rc_max_intra_bitrate_pct },
   1171   { VP8E_SET_SCREEN_CONTENT_MODE, set_screen_content_mode },
   1172   { VP8E_SET_GF_CBR_BOOST_PCT, ctrl_set_rc_gf_cbr_boost_pct },
   1173   { -1, NULL },
   1174 };
   1175 
   1176 static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] = {
   1177   { 0,
   1178     {
   1179         0, /* g_usage */
   1180         0, /* g_threads */
   1181         0, /* g_profile */
   1182 
   1183         320,        /* g_width */
   1184         240,        /* g_height */
   1185         VPX_BITS_8, /* g_bit_depth */
   1186         8,          /* g_input_bit_depth */
   1187 
   1188         { 1, 30 }, /* g_timebase */
   1189 
   1190         0, /* g_error_resilient */
   1191 
   1192         VPX_RC_ONE_PASS, /* g_pass */
   1193 
   1194         0, /* g_lag_in_frames */
   1195 
   1196         0,  /* rc_dropframe_thresh */
   1197         0,  /* rc_resize_allowed */
   1198         1,  /* rc_scaled_width */
   1199         1,  /* rc_scaled_height */
   1200         60, /* rc_resize_down_thresold */
   1201         30, /* rc_resize_up_thresold */
   1202 
   1203         VPX_VBR,     /* rc_end_usage */
   1204         { NULL, 0 }, /* rc_twopass_stats_in */
   1205         { NULL, 0 }, /* rc_firstpass_mb_stats_in */
   1206         256,         /* rc_target_bandwidth */
   1207         4,           /* rc_min_quantizer */
   1208         63,          /* rc_max_quantizer */
   1209         100,         /* rc_undershoot_pct */
   1210         100,         /* rc_overshoot_pct */
   1211 
   1212         6000, /* rc_max_buffer_size */
   1213         4000, /* rc_buffer_initial_size; */
   1214         5000, /* rc_buffer_optimal_size; */
   1215 
   1216         50,  /* rc_two_pass_vbrbias  */
   1217         0,   /* rc_two_pass_vbrmin_section */
   1218         400, /* rc_two_pass_vbrmax_section */
   1219         0,   // rc_2pass_vbr_corpus_complexity (only has meaningfull for VP9)
   1220 
   1221         /* keyframing settings (kf) */
   1222         VPX_KF_AUTO, /* g_kfmode*/
   1223         0,           /* kf_min_dist */
   1224         128,         /* kf_max_dist */
   1225 
   1226         VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */
   1227         { 0 },
   1228         { 0 }, /* ss_target_bitrate */
   1229         1,     /* ts_number_layers */
   1230         { 0 }, /* ts_target_bitrate */
   1231         { 0 }, /* ts_rate_decimator */
   1232         0,     /* ts_periodicity */
   1233         { 0 }, /* ts_layer_id */
   1234         { 0 }, /* layer_target_bitrate */
   1235         0      /* temporal_layering_mode */
   1236     } },
   1237 };
   1238 
   1239 #ifndef VERSION_STRING
   1240 #define VERSION_STRING
   1241 #endif
   1242 CODEC_INTERFACE(vpx_codec_vp8_cx) = {
   1243   "WebM Project VP8 Encoder" VERSION_STRING,
   1244   VPX_CODEC_INTERNAL_ABI_VERSION,
   1245   VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR | VPX_CODEC_CAP_OUTPUT_PARTITION,
   1246   /* vpx_codec_caps_t          caps; */
   1247   vp8e_init,     /* vpx_codec_init_fn_t       init; */
   1248   vp8e_destroy,  /* vpx_codec_destroy_fn_t    destroy; */
   1249   vp8e_ctf_maps, /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
   1250   {
   1251       NULL, /* vpx_codec_peek_si_fn_t    peek_si; */
   1252       NULL, /* vpx_codec_get_si_fn_t     get_si; */
   1253       NULL, /* vpx_codec_decode_fn_t     decode; */
   1254       NULL, /* vpx_codec_frame_get_fn_t  frame_get; */
   1255       NULL, /* vpx_codec_set_fb_fn_t     set_fb_fn; */
   1256   },
   1257   {
   1258       1,                  /* 1 cfg map */
   1259       vp8e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t    cfg_maps; */
   1260       vp8e_encode,        /* vpx_codec_encode_fn_t      encode; */
   1261       vp8e_get_cxdata,    /* vpx_codec_get_cx_data_fn_t   get_cx_data; */
   1262       vp8e_set_config, NULL, vp8e_get_preview, vp8e_mr_alloc_mem,
   1263   } /* encoder functions */
   1264 };
   1265