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 "vp9/encoder/vp9_encoder.h"
20 #include "vpx/vp8cx.h"
21 #include "vp9/encoder/vp9_firstpass.h"
22 #include "vp9/vp9_iface_common.h"
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
;
50 static struct vp9_extracfg default_extra_cfg
= {
52 1, // enable_auto_alt_ref
53 0, // noise_sensitivity
60 0, // min_gf_interval; 0 -> default decision
61 0, // max_gf_interval; 0 -> default decision
62 VP8_TUNE_PSNR
, // tuning
64 0, // rc_max_intra_bitrate_pct
65 0, // rc_max_inter_bitrate_pct
66 0, // gf_cbr_boost_pct
68 1, // frame_parallel_decoding_mode
70 0, // frame_periodic_delta_q
71 VPX_BITS_8
, // Bit depth
72 VP9E_CONTENT_DEFAULT
, // content
73 VPX_CS_UNKNOWN
, // color space
76 struct vpx_codec_alg_priv
{
77 vpx_codec_priv_t base
;
78 vpx_codec_enc_cfg_t cfg
;
79 struct vp9_extracfg extra_cfg
;
80 VP9EncoderConfig oxcf
;
82 unsigned char *cx_data
;
84 unsigned char *pending_cx_data
;
85 size_t pending_cx_data_sz
;
86 int pending_frame_count
;
87 size_t pending_frame_sizes
[8];
88 size_t pending_frame_magnitude
;
89 vpx_image_t preview_img
;
90 vpx_enc_frame_flags_t next_frame_flags
;
91 vp8_postproc_cfg_t preview_ppcfg
;
92 vpx_codec_pkt_list_decl(256) pkt_list
;
93 unsigned int fixed_kf_cntr
;
94 vpx_codec_priv_output_cx_pkt_cb_pair_t output_cx_pkt_cb
;
95 // BufferPool that holds all reference frames.
96 BufferPool
*buffer_pool
;
99 static VP9_REFFRAME
ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame
) {
102 return VP9_LAST_FLAG
;
104 return VP9_GOLD_FLAG
;
108 assert(0 && "Invalid Reference Frame");
109 return VP9_LAST_FLAG
;
112 static vpx_codec_err_t
update_error_state(vpx_codec_alg_priv_t
*ctx
,
113 const struct vpx_internal_error_info
*error
) {
114 const vpx_codec_err_t res
= error
->error_code
;
116 if (res
!= VPX_CODEC_OK
)
117 ctx
->base
.err_detail
= error
->has_detail
? error
->detail
: NULL
;
124 #define ERROR(str) do {\
125 ctx->base.err_detail = str;\
126 return VPX_CODEC_INVALID_PARAM;\
129 #define RANGE_CHECK(p, memb, lo, hi) do {\
130 if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
131 ERROR(#memb " out of range ["#lo".."#hi"]");\
134 #define RANGE_CHECK_HI(p, memb, hi) do {\
135 if (!((p)->memb <= (hi))) \
136 ERROR(#memb " out of range [.."#hi"]");\
139 #define RANGE_CHECK_LO(p, memb, lo) do {\
140 if (!((p)->memb >= (lo))) \
141 ERROR(#memb " out of range ["#lo"..]");\
144 #define RANGE_CHECK_BOOL(p, memb) do {\
145 if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
148 static vpx_codec_err_t
validate_config(vpx_codec_alg_priv_t
*ctx
,
149 const vpx_codec_enc_cfg_t
*cfg
,
150 const struct vp9_extracfg
*extra_cfg
) {
151 RANGE_CHECK(cfg
, g_w
, 1, 65535); // 16 bits available
152 RANGE_CHECK(cfg
, g_h
, 1, 65535); // 16 bits available
153 RANGE_CHECK(cfg
, g_timebase
.den
, 1, 1000000000);
154 RANGE_CHECK(cfg
, g_timebase
.num
, 1, cfg
->g_timebase
.den
);
155 RANGE_CHECK_HI(cfg
, g_profile
, 3);
157 RANGE_CHECK_HI(cfg
, rc_max_quantizer
, 63);
158 RANGE_CHECK_HI(cfg
, rc_min_quantizer
, cfg
->rc_max_quantizer
);
159 RANGE_CHECK_BOOL(extra_cfg
, lossless
);
160 RANGE_CHECK(extra_cfg
, aq_mode
, 0, AQ_MODE_COUNT
- 1);
161 RANGE_CHECK(extra_cfg
, frame_periodic_boost
, 0, 1);
162 RANGE_CHECK_HI(cfg
, g_threads
, 64);
163 RANGE_CHECK_HI(cfg
, g_lag_in_frames
, MAX_LAG_BUFFERS
);
164 RANGE_CHECK(cfg
, rc_end_usage
, VPX_VBR
, VPX_Q
);
165 RANGE_CHECK_HI(cfg
, rc_undershoot_pct
, 100);
166 RANGE_CHECK_HI(cfg
, rc_overshoot_pct
, 100);
167 RANGE_CHECK_HI(cfg
, rc_2pass_vbr_bias_pct
, 100);
168 RANGE_CHECK(cfg
, kf_mode
, VPX_KF_DISABLED
, VPX_KF_AUTO
);
169 RANGE_CHECK_BOOL(cfg
, rc_resize_allowed
);
170 RANGE_CHECK_HI(cfg
, rc_dropframe_thresh
, 100);
171 RANGE_CHECK_HI(cfg
, rc_resize_up_thresh
, 100);
172 RANGE_CHECK_HI(cfg
, rc_resize_down_thresh
, 100);
173 RANGE_CHECK(cfg
, g_pass
, VPX_RC_ONE_PASS
, VPX_RC_LAST_PASS
);
174 RANGE_CHECK(extra_cfg
, min_gf_interval
, 0, (MAX_LAG_BUFFERS
- 1));
175 RANGE_CHECK(extra_cfg
, max_gf_interval
, 0, (MAX_LAG_BUFFERS
- 1));
176 if (extra_cfg
->max_gf_interval
> 0) {
177 RANGE_CHECK(extra_cfg
, max_gf_interval
, 2, (MAX_LAG_BUFFERS
- 1));
179 if (extra_cfg
->min_gf_interval
> 0 && extra_cfg
->max_gf_interval
> 0) {
180 RANGE_CHECK(extra_cfg
, max_gf_interval
, extra_cfg
->min_gf_interval
,
181 (MAX_LAG_BUFFERS
- 1));
184 if (cfg
->rc_resize_allowed
== 1) {
185 RANGE_CHECK(cfg
, rc_scaled_width
, 0, cfg
->g_w
);
186 RANGE_CHECK(cfg
, rc_scaled_height
, 0, cfg
->g_h
);
189 RANGE_CHECK(cfg
, ss_number_layers
, 1, VPX_SS_MAX_LAYERS
);
190 RANGE_CHECK(cfg
, ts_number_layers
, 1, VPX_TS_MAX_LAYERS
);
192 if (cfg
->ss_number_layers
* cfg
->ts_number_layers
> VPX_MAX_LAYERS
)
193 ERROR("ss_number_layers * ts_number_layers is out of range");
194 if (cfg
->ts_number_layers
> 1) {
196 for (sl
= 1; sl
< cfg
->ss_number_layers
; ++sl
) {
197 for (tl
= 1; tl
< cfg
->ts_number_layers
; ++tl
) {
199 LAYER_IDS_TO_IDX(sl
, tl
, cfg
->ts_number_layers
);
200 if (cfg
->layer_target_bitrate
[layer
] <
201 cfg
->layer_target_bitrate
[layer
- 1])
202 ERROR("ts_target_bitrate entries are not increasing");
206 RANGE_CHECK(cfg
, ts_rate_decimator
[cfg
->ts_number_layers
- 1], 1, 1);
207 for (tl
= cfg
->ts_number_layers
- 2; tl
> 0; --tl
)
208 if (cfg
->ts_rate_decimator
[tl
- 1] != 2 * cfg
->ts_rate_decimator
[tl
])
209 ERROR("ts_rate_decimator factors are not powers of 2");
212 #if CONFIG_SPATIAL_SVC
214 if ((cfg
->ss_number_layers
> 1 || cfg
->ts_number_layers
> 1) &&
215 cfg
->g_pass
== VPX_RC_LAST_PASS
) {
216 unsigned int i
, alt_ref_sum
= 0;
217 for (i
= 0; i
< cfg
->ss_number_layers
; ++i
) {
218 if (cfg
->ss_enable_auto_alt_ref
[i
])
221 if (alt_ref_sum
> REF_FRAMES
- cfg
->ss_number_layers
)
222 ERROR("Not enough ref buffers for svc alt ref frames");
223 if (cfg
->ss_number_layers
* cfg
->ts_number_layers
> 3 &&
224 cfg
->g_error_resilient
== 0)
225 ERROR("Multiple frame context are not supported for more than 3 layers");
229 // VP9 does not support a lower bound on the keyframe interval in
230 // automatic keyframe placement mode.
231 if (cfg
->kf_mode
!= VPX_KF_DISABLED
&&
232 cfg
->kf_min_dist
!= cfg
->kf_max_dist
&&
233 cfg
->kf_min_dist
> 0)
234 ERROR("kf_min_dist not supported in auto mode, use 0 "
235 "or kf_max_dist instead.");
237 RANGE_CHECK(extra_cfg
, enable_auto_alt_ref
, 0, 2);
238 RANGE_CHECK(extra_cfg
, cpu_used
, -8, 8);
239 RANGE_CHECK_HI(extra_cfg
, noise_sensitivity
, 6);
240 RANGE_CHECK(extra_cfg
, tile_columns
, 0, 6);
241 RANGE_CHECK(extra_cfg
, tile_rows
, 0, 2);
242 RANGE_CHECK_HI(extra_cfg
, sharpness
, 7);
243 RANGE_CHECK(extra_cfg
, arnr_max_frames
, 0, 15);
244 RANGE_CHECK_HI(extra_cfg
, arnr_strength
, 6);
245 RANGE_CHECK(extra_cfg
, cq_level
, 0, 63);
246 RANGE_CHECK(cfg
, g_bit_depth
, VPX_BITS_8
, VPX_BITS_12
);
247 RANGE_CHECK(cfg
, g_input_bit_depth
, 8, 12);
248 RANGE_CHECK(extra_cfg
, content
,
249 VP9E_CONTENT_DEFAULT
, VP9E_CONTENT_INVALID
- 1);
251 // TODO(yaowu): remove this when ssim tuning is implemented for vp9
252 if (extra_cfg
->tuning
== VP8_TUNE_SSIM
)
253 ERROR("Option --tune=ssim is not currently supported in VP9.");
255 if (cfg
->g_pass
== VPX_RC_LAST_PASS
) {
256 const size_t packet_sz
= sizeof(FIRSTPASS_STATS
);
257 const int n_packets
= (int)(cfg
->rc_twopass_stats_in
.sz
/ packet_sz
);
258 const FIRSTPASS_STATS
*stats
;
260 if (cfg
->rc_twopass_stats_in
.buf
== NULL
)
261 ERROR("rc_twopass_stats_in.buf not set.");
263 if (cfg
->rc_twopass_stats_in
.sz
% packet_sz
)
264 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
266 if (cfg
->ss_number_layers
> 1 || cfg
->ts_number_layers
> 1) {
268 unsigned int n_packets_per_layer
[VPX_SS_MAX_LAYERS
] = {0};
270 stats
= cfg
->rc_twopass_stats_in
.buf
;
271 for (i
= 0; i
< n_packets
; ++i
) {
272 const int layer_id
= (int)stats
[i
].spatial_layer_id
;
273 if (layer_id
>= 0 && layer_id
< (int)cfg
->ss_number_layers
) {
274 ++n_packets_per_layer
[layer_id
];
278 for (i
= 0; i
< (int)cfg
->ss_number_layers
; ++i
) {
279 unsigned int layer_id
;
280 if (n_packets_per_layer
[i
] < 2) {
281 ERROR("rc_twopass_stats_in requires at least two packets for each "
285 stats
= (const FIRSTPASS_STATS
*)cfg
->rc_twopass_stats_in
.buf
+
286 n_packets
- cfg
->ss_number_layers
+ i
;
287 layer_id
= (int)stats
->spatial_layer_id
;
289 if (layer_id
>= cfg
->ss_number_layers
290 ||(unsigned int)(stats
->count
+ 0.5) !=
291 n_packets_per_layer
[layer_id
] - 1)
292 ERROR("rc_twopass_stats_in missing EOS stats packet");
295 if (cfg
->rc_twopass_stats_in
.sz
< 2 * packet_sz
)
296 ERROR("rc_twopass_stats_in requires at least two packets.");
299 (const FIRSTPASS_STATS
*)cfg
->rc_twopass_stats_in
.buf
+ n_packets
- 1;
301 if ((int)(stats
->count
+ 0.5) != n_packets
- 1)
302 ERROR("rc_twopass_stats_in missing EOS stats packet");
306 #if !CONFIG_VP9_HIGHBITDEPTH
307 if (cfg
->g_profile
> (unsigned int)PROFILE_1
) {
308 ERROR("Profile > 1 not supported in this build configuration");
311 if (cfg
->g_profile
<= (unsigned int)PROFILE_1
&&
312 cfg
->g_bit_depth
> VPX_BITS_8
) {
313 ERROR("Codec high bit-depth not supported in profile < 2");
315 if (cfg
->g_profile
<= (unsigned int)PROFILE_1
&&
316 cfg
->g_input_bit_depth
> 8) {
317 ERROR("Source high bit-depth not supported in profile < 2");
319 if (cfg
->g_profile
> (unsigned int)PROFILE_1
&&
320 cfg
->g_bit_depth
== VPX_BITS_8
) {
321 ERROR("Codec bit-depth 8 not supported in profile > 1");
323 RANGE_CHECK(extra_cfg
, color_space
, VPX_CS_UNKNOWN
, VPX_CS_SRGB
);
327 static vpx_codec_err_t
validate_img(vpx_codec_alg_priv_t
*ctx
,
328 const vpx_image_t
*img
) {
330 case VPX_IMG_FMT_YV12
:
331 case VPX_IMG_FMT_I420
:
332 case VPX_IMG_FMT_I42016
:
334 case VPX_IMG_FMT_I422
:
335 case VPX_IMG_FMT_I444
:
336 case VPX_IMG_FMT_I440
:
337 if (ctx
->cfg
.g_profile
!= (unsigned int)PROFILE_1
) {
338 ERROR("Invalid image format. I422, I444, I440 images are "
339 "not supported in profile.");
342 case VPX_IMG_FMT_I42216
:
343 case VPX_IMG_FMT_I44416
:
344 case VPX_IMG_FMT_I44016
:
345 if (ctx
->cfg
.g_profile
!= (unsigned int)PROFILE_1
&&
346 ctx
->cfg
.g_profile
!= (unsigned int)PROFILE_3
) {
347 ERROR("Invalid image format. 16-bit I422, I444, I440 images are "
348 "not supported in profile.");
352 ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
357 if (img
->d_w
!= ctx
->cfg
.g_w
|| img
->d_h
!= ctx
->cfg
.g_h
)
358 ERROR("Image size must match encoder init configuration size");
363 static int get_image_bps(const vpx_image_t
*img
) {
365 case VPX_IMG_FMT_YV12
:
366 case VPX_IMG_FMT_I420
: return 12;
367 case VPX_IMG_FMT_I422
: return 16;
368 case VPX_IMG_FMT_I444
: return 24;
369 case VPX_IMG_FMT_I440
: return 16;
370 case VPX_IMG_FMT_I42016
: return 24;
371 case VPX_IMG_FMT_I42216
: return 32;
372 case VPX_IMG_FMT_I44416
: return 48;
373 case VPX_IMG_FMT_I44016
: return 32;
374 default: assert(0 && "Invalid image format"); break;
379 static vpx_codec_err_t
set_encoder_config(
380 VP9EncoderConfig
*oxcf
,
381 const vpx_codec_enc_cfg_t
*cfg
,
382 const struct vp9_extracfg
*extra_cfg
) {
383 const int is_vbr
= cfg
->rc_end_usage
== VPX_VBR
;
385 oxcf
->profile
= cfg
->g_profile
;
386 oxcf
->max_threads
= (int)cfg
->g_threads
;
387 oxcf
->width
= cfg
->g_w
;
388 oxcf
->height
= cfg
->g_h
;
389 oxcf
->bit_depth
= cfg
->g_bit_depth
;
390 oxcf
->input_bit_depth
= cfg
->g_input_bit_depth
;
391 // guess a frame rate if out of whack, use 30
392 oxcf
->init_framerate
= (double)cfg
->g_timebase
.den
/ cfg
->g_timebase
.num
;
393 if (oxcf
->init_framerate
> 180)
394 oxcf
->init_framerate
= 30;
398 switch (cfg
->g_pass
) {
399 case VPX_RC_ONE_PASS
:
402 case VPX_RC_FIRST_PASS
:
405 case VPX_RC_LAST_PASS
:
410 oxcf
->lag_in_frames
= cfg
->g_pass
== VPX_RC_FIRST_PASS
? 0
411 : cfg
->g_lag_in_frames
;
412 oxcf
->rc_mode
= cfg
->rc_end_usage
;
414 // Convert target bandwidth from Kbit/s to Bit/s
415 oxcf
->target_bandwidth
= 1000 * cfg
->rc_target_bitrate
;
416 oxcf
->rc_max_intra_bitrate_pct
= extra_cfg
->rc_max_intra_bitrate_pct
;
417 oxcf
->rc_max_inter_bitrate_pct
= extra_cfg
->rc_max_inter_bitrate_pct
;
418 oxcf
->gf_cbr_boost_pct
= extra_cfg
->gf_cbr_boost_pct
;
420 oxcf
->best_allowed_q
=
421 extra_cfg
->lossless
? 0 : vp9_quantizer_to_qindex(cfg
->rc_min_quantizer
);
422 oxcf
->worst_allowed_q
=
423 extra_cfg
->lossless
? 0 : vp9_quantizer_to_qindex(cfg
->rc_max_quantizer
);
424 oxcf
->cq_level
= vp9_quantizer_to_qindex(extra_cfg
->cq_level
);
427 oxcf
->under_shoot_pct
= cfg
->rc_undershoot_pct
;
428 oxcf
->over_shoot_pct
= cfg
->rc_overshoot_pct
;
430 oxcf
->scaled_frame_width
= cfg
->rc_scaled_width
;
431 oxcf
->scaled_frame_height
= cfg
->rc_scaled_height
;
432 if (cfg
->rc_resize_allowed
== 1) {
434 (oxcf
->scaled_frame_width
== 0 || oxcf
->scaled_frame_height
== 0) ?
435 RESIZE_DYNAMIC
: RESIZE_FIXED
;
437 oxcf
->resize_mode
= RESIZE_NONE
;
440 oxcf
->maximum_buffer_size_ms
= is_vbr
? 240000 : cfg
->rc_buf_sz
;
441 oxcf
->starting_buffer_level_ms
= is_vbr
? 60000 : cfg
->rc_buf_initial_sz
;
442 oxcf
->optimal_buffer_level_ms
= is_vbr
? 60000 : cfg
->rc_buf_optimal_sz
;
444 oxcf
->drop_frames_water_mark
= cfg
->rc_dropframe_thresh
;
446 oxcf
->two_pass_vbrbias
= cfg
->rc_2pass_vbr_bias_pct
;
447 oxcf
->two_pass_vbrmin_section
= cfg
->rc_2pass_vbr_minsection_pct
;
448 oxcf
->two_pass_vbrmax_section
= cfg
->rc_2pass_vbr_maxsection_pct
;
450 oxcf
->auto_key
= cfg
->kf_mode
== VPX_KF_AUTO
&&
451 cfg
->kf_min_dist
!= cfg
->kf_max_dist
;
453 oxcf
->key_freq
= cfg
->kf_max_dist
;
455 oxcf
->speed
= abs(extra_cfg
->cpu_used
);
456 oxcf
->encode_breakout
= extra_cfg
->static_thresh
;
457 oxcf
->enable_auto_arf
= extra_cfg
->enable_auto_alt_ref
;
458 oxcf
->noise_sensitivity
= extra_cfg
->noise_sensitivity
;
459 oxcf
->sharpness
= extra_cfg
->sharpness
;
461 oxcf
->two_pass_stats_in
= cfg
->rc_twopass_stats_in
;
463 #if CONFIG_FP_MB_STATS
464 oxcf
->firstpass_mb_stats_in
= cfg
->rc_firstpass_mb_stats_in
;
467 oxcf
->color_space
= extra_cfg
->color_space
;
468 oxcf
->arnr_max_frames
= extra_cfg
->arnr_max_frames
;
469 oxcf
->arnr_strength
= extra_cfg
->arnr_strength
;
470 oxcf
->min_gf_interval
= extra_cfg
->min_gf_interval
;
471 oxcf
->max_gf_interval
= extra_cfg
->max_gf_interval
;
473 oxcf
->tuning
= extra_cfg
->tuning
;
474 oxcf
->content
= extra_cfg
->content
;
476 oxcf
->tile_columns
= extra_cfg
->tile_columns
;
477 oxcf
->tile_rows
= extra_cfg
->tile_rows
;
479 oxcf
->error_resilient_mode
= cfg
->g_error_resilient
;
480 oxcf
->frame_parallel_decoding_mode
= extra_cfg
->frame_parallel_decoding_mode
;
482 oxcf
->aq_mode
= extra_cfg
->aq_mode
;
484 oxcf
->frame_periodic_boost
= extra_cfg
->frame_periodic_boost
;
486 oxcf
->ss_number_layers
= cfg
->ss_number_layers
;
487 oxcf
->ts_number_layers
= cfg
->ts_number_layers
;
488 oxcf
->temporal_layering_mode
= (enum vp9e_temporal_layering_mode
)
489 cfg
->temporal_layering_mode
;
491 for (sl
= 0; sl
< oxcf
->ss_number_layers
; ++sl
) {
492 #if CONFIG_SPATIAL_SVC
493 oxcf
->ss_enable_auto_arf
[sl
] = cfg
->ss_enable_auto_alt_ref
[sl
];
495 for (tl
= 0; tl
< oxcf
->ts_number_layers
; ++tl
) {
496 oxcf
->layer_target_bitrate
[sl
* oxcf
->ts_number_layers
+ tl
] =
497 1000 * cfg
->layer_target_bitrate
[sl
* oxcf
->ts_number_layers
+ tl
];
500 if (oxcf
->ss_number_layers
== 1 && oxcf
->pass
!= 0) {
501 oxcf
->ss_target_bitrate
[0] = (int)oxcf
->target_bandwidth
;
502 #if CONFIG_SPATIAL_SVC
503 oxcf
->ss_enable_auto_arf
[0] = extra_cfg
->enable_auto_alt_ref
;
506 if (oxcf
->ts_number_layers
> 1) {
507 for (tl
= 0; tl
< VPX_TS_MAX_LAYERS
; ++tl
) {
508 oxcf
->ts_rate_decimator
[tl
] = cfg
->ts_rate_decimator
[tl
] ?
509 cfg
->ts_rate_decimator
[tl
] : 1;
511 } else if (oxcf
->ts_number_layers
== 1) {
512 oxcf
->ts_rate_decimator
[0] = 1;
515 printf("Current VP9 Settings: \n");
516 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
517 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
518 printf("sharpness: %d\n", oxcf->sharpness);
519 printf("cpu_used: %d\n", oxcf->cpu_used);
520 printf("Mode: %d\n", oxcf->mode);
521 printf("auto_key: %d\n", oxcf->auto_key);
522 printf("key_freq: %d\n", oxcf->key_freq);
523 printf("end_usage: %d\n", oxcf->end_usage);
524 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
525 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
526 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
527 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
528 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
529 printf("fixed_q: %d\n", oxcf->fixed_q);
530 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
531 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
532 printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
533 printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width);
534 printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height);
535 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
536 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
537 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
538 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
539 printf("enable_auto_arf: %d\n", oxcf->enable_auto_arf);
540 printf("Version: %d\n", oxcf->Version);
541 printf("encode_breakout: %d\n", oxcf->encode_breakout);
542 printf("error resilient: %d\n", oxcf->error_resilient_mode);
543 printf("frame parallel detokenization: %d\n",
544 oxcf->frame_parallel_decoding_mode);
549 static vpx_codec_err_t
encoder_set_config(vpx_codec_alg_priv_t
*ctx
,
550 const vpx_codec_enc_cfg_t
*cfg
) {
554 if (cfg
->g_w
!= ctx
->cfg
.g_w
|| cfg
->g_h
!= ctx
->cfg
.g_h
) {
555 if (cfg
->g_lag_in_frames
> 1 || cfg
->g_pass
!= VPX_RC_ONE_PASS
)
556 ERROR("Cannot change width or height after initialization");
557 if (!valid_ref_frame_size(ctx
->cfg
.g_w
, ctx
->cfg
.g_h
, cfg
->g_w
, cfg
->g_h
) ||
558 (ctx
->cpi
->initial_width
&& (int)cfg
->g_w
> ctx
->cpi
->initial_width
) ||
559 (ctx
->cpi
->initial_height
&& (int)cfg
->g_h
> ctx
->cpi
->initial_height
))
563 // Prevent increasing lag_in_frames. This check is stricter than it needs
564 // to be -- the limit is not increasing past the first lag_in_frames
565 // value, but we don't track the initial config, only the last successful
567 if (cfg
->g_lag_in_frames
> ctx
->cfg
.g_lag_in_frames
)
568 ERROR("Cannot increase lag_in_frames");
570 res
= validate_config(ctx
, cfg
, &ctx
->extra_cfg
);
572 if (res
== VPX_CODEC_OK
) {
574 set_encoder_config(&ctx
->oxcf
, &ctx
->cfg
, &ctx
->extra_cfg
);
575 // On profile change, request a key frame
576 force_key
|= ctx
->cpi
->common
.profile
!= ctx
->oxcf
.profile
;
577 vp9_change_config(ctx
->cpi
, &ctx
->oxcf
);
581 ctx
->next_frame_flags
|= VPX_EFLAG_FORCE_KF
;
586 static vpx_codec_err_t
ctrl_get_quantizer(vpx_codec_alg_priv_t
*ctx
,
588 int *const arg
= va_arg(args
, int *);
590 return VPX_CODEC_INVALID_PARAM
;
591 *arg
= vp9_get_quantizer(ctx
->cpi
);
595 static vpx_codec_err_t
ctrl_get_quantizer64(vpx_codec_alg_priv_t
*ctx
,
597 int *const arg
= va_arg(args
, int *);
599 return VPX_CODEC_INVALID_PARAM
;
600 *arg
= vp9_qindex_to_quantizer(vp9_get_quantizer(ctx
->cpi
));
604 static vpx_codec_err_t
update_extra_cfg(vpx_codec_alg_priv_t
*ctx
,
605 const struct vp9_extracfg
*extra_cfg
) {
606 const vpx_codec_err_t res
= validate_config(ctx
, &ctx
->cfg
, extra_cfg
);
607 if (res
== VPX_CODEC_OK
) {
608 ctx
->extra_cfg
= *extra_cfg
;
609 set_encoder_config(&ctx
->oxcf
, &ctx
->cfg
, &ctx
->extra_cfg
);
610 vp9_change_config(ctx
->cpi
, &ctx
->oxcf
);
615 static vpx_codec_err_t
ctrl_set_cpuused(vpx_codec_alg_priv_t
*ctx
,
617 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
618 extra_cfg
.cpu_used
= CAST(VP8E_SET_CPUUSED
, args
);
619 return update_extra_cfg(ctx
, &extra_cfg
);
622 static vpx_codec_err_t
ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t
*ctx
,
624 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
625 extra_cfg
.enable_auto_alt_ref
= CAST(VP8E_SET_ENABLEAUTOALTREF
, args
);
626 return update_extra_cfg(ctx
, &extra_cfg
);
629 static vpx_codec_err_t
ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t
*ctx
,
631 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
632 extra_cfg
.noise_sensitivity
= CAST(VP9E_SET_NOISE_SENSITIVITY
, args
);
633 return update_extra_cfg(ctx
, &extra_cfg
);
636 static vpx_codec_err_t
ctrl_set_sharpness(vpx_codec_alg_priv_t
*ctx
,
638 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
639 extra_cfg
.sharpness
= CAST(VP8E_SET_SHARPNESS
, args
);
640 return update_extra_cfg(ctx
, &extra_cfg
);
643 static vpx_codec_err_t
ctrl_set_static_thresh(vpx_codec_alg_priv_t
*ctx
,
645 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
646 extra_cfg
.static_thresh
= CAST(VP8E_SET_STATIC_THRESHOLD
, args
);
647 return update_extra_cfg(ctx
, &extra_cfg
);
650 static vpx_codec_err_t
ctrl_set_tile_columns(vpx_codec_alg_priv_t
*ctx
,
652 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
653 extra_cfg
.tile_columns
= CAST(VP9E_SET_TILE_COLUMNS
, args
);
654 return update_extra_cfg(ctx
, &extra_cfg
);
657 static vpx_codec_err_t
ctrl_set_tile_rows(vpx_codec_alg_priv_t
*ctx
,
659 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
660 extra_cfg
.tile_rows
= CAST(VP9E_SET_TILE_ROWS
, args
);
661 return update_extra_cfg(ctx
, &extra_cfg
);
664 static vpx_codec_err_t
ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t
*ctx
,
666 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
667 extra_cfg
.arnr_max_frames
= CAST(VP8E_SET_ARNR_MAXFRAMES
, args
);
668 return update_extra_cfg(ctx
, &extra_cfg
);
671 static vpx_codec_err_t
ctrl_set_arnr_strength(vpx_codec_alg_priv_t
*ctx
,
673 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
674 extra_cfg
.arnr_strength
= CAST(VP8E_SET_ARNR_STRENGTH
, args
);
675 return update_extra_cfg(ctx
, &extra_cfg
);
678 static vpx_codec_err_t
ctrl_set_arnr_type(vpx_codec_alg_priv_t
*ctx
,
685 static vpx_codec_err_t
ctrl_set_tuning(vpx_codec_alg_priv_t
*ctx
,
687 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
688 extra_cfg
.tuning
= CAST(VP8E_SET_TUNING
, args
);
689 return update_extra_cfg(ctx
, &extra_cfg
);
692 static vpx_codec_err_t
ctrl_set_cq_level(vpx_codec_alg_priv_t
*ctx
,
694 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
695 extra_cfg
.cq_level
= CAST(VP8E_SET_CQ_LEVEL
, args
);
696 return update_extra_cfg(ctx
, &extra_cfg
);
699 static vpx_codec_err_t
ctrl_set_rc_max_intra_bitrate_pct(
700 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
701 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
702 extra_cfg
.rc_max_intra_bitrate_pct
=
703 CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT
, args
);
704 return update_extra_cfg(ctx
, &extra_cfg
);
707 static vpx_codec_err_t
ctrl_set_rc_max_inter_bitrate_pct(
708 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
709 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
710 extra_cfg
.rc_max_inter_bitrate_pct
=
711 CAST(VP8E_SET_MAX_INTER_BITRATE_PCT
, args
);
712 return update_extra_cfg(ctx
, &extra_cfg
);
715 static vpx_codec_err_t
ctrl_set_rc_gf_cbr_boost_pct(
716 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
717 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
718 extra_cfg
.gf_cbr_boost_pct
=
719 CAST(VP9E_SET_GF_CBR_BOOST_PCT
, args
);
720 return update_extra_cfg(ctx
, &extra_cfg
);
723 static vpx_codec_err_t
ctrl_set_lossless(vpx_codec_alg_priv_t
*ctx
,
725 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
726 extra_cfg
.lossless
= CAST(VP9E_SET_LOSSLESS
, args
);
727 return update_extra_cfg(ctx
, &extra_cfg
);
730 static vpx_codec_err_t
ctrl_set_frame_parallel_decoding_mode(
731 vpx_codec_alg_priv_t
*ctx
, va_list args
) {
732 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
733 extra_cfg
.frame_parallel_decoding_mode
=
734 CAST(VP9E_SET_FRAME_PARALLEL_DECODING
, args
);
735 return update_extra_cfg(ctx
, &extra_cfg
);
738 static vpx_codec_err_t
ctrl_set_aq_mode(vpx_codec_alg_priv_t
*ctx
,
740 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
741 extra_cfg
.aq_mode
= CAST(VP9E_SET_AQ_MODE
, args
);
742 return update_extra_cfg(ctx
, &extra_cfg
);
745 static vpx_codec_err_t
ctrl_set_min_gf_interval(vpx_codec_alg_priv_t
*ctx
,
747 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
748 extra_cfg
.min_gf_interval
= CAST(VP9E_SET_MIN_GF_INTERVAL
, args
);
749 return update_extra_cfg(ctx
, &extra_cfg
);
752 static vpx_codec_err_t
ctrl_set_max_gf_interval(vpx_codec_alg_priv_t
*ctx
,
754 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
755 extra_cfg
.max_gf_interval
= CAST(VP9E_SET_MAX_GF_INTERVAL
, args
);
756 return update_extra_cfg(ctx
, &extra_cfg
);
759 static vpx_codec_err_t
ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t
*ctx
,
761 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
762 extra_cfg
.frame_periodic_boost
= CAST(VP9E_SET_FRAME_PERIODIC_BOOST
, args
);
763 return update_extra_cfg(ctx
, &extra_cfg
);
766 static vpx_codec_err_t
encoder_init(vpx_codec_ctx_t
*ctx
,
767 vpx_codec_priv_enc_mr_cfg_t
*data
) {
768 vpx_codec_err_t res
= VPX_CODEC_OK
;
771 if (ctx
->priv
== NULL
) {
772 vpx_codec_alg_priv_t
*const priv
= vpx_calloc(1, sizeof(*priv
));
774 return VPX_CODEC_MEM_ERROR
;
776 ctx
->priv
= (vpx_codec_priv_t
*)priv
;
777 ctx
->priv
->init_flags
= ctx
->init_flags
;
778 ctx
->priv
->enc
.total_encoders
= 1;
780 (BufferPool
*)vpx_calloc(1, sizeof(BufferPool
));
781 if (priv
->buffer_pool
== NULL
)
782 return VPX_CODEC_MEM_ERROR
;
784 #if CONFIG_MULTITHREAD
785 if (pthread_mutex_init(&priv
->buffer_pool
->pool_mutex
, NULL
)) {
786 return VPX_CODEC_MEM_ERROR
;
790 if (ctx
->config
.enc
) {
791 // Update the reference to the config structure to an internal copy.
792 priv
->cfg
= *ctx
->config
.enc
;
793 ctx
->config
.enc
= &priv
->cfg
;
796 priv
->extra_cfg
= default_extra_cfg
;
797 once(vp9_initialize_enc
);
799 res
= validate_config(priv
, &priv
->cfg
, &priv
->extra_cfg
);
801 if (res
== VPX_CODEC_OK
) {
802 set_encoder_config(&priv
->oxcf
, &priv
->cfg
, &priv
->extra_cfg
);
803 #if CONFIG_VP9_HIGHBITDEPTH
804 priv
->oxcf
.use_highbitdepth
=
805 (ctx
->init_flags
& VPX_CODEC_USE_HIGHBITDEPTH
) ? 1 : 0;
807 priv
->cpi
= vp9_create_compressor(&priv
->oxcf
, priv
->buffer_pool
);
808 if (priv
->cpi
== NULL
)
809 res
= VPX_CODEC_MEM_ERROR
;
811 priv
->cpi
->output_pkt_list
= &priv
->pkt_list
.head
;
818 static vpx_codec_err_t
encoder_destroy(vpx_codec_alg_priv_t
*ctx
) {
820 vp9_remove_compressor(ctx
->cpi
);
821 #if CONFIG_MULTITHREAD
822 pthread_mutex_destroy(&ctx
->buffer_pool
->pool_mutex
);
824 vpx_free(ctx
->buffer_pool
);
829 static void pick_quickcompress_mode(vpx_codec_alg_priv_t
*ctx
,
830 unsigned long duration
,
831 unsigned long deadline
) {
832 MODE new_mode
= BEST
;
834 switch (ctx
->cfg
.g_pass
) {
835 case VPX_RC_ONE_PASS
:
837 const vpx_codec_enc_cfg_t
*const cfg
= &ctx
->cfg
;
839 // Convert duration parameter from stream timebase to microseconds.
840 const uint64_t duration_us
= (uint64_t)duration
* 1000000 *
841 (uint64_t)cfg
->g_timebase
.num
/(uint64_t)cfg
->g_timebase
.den
;
843 // If the deadline is more that the duration this frame is to be shown,
844 // use good quality mode. Otherwise use realtime mode.
845 new_mode
= (deadline
> duration_us
) ? GOOD
: REALTIME
;
850 case VPX_RC_FIRST_PASS
:
852 case VPX_RC_LAST_PASS
:
853 new_mode
= deadline
> 0 ? GOOD
: BEST
;
857 if (ctx
->oxcf
.mode
!= new_mode
) {
858 ctx
->oxcf
.mode
= new_mode
;
859 vp9_change_config(ctx
->cpi
, &ctx
->oxcf
);
863 // Turn on to test if supplemental superframe data breaks decoding
864 // #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
865 static int write_superframe_index(vpx_codec_alg_priv_t
*ctx
) {
866 uint8_t marker
= 0xc0;
870 assert(ctx
->pending_frame_count
);
871 assert(ctx
->pending_frame_count
<= 8);
873 // Add the number of frames to the marker byte
874 marker
|= ctx
->pending_frame_count
- 1;
876 // Choose the magnitude
877 for (mag
= 0, mask
= 0xff; mag
< 4; mag
++) {
878 if (ctx
->pending_frame_magnitude
< mask
)
886 index_sz
= 2 + (mag
+ 1) * ctx
->pending_frame_count
;
887 if (ctx
->pending_cx_data_sz
+ index_sz
< ctx
->cx_data_sz
) {
888 uint8_t *x
= ctx
->pending_cx_data
+ ctx
->pending_cx_data_sz
;
890 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
891 uint8_t marker_test
= 0xc0;
892 int mag_test
= 2; // 1 - 4
893 int frames_test
= 4; // 1 - 8
894 int index_sz_test
= 2 + mag_test
* frames_test
;
895 marker_test
|= frames_test
- 1;
896 marker_test
|= (mag_test
- 1) << 3;
898 for (i
= 0; i
< mag_test
* frames_test
; ++i
)
899 *x
++ = 0; // fill up with arbitrary data
901 ctx
->pending_cx_data_sz
+= index_sz_test
;
902 printf("Added supplemental superframe data\n");
906 for (i
= 0; i
< ctx
->pending_frame_count
; i
++) {
907 unsigned int this_sz
= (unsigned int)ctx
->pending_frame_sizes
[i
];
909 for (j
= 0; j
<= mag
; j
++) {
910 *x
++ = this_sz
& 0xff;
915 ctx
->pending_cx_data_sz
+= index_sz
;
916 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
917 index_sz
+= index_sz_test
;
923 // vp9 uses 10,000,000 ticks/second as time stamp
924 #define TICKS_PER_SEC 10000000LL
926 static int64_t timebase_units_to_ticks(const vpx_rational_t
*timebase
,
928 return n
* TICKS_PER_SEC
* timebase
->num
/ timebase
->den
;
931 static int64_t ticks_to_timebase_units(const vpx_rational_t
*timebase
,
933 const int64_t round
= TICKS_PER_SEC
* timebase
->num
/ 2 - 1;
934 return (n
* timebase
->den
+ round
) / timebase
->num
/ TICKS_PER_SEC
;
937 static vpx_codec_frame_flags_t
get_frame_pkt_flags(const VP9_COMP
*cpi
,
938 unsigned int lib_flags
) {
939 vpx_codec_frame_flags_t flags
= lib_flags
<< 16;
941 if (lib_flags
& FRAMEFLAGS_KEY
||
943 cpi
->svc
.layer_context
[cpi
->svc
.spatial_layer_id
*
944 cpi
->svc
.number_temporal_layers
+
945 cpi
->svc
.temporal_layer_id
].is_key_frame
)
947 flags
|= VPX_FRAME_IS_KEY
;
950 flags
|= VPX_FRAME_IS_DROPPABLE
;
955 static vpx_codec_err_t
encoder_encode(vpx_codec_alg_priv_t
*ctx
,
956 const vpx_image_t
*img
,
958 unsigned long duration
,
959 vpx_enc_frame_flags_t flags
,
960 unsigned long deadline
) {
961 vpx_codec_err_t res
= VPX_CODEC_OK
;
962 VP9_COMP
*const cpi
= ctx
->cpi
;
963 const vpx_rational_t
*const timebase
= &ctx
->cfg
.g_timebase
;
967 res
= validate_img(ctx
, img
);
968 // TODO(jzern) the checks related to cpi's validity should be treated as a
969 // failure condition, encoder setup is done fully in init() currently.
970 if (res
== VPX_CODEC_OK
&& cpi
!= NULL
) {
971 // There's no codec control for multiple alt-refs so check the encoder
972 // instance for its status to determine the compressed data size.
973 data_sz
= ctx
->cfg
.g_w
* ctx
->cfg
.g_h
* get_image_bps(img
) / 8 *
974 (cpi
->multi_arf_allowed
? 8 : 2);
977 if (ctx
->cx_data
== NULL
|| ctx
->cx_data_sz
< data_sz
) {
978 ctx
->cx_data_sz
= data_sz
;
980 ctx
->cx_data
= (unsigned char*)malloc(ctx
->cx_data_sz
);
981 if (ctx
->cx_data
== NULL
) {
982 return VPX_CODEC_MEM_ERROR
;
988 pick_quickcompress_mode(ctx
, duration
, deadline
);
989 vpx_codec_pkt_list_init(&ctx
->pkt_list
);
992 if (((flags
& VP8_EFLAG_NO_UPD_GF
) && (flags
& VP8_EFLAG_FORCE_GF
)) ||
993 ((flags
& VP8_EFLAG_NO_UPD_ARF
) && (flags
& VP8_EFLAG_FORCE_ARF
))) {
994 ctx
->base
.err_detail
= "Conflicting flags.";
995 return VPX_CODEC_INVALID_PARAM
;
998 vp9_apply_encoding_flags(cpi
, flags
);
1000 // Handle fixed keyframe intervals
1001 if (ctx
->cfg
.kf_mode
== VPX_KF_AUTO
&&
1002 ctx
->cfg
.kf_min_dist
== ctx
->cfg
.kf_max_dist
) {
1003 if (++ctx
->fixed_kf_cntr
> ctx
->cfg
.kf_min_dist
) {
1004 flags
|= VPX_EFLAG_FORCE_KF
;
1005 ctx
->fixed_kf_cntr
= 1;
1009 // Initialize the encoder instance on the first frame.
1010 if (res
== VPX_CODEC_OK
&& cpi
!= NULL
) {
1011 unsigned int lib_flags
= 0;
1012 YV12_BUFFER_CONFIG sd
;
1013 int64_t dst_time_stamp
= timebase_units_to_ticks(timebase
, pts
);
1014 int64_t dst_end_time_stamp
=
1015 timebase_units_to_ticks(timebase
, pts
+ duration
);
1016 size_t size
, cx_data_sz
;
1017 unsigned char *cx_data
;
1019 // Set up internal flags
1020 if (ctx
->base
.init_flags
& VPX_CODEC_USE_PSNR
)
1021 cpi
->b_calculate_psnr
= 1;
1024 res
= image2yuvconfig(img
, &sd
);
1026 // Store the original flags in to the frame buffer. Will extract the
1027 // key frame flag when we actually encode this frame.
1028 if (vp9_receive_raw_frame(cpi
, flags
| ctx
->next_frame_flags
,
1029 &sd
, dst_time_stamp
, dst_end_time_stamp
)) {
1030 res
= update_error_state(ctx
, &cpi
->common
.error
);
1032 ctx
->next_frame_flags
= 0;
1035 cx_data
= ctx
->cx_data
;
1036 cx_data_sz
= ctx
->cx_data_sz
;
1038 /* Any pending invisible frames? */
1039 if (ctx
->pending_cx_data
) {
1040 memmove(cx_data
, ctx
->pending_cx_data
, ctx
->pending_cx_data_sz
);
1041 ctx
->pending_cx_data
= cx_data
;
1042 cx_data
+= ctx
->pending_cx_data_sz
;
1043 cx_data_sz
-= ctx
->pending_cx_data_sz
;
1045 /* TODO: this is a minimal check, the underlying codec doesn't respect
1046 * the buffer size anyway.
1048 if (cx_data_sz
< ctx
->cx_data_sz
/ 2) {
1049 ctx
->base
.err_detail
= "Compressed data buffer too small";
1050 return VPX_CODEC_ERROR
;
1054 while (cx_data_sz
>= ctx
->cx_data_sz
/ 2 &&
1055 -1 != vp9_get_compressed_data(cpi
, &lib_flags
, &size
,
1056 cx_data
, &dst_time_stamp
,
1057 &dst_end_time_stamp
, !img
)) {
1059 vpx_codec_cx_pkt_t pkt
;
1061 #if CONFIG_SPATIAL_SVC
1063 cpi
->svc
.layer_context
[cpi
->svc
.spatial_layer_id
*
1064 cpi
->svc
.number_temporal_layers
].layer_size
+= size
;
1067 // Pack invisible frames with the next visible frame
1068 if (!cpi
->common
.show_frame
||
1070 cpi
->svc
.spatial_layer_id
< cpi
->svc
.number_spatial_layers
- 1)
1072 if (ctx
->pending_cx_data
== 0)
1073 ctx
->pending_cx_data
= cx_data
;
1074 ctx
->pending_cx_data_sz
+= size
;
1075 ctx
->pending_frame_sizes
[ctx
->pending_frame_count
++] = size
;
1076 ctx
->pending_frame_magnitude
|= size
;
1080 if (ctx
->output_cx_pkt_cb
.output_cx_pkt
) {
1081 pkt
.kind
= VPX_CODEC_CX_FRAME_PKT
;
1082 pkt
.data
.frame
.pts
= ticks_to_timebase_units(timebase
,
1084 pkt
.data
.frame
.duration
=
1085 (unsigned long)ticks_to_timebase_units(timebase
,
1086 dst_end_time_stamp
- dst_time_stamp
);
1087 pkt
.data
.frame
.flags
= get_frame_pkt_flags(cpi
, lib_flags
);
1088 pkt
.data
.frame
.buf
= ctx
->pending_cx_data
;
1089 pkt
.data
.frame
.sz
= size
;
1090 ctx
->pending_cx_data
= NULL
;
1091 ctx
->pending_cx_data_sz
= 0;
1092 ctx
->pending_frame_count
= 0;
1093 ctx
->pending_frame_magnitude
= 0;
1094 ctx
->output_cx_pkt_cb
.output_cx_pkt(
1095 &pkt
, ctx
->output_cx_pkt_cb
.user_priv
);
1100 // Add the frame packet to the list of returned packets.
1101 pkt
.kind
= VPX_CODEC_CX_FRAME_PKT
;
1102 pkt
.data
.frame
.pts
= ticks_to_timebase_units(timebase
, dst_time_stamp
);
1103 pkt
.data
.frame
.duration
=
1104 (unsigned long)ticks_to_timebase_units(timebase
,
1105 dst_end_time_stamp
- dst_time_stamp
);
1106 pkt
.data
.frame
.flags
= get_frame_pkt_flags(cpi
, lib_flags
);
1108 if (ctx
->pending_cx_data
) {
1109 ctx
->pending_frame_sizes
[ctx
->pending_frame_count
++] = size
;
1110 ctx
->pending_frame_magnitude
|= size
;
1111 ctx
->pending_cx_data_sz
+= size
;
1112 // write the superframe only for the case when
1113 if (!ctx
->output_cx_pkt_cb
.output_cx_pkt
)
1114 size
+= write_superframe_index(ctx
);
1115 pkt
.data
.frame
.buf
= ctx
->pending_cx_data
;
1116 pkt
.data
.frame
.sz
= ctx
->pending_cx_data_sz
;
1117 ctx
->pending_cx_data
= NULL
;
1118 ctx
->pending_cx_data_sz
= 0;
1119 ctx
->pending_frame_count
= 0;
1120 ctx
->pending_frame_magnitude
= 0;
1122 pkt
.data
.frame
.buf
= cx_data
;
1123 pkt
.data
.frame
.sz
= size
;
1125 pkt
.data
.frame
.partition_id
= -1;
1127 if(ctx
->output_cx_pkt_cb
.output_cx_pkt
)
1128 ctx
->output_cx_pkt_cb
.output_cx_pkt(&pkt
,
1129 ctx
->output_cx_pkt_cb
.user_priv
);
1131 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt
);
1135 #if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
1136 #if CONFIG_SPATIAL_SVC
1137 if (cpi
->use_svc
&& !ctx
->output_cx_pkt_cb
.output_cx_pkt
) {
1138 vpx_codec_cx_pkt_t pkt_sizes
, pkt_psnr
;
1140 vp9_zero(pkt_sizes
);
1142 pkt_sizes
.kind
= VPX_CODEC_SPATIAL_SVC_LAYER_SIZES
;
1143 pkt_psnr
.kind
= VPX_CODEC_SPATIAL_SVC_LAYER_PSNR
;
1144 for (sl
= 0; sl
< cpi
->svc
.number_spatial_layers
; ++sl
) {
1146 &cpi
->svc
.layer_context
[sl
* cpi
->svc
.number_temporal_layers
];
1147 pkt_sizes
.data
.layer_sizes
[sl
] = lc
->layer_size
;
1148 pkt_psnr
.data
.layer_psnr
[sl
] = lc
->psnr_pkt
;
1152 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt_sizes
);
1154 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt_psnr
);
1158 if (is_one_pass_cbr_svc(cpi
) &&
1159 (cpi
->svc
.spatial_layer_id
== cpi
->svc
.number_spatial_layers
- 1)) {
1160 // Encoded all spatial layers; exit loop.
1170 static const vpx_codec_cx_pkt_t
*encoder_get_cxdata(vpx_codec_alg_priv_t
*ctx
,
1171 vpx_codec_iter_t
*iter
) {
1172 return vpx_codec_pkt_list_get(&ctx
->pkt_list
.head
, iter
);
1175 static vpx_codec_err_t
ctrl_set_reference(vpx_codec_alg_priv_t
*ctx
,
1177 vpx_ref_frame_t
*const frame
= va_arg(args
, vpx_ref_frame_t
*);
1179 if (frame
!= NULL
) {
1180 YV12_BUFFER_CONFIG sd
;
1182 image2yuvconfig(&frame
->img
, &sd
);
1183 vp9_set_reference_enc(ctx
->cpi
, ref_frame_to_vp9_reframe(frame
->frame_type
),
1185 return VPX_CODEC_OK
;
1187 return VPX_CODEC_INVALID_PARAM
;
1191 static vpx_codec_err_t
ctrl_copy_reference(vpx_codec_alg_priv_t
*ctx
,
1193 vpx_ref_frame_t
*const frame
= va_arg(args
, vpx_ref_frame_t
*);
1195 if (frame
!= NULL
) {
1196 YV12_BUFFER_CONFIG sd
;
1198 image2yuvconfig(&frame
->img
, &sd
);
1199 vp9_copy_reference_enc(ctx
->cpi
,
1200 ref_frame_to_vp9_reframe(frame
->frame_type
), &sd
);
1201 return VPX_CODEC_OK
;
1203 return VPX_CODEC_INVALID_PARAM
;
1207 static vpx_codec_err_t
ctrl_get_reference(vpx_codec_alg_priv_t
*ctx
,
1209 vp9_ref_frame_t
*const frame
= va_arg(args
, vp9_ref_frame_t
*);
1211 if (frame
!= NULL
) {
1212 YV12_BUFFER_CONFIG
*fb
= get_ref_frame(&ctx
->cpi
->common
, frame
->idx
);
1213 if (fb
== NULL
) return VPX_CODEC_ERROR
;
1215 yuvconfig2image(&frame
->img
, fb
, NULL
);
1216 return VPX_CODEC_OK
;
1218 return VPX_CODEC_INVALID_PARAM
;
1222 static vpx_codec_err_t
ctrl_set_previewpp(vpx_codec_alg_priv_t
*ctx
,
1224 #if CONFIG_VP9_POSTPROC
1225 vp8_postproc_cfg_t
*config
= va_arg(args
, vp8_postproc_cfg_t
*);
1226 if (config
!= NULL
) {
1227 ctx
->preview_ppcfg
= *config
;
1228 return VPX_CODEC_OK
;
1230 return VPX_CODEC_INVALID_PARAM
;
1235 return VPX_CODEC_INCAPABLE
;
1240 static vpx_image_t
*encoder_get_preview(vpx_codec_alg_priv_t
*ctx
) {
1241 YV12_BUFFER_CONFIG sd
;
1242 vp9_ppflags_t flags
;
1245 if (ctx
->preview_ppcfg
.post_proc_flag
) {
1246 flags
.post_proc_flag
= ctx
->preview_ppcfg
.post_proc_flag
;
1247 flags
.deblocking_level
= ctx
->preview_ppcfg
.deblocking_level
;
1248 flags
.noise_level
= ctx
->preview_ppcfg
.noise_level
;
1251 if (vp9_get_preview_raw_frame(ctx
->cpi
, &sd
, &flags
) == 0) {
1252 yuvconfig2image(&ctx
->preview_img
, &sd
, NULL
);
1253 return &ctx
->preview_img
;
1259 static vpx_codec_err_t
ctrl_update_entropy(vpx_codec_alg_priv_t
*ctx
,
1261 const int update
= va_arg(args
, int);
1263 vp9_update_entropy(ctx
->cpi
, update
);
1264 return VPX_CODEC_OK
;
1267 static vpx_codec_err_t
ctrl_update_reference(vpx_codec_alg_priv_t
*ctx
,
1269 const int ref_frame_flags
= va_arg(args
, int);
1271 vp9_update_reference(ctx
->cpi
, ref_frame_flags
);
1272 return VPX_CODEC_OK
;
1275 static vpx_codec_err_t
ctrl_use_reference(vpx_codec_alg_priv_t
*ctx
,
1277 const int reference_flag
= va_arg(args
, int);
1279 vp9_use_as_reference(ctx
->cpi
, reference_flag
);
1280 return VPX_CODEC_OK
;
1283 static vpx_codec_err_t
ctrl_set_roi_map(vpx_codec_alg_priv_t
*ctx
,
1288 // TODO(yaowu): Need to re-implement and test for VP9.
1289 return VPX_CODEC_INVALID_PARAM
;
1293 static vpx_codec_err_t
ctrl_set_active_map(vpx_codec_alg_priv_t
*ctx
,
1295 vpx_active_map_t
*const map
= va_arg(args
, vpx_active_map_t
*);
1298 if (!vp9_set_active_map(ctx
->cpi
, map
->active_map
,
1299 (int)map
->rows
, (int)map
->cols
))
1300 return VPX_CODEC_OK
;
1302 return VPX_CODEC_INVALID_PARAM
;
1304 return VPX_CODEC_INVALID_PARAM
;
1308 static vpx_codec_err_t
ctrl_get_active_map(vpx_codec_alg_priv_t
*ctx
,
1310 vpx_active_map_t
*const map
= va_arg(args
, vpx_active_map_t
*);
1313 if (!vp9_get_active_map(ctx
->cpi
, map
->active_map
,
1314 (int)map
->rows
, (int)map
->cols
))
1315 return VPX_CODEC_OK
;
1317 return VPX_CODEC_INVALID_PARAM
;
1319 return VPX_CODEC_INVALID_PARAM
;
1323 static vpx_codec_err_t
ctrl_set_scale_mode(vpx_codec_alg_priv_t
*ctx
,
1325 vpx_scaling_mode_t
*const mode
= va_arg(args
, vpx_scaling_mode_t
*);
1328 const int res
= vp9_set_internal_size(ctx
->cpi
,
1329 (VPX_SCALING
)mode
->h_scaling_mode
,
1330 (VPX_SCALING
)mode
->v_scaling_mode
);
1331 return (res
== 0) ? VPX_CODEC_OK
: VPX_CODEC_INVALID_PARAM
;
1333 return VPX_CODEC_INVALID_PARAM
;
1337 static vpx_codec_err_t
ctrl_set_svc(vpx_codec_alg_priv_t
*ctx
, va_list args
) {
1338 int data
= va_arg(args
, int);
1339 const vpx_codec_enc_cfg_t
*cfg
= &ctx
->cfg
;
1340 // Both one-pass and two-pass RC are supported now.
1341 // User setting this has to make sure of the following.
1342 // In two-pass setting: either (but not both)
1343 // cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
1344 // In one-pass setting:
1345 // either or both cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
1347 vp9_set_svc(ctx
->cpi
, data
);
1350 (cfg
->g_pass
== VPX_RC_FIRST_PASS
||
1351 cfg
->g_pass
== VPX_RC_LAST_PASS
) &&
1352 cfg
->ss_number_layers
> 1 &&
1353 cfg
->ts_number_layers
> 1) {
1354 return VPX_CODEC_INVALID_PARAM
;
1356 return VPX_CODEC_OK
;
1359 static vpx_codec_err_t
ctrl_set_svc_layer_id(vpx_codec_alg_priv_t
*ctx
,
1361 vpx_svc_layer_id_t
*const data
= va_arg(args
, vpx_svc_layer_id_t
*);
1362 VP9_COMP
*const cpi
= (VP9_COMP
*)ctx
->cpi
;
1363 SVC
*const svc
= &cpi
->svc
;
1365 svc
->spatial_layer_id
= data
->spatial_layer_id
;
1366 svc
->temporal_layer_id
= data
->temporal_layer_id
;
1367 // Checks on valid layer_id input.
1368 if (svc
->temporal_layer_id
< 0 ||
1369 svc
->temporal_layer_id
>= (int)ctx
->cfg
.ts_number_layers
) {
1370 return VPX_CODEC_INVALID_PARAM
;
1372 if (svc
->spatial_layer_id
< 0 ||
1373 svc
->spatial_layer_id
>= (int)ctx
->cfg
.ss_number_layers
) {
1374 return VPX_CODEC_INVALID_PARAM
;
1376 return VPX_CODEC_OK
;
1379 static vpx_codec_err_t
ctrl_get_svc_layer_id(vpx_codec_alg_priv_t
*ctx
,
1381 vpx_svc_layer_id_t
*data
= va_arg(args
, vpx_svc_layer_id_t
*);
1382 VP9_COMP
*const cpi
= (VP9_COMP
*)ctx
->cpi
;
1383 SVC
*const svc
= &cpi
->svc
;
1385 data
->spatial_layer_id
= svc
->spatial_layer_id
;
1386 data
->temporal_layer_id
= svc
->temporal_layer_id
;
1388 return VPX_CODEC_OK
;
1391 static vpx_codec_err_t
ctrl_set_svc_parameters(vpx_codec_alg_priv_t
*ctx
,
1393 VP9_COMP
*const cpi
= ctx
->cpi
;
1394 vpx_svc_extra_cfg_t
*const params
= va_arg(args
, vpx_svc_extra_cfg_t
*);
1397 // Number of temporal layers and number of spatial layers have to be set
1398 // properly before calling this control function.
1399 for (sl
= 0; sl
< cpi
->svc
.number_spatial_layers
; ++sl
) {
1400 for (tl
= 0; tl
< cpi
->svc
.number_temporal_layers
; ++tl
) {
1402 LAYER_IDS_TO_IDX(sl
, tl
, cpi
->svc
.number_temporal_layers
);
1404 &cpi
->svc
.layer_context
[layer
];
1405 lc
->max_q
= params
->max_quantizers
[sl
];
1406 lc
->min_q
= params
->min_quantizers
[sl
];
1407 lc
->scaling_factor_num
= params
->scaling_factor_num
[sl
];
1408 lc
->scaling_factor_den
= params
->scaling_factor_den
[sl
];
1412 return VPX_CODEC_OK
;
1415 static vpx_codec_err_t
ctrl_register_cx_callback(vpx_codec_alg_priv_t
*ctx
,
1417 vpx_codec_priv_output_cx_pkt_cb_pair_t
*cbp
=
1418 (vpx_codec_priv_output_cx_pkt_cb_pair_t
*)va_arg(args
, void *);
1419 ctx
->output_cx_pkt_cb
.output_cx_pkt
= cbp
->output_cx_pkt
;
1420 ctx
->output_cx_pkt_cb
.user_priv
= cbp
->user_priv
;
1422 return VPX_CODEC_OK
;
1425 static vpx_codec_err_t
ctrl_set_tune_content(vpx_codec_alg_priv_t
*ctx
,
1427 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
1428 extra_cfg
.content
= CAST(VP9E_SET_TUNE_CONTENT
, args
);
1429 return update_extra_cfg(ctx
, &extra_cfg
);
1432 static vpx_codec_err_t
ctrl_set_color_space(vpx_codec_alg_priv_t
*ctx
,
1434 struct vp9_extracfg extra_cfg
= ctx
->extra_cfg
;
1435 extra_cfg
.color_space
= CAST(VP9E_SET_COLOR_SPACE
, args
);
1436 return update_extra_cfg(ctx
, &extra_cfg
);
1439 static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps
[] = {
1440 {VP8_COPY_REFERENCE
, ctrl_copy_reference
},
1441 {VP8E_UPD_ENTROPY
, ctrl_update_entropy
},
1442 {VP8E_UPD_REFERENCE
, ctrl_update_reference
},
1443 {VP8E_USE_REFERENCE
, ctrl_use_reference
},
1446 {VP8_SET_REFERENCE
, ctrl_set_reference
},
1447 {VP8_SET_POSTPROC
, ctrl_set_previewpp
},
1448 {VP8E_SET_ROI_MAP
, ctrl_set_roi_map
},
1449 {VP8E_SET_ACTIVEMAP
, ctrl_set_active_map
},
1450 {VP8E_SET_SCALEMODE
, ctrl_set_scale_mode
},
1451 {VP8E_SET_CPUUSED
, ctrl_set_cpuused
},
1452 {VP8E_SET_ENABLEAUTOALTREF
, ctrl_set_enable_auto_alt_ref
},
1453 {VP8E_SET_SHARPNESS
, ctrl_set_sharpness
},
1454 {VP8E_SET_STATIC_THRESHOLD
, ctrl_set_static_thresh
},
1455 {VP9E_SET_TILE_COLUMNS
, ctrl_set_tile_columns
},
1456 {VP9E_SET_TILE_ROWS
, ctrl_set_tile_rows
},
1457 {VP8E_SET_ARNR_MAXFRAMES
, ctrl_set_arnr_max_frames
},
1458 {VP8E_SET_ARNR_STRENGTH
, ctrl_set_arnr_strength
},
1459 {VP8E_SET_ARNR_TYPE
, ctrl_set_arnr_type
},
1460 {VP8E_SET_TUNING
, ctrl_set_tuning
},
1461 {VP8E_SET_CQ_LEVEL
, ctrl_set_cq_level
},
1462 {VP8E_SET_MAX_INTRA_BITRATE_PCT
, ctrl_set_rc_max_intra_bitrate_pct
},
1463 {VP9E_SET_MAX_INTER_BITRATE_PCT
, ctrl_set_rc_max_inter_bitrate_pct
},
1464 {VP9E_SET_GF_CBR_BOOST_PCT
, ctrl_set_rc_gf_cbr_boost_pct
},
1465 {VP9E_SET_LOSSLESS
, ctrl_set_lossless
},
1466 {VP9E_SET_FRAME_PARALLEL_DECODING
, ctrl_set_frame_parallel_decoding_mode
},
1467 {VP9E_SET_AQ_MODE
, ctrl_set_aq_mode
},
1468 {VP9E_SET_FRAME_PERIODIC_BOOST
, ctrl_set_frame_periodic_boost
},
1469 {VP9E_SET_SVC
, ctrl_set_svc
},
1470 {VP9E_SET_SVC_PARAMETERS
, ctrl_set_svc_parameters
},
1471 {VP9E_REGISTER_CX_CALLBACK
, ctrl_register_cx_callback
},
1472 {VP9E_SET_SVC_LAYER_ID
, ctrl_set_svc_layer_id
},
1473 {VP9E_SET_TUNE_CONTENT
, ctrl_set_tune_content
},
1474 {VP9E_SET_COLOR_SPACE
, ctrl_set_color_space
},
1475 {VP9E_SET_NOISE_SENSITIVITY
, ctrl_set_noise_sensitivity
},
1476 {VP9E_SET_MIN_GF_INTERVAL
, ctrl_set_min_gf_interval
},
1477 {VP9E_SET_MAX_GF_INTERVAL
, ctrl_set_max_gf_interval
},
1480 {VP8E_GET_LAST_QUANTIZER
, ctrl_get_quantizer
},
1481 {VP8E_GET_LAST_QUANTIZER_64
, ctrl_get_quantizer64
},
1482 {VP9_GET_REFERENCE
, ctrl_get_reference
},
1483 {VP9E_GET_SVC_LAYER_ID
, ctrl_get_svc_layer_id
},
1484 {VP9E_GET_ACTIVEMAP
, ctrl_get_active_map
},
1489 static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map
[] = {
1499 VPX_BITS_8
, // g_bit_depth
1500 8, // g_input_bit_depth
1502 {1, 30}, // g_timebase
1504 0, // g_error_resilient
1506 VPX_RC_ONE_PASS
, // g_pass
1508 25, // g_lag_in_frames
1510 0, // rc_dropframe_thresh
1511 0, // rc_resize_allowed
1512 0, // rc_scaled_width
1513 0, // rc_scaled_height
1514 60, // rc_resize_down_thresold
1515 30, // rc_resize_up_thresold
1517 VPX_VBR
, // rc_end_usage
1518 {NULL
, 0}, // rc_twopass_stats_in
1519 {NULL
, 0}, // rc_firstpass_mb_stats_in
1520 256, // rc_target_bandwidth
1521 0, // rc_min_quantizer
1522 63, // rc_max_quantizer
1523 25, // rc_undershoot_pct
1524 25, // rc_overshoot_pct
1526 6000, // rc_max_buffer_size
1527 4000, // rc_buffer_initial_size
1528 5000, // rc_buffer_optimal_size
1530 50, // rc_two_pass_vbrbias
1531 0, // rc_two_pass_vbrmin_section
1532 2000, // rc_two_pass_vbrmax_section
1534 // keyframing settings (kf)
1535 VPX_KF_AUTO
, // g_kfmode
1537 9999, // kf_max_dist
1539 VPX_SS_DEFAULT_LAYERS
, // ss_number_layers
1541 {0}, // ss_target_bitrate
1542 1, // ts_number_layers
1543 {0}, // ts_target_bitrate
1544 {0}, // ts_rate_decimator
1545 0, // ts_periodicity
1547 {0}, // layer_taget_bitrate
1548 0 // temporal_layering_mode
1553 #ifndef VERSION_STRING
1554 #define VERSION_STRING
1556 CODEC_INTERFACE(vpx_codec_vp9_cx
) = {
1557 "WebM Project VP9 Encoder" VERSION_STRING
,
1558 VPX_CODEC_INTERNAL_ABI_VERSION
,
1559 #if CONFIG_VP9_HIGHBITDEPTH
1560 VPX_CODEC_CAP_HIGHBITDEPTH
|
1562 VPX_CODEC_CAP_ENCODER
| VPX_CODEC_CAP_PSNR
, // vpx_codec_caps_t
1563 encoder_init
, // vpx_codec_init_fn_t
1564 encoder_destroy
, // vpx_codec_destroy_fn_t
1565 encoder_ctrl_maps
, // vpx_codec_ctrl_fn_map_t
1567 NULL
, // vpx_codec_peek_si_fn_t
1568 NULL
, // vpx_codec_get_si_fn_t
1569 NULL
, // vpx_codec_decode_fn_t
1570 NULL
, // vpx_codec_frame_get_fn_t
1571 NULL
// vpx_codec_set_fb_fn_t
1575 encoder_usage_cfg_map
, // vpx_codec_enc_cfg_map_t
1576 encoder_encode
, // vpx_codec_encode_fn_t
1577 encoder_get_cxdata
, // vpx_codec_get_cx_data_fn_t
1578 encoder_set_config
, // vpx_codec_enc_config_set_fn_t
1579 NULL
, // vpx_codec_get_global_headers_fn_t
1580 encoder_get_preview
, // vpx_codec_get_preview_frame_fn_t
1581 NULL
// vpx_codec_enc_mr_get_mem_loc_fn_t