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.
12 #include "./vpx_config.h"
13 #include "./vp8_rtcd.h"
14 #include "./vpx_dsp_rtcd.h"
15 #include "./vpx_scale_rtcd.h"
16 #include "vpx/vpx_codec.h"
17 #include "vpx/internal/vpx_codec_internal.h"
18 #include "vpx_version.h"
19 #include "vpx_mem/vpx_mem.h"
20 #include "vpx_ports/vpx_once.h"
21 #include "vp8/encoder/onyx_int.h"
22 #include "vpx/vp8cx.h"
23 #include "vp8/encoder/firstpass.h"
24 #include "vp8/common/onyx.h"
30 struct vpx_codec_pkt_list
*pkt_list
;
31 int cpu_used
; /** available cpu percentage in 1/16*/
32 unsigned int enable_auto_alt_ref
; /** if encoder decides to uses alternate reference frame */
33 unsigned int noise_sensitivity
;
34 unsigned int Sharpness
;
35 unsigned int static_thresh
;
36 unsigned int token_partitions
;
37 unsigned int arnr_max_frames
; /* alt_ref Noise Reduction Max Frame Count */
38 unsigned int arnr_strength
; /* alt_ref Noise Reduction Strength */
39 unsigned int arnr_type
; /* alt_ref filter type */
41 unsigned int cq_level
; /* constrained quality level */
42 unsigned int rc_max_intra_bitrate_pct
;
43 unsigned int screen_content_mode
;
47 static struct vp8_extracfg default_extracfg
= {
49 #if !(CONFIG_REALTIME_ONLY)
54 0, /* enable_auto_alt_ref */
55 0, /* noise_sensitivity */
57 0, /* static_thresh */
58 #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
59 VP8_EIGHT_TOKENPARTITION
,
61 VP8_ONE_TOKENPARTITION
, /* token_partitions */
63 0, /* arnr_max_frames */
64 3, /* arnr_strength */
68 0, /* rc_max_intra_bitrate_pct */
69 0, /* screen_content_mode */
72 struct vpx_codec_alg_priv
74 vpx_codec_priv_t base
;
75 vpx_codec_enc_cfg_t cfg
;
76 struct vp8_extracfg vp8_cfg
;
79 unsigned char *cx_data
;
80 unsigned int cx_data_sz
;
81 vpx_image_t preview_img
;
82 unsigned int next_frame_flag
;
83 vp8_postproc_cfg_t preview_ppcfg
;
84 /* pkt_list size depends on the maximum number of lagged frames allowed. */
85 vpx_codec_pkt_list_decl(64) pkt_list
;
86 unsigned int fixed_kf_cntr
;
87 vpx_enc_frame_flags_t control_frame_flags
;
91 static vpx_codec_err_t
92 update_error_state(vpx_codec_alg_priv_t
*ctx
,
93 const struct vpx_internal_error_info
*error
)
97 if ((res
= error
->error_code
))
98 ctx
->base
.err_detail
= error
->has_detail
107 #define ERROR(str) do {\
108 ctx->base.err_detail = str;\
109 return VPX_CODEC_INVALID_PARAM;\
112 #define RANGE_CHECK(p,memb,lo,hi) do {\
113 if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
114 ERROR(#memb " out of range ["#lo".."#hi"]");\
117 #define RANGE_CHECK_HI(p,memb,hi) do {\
118 if(!((p)->memb <= (hi))) \
119 ERROR(#memb " out of range [.."#hi"]");\
122 #define RANGE_CHECK_LO(p,memb,lo) do {\
123 if(!((p)->memb >= (lo))) \
124 ERROR(#memb " out of range ["#lo"..]");\
127 #define RANGE_CHECK_BOOL(p,memb) do {\
128 if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
131 static vpx_codec_err_t
validate_config(vpx_codec_alg_priv_t
*ctx
,
132 const vpx_codec_enc_cfg_t
*cfg
,
133 const struct vp8_extracfg
*vp8_cfg
,
136 RANGE_CHECK(cfg
, g_w
, 1, 16383); /* 14 bits available */
137 RANGE_CHECK(cfg
, g_h
, 1, 16383); /* 14 bits available */
138 RANGE_CHECK(cfg
, g_timebase
.den
, 1, 1000000000);
139 RANGE_CHECK(cfg
, g_timebase
.num
, 1, 1000000000);
140 RANGE_CHECK_HI(cfg
, g_profile
, 3);
141 RANGE_CHECK_HI(cfg
, rc_max_quantizer
, 63);
142 RANGE_CHECK_HI(cfg
, rc_min_quantizer
, cfg
->rc_max_quantizer
);
143 RANGE_CHECK_HI(cfg
, g_threads
, 64);
144 #if CONFIG_REALTIME_ONLY
145 RANGE_CHECK_HI(cfg
, g_lag_in_frames
, 0);
146 #elif CONFIG_MULTI_RES_ENCODING
147 if (ctx
->base
.enc
.total_encoders
> 1)
148 RANGE_CHECK_HI(cfg
, g_lag_in_frames
, 0);
150 RANGE_CHECK_HI(cfg
, g_lag_in_frames
, 25);
152 RANGE_CHECK(cfg
, rc_end_usage
, VPX_VBR
, VPX_Q
);
153 RANGE_CHECK_HI(cfg
, rc_undershoot_pct
, 1000);
154 RANGE_CHECK_HI(cfg
, rc_overshoot_pct
, 1000);
155 RANGE_CHECK_HI(cfg
, rc_2pass_vbr_bias_pct
, 100);
156 RANGE_CHECK(cfg
, kf_mode
, VPX_KF_DISABLED
, VPX_KF_AUTO
);
158 /* TODO: add spatial re-sampling support and frame dropping in
159 * multi-res-encoder.*/
160 #if CONFIG_MULTI_RES_ENCODING
161 if (ctx
->base
.enc
.total_encoders
> 1)
162 RANGE_CHECK_HI(cfg
, rc_resize_allowed
, 0);
164 RANGE_CHECK_BOOL(cfg
, rc_resize_allowed
);
166 RANGE_CHECK_HI(cfg
, rc_dropframe_thresh
, 100);
167 RANGE_CHECK_HI(cfg
, rc_resize_up_thresh
, 100);
168 RANGE_CHECK_HI(cfg
, rc_resize_down_thresh
, 100);
170 #if CONFIG_REALTIME_ONLY
171 RANGE_CHECK(cfg
, g_pass
, VPX_RC_ONE_PASS
, VPX_RC_ONE_PASS
);
172 #elif CONFIG_MULTI_RES_ENCODING
173 if (ctx
->base
.enc
.total_encoders
> 1)
174 RANGE_CHECK(cfg
, g_pass
, VPX_RC_ONE_PASS
, VPX_RC_ONE_PASS
);
176 RANGE_CHECK(cfg
, g_pass
, VPX_RC_ONE_PASS
, VPX_RC_LAST_PASS
);
179 /* VP8 does not support a lower bound on the keyframe interval in
180 * automatic keyframe placement mode.
182 if (cfg
->kf_mode
!= VPX_KF_DISABLED
&& cfg
->kf_min_dist
!= cfg
->kf_max_dist
183 && cfg
->kf_min_dist
> 0)
184 ERROR("kf_min_dist not supported in auto mode, use 0 "
185 "or kf_max_dist instead.");
187 RANGE_CHECK_BOOL(vp8_cfg
, enable_auto_alt_ref
);
188 RANGE_CHECK(vp8_cfg
, cpu_used
, -16, 16);
190 #if CONFIG_REALTIME_ONLY && !CONFIG_TEMPORAL_DENOISING
191 RANGE_CHECK(vp8_cfg
, noise_sensitivity
, 0, 0);
193 RANGE_CHECK_HI(vp8_cfg
, noise_sensitivity
, 6);
196 RANGE_CHECK(vp8_cfg
, token_partitions
, VP8_ONE_TOKENPARTITION
,
197 VP8_EIGHT_TOKENPARTITION
);
198 RANGE_CHECK_HI(vp8_cfg
, Sharpness
, 7);
199 RANGE_CHECK(vp8_cfg
, arnr_max_frames
, 0, 15);
200 RANGE_CHECK_HI(vp8_cfg
, arnr_strength
, 6);
201 RANGE_CHECK(vp8_cfg
, arnr_type
, 1, 3);
202 RANGE_CHECK(vp8_cfg
, cq_level
, 0, 63);
203 RANGE_CHECK_HI(vp8_cfg
, screen_content_mode
, 2);
204 if (finalize
&& (cfg
->rc_end_usage
== VPX_CQ
|| cfg
->rc_end_usage
== VPX_Q
))
205 RANGE_CHECK(vp8_cfg
, cq_level
,
206 cfg
->rc_min_quantizer
, cfg
->rc_max_quantizer
);
208 #if !(CONFIG_REALTIME_ONLY)
209 if (cfg
->g_pass
== VPX_RC_LAST_PASS
)
211 size_t packet_sz
= sizeof(FIRSTPASS_STATS
);
212 int n_packets
= (int)(cfg
->rc_twopass_stats_in
.sz
/
214 FIRSTPASS_STATS
*stats
;
216 if (!cfg
->rc_twopass_stats_in
.buf
)
217 ERROR("rc_twopass_stats_in.buf not set.");
219 if (cfg
->rc_twopass_stats_in
.sz
% packet_sz
)
220 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
222 if (cfg
->rc_twopass_stats_in
.sz
< 2 * packet_sz
)
223 ERROR("rc_twopass_stats_in requires at least two packets.");
225 stats
= (void*)((char *)cfg
->rc_twopass_stats_in
.buf
226 + (n_packets
- 1) * packet_sz
);
228 if ((int)(stats
->count
+ 0.5) != n_packets
- 1)
229 ERROR("rc_twopass_stats_in missing EOS stats packet");
233 RANGE_CHECK(cfg
, ts_number_layers
, 1, 5);
235 if (cfg
->ts_number_layers
> 1)
238 RANGE_CHECK_HI(cfg
, ts_periodicity
, 16);
240 for (i
=1; i
<cfg
->ts_number_layers
; i
++)
241 if (cfg
->ts_target_bitrate
[i
] <= cfg
->ts_target_bitrate
[i
-1] &&
242 cfg
->rc_target_bitrate
> 0)
243 ERROR("ts_target_bitrate entries are not strictly increasing");
245 RANGE_CHECK(cfg
, ts_rate_decimator
[cfg
->ts_number_layers
-1], 1, 1);
246 for (i
=cfg
->ts_number_layers
-2; i
>0; i
--)
247 if (cfg
->ts_rate_decimator
[i
-1] != 2*cfg
->ts_rate_decimator
[i
])
248 ERROR("ts_rate_decimator factors are not powers of 2");
250 RANGE_CHECK_HI(cfg
, ts_layer_id
[i
], cfg
->ts_number_layers
-1);
253 #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
254 if(cfg
->g_threads
> (1 << vp8_cfg
->token_partitions
))
255 ERROR("g_threads cannot be bigger than number of token partitions");
262 static vpx_codec_err_t
validate_img(vpx_codec_alg_priv_t
*ctx
,
263 const vpx_image_t
*img
)
267 case VPX_IMG_FMT_YV12
:
268 case VPX_IMG_FMT_I420
:
269 case VPX_IMG_FMT_VPXI420
:
270 case VPX_IMG_FMT_VPXYV12
:
273 ERROR("Invalid image format. Only YV12 and I420 images are supported");
276 if ((img
->d_w
!= ctx
->cfg
.g_w
) || (img
->d_h
!= ctx
->cfg
.g_h
))
277 ERROR("Image size must match encoder init configuration size");
283 static vpx_codec_err_t
set_vp8e_config(VP8_CONFIG
*oxcf
,
284 vpx_codec_enc_cfg_t cfg
,
285 struct vp8_extracfg vp8_cfg
,
286 vpx_codec_priv_enc_mr_cfg_t
*mr_cfg
)
288 oxcf
->multi_threaded
= cfg
.g_threads
;
289 oxcf
->Version
= cfg
.g_profile
;
291 oxcf
->Width
= cfg
.g_w
;
292 oxcf
->Height
= cfg
.g_h
;
293 oxcf
->timebase
= cfg
.g_timebase
;
295 oxcf
->error_resilient_mode
= cfg
.g_error_resilient
;
299 case VPX_RC_ONE_PASS
:
300 oxcf
->Mode
= MODE_BESTQUALITY
;
302 case VPX_RC_FIRST_PASS
:
303 oxcf
->Mode
= MODE_FIRSTPASS
;
305 case VPX_RC_LAST_PASS
:
306 oxcf
->Mode
= MODE_SECONDPASS_BEST
;
310 if (cfg
.g_pass
== VPX_RC_FIRST_PASS
|| cfg
.g_pass
== VPX_RC_ONE_PASS
)
313 oxcf
->lag_in_frames
= 0;
317 oxcf
->allow_lag
= (cfg
.g_lag_in_frames
) > 0;
318 oxcf
->lag_in_frames
= cfg
.g_lag_in_frames
;
321 oxcf
->allow_df
= (cfg
.rc_dropframe_thresh
> 0);
322 oxcf
->drop_frames_water_mark
= cfg
.rc_dropframe_thresh
;
324 oxcf
->allow_spatial_resampling
= cfg
.rc_resize_allowed
;
325 oxcf
->resample_up_water_mark
= cfg
.rc_resize_up_thresh
;
326 oxcf
->resample_down_water_mark
= cfg
.rc_resize_down_thresh
;
328 if (cfg
.rc_end_usage
== VPX_VBR
) {
329 oxcf
->end_usage
= USAGE_LOCAL_FILE_PLAYBACK
;
330 } else if (cfg
.rc_end_usage
== VPX_CBR
) {
331 oxcf
->end_usage
= USAGE_STREAM_FROM_SERVER
;
332 } else if (cfg
.rc_end_usage
== VPX_CQ
) {
333 oxcf
->end_usage
= USAGE_CONSTRAINED_QUALITY
;
334 } else if (cfg
.rc_end_usage
== VPX_Q
) {
335 oxcf
->end_usage
= USAGE_CONSTANT_QUALITY
;
338 oxcf
->target_bandwidth
= cfg
.rc_target_bitrate
;
339 oxcf
->rc_max_intra_bitrate_pct
= vp8_cfg
.rc_max_intra_bitrate_pct
;
341 oxcf
->best_allowed_q
= cfg
.rc_min_quantizer
;
342 oxcf
->worst_allowed_q
= cfg
.rc_max_quantizer
;
343 oxcf
->cq_level
= vp8_cfg
.cq_level
;
346 oxcf
->under_shoot_pct
= cfg
.rc_undershoot_pct
;
347 oxcf
->over_shoot_pct
= cfg
.rc_overshoot_pct
;
349 oxcf
->maximum_buffer_size_in_ms
= cfg
.rc_buf_sz
;
350 oxcf
->starting_buffer_level_in_ms
= cfg
.rc_buf_initial_sz
;
351 oxcf
->optimal_buffer_level_in_ms
= cfg
.rc_buf_optimal_sz
;
353 oxcf
->maximum_buffer_size
= cfg
.rc_buf_sz
;
354 oxcf
->starting_buffer_level
= cfg
.rc_buf_initial_sz
;
355 oxcf
->optimal_buffer_level
= cfg
.rc_buf_optimal_sz
;
357 oxcf
->two_pass_vbrbias
= cfg
.rc_2pass_vbr_bias_pct
;
358 oxcf
->two_pass_vbrmin_section
= cfg
.rc_2pass_vbr_minsection_pct
;
359 oxcf
->two_pass_vbrmax_section
= cfg
.rc_2pass_vbr_maxsection_pct
;
361 oxcf
->auto_key
= cfg
.kf_mode
== VPX_KF_AUTO
362 && cfg
.kf_min_dist
!= cfg
.kf_max_dist
;
363 oxcf
->key_freq
= cfg
.kf_max_dist
;
365 oxcf
->number_of_layers
= cfg
.ts_number_layers
;
366 oxcf
->periodicity
= cfg
.ts_periodicity
;
368 if (oxcf
->number_of_layers
> 1)
370 memcpy (oxcf
->target_bitrate
, cfg
.ts_target_bitrate
,
371 sizeof(cfg
.ts_target_bitrate
));
372 memcpy (oxcf
->rate_decimator
, cfg
.ts_rate_decimator
,
373 sizeof(cfg
.ts_rate_decimator
));
374 memcpy (oxcf
->layer_id
, cfg
.ts_layer_id
, sizeof(cfg
.ts_layer_id
));
377 #if CONFIG_MULTI_RES_ENCODING
378 /* When mr_cfg is NULL, oxcf->mr_total_resolutions and oxcf->mr_encoder_id
379 * are both memset to 0, which ensures the correct logic under this
384 oxcf
->mr_total_resolutions
= mr_cfg
->mr_total_resolutions
;
385 oxcf
->mr_encoder_id
= mr_cfg
->mr_encoder_id
;
386 oxcf
->mr_down_sampling_factor
.num
= mr_cfg
->mr_down_sampling_factor
.num
;
387 oxcf
->mr_down_sampling_factor
.den
= mr_cfg
->mr_down_sampling_factor
.den
;
388 oxcf
->mr_low_res_mode_info
= mr_cfg
->mr_low_res_mode_info
;
394 oxcf
->cpu_used
= vp8_cfg
.cpu_used
;
395 oxcf
->encode_breakout
= vp8_cfg
.static_thresh
;
396 oxcf
->play_alternate
= vp8_cfg
.enable_auto_alt_ref
;
397 oxcf
->noise_sensitivity
= vp8_cfg
.noise_sensitivity
;
398 oxcf
->Sharpness
= vp8_cfg
.Sharpness
;
399 oxcf
->token_partitions
= vp8_cfg
.token_partitions
;
401 oxcf
->two_pass_stats_in
= cfg
.rc_twopass_stats_in
;
402 oxcf
->output_pkt_list
= vp8_cfg
.pkt_list
;
404 oxcf
->arnr_max_frames
= vp8_cfg
.arnr_max_frames
;
405 oxcf
->arnr_strength
= vp8_cfg
.arnr_strength
;
406 oxcf
->arnr_type
= vp8_cfg
.arnr_type
;
408 oxcf
->tuning
= vp8_cfg
.tuning
;
410 oxcf
->screen_content_mode
= vp8_cfg
.screen_content_mode
;
413 printf("Current VP8 Settings: \n");
414 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
415 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
416 printf("Sharpness: %d\n", oxcf->Sharpness);
417 printf("cpu_used: %d\n", oxcf->cpu_used);
418 printf("Mode: %d\n", oxcf->Mode);
419 printf("auto_key: %d\n", oxcf->auto_key);
420 printf("key_freq: %d\n", oxcf->key_freq);
421 printf("end_usage: %d\n", oxcf->end_usage);
422 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
423 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
424 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
425 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
426 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
427 printf("fixed_q: %d\n", oxcf->fixed_q);
428 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
429 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
430 printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
431 printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark);
432 printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark);
433 printf("allow_df: %d\n", oxcf->allow_df);
434 printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark);
435 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
436 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
437 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
438 printf("allow_lag: %d\n", oxcf->allow_lag);
439 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
440 printf("play_alternate: %d\n", oxcf->play_alternate);
441 printf("Version: %d\n", oxcf->Version);
442 printf("multi_threaded: %d\n", oxcf->multi_threaded);
443 printf("encode_breakout: %d\n", oxcf->encode_breakout);
448 static vpx_codec_err_t
vp8e_set_config(vpx_codec_alg_priv_t
*ctx
,
449 const vpx_codec_enc_cfg_t
*cfg
)
453 if (cfg
->g_w
!= ctx
->cfg
.g_w
|| cfg
->g_h
!= ctx
->cfg
.g_h
)
455 if (cfg
->g_lag_in_frames
> 1 || cfg
->g_pass
!= VPX_RC_ONE_PASS
)
456 ERROR("Cannot change width or height after initialization");
457 if ((ctx
->cpi
->initial_width
&& (int)cfg
->g_w
> ctx
->cpi
->initial_width
) ||
458 (ctx
->cpi
->initial_height
&& (int)cfg
->g_h
> ctx
->cpi
->initial_height
))
459 ERROR("Cannot increase width or height larger than their initial values");
462 /* Prevent increasing lag_in_frames. This check is stricter than it needs
463 * to be -- the limit is not increasing past the first lag_in_frames
464 * value, but we don't track the initial config, only the last successful
467 if ((cfg
->g_lag_in_frames
> ctx
->cfg
.g_lag_in_frames
))
468 ERROR("Cannot increase lag_in_frames");
470 res
= validate_config(ctx
, cfg
, &ctx
->vp8_cfg
, 0);
475 set_vp8e_config(&ctx
->oxcf
, ctx
->cfg
, ctx
->vp8_cfg
, NULL
);
476 vp8_change_config(ctx
->cpi
, &ctx
->oxcf
);
482 static vpx_codec_err_t
get_quantizer(vpx_codec_alg_priv_t
*ctx
, va_list args
)
484 int *const arg
= va_arg(args
, int *);
486 return VPX_CODEC_INVALID_PARAM
;
487 *arg
= vp8_get_quantizer(ctx
->cpi
);
491 static vpx_codec_err_t
get_quantizer64(vpx_codec_alg_priv_t
*ctx
, va_list args
)
493 int *const arg
= va_arg(args
, int *);
495 return VPX_CODEC_INVALID_PARAM
;
496 *arg
= vp8_reverse_trans(vp8_get_quantizer(ctx
->cpi
));
500 static vpx_codec_err_t
update_extracfg(vpx_codec_alg_priv_t
*ctx
,
501 const struct vp8_extracfg
*extra_cfg
)
503 const vpx_codec_err_t res
= validate_config(ctx
, &ctx
->cfg
, extra_cfg
, 0);
504 if (res
== VPX_CODEC_OK
) {
505 ctx
->vp8_cfg
= *extra_cfg
;
506 set_vp8e_config(&ctx
->oxcf
, ctx
->cfg
, ctx
->vp8_cfg
, NULL
);
507 vp8_change_config(ctx
->cpi
, &ctx
->oxcf
);
512 static vpx_codec_err_t
set_cpu_used(vpx_codec_alg_priv_t
*ctx
, va_list args
)
514 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
515 extra_cfg
.cpu_used
= CAST(VP8E_SET_CPUUSED
, args
);
516 return update_extracfg(ctx
, &extra_cfg
);
519 static vpx_codec_err_t
set_enable_auto_alt_ref(vpx_codec_alg_priv_t
*ctx
,
522 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
523 extra_cfg
.enable_auto_alt_ref
= CAST(VP8E_SET_ENABLEAUTOALTREF
, args
);
524 return update_extracfg(ctx
, &extra_cfg
);
527 static vpx_codec_err_t
set_noise_sensitivity(vpx_codec_alg_priv_t
*ctx
,
530 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
531 extra_cfg
.noise_sensitivity
= CAST(VP8E_SET_NOISE_SENSITIVITY
, args
);
532 return update_extracfg(ctx
, &extra_cfg
);
535 static vpx_codec_err_t
set_sharpness(vpx_codec_alg_priv_t
*ctx
, va_list args
)
537 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
538 extra_cfg
.Sharpness
= CAST(VP8E_SET_SHARPNESS
, args
);
539 return update_extracfg(ctx
, &extra_cfg
);
542 static vpx_codec_err_t
set_static_thresh(vpx_codec_alg_priv_t
*ctx
,
545 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
546 extra_cfg
.static_thresh
= CAST(VP8E_SET_STATIC_THRESHOLD
, args
);
547 return update_extracfg(ctx
, &extra_cfg
);
550 static vpx_codec_err_t
set_token_partitions(vpx_codec_alg_priv_t
*ctx
,
553 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
554 extra_cfg
.token_partitions
= CAST(VP8E_SET_TOKEN_PARTITIONS
, args
);
555 return update_extracfg(ctx
, &extra_cfg
);
558 static vpx_codec_err_t
set_arnr_max_frames(vpx_codec_alg_priv_t
*ctx
,
561 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
562 extra_cfg
.arnr_max_frames
= CAST(VP8E_SET_ARNR_MAXFRAMES
, args
);
563 return update_extracfg(ctx
, &extra_cfg
);
566 static vpx_codec_err_t
set_arnr_strength(vpx_codec_alg_priv_t
*ctx
,
569 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
570 extra_cfg
.arnr_strength
= CAST(VP8E_SET_ARNR_STRENGTH
, args
);
571 return update_extracfg(ctx
, &extra_cfg
);
574 static vpx_codec_err_t
set_arnr_type(vpx_codec_alg_priv_t
*ctx
, va_list args
)
576 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
577 extra_cfg
.arnr_type
= CAST(VP8E_SET_ARNR_TYPE
, args
);
578 return update_extracfg(ctx
, &extra_cfg
);
581 static vpx_codec_err_t
set_tuning(vpx_codec_alg_priv_t
*ctx
, va_list args
)
583 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
584 extra_cfg
.tuning
= CAST(VP8E_SET_TUNING
, args
);
585 return update_extracfg(ctx
, &extra_cfg
);
588 static vpx_codec_err_t
set_cq_level(vpx_codec_alg_priv_t
*ctx
, va_list args
)
590 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
591 extra_cfg
.cq_level
= CAST(VP8E_SET_CQ_LEVEL
, args
);
592 return update_extracfg(ctx
, &extra_cfg
);
595 static vpx_codec_err_t
set_rc_max_intra_bitrate_pct(vpx_codec_alg_priv_t
*ctx
,
598 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
599 extra_cfg
.rc_max_intra_bitrate_pct
=
600 CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT
, args
);
601 return update_extracfg(ctx
, &extra_cfg
);
604 static vpx_codec_err_t
set_screen_content_mode(vpx_codec_alg_priv_t
*ctx
,
607 struct vp8_extracfg extra_cfg
= ctx
->vp8_cfg
;
608 extra_cfg
.screen_content_mode
=
609 CAST(VP8E_SET_SCREEN_CONTENT_MODE
, args
);
610 return update_extracfg(ctx
, &extra_cfg
);
613 static vpx_codec_err_t
vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t
*cfg
,
616 vpx_codec_err_t res
= 0;
618 #if CONFIG_MULTI_RES_ENCODING
619 LOWER_RES_FRAME_INFO
*shared_mem_loc
;
620 int mb_rows
= ((cfg
->g_w
+ 15) >>4);
621 int mb_cols
= ((cfg
->g_h
+ 15) >>4);
623 shared_mem_loc
= calloc(1, sizeof(LOWER_RES_FRAME_INFO
));
626 res
= VPX_CODEC_MEM_ERROR
;
629 shared_mem_loc
->mb_info
= calloc(mb_rows
*mb_cols
, sizeof(LOWER_RES_MB_INFO
));
630 if(!(shared_mem_loc
->mb_info
))
632 res
= VPX_CODEC_MEM_ERROR
;
636 *mem_loc
= (void *)shared_mem_loc
;
646 static vpx_codec_err_t
vp8e_init(vpx_codec_ctx_t
*ctx
,
647 vpx_codec_priv_enc_mr_cfg_t
*mr_cfg
)
649 vpx_codec_err_t res
= VPX_CODEC_OK
;
658 struct vpx_codec_alg_priv
*priv
=
659 (struct vpx_codec_alg_priv
*)vpx_calloc(1, sizeof(*priv
));
663 return VPX_CODEC_MEM_ERROR
;
666 ctx
->priv
= (vpx_codec_priv_t
*)priv
;
667 ctx
->priv
->init_flags
= ctx
->init_flags
;
671 /* Update the reference to the config structure to an
674 priv
->cfg
= *ctx
->config
.enc
;
675 ctx
->config
.enc
= &priv
->cfg
;
678 priv
->vp8_cfg
= default_extracfg
;
679 priv
->vp8_cfg
.pkt_list
= &priv
->pkt_list
.head
;
681 priv
->cx_data_sz
= priv
->cfg
.g_w
* priv
->cfg
.g_h
* 3 / 2 * 2;
683 if (priv
->cx_data_sz
< 32768) priv
->cx_data_sz
= 32768;
685 priv
->cx_data
= malloc(priv
->cx_data_sz
);
689 return VPX_CODEC_MEM_ERROR
;
693 ctx
->priv
->enc
.total_encoders
= mr_cfg
->mr_total_resolutions
;
695 ctx
->priv
->enc
.total_encoders
= 1;
697 once(vp8_initialize_enc
);
699 res
= validate_config(priv
, &priv
->cfg
, &priv
->vp8_cfg
, 0);
703 set_vp8e_config(&priv
->oxcf
, priv
->cfg
, priv
->vp8_cfg
, mr_cfg
);
704 priv
->cpi
= vp8_create_compressor(&priv
->oxcf
);
706 res
= VPX_CODEC_MEM_ERROR
;
713 static vpx_codec_err_t
vp8e_destroy(vpx_codec_alg_priv_t
*ctx
)
715 #if CONFIG_MULTI_RES_ENCODING
716 /* Free multi-encoder shared memory */
717 if (ctx
->oxcf
.mr_total_resolutions
> 0 && (ctx
->oxcf
.mr_encoder_id
== ctx
->oxcf
.mr_total_resolutions
-1))
719 LOWER_RES_FRAME_INFO
*shared_mem_loc
= (LOWER_RES_FRAME_INFO
*)ctx
->oxcf
.mr_low_res_mode_info
;
720 free(shared_mem_loc
->mb_info
);
721 free(ctx
->oxcf
.mr_low_res_mode_info
);
726 vp8_remove_compressor(&ctx
->cpi
);
731 static vpx_codec_err_t
image2yuvconfig(const vpx_image_t
*img
,
732 YV12_BUFFER_CONFIG
*yv12
)
734 const int y_w
= img
->d_w
;
735 const int y_h
= img
->d_h
;
736 const int uv_w
= (img
->d_w
+ 1) / 2;
737 const int uv_h
= (img
->d_h
+ 1) / 2;
738 vpx_codec_err_t res
= VPX_CODEC_OK
;
739 yv12
->y_buffer
= img
->planes
[VPX_PLANE_Y
];
740 yv12
->u_buffer
= img
->planes
[VPX_PLANE_U
];
741 yv12
->v_buffer
= img
->planes
[VPX_PLANE_V
];
743 yv12
->y_crop_width
= y_w
;
744 yv12
->y_crop_height
= y_h
;
746 yv12
->y_height
= y_h
;
747 yv12
->uv_crop_width
= uv_w
;
748 yv12
->uv_crop_height
= uv_h
;
749 yv12
->uv_width
= uv_w
;
750 yv12
->uv_height
= uv_h
;
752 yv12
->y_stride
= img
->stride
[VPX_PLANE_Y
];
753 yv12
->uv_stride
= img
->stride
[VPX_PLANE_U
];
755 yv12
->border
= (img
->stride
[VPX_PLANE_Y
] - img
->w
) / 2;
759 static void pick_quickcompress_mode(vpx_codec_alg_priv_t
*ctx
,
760 unsigned long duration
,
761 unsigned long deadline
)
765 #if !(CONFIG_REALTIME_ONLY)
766 /* Use best quality mode if no deadline is given. */
767 new_qc
= MODE_BESTQUALITY
;
771 uint64_t duration_us
;
773 /* Convert duration parameter from stream timebase to microseconds */
774 duration_us
= (uint64_t)duration
* 1000000
775 * (uint64_t)ctx
->cfg
.g_timebase
.num
776 / (uint64_t)ctx
->cfg
.g_timebase
.den
;
778 /* If the deadline is more that the duration this frame is to be shown,
779 * use good quality mode. Otherwise use realtime mode.
781 new_qc
= (deadline
> duration_us
) ? MODE_GOODQUALITY
: MODE_REALTIME
;
785 new_qc
= MODE_REALTIME
;
788 if (ctx
->cfg
.g_pass
== VPX_RC_FIRST_PASS
)
789 new_qc
= MODE_FIRSTPASS
;
790 else if (ctx
->cfg
.g_pass
== VPX_RC_LAST_PASS
)
791 new_qc
= (new_qc
== MODE_BESTQUALITY
)
792 ? MODE_SECONDPASS_BEST
795 if (ctx
->oxcf
.Mode
!= new_qc
)
797 ctx
->oxcf
.Mode
= new_qc
;
798 vp8_change_config(ctx
->cpi
, &ctx
->oxcf
);
802 static vpx_codec_err_t
set_reference_and_update(vpx_codec_alg_priv_t
*ctx
,
807 if (((flags
& VP8_EFLAG_NO_UPD_GF
) && (flags
& VP8_EFLAG_FORCE_GF
))
808 || ((flags
& VP8_EFLAG_NO_UPD_ARF
) && (flags
& VP8_EFLAG_FORCE_ARF
)))
810 ctx
->base
.err_detail
= "Conflicting flags.";
811 return VPX_CODEC_INVALID_PARAM
;
814 if (flags
& (VP8_EFLAG_NO_REF_LAST
| VP8_EFLAG_NO_REF_GF
815 | VP8_EFLAG_NO_REF_ARF
))
819 if (flags
& VP8_EFLAG_NO_REF_LAST
)
820 ref
^= VP8_LAST_FRAME
;
822 if (flags
& VP8_EFLAG_NO_REF_GF
)
823 ref
^= VP8_GOLD_FRAME
;
825 if (flags
& VP8_EFLAG_NO_REF_ARF
)
826 ref
^= VP8_ALTR_FRAME
;
828 vp8_use_as_reference(ctx
->cpi
, ref
);
831 if (flags
& (VP8_EFLAG_NO_UPD_LAST
| VP8_EFLAG_NO_UPD_GF
832 | VP8_EFLAG_NO_UPD_ARF
| VP8_EFLAG_FORCE_GF
833 | VP8_EFLAG_FORCE_ARF
))
837 if (flags
& VP8_EFLAG_NO_UPD_LAST
)
838 upd
^= VP8_LAST_FRAME
;
840 if (flags
& VP8_EFLAG_NO_UPD_GF
)
841 upd
^= VP8_GOLD_FRAME
;
843 if (flags
& VP8_EFLAG_NO_UPD_ARF
)
844 upd
^= VP8_ALTR_FRAME
;
846 vp8_update_reference(ctx
->cpi
, upd
);
849 if (flags
& VP8_EFLAG_NO_UPD_ENTROPY
)
851 vp8_update_entropy(ctx
->cpi
, 0);
857 static vpx_codec_err_t
vp8e_encode(vpx_codec_alg_priv_t
*ctx
,
858 const vpx_image_t
*img
,
860 unsigned long duration
,
861 vpx_enc_frame_flags_t flags
,
862 unsigned long deadline
)
864 vpx_codec_err_t res
= VPX_CODEC_OK
;
866 if (!ctx
->cfg
.rc_target_bitrate
)
870 res
= validate_img(ctx
, img
);
873 res
= validate_config(ctx
, &ctx
->cfg
, &ctx
->vp8_cfg
, 1);
875 pick_quickcompress_mode(ctx
, duration
, deadline
);
876 vpx_codec_pkt_list_init(&ctx
->pkt_list
);
878 // If no flags are set in the encode call, then use the frame flags as
879 // defined via the control function: vp8e_set_frame_flags.
881 flags
= ctx
->control_frame_flags
;
883 ctx
->control_frame_flags
= 0;
886 res
= set_reference_and_update(ctx
, flags
);
888 /* Handle fixed keyframe intervals */
889 if (ctx
->cfg
.kf_mode
== VPX_KF_AUTO
890 && ctx
->cfg
.kf_min_dist
== ctx
->cfg
.kf_max_dist
)
892 if (++ctx
->fixed_kf_cntr
> ctx
->cfg
.kf_min_dist
)
894 flags
|= VPX_EFLAG_FORCE_KF
;
895 ctx
->fixed_kf_cntr
= 1;
899 /* Initialize the encoder instance on the first frame*/
900 if (!res
&& ctx
->cpi
)
902 unsigned int lib_flags
;
903 YV12_BUFFER_CONFIG sd
;
904 int64_t dst_time_stamp
, dst_end_time_stamp
;
905 unsigned long size
, cx_data_sz
;
906 unsigned char *cx_data
;
907 unsigned char *cx_data_end
;
908 int comp_data_state
= 0;
910 /* Set up internal flags */
911 if (ctx
->base
.init_flags
& VPX_CODEC_USE_PSNR
)
912 ((VP8_COMP
*)ctx
->cpi
)->b_calculate_psnr
= 1;
914 if (ctx
->base
.init_flags
& VPX_CODEC_USE_OUTPUT_PARTITION
)
915 ((VP8_COMP
*)ctx
->cpi
)->output_partition
= 1;
917 /* Convert API flags to internal codec lib flags */
918 lib_flags
= (flags
& VPX_EFLAG_FORCE_KF
) ? FRAMEFLAGS_KEY
: 0;
920 /* vp8 use 10,000,000 ticks/second as time stamp */
921 dst_time_stamp
= pts
* 10000000 * ctx
->cfg
.g_timebase
.num
/ ctx
->cfg
.g_timebase
.den
;
922 dst_end_time_stamp
= (pts
+ duration
) * 10000000 * ctx
->cfg
.g_timebase
.num
/ ctx
->cfg
.g_timebase
.den
;
926 res
= image2yuvconfig(img
, &sd
);
928 if (vp8_receive_raw_frame(ctx
->cpi
, ctx
->next_frame_flag
| lib_flags
,
929 &sd
, dst_time_stamp
, dst_end_time_stamp
))
931 VP8_COMP
*cpi
= (VP8_COMP
*)ctx
->cpi
;
932 res
= update_error_state(ctx
, &cpi
->common
.error
);
935 /* reset for next frame */
936 ctx
->next_frame_flag
= 0;
939 cx_data
= ctx
->cx_data
;
940 cx_data_sz
= ctx
->cx_data_sz
;
941 cx_data_end
= ctx
->cx_data
+ cx_data_sz
;
944 while (cx_data_sz
>= ctx
->cx_data_sz
/ 2)
946 comp_data_state
= vp8_get_compressed_data(ctx
->cpi
,
955 if(comp_data_state
== VPX_CODEC_CORRUPT_FRAME
)
956 return VPX_CODEC_CORRUPT_FRAME
;
957 else if(comp_data_state
== -1)
962 vpx_codec_pts_t round
, delta
;
963 vpx_codec_cx_pkt_t pkt
;
964 VP8_COMP
*cpi
= (VP8_COMP
*)ctx
->cpi
;
966 /* Add the frame packet to the list of returned packets. */
967 round
= (vpx_codec_pts_t
)10000000
968 * ctx
->cfg
.g_timebase
.num
/ 2 - 1;
969 delta
= (dst_end_time_stamp
- dst_time_stamp
);
970 pkt
.kind
= VPX_CODEC_CX_FRAME_PKT
;
972 (dst_time_stamp
* ctx
->cfg
.g_timebase
.den
+ round
)
973 / ctx
->cfg
.g_timebase
.num
/ 10000000;
974 pkt
.data
.frame
.duration
= (unsigned long)
975 ((delta
* ctx
->cfg
.g_timebase
.den
+ round
)
976 / ctx
->cfg
.g_timebase
.num
/ 10000000);
977 pkt
.data
.frame
.flags
= lib_flags
<< 16;
979 if (lib_flags
& FRAMEFLAGS_KEY
)
980 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_KEY
;
982 if (!cpi
->common
.show_frame
)
984 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_INVISIBLE
;
986 /* This timestamp should be as close as possible to the
987 * prior PTS so that if a decoder uses pts to schedule when
988 * to do this, we start right after last frame was decoded.
989 * Invisible frames have no duration.
991 pkt
.data
.frame
.pts
= ((cpi
->last_time_stamp_seen
992 * ctx
->cfg
.g_timebase
.den
+ round
)
993 / ctx
->cfg
.g_timebase
.num
/ 10000000) + 1;
994 pkt
.data
.frame
.duration
= 0;
998 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_DROPPABLE
;
1000 if (cpi
->output_partition
)
1003 const int num_partitions
=
1004 (1 << cpi
->common
.multi_token_partition
) + 1;
1006 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_FRAGMENT
;
1008 for (i
= 0; i
< num_partitions
; ++i
)
1010 #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
1011 pkt
.data
.frame
.buf
= cpi
->partition_d
[i
];
1013 pkt
.data
.frame
.buf
= cx_data
;
1014 cx_data
+= cpi
->partition_sz
[i
];
1015 cx_data_sz
-= cpi
->partition_sz
[i
];
1017 pkt
.data
.frame
.sz
= cpi
->partition_sz
[i
];
1018 pkt
.data
.frame
.partition_id
= i
;
1019 /* don't set the fragment bit for the last partition */
1020 if (i
== (num_partitions
- 1))
1021 pkt
.data
.frame
.flags
&= ~VPX_FRAME_IS_FRAGMENT
;
1022 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt
);
1024 #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
1025 /* In lagged mode the encoder can buffer multiple frames.
1026 * We don't want this in partitioned output because
1027 * partitions are spread all over the output buffer.
1028 * So, force an exit!
1030 cx_data_sz
-= ctx
->cx_data_sz
/ 2;
1035 pkt
.data
.frame
.buf
= cx_data
;
1036 pkt
.data
.frame
.sz
= size
;
1037 pkt
.data
.frame
.partition_id
= -1;
1038 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt
);
1050 static const vpx_codec_cx_pkt_t
*vp8e_get_cxdata(vpx_codec_alg_priv_t
*ctx
,
1051 vpx_codec_iter_t
*iter
)
1053 return vpx_codec_pkt_list_get(&ctx
->pkt_list
.head
, iter
);
1056 static vpx_codec_err_t
vp8e_set_reference(vpx_codec_alg_priv_t
*ctx
,
1059 vpx_ref_frame_t
*data
= va_arg(args
, vpx_ref_frame_t
*);
1063 vpx_ref_frame_t
*frame
= (vpx_ref_frame_t
*)data
;
1064 YV12_BUFFER_CONFIG sd
;
1066 image2yuvconfig(&frame
->img
, &sd
);
1067 vp8_set_reference(ctx
->cpi
, frame
->frame_type
, &sd
);
1068 return VPX_CODEC_OK
;
1071 return VPX_CODEC_INVALID_PARAM
;
1075 static vpx_codec_err_t
vp8e_get_reference(vpx_codec_alg_priv_t
*ctx
,
1079 vpx_ref_frame_t
*data
= va_arg(args
, vpx_ref_frame_t
*);
1083 vpx_ref_frame_t
*frame
= (vpx_ref_frame_t
*)data
;
1084 YV12_BUFFER_CONFIG sd
;
1086 image2yuvconfig(&frame
->img
, &sd
);
1087 vp8_get_reference(ctx
->cpi
, frame
->frame_type
, &sd
);
1088 return VPX_CODEC_OK
;
1091 return VPX_CODEC_INVALID_PARAM
;
1094 static vpx_codec_err_t
vp8e_set_previewpp(vpx_codec_alg_priv_t
*ctx
,
1098 vp8_postproc_cfg_t
*data
= va_arg(args
, vp8_postproc_cfg_t
*);
1102 ctx
->preview_ppcfg
= *((vp8_postproc_cfg_t
*)data
);
1103 return VPX_CODEC_OK
;
1106 return VPX_CODEC_INVALID_PARAM
;
1110 return VPX_CODEC_INCAPABLE
;
1115 static vpx_image_t
*vp8e_get_preview(vpx_codec_alg_priv_t
*ctx
)
1118 YV12_BUFFER_CONFIG sd
;
1119 vp8_ppflags_t flags
= {0};
1121 if (ctx
->preview_ppcfg
.post_proc_flag
)
1123 flags
.post_proc_flag
= ctx
->preview_ppcfg
.post_proc_flag
;
1124 flags
.deblocking_level
= ctx
->preview_ppcfg
.deblocking_level
;
1125 flags
.noise_level
= ctx
->preview_ppcfg
.noise_level
;
1128 if (0 == vp8_get_preview_raw_frame(ctx
->cpi
, &sd
, &flags
))
1132 vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12,
1133 sd.y_width + 2*VP8BORDERINPIXELS,
1134 sd.y_height + 2*VP8BORDERINPIXELS,
1137 vpx_img_set_rect(&ctx->preview_img,
1138 VP8BORDERINPIXELS, VP8BORDERINPIXELS,
1139 sd.y_width, sd.y_height);
1142 ctx
->preview_img
.bps
= 12;
1143 ctx
->preview_img
.planes
[VPX_PLANE_Y
] = sd
.y_buffer
;
1144 ctx
->preview_img
.planes
[VPX_PLANE_U
] = sd
.u_buffer
;
1145 ctx
->preview_img
.planes
[VPX_PLANE_V
] = sd
.v_buffer
;
1147 ctx
->preview_img
.fmt
= VPX_IMG_FMT_I420
;
1148 ctx
->preview_img
.x_chroma_shift
= 1;
1149 ctx
->preview_img
.y_chroma_shift
= 1;
1151 ctx
->preview_img
.d_w
= sd
.y_width
;
1152 ctx
->preview_img
.d_h
= sd
.y_height
;
1153 ctx
->preview_img
.stride
[VPX_PLANE_Y
] = sd
.y_stride
;
1154 ctx
->preview_img
.stride
[VPX_PLANE_U
] = sd
.uv_stride
;
1155 ctx
->preview_img
.stride
[VPX_PLANE_V
] = sd
.uv_stride
;
1156 ctx
->preview_img
.w
= sd
.y_width
;
1157 ctx
->preview_img
.h
= sd
.y_height
;
1159 return &ctx
->preview_img
;
1165 static vpx_codec_err_t
vp8e_update_entropy(vpx_codec_alg_priv_t
*ctx
,
1168 int update
= va_arg(args
, int);
1169 vp8_update_entropy(ctx
->cpi
, update
);
1170 return VPX_CODEC_OK
;
1174 static vpx_codec_err_t
vp8e_update_reference(vpx_codec_alg_priv_t
*ctx
,
1177 int update
= va_arg(args
, int);
1178 vp8_update_reference(ctx
->cpi
, update
);
1179 return VPX_CODEC_OK
;
1182 static vpx_codec_err_t
vp8e_use_reference(vpx_codec_alg_priv_t
*ctx
,
1185 int reference_flag
= va_arg(args
, int);
1186 vp8_use_as_reference(ctx
->cpi
, reference_flag
);
1187 return VPX_CODEC_OK
;
1190 static vpx_codec_err_t
vp8e_set_frame_flags(vpx_codec_alg_priv_t
*ctx
,
1193 int frame_flags
= va_arg(args
, int);
1194 ctx
->control_frame_flags
= frame_flags
;
1195 return set_reference_and_update(ctx
, frame_flags
);
1198 static vpx_codec_err_t
vp8e_set_temporal_layer_id(vpx_codec_alg_priv_t
*ctx
,
1201 int layer_id
= va_arg(args
, int);
1202 if (layer_id
< 0 || layer_id
>= (int)ctx
->cfg
.ts_number_layers
) {
1203 return VPX_CODEC_INVALID_PARAM
;
1205 ctx
->cpi
->temporal_layer_id
= layer_id
;
1206 return VPX_CODEC_OK
;
1209 static vpx_codec_err_t
vp8e_set_roi_map(vpx_codec_alg_priv_t
*ctx
,
1212 vpx_roi_map_t
*data
= va_arg(args
, vpx_roi_map_t
*);
1216 vpx_roi_map_t
*roi
= (vpx_roi_map_t
*)data
;
1218 if (!vp8_set_roimap(ctx
->cpi
, roi
->roi_map
, roi
->rows
, roi
->cols
, roi
->delta_q
, roi
->delta_lf
, roi
->static_threshold
))
1219 return VPX_CODEC_OK
;
1221 return VPX_CODEC_INVALID_PARAM
;
1224 return VPX_CODEC_INVALID_PARAM
;
1228 static vpx_codec_err_t
vp8e_set_activemap(vpx_codec_alg_priv_t
*ctx
,
1231 vpx_active_map_t
*data
= va_arg(args
, vpx_active_map_t
*);
1236 vpx_active_map_t
*map
= (vpx_active_map_t
*)data
;
1238 if (!vp8_set_active_map(ctx
->cpi
, map
->active_map
, map
->rows
, map
->cols
))
1239 return VPX_CODEC_OK
;
1241 return VPX_CODEC_INVALID_PARAM
;
1244 return VPX_CODEC_INVALID_PARAM
;
1247 static vpx_codec_err_t
vp8e_set_scalemode(vpx_codec_alg_priv_t
*ctx
,
1251 vpx_scaling_mode_t
*data
= va_arg(args
, vpx_scaling_mode_t
*);
1256 vpx_scaling_mode_t scalemode
= *(vpx_scaling_mode_t
*)data
;
1257 res
= vp8_set_internal_size(ctx
->cpi
,
1258 (VPX_SCALING
)scalemode
.h_scaling_mode
,
1259 (VPX_SCALING
)scalemode
.v_scaling_mode
);
1263 /*force next frame a key frame to effect scaling mode */
1264 ctx
->next_frame_flag
|= FRAMEFLAGS_KEY
;
1265 return VPX_CODEC_OK
;
1268 return VPX_CODEC_INVALID_PARAM
;
1271 return VPX_CODEC_INVALID_PARAM
;
1275 static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps
[] =
1277 {VP8_SET_REFERENCE
, vp8e_set_reference
},
1278 {VP8_COPY_REFERENCE
, vp8e_get_reference
},
1279 {VP8_SET_POSTPROC
, vp8e_set_previewpp
},
1280 {VP8E_SET_FRAME_FLAGS
, vp8e_set_frame_flags
},
1281 {VP8E_SET_TEMPORAL_LAYER_ID
, vp8e_set_temporal_layer_id
},
1282 {VP8E_SET_ROI_MAP
, vp8e_set_roi_map
},
1283 {VP8E_SET_ACTIVEMAP
, vp8e_set_activemap
},
1284 {VP8E_SET_SCALEMODE
, vp8e_set_scalemode
},
1285 {VP8E_SET_CPUUSED
, set_cpu_used
},
1286 {VP8E_SET_NOISE_SENSITIVITY
, set_noise_sensitivity
},
1287 {VP8E_SET_ENABLEAUTOALTREF
, set_enable_auto_alt_ref
},
1288 {VP8E_SET_SHARPNESS
, set_sharpness
},
1289 {VP8E_SET_STATIC_THRESHOLD
, set_static_thresh
},
1290 {VP8E_SET_TOKEN_PARTITIONS
, set_token_partitions
},
1291 {VP8E_GET_LAST_QUANTIZER
, get_quantizer
},
1292 {VP8E_GET_LAST_QUANTIZER_64
, get_quantizer64
},
1293 {VP8E_SET_ARNR_MAXFRAMES
, set_arnr_max_frames
},
1294 {VP8E_SET_ARNR_STRENGTH
, set_arnr_strength
},
1295 {VP8E_SET_ARNR_TYPE
, set_arnr_type
},
1296 {VP8E_SET_TUNING
, set_tuning
},
1297 {VP8E_SET_CQ_LEVEL
, set_cq_level
},
1298 {VP8E_SET_MAX_INTRA_BITRATE_PCT
, set_rc_max_intra_bitrate_pct
},
1299 {VP8E_SET_SCREEN_CONTENT_MODE
, set_screen_content_mode
},
1303 static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map
[] =
1314 VPX_BITS_8
, /* g_bit_depth */
1315 8, /* g_input_bit_depth */
1317 {1, 30}, /* g_timebase */
1319 0, /* g_error_resilient */
1321 VPX_RC_ONE_PASS
, /* g_pass */
1323 0, /* g_lag_in_frames */
1325 0, /* rc_dropframe_thresh */
1326 0, /* rc_resize_allowed */
1327 1, /* rc_scaled_width */
1328 1, /* rc_scaled_height */
1329 60, /* rc_resize_down_thresold */
1330 30, /* rc_resize_up_thresold */
1332 VPX_VBR
, /* rc_end_usage */
1333 {0}, /* rc_twopass_stats_in */
1334 {0}, /* rc_firstpass_mb_stats_in */
1335 256, /* rc_target_bandwidth */
1336 4, /* rc_min_quantizer */
1337 63, /* rc_max_quantizer */
1338 100, /* rc_undershoot_pct */
1339 100, /* rc_overshoot_pct */
1341 6000, /* rc_max_buffer_size */
1342 4000, /* rc_buffer_initial_size; */
1343 5000, /* rc_buffer_optimal_size; */
1345 50, /* rc_two_pass_vbrbias */
1346 0, /* rc_two_pass_vbrmin_section */
1347 400, /* rc_two_pass_vbrmax_section */
1349 /* keyframing settings (kf) */
1350 VPX_KF_AUTO
, /* g_kfmode*/
1351 0, /* kf_min_dist */
1352 128, /* kf_max_dist */
1354 VPX_SS_DEFAULT_LAYERS
, /* ss_number_layers */
1356 {0}, /* ss_target_bitrate */
1357 1, /* ts_number_layers */
1358 {0}, /* ts_target_bitrate */
1359 {0}, /* ts_rate_decimator */
1360 0, /* ts_periodicity */
1361 {0}, /* ts_layer_id */
1366 #ifndef VERSION_STRING
1367 #define VERSION_STRING
1369 CODEC_INTERFACE(vpx_codec_vp8_cx
) =
1371 "WebM Project VP8 Encoder" VERSION_STRING
,
1372 VPX_CODEC_INTERNAL_ABI_VERSION
,
1373 VPX_CODEC_CAP_ENCODER
| VPX_CODEC_CAP_PSNR
|
1374 VPX_CODEC_CAP_OUTPUT_PARTITION
,
1375 /* vpx_codec_caps_t caps; */
1376 vp8e_init
, /* vpx_codec_init_fn_t init; */
1377 vp8e_destroy
, /* vpx_codec_destroy_fn_t destroy; */
1378 vp8e_ctf_maps
, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1380 NULL
, /* vpx_codec_peek_si_fn_t peek_si; */
1381 NULL
, /* vpx_codec_get_si_fn_t get_si; */
1382 NULL
, /* vpx_codec_decode_fn_t decode; */
1383 NULL
, /* vpx_codec_frame_get_fn_t frame_get; */
1384 NULL
, /* vpx_codec_set_fb_fn_t set_fb_fn; */
1388 vp8e_usage_cfg_map
, /* vpx_codec_enc_cfg_map_t cfg_maps; */
1389 vp8e_encode
, /* vpx_codec_encode_fn_t encode; */
1390 vp8e_get_cxdata
, /* vpx_codec_get_cx_data_fn_t get_cx_data; */
1395 } /* encoder functions */