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 <stdlib.h>
12 : #include <string.h>
13 :
14 : #include "./vpx_config.h"
15 : #include "vpx/vpx_encoder.h"
16 : #include "vpx_ports/vpx_once.h"
17 : #include "vpx_ports/system_state.h"
18 : #include "vpx/internal/vpx_codec_internal.h"
19 : #include "./vpx_version.h"
20 : #include "vp9/encoder/vp9_encoder.h"
21 : #include "vpx/vp8cx.h"
22 : #include "vp9/encoder/vp9_firstpass.h"
23 : #include "vp9/vp9_iface_common.h"
24 :
25 : struct vp9_extracfg {
26 : int cpu_used; // available cpu percentage in 1/16
27 : unsigned int enable_auto_alt_ref;
28 : unsigned int noise_sensitivity;
29 : unsigned int sharpness;
30 : unsigned int static_thresh;
31 : unsigned int tile_columns;
32 : unsigned int tile_rows;
33 : unsigned int arnr_max_frames;
34 : unsigned int arnr_strength;
35 : unsigned int min_gf_interval;
36 : unsigned int max_gf_interval;
37 : vp8e_tuning tuning;
38 : unsigned int cq_level; // constrained quality level
39 : unsigned int rc_max_intra_bitrate_pct;
40 : unsigned int rc_max_inter_bitrate_pct;
41 : unsigned int gf_cbr_boost_pct;
42 : unsigned int lossless;
43 : unsigned int target_level;
44 : unsigned int frame_parallel_decoding_mode;
45 : AQ_MODE aq_mode;
46 : int alt_ref_aq;
47 : unsigned int frame_periodic_boost;
48 : vpx_bit_depth_t bit_depth;
49 : vp9e_tune_content content;
50 : vpx_color_space_t color_space;
51 : vpx_color_range_t color_range;
52 : int render_width;
53 : int render_height;
54 : };
55 :
56 : static struct vp9_extracfg default_extra_cfg = {
57 : 0, // cpu_used
58 : 1, // enable_auto_alt_ref
59 : 0, // noise_sensitivity
60 : 0, // sharpness
61 : 0, // static_thresh
62 : 6, // tile_columns
63 : 0, // tile_rows
64 : 7, // arnr_max_frames
65 : 5, // arnr_strength
66 : 0, // min_gf_interval; 0 -> default decision
67 : 0, // max_gf_interval; 0 -> default decision
68 : VP8_TUNE_PSNR, // tuning
69 : 10, // cq_level
70 : 0, // rc_max_intra_bitrate_pct
71 : 0, // rc_max_inter_bitrate_pct
72 : 0, // gf_cbr_boost_pct
73 : 0, // lossless
74 : 255, // target_level
75 : 1, // frame_parallel_decoding_mode
76 : NO_AQ, // aq_mode
77 : 0, // alt_ref_aq
78 : 0, // frame_periodic_delta_q
79 : VPX_BITS_8, // Bit depth
80 : VP9E_CONTENT_DEFAULT, // content
81 : VPX_CS_UNKNOWN, // color space
82 : 0, // color range
83 : 0, // render width
84 : 0, // render height
85 : };
86 :
87 : struct vpx_codec_alg_priv {
88 : vpx_codec_priv_t base;
89 : vpx_codec_enc_cfg_t cfg;
90 : struct vp9_extracfg extra_cfg;
91 : VP9EncoderConfig oxcf;
92 : VP9_COMP *cpi;
93 : unsigned char *cx_data;
94 : size_t cx_data_sz;
95 : unsigned char *pending_cx_data;
96 : size_t pending_cx_data_sz;
97 : int pending_frame_count;
98 : size_t pending_frame_sizes[8];
99 : size_t pending_frame_magnitude;
100 : vpx_image_t preview_img;
101 : vpx_enc_frame_flags_t next_frame_flags;
102 : vp8_postproc_cfg_t preview_ppcfg;
103 : vpx_codec_pkt_list_decl(256) pkt_list;
104 : unsigned int fixed_kf_cntr;
105 : vpx_codec_priv_output_cx_pkt_cb_pair_t output_cx_pkt_cb;
106 : // BufferPool that holds all reference frames.
107 : BufferPool *buffer_pool;
108 : };
109 :
110 0 : static vpx_codec_err_t update_error_state(
111 : vpx_codec_alg_priv_t *ctx, const struct vpx_internal_error_info *error) {
112 0 : const vpx_codec_err_t res = error->error_code;
113 :
114 0 : if (res != VPX_CODEC_OK)
115 0 : ctx->base.err_detail = error->has_detail ? error->detail : NULL;
116 :
117 0 : return res;
118 : }
119 :
120 : #undef ERROR
121 : #define ERROR(str) \
122 : do { \
123 : ctx->base.err_detail = str; \
124 : return VPX_CODEC_INVALID_PARAM; \
125 : } while (0)
126 :
127 : #define RANGE_CHECK(p, memb, lo, hi) \
128 : do { \
129 : if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
130 : ERROR(#memb " out of range [" #lo ".." #hi "]"); \
131 : } while (0)
132 :
133 : #define RANGE_CHECK_HI(p, memb, hi) \
134 : do { \
135 : if (!((p)->memb <= (hi))) ERROR(#memb " out of range [.." #hi "]"); \
136 : } while (0)
137 :
138 : #define RANGE_CHECK_LO(p, memb, lo) \
139 : do { \
140 : if (!((p)->memb >= (lo))) ERROR(#memb " out of range [" #lo "..]"); \
141 : } while (0)
142 :
143 : #define RANGE_CHECK_BOOL(p, memb) \
144 : do { \
145 : if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean"); \
146 : } while (0)
147 :
148 0 : static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
149 : const vpx_codec_enc_cfg_t *cfg,
150 : const struct vp9_extracfg *extra_cfg) {
151 0 : RANGE_CHECK(cfg, g_w, 1, 65535); // 16 bits available
152 0 : RANGE_CHECK(cfg, g_h, 1, 65535); // 16 bits available
153 0 : RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
154 0 : RANGE_CHECK(cfg, g_timebase.num, 1, 1000000000);
155 0 : RANGE_CHECK_HI(cfg, g_profile, 3);
156 :
157 0 : RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
158 0 : RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
159 0 : RANGE_CHECK_BOOL(extra_cfg, lossless);
160 0 : RANGE_CHECK_BOOL(extra_cfg, frame_parallel_decoding_mode);
161 0 : RANGE_CHECK(extra_cfg, aq_mode, 0, AQ_MODE_COUNT - 2);
162 0 : RANGE_CHECK(extra_cfg, alt_ref_aq, 0, 1);
163 0 : RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1);
164 0 : RANGE_CHECK_HI(cfg, g_threads, 64);
165 0 : RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
166 0 : RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q);
167 0 : RANGE_CHECK_HI(cfg, rc_undershoot_pct, 100);
168 0 : RANGE_CHECK_HI(cfg, rc_overshoot_pct, 100);
169 0 : RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
170 0 : RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO);
171 0 : RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
172 0 : RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
173 0 : RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
174 0 : RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
175 0 : RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
176 0 : RANGE_CHECK(extra_cfg, min_gf_interval, 0, (MAX_LAG_BUFFERS - 1));
177 0 : RANGE_CHECK(extra_cfg, max_gf_interval, 0, (MAX_LAG_BUFFERS - 1));
178 0 : if (extra_cfg->max_gf_interval > 0) {
179 0 : RANGE_CHECK(extra_cfg, max_gf_interval, 2, (MAX_LAG_BUFFERS - 1));
180 : }
181 0 : if (extra_cfg->min_gf_interval > 0 && extra_cfg->max_gf_interval > 0) {
182 0 : RANGE_CHECK(extra_cfg, max_gf_interval, extra_cfg->min_gf_interval,
183 : (MAX_LAG_BUFFERS - 1));
184 : }
185 :
186 0 : if (cfg->rc_resize_allowed == 1) {
187 0 : RANGE_CHECK(cfg, rc_scaled_width, 0, cfg->g_w);
188 0 : RANGE_CHECK(cfg, rc_scaled_height, 0, cfg->g_h);
189 : }
190 :
191 0 : RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
192 0 : RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
193 :
194 : {
195 0 : unsigned int level = extra_cfg->target_level;
196 0 : if (level != LEVEL_1 && level != LEVEL_1_1 && level != LEVEL_2 &&
197 0 : level != LEVEL_2_1 && level != LEVEL_3 && level != LEVEL_3_1 &&
198 0 : level != LEVEL_4 && level != LEVEL_4_1 && level != LEVEL_5 &&
199 0 : level != LEVEL_5_1 && level != LEVEL_5_2 && level != LEVEL_6 &&
200 0 : level != LEVEL_6_1 && level != LEVEL_6_2 && level != LEVEL_UNKNOWN &&
201 : level != LEVEL_MAX)
202 0 : ERROR("target_level is invalid");
203 : }
204 :
205 0 : if (cfg->ss_number_layers * cfg->ts_number_layers > VPX_MAX_LAYERS)
206 0 : ERROR("ss_number_layers * ts_number_layers is out of range");
207 0 : if (cfg->ts_number_layers > 1) {
208 : unsigned int sl, tl;
209 0 : for (sl = 1; sl < cfg->ss_number_layers; ++sl) {
210 0 : for (tl = 1; tl < cfg->ts_number_layers; ++tl) {
211 0 : const int layer = LAYER_IDS_TO_IDX(sl, tl, cfg->ts_number_layers);
212 0 : if (cfg->layer_target_bitrate[layer] <
213 0 : cfg->layer_target_bitrate[layer - 1])
214 0 : ERROR("ts_target_bitrate entries are not increasing");
215 : }
216 : }
217 :
218 0 : RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
219 0 : for (tl = cfg->ts_number_layers - 2; tl > 0; --tl)
220 0 : if (cfg->ts_rate_decimator[tl - 1] != 2 * cfg->ts_rate_decimator[tl])
221 0 : ERROR("ts_rate_decimator factors are not powers of 2");
222 : }
223 :
224 : #if CONFIG_SPATIAL_SVC
225 :
226 : if ((cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) &&
227 : cfg->g_pass == VPX_RC_LAST_PASS) {
228 : unsigned int i, alt_ref_sum = 0;
229 : for (i = 0; i < cfg->ss_number_layers; ++i) {
230 : if (cfg->ss_enable_auto_alt_ref[i]) ++alt_ref_sum;
231 : }
232 : if (alt_ref_sum > REF_FRAMES - cfg->ss_number_layers)
233 : ERROR("Not enough ref buffers for svc alt ref frames");
234 : if (cfg->ss_number_layers * cfg->ts_number_layers > 3 &&
235 : cfg->g_error_resilient == 0)
236 : ERROR("Multiple frame context are not supported for more than 3 layers");
237 : }
238 : #endif
239 :
240 : // VP9 does not support a lower bound on the keyframe interval in
241 : // automatic keyframe placement mode.
242 0 : if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist &&
243 0 : cfg->kf_min_dist > 0)
244 0 : ERROR(
245 : "kf_min_dist not supported in auto mode, use 0 "
246 : "or kf_max_dist instead.");
247 :
248 0 : RANGE_CHECK(extra_cfg, enable_auto_alt_ref, 0, 2);
249 0 : RANGE_CHECK(extra_cfg, cpu_used, -8, 8);
250 0 : RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
251 0 : RANGE_CHECK(extra_cfg, tile_columns, 0, 6);
252 0 : RANGE_CHECK(extra_cfg, tile_rows, 0, 2);
253 0 : RANGE_CHECK_HI(extra_cfg, sharpness, 7);
254 0 : RANGE_CHECK(extra_cfg, arnr_max_frames, 0, 15);
255 0 : RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
256 0 : RANGE_CHECK(extra_cfg, cq_level, 0, 63);
257 0 : RANGE_CHECK(cfg, g_bit_depth, VPX_BITS_8, VPX_BITS_12);
258 0 : RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
259 0 : RANGE_CHECK(extra_cfg, content, VP9E_CONTENT_DEFAULT,
260 : VP9E_CONTENT_INVALID - 1);
261 :
262 : // TODO(yaowu): remove this when ssim tuning is implemented for vp9
263 0 : if (extra_cfg->tuning == VP8_TUNE_SSIM)
264 0 : ERROR("Option --tune=ssim is not currently supported in VP9.");
265 :
266 0 : if (cfg->g_pass == VPX_RC_LAST_PASS) {
267 0 : const size_t packet_sz = sizeof(FIRSTPASS_STATS);
268 0 : const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
269 : const FIRSTPASS_STATS *stats;
270 :
271 0 : if (cfg->rc_twopass_stats_in.buf == NULL)
272 0 : ERROR("rc_twopass_stats_in.buf not set.");
273 :
274 0 : if (cfg->rc_twopass_stats_in.sz % packet_sz)
275 0 : ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
276 :
277 0 : if (cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) {
278 : int i;
279 0 : unsigned int n_packets_per_layer[VPX_SS_MAX_LAYERS] = { 0 };
280 :
281 0 : stats = cfg->rc_twopass_stats_in.buf;
282 0 : for (i = 0; i < n_packets; ++i) {
283 0 : const int layer_id = (int)stats[i].spatial_layer_id;
284 0 : if (layer_id >= 0 && layer_id < (int)cfg->ss_number_layers) {
285 0 : ++n_packets_per_layer[layer_id];
286 : }
287 : }
288 :
289 0 : for (i = 0; i < (int)cfg->ss_number_layers; ++i) {
290 : unsigned int layer_id;
291 0 : if (n_packets_per_layer[i] < 2) {
292 0 : ERROR(
293 : "rc_twopass_stats_in requires at least two packets for each "
294 : "layer.");
295 : }
296 :
297 0 : stats = (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf +
298 0 : n_packets - cfg->ss_number_layers + i;
299 0 : layer_id = (int)stats->spatial_layer_id;
300 :
301 0 : if (layer_id >= cfg->ss_number_layers ||
302 0 : (unsigned int)(stats->count + 0.5) !=
303 0 : n_packets_per_layer[layer_id] - 1)
304 0 : ERROR("rc_twopass_stats_in missing EOS stats packet");
305 : }
306 : } else {
307 0 : if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
308 0 : ERROR("rc_twopass_stats_in requires at least two packets.");
309 :
310 0 : stats =
311 0 : (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
312 :
313 0 : if ((int)(stats->count + 0.5) != n_packets - 1)
314 0 : ERROR("rc_twopass_stats_in missing EOS stats packet");
315 : }
316 : }
317 :
318 : #if !CONFIG_VP9_HIGHBITDEPTH
319 0 : if (cfg->g_profile > (unsigned int)PROFILE_1) {
320 0 : ERROR("Profile > 1 not supported in this build configuration");
321 : }
322 : #endif
323 0 : if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
324 0 : cfg->g_bit_depth > VPX_BITS_8) {
325 0 : ERROR("Codec high bit-depth not supported in profile < 2");
326 : }
327 0 : if (cfg->g_profile <= (unsigned int)PROFILE_1 && cfg->g_input_bit_depth > 8) {
328 0 : ERROR("Source high bit-depth not supported in profile < 2");
329 : }
330 0 : if (cfg->g_profile > (unsigned int)PROFILE_1 &&
331 0 : cfg->g_bit_depth == VPX_BITS_8) {
332 0 : ERROR("Codec bit-depth 8 not supported in profile > 1");
333 : }
334 0 : RANGE_CHECK(extra_cfg, color_space, VPX_CS_UNKNOWN, VPX_CS_SRGB);
335 0 : RANGE_CHECK(extra_cfg, color_range, VPX_CR_STUDIO_RANGE, VPX_CR_FULL_RANGE);
336 0 : return VPX_CODEC_OK;
337 : }
338 :
339 0 : static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
340 : const vpx_image_t *img) {
341 0 : switch (img->fmt) {
342 : case VPX_IMG_FMT_YV12:
343 : case VPX_IMG_FMT_I420:
344 0 : case VPX_IMG_FMT_I42016: break;
345 : case VPX_IMG_FMT_I422:
346 : case VPX_IMG_FMT_I444:
347 : case VPX_IMG_FMT_I440:
348 0 : if (ctx->cfg.g_profile != (unsigned int)PROFILE_1) {
349 0 : ERROR(
350 : "Invalid image format. I422, I444, I440 images are "
351 : "not supported in profile.");
352 : }
353 0 : break;
354 : case VPX_IMG_FMT_I42216:
355 : case VPX_IMG_FMT_I44416:
356 : case VPX_IMG_FMT_I44016:
357 0 : if (ctx->cfg.g_profile != (unsigned int)PROFILE_1 &&
358 0 : ctx->cfg.g_profile != (unsigned int)PROFILE_3) {
359 0 : ERROR(
360 : "Invalid image format. 16-bit I422, I444, I440 images are "
361 : "not supported in profile.");
362 : }
363 0 : break;
364 : default:
365 0 : ERROR(
366 : "Invalid image format. Only YV12, I420, I422, I444 images are "
367 : "supported.");
368 : break;
369 : }
370 :
371 0 : if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h)
372 0 : ERROR("Image size must match encoder init configuration size");
373 :
374 0 : return VPX_CODEC_OK;
375 : }
376 :
377 0 : static int get_image_bps(const vpx_image_t *img) {
378 0 : switch (img->fmt) {
379 : case VPX_IMG_FMT_YV12:
380 0 : case VPX_IMG_FMT_I420: return 12;
381 0 : case VPX_IMG_FMT_I422: return 16;
382 0 : case VPX_IMG_FMT_I444: return 24;
383 0 : case VPX_IMG_FMT_I440: return 16;
384 0 : case VPX_IMG_FMT_I42016: return 24;
385 0 : case VPX_IMG_FMT_I42216: return 32;
386 0 : case VPX_IMG_FMT_I44416: return 48;
387 0 : case VPX_IMG_FMT_I44016: return 32;
388 0 : default: assert(0 && "Invalid image format"); break;
389 : }
390 : return 0;
391 : }
392 :
393 : // Modify the encoder config for the target level.
394 0 : static void config_target_level(VP9EncoderConfig *oxcf) {
395 : double max_average_bitrate; // in bits per second
396 : int max_over_shoot_pct;
397 0 : const int target_level_index = get_level_index(oxcf->target_level);
398 :
399 0 : vpx_clear_system_state();
400 0 : assert(target_level_index >= 0);
401 0 : assert(target_level_index < VP9_LEVELS);
402 :
403 : // Maximum target bit-rate is level_limit * 80%.
404 0 : max_average_bitrate =
405 0 : vp9_level_defs[target_level_index].average_bitrate * 800.0;
406 0 : if ((double)oxcf->target_bandwidth > max_average_bitrate)
407 0 : oxcf->target_bandwidth = (int64_t)(max_average_bitrate);
408 0 : if (oxcf->ss_number_layers == 1 && oxcf->pass != 0)
409 0 : oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
410 :
411 : // Adjust max over-shoot percentage.
412 0 : max_over_shoot_pct =
413 0 : (int)((max_average_bitrate * 1.10 - (double)oxcf->target_bandwidth) *
414 0 : 100 / (double)(oxcf->target_bandwidth));
415 0 : if (oxcf->over_shoot_pct > max_over_shoot_pct)
416 0 : oxcf->over_shoot_pct = max_over_shoot_pct;
417 :
418 : // Adjust worst allowed quantizer.
419 0 : oxcf->worst_allowed_q = vp9_quantizer_to_qindex(63);
420 :
421 : // Adjust minimum art-ref distance.
422 0 : if (oxcf->min_gf_interval <
423 0 : (int)vp9_level_defs[target_level_index].min_altref_distance)
424 0 : oxcf->min_gf_interval =
425 0 : (int)vp9_level_defs[target_level_index].min_altref_distance;
426 :
427 : // Adjust maximum column tiles.
428 0 : if (vp9_level_defs[target_level_index].max_col_tiles <
429 0 : (1 << oxcf->tile_columns)) {
430 0 : while (oxcf->tile_columns > 0 &&
431 0 : vp9_level_defs[target_level_index].max_col_tiles <
432 0 : (1 << oxcf->tile_columns))
433 0 : --oxcf->tile_columns;
434 : }
435 0 : }
436 :
437 0 : static vpx_codec_err_t set_encoder_config(
438 : VP9EncoderConfig *oxcf, const vpx_codec_enc_cfg_t *cfg,
439 : const struct vp9_extracfg *extra_cfg) {
440 0 : const int is_vbr = cfg->rc_end_usage == VPX_VBR;
441 : int sl, tl;
442 0 : oxcf->profile = cfg->g_profile;
443 0 : oxcf->max_threads = (int)cfg->g_threads;
444 0 : oxcf->width = cfg->g_w;
445 0 : oxcf->height = cfg->g_h;
446 0 : oxcf->bit_depth = cfg->g_bit_depth;
447 0 : oxcf->input_bit_depth = cfg->g_input_bit_depth;
448 : // guess a frame rate if out of whack, use 30
449 0 : oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
450 0 : if (oxcf->init_framerate > 180) oxcf->init_framerate = 30;
451 :
452 0 : oxcf->mode = GOOD;
453 :
454 0 : switch (cfg->g_pass) {
455 0 : case VPX_RC_ONE_PASS: oxcf->pass = 0; break;
456 0 : case VPX_RC_FIRST_PASS: oxcf->pass = 1; break;
457 0 : case VPX_RC_LAST_PASS: oxcf->pass = 2; break;
458 : }
459 :
460 0 : oxcf->lag_in_frames =
461 0 : cfg->g_pass == VPX_RC_FIRST_PASS ? 0 : cfg->g_lag_in_frames;
462 0 : oxcf->rc_mode = cfg->rc_end_usage;
463 :
464 : // Convert target bandwidth from Kbit/s to Bit/s
465 0 : oxcf->target_bandwidth = 1000 * cfg->rc_target_bitrate;
466 0 : oxcf->rc_max_intra_bitrate_pct = extra_cfg->rc_max_intra_bitrate_pct;
467 0 : oxcf->rc_max_inter_bitrate_pct = extra_cfg->rc_max_inter_bitrate_pct;
468 0 : oxcf->gf_cbr_boost_pct = extra_cfg->gf_cbr_boost_pct;
469 :
470 0 : oxcf->best_allowed_q =
471 0 : extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_min_quantizer);
472 0 : oxcf->worst_allowed_q =
473 0 : extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_max_quantizer);
474 0 : oxcf->cq_level = vp9_quantizer_to_qindex(extra_cfg->cq_level);
475 0 : oxcf->fixed_q = -1;
476 :
477 0 : oxcf->under_shoot_pct = cfg->rc_undershoot_pct;
478 0 : oxcf->over_shoot_pct = cfg->rc_overshoot_pct;
479 :
480 0 : oxcf->scaled_frame_width = cfg->rc_scaled_width;
481 0 : oxcf->scaled_frame_height = cfg->rc_scaled_height;
482 0 : if (cfg->rc_resize_allowed == 1) {
483 0 : oxcf->resize_mode =
484 0 : (oxcf->scaled_frame_width == 0 || oxcf->scaled_frame_height == 0)
485 : ? RESIZE_DYNAMIC
486 0 : : RESIZE_FIXED;
487 : } else {
488 0 : oxcf->resize_mode = RESIZE_NONE;
489 : }
490 :
491 0 : oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
492 0 : oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
493 0 : oxcf->optimal_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
494 :
495 0 : oxcf->drop_frames_water_mark = cfg->rc_dropframe_thresh;
496 :
497 0 : oxcf->two_pass_vbrbias = cfg->rc_2pass_vbr_bias_pct;
498 0 : oxcf->two_pass_vbrmin_section = cfg->rc_2pass_vbr_minsection_pct;
499 0 : oxcf->two_pass_vbrmax_section = cfg->rc_2pass_vbr_maxsection_pct;
500 :
501 0 : oxcf->auto_key =
502 0 : cfg->kf_mode == VPX_KF_AUTO && cfg->kf_min_dist != cfg->kf_max_dist;
503 :
504 0 : oxcf->key_freq = cfg->kf_max_dist;
505 :
506 0 : oxcf->speed = abs(extra_cfg->cpu_used);
507 0 : oxcf->encode_breakout = extra_cfg->static_thresh;
508 0 : oxcf->enable_auto_arf = extra_cfg->enable_auto_alt_ref;
509 0 : oxcf->noise_sensitivity = extra_cfg->noise_sensitivity;
510 0 : oxcf->sharpness = extra_cfg->sharpness;
511 :
512 0 : oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
513 :
514 : #if CONFIG_FP_MB_STATS
515 : oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in;
516 : #endif
517 :
518 0 : oxcf->color_space = extra_cfg->color_space;
519 0 : oxcf->color_range = extra_cfg->color_range;
520 0 : oxcf->render_width = extra_cfg->render_width;
521 0 : oxcf->render_height = extra_cfg->render_height;
522 0 : oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
523 0 : oxcf->arnr_strength = extra_cfg->arnr_strength;
524 0 : oxcf->min_gf_interval = extra_cfg->min_gf_interval;
525 0 : oxcf->max_gf_interval = extra_cfg->max_gf_interval;
526 :
527 0 : oxcf->tuning = extra_cfg->tuning;
528 0 : oxcf->content = extra_cfg->content;
529 :
530 0 : oxcf->tile_columns = extra_cfg->tile_columns;
531 :
532 : // TODO(yunqing): The dependencies between row tiles cause error in multi-
533 : // threaded encoding. For now, tile_rows is forced to be 0 in this case.
534 : // The further fix can be done by adding synchronizations after a tile row
535 : // is encoded. But this will hurt multi-threaded encoder performance. So,
536 : // it is recommended to use tile-rows=0 while encoding with threads > 1.
537 0 : if (oxcf->max_threads > 1 && oxcf->tile_columns > 0)
538 0 : oxcf->tile_rows = 0;
539 : else
540 0 : oxcf->tile_rows = extra_cfg->tile_rows;
541 :
542 0 : oxcf->error_resilient_mode = cfg->g_error_resilient;
543 0 : oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;
544 :
545 0 : oxcf->aq_mode = extra_cfg->aq_mode;
546 0 : oxcf->alt_ref_aq = extra_cfg->alt_ref_aq;
547 :
548 0 : oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
549 :
550 0 : oxcf->ss_number_layers = cfg->ss_number_layers;
551 0 : oxcf->ts_number_layers = cfg->ts_number_layers;
552 0 : oxcf->temporal_layering_mode =
553 0 : (enum vp9e_temporal_layering_mode)cfg->temporal_layering_mode;
554 :
555 0 : oxcf->target_level = extra_cfg->target_level;
556 :
557 0 : for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
558 : #if CONFIG_SPATIAL_SVC
559 : oxcf->ss_enable_auto_arf[sl] = cfg->ss_enable_auto_alt_ref[sl];
560 : #endif
561 0 : for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
562 0 : oxcf->layer_target_bitrate[sl * oxcf->ts_number_layers + tl] =
563 0 : 1000 * cfg->layer_target_bitrate[sl * oxcf->ts_number_layers + tl];
564 : }
565 : }
566 0 : if (oxcf->ss_number_layers == 1 && oxcf->pass != 0) {
567 0 : oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
568 : #if CONFIG_SPATIAL_SVC
569 : oxcf->ss_enable_auto_arf[0] = extra_cfg->enable_auto_alt_ref;
570 : #endif
571 : }
572 0 : if (oxcf->ts_number_layers > 1) {
573 0 : for (tl = 0; tl < VPX_TS_MAX_LAYERS; ++tl) {
574 0 : oxcf->ts_rate_decimator[tl] =
575 0 : cfg->ts_rate_decimator[tl] ? cfg->ts_rate_decimator[tl] : 1;
576 : }
577 0 : } else if (oxcf->ts_number_layers == 1) {
578 0 : oxcf->ts_rate_decimator[0] = 1;
579 : }
580 :
581 0 : if (get_level_index(oxcf->target_level) >= 0) config_target_level(oxcf);
582 : /*
583 : printf("Current VP9 Settings: \n");
584 : printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
585 : printf("target_level: %d\n", oxcf->target_level);
586 : printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
587 : printf("sharpness: %d\n", oxcf->sharpness);
588 : printf("cpu_used: %d\n", oxcf->cpu_used);
589 : printf("Mode: %d\n", oxcf->mode);
590 : printf("auto_key: %d\n", oxcf->auto_key);
591 : printf("key_freq: %d\n", oxcf->key_freq);
592 : printf("end_usage: %d\n", oxcf->end_usage);
593 : printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
594 : printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
595 : printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
596 : printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
597 : printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
598 : printf("fixed_q: %d\n", oxcf->fixed_q);
599 : printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
600 : printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
601 : printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
602 : printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width);
603 : printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height);
604 : printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
605 : printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
606 : printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
607 : printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
608 : printf("enable_auto_arf: %d\n", oxcf->enable_auto_arf);
609 : printf("Version: %d\n", oxcf->Version);
610 : printf("encode_breakout: %d\n", oxcf->encode_breakout);
611 : printf("error resilient: %d\n", oxcf->error_resilient_mode);
612 : printf("frame parallel detokenization: %d\n",
613 : oxcf->frame_parallel_decoding_mode);
614 : */
615 0 : return VPX_CODEC_OK;
616 : }
617 :
618 0 : static vpx_codec_err_t encoder_set_config(vpx_codec_alg_priv_t *ctx,
619 : const vpx_codec_enc_cfg_t *cfg) {
620 : vpx_codec_err_t res;
621 0 : int force_key = 0;
622 :
623 0 : if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h) {
624 0 : if (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS)
625 0 : ERROR("Cannot change width or height after initialization");
626 0 : if (!valid_ref_frame_size(ctx->cfg.g_w, ctx->cfg.g_h, cfg->g_w, cfg->g_h) ||
627 0 : (ctx->cpi->initial_width && (int)cfg->g_w > ctx->cpi->initial_width) ||
628 0 : (ctx->cpi->initial_height && (int)cfg->g_h > ctx->cpi->initial_height))
629 0 : force_key = 1;
630 : }
631 :
632 : // Prevent increasing lag_in_frames. This check is stricter than it needs
633 : // to be -- the limit is not increasing past the first lag_in_frames
634 : // value, but we don't track the initial config, only the last successful
635 : // config.
636 0 : if (cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)
637 0 : ERROR("Cannot increase lag_in_frames");
638 :
639 0 : res = validate_config(ctx, cfg, &ctx->extra_cfg);
640 :
641 0 : if (res == VPX_CODEC_OK) {
642 0 : ctx->cfg = *cfg;
643 0 : set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
644 : // On profile change, request a key frame
645 0 : force_key |= ctx->cpi->common.profile != ctx->oxcf.profile;
646 0 : vp9_change_config(ctx->cpi, &ctx->oxcf);
647 : }
648 :
649 0 : if (force_key) ctx->next_frame_flags |= VPX_EFLAG_FORCE_KF;
650 :
651 0 : return res;
652 : }
653 :
654 0 : static vpx_codec_err_t ctrl_get_quantizer(vpx_codec_alg_priv_t *ctx,
655 : va_list args) {
656 0 : int *const arg = va_arg(args, int *);
657 0 : if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
658 0 : *arg = vp9_get_quantizer(ctx->cpi);
659 0 : return VPX_CODEC_OK;
660 : }
661 :
662 0 : static vpx_codec_err_t ctrl_get_quantizer64(vpx_codec_alg_priv_t *ctx,
663 : va_list args) {
664 0 : int *const arg = va_arg(args, int *);
665 0 : if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
666 0 : *arg = vp9_qindex_to_quantizer(vp9_get_quantizer(ctx->cpi));
667 0 : return VPX_CODEC_OK;
668 : }
669 :
670 0 : static vpx_codec_err_t update_extra_cfg(vpx_codec_alg_priv_t *ctx,
671 : const struct vp9_extracfg *extra_cfg) {
672 0 : const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg);
673 0 : if (res == VPX_CODEC_OK) {
674 0 : ctx->extra_cfg = *extra_cfg;
675 0 : set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
676 0 : vp9_change_config(ctx->cpi, &ctx->oxcf);
677 : }
678 0 : return res;
679 : }
680 :
681 0 : static vpx_codec_err_t ctrl_set_cpuused(vpx_codec_alg_priv_t *ctx,
682 : va_list args) {
683 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
684 0 : extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args);
685 0 : return update_extra_cfg(ctx, &extra_cfg);
686 : }
687 :
688 0 : static vpx_codec_err_t ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx,
689 : va_list args) {
690 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
691 0 : extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args);
692 0 : return update_extra_cfg(ctx, &extra_cfg);
693 : }
694 :
695 0 : static vpx_codec_err_t ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t *ctx,
696 : va_list args) {
697 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
698 0 : extra_cfg.noise_sensitivity = CAST(VP9E_SET_NOISE_SENSITIVITY, args);
699 0 : return update_extra_cfg(ctx, &extra_cfg);
700 : }
701 :
702 0 : static vpx_codec_err_t ctrl_set_sharpness(vpx_codec_alg_priv_t *ctx,
703 : va_list args) {
704 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
705 0 : extra_cfg.sharpness = CAST(VP8E_SET_SHARPNESS, args);
706 0 : return update_extra_cfg(ctx, &extra_cfg);
707 : }
708 :
709 0 : static vpx_codec_err_t ctrl_set_static_thresh(vpx_codec_alg_priv_t *ctx,
710 : va_list args) {
711 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
712 0 : extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args);
713 0 : return update_extra_cfg(ctx, &extra_cfg);
714 : }
715 :
716 0 : static vpx_codec_err_t ctrl_set_tile_columns(vpx_codec_alg_priv_t *ctx,
717 : va_list args) {
718 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
719 0 : extra_cfg.tile_columns = CAST(VP9E_SET_TILE_COLUMNS, args);
720 0 : return update_extra_cfg(ctx, &extra_cfg);
721 : }
722 :
723 0 : static vpx_codec_err_t ctrl_set_tile_rows(vpx_codec_alg_priv_t *ctx,
724 : va_list args) {
725 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
726 0 : extra_cfg.tile_rows = CAST(VP9E_SET_TILE_ROWS, args);
727 0 : return update_extra_cfg(ctx, &extra_cfg);
728 : }
729 :
730 0 : static vpx_codec_err_t ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t *ctx,
731 : va_list args) {
732 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
733 0 : extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args);
734 0 : return update_extra_cfg(ctx, &extra_cfg);
735 : }
736 :
737 0 : static vpx_codec_err_t ctrl_set_arnr_strength(vpx_codec_alg_priv_t *ctx,
738 : va_list args) {
739 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
740 0 : extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args);
741 0 : return update_extra_cfg(ctx, &extra_cfg);
742 : }
743 :
744 0 : static vpx_codec_err_t ctrl_set_arnr_type(vpx_codec_alg_priv_t *ctx,
745 : va_list args) {
746 : (void)ctx;
747 : (void)args;
748 0 : return VPX_CODEC_OK;
749 : }
750 :
751 0 : static vpx_codec_err_t ctrl_set_tuning(vpx_codec_alg_priv_t *ctx,
752 : va_list args) {
753 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
754 0 : extra_cfg.tuning = CAST(VP8E_SET_TUNING, args);
755 0 : return update_extra_cfg(ctx, &extra_cfg);
756 : }
757 :
758 0 : static vpx_codec_err_t ctrl_set_cq_level(vpx_codec_alg_priv_t *ctx,
759 : va_list args) {
760 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
761 0 : extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args);
762 0 : return update_extra_cfg(ctx, &extra_cfg);
763 : }
764 :
765 0 : static vpx_codec_err_t ctrl_set_rc_max_intra_bitrate_pct(
766 : vpx_codec_alg_priv_t *ctx, va_list args) {
767 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
768 0 : extra_cfg.rc_max_intra_bitrate_pct =
769 0 : CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args);
770 0 : return update_extra_cfg(ctx, &extra_cfg);
771 : }
772 :
773 0 : static vpx_codec_err_t ctrl_set_rc_max_inter_bitrate_pct(
774 : vpx_codec_alg_priv_t *ctx, va_list args) {
775 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
776 0 : extra_cfg.rc_max_inter_bitrate_pct =
777 0 : CAST(VP8E_SET_MAX_INTER_BITRATE_PCT, args);
778 0 : return update_extra_cfg(ctx, &extra_cfg);
779 : }
780 :
781 0 : static vpx_codec_err_t ctrl_set_rc_gf_cbr_boost_pct(vpx_codec_alg_priv_t *ctx,
782 : va_list args) {
783 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
784 0 : extra_cfg.gf_cbr_boost_pct = CAST(VP9E_SET_GF_CBR_BOOST_PCT, args);
785 0 : return update_extra_cfg(ctx, &extra_cfg);
786 : }
787 :
788 0 : static vpx_codec_err_t ctrl_set_lossless(vpx_codec_alg_priv_t *ctx,
789 : va_list args) {
790 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
791 0 : extra_cfg.lossless = CAST(VP9E_SET_LOSSLESS, args);
792 0 : return update_extra_cfg(ctx, &extra_cfg);
793 : }
794 :
795 0 : static vpx_codec_err_t ctrl_set_frame_parallel_decoding_mode(
796 : vpx_codec_alg_priv_t *ctx, va_list args) {
797 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
798 0 : extra_cfg.frame_parallel_decoding_mode =
799 0 : CAST(VP9E_SET_FRAME_PARALLEL_DECODING, args);
800 0 : return update_extra_cfg(ctx, &extra_cfg);
801 : }
802 :
803 0 : static vpx_codec_err_t ctrl_set_aq_mode(vpx_codec_alg_priv_t *ctx,
804 : va_list args) {
805 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
806 0 : extra_cfg.aq_mode = CAST(VP9E_SET_AQ_MODE, args);
807 0 : return update_extra_cfg(ctx, &extra_cfg);
808 : }
809 :
810 0 : static vpx_codec_err_t ctrl_set_alt_ref_aq(vpx_codec_alg_priv_t *ctx,
811 : va_list args) {
812 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
813 0 : extra_cfg.alt_ref_aq = CAST(VP9E_SET_ALT_REF_AQ, args);
814 0 : return update_extra_cfg(ctx, &extra_cfg);
815 : }
816 :
817 0 : static vpx_codec_err_t ctrl_set_min_gf_interval(vpx_codec_alg_priv_t *ctx,
818 : va_list args) {
819 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
820 0 : extra_cfg.min_gf_interval = CAST(VP9E_SET_MIN_GF_INTERVAL, args);
821 0 : return update_extra_cfg(ctx, &extra_cfg);
822 : }
823 :
824 0 : static vpx_codec_err_t ctrl_set_max_gf_interval(vpx_codec_alg_priv_t *ctx,
825 : va_list args) {
826 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
827 0 : extra_cfg.max_gf_interval = CAST(VP9E_SET_MAX_GF_INTERVAL, args);
828 0 : return update_extra_cfg(ctx, &extra_cfg);
829 : }
830 :
831 0 : static vpx_codec_err_t ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t *ctx,
832 : va_list args) {
833 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
834 0 : extra_cfg.frame_periodic_boost = CAST(VP9E_SET_FRAME_PERIODIC_BOOST, args);
835 0 : return update_extra_cfg(ctx, &extra_cfg);
836 : }
837 :
838 0 : static vpx_codec_err_t ctrl_set_target_level(vpx_codec_alg_priv_t *ctx,
839 : va_list args) {
840 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
841 0 : extra_cfg.target_level = CAST(VP9E_SET_TARGET_LEVEL, args);
842 0 : return update_extra_cfg(ctx, &extra_cfg);
843 : }
844 :
845 0 : static vpx_codec_err_t ctrl_get_level(vpx_codec_alg_priv_t *ctx, va_list args) {
846 0 : int *const arg = va_arg(args, int *);
847 0 : if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
848 0 : *arg = (int)vp9_get_level(&ctx->cpi->level_info.level_spec);
849 0 : return VPX_CODEC_OK;
850 : }
851 :
852 0 : static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
853 : vpx_codec_priv_enc_mr_cfg_t *data) {
854 0 : vpx_codec_err_t res = VPX_CODEC_OK;
855 : (void)data;
856 :
857 0 : if (ctx->priv == NULL) {
858 0 : vpx_codec_alg_priv_t *const priv = vpx_calloc(1, sizeof(*priv));
859 0 : if (priv == NULL) return VPX_CODEC_MEM_ERROR;
860 :
861 0 : ctx->priv = (vpx_codec_priv_t *)priv;
862 0 : ctx->priv->init_flags = ctx->init_flags;
863 0 : ctx->priv->enc.total_encoders = 1;
864 0 : priv->buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(BufferPool));
865 0 : if (priv->buffer_pool == NULL) return VPX_CODEC_MEM_ERROR;
866 :
867 : #if CONFIG_MULTITHREAD
868 0 : if (pthread_mutex_init(&priv->buffer_pool->pool_mutex, NULL)) {
869 0 : return VPX_CODEC_MEM_ERROR;
870 : }
871 : #endif
872 :
873 0 : if (ctx->config.enc) {
874 : // Update the reference to the config structure to an internal copy.
875 0 : priv->cfg = *ctx->config.enc;
876 0 : ctx->config.enc = &priv->cfg;
877 : }
878 :
879 0 : priv->extra_cfg = default_extra_cfg;
880 0 : once(vp9_initialize_enc);
881 :
882 0 : res = validate_config(priv, &priv->cfg, &priv->extra_cfg);
883 :
884 0 : if (res == VPX_CODEC_OK) {
885 0 : set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
886 : #if CONFIG_VP9_HIGHBITDEPTH
887 : priv->oxcf.use_highbitdepth =
888 : (ctx->init_flags & VPX_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
889 : #endif
890 0 : priv->cpi = vp9_create_compressor(&priv->oxcf, priv->buffer_pool);
891 0 : if (priv->cpi == NULL)
892 0 : res = VPX_CODEC_MEM_ERROR;
893 : else
894 0 : priv->cpi->output_pkt_list = &priv->pkt_list.head;
895 : }
896 : }
897 :
898 0 : return res;
899 : }
900 :
901 0 : static vpx_codec_err_t encoder_destroy(vpx_codec_alg_priv_t *ctx) {
902 0 : free(ctx->cx_data);
903 0 : vp9_remove_compressor(ctx->cpi);
904 : #if CONFIG_MULTITHREAD
905 0 : pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
906 : #endif
907 0 : vpx_free(ctx->buffer_pool);
908 0 : vpx_free(ctx);
909 0 : return VPX_CODEC_OK;
910 : }
911 :
912 0 : static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
913 : unsigned long duration,
914 : unsigned long deadline) {
915 0 : MODE new_mode = BEST;
916 :
917 0 : switch (ctx->cfg.g_pass) {
918 : case VPX_RC_ONE_PASS:
919 0 : if (deadline > 0) {
920 0 : const vpx_codec_enc_cfg_t *const cfg = &ctx->cfg;
921 :
922 : // Convert duration parameter from stream timebase to microseconds.
923 0 : const uint64_t duration_us = (uint64_t)duration * 1000000 *
924 0 : (uint64_t)cfg->g_timebase.num /
925 0 : (uint64_t)cfg->g_timebase.den;
926 :
927 : // If the deadline is more that the duration this frame is to be shown,
928 : // use good quality mode. Otherwise use realtime mode.
929 0 : new_mode = (deadline > duration_us) ? GOOD : REALTIME;
930 : } else {
931 0 : new_mode = BEST;
932 : }
933 0 : break;
934 0 : case VPX_RC_FIRST_PASS: break;
935 0 : case VPX_RC_LAST_PASS: new_mode = deadline > 0 ? GOOD : BEST; break;
936 : }
937 :
938 0 : if (deadline == VPX_DL_REALTIME) {
939 0 : ctx->oxcf.pass = 0;
940 0 : new_mode = REALTIME;
941 : }
942 :
943 0 : if (ctx->oxcf.mode != new_mode) {
944 0 : ctx->oxcf.mode = new_mode;
945 0 : vp9_change_config(ctx->cpi, &ctx->oxcf);
946 : }
947 0 : }
948 :
949 : // Turn on to test if supplemental superframe data breaks decoding
950 : // #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
951 0 : static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
952 0 : uint8_t marker = 0xc0;
953 : unsigned int mask;
954 : int mag, index_sz;
955 :
956 0 : assert(ctx->pending_frame_count);
957 0 : assert(ctx->pending_frame_count <= 8);
958 :
959 : // Add the number of frames to the marker byte
960 0 : marker |= ctx->pending_frame_count - 1;
961 :
962 : // Choose the magnitude
963 0 : for (mag = 0, mask = 0xff; mag < 4; mag++) {
964 0 : if (ctx->pending_frame_magnitude < mask) break;
965 0 : mask <<= 8;
966 0 : mask |= 0xff;
967 : }
968 0 : marker |= mag << 3;
969 :
970 : // Write the index
971 0 : index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
972 0 : if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
973 0 : uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
974 : int i, j;
975 : #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
976 : uint8_t marker_test = 0xc0;
977 : int mag_test = 2; // 1 - 4
978 : int frames_test = 4; // 1 - 8
979 : int index_sz_test = 2 + mag_test * frames_test;
980 : marker_test |= frames_test - 1;
981 : marker_test |= (mag_test - 1) << 3;
982 : *x++ = marker_test;
983 : for (i = 0; i < mag_test * frames_test; ++i)
984 : *x++ = 0; // fill up with arbitrary data
985 : *x++ = marker_test;
986 : ctx->pending_cx_data_sz += index_sz_test;
987 : printf("Added supplemental superframe data\n");
988 : #endif
989 :
990 0 : *x++ = marker;
991 0 : for (i = 0; i < ctx->pending_frame_count; i++) {
992 0 : unsigned int this_sz = (unsigned int)ctx->pending_frame_sizes[i];
993 :
994 0 : for (j = 0; j <= mag; j++) {
995 0 : *x++ = this_sz & 0xff;
996 0 : this_sz >>= 8;
997 : }
998 : }
999 0 : *x++ = marker;
1000 0 : ctx->pending_cx_data_sz += index_sz;
1001 : #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
1002 : index_sz += index_sz_test;
1003 : #endif
1004 : }
1005 0 : return index_sz;
1006 : }
1007 :
1008 0 : static int64_t timebase_units_to_ticks(const vpx_rational_t *timebase,
1009 : int64_t n) {
1010 0 : return n * TICKS_PER_SEC * timebase->num / timebase->den;
1011 : }
1012 :
1013 0 : static int64_t ticks_to_timebase_units(const vpx_rational_t *timebase,
1014 : int64_t n) {
1015 0 : const int64_t round = (int64_t)TICKS_PER_SEC * timebase->num / 2 - 1;
1016 0 : return (n * timebase->den + round) / timebase->num / TICKS_PER_SEC;
1017 : }
1018 :
1019 0 : static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP9_COMP *cpi,
1020 : unsigned int lib_flags) {
1021 0 : vpx_codec_frame_flags_t flags = lib_flags << 16;
1022 :
1023 0 : if (lib_flags & FRAMEFLAGS_KEY ||
1024 0 : (cpi->use_svc &&
1025 : cpi->svc
1026 0 : .layer_context[cpi->svc.spatial_layer_id *
1027 0 : cpi->svc.number_temporal_layers +
1028 0 : cpi->svc.temporal_layer_id]
1029 0 : .is_key_frame))
1030 0 : flags |= VPX_FRAME_IS_KEY;
1031 :
1032 0 : if (cpi->droppable) flags |= VPX_FRAME_IS_DROPPABLE;
1033 :
1034 0 : return flags;
1035 : }
1036 :
1037 : const size_t kMinCompressedSize = 8192;
1038 0 : static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
1039 : const vpx_image_t *img,
1040 : vpx_codec_pts_t pts,
1041 : unsigned long duration,
1042 : vpx_enc_frame_flags_t enc_flags,
1043 : unsigned long deadline) {
1044 0 : volatile vpx_codec_err_t res = VPX_CODEC_OK;
1045 0 : volatile vpx_enc_frame_flags_t flags = enc_flags;
1046 0 : VP9_COMP *const cpi = ctx->cpi;
1047 0 : const vpx_rational_t *const timebase = &ctx->cfg.g_timebase;
1048 : size_t data_sz;
1049 :
1050 0 : if (cpi == NULL) return VPX_CODEC_INVALID_PARAM;
1051 :
1052 0 : if (cpi->oxcf.pass == 2 && cpi->level_constraint.level_index >= 0 &&
1053 0 : !cpi->level_constraint.rc_config_updated) {
1054 0 : SVC *const svc = &cpi->svc;
1055 0 : const int is_two_pass_svc =
1056 0 : (svc->number_spatial_layers > 1) || (svc->number_temporal_layers > 1);
1057 0 : const VP9EncoderConfig *const oxcf = &cpi->oxcf;
1058 0 : TWO_PASS *const twopass = &cpi->twopass;
1059 0 : FIRSTPASS_STATS *stats = &twopass->total_stats;
1060 0 : if (is_two_pass_svc) {
1061 0 : const double frame_rate = 10000000.0 * stats->count / stats->duration;
1062 0 : vp9_update_spatial_layer_framerate(cpi, frame_rate);
1063 0 : twopass->bits_left =
1064 0 : (int64_t)(stats->duration *
1065 0 : svc->layer_context[svc->spatial_layer_id].target_bandwidth /
1066 : 10000000.0);
1067 : } else {
1068 0 : twopass->bits_left =
1069 0 : (int64_t)(stats->duration * oxcf->target_bandwidth / 10000000.0);
1070 : }
1071 0 : cpi->level_constraint.rc_config_updated = 1;
1072 : }
1073 :
1074 0 : if (img != NULL) {
1075 0 : res = validate_img(ctx, img);
1076 0 : if (res == VPX_CODEC_OK) {
1077 : // There's no codec control for multiple alt-refs so check the encoder
1078 : // instance for its status to determine the compressed data size.
1079 0 : data_sz = ctx->cfg.g_w * ctx->cfg.g_h * get_image_bps(img) / 8 *
1080 0 : (cpi->multi_arf_allowed ? 8 : 2);
1081 0 : if (data_sz < kMinCompressedSize) data_sz = kMinCompressedSize;
1082 0 : if (ctx->cx_data == NULL || ctx->cx_data_sz < data_sz) {
1083 0 : ctx->cx_data_sz = data_sz;
1084 0 : free(ctx->cx_data);
1085 0 : ctx->cx_data = (unsigned char *)malloc(ctx->cx_data_sz);
1086 0 : if (ctx->cx_data == NULL) {
1087 0 : return VPX_CODEC_MEM_ERROR;
1088 : }
1089 : }
1090 : }
1091 : }
1092 :
1093 0 : pick_quickcompress_mode(ctx, duration, deadline);
1094 0 : vpx_codec_pkt_list_init(&ctx->pkt_list);
1095 :
1096 : // Handle Flags
1097 0 : if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) ||
1098 0 : ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
1099 0 : ctx->base.err_detail = "Conflicting flags.";
1100 0 : return VPX_CODEC_INVALID_PARAM;
1101 : }
1102 :
1103 0 : if (setjmp(cpi->common.error.jmp)) {
1104 0 : cpi->common.error.setjmp = 0;
1105 0 : res = update_error_state(ctx, &cpi->common.error);
1106 0 : vpx_clear_system_state();
1107 0 : return res;
1108 : }
1109 0 : cpi->common.error.setjmp = 1;
1110 :
1111 0 : vp9_apply_encoding_flags(cpi, flags);
1112 :
1113 : // Handle fixed keyframe intervals
1114 0 : if (ctx->cfg.kf_mode == VPX_KF_AUTO &&
1115 0 : ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
1116 0 : if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
1117 0 : flags |= VPX_EFLAG_FORCE_KF;
1118 0 : ctx->fixed_kf_cntr = 1;
1119 : }
1120 : }
1121 :
1122 0 : if (res == VPX_CODEC_OK) {
1123 0 : unsigned int lib_flags = 0;
1124 : YV12_BUFFER_CONFIG sd;
1125 0 : int64_t dst_time_stamp = timebase_units_to_ticks(timebase, pts);
1126 0 : int64_t dst_end_time_stamp =
1127 0 : timebase_units_to_ticks(timebase, pts + duration);
1128 : size_t size, cx_data_sz;
1129 : unsigned char *cx_data;
1130 :
1131 : // Set up internal flags
1132 0 : if (ctx->base.init_flags & VPX_CODEC_USE_PSNR) cpi->b_calculate_psnr = 1;
1133 :
1134 0 : if (img != NULL) {
1135 0 : res = image2yuvconfig(img, &sd);
1136 :
1137 0 : if (sd.y_width != ctx->cfg.g_w || sd.y_height != ctx->cfg.g_h) {
1138 : /* from vpx_encoder.h for g_w/g_h:
1139 : "Note that the frames passed as input to the encoder must have this
1140 : resolution"
1141 : */
1142 0 : ctx->base.err_detail = "Invalid input frame resolution";
1143 0 : res = VPX_CODEC_INVALID_PARAM;
1144 : } else {
1145 : // Store the original flags in to the frame buffer. Will extract the
1146 : // key frame flag when we actually encode this frame.
1147 0 : if (vp9_receive_raw_frame(cpi, flags | ctx->next_frame_flags, &sd,
1148 : dst_time_stamp, dst_end_time_stamp)) {
1149 0 : res = update_error_state(ctx, &cpi->common.error);
1150 : }
1151 : }
1152 0 : ctx->next_frame_flags = 0;
1153 : }
1154 :
1155 0 : cx_data = ctx->cx_data;
1156 0 : cx_data_sz = ctx->cx_data_sz;
1157 :
1158 : /* Any pending invisible frames? */
1159 0 : if (ctx->pending_cx_data) {
1160 0 : memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
1161 0 : ctx->pending_cx_data = cx_data;
1162 0 : cx_data += ctx->pending_cx_data_sz;
1163 0 : cx_data_sz -= ctx->pending_cx_data_sz;
1164 :
1165 : /* TODO: this is a minimal check, the underlying codec doesn't respect
1166 : * the buffer size anyway.
1167 : */
1168 0 : if (cx_data_sz < ctx->cx_data_sz / 2) {
1169 0 : vpx_internal_error(&cpi->common.error, VPX_CODEC_ERROR,
1170 : "Compressed data buffer too small");
1171 0 : return VPX_CODEC_ERROR;
1172 : }
1173 : }
1174 :
1175 0 : while (cx_data_sz >= ctx->cx_data_sz / 2 &&
1176 0 : -1 != vp9_get_compressed_data(cpi, &lib_flags, &size, cx_data,
1177 : &dst_time_stamp, &dst_end_time_stamp,
1178 : !img)) {
1179 0 : if (size) {
1180 : vpx_codec_cx_pkt_t pkt;
1181 :
1182 : #if CONFIG_SPATIAL_SVC
1183 : if (cpi->use_svc)
1184 : cpi->svc
1185 : .layer_context[cpi->svc.spatial_layer_id *
1186 : cpi->svc.number_temporal_layers]
1187 : .layer_size += size;
1188 : #endif
1189 :
1190 : // Pack invisible frames with the next visible frame
1191 0 : if (!cpi->common.show_frame ||
1192 0 : (cpi->use_svc &&
1193 0 : cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)) {
1194 0 : if (ctx->pending_cx_data == 0) ctx->pending_cx_data = cx_data;
1195 0 : ctx->pending_cx_data_sz += size;
1196 0 : ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
1197 0 : ctx->pending_frame_magnitude |= size;
1198 0 : cx_data += size;
1199 0 : cx_data_sz -= size;
1200 :
1201 0 : if (ctx->output_cx_pkt_cb.output_cx_pkt) {
1202 0 : pkt.kind = VPX_CODEC_CX_FRAME_PKT;
1203 0 : pkt.data.frame.pts =
1204 0 : ticks_to_timebase_units(timebase, dst_time_stamp);
1205 0 : pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units(
1206 : timebase, dst_end_time_stamp - dst_time_stamp);
1207 0 : pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
1208 0 : pkt.data.frame.buf = ctx->pending_cx_data;
1209 0 : pkt.data.frame.sz = size;
1210 0 : ctx->pending_cx_data = NULL;
1211 0 : ctx->pending_cx_data_sz = 0;
1212 0 : ctx->pending_frame_count = 0;
1213 0 : ctx->pending_frame_magnitude = 0;
1214 0 : ctx->output_cx_pkt_cb.output_cx_pkt(
1215 : &pkt, ctx->output_cx_pkt_cb.user_priv);
1216 : }
1217 0 : continue;
1218 : }
1219 :
1220 : // Add the frame packet to the list of returned packets.
1221 0 : pkt.kind = VPX_CODEC_CX_FRAME_PKT;
1222 0 : pkt.data.frame.pts = ticks_to_timebase_units(timebase, dst_time_stamp);
1223 0 : pkt.data.frame.duration = (unsigned long)ticks_to_timebase_units(
1224 : timebase, dst_end_time_stamp - dst_time_stamp);
1225 0 : pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
1226 :
1227 0 : if (ctx->pending_cx_data) {
1228 0 : ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
1229 0 : ctx->pending_frame_magnitude |= size;
1230 0 : ctx->pending_cx_data_sz += size;
1231 : // write the superframe only for the case when
1232 0 : if (!ctx->output_cx_pkt_cb.output_cx_pkt)
1233 0 : size += write_superframe_index(ctx);
1234 0 : pkt.data.frame.buf = ctx->pending_cx_data;
1235 0 : pkt.data.frame.sz = ctx->pending_cx_data_sz;
1236 0 : ctx->pending_cx_data = NULL;
1237 0 : ctx->pending_cx_data_sz = 0;
1238 0 : ctx->pending_frame_count = 0;
1239 0 : ctx->pending_frame_magnitude = 0;
1240 : } else {
1241 0 : pkt.data.frame.buf = cx_data;
1242 0 : pkt.data.frame.sz = size;
1243 : }
1244 0 : pkt.data.frame.partition_id = -1;
1245 :
1246 0 : if (ctx->output_cx_pkt_cb.output_cx_pkt)
1247 0 : ctx->output_cx_pkt_cb.output_cx_pkt(&pkt,
1248 : ctx->output_cx_pkt_cb.user_priv);
1249 : else
1250 0 : vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
1251 :
1252 0 : cx_data += size;
1253 0 : cx_data_sz -= size;
1254 : #if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
1255 : #if CONFIG_SPATIAL_SVC
1256 : if (cpi->use_svc && !ctx->output_cx_pkt_cb.output_cx_pkt) {
1257 : vpx_codec_cx_pkt_t pkt_sizes, pkt_psnr;
1258 : int sl;
1259 : vp9_zero(pkt_sizes);
1260 : vp9_zero(pkt_psnr);
1261 : pkt_sizes.kind = VPX_CODEC_SPATIAL_SVC_LAYER_SIZES;
1262 : pkt_psnr.kind = VPX_CODEC_SPATIAL_SVC_LAYER_PSNR;
1263 : for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
1264 : LAYER_CONTEXT *lc =
1265 : &cpi->svc.layer_context[sl * cpi->svc.number_temporal_layers];
1266 : pkt_sizes.data.layer_sizes[sl] = lc->layer_size;
1267 : pkt_psnr.data.layer_psnr[sl] = lc->psnr_pkt;
1268 : lc->layer_size = 0;
1269 : }
1270 :
1271 : vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_sizes);
1272 :
1273 : vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_psnr);
1274 : }
1275 : #endif
1276 : #endif
1277 0 : if (is_one_pass_cbr_svc(cpi) &&
1278 0 : (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1)) {
1279 : // Encoded all spatial layers; exit loop.
1280 0 : break;
1281 : }
1282 : }
1283 : }
1284 : }
1285 :
1286 0 : cpi->common.error.setjmp = 0;
1287 0 : return res;
1288 : }
1289 :
1290 0 : static const vpx_codec_cx_pkt_t *encoder_get_cxdata(vpx_codec_alg_priv_t *ctx,
1291 : vpx_codec_iter_t *iter) {
1292 0 : return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
1293 : }
1294 :
1295 0 : static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
1296 : va_list args) {
1297 0 : vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
1298 :
1299 0 : if (frame != NULL) {
1300 : YV12_BUFFER_CONFIG sd;
1301 :
1302 0 : image2yuvconfig(&frame->img, &sd);
1303 0 : vp9_set_reference_enc(ctx->cpi, ref_frame_to_vp9_reframe(frame->frame_type),
1304 : &sd);
1305 0 : return VPX_CODEC_OK;
1306 : } else {
1307 0 : return VPX_CODEC_INVALID_PARAM;
1308 : }
1309 : }
1310 :
1311 0 : static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
1312 : va_list args) {
1313 0 : vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
1314 :
1315 0 : if (frame != NULL) {
1316 : YV12_BUFFER_CONFIG sd;
1317 :
1318 0 : image2yuvconfig(&frame->img, &sd);
1319 0 : vp9_copy_reference_enc(ctx->cpi,
1320 : ref_frame_to_vp9_reframe(frame->frame_type), &sd);
1321 0 : return VPX_CODEC_OK;
1322 : } else {
1323 0 : return VPX_CODEC_INVALID_PARAM;
1324 : }
1325 : }
1326 :
1327 0 : static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
1328 : va_list args) {
1329 0 : vp9_ref_frame_t *const frame = va_arg(args, vp9_ref_frame_t *);
1330 :
1331 0 : if (frame != NULL) {
1332 0 : YV12_BUFFER_CONFIG *fb = get_ref_frame(&ctx->cpi->common, frame->idx);
1333 0 : if (fb == NULL) return VPX_CODEC_ERROR;
1334 :
1335 0 : yuvconfig2image(&frame->img, fb, NULL);
1336 0 : return VPX_CODEC_OK;
1337 : } else {
1338 0 : return VPX_CODEC_INVALID_PARAM;
1339 : }
1340 : }
1341 :
1342 0 : static vpx_codec_err_t ctrl_set_previewpp(vpx_codec_alg_priv_t *ctx,
1343 : va_list args) {
1344 : #if CONFIG_VP9_POSTPROC
1345 0 : vp8_postproc_cfg_t *config = va_arg(args, vp8_postproc_cfg_t *);
1346 0 : if (config != NULL) {
1347 0 : ctx->preview_ppcfg = *config;
1348 0 : return VPX_CODEC_OK;
1349 : } else {
1350 0 : return VPX_CODEC_INVALID_PARAM;
1351 : }
1352 : #else
1353 : (void)ctx;
1354 : (void)args;
1355 : return VPX_CODEC_INCAPABLE;
1356 : #endif
1357 : }
1358 :
1359 0 : static vpx_image_t *encoder_get_preview(vpx_codec_alg_priv_t *ctx) {
1360 : YV12_BUFFER_CONFIG sd;
1361 : vp9_ppflags_t flags;
1362 0 : vp9_zero(flags);
1363 :
1364 0 : if (ctx->preview_ppcfg.post_proc_flag) {
1365 0 : flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag;
1366 0 : flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
1367 0 : flags.noise_level = ctx->preview_ppcfg.noise_level;
1368 : }
1369 :
1370 0 : if (vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags) == 0) {
1371 0 : yuvconfig2image(&ctx->preview_img, &sd, NULL);
1372 0 : return &ctx->preview_img;
1373 : } else {
1374 0 : return NULL;
1375 : }
1376 : }
1377 :
1378 0 : static vpx_codec_err_t ctrl_set_roi_map(vpx_codec_alg_priv_t *ctx,
1379 : va_list args) {
1380 : (void)ctx;
1381 : (void)args;
1382 :
1383 : // TODO(yaowu): Need to re-implement and test for VP9.
1384 0 : return VPX_CODEC_INVALID_PARAM;
1385 : }
1386 :
1387 0 : static vpx_codec_err_t ctrl_set_active_map(vpx_codec_alg_priv_t *ctx,
1388 : va_list args) {
1389 0 : vpx_active_map_t *const map = va_arg(args, vpx_active_map_t *);
1390 :
1391 0 : if (map) {
1392 0 : if (!vp9_set_active_map(ctx->cpi, map->active_map, (int)map->rows,
1393 0 : (int)map->cols))
1394 0 : return VPX_CODEC_OK;
1395 : else
1396 0 : return VPX_CODEC_INVALID_PARAM;
1397 : } else {
1398 0 : return VPX_CODEC_INVALID_PARAM;
1399 : }
1400 : }
1401 :
1402 0 : static vpx_codec_err_t ctrl_get_active_map(vpx_codec_alg_priv_t *ctx,
1403 : va_list args) {
1404 0 : vpx_active_map_t *const map = va_arg(args, vpx_active_map_t *);
1405 :
1406 0 : if (map) {
1407 0 : if (!vp9_get_active_map(ctx->cpi, map->active_map, (int)map->rows,
1408 0 : (int)map->cols))
1409 0 : return VPX_CODEC_OK;
1410 : else
1411 0 : return VPX_CODEC_INVALID_PARAM;
1412 : } else {
1413 0 : return VPX_CODEC_INVALID_PARAM;
1414 : }
1415 : }
1416 :
1417 0 : static vpx_codec_err_t ctrl_set_scale_mode(vpx_codec_alg_priv_t *ctx,
1418 : va_list args) {
1419 0 : vpx_scaling_mode_t *const mode = va_arg(args, vpx_scaling_mode_t *);
1420 :
1421 0 : if (mode) {
1422 0 : const int res =
1423 0 : vp9_set_internal_size(ctx->cpi, (VPX_SCALING)mode->h_scaling_mode,
1424 0 : (VPX_SCALING)mode->v_scaling_mode);
1425 0 : return (res == 0) ? VPX_CODEC_OK : VPX_CODEC_INVALID_PARAM;
1426 : } else {
1427 0 : return VPX_CODEC_INVALID_PARAM;
1428 : }
1429 : }
1430 :
1431 0 : static vpx_codec_err_t ctrl_set_svc(vpx_codec_alg_priv_t *ctx, va_list args) {
1432 0 : int data = va_arg(args, int);
1433 0 : const vpx_codec_enc_cfg_t *cfg = &ctx->cfg;
1434 : // Both one-pass and two-pass RC are supported now.
1435 : // User setting this has to make sure of the following.
1436 : // In two-pass setting: either (but not both)
1437 : // cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
1438 : // In one-pass setting:
1439 : // either or both cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
1440 :
1441 0 : vp9_set_svc(ctx->cpi, data);
1442 :
1443 0 : if (data == 1 &&
1444 0 : (cfg->g_pass == VPX_RC_FIRST_PASS || cfg->g_pass == VPX_RC_LAST_PASS) &&
1445 0 : cfg->ss_number_layers > 1 && cfg->ts_number_layers > 1) {
1446 0 : return VPX_CODEC_INVALID_PARAM;
1447 : }
1448 0 : return VPX_CODEC_OK;
1449 : }
1450 :
1451 0 : static vpx_codec_err_t ctrl_set_svc_layer_id(vpx_codec_alg_priv_t *ctx,
1452 : va_list args) {
1453 0 : vpx_svc_layer_id_t *const data = va_arg(args, vpx_svc_layer_id_t *);
1454 0 : VP9_COMP *const cpi = (VP9_COMP *)ctx->cpi;
1455 0 : SVC *const svc = &cpi->svc;
1456 :
1457 0 : svc->first_spatial_layer_to_encode = data->spatial_layer_id;
1458 0 : svc->spatial_layer_to_encode = data->spatial_layer_id;
1459 0 : svc->temporal_layer_id = data->temporal_layer_id;
1460 : // Checks on valid layer_id input.
1461 0 : if (svc->temporal_layer_id < 0 ||
1462 0 : svc->temporal_layer_id >= (int)ctx->cfg.ts_number_layers) {
1463 0 : return VPX_CODEC_INVALID_PARAM;
1464 : }
1465 0 : if (svc->first_spatial_layer_to_encode < 0 ||
1466 0 : svc->first_spatial_layer_to_encode >= (int)ctx->cfg.ss_number_layers) {
1467 0 : return VPX_CODEC_INVALID_PARAM;
1468 : }
1469 : // First spatial layer to encode not implemented for two-pass.
1470 0 : if (is_two_pass_svc(cpi) && svc->first_spatial_layer_to_encode > 0)
1471 0 : return VPX_CODEC_INVALID_PARAM;
1472 0 : return VPX_CODEC_OK;
1473 : }
1474 :
1475 0 : static vpx_codec_err_t ctrl_get_svc_layer_id(vpx_codec_alg_priv_t *ctx,
1476 : va_list args) {
1477 0 : vpx_svc_layer_id_t *data = va_arg(args, vpx_svc_layer_id_t *);
1478 0 : VP9_COMP *const cpi = (VP9_COMP *)ctx->cpi;
1479 0 : SVC *const svc = &cpi->svc;
1480 :
1481 0 : data->spatial_layer_id = svc->spatial_layer_id;
1482 0 : data->temporal_layer_id = svc->temporal_layer_id;
1483 :
1484 0 : return VPX_CODEC_OK;
1485 : }
1486 :
1487 0 : static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
1488 : va_list args) {
1489 0 : VP9_COMP *const cpi = ctx->cpi;
1490 0 : vpx_svc_extra_cfg_t *const params = va_arg(args, vpx_svc_extra_cfg_t *);
1491 : int sl, tl;
1492 :
1493 : // Number of temporal layers and number of spatial layers have to be set
1494 : // properly before calling this control function.
1495 0 : for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
1496 0 : for (tl = 0; tl < cpi->svc.number_temporal_layers; ++tl) {
1497 0 : const int layer =
1498 0 : LAYER_IDS_TO_IDX(sl, tl, cpi->svc.number_temporal_layers);
1499 0 : LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
1500 0 : lc->max_q = params->max_quantizers[layer];
1501 0 : lc->min_q = params->min_quantizers[layer];
1502 0 : lc->scaling_factor_num = params->scaling_factor_num[sl];
1503 0 : lc->scaling_factor_den = params->scaling_factor_den[sl];
1504 0 : lc->speed = params->speed_per_layer[sl];
1505 : }
1506 : }
1507 :
1508 0 : return VPX_CODEC_OK;
1509 : }
1510 :
1511 0 : static vpx_codec_err_t ctrl_set_svc_ref_frame_config(vpx_codec_alg_priv_t *ctx,
1512 : va_list args) {
1513 0 : VP9_COMP *const cpi = ctx->cpi;
1514 0 : vpx_svc_ref_frame_config_t *data = va_arg(args, vpx_svc_ref_frame_config_t *);
1515 : int sl;
1516 0 : for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
1517 0 : cpi->svc.ext_frame_flags[sl] = data->frame_flags[sl];
1518 0 : cpi->svc.ext_lst_fb_idx[sl] = data->lst_fb_idx[sl];
1519 0 : cpi->svc.ext_gld_fb_idx[sl] = data->gld_fb_idx[sl];
1520 0 : cpi->svc.ext_alt_fb_idx[sl] = data->alt_fb_idx[sl];
1521 : }
1522 0 : return VPX_CODEC_OK;
1523 : }
1524 :
1525 0 : static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx,
1526 : va_list args) {
1527 0 : vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp =
1528 : (vpx_codec_priv_output_cx_pkt_cb_pair_t *)va_arg(args, void *);
1529 0 : ctx->output_cx_pkt_cb.output_cx_pkt = cbp->output_cx_pkt;
1530 0 : ctx->output_cx_pkt_cb.user_priv = cbp->user_priv;
1531 :
1532 0 : return VPX_CODEC_OK;
1533 : }
1534 :
1535 0 : static vpx_codec_err_t ctrl_set_tune_content(vpx_codec_alg_priv_t *ctx,
1536 : va_list args) {
1537 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
1538 0 : extra_cfg.content = CAST(VP9E_SET_TUNE_CONTENT, args);
1539 0 : return update_extra_cfg(ctx, &extra_cfg);
1540 : }
1541 :
1542 0 : static vpx_codec_err_t ctrl_set_color_space(vpx_codec_alg_priv_t *ctx,
1543 : va_list args) {
1544 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
1545 0 : extra_cfg.color_space = CAST(VP9E_SET_COLOR_SPACE, args);
1546 0 : return update_extra_cfg(ctx, &extra_cfg);
1547 : }
1548 :
1549 0 : static vpx_codec_err_t ctrl_set_color_range(vpx_codec_alg_priv_t *ctx,
1550 : va_list args) {
1551 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
1552 0 : extra_cfg.color_range = CAST(VP9E_SET_COLOR_RANGE, args);
1553 0 : return update_extra_cfg(ctx, &extra_cfg);
1554 : }
1555 :
1556 0 : static vpx_codec_err_t ctrl_set_render_size(vpx_codec_alg_priv_t *ctx,
1557 : va_list args) {
1558 0 : struct vp9_extracfg extra_cfg = ctx->extra_cfg;
1559 0 : int *const render_size = va_arg(args, int *);
1560 0 : extra_cfg.render_width = render_size[0];
1561 0 : extra_cfg.render_height = render_size[1];
1562 0 : return update_extra_cfg(ctx, &extra_cfg);
1563 : }
1564 :
1565 : static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
1566 : { VP8_COPY_REFERENCE, ctrl_copy_reference },
1567 :
1568 : // Setters
1569 : { VP8_SET_REFERENCE, ctrl_set_reference },
1570 : { VP8_SET_POSTPROC, ctrl_set_previewpp },
1571 : { VP8E_SET_ROI_MAP, ctrl_set_roi_map },
1572 : { VP8E_SET_ACTIVEMAP, ctrl_set_active_map },
1573 : { VP8E_SET_SCALEMODE, ctrl_set_scale_mode },
1574 : { VP8E_SET_CPUUSED, ctrl_set_cpuused },
1575 : { VP8E_SET_ENABLEAUTOALTREF, ctrl_set_enable_auto_alt_ref },
1576 : { VP8E_SET_SHARPNESS, ctrl_set_sharpness },
1577 : { VP8E_SET_STATIC_THRESHOLD, ctrl_set_static_thresh },
1578 : { VP9E_SET_TILE_COLUMNS, ctrl_set_tile_columns },
1579 : { VP9E_SET_TILE_ROWS, ctrl_set_tile_rows },
1580 : { VP8E_SET_ARNR_MAXFRAMES, ctrl_set_arnr_max_frames },
1581 : { VP8E_SET_ARNR_STRENGTH, ctrl_set_arnr_strength },
1582 : { VP8E_SET_ARNR_TYPE, ctrl_set_arnr_type },
1583 : { VP8E_SET_TUNING, ctrl_set_tuning },
1584 : { VP8E_SET_CQ_LEVEL, ctrl_set_cq_level },
1585 : { VP8E_SET_MAX_INTRA_BITRATE_PCT, ctrl_set_rc_max_intra_bitrate_pct },
1586 : { VP9E_SET_MAX_INTER_BITRATE_PCT, ctrl_set_rc_max_inter_bitrate_pct },
1587 : { VP9E_SET_GF_CBR_BOOST_PCT, ctrl_set_rc_gf_cbr_boost_pct },
1588 : { VP9E_SET_LOSSLESS, ctrl_set_lossless },
1589 : { VP9E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode },
1590 : { VP9E_SET_AQ_MODE, ctrl_set_aq_mode },
1591 : { VP9E_SET_ALT_REF_AQ, ctrl_set_alt_ref_aq },
1592 : { VP9E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost },
1593 : { VP9E_SET_SVC, ctrl_set_svc },
1594 : { VP9E_SET_SVC_PARAMETERS, ctrl_set_svc_parameters },
1595 : { VP9E_REGISTER_CX_CALLBACK, ctrl_register_cx_callback },
1596 : { VP9E_SET_SVC_LAYER_ID, ctrl_set_svc_layer_id },
1597 : { VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content },
1598 : { VP9E_SET_COLOR_SPACE, ctrl_set_color_space },
1599 : { VP9E_SET_COLOR_RANGE, ctrl_set_color_range },
1600 : { VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity },
1601 : { VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval },
1602 : { VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval },
1603 : { VP9E_SET_SVC_REF_FRAME_CONFIG, ctrl_set_svc_ref_frame_config },
1604 : { VP9E_SET_RENDER_SIZE, ctrl_set_render_size },
1605 : { VP9E_SET_TARGET_LEVEL, ctrl_set_target_level },
1606 :
1607 : // Getters
1608 : { VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer },
1609 : { VP8E_GET_LAST_QUANTIZER_64, ctrl_get_quantizer64 },
1610 : { VP9_GET_REFERENCE, ctrl_get_reference },
1611 : { VP9E_GET_SVC_LAYER_ID, ctrl_get_svc_layer_id },
1612 : { VP9E_GET_ACTIVEMAP, ctrl_get_active_map },
1613 : { VP9E_GET_LEVEL, ctrl_get_level },
1614 :
1615 : { -1, NULL },
1616 : };
1617 :
1618 : static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
1619 : { 0,
1620 : {
1621 : // NOLINT
1622 : 0, // g_usage
1623 : 8, // g_threads
1624 : 0, // g_profile
1625 :
1626 : 320, // g_width
1627 : 240, // g_height
1628 : VPX_BITS_8, // g_bit_depth
1629 : 8, // g_input_bit_depth
1630 :
1631 : { 1, 30 }, // g_timebase
1632 :
1633 : 0, // g_error_resilient
1634 :
1635 : VPX_RC_ONE_PASS, // g_pass
1636 :
1637 : 25, // g_lag_in_frames
1638 :
1639 : 0, // rc_dropframe_thresh
1640 : 0, // rc_resize_allowed
1641 : 0, // rc_scaled_width
1642 : 0, // rc_scaled_height
1643 : 60, // rc_resize_down_thresold
1644 : 30, // rc_resize_up_thresold
1645 :
1646 : VPX_VBR, // rc_end_usage
1647 : { NULL, 0 }, // rc_twopass_stats_in
1648 : { NULL, 0 }, // rc_firstpass_mb_stats_in
1649 : 256, // rc_target_bandwidth
1650 : 0, // rc_min_quantizer
1651 : 63, // rc_max_quantizer
1652 : 25, // rc_undershoot_pct
1653 : 25, // rc_overshoot_pct
1654 :
1655 : 6000, // rc_max_buffer_size
1656 : 4000, // rc_buffer_initial_size
1657 : 5000, // rc_buffer_optimal_size
1658 :
1659 : 50, // rc_two_pass_vbrbias
1660 : 0, // rc_two_pass_vbrmin_section
1661 : 2000, // rc_two_pass_vbrmax_section
1662 :
1663 : // keyframing settings (kf)
1664 : VPX_KF_AUTO, // g_kfmode
1665 : 0, // kf_min_dist
1666 : 128, // kf_max_dist
1667 :
1668 : VPX_SS_DEFAULT_LAYERS, // ss_number_layers
1669 : { 0 },
1670 : { 0 }, // ss_target_bitrate
1671 : 1, // ts_number_layers
1672 : { 0 }, // ts_target_bitrate
1673 : { 0 }, // ts_rate_decimator
1674 : 0, // ts_periodicity
1675 : { 0 }, // ts_layer_id
1676 : { 0 }, // layer_taget_bitrate
1677 : 0 // temporal_layering_mode
1678 : } },
1679 : };
1680 :
1681 : #ifndef VERSION_STRING
1682 : #define VERSION_STRING
1683 : #endif
1684 0 : CODEC_INTERFACE(vpx_codec_vp9_cx) = {
1685 : "WebM Project VP9 Encoder" VERSION_STRING,
1686 : VPX_CODEC_INTERNAL_ABI_VERSION,
1687 : #if CONFIG_VP9_HIGHBITDEPTH
1688 : VPX_CODEC_CAP_HIGHBITDEPTH |
1689 : #endif
1690 : VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR, // vpx_codec_caps_t
1691 : encoder_init, // vpx_codec_init_fn_t
1692 : encoder_destroy, // vpx_codec_destroy_fn_t
1693 : encoder_ctrl_maps, // vpx_codec_ctrl_fn_map_t
1694 : {
1695 : // NOLINT
1696 : NULL, // vpx_codec_peek_si_fn_t
1697 : NULL, // vpx_codec_get_si_fn_t
1698 : NULL, // vpx_codec_decode_fn_t
1699 : NULL, // vpx_codec_frame_get_fn_t
1700 : NULL // vpx_codec_set_fb_fn_t
1701 : },
1702 : {
1703 : // NOLINT
1704 : 1, // 1 cfg map
1705 : encoder_usage_cfg_map, // vpx_codec_enc_cfg_map_t
1706 : encoder_encode, // vpx_codec_encode_fn_t
1707 : encoder_get_cxdata, // vpx_codec_get_cx_data_fn_t
1708 : encoder_set_config, // vpx_codec_enc_config_set_fn_t
1709 : NULL, // vpx_codec_get_global_headers_fn_t
1710 : encoder_get_preview, // vpx_codec_get_preview_frame_fn_t
1711 : NULL // vpx_codec_enc_mr_get_mem_loc_fn_t
1712 : }
1713 : };
|