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/vpx_codec.h"
13 #include "vpx/internal/vpx_codec_internal.h"
14 #include "vpx_version.h"
15 #include "vp9/encoder/vp9_onyx_int.h"
16 #include "vpx/vp8cx.h"
17 #include "vp9/encoder/vp9_firstpass.h"
18 #include "vp9/common/vp9_onyx.h"
19 #include "vp9/vp9_iface_common.h"
24 struct vpx_codec_pkt_list
*pkt_list
;
25 int cpu_used
; /** available cpu percentage in 1/16*/
26 unsigned int enable_auto_alt_ref
; /** if encoder decides to uses alternate reference frame */
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
; /* alt_ref Noise Reduction Max Frame Count */
33 unsigned int arnr_strength
; /* alt_ref Noise Reduction Strength */
34 unsigned int arnr_type
; /* alt_ref filter type */
35 unsigned int experimental
;
37 unsigned int cq_level
; /* constrained quality level */
38 unsigned int rc_max_intra_bitrate_pct
;
39 unsigned int lossless
;
40 unsigned int frame_parallel_decoding_mode
;
43 struct extraconfig_map
{
45 struct vp9_extracfg cfg
;
48 static const struct extraconfig_map extracfg_map
[] = {
54 0, /* enable_auto_alt_ref */
55 0, /* noise_sensitivity */
57 0, /* static_thresh */
60 0, /* arnr_max_frames */
61 3, /* arnr_strength */
63 0, /* experimental mode */
66 0, /* rc_max_intra_bitrate_pct */
68 0, /* frame_parallel_decoding_mode */
73 struct vpx_codec_alg_priv
{
74 vpx_codec_priv_t base
;
75 vpx_codec_enc_cfg_t cfg
;
76 struct vp9_extracfg vp8_cfg
;
79 unsigned char *cx_data
;
80 unsigned int cx_data_sz
;
81 unsigned char *pending_cx_data
;
82 unsigned int pending_cx_data_sz
;
83 int pending_frame_count
;
84 uint32_t pending_frame_sizes
[8];
85 uint32_t pending_frame_magnitude
;
86 vpx_image_t preview_img
;
87 vp8_postproc_cfg_t preview_ppcfg
;
88 vpx_codec_pkt_list_decl(64) pkt_list
; // changed to accomendate the maximum number of lagged frames allowed
89 unsigned int fixed_kf_cntr
;
93 static vpx_codec_err_t
94 update_error_state(vpx_codec_alg_priv_t
*ctx
,
95 const struct vpx_internal_error_info
*error
) {
98 if ((res
= error
->error_code
))
99 ctx
->base
.err_detail
= error
->has_detail
108 #define ERROR(str) do {\
109 ctx->base.err_detail = str;\
110 return VPX_CODEC_INVALID_PARAM;\
113 #define RANGE_CHECK(p,memb,lo,hi) do {\
114 if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
115 ERROR(#memb " out of range ["#lo".."#hi"]");\
118 #define RANGE_CHECK_HI(p,memb,hi) do {\
119 if(!((p)->memb <= (hi))) \
120 ERROR(#memb " out of range [.."#hi"]");\
123 #define RANGE_CHECK_LO(p,memb,lo) do {\
124 if(!((p)->memb >= (lo))) \
125 ERROR(#memb " out of range ["#lo"..]");\
128 #define RANGE_CHECK_BOOL(p,memb) do {\
129 if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
132 static vpx_codec_err_t
validate_config(vpx_codec_alg_priv_t
*ctx
,
133 const vpx_codec_enc_cfg_t
*cfg
,
134 const struct vp9_extracfg
*vp8_cfg
) {
135 RANGE_CHECK(cfg
, g_w
, 1, 65535); /* 16 bits available */
136 RANGE_CHECK(cfg
, g_h
, 1, 65535); /* 16 bits available */
137 RANGE_CHECK(cfg
, g_timebase
.den
, 1, 1000000000);
138 RANGE_CHECK(cfg
, g_timebase
.num
, 1, cfg
->g_timebase
.den
);
139 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_BOOL(vp8_cfg
, lossless
);
144 if (vp8_cfg
->lossless
) {
145 RANGE_CHECK_HI(cfg
, rc_max_quantizer
, 0);
146 RANGE_CHECK_HI(cfg
, rc_min_quantizer
, 0);
149 RANGE_CHECK_HI(cfg
, g_threads
, 64);
150 RANGE_CHECK_HI(cfg
, g_lag_in_frames
, MAX_LAG_BUFFERS
);
151 RANGE_CHECK(cfg
, rc_end_usage
, VPX_VBR
, VPX_CQ
);
152 RANGE_CHECK_HI(cfg
, rc_undershoot_pct
, 1000);
153 RANGE_CHECK_HI(cfg
, rc_overshoot_pct
, 1000);
154 RANGE_CHECK_HI(cfg
, rc_2pass_vbr_bias_pct
, 100);
155 RANGE_CHECK(cfg
, kf_mode
, VPX_KF_DISABLED
, VPX_KF_AUTO
);
156 // RANGE_CHECK_BOOL(cfg, g_delete_firstpassfile);
157 RANGE_CHECK_BOOL(cfg
, rc_resize_allowed
);
158 RANGE_CHECK_HI(cfg
, rc_dropframe_thresh
, 100);
159 RANGE_CHECK_HI(cfg
, rc_resize_up_thresh
, 100);
160 RANGE_CHECK_HI(cfg
, rc_resize_down_thresh
, 100);
161 RANGE_CHECK(cfg
, g_pass
, VPX_RC_ONE_PASS
, VPX_RC_LAST_PASS
);
163 /* VP8 does not support a lower bound on the keyframe interval in
164 * automatic keyframe placement mode.
166 if (cfg
->kf_mode
!= VPX_KF_DISABLED
&& cfg
->kf_min_dist
!= cfg
->kf_max_dist
167 && cfg
->kf_min_dist
> 0)
168 ERROR("kf_min_dist not supported in auto mode, use 0 "
169 "or kf_max_dist instead.");
171 RANGE_CHECK_BOOL(vp8_cfg
, enable_auto_alt_ref
);
172 RANGE_CHECK(vp8_cfg
, cpu_used
, -16, 16);
174 RANGE_CHECK_HI(vp8_cfg
, noise_sensitivity
, 6);
176 RANGE_CHECK(vp8_cfg
, tile_columns
, 0, 6);
177 RANGE_CHECK(vp8_cfg
, tile_rows
, 0, 2);
178 RANGE_CHECK_HI(vp8_cfg
, Sharpness
, 7);
179 RANGE_CHECK(vp8_cfg
, arnr_max_frames
, 0, 15);
180 RANGE_CHECK_HI(vp8_cfg
, arnr_strength
, 6);
181 RANGE_CHECK(vp8_cfg
, arnr_type
, 1, 3);
182 RANGE_CHECK(vp8_cfg
, cq_level
, 0, 63);
184 if (cfg
->g_pass
== VPX_RC_LAST_PASS
) {
185 size_t packet_sz
= sizeof(FIRSTPASS_STATS
);
186 int n_packets
= (int)(cfg
->rc_twopass_stats_in
.sz
/ packet_sz
);
187 FIRSTPASS_STATS
*stats
;
189 if (!cfg
->rc_twopass_stats_in
.buf
)
190 ERROR("rc_twopass_stats_in.buf not set.");
192 if (cfg
->rc_twopass_stats_in
.sz
% packet_sz
)
193 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
195 if (cfg
->rc_twopass_stats_in
.sz
< 2 * packet_sz
)
196 ERROR("rc_twopass_stats_in requires at least two packets.");
198 stats
= (void *)((char *)cfg
->rc_twopass_stats_in
.buf
199 + (n_packets
- 1) * packet_sz
);
201 if ((int)(stats
->count
+ 0.5) != n_packets
- 1)
202 ERROR("rc_twopass_stats_in missing EOS stats packet");
209 static vpx_codec_err_t
validate_img(vpx_codec_alg_priv_t
*ctx
,
210 const vpx_image_t
*img
) {
212 case VPX_IMG_FMT_YV12
:
213 case VPX_IMG_FMT_I420
:
214 case VPX_IMG_FMT_I422
:
215 case VPX_IMG_FMT_I444
:
218 ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
222 if ((img
->d_w
!= ctx
->cfg
.g_w
) || (img
->d_h
!= ctx
->cfg
.g_h
))
223 ERROR("Image size must match encoder init configuration size");
229 static vpx_codec_err_t
set_vp9e_config(VP9_CONFIG
*oxcf
,
230 vpx_codec_enc_cfg_t cfg
,
231 struct vp9_extracfg vp8_cfg
) {
232 oxcf
->version
= cfg
.g_profile
| (vp8_cfg
.experimental
? 0x4 : 0);
233 oxcf
->width
= cfg
.g_w
;
234 oxcf
->height
= cfg
.g_h
;
235 /* guess a frame rate if out of whack, use 30 */
236 oxcf
->frame_rate
= (double)(cfg
.g_timebase
.den
) / (double)(cfg
.g_timebase
.num
);
238 if (oxcf
->frame_rate
> 180) {
239 oxcf
->frame_rate
= 30;
242 switch (cfg
.g_pass
) {
243 case VPX_RC_ONE_PASS
:
244 oxcf
->Mode
= MODE_BESTQUALITY
;
246 case VPX_RC_FIRST_PASS
:
247 oxcf
->Mode
= MODE_FIRSTPASS
;
249 case VPX_RC_LAST_PASS
:
250 oxcf
->Mode
= MODE_SECONDPASS_BEST
;
254 if (cfg
.g_pass
== VPX_RC_FIRST_PASS
) {
256 oxcf
->lag_in_frames
= 0;
258 oxcf
->allow_lag
= (cfg
.g_lag_in_frames
) > 0;
259 oxcf
->lag_in_frames
= cfg
.g_lag_in_frames
;
262 // VBR only supported for now.
263 // CBR code has been deprectated for experimental phase.
264 // CQ mode not yet tested
265 oxcf
->end_usage
= USAGE_LOCAL_FILE_PLAYBACK
;
266 /*if (cfg.rc_end_usage == VPX_CQ)
267 oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
269 oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;*/
271 oxcf
->target_bandwidth
= cfg
.rc_target_bitrate
;
272 oxcf
->rc_max_intra_bitrate_pct
= vp8_cfg
.rc_max_intra_bitrate_pct
;
274 oxcf
->best_allowed_q
= cfg
.rc_min_quantizer
;
275 oxcf
->worst_allowed_q
= cfg
.rc_max_quantizer
;
276 oxcf
->cq_level
= vp8_cfg
.cq_level
;
279 oxcf
->under_shoot_pct
= cfg
.rc_undershoot_pct
;
280 oxcf
->over_shoot_pct
= cfg
.rc_overshoot_pct
;
282 oxcf
->maximum_buffer_size
= cfg
.rc_buf_sz
;
283 oxcf
->starting_buffer_level
= cfg
.rc_buf_initial_sz
;
284 oxcf
->optimal_buffer_level
= cfg
.rc_buf_optimal_sz
;
286 oxcf
->two_pass_vbrbias
= cfg
.rc_2pass_vbr_bias_pct
;
287 oxcf
->two_pass_vbrmin_section
= cfg
.rc_2pass_vbr_minsection_pct
;
288 oxcf
->two_pass_vbrmax_section
= cfg
.rc_2pass_vbr_maxsection_pct
;
290 oxcf
->auto_key
= cfg
.kf_mode
== VPX_KF_AUTO
291 && cfg
.kf_min_dist
!= cfg
.kf_max_dist
;
292 // oxcf->kf_min_dist = cfg.kf_min_dis;
293 oxcf
->key_freq
= cfg
.kf_max_dist
;
295 // oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
296 // strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
298 oxcf
->cpu_used
= vp8_cfg
.cpu_used
;
299 oxcf
->encode_breakout
= vp8_cfg
.static_thresh
;
300 oxcf
->play_alternate
= vp8_cfg
.enable_auto_alt_ref
;
301 oxcf
->noise_sensitivity
= vp8_cfg
.noise_sensitivity
;
302 oxcf
->Sharpness
= vp8_cfg
.Sharpness
;
304 oxcf
->two_pass_stats_in
= cfg
.rc_twopass_stats_in
;
305 oxcf
->output_pkt_list
= vp8_cfg
.pkt_list
;
307 oxcf
->arnr_max_frames
= vp8_cfg
.arnr_max_frames
;
308 oxcf
->arnr_strength
= vp8_cfg
.arnr_strength
;
309 oxcf
->arnr_type
= vp8_cfg
.arnr_type
;
311 oxcf
->tuning
= vp8_cfg
.tuning
;
313 oxcf
->tile_columns
= vp8_cfg
.tile_columns
;
314 oxcf
->tile_rows
= vp8_cfg
.tile_rows
;
316 oxcf
->lossless
= vp8_cfg
.lossless
;
318 oxcf
->error_resilient_mode
= cfg
.g_error_resilient
;
319 oxcf
->frame_parallel_decoding_mode
= vp8_cfg
.frame_parallel_decoding_mode
;
321 printf("Current VP9 Settings: \n");
322 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
323 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
324 printf("Sharpness: %d\n", oxcf->Sharpness);
325 printf("cpu_used: %d\n", oxcf->cpu_used);
326 printf("Mode: %d\n", oxcf->Mode);
327 // printf("delete_first_pass_file: %d\n", oxcf->delete_first_pass_file);
328 printf("auto_key: %d\n", oxcf->auto_key);
329 printf("key_freq: %d\n", oxcf->key_freq);
330 printf("end_usage: %d\n", oxcf->end_usage);
331 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
332 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
333 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
334 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
335 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
336 printf("fixed_q: %d\n", oxcf->fixed_q);
337 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
338 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
339 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
340 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
341 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
342 printf("allow_lag: %d\n", oxcf->allow_lag);
343 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
344 printf("play_alternate: %d\n", oxcf->play_alternate);
345 printf("Version: %d\n", oxcf->Version);
346 printf("encode_breakout: %d\n", oxcf->encode_breakout);
347 printf("error resilient: %d\n", oxcf->error_resilient_mode);
348 printf("frame parallel detokenization: %d\n",
349 oxcf->frame_parallel_decoding_mode);
354 static vpx_codec_err_t
vp9e_set_config(vpx_codec_alg_priv_t
*ctx
,
355 const vpx_codec_enc_cfg_t
*cfg
) {
358 if ((cfg
->g_w
!= ctx
->cfg
.g_w
) || (cfg
->g_h
!= ctx
->cfg
.g_h
))
359 ERROR("Cannot change width or height after initialization");
361 /* Prevent increasing lag_in_frames. This check is stricter than it needs
362 * to be -- the limit is not increasing past the first lag_in_frames
363 * value, but we don't track the initial config, only the last successful
366 if ((cfg
->g_lag_in_frames
> ctx
->cfg
.g_lag_in_frames
))
367 ERROR("Cannot increase lag_in_frames");
369 res
= validate_config(ctx
, cfg
, &ctx
->vp8_cfg
);
373 set_vp9e_config(&ctx
->oxcf
, ctx
->cfg
, ctx
->vp8_cfg
);
374 vp9_change_config(ctx
->cpi
, &ctx
->oxcf
);
381 int vp9_reverse_trans(int q
);
384 static vpx_codec_err_t
get_param(vpx_codec_alg_priv_t
*ctx
,
387 void *arg
= va_arg(args
, void *);
389 #define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
392 return VPX_CODEC_INVALID_PARAM
;
395 MAP(VP8E_GET_LAST_QUANTIZER
, vp9_get_quantizer(ctx
->cpi
));
396 MAP(VP8E_GET_LAST_QUANTIZER_64
,
397 vp9_reverse_trans(vp9_get_quantizer(ctx
->cpi
)));
405 static vpx_codec_err_t
set_param(vpx_codec_alg_priv_t
*ctx
,
408 vpx_codec_err_t res
= VPX_CODEC_OK
;
409 struct vp9_extracfg xcfg
= ctx
->vp8_cfg
;
411 #define MAP(id, var) case id: var = CAST(id, args); break;
414 MAP(VP8E_SET_CPUUSED
, xcfg
.cpu_used
);
415 MAP(VP8E_SET_ENABLEAUTOALTREF
, xcfg
.enable_auto_alt_ref
);
416 MAP(VP8E_SET_NOISE_SENSITIVITY
, xcfg
.noise_sensitivity
);
417 MAP(VP8E_SET_SHARPNESS
, xcfg
.Sharpness
);
418 MAP(VP8E_SET_STATIC_THRESHOLD
, xcfg
.static_thresh
);
419 MAP(VP9E_SET_TILE_COLUMNS
, xcfg
.tile_columns
);
420 MAP(VP9E_SET_TILE_ROWS
, xcfg
.tile_rows
);
422 MAP(VP8E_SET_ARNR_MAXFRAMES
, xcfg
.arnr_max_frames
);
423 MAP(VP8E_SET_ARNR_STRENGTH
, xcfg
.arnr_strength
);
424 MAP(VP8E_SET_ARNR_TYPE
, xcfg
.arnr_type
);
425 MAP(VP8E_SET_TUNING
, xcfg
.tuning
);
426 MAP(VP8E_SET_CQ_LEVEL
, xcfg
.cq_level
);
427 MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT
, xcfg
.rc_max_intra_bitrate_pct
);
428 MAP(VP9E_SET_LOSSLESS
, xcfg
.lossless
);
429 MAP(VP9E_SET_FRAME_PARALLEL_DECODING
, xcfg
.frame_parallel_decoding_mode
);
432 res
= validate_config(ctx
, &ctx
->cfg
, &xcfg
);
436 set_vp9e_config(&ctx
->oxcf
, ctx
->cfg
, ctx
->vp8_cfg
);
437 vp9_change_config(ctx
->cpi
, &ctx
->oxcf
);
445 static vpx_codec_err_t
vp9e_common_init(vpx_codec_ctx_t
*ctx
,
447 vpx_codec_err_t res
= VPX_CODEC_OK
;
448 struct vpx_codec_alg_priv
*priv
;
449 vpx_codec_enc_cfg_t
*cfg
;
455 priv
= calloc(1, sizeof(struct vpx_codec_alg_priv
));
458 return VPX_CODEC_MEM_ERROR
;
461 ctx
->priv
= &priv
->base
;
462 ctx
->priv
->sz
= sizeof(*ctx
->priv
);
463 ctx
->priv
->iface
= ctx
->iface
;
464 ctx
->priv
->alg_priv
= priv
;
465 ctx
->priv
->init_flags
= ctx
->init_flags
;
466 ctx
->priv
->enc
.total_encoders
= 1;
468 if (ctx
->config
.enc
) {
469 /* Update the reference to the config structure to an
472 ctx
->priv
->alg_priv
->cfg
= *ctx
->config
.enc
;
473 ctx
->config
.enc
= &ctx
->priv
->alg_priv
->cfg
;
476 cfg
= &ctx
->priv
->alg_priv
->cfg
;
478 /* Select the extra vp6 configuration table based on the current
479 * usage value. If the current usage value isn't found, use the
480 * values for usage case 0.
483 extracfg_map
[i
].usage
&& extracfg_map
[i
].usage
!= cfg
->g_usage
;
486 priv
->vp8_cfg
= extracfg_map
[i
].cfg
;
487 priv
->vp8_cfg
.pkt_list
= &priv
->pkt_list
.head
;
488 priv
->vp8_cfg
.experimental
= experimental
;
490 // TODO(agrange) Check the limits set on this buffer, or the check that is
491 // applied in vp9e_encode.
492 priv
->cx_data_sz
= priv
->cfg
.g_w
* priv
->cfg
.g_h
* 3 / 2 * 8;
493 // priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
495 if (priv
->cx_data_sz
< 4096) priv
->cx_data_sz
= 4096;
497 priv
->cx_data
= malloc(priv
->cx_data_sz
);
499 if (!priv
->cx_data
) {
500 return VPX_CODEC_MEM_ERROR
;
503 vp9_initialize_enc();
505 res
= validate_config(priv
, &priv
->cfg
, &priv
->vp8_cfg
);
508 set_vp9e_config(&ctx
->priv
->alg_priv
->oxcf
,
509 ctx
->priv
->alg_priv
->cfg
,
510 ctx
->priv
->alg_priv
->vp8_cfg
);
511 optr
= vp9_create_compressor(&ctx
->priv
->alg_priv
->oxcf
);
514 res
= VPX_CODEC_MEM_ERROR
;
516 ctx
->priv
->alg_priv
->cpi
= optr
;
524 static vpx_codec_err_t
vp9e_init(vpx_codec_ctx_t
*ctx
,
525 vpx_codec_priv_enc_mr_cfg_t
*data
) {
526 return vp9e_common_init(ctx
, 0);
530 #if CONFIG_EXPERIMENTAL
531 static vpx_codec_err_t
vp9e_exp_init(vpx_codec_ctx_t
*ctx
,
532 vpx_codec_priv_enc_mr_cfg_t
*data
) {
533 return vp9e_common_init(ctx
, 1);
538 static vpx_codec_err_t
vp9e_destroy(vpx_codec_alg_priv_t
*ctx
) {
541 vp9_remove_compressor(&ctx
->cpi
);
546 static void pick_quickcompress_mode(vpx_codec_alg_priv_t
*ctx
,
547 unsigned long duration
,
548 unsigned long deadline
) {
551 /* Use best quality mode if no deadline is given. */
553 new_qc
= MODE_GOODQUALITY
;
555 new_qc
= MODE_BESTQUALITY
;
557 if (ctx
->cfg
.g_pass
== VPX_RC_FIRST_PASS
)
558 new_qc
= MODE_FIRSTPASS
;
559 else if (ctx
->cfg
.g_pass
== VPX_RC_LAST_PASS
)
560 new_qc
= (new_qc
== MODE_BESTQUALITY
)
561 ? MODE_SECONDPASS_BEST
564 if (ctx
->oxcf
.Mode
!= new_qc
) {
565 ctx
->oxcf
.Mode
= new_qc
;
566 vp9_change_config(ctx
->cpi
, &ctx
->oxcf
);
571 static int write_superframe_index(vpx_codec_alg_priv_t
*ctx
) {
572 uint8_t marker
= 0xc0;
573 int mag
, mask
, index_sz
;
575 assert(ctx
->pending_frame_count
);
576 assert(ctx
->pending_frame_count
<= 8);
578 /* Add the number of frames to the marker byte */
579 marker
|= ctx
->pending_frame_count
- 1;
581 /* Choose the magnitude */
582 for (mag
= 0, mask
= 0xff; mag
< 4; mag
++) {
583 if (ctx
->pending_frame_magnitude
< mask
)
590 /* Write the index */
591 index_sz
= 2 + (mag
+ 1) * ctx
->pending_frame_count
;
592 if (ctx
->pending_cx_data_sz
+ index_sz
< ctx
->cx_data_sz
) {
593 uint8_t *x
= ctx
->pending_cx_data
+ ctx
->pending_cx_data_sz
;
597 for (i
= 0; i
< ctx
->pending_frame_count
; i
++) {
598 int this_sz
= ctx
->pending_frame_sizes
[i
];
600 for (j
= 0; j
<= mag
; j
++) {
601 *x
++ = this_sz
& 0xff;
606 ctx
->pending_cx_data_sz
+= index_sz
;
611 static vpx_codec_err_t
vp9e_encode(vpx_codec_alg_priv_t
*ctx
,
612 const vpx_image_t
*img
,
614 unsigned long duration
,
615 vpx_enc_frame_flags_t flags
,
616 unsigned long deadline
) {
617 vpx_codec_err_t res
= VPX_CODEC_OK
;
620 res
= validate_img(ctx
, img
);
622 pick_quickcompress_mode(ctx
, duration
, deadline
);
623 vpx_codec_pkt_list_init(&ctx
->pkt_list
);
626 if (((flags
& VP8_EFLAG_NO_UPD_GF
) && (flags
& VP8_EFLAG_FORCE_GF
))
627 || ((flags
& VP8_EFLAG_NO_UPD_ARF
) && (flags
& VP8_EFLAG_FORCE_ARF
))) {
628 ctx
->base
.err_detail
= "Conflicting flags.";
629 return VPX_CODEC_INVALID_PARAM
;
632 if (flags
& (VP8_EFLAG_NO_REF_LAST
| VP8_EFLAG_NO_REF_GF
633 | VP8_EFLAG_NO_REF_ARF
)) {
636 if (flags
& VP8_EFLAG_NO_REF_LAST
)
637 ref
^= VP9_LAST_FLAG
;
639 if (flags
& VP8_EFLAG_NO_REF_GF
)
640 ref
^= VP9_GOLD_FLAG
;
642 if (flags
& VP8_EFLAG_NO_REF_ARF
)
645 vp9_use_as_reference(ctx
->cpi
, ref
);
648 if (flags
& (VP8_EFLAG_NO_UPD_LAST
| VP8_EFLAG_NO_UPD_GF
649 | VP8_EFLAG_NO_UPD_ARF
| VP8_EFLAG_FORCE_GF
650 | VP8_EFLAG_FORCE_ARF
)) {
653 if (flags
& VP8_EFLAG_NO_UPD_LAST
)
654 upd
^= VP9_LAST_FLAG
;
656 if (flags
& VP8_EFLAG_NO_UPD_GF
)
657 upd
^= VP9_GOLD_FLAG
;
659 if (flags
& VP8_EFLAG_NO_UPD_ARF
)
662 vp9_update_reference(ctx
->cpi
, upd
);
665 if (flags
& VP8_EFLAG_NO_UPD_ENTROPY
) {
666 vp9_update_entropy(ctx
->cpi
, 0);
669 /* Handle fixed keyframe intervals */
670 if (ctx
->cfg
.kf_mode
== VPX_KF_AUTO
671 && ctx
->cfg
.kf_min_dist
== ctx
->cfg
.kf_max_dist
) {
672 if (++ctx
->fixed_kf_cntr
> ctx
->cfg
.kf_min_dist
) {
673 flags
|= VPX_EFLAG_FORCE_KF
;
674 ctx
->fixed_kf_cntr
= 1;
678 /* Initialize the encoder instance on the first frame*/
679 if (!res
&& ctx
->cpi
) {
680 unsigned int lib_flags
;
681 YV12_BUFFER_CONFIG sd
;
682 int64_t dst_time_stamp
, dst_end_time_stamp
;
683 unsigned long size
, cx_data_sz
;
684 unsigned char *cx_data
;
686 /* Set up internal flags */
687 if (ctx
->base
.init_flags
& VPX_CODEC_USE_PSNR
)
688 ((VP9_COMP
*)ctx
->cpi
)->b_calculate_psnr
= 1;
690 // if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
691 // ((VP9_COMP *)ctx->cpi)->output_partition = 1;
693 /* Convert API flags to internal codec lib flags */
694 lib_flags
= (flags
& VPX_EFLAG_FORCE_KF
) ? FRAMEFLAGS_KEY
: 0;
696 /* vp8 use 10,000,000 ticks/second as time stamp */
697 dst_time_stamp
= pts
* 10000000 * ctx
->cfg
.g_timebase
.num
/ ctx
->cfg
.g_timebase
.den
;
698 dst_end_time_stamp
= (pts
+ duration
) * 10000000 * ctx
->cfg
.g_timebase
.num
/ ctx
->cfg
.g_timebase
.den
;
701 res
= image2yuvconfig(img
, &sd
);
703 if (vp9_receive_raw_frame(ctx
->cpi
, lib_flags
,
704 &sd
, dst_time_stamp
, dst_end_time_stamp
)) {
705 VP9_COMP
*cpi
= (VP9_COMP
*)ctx
->cpi
;
706 res
= update_error_state(ctx
, &cpi
->common
.error
);
710 cx_data
= ctx
->cx_data
;
711 cx_data_sz
= ctx
->cx_data_sz
;
714 /* Any pending invisible frames? */
715 if (ctx
->pending_cx_data
) {
716 memmove(cx_data
, ctx
->pending_cx_data
, ctx
->pending_cx_data_sz
);
717 ctx
->pending_cx_data
= cx_data
;
718 cx_data
+= ctx
->pending_cx_data_sz
;
719 cx_data_sz
-= ctx
->pending_cx_data_sz
;
721 /* TODO: this is a minimal check, the underlying codec doesn't respect
722 * the buffer size anyway.
724 if (cx_data_sz
< ctx
->cx_data_sz
/ 2) {
725 ctx
->base
.err_detail
= "Compressed data buffer too small";
726 return VPX_CODEC_ERROR
;
730 while (cx_data_sz
>= ctx
->cx_data_sz
/ 2 &&
731 -1 != vp9_get_compressed_data(ctx
->cpi
, &lib_flags
, &size
,
732 cx_data
, &dst_time_stamp
,
733 &dst_end_time_stamp
, !img
)) {
735 vpx_codec_pts_t round
, delta
;
736 vpx_codec_cx_pkt_t pkt
;
737 VP9_COMP
*cpi
= (VP9_COMP
*)ctx
->cpi
;
739 /* Pack invisible frames with the next visible frame */
740 if (!cpi
->common
.show_frame
) {
741 if (!ctx
->pending_cx_data
)
742 ctx
->pending_cx_data
= cx_data
;
743 ctx
->pending_cx_data_sz
+= size
;
744 ctx
->pending_frame_sizes
[ctx
->pending_frame_count
++] = size
;
745 ctx
->pending_frame_magnitude
|= size
;
751 /* Add the frame packet to the list of returned packets. */
752 round
= 1000000 * ctx
->cfg
.g_timebase
.num
/ 2 - 1;
753 delta
= (dst_end_time_stamp
- dst_time_stamp
);
754 pkt
.kind
= VPX_CODEC_CX_FRAME_PKT
;
756 (dst_time_stamp
* ctx
->cfg
.g_timebase
.den
+ round
)
757 / ctx
->cfg
.g_timebase
.num
/ 10000000;
758 pkt
.data
.frame
.duration
= (unsigned long)
759 ((delta
* ctx
->cfg
.g_timebase
.den
+ round
)
760 / ctx
->cfg
.g_timebase
.num
/ 10000000);
761 pkt
.data
.frame
.flags
= lib_flags
<< 16;
763 if (lib_flags
& FRAMEFLAGS_KEY
)
764 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_KEY
;
766 if (!cpi
->common
.show_frame
) {
767 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_INVISIBLE
;
769 // This timestamp should be as close as possible to the
770 // prior PTS so that if a decoder uses pts to schedule when
771 // to do this, we start right after last frame was decoded.
772 // Invisible frames have no duration.
773 pkt
.data
.frame
.pts
= ((cpi
->last_time_stamp_seen
774 * ctx
->cfg
.g_timebase
.den
+ round
)
775 / ctx
->cfg
.g_timebase
.num
/ 10000000) + 1;
776 pkt
.data
.frame
.duration
= 0;
780 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_DROPPABLE
;
782 /*if (cpi->output_partition)
785 const int num_partitions = 1;
787 pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
789 for (i = 0; i < num_partitions; ++i)
791 pkt.data.frame.buf = cx_data;
792 pkt.data.frame.sz = cpi->partition_sz[i];
793 pkt.data.frame.partition_id = i;
794 // don't set the fragment bit for the last partition
795 if (i == (num_partitions - 1))
796 pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
797 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
798 cx_data += cpi->partition_sz[i];
799 cx_data_sz -= cpi->partition_sz[i];
804 if (ctx
->pending_cx_data
) {
805 ctx
->pending_frame_sizes
[ctx
->pending_frame_count
++] = size
;
806 ctx
->pending_frame_magnitude
|= size
;
807 ctx
->pending_cx_data_sz
+= size
;
808 size
+= write_superframe_index(ctx
);
809 pkt
.data
.frame
.buf
= ctx
->pending_cx_data
;
810 pkt
.data
.frame
.sz
= ctx
->pending_cx_data_sz
;
811 ctx
->pending_cx_data
= NULL
;
812 ctx
->pending_cx_data_sz
= 0;
813 ctx
->pending_frame_count
= 0;
814 ctx
->pending_frame_magnitude
= 0;
816 pkt
.data
.frame
.buf
= cx_data
;
817 pkt
.data
.frame
.sz
= size
;
819 pkt
.data
.frame
.partition_id
= -1;
820 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt
);
825 // printf("timestamp: %lld, duration: %d\n", pkt->data.frame.pts, pkt->data.frame.duration);
834 static const vpx_codec_cx_pkt_t
*vp9e_get_cxdata(vpx_codec_alg_priv_t
*ctx
,
835 vpx_codec_iter_t
*iter
) {
836 return vpx_codec_pkt_list_get(&ctx
->pkt_list
.head
, iter
);
839 static vpx_codec_err_t
vp9e_set_reference(vpx_codec_alg_priv_t
*ctx
,
842 vpx_ref_frame_t
*data
= va_arg(args
, vpx_ref_frame_t
*);
845 vpx_ref_frame_t
*frame
= (vpx_ref_frame_t
*)data
;
846 YV12_BUFFER_CONFIG sd
;
848 image2yuvconfig(&frame
->img
, &sd
);
849 vp9_set_reference_enc(ctx
->cpi
, frame
->frame_type
, &sd
);
852 return VPX_CODEC_INVALID_PARAM
;
856 static vpx_codec_err_t
vp9e_copy_reference(vpx_codec_alg_priv_t
*ctx
,
860 vpx_ref_frame_t
*data
= va_arg(args
, vpx_ref_frame_t
*);
863 vpx_ref_frame_t
*frame
= (vpx_ref_frame_t
*)data
;
864 YV12_BUFFER_CONFIG sd
;
866 image2yuvconfig(&frame
->img
, &sd
);
867 vp9_copy_reference_enc(ctx
->cpi
, frame
->frame_type
, &sd
);
870 return VPX_CODEC_INVALID_PARAM
;
873 static vpx_codec_err_t
get_reference(vpx_codec_alg_priv_t
*ctx
,
876 vp9_ref_frame_t
*data
= va_arg(args
, vp9_ref_frame_t
*);
879 YV12_BUFFER_CONFIG
* fb
;
881 vp9_get_reference_enc(ctx
->cpi
, data
->idx
, &fb
);
882 yuvconfig2image(&data
->img
, fb
, NULL
);
885 return VPX_CODEC_INVALID_PARAM
;
889 static vpx_codec_err_t
vp9e_set_previewpp(vpx_codec_alg_priv_t
*ctx
,
893 vp8_postproc_cfg_t
*data
= va_arg(args
, vp8_postproc_cfg_t
*);
897 ctx
->preview_ppcfg
= *((vp8_postproc_cfg_t
*)data
);
900 return VPX_CODEC_INVALID_PARAM
;
905 return VPX_CODEC_INCAPABLE
;
910 static vpx_image_t
*vp9e_get_preview(vpx_codec_alg_priv_t
*ctx
) {
912 YV12_BUFFER_CONFIG sd
;
913 vp9_ppflags_t flags
= {0};
915 if (ctx
->preview_ppcfg
.post_proc_flag
) {
916 flags
.post_proc_flag
= ctx
->preview_ppcfg
.post_proc_flag
;
917 flags
.deblocking_level
= ctx
->preview_ppcfg
.deblocking_level
;
918 flags
.noise_level
= ctx
->preview_ppcfg
.noise_level
;
921 if (0 == vp9_get_preview_raw_frame(ctx
->cpi
, &sd
, &flags
)) {
922 yuvconfig2image(&ctx
->preview_img
, &sd
, NULL
);
923 return &ctx
->preview_img
;
928 static vpx_codec_err_t
vp9e_update_entropy(vpx_codec_alg_priv_t
*ctx
,
931 int update
= va_arg(args
, int);
932 vp9_update_entropy(ctx
->cpi
, update
);
937 static vpx_codec_err_t
vp9e_update_reference(vpx_codec_alg_priv_t
*ctx
,
940 int update
= va_arg(args
, int);
941 vp9_update_reference(ctx
->cpi
, update
);
945 static vpx_codec_err_t
vp9e_use_reference(vpx_codec_alg_priv_t
*ctx
,
948 int reference_flag
= va_arg(args
, int);
949 vp9_use_as_reference(ctx
->cpi
, reference_flag
);
953 static vpx_codec_err_t
vp9e_set_roi_map(vpx_codec_alg_priv_t
*ctx
,
956 vpx_roi_map_t
*data
= va_arg(args
, vpx_roi_map_t
*);
959 vpx_roi_map_t
*roi
= (vpx_roi_map_t
*)data
;
961 if (!vp9_set_roimap(ctx
->cpi
, roi
->roi_map
, roi
->rows
, roi
->cols
,
962 roi
->delta_q
, roi
->delta_lf
, roi
->static_threshold
))
965 return VPX_CODEC_INVALID_PARAM
;
967 return VPX_CODEC_INVALID_PARAM
;
971 static vpx_codec_err_t
vp9e_set_activemap(vpx_codec_alg_priv_t
*ctx
,
974 vpx_active_map_t
*data
= va_arg(args
, vpx_active_map_t
*);
978 vpx_active_map_t
*map
= (vpx_active_map_t
*)data
;
980 if (!vp9_set_active_map(ctx
->cpi
, map
->active_map
, map
->rows
, map
->cols
))
983 return VPX_CODEC_INVALID_PARAM
;
985 return VPX_CODEC_INVALID_PARAM
;
988 static vpx_codec_err_t
vp9e_set_scalemode(vpx_codec_alg_priv_t
*ctx
,
992 vpx_scaling_mode_t
*data
= va_arg(args
, vpx_scaling_mode_t
*);
996 vpx_scaling_mode_t scalemode
= *(vpx_scaling_mode_t
*)data
;
997 res
= vp9_set_internal_size(ctx
->cpi
, scalemode
.h_scaling_mode
,
998 scalemode
.v_scaling_mode
);
1001 return VPX_CODEC_OK
;
1003 return VPX_CODEC_INVALID_PARAM
;
1005 return VPX_CODEC_INVALID_PARAM
;
1009 static vpx_codec_ctrl_fn_map_t vp9e_ctf_maps
[] = {
1010 {VP8_SET_REFERENCE
, vp9e_set_reference
},
1011 {VP8_COPY_REFERENCE
, vp9e_copy_reference
},
1012 {VP8_SET_POSTPROC
, vp9e_set_previewpp
},
1013 {VP8E_UPD_ENTROPY
, vp9e_update_entropy
},
1014 {VP8E_UPD_REFERENCE
, vp9e_update_reference
},
1015 {VP8E_USE_REFERENCE
, vp9e_use_reference
},
1016 {VP8E_SET_ROI_MAP
, vp9e_set_roi_map
},
1017 {VP8E_SET_ACTIVEMAP
, vp9e_set_activemap
},
1018 {VP8E_SET_SCALEMODE
, vp9e_set_scalemode
},
1019 {VP8E_SET_CPUUSED
, set_param
},
1020 {VP8E_SET_NOISE_SENSITIVITY
, set_param
},
1021 {VP8E_SET_ENABLEAUTOALTREF
, set_param
},
1022 {VP8E_SET_SHARPNESS
, set_param
},
1023 {VP8E_SET_STATIC_THRESHOLD
, set_param
},
1024 {VP9E_SET_TILE_COLUMNS
, set_param
},
1025 {VP9E_SET_TILE_ROWS
, set_param
},
1026 {VP8E_GET_LAST_QUANTIZER
, get_param
},
1027 {VP8E_GET_LAST_QUANTIZER_64
, get_param
},
1028 {VP8E_SET_ARNR_MAXFRAMES
, set_param
},
1029 {VP8E_SET_ARNR_STRENGTH
, set_param
},
1030 {VP8E_SET_ARNR_TYPE
, set_param
},
1031 {VP8E_SET_TUNING
, set_param
},
1032 {VP8E_SET_CQ_LEVEL
, set_param
},
1033 {VP8E_SET_MAX_INTRA_BITRATE_PCT
, set_param
},
1034 {VP9E_SET_LOSSLESS
, set_param
},
1035 {VP9_GET_REFERENCE
, get_reference
},
1039 static vpx_codec_enc_cfg_map_t vp9e_usage_cfg_map
[] = {
1049 {1, 30}, /* g_timebase */
1051 0, /* g_error_resilient */
1053 VPX_RC_ONE_PASS
, /* g_pass */
1055 0, /* g_lag_in_frames */
1057 0, /* rc_dropframe_thresh */
1058 0, /* rc_resize_allowed */
1059 60, /* rc_resize_down_thresold */
1060 30, /* rc_resize_up_thresold */
1062 VPX_VBR
, /* rc_end_usage */
1063 #if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
1064 {0}, /* rc_twopass_stats_in */
1066 256, /* rc_target_bandwidth */
1067 4, /* rc_min_quantizer */
1068 63, /* rc_max_quantizer */
1069 100, /* rc_undershoot_pct */
1070 100, /* rc_overshoot_pct */
1072 6000, /* rc_max_buffer_size */
1073 4000, /* rc_buffer_initial_size; */
1074 5000, /* rc_buffer_optimal_size; */
1076 50, /* rc_two_pass_vbrbias */
1077 0, /* rc_two_pass_vbrmin_section */
1078 400, /* rc_two_pass_vbrmax_section */
1080 /* keyframing settings (kf) */
1081 VPX_KF_AUTO
, /* g_kfmode*/
1082 0, /* kf_min_dist */
1083 9999, /* kf_max_dist */
1085 #if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
1086 1, /* g_delete_first_pass_file */
1087 "vp8.fpf" /* first pass filename */
1091 { -1, {NOT_IMPLEMENTED
}}
1095 #ifndef VERSION_STRING
1096 #define VERSION_STRING
1098 CODEC_INTERFACE(vpx_codec_vp9_cx
) = {
1099 "WebM Project VP9 Encoder" VERSION_STRING
,
1100 VPX_CODEC_INTERNAL_ABI_VERSION
,
1101 VPX_CODEC_CAP_ENCODER
| VPX_CODEC_CAP_PSNR
|
1102 VPX_CODEC_CAP_OUTPUT_PARTITION
,
1103 /* vpx_codec_caps_t caps; */
1104 vp9e_init
, /* vpx_codec_init_fn_t init; */
1105 vp9e_destroy
, /* vpx_codec_destroy_fn_t destroy; */
1106 vp9e_ctf_maps
, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1107 NOT_IMPLEMENTED
, /* vpx_codec_get_mmap_fn_t get_mmap; */
1108 NOT_IMPLEMENTED
, /* vpx_codec_set_mmap_fn_t set_mmap; */
1110 NOT_IMPLEMENTED
, /* vpx_codec_peek_si_fn_t peek_si; */
1111 NOT_IMPLEMENTED
, /* vpx_codec_get_si_fn_t get_si; */
1112 NOT_IMPLEMENTED
, /* vpx_codec_decode_fn_t decode; */
1113 NOT_IMPLEMENTED
, /* vpx_codec_frame_get_fn_t frame_get; */
1116 vp9e_usage_cfg_map
, /* vpx_codec_enc_cfg_map_t peek_si; */
1117 vp9e_encode
, /* vpx_codec_encode_fn_t encode; */
1118 vp9e_get_cxdata
, /* vpx_codec_get_cx_data_fn_t frame_get; */
1122 } /* encoder functions */
1126 #if CONFIG_EXPERIMENTAL
1128 CODEC_INTERFACE(vpx_codec_vp9x_cx
) = {
1129 "VP8 Experimental Encoder" VERSION_STRING
,
1130 VPX_CODEC_INTERNAL_ABI_VERSION
,
1131 VPX_CODEC_CAP_ENCODER
| VPX_CODEC_CAP_PSNR
,
1132 /* vpx_codec_caps_t caps; */
1133 vp9e_exp_init
, /* vpx_codec_init_fn_t init; */
1134 vp9e_destroy
, /* vpx_codec_destroy_fn_t destroy; */
1135 vp9e_ctf_maps
, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1136 NOT_IMPLEMENTED
, /* vpx_codec_get_mmap_fn_t get_mmap; */
1137 NOT_IMPLEMENTED
, /* vpx_codec_set_mmap_fn_t set_mmap; */
1139 NOT_IMPLEMENTED
, /* vpx_codec_peek_si_fn_t peek_si; */
1140 NOT_IMPLEMENTED
, /* vpx_codec_get_si_fn_t get_si; */
1141 NOT_IMPLEMENTED
, /* vpx_codec_decode_fn_t decode; */
1142 NOT_IMPLEMENTED
, /* vpx_codec_frame_get_fn_t frame_get; */
1145 vp9e_usage_cfg_map
, /* vpx_codec_enc_cfg_map_t peek_si; */
1146 vp9e_encode
, /* vpx_codec_encode_fn_t encode; */
1147 vp9e_get_cxdata
, /* vpx_codec_get_cx_data_fn_t frame_get; */
1151 } /* encoder functions */