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_ports/system_state.h"
18 #include "vpx/internal/vpx_codec_internal.h"
19 #include "./vpx_version.h"
20 #include "vp10/encoder/encoder.h"
21 #include "vpx/vp8cx.h"
22 #include "vp10/encoder/firstpass.h"
23 #include "vp10/vp10_iface_common.h"
25 struct vp10_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
;
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 frame_parallel_decoding_mode
;
45 unsigned int frame_periodic_boost
;
46 vpx_bit_depth_t bit_depth
;
47 vp9e_tune_content content
;
48 vpx_color_space_t color_space
;
54 static struct vp10_extracfg default_extra_cfg
= {
56 1, // enable_auto_alt_ref
57 0, // noise_sensitivity
64 0, // min_gf_interval; 0 -> default decision
65 0, // max_gf_interval; 0 -> default decision
66 VP8_TUNE_PSNR
, // tuning
68 0, // rc_max_intra_bitrate_pct
69 0, // rc_max_inter_bitrate_pct
70 0, // gf_cbr_boost_pct
72 1, // frame_parallel_decoding_mode
74 0, // frame_periodic_delta_q
75 VPX_BITS_8
, // Bit depth
76 VP9E_CONTENT_DEFAULT
, // content
77 VPX_CS_UNKNOWN
, // color space
83 struct vpx_codec_alg_priv
{
84 vpx_codec_priv_t base
;
85 vpx_codec_enc_cfg_t cfg
;
86 struct vp10_extracfg extra_cfg
;
87 VP10EncoderConfig oxcf
;
89 unsigned char *cx_data
;
91 unsigned char *pending_cx_data
;
92 size_t pending_cx_data_sz
;
93 int pending_frame_count
;
94 size_t pending_frame_sizes
[8];
95 #if !CONFIG_MISC_FIXES
96 size_t pending_frame_magnitude
;
98 vpx_image_t preview_img
;
99 vpx_enc_frame_flags_t next_frame_flags
;
100 vp8_postproc_cfg_t preview_ppcfg
;
101 vpx_codec_pkt_list_decl(256) pkt_list
;
102 unsigned int fixed_kf_cntr
;
103 vpx_codec_priv_output_cx_pkt_cb_pair_t output_cx_pkt_cb
;
104 // BufferPool that holds all reference frames.
105 BufferPool
*buffer_pool
;
108 static VP9_REFFRAME
ref_frame_to_vp10_reframe(vpx_ref_frame_type_t frame
) {
111 return VP9_LAST_FLAG
;
113 return VP9_GOLD_FLAG
;
117 assert(0 && "Invalid Reference Frame");
118 return VP9_LAST_FLAG
;
121 static vpx_codec_err_t
update_error_state(vpx_codec_alg_priv_t
*ctx
,
122 const struct vpx_internal_error_info
*error
) {
123 const vpx_codec_err_t res
= error
->error_code
;
125 if (res
!= VPX_CODEC_OK
)
126 ctx
->base
.err_detail
= error
->has_detail
? error
->detail
: NULL
;
133 #define ERROR(str) do {\
134 ctx->base.err_detail = str;\
135 return VPX_CODEC_INVALID_PARAM;\
138 #define RANGE_CHECK(p, memb, lo, hi) do {\
139 if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
140 ERROR(#memb " out of range ["#lo".."#hi"]");\
143 #define RANGE_CHECK_HI(p, memb, hi) do {\
144 if (!((p)->memb <= (hi))) \
145 ERROR(#memb " out of range [.."#hi"]");\
148 #define RANGE_CHECK_LO(p, memb, lo) do {\
149 if (!((p)->memb >= (lo))) \
150 ERROR(#memb " out of range ["#lo"..]");\
153 #define RANGE_CHECK_BOOL(p, memb) do {\
154 if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
157 static vpx_codec_err_t
validate_config(vpx_codec_alg_priv_t
*ctx
,
158 const vpx_codec_enc_cfg_t
*cfg
,
159 const struct vp10_extracfg
*extra_cfg
) {
160 RANGE_CHECK(cfg
, g_w
, 1, 65535); // 16 bits available
161 RANGE_CHECK(cfg
, g_h
, 1, 65535); // 16 bits available
162 RANGE_CHECK(cfg
, g_timebase
.den
, 1, 1000000000);
163 RANGE_CHECK(cfg
, g_timebase
.num
, 1, cfg
->g_timebase
.den
);
164 RANGE_CHECK_HI(cfg
, g_profile
, 3);
166 RANGE_CHECK_HI(cfg
, rc_max_quantizer
, 63);
167 RANGE_CHECK_HI(cfg
, rc_min_quantizer
, cfg
->rc_max_quantizer
);
168 RANGE_CHECK_BOOL(extra_cfg
, lossless
);
169 RANGE_CHECK(extra_cfg
, aq_mode
, 0, AQ_MODE_COUNT
- 1);
170 RANGE_CHECK(extra_cfg
, frame_periodic_boost
, 0, 1);
171 RANGE_CHECK_HI(cfg
, g_threads
, 64);
172 RANGE_CHECK_HI(cfg
, g_lag_in_frames
, MAX_LAG_BUFFERS
);
173 RANGE_CHECK(cfg
, rc_end_usage
, VPX_VBR
, VPX_Q
);
174 RANGE_CHECK_HI(cfg
, rc_undershoot_pct
, 100);
175 RANGE_CHECK_HI(cfg
, rc_overshoot_pct
, 100);
176 RANGE_CHECK_HI(cfg
, rc_2pass_vbr_bias_pct
, 100);
177 RANGE_CHECK(cfg
, kf_mode
, VPX_KF_DISABLED
, VPX_KF_AUTO
);
178 RANGE_CHECK_BOOL(cfg
, rc_resize_allowed
);
179 RANGE_CHECK_HI(cfg
, rc_dropframe_thresh
, 100);
180 RANGE_CHECK_HI(cfg
, rc_resize_up_thresh
, 100);
181 RANGE_CHECK_HI(cfg
, rc_resize_down_thresh
, 100);
182 RANGE_CHECK(cfg
, g_pass
, VPX_RC_ONE_PASS
, VPX_RC_LAST_PASS
);
183 RANGE_CHECK(extra_cfg
, min_gf_interval
, 0, (MAX_LAG_BUFFERS
- 1));
184 RANGE_CHECK(extra_cfg
, max_gf_interval
, 0, (MAX_LAG_BUFFERS
- 1));
185 if (extra_cfg
->max_gf_interval
> 0) {
186 RANGE_CHECK(extra_cfg
, max_gf_interval
, 2, (MAX_LAG_BUFFERS
- 1));
188 if (extra_cfg
->min_gf_interval
> 0 && extra_cfg
->max_gf_interval
> 0) {
189 RANGE_CHECK(extra_cfg
, max_gf_interval
, extra_cfg
->min_gf_interval
,
190 (MAX_LAG_BUFFERS
- 1));
193 if (cfg
->rc_resize_allowed
== 1) {
194 RANGE_CHECK(cfg
, rc_scaled_width
, 0, cfg
->g_w
);
195 RANGE_CHECK(cfg
, rc_scaled_height
, 0, cfg
->g_h
);
198 // Spatial/temporal scalability are not yet supported in VP10.
199 // Only accept the default value for range checking.
200 RANGE_CHECK(cfg
, ss_number_layers
, 1, 1);
201 RANGE_CHECK(cfg
, ts_number_layers
, 1, 1);
202 // VP9 does not support a lower bound on the keyframe interval in
203 // automatic keyframe placement mode.
204 if (cfg
->kf_mode
!= VPX_KF_DISABLED
&&
205 cfg
->kf_min_dist
!= cfg
->kf_max_dist
&&
206 cfg
->kf_min_dist
> 0)
207 ERROR("kf_min_dist not supported in auto mode, use 0 "
208 "or kf_max_dist instead.");
210 RANGE_CHECK(extra_cfg
, enable_auto_alt_ref
, 0, 2);
211 RANGE_CHECK(extra_cfg
, cpu_used
, -8, 8);
212 RANGE_CHECK_HI(extra_cfg
, noise_sensitivity
, 6);
213 RANGE_CHECK(extra_cfg
, tile_columns
, 0, 6);
214 RANGE_CHECK(extra_cfg
, tile_rows
, 0, 2);
215 RANGE_CHECK_HI(extra_cfg
, sharpness
, 7);
216 RANGE_CHECK(extra_cfg
, arnr_max_frames
, 0, 15);
217 RANGE_CHECK_HI(extra_cfg
, arnr_strength
, 6);
218 RANGE_CHECK(extra_cfg
, cq_level
, 0, 63);
219 RANGE_CHECK(cfg
, g_bit_depth
, VPX_BITS_8
, VPX_BITS_12
);
220 RANGE_CHECK(cfg
, g_input_bit_depth
, 8, 12);
221 RANGE_CHECK(extra_cfg
, content
,
222 VP9E_CONTENT_DEFAULT
, VP9E_CONTENT_INVALID
- 1);
224 // TODO(yaowu): remove this when ssim tuning is implemented for vp9
225 if (extra_cfg
->tuning
== VP8_TUNE_SSIM
)
226 ERROR("Option --tune=ssim is not currently supported in VP9.");
228 if (cfg
->g_pass
== VPX_RC_LAST_PASS
) {
229 const size_t packet_sz
= sizeof(FIRSTPASS_STATS
);
230 const int n_packets
= (int)(cfg
->rc_twopass_stats_in
.sz
/ packet_sz
);
231 const FIRSTPASS_STATS
*stats
;
233 if (cfg
->rc_twopass_stats_in
.buf
== NULL
)
234 ERROR("rc_twopass_stats_in.buf not set.");
236 if (cfg
->rc_twopass_stats_in
.sz
% packet_sz
)
237 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
239 if (cfg
->rc_twopass_stats_in
.sz
< 2 * packet_sz
)
240 ERROR("rc_twopass_stats_in requires at least two packets.");
243 (const FIRSTPASS_STATS
*)cfg
->rc_twopass_stats_in
.buf
+ n_packets
- 1;
245 if ((int)(stats
->count
+ 0.5) != n_packets
- 1)
246 ERROR("rc_twopass_stats_in missing EOS stats packet");
249 #if !CONFIG_VP9_HIGHBITDEPTH
250 if (cfg
->g_profile
> (unsigned int)PROFILE_1
) {
251 ERROR("Profile > 1 not supported in this build configuration");
254 if (cfg
->g_profile
<= (unsigned int)PROFILE_1
&&
255 cfg
->g_bit_depth
> VPX_BITS_8
) {
256 ERROR("Codec high bit-depth not supported in profile < 2");
258 if (cfg
->g_profile
<= (unsigned int)PROFILE_1
&&
259 cfg
->g_input_bit_depth
> 8) {
260 ERROR("Source high bit-depth not supported in profile < 2");
262 if (cfg
->g_profile
> (unsigned int)PROFILE_1
&&
263 cfg
->g_bit_depth
== VPX_BITS_8
) {
264 ERROR("Codec bit-depth 8 not supported in profile > 1");
266 RANGE_CHECK(extra_cfg
, color_space
, VPX_CS_UNKNOWN
, VPX_CS_SRGB
);
267 RANGE_CHECK(extra_cfg
, color_range
, 0, 1);
271 static vpx_codec_err_t
validate_img(vpx_codec_alg_priv_t
*ctx
,
272 const vpx_image_t
*img
) {
274 case VPX_IMG_FMT_YV12
:
275 case VPX_IMG_FMT_I420
:
276 case VPX_IMG_FMT_I42016
:
278 case VPX_IMG_FMT_I422
:
279 case VPX_IMG_FMT_I444
:
280 case VPX_IMG_FMT_I440
:
281 if (ctx
->cfg
.g_profile
!= (unsigned int)PROFILE_1
) {
282 ERROR("Invalid image format. I422, I444, I440 images are "
283 "not supported in profile.");
286 case VPX_IMG_FMT_I42216
:
287 case VPX_IMG_FMT_I44416
:
288 case VPX_IMG_FMT_I44016
:
289 if (ctx
->cfg
.g_profile
!= (unsigned int)PROFILE_1
&&
290 ctx
->cfg
.g_profile
!= (unsigned int)PROFILE_3
) {
291 ERROR("Invalid image format. 16-bit I422, I444, I440 images are "
292 "not supported in profile.");
296 ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
301 if (img
->d_w
!= ctx
->cfg
.g_w
|| img
->d_h
!= ctx
->cfg
.g_h
)
302 ERROR("Image size must match encoder init configuration size");
307 static int get_image_bps(const vpx_image_t
*img
) {
309 case VPX_IMG_FMT_YV12
:
310 case VPX_IMG_FMT_I420
: return 12;
311 case VPX_IMG_FMT_I422
: return 16;
312 case VPX_IMG_FMT_I444
: return 24;
313 case VPX_IMG_FMT_I440
: return 16;
314 case VPX_IMG_FMT_I42016
: return 24;
315 case VPX_IMG_FMT_I42216
: return 32;
316 case VPX_IMG_FMT_I44416
: return 48;
317 case VPX_IMG_FMT_I44016
: return 32;
318 default: assert(0 && "Invalid image format"); break;
323 static vpx_codec_err_t
set_encoder_config(
324 VP10EncoderConfig
*oxcf
,
325 const vpx_codec_enc_cfg_t
*cfg
,
326 const struct vp10_extracfg
*extra_cfg
) {
327 const int is_vbr
= cfg
->rc_end_usage
== VPX_VBR
;
328 oxcf
->profile
= cfg
->g_profile
;
329 oxcf
->max_threads
= (int)cfg
->g_threads
;
330 oxcf
->width
= cfg
->g_w
;
331 oxcf
->height
= cfg
->g_h
;
332 oxcf
->bit_depth
= cfg
->g_bit_depth
;
333 oxcf
->input_bit_depth
= cfg
->g_input_bit_depth
;
334 // guess a frame rate if out of whack, use 30
335 oxcf
->init_framerate
= (double)cfg
->g_timebase
.den
/ cfg
->g_timebase
.num
;
336 if (oxcf
->init_framerate
> 180)
337 oxcf
->init_framerate
= 30;
341 switch (cfg
->g_pass
) {
342 case VPX_RC_ONE_PASS
:
345 case VPX_RC_FIRST_PASS
:
348 case VPX_RC_LAST_PASS
:
353 oxcf
->lag_in_frames
= cfg
->g_pass
== VPX_RC_FIRST_PASS
? 0
354 : cfg
->g_lag_in_frames
;
355 oxcf
->rc_mode
= cfg
->rc_end_usage
;
357 // Convert target bandwidth from Kbit/s to Bit/s
358 oxcf
->target_bandwidth
= 1000 * cfg
->rc_target_bitrate
;
359 oxcf
->rc_max_intra_bitrate_pct
= extra_cfg
->rc_max_intra_bitrate_pct
;
360 oxcf
->rc_max_inter_bitrate_pct
= extra_cfg
->rc_max_inter_bitrate_pct
;
361 oxcf
->gf_cbr_boost_pct
= extra_cfg
->gf_cbr_boost_pct
;
363 oxcf
->best_allowed_q
=
364 extra_cfg
->lossless
? 0 : vp10_quantizer_to_qindex(cfg
->rc_min_quantizer
);
365 oxcf
->worst_allowed_q
=
366 extra_cfg
->lossless
? 0 : vp10_quantizer_to_qindex(cfg
->rc_max_quantizer
);
367 oxcf
->cq_level
= vp10_quantizer_to_qindex(extra_cfg
->cq_level
);
370 oxcf
->under_shoot_pct
= cfg
->rc_undershoot_pct
;
371 oxcf
->over_shoot_pct
= cfg
->rc_overshoot_pct
;
373 oxcf
->scaled_frame_width
= cfg
->rc_scaled_width
;
374 oxcf
->scaled_frame_height
= cfg
->rc_scaled_height
;
375 if (cfg
->rc_resize_allowed
== 1) {
377 (oxcf
->scaled_frame_width
== 0 || oxcf
->scaled_frame_height
== 0) ?
378 RESIZE_DYNAMIC
: RESIZE_FIXED
;
380 oxcf
->resize_mode
= RESIZE_NONE
;
383 oxcf
->maximum_buffer_size_ms
= is_vbr
? 240000 : cfg
->rc_buf_sz
;
384 oxcf
->starting_buffer_level_ms
= is_vbr
? 60000 : cfg
->rc_buf_initial_sz
;
385 oxcf
->optimal_buffer_level_ms
= is_vbr
? 60000 : cfg
->rc_buf_optimal_sz
;
387 oxcf
->drop_frames_water_mark
= cfg
->rc_dropframe_thresh
;
389 oxcf
->two_pass_vbrbias
= cfg
->rc_2pass_vbr_bias_pct
;
390 oxcf
->two_pass_vbrmin_section
= cfg
->rc_2pass_vbr_minsection_pct
;
391 oxcf
->two_pass_vbrmax_section
= cfg
->rc_2pass_vbr_maxsection_pct
;
393 oxcf
->auto_key
= cfg
->kf_mode
== VPX_KF_AUTO
&&
394 cfg
->kf_min_dist
!= cfg
->kf_max_dist
;
396 oxcf
->key_freq
= cfg
->kf_max_dist
;
398 oxcf
->speed
= abs(extra_cfg
->cpu_used
);
399 oxcf
->encode_breakout
= extra_cfg
->static_thresh
;
400 oxcf
->enable_auto_arf
= extra_cfg
->enable_auto_alt_ref
;
401 oxcf
->noise_sensitivity
= extra_cfg
->noise_sensitivity
;
402 oxcf
->sharpness
= extra_cfg
->sharpness
;
404 oxcf
->two_pass_stats_in
= cfg
->rc_twopass_stats_in
;
406 #if CONFIG_FP_MB_STATS
407 oxcf
->firstpass_mb_stats_in
= cfg
->rc_firstpass_mb_stats_in
;
410 oxcf
->color_space
= extra_cfg
->color_space
;
411 oxcf
->color_range
= extra_cfg
->color_range
;
412 oxcf
->render_width
= extra_cfg
->render_width
;
413 oxcf
->render_height
= extra_cfg
->render_height
;
414 oxcf
->arnr_max_frames
= extra_cfg
->arnr_max_frames
;
415 oxcf
->arnr_strength
= extra_cfg
->arnr_strength
;
416 oxcf
->min_gf_interval
= extra_cfg
->min_gf_interval
;
417 oxcf
->max_gf_interval
= extra_cfg
->max_gf_interval
;
419 oxcf
->tuning
= extra_cfg
->tuning
;
420 oxcf
->content
= extra_cfg
->content
;
422 oxcf
->tile_columns
= extra_cfg
->tile_columns
;
423 oxcf
->tile_rows
= extra_cfg
->tile_rows
;
425 oxcf
->error_resilient_mode
= cfg
->g_error_resilient
;
426 oxcf
->frame_parallel_decoding_mode
= extra_cfg
->frame_parallel_decoding_mode
;
428 oxcf
->aq_mode
= extra_cfg
->aq_mode
;
430 oxcf
->frame_periodic_boost
= extra_cfg
->frame_periodic_boost
;
433 printf("Current VP9 Settings: \n");
434 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
435 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
436 printf("sharpness: %d\n", oxcf->sharpness);
437 printf("cpu_used: %d\n", oxcf->cpu_used);
438 printf("Mode: %d\n", oxcf->mode);
439 printf("auto_key: %d\n", oxcf->auto_key);
440 printf("key_freq: %d\n", oxcf->key_freq);
441 printf("end_usage: %d\n", oxcf->end_usage);
442 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
443 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
444 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
445 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
446 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
447 printf("fixed_q: %d\n", oxcf->fixed_q);
448 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
449 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
450 printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
451 printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width);
452 printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height);
453 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
454 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
455 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
456 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
457 printf("enable_auto_arf: %d\n", oxcf->enable_auto_arf);
458 printf("Version: %d\n", oxcf->Version);
459 printf("encode_breakout: %d\n", oxcf->encode_breakout);
460 printf("error resilient: %d\n", oxcf->error_resilient_mode);
461 printf("frame parallel detokenization: %d\n",
462 oxcf->frame_parallel_decoding_mode);
467 static vpx_codec_err_t
encoder_set_config(vpx_codec_alg_priv_t
*ctx
,
468 const vpx_codec_enc_cfg_t
*cfg
) {
472 if (cfg
->g_w
!= ctx
->cfg
.g_w
|| cfg
->g_h
!= ctx
->cfg
.g_h
) {
473 if (cfg
->g_lag_in_frames
> 1 || cfg
->g_pass
!= VPX_RC_ONE_PASS
)
474 ERROR("Cannot change width or height after initialization");
475 if (!valid_ref_frame_size(ctx
->cfg
.g_w
, ctx
->cfg
.g_h
, cfg
->g_w
, cfg
->g_h
) ||
476 (ctx
->cpi
->initial_width
&& (int)cfg
->g_w
> ctx
->cpi
->initial_width
) ||
477 (ctx
->cpi
->initial_height
&& (int)cfg
->g_h
> ctx
->cpi
->initial_height
))
481 // Prevent increasing lag_in_frames. This check is stricter than it needs
482 // to be -- the limit is not increasing past the first lag_in_frames
483 // value, but we don't track the initial config, only the last successful
485 if (cfg
->g_lag_in_frames
> ctx
->cfg
.g_lag_in_frames
)
486 ERROR("Cannot increase lag_in_frames");
488 res
= validate_config(ctx
, cfg
, &ctx
->extra_cfg
);
490 if (res
== VPX_CODEC_OK
) {
492 set_encoder_config(&ctx
->oxcf
, &ctx
->cfg
, &ctx
->extra_cfg
);
493 // On profile change, request a key frame
494 force_key
|= ctx
->cpi
->common
.profile
!= ctx
->oxcf
.profile
;
495 vp10_change_config(ctx
->cpi
, &ctx
->oxcf
);
499 ctx
->next_frame_flags
|= VPX_EFLAG_FORCE_KF
;
504 static vpx_codec_err_t
ctrl_get_quantizer(vpx_codec_alg_priv_t
*ctx
,
506 int *const arg
= va_arg(args
, int *);
508 return VPX_CODEC_INVALID_PARAM
;
509 *arg
= vp10_get_quantizer(ctx
->cpi
);
513 static vpx_codec_err_t
ctrl_get_quantizer64(vpx_codec_alg_priv_t
*ctx
,
515 int *const arg
= va_arg(args
, int *);
517 return VPX_CODEC_INVALID_PARAM
;
518 *arg
= vp10_qindex_to_quantizer(vp10_get_quantizer(ctx
->cpi
));
522 static vpx_codec_err_t
update_extra_cfg(vpx_codec_alg_priv_t
*ctx
,
523 const struct vp10_extracfg
*extra_cfg
) {
524 const vpx_codec_err_t res
= validate_config(ctx
, &ctx
->cfg
, extra_cfg
);
525 if (res
== VPX_CODEC_OK
) {
526 ctx
->extra_cfg
= *extra_cfg
;
527 set_encoder_config(&ctx
->oxcf
, &ctx
->cfg
, &ctx
->extra_cfg
);
528 vp10_change_config(ctx
->cpi
, &ctx
->oxcf
);
533 static vpx_codec_err_t
ctrl_set_cpuused(vpx_codec_alg_priv_t
*ctx
,
535 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
536 extra_cfg
.cpu_used
= CAST(VP8E_SET_CPUUSED
, args
);
537 return update_extra_cfg(ctx
, &extra_cfg
);
540 static vpx_codec_err_t
ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t
*ctx
,
542 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
543 extra_cfg
.enable_auto_alt_ref
= CAST(VP8E_SET_ENABLEAUTOALTREF
, args
);
544 return update_extra_cfg(ctx
, &extra_cfg
);
547 static vpx_codec_err_t
ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t
*ctx
,
549 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
550 extra_cfg
.noise_sensitivity
= CAST(VP9E_SET_NOISE_SENSITIVITY
, args
);
551 return update_extra_cfg(ctx
, &extra_cfg
);
554 static vpx_codec_err_t
ctrl_set_sharpness(vpx_codec_alg_priv_t
*ctx
,
556 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
557 extra_cfg
.sharpness
= CAST(VP8E_SET_SHARPNESS
, args
);
558 return update_extra_cfg(ctx
, &extra_cfg
);
561 static vpx_codec_err_t
ctrl_set_static_thresh(vpx_codec_alg_priv_t
*ctx
,
563 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
564 extra_cfg
.static_thresh
= CAST(VP8E_SET_STATIC_THRESHOLD
, args
);
565 return update_extra_cfg(ctx
, &extra_cfg
);
568 static vpx_codec_err_t
ctrl_set_tile_columns(vpx_codec_alg_priv_t
*ctx
,
570 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
571 extra_cfg
.tile_columns
= CAST(VP9E_SET_TILE_COLUMNS
, args
);
572 return update_extra_cfg(ctx
, &extra_cfg
);
575 static vpx_codec_err_t
ctrl_set_tile_rows(vpx_codec_alg_priv_t
*ctx
,
577 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
578 extra_cfg
.tile_rows
= CAST(VP9E_SET_TILE_ROWS
, args
);
579 return update_extra_cfg(ctx
, &extra_cfg
);
582 static vpx_codec_err_t
ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t
*ctx
,
584 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
585 extra_cfg
.arnr_max_frames
= CAST(VP8E_SET_ARNR_MAXFRAMES
, args
);
586 return update_extra_cfg(ctx
, &extra_cfg
);
589 static vpx_codec_err_t
ctrl_set_arnr_strength(vpx_codec_alg_priv_t
*ctx
,
591 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
592 extra_cfg
.arnr_strength
= CAST(VP8E_SET_ARNR_STRENGTH
, args
);
593 return update_extra_cfg(ctx
, &extra_cfg
);
596 static vpx_codec_err_t
ctrl_set_arnr_type(vpx_codec_alg_priv_t
*ctx
,
603 static vpx_codec_err_t
ctrl_set_tuning(vpx_codec_alg_priv_t
*ctx
,
605 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
606 extra_cfg
.tuning
= CAST(VP8E_SET_TUNING
, args
);
607 return update_extra_cfg(ctx
, &extra_cfg
);
610 static vpx_codec_err_t
ctrl_set_cq_level(vpx_codec_alg_priv_t
*ctx
,
612 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
613 extra_cfg
.cq_level
= CAST(VP8E_SET_CQ_LEVEL
, args
);
614 return update_extra_cfg(ctx
, &extra_cfg
);
617 static vpx_codec_err_t
ctrl_set_rc_max_intra_bitrate_pct(
618 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
619 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
620 extra_cfg
.rc_max_intra_bitrate_pct
=
621 CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT
, args
);
622 return update_extra_cfg(ctx
, &extra_cfg
);
625 static vpx_codec_err_t
ctrl_set_rc_max_inter_bitrate_pct(
626 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
627 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
628 extra_cfg
.rc_max_inter_bitrate_pct
=
629 CAST(VP8E_SET_MAX_INTER_BITRATE_PCT
, args
);
630 return update_extra_cfg(ctx
, &extra_cfg
);
633 static vpx_codec_err_t
ctrl_set_rc_gf_cbr_boost_pct(
634 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
635 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
636 extra_cfg
.gf_cbr_boost_pct
=
637 CAST(VP9E_SET_GF_CBR_BOOST_PCT
, args
);
638 return update_extra_cfg(ctx
, &extra_cfg
);
641 static vpx_codec_err_t
ctrl_set_lossless(vpx_codec_alg_priv_t
*ctx
,
643 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
644 extra_cfg
.lossless
= CAST(VP9E_SET_LOSSLESS
, args
);
645 return update_extra_cfg(ctx
, &extra_cfg
);
648 static vpx_codec_err_t
ctrl_set_frame_parallel_decoding_mode(
649 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
650 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
651 extra_cfg
.frame_parallel_decoding_mode
=
652 CAST(VP9E_SET_FRAME_PARALLEL_DECODING
, args
);
653 return update_extra_cfg(ctx
, &extra_cfg
);
656 static vpx_codec_err_t
ctrl_set_aq_mode(vpx_codec_alg_priv_t
*ctx
,
658 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
659 extra_cfg
.aq_mode
= CAST(VP9E_SET_AQ_MODE
, args
);
660 return update_extra_cfg(ctx
, &extra_cfg
);
663 static vpx_codec_err_t
ctrl_set_min_gf_interval(vpx_codec_alg_priv_t
*ctx
,
665 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
666 extra_cfg
.min_gf_interval
= CAST(VP9E_SET_MIN_GF_INTERVAL
, args
);
667 return update_extra_cfg(ctx
, &extra_cfg
);
670 static vpx_codec_err_t
ctrl_set_max_gf_interval(vpx_codec_alg_priv_t
*ctx
,
672 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
673 extra_cfg
.max_gf_interval
= CAST(VP9E_SET_MAX_GF_INTERVAL
, args
);
674 return update_extra_cfg(ctx
, &extra_cfg
);
677 static vpx_codec_err_t
ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t
*ctx
,
679 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
680 extra_cfg
.frame_periodic_boost
= CAST(VP9E_SET_FRAME_PERIODIC_BOOST
, args
);
681 return update_extra_cfg(ctx
, &extra_cfg
);
684 static vpx_codec_err_t
encoder_init(vpx_codec_ctx_t
*ctx
,
685 vpx_codec_priv_enc_mr_cfg_t
*data
) {
686 vpx_codec_err_t res
= VPX_CODEC_OK
;
689 if (ctx
->priv
== NULL
) {
690 vpx_codec_alg_priv_t
*const priv
= vpx_calloc(1, sizeof(*priv
));
692 return VPX_CODEC_MEM_ERROR
;
694 ctx
->priv
= (vpx_codec_priv_t
*)priv
;
695 ctx
->priv
->init_flags
= ctx
->init_flags
;
696 ctx
->priv
->enc
.total_encoders
= 1;
698 (BufferPool
*)vpx_calloc(1, sizeof(BufferPool
));
699 if (priv
->buffer_pool
== NULL
)
700 return VPX_CODEC_MEM_ERROR
;
702 #if CONFIG_MULTITHREAD
703 if (pthread_mutex_init(&priv
->buffer_pool
->pool_mutex
, NULL
)) {
704 return VPX_CODEC_MEM_ERROR
;
708 if (ctx
->config
.enc
) {
709 // Update the reference to the config structure to an internal copy.
710 priv
->cfg
= *ctx
->config
.enc
;
711 ctx
->config
.enc
= &priv
->cfg
;
714 priv
->extra_cfg
= default_extra_cfg
;
715 once(vp10_initialize_enc
);
717 res
= validate_config(priv
, &priv
->cfg
, &priv
->extra_cfg
);
719 if (res
== VPX_CODEC_OK
) {
720 set_encoder_config(&priv
->oxcf
, &priv
->cfg
, &priv
->extra_cfg
);
721 #if CONFIG_VP9_HIGHBITDEPTH
722 priv
->oxcf
.use_highbitdepth
=
723 (ctx
->init_flags
& VPX_CODEC_USE_HIGHBITDEPTH
) ? 1 : 0;
725 priv
->cpi
= vp10_create_compressor(&priv
->oxcf
, priv
->buffer_pool
);
726 if (priv
->cpi
== NULL
)
727 res
= VPX_CODEC_MEM_ERROR
;
729 priv
->cpi
->output_pkt_list
= &priv
->pkt_list
.head
;
736 static vpx_codec_err_t
encoder_destroy(vpx_codec_alg_priv_t
*ctx
) {
738 vp10_remove_compressor(ctx
->cpi
);
739 #if CONFIG_MULTITHREAD
740 pthread_mutex_destroy(&ctx
->buffer_pool
->pool_mutex
);
742 vpx_free(ctx
->buffer_pool
);
747 static void pick_quickcompress_mode(vpx_codec_alg_priv_t
*ctx
,
748 unsigned long duration
,
749 unsigned long deadline
) {
750 MODE new_mode
= BEST
;
752 switch (ctx
->cfg
.g_pass
) {
753 case VPX_RC_ONE_PASS
:
755 const vpx_codec_enc_cfg_t
*const cfg
= &ctx
->cfg
;
757 // Convert duration parameter from stream timebase to microseconds.
758 const uint64_t duration_us
= (uint64_t)duration
* 1000000 *
759 (uint64_t)cfg
->g_timebase
.num
/(uint64_t)cfg
->g_timebase
.den
;
761 // If the deadline is more that the duration this frame is to be shown,
762 // use good quality mode. Otherwise use realtime mode.
763 new_mode
= (deadline
> duration_us
) ? GOOD
: REALTIME
;
768 case VPX_RC_FIRST_PASS
:
770 case VPX_RC_LAST_PASS
:
771 new_mode
= deadline
> 0 ? GOOD
: BEST
;
775 if (ctx
->oxcf
.mode
!= new_mode
) {
776 ctx
->oxcf
.mode
= new_mode
;
777 vp10_change_config(ctx
->cpi
, &ctx
->oxcf
);
781 // Turn on to test if supplemental superframe data breaks decoding
782 // #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
783 static int write_superframe_index(vpx_codec_alg_priv_t
*ctx
) {
784 uint8_t marker
= 0xc0;
787 #if CONFIG_MISC_FIXES
789 size_t max_frame_sz
= 0;
792 assert(ctx
->pending_frame_count
);
793 assert(ctx
->pending_frame_count
<= 8);
795 // Add the number of frames to the marker byte
796 marker
|= ctx
->pending_frame_count
- 1;
797 #if CONFIG_MISC_FIXES
798 for (i
= 0; i
< ctx
->pending_frame_count
- 1; i
++) {
799 const size_t frame_sz
= (unsigned int) ctx
->pending_frame_sizes
[i
] - 1;
800 max_frame_sz
= frame_sz
> max_frame_sz
? frame_sz
: max_frame_sz
;
804 // Choose the magnitude
805 for (mag
= 0, mask
= 0xff; mag
< 4; mag
++) {
806 #if CONFIG_MISC_FIXES
807 if (max_frame_sz
<= mask
)
810 if (ctx
->pending_frame_magnitude
< mask
)
819 index_sz
= 2 + (mag
+ 1) * (ctx
->pending_frame_count
- CONFIG_MISC_FIXES
);
820 if (ctx
->pending_cx_data_sz
+ index_sz
< ctx
->cx_data_sz
) {
821 uint8_t *x
= ctx
->pending_cx_data
+ ctx
->pending_cx_data_sz
;
823 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
824 uint8_t marker_test
= 0xc0;
825 int mag_test
= 2; // 1 - 4
826 int frames_test
= 4; // 1 - 8
827 int index_sz_test
= 2 + mag_test
* frames_test
;
828 marker_test
|= frames_test
- 1;
829 marker_test
|= (mag_test
- 1) << 3;
831 for (i
= 0; i
< mag_test
* frames_test
; ++i
)
832 *x
++ = 0; // fill up with arbitrary data
834 ctx
->pending_cx_data_sz
+= index_sz_test
;
835 printf("Added supplemental superframe data\n");
839 for (i
= 0; i
< ctx
->pending_frame_count
- CONFIG_MISC_FIXES
; i
++) {
840 unsigned int this_sz
;
842 assert(ctx
->pending_frame_sizes
[i
] > 0);
843 this_sz
= (unsigned int)ctx
->pending_frame_sizes
[i
] - CONFIG_MISC_FIXES
;
844 for (j
= 0; j
<= mag
; j
++) {
845 *x
++ = this_sz
& 0xff;
850 ctx
->pending_cx_data_sz
+= index_sz
;
851 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
852 index_sz
+= index_sz_test
;
858 // vp9 uses 10,000,000 ticks/second as time stamp
859 #define TICKS_PER_SEC 10000000LL
861 static int64_t timebase_units_to_ticks(const vpx_rational_t
*timebase
,
863 return n
* TICKS_PER_SEC
* timebase
->num
/ timebase
->den
;
866 static int64_t ticks_to_timebase_units(const vpx_rational_t
*timebase
,
868 const int64_t round
= TICKS_PER_SEC
* timebase
->num
/ 2 - 1;
869 return (n
* timebase
->den
+ round
) / timebase
->num
/ TICKS_PER_SEC
;
872 static vpx_codec_frame_flags_t
get_frame_pkt_flags(const VP10_COMP
*cpi
,
873 unsigned int lib_flags
) {
874 vpx_codec_frame_flags_t flags
= lib_flags
<< 16;
876 if (lib_flags
& FRAMEFLAGS_KEY
)
877 flags
|= VPX_FRAME_IS_KEY
;
880 flags
|= VPX_FRAME_IS_DROPPABLE
;
885 static vpx_codec_err_t
encoder_encode(vpx_codec_alg_priv_t
*ctx
,
886 const vpx_image_t
*img
,
888 unsigned long duration
,
889 vpx_enc_frame_flags_t enc_flags
,
890 unsigned long deadline
) {
891 volatile vpx_codec_err_t res
= VPX_CODEC_OK
;
892 volatile vpx_enc_frame_flags_t flags
= enc_flags
;
893 VP10_COMP
*const cpi
= ctx
->cpi
;
894 const vpx_rational_t
*const timebase
= &ctx
->cfg
.g_timebase
;
897 if (cpi
== NULL
) return VPX_CODEC_INVALID_PARAM
;
900 res
= validate_img(ctx
, img
);
901 // TODO(jzern) the checks related to cpi's validity should be treated as a
902 // failure condition, encoder setup is done fully in init() currently.
903 if (res
== VPX_CODEC_OK
) {
904 // There's no codec control for multiple alt-refs so check the encoder
905 // instance for its status to determine the compressed data size.
906 data_sz
= ctx
->cfg
.g_w
* ctx
->cfg
.g_h
* get_image_bps(img
) / 8 *
907 (cpi
->multi_arf_allowed
? 8 : 2);
910 if (ctx
->cx_data
== NULL
|| ctx
->cx_data_sz
< data_sz
) {
911 ctx
->cx_data_sz
= data_sz
;
913 ctx
->cx_data
= (unsigned char*)malloc(ctx
->cx_data_sz
);
914 if (ctx
->cx_data
== NULL
) {
915 return VPX_CODEC_MEM_ERROR
;
921 pick_quickcompress_mode(ctx
, duration
, deadline
);
922 vpx_codec_pkt_list_init(&ctx
->pkt_list
);
925 if (((flags
& VP8_EFLAG_NO_UPD_GF
) && (flags
& VP8_EFLAG_FORCE_GF
)) ||
926 ((flags
& VP8_EFLAG_NO_UPD_ARF
) && (flags
& VP8_EFLAG_FORCE_ARF
))) {
927 ctx
->base
.err_detail
= "Conflicting flags.";
928 return VPX_CODEC_INVALID_PARAM
;
931 if (setjmp(cpi
->common
.error
.jmp
)) {
932 cpi
->common
.error
.setjmp
= 0;
933 res
= update_error_state(ctx
, &cpi
->common
.error
);
934 vpx_clear_system_state();
937 cpi
->common
.error
.setjmp
= 1;
939 vp10_apply_encoding_flags(cpi
, flags
);
941 // Handle fixed keyframe intervals
942 if (ctx
->cfg
.kf_mode
== VPX_KF_AUTO
&&
943 ctx
->cfg
.kf_min_dist
== ctx
->cfg
.kf_max_dist
) {
944 if (++ctx
->fixed_kf_cntr
> ctx
->cfg
.kf_min_dist
) {
945 flags
|= VPX_EFLAG_FORCE_KF
;
946 ctx
->fixed_kf_cntr
= 1;
950 if (res
== VPX_CODEC_OK
) {
951 unsigned int lib_flags
= 0;
952 YV12_BUFFER_CONFIG sd
;
953 int64_t dst_time_stamp
= timebase_units_to_ticks(timebase
, pts
);
954 int64_t dst_end_time_stamp
=
955 timebase_units_to_ticks(timebase
, pts
+ duration
);
956 size_t size
, cx_data_sz
;
957 unsigned char *cx_data
;
959 // Set up internal flags
960 if (ctx
->base
.init_flags
& VPX_CODEC_USE_PSNR
)
961 cpi
->b_calculate_psnr
= 1;
964 res
= image2yuvconfig(img
, &sd
);
966 // Store the original flags in to the frame buffer. Will extract the
967 // key frame flag when we actually encode this frame.
968 if (vp10_receive_raw_frame(cpi
, flags
| ctx
->next_frame_flags
,
969 &sd
, dst_time_stamp
, dst_end_time_stamp
)) {
970 res
= update_error_state(ctx
, &cpi
->common
.error
);
972 ctx
->next_frame_flags
= 0;
975 cx_data
= ctx
->cx_data
;
976 cx_data_sz
= ctx
->cx_data_sz
;
978 /* Any pending invisible frames? */
979 if (ctx
->pending_cx_data
) {
980 memmove(cx_data
, ctx
->pending_cx_data
, ctx
->pending_cx_data_sz
);
981 ctx
->pending_cx_data
= cx_data
;
982 cx_data
+= ctx
->pending_cx_data_sz
;
983 cx_data_sz
-= ctx
->pending_cx_data_sz
;
985 /* TODO: this is a minimal check, the underlying codec doesn't respect
986 * the buffer size anyway.
988 if (cx_data_sz
< ctx
->cx_data_sz
/ 2) {
989 vpx_internal_error(&cpi
->common
.error
, VPX_CODEC_ERROR
,
990 "Compressed data buffer too small");
991 return VPX_CODEC_ERROR
;
995 while (cx_data_sz
>= ctx
->cx_data_sz
/ 2 &&
996 -1 != vp10_get_compressed_data(cpi
, &lib_flags
, &size
,
997 cx_data
, &dst_time_stamp
,
998 &dst_end_time_stamp
, !img
)) {
1000 vpx_codec_cx_pkt_t pkt
;
1002 // Pack invisible frames with the next visible frame
1003 if (!cpi
->common
.show_frame
) {
1004 if (ctx
->pending_cx_data
== 0)
1005 ctx
->pending_cx_data
= cx_data
;
1006 ctx
->pending_cx_data_sz
+= size
;
1007 ctx
->pending_frame_sizes
[ctx
->pending_frame_count
++] = size
;
1008 #if !CONFIG_MISC_FIXES
1009 ctx
->pending_frame_magnitude
|= size
;
1014 if (ctx
->output_cx_pkt_cb
.output_cx_pkt
) {
1015 pkt
.kind
= VPX_CODEC_CX_FRAME_PKT
;
1016 pkt
.data
.frame
.pts
= ticks_to_timebase_units(timebase
,
1018 pkt
.data
.frame
.duration
=
1019 (unsigned long)ticks_to_timebase_units(timebase
,
1020 dst_end_time_stamp
- dst_time_stamp
);
1021 pkt
.data
.frame
.flags
= get_frame_pkt_flags(cpi
, lib_flags
);
1022 pkt
.data
.frame
.buf
= ctx
->pending_cx_data
;
1023 pkt
.data
.frame
.sz
= size
;
1024 ctx
->pending_cx_data
= NULL
;
1025 ctx
->pending_cx_data_sz
= 0;
1026 ctx
->pending_frame_count
= 0;
1027 #if !CONFIG_MISC_FIXES
1028 ctx
->pending_frame_magnitude
= 0;
1030 ctx
->output_cx_pkt_cb
.output_cx_pkt(
1031 &pkt
, ctx
->output_cx_pkt_cb
.user_priv
);
1036 // Add the frame packet to the list of returned packets.
1037 pkt
.kind
= VPX_CODEC_CX_FRAME_PKT
;
1038 pkt
.data
.frame
.pts
= ticks_to_timebase_units(timebase
, dst_time_stamp
);
1039 pkt
.data
.frame
.duration
=
1040 (unsigned long)ticks_to_timebase_units(timebase
,
1041 dst_end_time_stamp
- dst_time_stamp
);
1042 pkt
.data
.frame
.flags
= get_frame_pkt_flags(cpi
, lib_flags
);
1044 if (ctx
->pending_cx_data
) {
1045 ctx
->pending_frame_sizes
[ctx
->pending_frame_count
++] = size
;
1046 #if !CONFIG_MISC_FIXES
1047 ctx
->pending_frame_magnitude
|= size
;
1049 ctx
->pending_cx_data_sz
+= size
;
1050 // write the superframe only for the case when
1051 if (!ctx
->output_cx_pkt_cb
.output_cx_pkt
)
1052 size
+= write_superframe_index(ctx
);
1053 pkt
.data
.frame
.buf
= ctx
->pending_cx_data
;
1054 pkt
.data
.frame
.sz
= ctx
->pending_cx_data_sz
;
1055 ctx
->pending_cx_data
= NULL
;
1056 ctx
->pending_cx_data_sz
= 0;
1057 ctx
->pending_frame_count
= 0;
1058 #if !CONFIG_MISC_FIXES
1059 ctx
->pending_frame_magnitude
= 0;
1062 pkt
.data
.frame
.buf
= cx_data
;
1063 pkt
.data
.frame
.sz
= size
;
1065 pkt
.data
.frame
.partition_id
= -1;
1067 if(ctx
->output_cx_pkt_cb
.output_cx_pkt
)
1068 ctx
->output_cx_pkt_cb
.output_cx_pkt(&pkt
,
1069 ctx
->output_cx_pkt_cb
.user_priv
);
1071 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt
);
1079 cpi
->common
.error
.setjmp
= 0;
1083 static const vpx_codec_cx_pkt_t
*encoder_get_cxdata(vpx_codec_alg_priv_t
*ctx
,
1084 vpx_codec_iter_t
*iter
) {
1085 return vpx_codec_pkt_list_get(&ctx
->pkt_list
.head
, iter
);
1088 static vpx_codec_err_t
ctrl_set_reference(vpx_codec_alg_priv_t
*ctx
,
1090 vpx_ref_frame_t
*const frame
= va_arg(args
, vpx_ref_frame_t
*);
1092 if (frame
!= NULL
) {
1093 YV12_BUFFER_CONFIG sd
;
1095 image2yuvconfig(&frame
->img
, &sd
);
1096 vp10_set_reference_enc(ctx
->cpi
, ref_frame_to_vp10_reframe(frame
->frame_type
),
1098 return VPX_CODEC_OK
;
1100 return VPX_CODEC_INVALID_PARAM
;
1104 static vpx_codec_err_t
ctrl_copy_reference(vpx_codec_alg_priv_t
*ctx
,
1106 vpx_ref_frame_t
*const frame
= va_arg(args
, vpx_ref_frame_t
*);
1108 if (frame
!= NULL
) {
1109 YV12_BUFFER_CONFIG sd
;
1111 image2yuvconfig(&frame
->img
, &sd
);
1112 vp10_copy_reference_enc(ctx
->cpi
,
1113 ref_frame_to_vp10_reframe(frame
->frame_type
), &sd
);
1114 return VPX_CODEC_OK
;
1116 return VPX_CODEC_INVALID_PARAM
;
1120 static vpx_codec_err_t
ctrl_get_reference(vpx_codec_alg_priv_t
*ctx
,
1122 vp9_ref_frame_t
*const frame
= va_arg(args
, vp9_ref_frame_t
*);
1124 if (frame
!= NULL
) {
1125 YV12_BUFFER_CONFIG
*fb
= get_ref_frame(&ctx
->cpi
->common
, frame
->idx
);
1126 if (fb
== NULL
) return VPX_CODEC_ERROR
;
1128 yuvconfig2image(&frame
->img
, fb
, NULL
);
1129 return VPX_CODEC_OK
;
1131 return VPX_CODEC_INVALID_PARAM
;
1135 static vpx_codec_err_t
ctrl_set_previewpp(vpx_codec_alg_priv_t
*ctx
,
1137 #if CONFIG_VP9_POSTPROC
1138 vp8_postproc_cfg_t
*config
= va_arg(args
, vp8_postproc_cfg_t
*);
1139 if (config
!= NULL
) {
1140 ctx
->preview_ppcfg
= *config
;
1141 return VPX_CODEC_OK
;
1143 return VPX_CODEC_INVALID_PARAM
;
1148 return VPX_CODEC_INCAPABLE
;
1153 static vpx_image_t
*encoder_get_preview(vpx_codec_alg_priv_t
*ctx
) {
1154 YV12_BUFFER_CONFIG sd
;
1155 vp10_ppflags_t flags
;
1158 if (ctx
->preview_ppcfg
.post_proc_flag
) {
1159 flags
.post_proc_flag
= ctx
->preview_ppcfg
.post_proc_flag
;
1160 flags
.deblocking_level
= ctx
->preview_ppcfg
.deblocking_level
;
1161 flags
.noise_level
= ctx
->preview_ppcfg
.noise_level
;
1164 if (vp10_get_preview_raw_frame(ctx
->cpi
, &sd
, &flags
) == 0) {
1165 yuvconfig2image(&ctx
->preview_img
, &sd
, NULL
);
1166 return &ctx
->preview_img
;
1172 static vpx_codec_err_t
ctrl_set_roi_map(vpx_codec_alg_priv_t
*ctx
,
1177 // TODO(yaowu): Need to re-implement and test for VP9.
1178 return VPX_CODEC_INVALID_PARAM
;
1182 static vpx_codec_err_t
ctrl_set_active_map(vpx_codec_alg_priv_t
*ctx
,
1184 vpx_active_map_t
*const map
= va_arg(args
, vpx_active_map_t
*);
1187 if (!vp10_set_active_map(ctx
->cpi
, map
->active_map
,
1188 (int)map
->rows
, (int)map
->cols
))
1189 return VPX_CODEC_OK
;
1191 return VPX_CODEC_INVALID_PARAM
;
1193 return VPX_CODEC_INVALID_PARAM
;
1197 static vpx_codec_err_t
ctrl_get_active_map(vpx_codec_alg_priv_t
*ctx
,
1199 vpx_active_map_t
*const map
= va_arg(args
, vpx_active_map_t
*);
1202 if (!vp10_get_active_map(ctx
->cpi
, map
->active_map
,
1203 (int)map
->rows
, (int)map
->cols
))
1204 return VPX_CODEC_OK
;
1206 return VPX_CODEC_INVALID_PARAM
;
1208 return VPX_CODEC_INVALID_PARAM
;
1212 static vpx_codec_err_t
ctrl_set_scale_mode(vpx_codec_alg_priv_t
*ctx
,
1214 vpx_scaling_mode_t
*const mode
= va_arg(args
, vpx_scaling_mode_t
*);
1217 const int res
= vp10_set_internal_size(ctx
->cpi
,
1218 (VPX_SCALING
)mode
->h_scaling_mode
,
1219 (VPX_SCALING
)mode
->v_scaling_mode
);
1220 return (res
== 0) ? VPX_CODEC_OK
: VPX_CODEC_INVALID_PARAM
;
1222 return VPX_CODEC_INVALID_PARAM
;
1226 static vpx_codec_err_t
ctrl_register_cx_callback(vpx_codec_alg_priv_t
*ctx
,
1228 vpx_codec_priv_output_cx_pkt_cb_pair_t
*cbp
=
1229 (vpx_codec_priv_output_cx_pkt_cb_pair_t
*)va_arg(args
, void *);
1230 ctx
->output_cx_pkt_cb
.output_cx_pkt
= cbp
->output_cx_pkt
;
1231 ctx
->output_cx_pkt_cb
.user_priv
= cbp
->user_priv
;
1233 return VPX_CODEC_OK
;
1236 static vpx_codec_err_t
ctrl_set_tune_content(vpx_codec_alg_priv_t
*ctx
,
1238 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
1239 extra_cfg
.content
= CAST(VP9E_SET_TUNE_CONTENT
, args
);
1240 return update_extra_cfg(ctx
, &extra_cfg
);
1243 static vpx_codec_err_t
ctrl_set_color_space(vpx_codec_alg_priv_t
*ctx
,
1245 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
1246 extra_cfg
.color_space
= CAST(VP9E_SET_COLOR_SPACE
, args
);
1247 return update_extra_cfg(ctx
, &extra_cfg
);
1250 static vpx_codec_err_t
ctrl_set_color_range(vpx_codec_alg_priv_t
*ctx
,
1252 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
1253 extra_cfg
.color_range
= CAST(VP9E_SET_COLOR_RANGE
, args
);
1254 return update_extra_cfg(ctx
, &extra_cfg
);
1257 static vpx_codec_err_t
ctrl_set_render_size(vpx_codec_alg_priv_t
*ctx
,
1259 struct vp10_extracfg extra_cfg
= ctx
->extra_cfg
;
1260 int *const render_size
= va_arg(args
, int *);
1261 extra_cfg
.render_width
= render_size
[0];
1262 extra_cfg
.render_height
= render_size
[1];
1263 return update_extra_cfg(ctx
, &extra_cfg
);
1266 static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps
[] = {
1267 {VP8_COPY_REFERENCE
, ctrl_copy_reference
},
1270 {VP8_SET_REFERENCE
, ctrl_set_reference
},
1271 {VP8_SET_POSTPROC
, ctrl_set_previewpp
},
1272 {VP8E_SET_ROI_MAP
, ctrl_set_roi_map
},
1273 {VP8E_SET_ACTIVEMAP
, ctrl_set_active_map
},
1274 {VP8E_SET_SCALEMODE
, ctrl_set_scale_mode
},
1275 {VP8E_SET_CPUUSED
, ctrl_set_cpuused
},
1276 {VP8E_SET_ENABLEAUTOALTREF
, ctrl_set_enable_auto_alt_ref
},
1277 {VP8E_SET_SHARPNESS
, ctrl_set_sharpness
},
1278 {VP8E_SET_STATIC_THRESHOLD
, ctrl_set_static_thresh
},
1279 {VP9E_SET_TILE_COLUMNS
, ctrl_set_tile_columns
},
1280 {VP9E_SET_TILE_ROWS
, ctrl_set_tile_rows
},
1281 {VP8E_SET_ARNR_MAXFRAMES
, ctrl_set_arnr_max_frames
},
1282 {VP8E_SET_ARNR_STRENGTH
, ctrl_set_arnr_strength
},
1283 {VP8E_SET_ARNR_TYPE
, ctrl_set_arnr_type
},
1284 {VP8E_SET_TUNING
, ctrl_set_tuning
},
1285 {VP8E_SET_CQ_LEVEL
, ctrl_set_cq_level
},
1286 {VP8E_SET_MAX_INTRA_BITRATE_PCT
, ctrl_set_rc_max_intra_bitrate_pct
},
1287 {VP9E_SET_MAX_INTER_BITRATE_PCT
, ctrl_set_rc_max_inter_bitrate_pct
},
1288 {VP9E_SET_GF_CBR_BOOST_PCT
, ctrl_set_rc_gf_cbr_boost_pct
},
1289 {VP9E_SET_LOSSLESS
, ctrl_set_lossless
},
1290 {VP9E_SET_FRAME_PARALLEL_DECODING
, ctrl_set_frame_parallel_decoding_mode
},
1291 {VP9E_SET_AQ_MODE
, ctrl_set_aq_mode
},
1292 {VP9E_SET_FRAME_PERIODIC_BOOST
, ctrl_set_frame_periodic_boost
},
1293 {VP9E_REGISTER_CX_CALLBACK
, ctrl_register_cx_callback
},
1294 {VP9E_SET_TUNE_CONTENT
, ctrl_set_tune_content
},
1295 {VP9E_SET_COLOR_SPACE
, ctrl_set_color_space
},
1296 {VP9E_SET_COLOR_RANGE
, ctrl_set_color_range
},
1297 {VP9E_SET_NOISE_SENSITIVITY
, ctrl_set_noise_sensitivity
},
1298 {VP9E_SET_MIN_GF_INTERVAL
, ctrl_set_min_gf_interval
},
1299 {VP9E_SET_MAX_GF_INTERVAL
, ctrl_set_max_gf_interval
},
1300 {VP9E_SET_RENDER_SIZE
, ctrl_set_render_size
},
1303 {VP8E_GET_LAST_QUANTIZER
, ctrl_get_quantizer
},
1304 {VP8E_GET_LAST_QUANTIZER_64
, ctrl_get_quantizer64
},
1305 {VP9_GET_REFERENCE
, ctrl_get_reference
},
1306 {VP9E_GET_ACTIVEMAP
, ctrl_get_active_map
},
1311 static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map
[] = {
1321 VPX_BITS_8
, // g_bit_depth
1322 8, // g_input_bit_depth
1324 {1, 30}, // g_timebase
1326 0, // g_error_resilient
1328 VPX_RC_ONE_PASS
, // g_pass
1330 25, // g_lag_in_frames
1332 0, // rc_dropframe_thresh
1333 0, // rc_resize_allowed
1334 0, // rc_scaled_width
1335 0, // rc_scaled_height
1336 60, // rc_resize_down_thresold
1337 30, // rc_resize_up_thresold
1339 VPX_VBR
, // rc_end_usage
1340 {NULL
, 0}, // rc_twopass_stats_in
1341 {NULL
, 0}, // rc_firstpass_mb_stats_in
1342 256, // rc_target_bandwidth
1343 0, // rc_min_quantizer
1344 63, // rc_max_quantizer
1345 25, // rc_undershoot_pct
1346 25, // rc_overshoot_pct
1348 6000, // rc_max_buffer_size
1349 4000, // rc_buffer_initial_size
1350 5000, // rc_buffer_optimal_size
1352 50, // rc_two_pass_vbrbias
1353 0, // rc_two_pass_vbrmin_section
1354 2000, // rc_two_pass_vbrmax_section
1356 // keyframing settings (kf)
1357 VPX_KF_AUTO
, // g_kfmode
1359 9999, // kf_max_dist
1361 // TODO(yunqingwang): Spatial/temporal scalability are not supported
1362 // in VP10. The following 10 parameters are not used, which should
1363 // be removed later.
1364 1, // ss_number_layers
1366 {0}, // ss_target_bitrate
1367 1, // ts_number_layers
1368 {0}, // ts_target_bitrate
1369 {0}, // ts_rate_decimator
1370 0, // ts_periodicity
1372 {0}, // layer_taget_bitrate
1373 0 // temporal_layering_mode
1378 #ifndef VERSION_STRING
1379 #define VERSION_STRING
1381 CODEC_INTERFACE(vpx_codec_vp10_cx
) = {
1382 "WebM Project VP10 Encoder" VERSION_STRING
,
1383 VPX_CODEC_INTERNAL_ABI_VERSION
,
1384 #if CONFIG_VP9_HIGHBITDEPTH
1385 VPX_CODEC_CAP_HIGHBITDEPTH
|
1387 VPX_CODEC_CAP_ENCODER
| VPX_CODEC_CAP_PSNR
, // vpx_codec_caps_t
1388 encoder_init
, // vpx_codec_init_fn_t
1389 encoder_destroy
, // vpx_codec_destroy_fn_t
1390 encoder_ctrl_maps
, // vpx_codec_ctrl_fn_map_t
1392 NULL
, // vpx_codec_peek_si_fn_t
1393 NULL
, // vpx_codec_get_si_fn_t
1394 NULL
, // vpx_codec_decode_fn_t
1395 NULL
, // vpx_codec_frame_get_fn_t
1396 NULL
// vpx_codec_set_fb_fn_t
1400 encoder_usage_cfg_map
, // vpx_codec_enc_cfg_map_t
1401 encoder_encode
, // vpx_codec_encode_fn_t
1402 encoder_get_cxdata
, // vpx_codec_get_cx_data_fn_t
1403 encoder_set_config
, // vpx_codec_enc_config_set_fn_t
1404 NULL
, // vpx_codec_get_global_headers_fn_t
1405 encoder_get_preview
, // vpx_codec_get_preview_frame_fn_t
1406 NULL
// vpx_codec_enc_mr_get_mem_loc_fn_t