2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
14 #include "./vpx_config.h"
15 #include "vpx/vpx_encoder.h"
16 #include "vpx_ports/vpx_once.h"
17 #include "vpx/internal/vpx_codec_internal.h"
18 #include "./vpx_version.h"
19 #include "vp10/encoder/encoder.h"
20 #include "vpx/vp8cx.h"
21 #include "vp10/encoder/firstpass.h"
22 #include "vp10/vp10_iface_common.h"
24 struct vp10_extracfg
{
25 int cpu_used
; // available cpu percentage in 1/16
26 unsigned int enable_auto_alt_ref
;
27 unsigned int noise_sensitivity
;
28 unsigned int sharpness
;
29 unsigned int static_thresh
;
30 unsigned int tile_columns
;
31 unsigned int tile_rows
;
32 unsigned int arnr_max_frames
;
33 unsigned int arnr_strength
;
34 unsigned int min_gf_interval
;
35 unsigned int max_gf_interval
;
37 unsigned int cq_level
; // constrained quality level
38 unsigned int rc_max_intra_bitrate_pct
;
39 unsigned int rc_max_inter_bitrate_pct
;
40 unsigned int gf_cbr_boost_pct
;
41 unsigned int lossless
;
42 unsigned int frame_parallel_decoding_mode
;
44 unsigned int frame_periodic_boost
;
45 vpx_bit_depth_t bit_depth
;
46 vp9e_tune_content content
;
47 vpx_color_space_t color_space
;
53 static struct vp10_extracfg default_extra_cfg
= {
55 1, // enable_auto_alt_ref
56 0, // noise_sensitivity
63 0, // min_gf_interval; 0 -> default decision
64 0, // max_gf_interval; 0 -> default decision
65 VP8_TUNE_PSNR
, // tuning
67 0, // rc_max_intra_bitrate_pct
68 0, // rc_max_inter_bitrate_pct
69 0, // gf_cbr_boost_pct
71 1, // frame_parallel_decoding_mode
73 0, // frame_periodic_delta_q
74 VPX_BITS_8
, // Bit depth
75 VP9E_CONTENT_DEFAULT
, // content
76 VPX_CS_UNKNOWN
, // color space
82 struct vpx_codec_alg_priv
{
83 vpx_codec_priv_t base
;
84 vpx_codec_enc_cfg_t cfg
;
85 struct vp10_extracfg extra_cfg
;
86 VP10EncoderConfig oxcf
;
88 unsigned char *cx_data
;
90 unsigned char *pending_cx_data
;
91 size_t pending_cx_data_sz
;
92 int pending_frame_count
;
93 size_t pending_frame_sizes
[8];
94 #if !CONFIG_MISC_FIXES
95 size_t pending_frame_magnitude
;
97 vpx_image_t preview_img
;
98 vpx_enc_frame_flags_t next_frame_flags
;
99 vp8_postproc_cfg_t preview_ppcfg
;
100 vpx_codec_pkt_list_decl(256) pkt_list
;
101 unsigned int fixed_kf_cntr
;
102 vpx_codec_priv_output_cx_pkt_cb_pair_t output_cx_pkt_cb
;
103 // BufferPool that holds all reference frames.
104 BufferPool
*buffer_pool
;
107 static VP9_REFFRAME
ref_frame_to_vp10_reframe(vpx_ref_frame_type_t frame
) {
110 return VP9_LAST_FLAG
;
112 return VP9_GOLD_FLAG
;
116 assert(0 && "Invalid Reference Frame");
117 return VP9_LAST_FLAG
;
120 static vpx_codec_err_t
update_error_state(vpx_codec_alg_priv_t
*ctx
,
121 const struct vpx_internal_error_info
*error
) {
122 const vpx_codec_err_t res
= error
->error_code
;
124 if (res
!= VPX_CODEC_OK
)
125 ctx
->base
.err_detail
= error
->has_detail
? error
->detail
: NULL
;
132 #define ERROR(str) do {\
133 ctx->base.err_detail = str;\
134 return VPX_CODEC_INVALID_PARAM;\
137 #define RANGE_CHECK(p, memb, lo, hi) do {\
138 if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
139 ERROR(#memb " out of range ["#lo".."#hi"]");\
142 #define RANGE_CHECK_HI(p, memb, hi) do {\
143 if (!((p)->memb <= (hi))) \
144 ERROR(#memb " out of range [.."#hi"]");\
147 #define RANGE_CHECK_LO(p, memb, lo) do {\
148 if (!((p)->memb >= (lo))) \
149 ERROR(#memb " out of range ["#lo"..]");\
152 #define RANGE_CHECK_BOOL(p, memb) do {\
153 if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
156 static vpx_codec_err_t
validate_config(vpx_codec_alg_priv_t
*ctx
,
157 const vpx_codec_enc_cfg_t
*cfg
,
158 const struct vp10_extracfg
*extra_cfg
) {
159 RANGE_CHECK(cfg
, g_w
, 1, 65535); // 16 bits available
160 RANGE_CHECK(cfg
, g_h
, 1, 65535); // 16 bits available
161 RANGE_CHECK(cfg
, g_timebase
.den
, 1, 1000000000);
162 RANGE_CHECK(cfg
, g_timebase
.num
, 1, cfg
->g_timebase
.den
);
163 RANGE_CHECK_HI(cfg
, g_profile
, 3);
165 RANGE_CHECK_HI(cfg
, rc_max_quantizer
, 63);
166 RANGE_CHECK_HI(cfg
, rc_min_quantizer
, cfg
->rc_max_quantizer
);
167 RANGE_CHECK_BOOL(extra_cfg
, lossless
);
168 RANGE_CHECK(extra_cfg
, aq_mode
, 0, AQ_MODE_COUNT
- 1);
169 RANGE_CHECK(extra_cfg
, frame_periodic_boost
, 0, 1);
170 RANGE_CHECK_HI(cfg
, g_threads
, 64);
171 RANGE_CHECK_HI(cfg
, g_lag_in_frames
, MAX_LAG_BUFFERS
);
172 RANGE_CHECK(cfg
, rc_end_usage
, VPX_VBR
, VPX_Q
);
173 RANGE_CHECK_HI(cfg
, rc_undershoot_pct
, 100);
174 RANGE_CHECK_HI(cfg
, rc_overshoot_pct
, 100);
175 RANGE_CHECK_HI(cfg
, rc_2pass_vbr_bias_pct
, 100);
176 RANGE_CHECK(cfg
, kf_mode
, VPX_KF_DISABLED
, VPX_KF_AUTO
);
177 RANGE_CHECK_BOOL(cfg
, rc_resize_allowed
);
178 RANGE_CHECK_HI(cfg
, rc_dropframe_thresh
, 100);
179 RANGE_CHECK_HI(cfg
, rc_resize_up_thresh
, 100);
180 RANGE_CHECK_HI(cfg
, rc_resize_down_thresh
, 100);
181 RANGE_CHECK(cfg
, g_pass
, VPX_RC_ONE_PASS
, VPX_RC_LAST_PASS
);
182 RANGE_CHECK(extra_cfg
, min_gf_interval
, 0, (MAX_LAG_BUFFERS
- 1));
183 RANGE_CHECK(extra_cfg
, max_gf_interval
, 0, (MAX_LAG_BUFFERS
- 1));
184 if (extra_cfg
->max_gf_interval
> 0) {
185 RANGE_CHECK(extra_cfg
, max_gf_interval
, 2, (MAX_LAG_BUFFERS
- 1));
187 if (extra_cfg
->min_gf_interval
> 0 && extra_cfg
->max_gf_interval
> 0) {
188 RANGE_CHECK(extra_cfg
, max_gf_interval
, extra_cfg
->min_gf_interval
,
189 (MAX_LAG_BUFFERS
- 1));
192 if (cfg
->rc_resize_allowed
== 1) {
193 RANGE_CHECK(cfg
, rc_scaled_width
, 0, cfg
->g_w
);
194 RANGE_CHECK(cfg
, rc_scaled_height
, 0, cfg
->g_h
);
197 // Spatial/temporal scalability are not yet supported in VP10.
198 // Only accept the default value for range checking.
199 RANGE_CHECK(cfg
, ss_number_layers
, 1, 1);
200 RANGE_CHECK(cfg
, ts_number_layers
, 1, 1);
201 // VP9 does not support a lower bound on the keyframe interval in
202 // automatic keyframe placement mode.
203 if (cfg
->kf_mode
!= VPX_KF_DISABLED
&&
204 cfg
->kf_min_dist
!= cfg
->kf_max_dist
&&
205 cfg
->kf_min_dist
> 0)
206 ERROR("kf_min_dist not supported in auto mode, use 0 "
207 "or kf_max_dist instead.");
209 RANGE_CHECK(extra_cfg
, enable_auto_alt_ref
, 0, 2);
210 RANGE_CHECK(extra_cfg
, cpu_used
, -8, 8);
211 RANGE_CHECK_HI(extra_cfg
, noise_sensitivity
, 6);
212 RANGE_CHECK(extra_cfg
, tile_columns
, 0, 6);
213 RANGE_CHECK(extra_cfg
, tile_rows
, 0, 2);
214 RANGE_CHECK_HI(extra_cfg
, sharpness
, 7);
215 RANGE_CHECK(extra_cfg
, arnr_max_frames
, 0, 15);
216 RANGE_CHECK_HI(extra_cfg
, arnr_strength
, 6);
217 RANGE_CHECK(extra_cfg
, cq_level
, 0, 63);
218 RANGE_CHECK(cfg
, g_bit_depth
, VPX_BITS_8
, VPX_BITS_12
);
219 RANGE_CHECK(cfg
, g_input_bit_depth
, 8, 12);
220 RANGE_CHECK(extra_cfg
, content
,
221 VP9E_CONTENT_DEFAULT
, VP9E_CONTENT_INVALID
- 1);
223 // TODO(yaowu): remove this when ssim tuning is implemented for vp9
224 if (extra_cfg
->tuning
== VP8_TUNE_SSIM
)
225 ERROR("Option --tune=ssim is not currently supported in VP9.");
227 if (cfg
->g_pass
== VPX_RC_LAST_PASS
) {
228 const size_t packet_sz
= sizeof(FIRSTPASS_STATS
);
229 const int n_packets
= (int)(cfg
->rc_twopass_stats_in
.sz
/ packet_sz
);
230 const FIRSTPASS_STATS
*stats
;
232 if (cfg
->rc_twopass_stats_in
.buf
== NULL
)
233 ERROR("rc_twopass_stats_in.buf not set.");
235 if (cfg
->rc_twopass_stats_in
.sz
% packet_sz
)
236 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
238 if (cfg
->rc_twopass_stats_in
.sz
< 2 * packet_sz
)
239 ERROR("rc_twopass_stats_in requires at least two packets.");
242 (const FIRSTPASS_STATS
*)cfg
->rc_twopass_stats_in
.buf
+ n_packets
- 1;
244 if ((int)(stats
->count
+ 0.5) != n_packets
- 1)
245 ERROR("rc_twopass_stats_in missing EOS stats packet");
248 #if !CONFIG_VP9_HIGHBITDEPTH
249 if (cfg
->g_profile
> (unsigned int)PROFILE_1
) {
250 ERROR("Profile > 1 not supported in this build configuration");
253 if (cfg
->g_profile
<= (unsigned int)PROFILE_1
&&
254 cfg
->g_bit_depth
> VPX_BITS_8
) {
255 ERROR("Codec high bit-depth not supported in profile < 2");
257 if (cfg
->g_profile
<= (unsigned int)PROFILE_1
&&
258 cfg
->g_input_bit_depth
> 8) {
259 ERROR("Source high bit-depth not supported in profile < 2");
261 if (cfg
->g_profile
> (unsigned int)PROFILE_1
&&
262 cfg
->g_bit_depth
== VPX_BITS_8
) {
263 ERROR("Codec bit-depth 8 not supported in profile > 1");
265 RANGE_CHECK(extra_cfg
, color_space
, VPX_CS_UNKNOWN
, VPX_CS_SRGB
);
266 RANGE_CHECK(extra_cfg
, color_range
, 0, 1);
270 static vpx_codec_err_t
validate_img(vpx_codec_alg_priv_t
*ctx
,
271 const vpx_image_t
*img
) {
273 case VPX_IMG_FMT_YV12
:
274 case VPX_IMG_FMT_I420
:
275 case VPX_IMG_FMT_I42016
:
277 case VPX_IMG_FMT_I422
:
278 case VPX_IMG_FMT_I444
:
279 case VPX_IMG_FMT_I440
:
280 if (ctx
->cfg
.g_profile
!= (unsigned int)PROFILE_1
) {
281 ERROR("Invalid image format. I422, I444, I440 images are "
282 "not supported in profile.");
285 case VPX_IMG_FMT_I42216
:
286 case VPX_IMG_FMT_I44416
:
287 case VPX_IMG_FMT_I44016
:
288 if (ctx
->cfg
.g_profile
!= (unsigned int)PROFILE_1
&&
289 ctx
->cfg
.g_profile
!= (unsigned int)PROFILE_3
) {
290 ERROR("Invalid image format. 16-bit I422, I444, I440 images are "
291 "not supported in profile.");
295 ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
300 if (img
->d_w
!= ctx
->cfg
.g_w
|| img
->d_h
!= ctx
->cfg
.g_h
)
301 ERROR("Image size must match encoder init configuration size");
306 static int get_image_bps(const vpx_image_t
*img
) {
308 case VPX_IMG_FMT_YV12
:
309 case VPX_IMG_FMT_I420
: return 12;
310 case VPX_IMG_FMT_I422
: return 16;
311 case VPX_IMG_FMT_I444
: return 24;
312 case VPX_IMG_FMT_I440
: return 16;
313 case VPX_IMG_FMT_I42016
: return 24;
314 case VPX_IMG_FMT_I42216
: return 32;
315 case VPX_IMG_FMT_I44416
: return 48;
316 case VPX_IMG_FMT_I44016
: return 32;
317 default: assert(0 && "Invalid image format"); break;
322 static vpx_codec_err_t
set_encoder_config(
323 VP10EncoderConfig
*oxcf
,
324 const vpx_codec_enc_cfg_t
*cfg
,
325 const struct vp10_extracfg
*extra_cfg
) {
326 const int is_vbr
= cfg
->rc_end_usage
== VPX_VBR
;
327 oxcf
->profile
= cfg
->g_profile
;
328 oxcf
->max_threads
= (int)cfg
->g_threads
;
329 oxcf
->width
= cfg
->g_w
;
330 oxcf
->height
= cfg
->g_h
;
331 oxcf
->bit_depth
= cfg
->g_bit_depth
;
332 oxcf
->input_bit_depth
= cfg
->g_input_bit_depth
;
333 // guess a frame rate if out of whack, use 30
334 oxcf
->init_framerate
= (double)cfg
->g_timebase
.den
/ cfg
->g_timebase
.num
;
335 if (oxcf
->init_framerate
> 180)
336 oxcf
->init_framerate
= 30;
340 switch (cfg
->g_pass
) {
341 case VPX_RC_ONE_PASS
:
344 case VPX_RC_FIRST_PASS
:
347 case VPX_RC_LAST_PASS
:
352 oxcf
->lag_in_frames
= cfg
->g_pass
== VPX_RC_FIRST_PASS
? 0
353 : cfg
->g_lag_in_frames
;
354 oxcf
->rc_mode
= cfg
->rc_end_usage
;
356 // Convert target bandwidth from Kbit/s to Bit/s
357 oxcf
->target_bandwidth
= 1000 * cfg
->rc_target_bitrate
;
358 oxcf
->rc_max_intra_bitrate_pct
= extra_cfg
->rc_max_intra_bitrate_pct
;
359 oxcf
->rc_max_inter_bitrate_pct
= extra_cfg
->rc_max_inter_bitrate_pct
;
360 oxcf
->gf_cbr_boost_pct
= extra_cfg
->gf_cbr_boost_pct
;
362 oxcf
->best_allowed_q
=
363 extra_cfg
->lossless
? 0 : vp10_quantizer_to_qindex(cfg
->rc_min_quantizer
);
364 oxcf
->worst_allowed_q
=
365 extra_cfg
->lossless
? 0 : vp10_quantizer_to_qindex(cfg
->rc_max_quantizer
);
366 oxcf
->cq_level
= vp10_quantizer_to_qindex(extra_cfg
->cq_level
);
369 oxcf
->under_shoot_pct
= cfg
->rc_undershoot_pct
;
370 oxcf
->over_shoot_pct
= cfg
->rc_overshoot_pct
;
372 oxcf
->scaled_frame_width
= cfg
->rc_scaled_width
;
373 oxcf
->scaled_frame_height
= cfg
->rc_scaled_height
;
374 if (cfg
->rc_resize_allowed
== 1) {
376 (oxcf
->scaled_frame_width
== 0 || oxcf
->scaled_frame_height
== 0) ?
377 RESIZE_DYNAMIC
: RESIZE_FIXED
;
379 oxcf
->resize_mode
= RESIZE_NONE
;
382 oxcf
->maximum_buffer_size_ms
= is_vbr
? 240000 : cfg
->rc_buf_sz
;
383 oxcf
->starting_buffer_level_ms
= is_vbr
? 60000 : cfg
->rc_buf_initial_sz
;
384 oxcf
->optimal_buffer_level_ms
= is_vbr
? 60000 : cfg
->rc_buf_optimal_sz
;
386 oxcf
->drop_frames_water_mark
= cfg
->rc_dropframe_thresh
;
388 oxcf
->two_pass_vbrbias
= cfg
->rc_2pass_vbr_bias_pct
;
389 oxcf
->two_pass_vbrmin_section
= cfg
->rc_2pass_vbr_minsection_pct
;
390 oxcf
->two_pass_vbrmax_section
= cfg
->rc_2pass_vbr_maxsection_pct
;
392 oxcf
->auto_key
= cfg
->kf_mode
== VPX_KF_AUTO
&&
393 cfg
->kf_min_dist
!= cfg
->kf_max_dist
;
395 oxcf
->key_freq
= cfg
->kf_max_dist
;
397 oxcf
->speed
= abs(extra_cfg
->cpu_used
);
398 oxcf
->encode_breakout
= extra_cfg
->static_thresh
;
399 oxcf
->enable_auto_arf
= extra_cfg
->enable_auto_alt_ref
;
400 oxcf
->noise_sensitivity
= extra_cfg
->noise_sensitivity
;
401 oxcf
->sharpness
= extra_cfg
->sharpness
;
403 oxcf
->two_pass_stats_in
= cfg
->rc_twopass_stats_in
;
405 #if CONFIG_FP_MB_STATS
406 oxcf
->firstpass_mb_stats_in
= cfg
->rc_firstpass_mb_stats_in
;
409 oxcf
->color_space
= extra_cfg
->color_space
;
410 oxcf
->color_range
= extra_cfg
->color_range
;
411 oxcf
->render_width
= extra_cfg
->render_width
;
412 oxcf
->render_height
= extra_cfg
->render_height
;
413 oxcf
->arnr_max_frames
= extra_cfg
->arnr_max_frames
;
414 oxcf
->arnr_strength
= extra_cfg
->arnr_strength
;
415 oxcf
->min_gf_interval
= extra_cfg
->min_gf_interval
;
416 oxcf
->max_gf_interval
= extra_cfg
->max_gf_interval
;
418 oxcf
->tuning
= extra_cfg
->tuning
;
419 oxcf
->content
= extra_cfg
->content
;
421 oxcf
->tile_columns
= extra_cfg
->tile_columns
;
422 oxcf
->tile_rows
= extra_cfg
->tile_rows
;
424 oxcf
->error_resilient_mode
= cfg
->g_error_resilient
;
425 oxcf
->frame_parallel_decoding_mode
= extra_cfg
->frame_parallel_decoding_mode
;
427 oxcf
->aq_mode
= extra_cfg
->aq_mode
;
429 oxcf
->frame_periodic_boost
= extra_cfg
->frame_periodic_boost
;
432 printf("Current VP9 Settings: \n");
433 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
434 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
435 printf("sharpness: %d\n", oxcf->sharpness);
436 printf("cpu_used: %d\n", oxcf->cpu_used);
437 printf("Mode: %d\n", oxcf->mode);
438 printf("auto_key: %d\n", oxcf->auto_key);
439 printf("key_freq: %d\n", oxcf->key_freq);
440 printf("end_usage: %d\n", oxcf->end_usage);
441 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
442 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
443 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
444 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
445 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
446 printf("fixed_q: %d\n", oxcf->fixed_q);
447 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
448 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
449 printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
450 printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width);
451 printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height);
452 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
453 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
454 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
455 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
456 printf("enable_auto_arf: %d\n", oxcf->enable_auto_arf);
457 printf("Version: %d\n", oxcf->Version);
458 printf("encode_breakout: %d\n", oxcf->encode_breakout);
459 printf("error resilient: %d\n", oxcf->error_resilient_mode);
460 printf("frame parallel detokenization: %d\n",
461 oxcf->frame_parallel_decoding_mode);
466 static vpx_codec_err_t
encoder_set_config(vpx_codec_alg_priv_t
*ctx
,
467 const vpx_codec_enc_cfg_t
*cfg
) {
471 if (cfg
->g_w
!= ctx
->cfg
.g_w
|| cfg
->g_h
!= ctx
->cfg
.g_h
) {
472 if (cfg
->g_lag_in_frames
> 1 || cfg
->g_pass
!= VPX_RC_ONE_PASS
)
473 ERROR("Cannot change width or height after initialization");
474 if (!valid_ref_frame_size(ctx
->cfg
.g_w
, ctx
->cfg
.g_h
, cfg
->g_w
, cfg
->g_h
) ||
475 (ctx
->cpi
->initial_width
&& (int)cfg
->g_w
> ctx
->cpi
->initial_width
) ||
476 (ctx
->cpi
->initial_height
&& (int)cfg
->g_h
> ctx
->cpi
->initial_height
))
480 // Prevent increasing lag_in_frames. This check is stricter than it needs
481 // to be -- the limit is not increasing past the first lag_in_frames
482 // value, but we don't track the initial config, only the last successful
484 if (cfg
->g_lag_in_frames
> ctx
->cfg
.g_lag_in_frames
)
485 ERROR("Cannot increase lag_in_frames");
487 res
= validate_config(ctx
, cfg
, &ctx
->extra_cfg
);
489 if (res
== VPX_CODEC_OK
) {
491 set_encoder_config(&ctx
->oxcf
, &ctx
->cfg
, &ctx
->extra_cfg
);
492 // On profile change, request a key frame
493 force_key
|= ctx
->cpi
->common
.profile
!= ctx
->oxcf
.profile
;
494 vp10_change_config(ctx
->cpi
, &ctx
->oxcf
);
498 ctx
->next_frame_flags
|= VPX_EFLAG_FORCE_KF
;
503 static vpx_codec_err_t
ctrl_get_quantizer(vpx_codec_alg_priv_t
*ctx
,
505 int *const arg
= va_arg(args
, int *);
507 return VPX_CODEC_INVALID_PARAM
;
508 *arg
= vp10_get_quantizer(ctx
->cpi
);
512 static vpx_codec_err_t
ctrl_get_quantizer64(vpx_codec_alg_priv_t
*ctx
,
514 int *const arg
= va_arg(args
, int *);
516 return VPX_CODEC_INVALID_PARAM
;
517 *arg
= vp10_qindex_to_quantizer(vp10_get_quantizer(ctx
->cpi
));
521 static vpx_codec_err_t
update_extra_cfg(vpx_codec_alg_priv_t
*ctx
,
522 const struct vp10_extracfg
*extra_cfg
) {
523 const vpx_codec_err_t res
= validate_config(ctx
, &ctx
->cfg
, extra_cfg
);
524 if (res
== VPX_CODEC_OK
) {
525 ctx
->extra_cfg
= *extra_cfg
;
526 set_encoder_config(&ctx
->oxcf
, &ctx
->cfg
, &ctx
->extra_cfg
);
527 vp10_change_config(ctx
->cpi
, &ctx
->oxcf
);
532 static vpx_codec_err_t
ctrl_set_cpuused(vpx_codec_alg_priv_t
*ctx
,
534 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
535 extra_cfg
.cpu_used
= CAST(VP8E_SET_CPUUSED
, args
);
536 return update_extra_cfg(ctx
, &extra_cfg
);
539 static vpx_codec_err_t
ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t
*ctx
,
541 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
542 extra_cfg
.enable_auto_alt_ref
= CAST(VP8E_SET_ENABLEAUTOALTREF
, args
);
543 return update_extra_cfg(ctx
, &extra_cfg
);
546 static vpx_codec_err_t
ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t
*ctx
,
548 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
549 extra_cfg
.noise_sensitivity
= CAST(VP9E_SET_NOISE_SENSITIVITY
, args
);
550 return update_extra_cfg(ctx
, &extra_cfg
);
553 static vpx_codec_err_t
ctrl_set_sharpness(vpx_codec_alg_priv_t
*ctx
,
555 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
556 extra_cfg
.sharpness
= CAST(VP8E_SET_SHARPNESS
, args
);
557 return update_extra_cfg(ctx
, &extra_cfg
);
560 static vpx_codec_err_t
ctrl_set_static_thresh(vpx_codec_alg_priv_t
*ctx
,
562 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
563 extra_cfg
.static_thresh
= CAST(VP8E_SET_STATIC_THRESHOLD
, args
);
564 return update_extra_cfg(ctx
, &extra_cfg
);
567 static vpx_codec_err_t
ctrl_set_tile_columns(vpx_codec_alg_priv_t
*ctx
,
569 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
570 extra_cfg
.tile_columns
= CAST(VP9E_SET_TILE_COLUMNS
, args
);
571 return update_extra_cfg(ctx
, &extra_cfg
);
574 static vpx_codec_err_t
ctrl_set_tile_rows(vpx_codec_alg_priv_t
*ctx
,
576 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
577 extra_cfg
.tile_rows
= CAST(VP9E_SET_TILE_ROWS
, args
);
578 return update_extra_cfg(ctx
, &extra_cfg
);
581 static vpx_codec_err_t
ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t
*ctx
,
583 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
584 extra_cfg
.arnr_max_frames
= CAST(VP8E_SET_ARNR_MAXFRAMES
, args
);
585 return update_extra_cfg(ctx
, &extra_cfg
);
588 static vpx_codec_err_t
ctrl_set_arnr_strength(vpx_codec_alg_priv_t
*ctx
,
590 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
591 extra_cfg
.arnr_strength
= CAST(VP8E_SET_ARNR_STRENGTH
, args
);
592 return update_extra_cfg(ctx
, &extra_cfg
);
595 static vpx_codec_err_t
ctrl_set_arnr_type(vpx_codec_alg_priv_t
*ctx
,
602 static vpx_codec_err_t
ctrl_set_tuning(vpx_codec_alg_priv_t
*ctx
,
604 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
605 extra_cfg
.tuning
= CAST(VP8E_SET_TUNING
, args
);
606 return update_extra_cfg(ctx
, &extra_cfg
);
609 static vpx_codec_err_t
ctrl_set_cq_level(vpx_codec_alg_priv_t
*ctx
,
611 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
612 extra_cfg
.cq_level
= CAST(VP8E_SET_CQ_LEVEL
, args
);
613 return update_extra_cfg(ctx
, &extra_cfg
);
616 static vpx_codec_err_t
ctrl_set_rc_max_intra_bitrate_pct(
617 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
618 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
619 extra_cfg
.rc_max_intra_bitrate_pct
=
620 CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT
, args
);
621 return update_extra_cfg(ctx
, &extra_cfg
);
624 static vpx_codec_err_t
ctrl_set_rc_max_inter_bitrate_pct(
625 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
626 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
627 extra_cfg
.rc_max_inter_bitrate_pct
=
628 CAST(VP8E_SET_MAX_INTER_BITRATE_PCT
, args
);
629 return update_extra_cfg(ctx
, &extra_cfg
);
632 static vpx_codec_err_t
ctrl_set_rc_gf_cbr_boost_pct(
633 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
634 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
635 extra_cfg
.gf_cbr_boost_pct
=
636 CAST(VP9E_SET_GF_CBR_BOOST_PCT
, args
);
637 return update_extra_cfg(ctx
, &extra_cfg
);
640 static vpx_codec_err_t
ctrl_set_lossless(vpx_codec_alg_priv_t
*ctx
,
642 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
643 extra_cfg
.lossless
= CAST(VP9E_SET_LOSSLESS
, args
);
644 return update_extra_cfg(ctx
, &extra_cfg
);
647 static vpx_codec_err_t
ctrl_set_frame_parallel_decoding_mode(
648 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
649 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
650 extra_cfg
.frame_parallel_decoding_mode
=
651 CAST(VP9E_SET_FRAME_PARALLEL_DECODING
, args
);
652 return update_extra_cfg(ctx
, &extra_cfg
);
655 static vpx_codec_err_t
ctrl_set_aq_mode(vpx_codec_alg_priv_t
*ctx
,
657 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
658 extra_cfg
.aq_mode
= CAST(VP9E_SET_AQ_MODE
, args
);
659 return update_extra_cfg(ctx
, &extra_cfg
);
662 static vpx_codec_err_t
ctrl_set_min_gf_interval(vpx_codec_alg_priv_t
*ctx
,
664 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
665 extra_cfg
.min_gf_interval
= CAST(VP9E_SET_MIN_GF_INTERVAL
, args
);
666 return update_extra_cfg(ctx
, &extra_cfg
);
669 static vpx_codec_err_t
ctrl_set_max_gf_interval(vpx_codec_alg_priv_t
*ctx
,
671 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
672 extra_cfg
.max_gf_interval
= CAST(VP9E_SET_MAX_GF_INTERVAL
, args
);
673 return update_extra_cfg(ctx
, &extra_cfg
);
676 static vpx_codec_err_t
ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t
*ctx
,
678 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
679 extra_cfg
.frame_periodic_boost
= CAST(VP9E_SET_FRAME_PERIODIC_BOOST
, args
);
680 return update_extra_cfg(ctx
, &extra_cfg
);
683 static vpx_codec_err_t
encoder_init(vpx_codec_ctx_t
*ctx
,
684 vpx_codec_priv_enc_mr_cfg_t
*data
) {
685 vpx_codec_err_t res
= VPX_CODEC_OK
;
688 if (ctx
->priv
== NULL
) {
689 vpx_codec_alg_priv_t
*const priv
= vpx_calloc(1, sizeof(*priv
));
691 return VPX_CODEC_MEM_ERROR
;
693 ctx
->priv
= (vpx_codec_priv_t
*)priv
;
694 ctx
->priv
->init_flags
= ctx
->init_flags
;
695 ctx
->priv
->enc
.total_encoders
= 1;
697 (BufferPool
*)vpx_calloc(1, sizeof(BufferPool
));
698 if (priv
->buffer_pool
== NULL
)
699 return VPX_CODEC_MEM_ERROR
;
701 #if CONFIG_MULTITHREAD
702 if (pthread_mutex_init(&priv
->buffer_pool
->pool_mutex
, NULL
)) {
703 return VPX_CODEC_MEM_ERROR
;
707 if (ctx
->config
.enc
) {
708 // Update the reference to the config structure to an internal copy.
709 priv
->cfg
= *ctx
->config
.enc
;
710 ctx
->config
.enc
= &priv
->cfg
;
713 priv
->extra_cfg
= default_extra_cfg
;
714 once(vp10_initialize_enc
);
716 res
= validate_config(priv
, &priv
->cfg
, &priv
->extra_cfg
);
718 if (res
== VPX_CODEC_OK
) {
719 set_encoder_config(&priv
->oxcf
, &priv
->cfg
, &priv
->extra_cfg
);
720 #if CONFIG_VP9_HIGHBITDEPTH
721 priv
->oxcf
.use_highbitdepth
=
722 (ctx
->init_flags
& VPX_CODEC_USE_HIGHBITDEPTH
) ? 1 : 0;
724 priv
->cpi
= vp10_create_compressor(&priv
->oxcf
, priv
->buffer_pool
);
725 if (priv
->cpi
== NULL
)
726 res
= VPX_CODEC_MEM_ERROR
;
728 priv
->cpi
->output_pkt_list
= &priv
->pkt_list
.head
;
735 static vpx_codec_err_t
encoder_destroy(vpx_codec_alg_priv_t
*ctx
) {
737 vp10_remove_compressor(ctx
->cpi
);
738 #if CONFIG_MULTITHREAD
739 pthread_mutex_destroy(&ctx
->buffer_pool
->pool_mutex
);
741 vpx_free(ctx
->buffer_pool
);
746 static void pick_quickcompress_mode(vpx_codec_alg_priv_t
*ctx
,
747 unsigned long duration
,
748 unsigned long deadline
) {
749 MODE new_mode
= BEST
;
751 switch (ctx
->cfg
.g_pass
) {
752 case VPX_RC_ONE_PASS
:
754 const vpx_codec_enc_cfg_t
*const cfg
= &ctx
->cfg
;
756 // Convert duration parameter from stream timebase to microseconds.
757 const uint64_t duration_us
= (uint64_t)duration
* 1000000 *
758 (uint64_t)cfg
->g_timebase
.num
/(uint64_t)cfg
->g_timebase
.den
;
760 // If the deadline is more that the duration this frame is to be shown,
761 // use good quality mode. Otherwise use realtime mode.
762 new_mode
= (deadline
> duration_us
) ? GOOD
: REALTIME
;
767 case VPX_RC_FIRST_PASS
:
769 case VPX_RC_LAST_PASS
:
770 new_mode
= deadline
> 0 ? GOOD
: BEST
;
774 if (ctx
->oxcf
.mode
!= new_mode
) {
775 ctx
->oxcf
.mode
= new_mode
;
776 vp10_change_config(ctx
->cpi
, &ctx
->oxcf
);
780 // Turn on to test if supplemental superframe data breaks decoding
781 // #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
782 static int write_superframe_index(vpx_codec_alg_priv_t
*ctx
) {
783 uint8_t marker
= 0xc0;
786 #if CONFIG_MISC_FIXES
788 size_t max_frame_sz
= 0;
791 assert(ctx
->pending_frame_count
);
792 assert(ctx
->pending_frame_count
<= 8);
794 // Add the number of frames to the marker byte
795 marker
|= ctx
->pending_frame_count
- 1;
796 #if CONFIG_MISC_FIXES
797 for (i
= 0; i
< ctx
->pending_frame_count
- 1; i
++) {
798 const size_t frame_sz
= (unsigned int) ctx
->pending_frame_sizes
[i
] - 1;
799 max_frame_sz
= frame_sz
> max_frame_sz
? frame_sz
: max_frame_sz
;
803 // Choose the magnitude
804 for (mag
= 0, mask
= 0xff; mag
< 4; mag
++) {
805 #if CONFIG_MISC_FIXES
806 if (max_frame_sz
<= mask
)
809 if (ctx
->pending_frame_magnitude
< mask
)
818 index_sz
= 2 + (mag
+ 1) * (ctx
->pending_frame_count
- CONFIG_MISC_FIXES
);
819 if (ctx
->pending_cx_data_sz
+ index_sz
< ctx
->cx_data_sz
) {
820 uint8_t *x
= ctx
->pending_cx_data
+ ctx
->pending_cx_data_sz
;
822 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
823 uint8_t marker_test
= 0xc0;
824 int mag_test
= 2; // 1 - 4
825 int frames_test
= 4; // 1 - 8
826 int index_sz_test
= 2 + mag_test
* frames_test
;
827 marker_test
|= frames_test
- 1;
828 marker_test
|= (mag_test
- 1) << 3;
830 for (i
= 0; i
< mag_test
* frames_test
; ++i
)
831 *x
++ = 0; // fill up with arbitrary data
833 ctx
->pending_cx_data_sz
+= index_sz_test
;
834 printf("Added supplemental superframe data\n");
838 for (i
= 0; i
< ctx
->pending_frame_count
- CONFIG_MISC_FIXES
; i
++) {
839 unsigned int this_sz
;
841 assert(ctx
->pending_frame_sizes
[i
] > 0);
842 this_sz
= (unsigned int)ctx
->pending_frame_sizes
[i
] - CONFIG_MISC_FIXES
;
843 for (j
= 0; j
<= mag
; j
++) {
844 *x
++ = this_sz
& 0xff;
849 ctx
->pending_cx_data_sz
+= index_sz
;
850 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
851 index_sz
+= index_sz_test
;
857 // vp9 uses 10,000,000 ticks/second as time stamp
858 #define TICKS_PER_SEC 10000000LL
860 static int64_t timebase_units_to_ticks(const vpx_rational_t
*timebase
,
862 return n
* TICKS_PER_SEC
* timebase
->num
/ timebase
->den
;
865 static int64_t ticks_to_timebase_units(const vpx_rational_t
*timebase
,
867 const int64_t round
= TICKS_PER_SEC
* timebase
->num
/ 2 - 1;
868 return (n
* timebase
->den
+ round
) / timebase
->num
/ TICKS_PER_SEC
;
871 static vpx_codec_frame_flags_t
get_frame_pkt_flags(const VP10_COMP
*cpi
,
872 unsigned int lib_flags
) {
873 vpx_codec_frame_flags_t flags
= lib_flags
<< 16;
875 if (lib_flags
& FRAMEFLAGS_KEY
)
876 flags
|= VPX_FRAME_IS_KEY
;
879 flags
|= VPX_FRAME_IS_DROPPABLE
;
884 static vpx_codec_err_t
encoder_encode(vpx_codec_alg_priv_t
*ctx
,
885 const vpx_image_t
*img
,
887 unsigned long duration
,
888 vpx_enc_frame_flags_t flags
,
889 unsigned long deadline
) {
890 vpx_codec_err_t res
= VPX_CODEC_OK
;
891 VP10_COMP
*const cpi
= ctx
->cpi
;
892 const vpx_rational_t
*const timebase
= &ctx
->cfg
.g_timebase
;
896 res
= validate_img(ctx
, img
);
897 // TODO(jzern) the checks related to cpi's validity should be treated as a
898 // failure condition, encoder setup is done fully in init() currently.
899 if (res
== VPX_CODEC_OK
&& cpi
!= NULL
) {
900 // There's no codec control for multiple alt-refs so check the encoder
901 // instance for its status to determine the compressed data size.
902 data_sz
= ctx
->cfg
.g_w
* ctx
->cfg
.g_h
* get_image_bps(img
) / 8 *
903 (cpi
->multi_arf_allowed
? 8 : 2);
906 if (ctx
->cx_data
== NULL
|| ctx
->cx_data_sz
< data_sz
) {
907 ctx
->cx_data_sz
= data_sz
;
909 ctx
->cx_data
= (unsigned char*)malloc(ctx
->cx_data_sz
);
910 if (ctx
->cx_data
== NULL
) {
911 return VPX_CODEC_MEM_ERROR
;
917 pick_quickcompress_mode(ctx
, duration
, deadline
);
918 vpx_codec_pkt_list_init(&ctx
->pkt_list
);
921 if (((flags
& VP8_EFLAG_NO_UPD_GF
) && (flags
& VP8_EFLAG_FORCE_GF
)) ||
922 ((flags
& VP8_EFLAG_NO_UPD_ARF
) && (flags
& VP8_EFLAG_FORCE_ARF
))) {
923 ctx
->base
.err_detail
= "Conflicting flags.";
924 return VPX_CODEC_INVALID_PARAM
;
927 vp10_apply_encoding_flags(cpi
, flags
);
929 // Handle fixed keyframe intervals
930 if (ctx
->cfg
.kf_mode
== VPX_KF_AUTO
&&
931 ctx
->cfg
.kf_min_dist
== ctx
->cfg
.kf_max_dist
) {
932 if (++ctx
->fixed_kf_cntr
> ctx
->cfg
.kf_min_dist
) {
933 flags
|= VPX_EFLAG_FORCE_KF
;
934 ctx
->fixed_kf_cntr
= 1;
938 // Initialize the encoder instance on the first frame.
939 if (res
== VPX_CODEC_OK
&& cpi
!= NULL
) {
940 unsigned int lib_flags
= 0;
941 YV12_BUFFER_CONFIG sd
;
942 int64_t dst_time_stamp
= timebase_units_to_ticks(timebase
, pts
);
943 int64_t dst_end_time_stamp
=
944 timebase_units_to_ticks(timebase
, pts
+ duration
);
945 size_t size
, cx_data_sz
;
946 unsigned char *cx_data
;
948 // Set up internal flags
949 if (ctx
->base
.init_flags
& VPX_CODEC_USE_PSNR
)
950 cpi
->b_calculate_psnr
= 1;
953 res
= image2yuvconfig(img
, &sd
);
955 // Store the original flags in to the frame buffer. Will extract the
956 // key frame flag when we actually encode this frame.
957 if (vp10_receive_raw_frame(cpi
, flags
| ctx
->next_frame_flags
,
958 &sd
, dst_time_stamp
, dst_end_time_stamp
)) {
959 res
= update_error_state(ctx
, &cpi
->common
.error
);
961 ctx
->next_frame_flags
= 0;
964 cx_data
= ctx
->cx_data
;
965 cx_data_sz
= ctx
->cx_data_sz
;
967 /* Any pending invisible frames? */
968 if (ctx
->pending_cx_data
) {
969 memmove(cx_data
, ctx
->pending_cx_data
, ctx
->pending_cx_data_sz
);
970 ctx
->pending_cx_data
= cx_data
;
971 cx_data
+= ctx
->pending_cx_data_sz
;
972 cx_data_sz
-= ctx
->pending_cx_data_sz
;
974 /* TODO: this is a minimal check, the underlying codec doesn't respect
975 * the buffer size anyway.
977 if (cx_data_sz
< ctx
->cx_data_sz
/ 2) {
978 ctx
->base
.err_detail
= "Compressed data buffer too small";
979 return VPX_CODEC_ERROR
;
983 while (cx_data_sz
>= ctx
->cx_data_sz
/ 2 &&
984 -1 != vp10_get_compressed_data(cpi
, &lib_flags
, &size
,
985 cx_data
, &dst_time_stamp
,
986 &dst_end_time_stamp
, !img
)) {
988 vpx_codec_cx_pkt_t pkt
;
990 // Pack invisible frames with the next visible frame
991 if (!cpi
->common
.show_frame
) {
992 if (ctx
->pending_cx_data
== 0)
993 ctx
->pending_cx_data
= cx_data
;
994 ctx
->pending_cx_data_sz
+= size
;
995 ctx
->pending_frame_sizes
[ctx
->pending_frame_count
++] = size
;
996 #if !CONFIG_MISC_FIXES
997 ctx
->pending_frame_magnitude
|= size
;
1002 if (ctx
->output_cx_pkt_cb
.output_cx_pkt
) {
1003 pkt
.kind
= VPX_CODEC_CX_FRAME_PKT
;
1004 pkt
.data
.frame
.pts
= ticks_to_timebase_units(timebase
,
1006 pkt
.data
.frame
.duration
=
1007 (unsigned long)ticks_to_timebase_units(timebase
,
1008 dst_end_time_stamp
- dst_time_stamp
);
1009 pkt
.data
.frame
.flags
= get_frame_pkt_flags(cpi
, lib_flags
);
1010 pkt
.data
.frame
.buf
= ctx
->pending_cx_data
;
1011 pkt
.data
.frame
.sz
= size
;
1012 ctx
->pending_cx_data
= NULL
;
1013 ctx
->pending_cx_data_sz
= 0;
1014 ctx
->pending_frame_count
= 0;
1015 #if !CONFIG_MISC_FIXES
1016 ctx
->pending_frame_magnitude
= 0;
1018 ctx
->output_cx_pkt_cb
.output_cx_pkt(
1019 &pkt
, ctx
->output_cx_pkt_cb
.user_priv
);
1024 // Add the frame packet to the list of returned packets.
1025 pkt
.kind
= VPX_CODEC_CX_FRAME_PKT
;
1026 pkt
.data
.frame
.pts
= ticks_to_timebase_units(timebase
, dst_time_stamp
);
1027 pkt
.data
.frame
.duration
=
1028 (unsigned long)ticks_to_timebase_units(timebase
,
1029 dst_end_time_stamp
- dst_time_stamp
);
1030 pkt
.data
.frame
.flags
= get_frame_pkt_flags(cpi
, lib_flags
);
1032 if (ctx
->pending_cx_data
) {
1033 ctx
->pending_frame_sizes
[ctx
->pending_frame_count
++] = size
;
1034 #if !CONFIG_MISC_FIXES
1035 ctx
->pending_frame_magnitude
|= size
;
1037 ctx
->pending_cx_data_sz
+= size
;
1038 // write the superframe only for the case when
1039 if (!ctx
->output_cx_pkt_cb
.output_cx_pkt
)
1040 size
+= write_superframe_index(ctx
);
1041 pkt
.data
.frame
.buf
= ctx
->pending_cx_data
;
1042 pkt
.data
.frame
.sz
= ctx
->pending_cx_data_sz
;
1043 ctx
->pending_cx_data
= NULL
;
1044 ctx
->pending_cx_data_sz
= 0;
1045 ctx
->pending_frame_count
= 0;
1046 #if !CONFIG_MISC_FIXES
1047 ctx
->pending_frame_magnitude
= 0;
1050 pkt
.data
.frame
.buf
= cx_data
;
1051 pkt
.data
.frame
.sz
= size
;
1053 pkt
.data
.frame
.partition_id
= -1;
1055 if(ctx
->output_cx_pkt_cb
.output_cx_pkt
)
1056 ctx
->output_cx_pkt_cb
.output_cx_pkt(&pkt
,
1057 ctx
->output_cx_pkt_cb
.user_priv
);
1059 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt
);
1070 static const vpx_codec_cx_pkt_t
*encoder_get_cxdata(vpx_codec_alg_priv_t
*ctx
,
1071 vpx_codec_iter_t
*iter
) {
1072 return vpx_codec_pkt_list_get(&ctx
->pkt_list
.head
, iter
);
1075 static vpx_codec_err_t
ctrl_set_reference(vpx_codec_alg_priv_t
*ctx
,
1077 vpx_ref_frame_t
*const frame
= va_arg(args
, vpx_ref_frame_t
*);
1079 if (frame
!= NULL
) {
1080 YV12_BUFFER_CONFIG sd
;
1082 image2yuvconfig(&frame
->img
, &sd
);
1083 vp10_set_reference_enc(ctx
->cpi
, ref_frame_to_vp10_reframe(frame
->frame_type
),
1085 return VPX_CODEC_OK
;
1087 return VPX_CODEC_INVALID_PARAM
;
1091 static vpx_codec_err_t
ctrl_copy_reference(vpx_codec_alg_priv_t
*ctx
,
1093 vpx_ref_frame_t
*const frame
= va_arg(args
, vpx_ref_frame_t
*);
1095 if (frame
!= NULL
) {
1096 YV12_BUFFER_CONFIG sd
;
1098 image2yuvconfig(&frame
->img
, &sd
);
1099 vp10_copy_reference_enc(ctx
->cpi
,
1100 ref_frame_to_vp10_reframe(frame
->frame_type
), &sd
);
1101 return VPX_CODEC_OK
;
1103 return VPX_CODEC_INVALID_PARAM
;
1107 static vpx_codec_err_t
ctrl_get_reference(vpx_codec_alg_priv_t
*ctx
,
1109 vp9_ref_frame_t
*const frame
= va_arg(args
, vp9_ref_frame_t
*);
1111 if (frame
!= NULL
) {
1112 YV12_BUFFER_CONFIG
*fb
= get_ref_frame(&ctx
->cpi
->common
, frame
->idx
);
1113 if (fb
== NULL
) return VPX_CODEC_ERROR
;
1115 yuvconfig2image(&frame
->img
, fb
, NULL
);
1116 return VPX_CODEC_OK
;
1118 return VPX_CODEC_INVALID_PARAM
;
1122 static vpx_codec_err_t
ctrl_set_previewpp(vpx_codec_alg_priv_t
*ctx
,
1124 #if CONFIG_VP9_POSTPROC
1125 vp8_postproc_cfg_t
*config
= va_arg(args
, vp8_postproc_cfg_t
*);
1126 if (config
!= NULL
) {
1127 ctx
->preview_ppcfg
= *config
;
1128 return VPX_CODEC_OK
;
1130 return VPX_CODEC_INVALID_PARAM
;
1135 return VPX_CODEC_INCAPABLE
;
1140 static vpx_image_t
*encoder_get_preview(vpx_codec_alg_priv_t
*ctx
) {
1141 YV12_BUFFER_CONFIG sd
;
1142 vp10_ppflags_t flags
;
1145 if (ctx
->preview_ppcfg
.post_proc_flag
) {
1146 flags
.post_proc_flag
= ctx
->preview_ppcfg
.post_proc_flag
;
1147 flags
.deblocking_level
= ctx
->preview_ppcfg
.deblocking_level
;
1148 flags
.noise_level
= ctx
->preview_ppcfg
.noise_level
;
1151 if (vp10_get_preview_raw_frame(ctx
->cpi
, &sd
, &flags
) == 0) {
1152 yuvconfig2image(&ctx
->preview_img
, &sd
, NULL
);
1153 return &ctx
->preview_img
;
1159 static vpx_codec_err_t
ctrl_set_roi_map(vpx_codec_alg_priv_t
*ctx
,
1164 // TODO(yaowu): Need to re-implement and test for VP9.
1165 return VPX_CODEC_INVALID_PARAM
;
1169 static vpx_codec_err_t
ctrl_set_active_map(vpx_codec_alg_priv_t
*ctx
,
1171 vpx_active_map_t
*const map
= va_arg(args
, vpx_active_map_t
*);
1174 if (!vp10_set_active_map(ctx
->cpi
, map
->active_map
,
1175 (int)map
->rows
, (int)map
->cols
))
1176 return VPX_CODEC_OK
;
1178 return VPX_CODEC_INVALID_PARAM
;
1180 return VPX_CODEC_INVALID_PARAM
;
1184 static vpx_codec_err_t
ctrl_get_active_map(vpx_codec_alg_priv_t
*ctx
,
1186 vpx_active_map_t
*const map
= va_arg(args
, vpx_active_map_t
*);
1189 if (!vp10_get_active_map(ctx
->cpi
, map
->active_map
,
1190 (int)map
->rows
, (int)map
->cols
))
1191 return VPX_CODEC_OK
;
1193 return VPX_CODEC_INVALID_PARAM
;
1195 return VPX_CODEC_INVALID_PARAM
;
1199 static vpx_codec_err_t
ctrl_set_scale_mode(vpx_codec_alg_priv_t
*ctx
,
1201 vpx_scaling_mode_t
*const mode
= va_arg(args
, vpx_scaling_mode_t
*);
1204 const int res
= vp10_set_internal_size(ctx
->cpi
,
1205 (VPX_SCALING
)mode
->h_scaling_mode
,
1206 (VPX_SCALING
)mode
->v_scaling_mode
);
1207 return (res
== 0) ? VPX_CODEC_OK
: VPX_CODEC_INVALID_PARAM
;
1209 return VPX_CODEC_INVALID_PARAM
;
1213 static vpx_codec_err_t
ctrl_register_cx_callback(vpx_codec_alg_priv_t
*ctx
,
1215 vpx_codec_priv_output_cx_pkt_cb_pair_t
*cbp
=
1216 (vpx_codec_priv_output_cx_pkt_cb_pair_t
*)va_arg(args
, void *);
1217 ctx
->output_cx_pkt_cb
.output_cx_pkt
= cbp
->output_cx_pkt
;
1218 ctx
->output_cx_pkt_cb
.user_priv
= cbp
->user_priv
;
1220 return VPX_CODEC_OK
;
1223 static vpx_codec_err_t
ctrl_set_tune_content(vpx_codec_alg_priv_t
*ctx
,
1225 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
1226 extra_cfg
.content
= CAST(VP9E_SET_TUNE_CONTENT
, args
);
1227 return update_extra_cfg(ctx
, &extra_cfg
);
1230 static vpx_codec_err_t
ctrl_set_color_space(vpx_codec_alg_priv_t
*ctx
,
1232 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
1233 extra_cfg
.color_space
= CAST(VP9E_SET_COLOR_SPACE
, args
);
1234 return update_extra_cfg(ctx
, &extra_cfg
);
1237 static vpx_codec_err_t
ctrl_set_color_range(vpx_codec_alg_priv_t
*ctx
,
1239 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
1240 extra_cfg
.color_range
= CAST(VP9E_SET_COLOR_RANGE
, args
);
1241 return update_extra_cfg(ctx
, &extra_cfg
);
1244 static vpx_codec_err_t
ctrl_set_render_size(vpx_codec_alg_priv_t
*ctx
,
1246 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
1247 int *const render_size
= va_arg(args
, int *);
1248 extra_cfg
.render_width
= render_size
[0];
1249 extra_cfg
.render_height
= render_size
[1];
1250 return update_extra_cfg(ctx
, &extra_cfg
);
1253 static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps
[] = {
1254 {VP8_COPY_REFERENCE
, ctrl_copy_reference
},
1257 {VP8_SET_REFERENCE
, ctrl_set_reference
},
1258 {VP8_SET_POSTPROC
, ctrl_set_previewpp
},
1259 {VP8E_SET_ROI_MAP
, ctrl_set_roi_map
},
1260 {VP8E_SET_ACTIVEMAP
, ctrl_set_active_map
},
1261 {VP8E_SET_SCALEMODE
, ctrl_set_scale_mode
},
1262 {VP8E_SET_CPUUSED
, ctrl_set_cpuused
},
1263 {VP8E_SET_ENABLEAUTOALTREF
, ctrl_set_enable_auto_alt_ref
},
1264 {VP8E_SET_SHARPNESS
, ctrl_set_sharpness
},
1265 {VP8E_SET_STATIC_THRESHOLD
, ctrl_set_static_thresh
},
1266 {VP9E_SET_TILE_COLUMNS
, ctrl_set_tile_columns
},
1267 {VP9E_SET_TILE_ROWS
, ctrl_set_tile_rows
},
1268 {VP8E_SET_ARNR_MAXFRAMES
, ctrl_set_arnr_max_frames
},
1269 {VP8E_SET_ARNR_STRENGTH
, ctrl_set_arnr_strength
},
1270 {VP8E_SET_ARNR_TYPE
, ctrl_set_arnr_type
},
1271 {VP8E_SET_TUNING
, ctrl_set_tuning
},
1272 {VP8E_SET_CQ_LEVEL
, ctrl_set_cq_level
},
1273 {VP8E_SET_MAX_INTRA_BITRATE_PCT
, ctrl_set_rc_max_intra_bitrate_pct
},
1274 {VP9E_SET_MAX_INTER_BITRATE_PCT
, ctrl_set_rc_max_inter_bitrate_pct
},
1275 {VP9E_SET_GF_CBR_BOOST_PCT
, ctrl_set_rc_gf_cbr_boost_pct
},
1276 {VP9E_SET_LOSSLESS
, ctrl_set_lossless
},
1277 {VP9E_SET_FRAME_PARALLEL_DECODING
, ctrl_set_frame_parallel_decoding_mode
},
1278 {VP9E_SET_AQ_MODE
, ctrl_set_aq_mode
},
1279 {VP9E_SET_FRAME_PERIODIC_BOOST
, ctrl_set_frame_periodic_boost
},
1280 {VP9E_REGISTER_CX_CALLBACK
, ctrl_register_cx_callback
},
1281 {VP9E_SET_TUNE_CONTENT
, ctrl_set_tune_content
},
1282 {VP9E_SET_COLOR_SPACE
, ctrl_set_color_space
},
1283 {VP9E_SET_COLOR_RANGE
, ctrl_set_color_range
},
1284 {VP9E_SET_NOISE_SENSITIVITY
, ctrl_set_noise_sensitivity
},
1285 {VP9E_SET_MIN_GF_INTERVAL
, ctrl_set_min_gf_interval
},
1286 {VP9E_SET_MAX_GF_INTERVAL
, ctrl_set_max_gf_interval
},
1287 {VP9E_SET_RENDER_SIZE
, ctrl_set_render_size
},
1290 {VP8E_GET_LAST_QUANTIZER
, ctrl_get_quantizer
},
1291 {VP8E_GET_LAST_QUANTIZER_64
, ctrl_get_quantizer64
},
1292 {VP9_GET_REFERENCE
, ctrl_get_reference
},
1293 {VP9E_GET_ACTIVEMAP
, ctrl_get_active_map
},
1298 static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map
[] = {
1308 VPX_BITS_8
, // g_bit_depth
1309 8, // g_input_bit_depth
1311 {1, 30}, // g_timebase
1313 0, // g_error_resilient
1315 VPX_RC_ONE_PASS
, // g_pass
1317 25, // g_lag_in_frames
1319 0, // rc_dropframe_thresh
1320 0, // rc_resize_allowed
1321 0, // rc_scaled_width
1322 0, // rc_scaled_height
1323 60, // rc_resize_down_thresold
1324 30, // rc_resize_up_thresold
1326 VPX_VBR
, // rc_end_usage
1327 {NULL
, 0}, // rc_twopass_stats_in
1328 {NULL
, 0}, // rc_firstpass_mb_stats_in
1329 256, // rc_target_bandwidth
1330 0, // rc_min_quantizer
1331 63, // rc_max_quantizer
1332 25, // rc_undershoot_pct
1333 25, // rc_overshoot_pct
1335 6000, // rc_max_buffer_size
1336 4000, // rc_buffer_initial_size
1337 5000, // rc_buffer_optimal_size
1339 50, // rc_two_pass_vbrbias
1340 0, // rc_two_pass_vbrmin_section
1341 2000, // rc_two_pass_vbrmax_section
1343 // keyframing settings (kf)
1344 VPX_KF_AUTO
, // g_kfmode
1346 9999, // kf_max_dist
1348 // TODO(yunqingwang): Spatial/temporal scalability are not supported
1349 // in VP10. The following 10 parameters are not used, which should
1350 // be removed later.
1351 1, // ss_number_layers
1353 {0}, // ss_target_bitrate
1354 1, // ts_number_layers
1355 {0}, // ts_target_bitrate
1356 {0}, // ts_rate_decimator
1357 0, // ts_periodicity
1359 {0}, // layer_taget_bitrate
1360 0 // temporal_layering_mode
1365 #ifndef VERSION_STRING
1366 #define VERSION_STRING
1368 CODEC_INTERFACE(vpx_codec_vp10_cx
) = {
1369 "WebM Project VP10 Encoder" VERSION_STRING
,
1370 VPX_CODEC_INTERNAL_ABI_VERSION
,
1371 #if CONFIG_VP9_HIGHBITDEPTH
1372 VPX_CODEC_CAP_HIGHBITDEPTH
|
1374 VPX_CODEC_CAP_ENCODER
| VPX_CODEC_CAP_PSNR
, // vpx_codec_caps_t
1375 encoder_init
, // vpx_codec_init_fn_t
1376 encoder_destroy
, // vpx_codec_destroy_fn_t
1377 encoder_ctrl_maps
, // vpx_codec_ctrl_fn_map_t
1379 NULL
, // vpx_codec_peek_si_fn_t
1380 NULL
, // vpx_codec_get_si_fn_t
1381 NULL
, // vpx_codec_decode_fn_t
1382 NULL
, // vpx_codec_frame_get_fn_t
1383 NULL
// vpx_codec_set_fb_fn_t
1387 encoder_usage_cfg_map
, // vpx_codec_enc_cfg_map_t
1388 encoder_encode
, // vpx_codec_encode_fn_t
1389 encoder_get_cxdata
, // vpx_codec_get_cx_data_fn_t
1390 encoder_set_config
, // vpx_codec_enc_config_set_fn_t
1391 NULL
, // vpx_codec_get_global_headers_fn_t
1392 encoder_get_preview
, // vpx_codec_get_preview_frame_fn_t
1393 NULL
// vpx_codec_enc_mr_get_mem_loc_fn_t