Coverage Report

Created: 2026-10-28 08:13

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