LCOV - code coverage report
Current view: top level - media/libvpx/libvpx/vp8 - vp8_cx_iface.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 526 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13