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 "vp8/encoder/onyx_int.h"
17 #include "vp8/encoder/firstpass.h"
18 #include "vp8/common/onyx.h"
22 /* This value is a sentinel for determining whether the user has set a mode
23 * directly through the deprecated VP8E_SET_ENCODING_MODE control.
25 #define NO_MODE_SET 255
29 struct vpx_codec_pkt_list
*pkt_list
;
30 vp8e_encoding_mode encoding_mode
; /** best, good, realtime */
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
;
46 struct extraconfig_map
49 struct vp8_extracfg cfg
;
52 static const struct extraconfig_map extracfg_map
[] =
58 #if !(CONFIG_REALTIME_ONLY)
59 VP8_BEST_QUALITY_ENCODING
, /* Encoding Mode */
62 VP8_REAL_TIME_ENCODING
, /* Encoding Mode */
65 0, /* enable_auto_alt_ref */
66 0, /* noise_sensitivity */
68 0, /* static_thresh */
69 VP8_ONE_TOKENPARTITION
, /* token_partitions */
70 0, /* arnr_max_frames */
71 3, /* arnr_strength */
75 0, /* rc_max_intra_bitrate_pct */
80 struct vpx_codec_alg_priv
82 vpx_codec_priv_t base
;
83 vpx_codec_enc_cfg_t cfg
;
84 struct vp8_extracfg vp8_cfg
;
87 unsigned char *cx_data
;
88 unsigned int cx_data_sz
;
89 vpx_image_t preview_img
;
90 unsigned int next_frame_flag
;
91 vp8_postproc_cfg_t preview_ppcfg
;
92 vpx_codec_pkt_list_decl(64) pkt_list
; // changed to accomendate the maximum number of lagged frames allowed
94 unsigned int fixed_kf_cntr
;
98 static vpx_codec_err_t
99 update_error_state(vpx_codec_alg_priv_t
*ctx
,
100 const struct vpx_internal_error_info
*error
)
104 if ((res
= error
->error_code
))
105 ctx
->base
.err_detail
= error
->has_detail
114 #define ERROR(str) do {\
115 ctx->base.err_detail = str;\
116 return VPX_CODEC_INVALID_PARAM;\
119 #define RANGE_CHECK(p,memb,lo,hi) do {\
120 if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
121 ERROR(#memb " out of range ["#lo".."#hi"]");\
124 #define RANGE_CHECK_HI(p,memb,hi) do {\
125 if(!((p)->memb <= (hi))) \
126 ERROR(#memb " out of range [.."#hi"]");\
129 #define RANGE_CHECK_LO(p,memb,lo) do {\
130 if(!((p)->memb >= (lo))) \
131 ERROR(#memb " out of range ["#lo"..]");\
134 #define RANGE_CHECK_BOOL(p,memb) do {\
135 if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
138 static vpx_codec_err_t
validate_config(vpx_codec_alg_priv_t
*ctx
,
139 const vpx_codec_enc_cfg_t
*cfg
,
140 const struct vp8_extracfg
*vp8_cfg
)
142 RANGE_CHECK(cfg
, g_w
, 1, 16383); /* 14 bits available */
143 RANGE_CHECK(cfg
, g_h
, 1, 16383); /* 14 bits available */
144 RANGE_CHECK(cfg
, g_timebase
.den
, 1, 1000000000);
145 RANGE_CHECK(cfg
, g_timebase
.num
, 1, cfg
->g_timebase
.den
);
146 RANGE_CHECK_HI(cfg
, g_profile
, 3);
147 RANGE_CHECK_HI(cfg
, rc_max_quantizer
, 63);
148 RANGE_CHECK_HI(cfg
, rc_min_quantizer
, cfg
->rc_max_quantizer
);
149 RANGE_CHECK_HI(cfg
, g_threads
, 64);
150 #if !(CONFIG_REALTIME_ONLY)
151 RANGE_CHECK_HI(cfg
, g_lag_in_frames
, 25);
153 RANGE_CHECK_HI(cfg
, g_lag_in_frames
, 0);
155 RANGE_CHECK(cfg
, rc_end_usage
, VPX_VBR
, VPX_CQ
);
156 RANGE_CHECK_HI(cfg
, rc_undershoot_pct
, 1000);
157 RANGE_CHECK_HI(cfg
, rc_overshoot_pct
, 1000);
158 RANGE_CHECK_HI(cfg
, rc_2pass_vbr_bias_pct
, 100);
159 RANGE_CHECK(cfg
, kf_mode
, VPX_KF_DISABLED
, VPX_KF_AUTO
);
160 //RANGE_CHECK_BOOL(cfg, g_delete_firstpassfile);
161 RANGE_CHECK_BOOL(cfg
, rc_resize_allowed
);
162 RANGE_CHECK_HI(cfg
, rc_dropframe_thresh
, 100);
163 RANGE_CHECK_HI(cfg
, rc_resize_up_thresh
, 100);
164 RANGE_CHECK_HI(cfg
, rc_resize_down_thresh
, 100);
165 #if !(CONFIG_REALTIME_ONLY)
166 RANGE_CHECK(cfg
, g_pass
, VPX_RC_ONE_PASS
, VPX_RC_LAST_PASS
);
168 RANGE_CHECK(cfg
, g_pass
, VPX_RC_ONE_PASS
, VPX_RC_ONE_PASS
);
171 /* VP8 does not support a lower bound on the keyframe interval in
172 * automatic keyframe placement mode.
174 if (cfg
->kf_mode
!= VPX_KF_DISABLED
&& cfg
->kf_min_dist
!= cfg
->kf_max_dist
175 && cfg
->kf_min_dist
> 0)
176 ERROR("kf_min_dist not supported in auto mode, use 0 "
177 "or kf_max_dist instead.");
179 RANGE_CHECK_BOOL(vp8_cfg
, enable_auto_alt_ref
);
180 RANGE_CHECK(vp8_cfg
, cpu_used
, -16, 16);
182 #if !(CONFIG_REALTIME_ONLY)
183 RANGE_CHECK(vp8_cfg
, encoding_mode
, VP8_BEST_QUALITY_ENCODING
, VP8_REAL_TIME_ENCODING
);
184 RANGE_CHECK_HI(vp8_cfg
, noise_sensitivity
, 6);
186 RANGE_CHECK(vp8_cfg
, encoding_mode
, VP8_REAL_TIME_ENCODING
, VP8_REAL_TIME_ENCODING
);
187 RANGE_CHECK(vp8_cfg
, noise_sensitivity
, 0, 0);
190 RANGE_CHECK(vp8_cfg
, token_partitions
, VP8_ONE_TOKENPARTITION
, VP8_EIGHT_TOKENPARTITION
);
191 RANGE_CHECK_HI(vp8_cfg
, Sharpness
, 7);
192 RANGE_CHECK(vp8_cfg
, arnr_max_frames
, 0, 15);
193 RANGE_CHECK_HI(vp8_cfg
, arnr_strength
, 6);
194 RANGE_CHECK(vp8_cfg
, arnr_type
, 1, 3);
195 RANGE_CHECK(vp8_cfg
, cq_level
, 0, 63);
197 #if !(CONFIG_REALTIME_ONLY)
198 if (cfg
->g_pass
== VPX_RC_LAST_PASS
)
200 size_t packet_sz
= sizeof(FIRSTPASS_STATS
);
201 int n_packets
= cfg
->rc_twopass_stats_in
.sz
/ packet_sz
;
202 FIRSTPASS_STATS
*stats
;
204 if (!cfg
->rc_twopass_stats_in
.buf
)
205 ERROR("rc_twopass_stats_in.buf not set.");
207 if (cfg
->rc_twopass_stats_in
.sz
% packet_sz
)
208 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
210 if (cfg
->rc_twopass_stats_in
.sz
< 2 * packet_sz
)
211 ERROR("rc_twopass_stats_in requires at least two packets.");
213 stats
= (void*)((char *)cfg
->rc_twopass_stats_in
.buf
214 + (n_packets
- 1) * packet_sz
);
216 if ((int)(stats
->count
+ 0.5) != n_packets
- 1)
217 ERROR("rc_twopass_stats_in missing EOS stats packet");
225 static vpx_codec_err_t
validate_img(vpx_codec_alg_priv_t
*ctx
,
226 const vpx_image_t
*img
)
230 case VPX_IMG_FMT_YV12
:
231 case VPX_IMG_FMT_I420
:
232 case VPX_IMG_FMT_VPXI420
:
233 case VPX_IMG_FMT_VPXYV12
:
236 ERROR("Invalid image format. Only YV12 and I420 images are supported");
239 if ((img
->d_w
!= ctx
->cfg
.g_w
) || (img
->d_h
!= ctx
->cfg
.g_h
))
240 ERROR("Image size must match encoder init configuration size");
246 static vpx_codec_err_t
set_vp8e_config(VP8_CONFIG
*oxcf
,
247 vpx_codec_enc_cfg_t cfg
,
248 struct vp8_extracfg vp8_cfg
)
250 oxcf
->multi_threaded
= cfg
.g_threads
;
251 oxcf
->Version
= cfg
.g_profile
;
253 oxcf
->Width
= cfg
.g_w
;
254 oxcf
->Height
= cfg
.g_h
;
255 /* guess a frame rate if out of whack, use 30 */
256 oxcf
->frame_rate
= (double)(cfg
.g_timebase
.den
) / (double)(cfg
.g_timebase
.num
);
258 if (oxcf
->frame_rate
> 180)
260 oxcf
->frame_rate
= 30;
263 oxcf
->error_resilient_mode
= cfg
.g_error_resilient
;
267 case VPX_RC_ONE_PASS
:
268 oxcf
->Mode
= MODE_BESTQUALITY
;
270 case VPX_RC_FIRST_PASS
:
271 oxcf
->Mode
= MODE_FIRSTPASS
;
273 case VPX_RC_LAST_PASS
:
274 oxcf
->Mode
= MODE_SECONDPASS_BEST
;
278 if (cfg
.g_pass
== VPX_RC_FIRST_PASS
)
281 oxcf
->lag_in_frames
= 0;
285 oxcf
->allow_lag
= (cfg
.g_lag_in_frames
) > 0;
286 oxcf
->lag_in_frames
= cfg
.g_lag_in_frames
;
289 oxcf
->allow_df
= (cfg
.rc_dropframe_thresh
> 0);
290 oxcf
->drop_frames_water_mark
= cfg
.rc_dropframe_thresh
;
292 oxcf
->allow_spatial_resampling
= cfg
.rc_resize_allowed
;
293 oxcf
->resample_up_water_mark
= cfg
.rc_resize_up_thresh
;
294 oxcf
->resample_down_water_mark
= cfg
.rc_resize_down_thresh
;
296 if (cfg
.rc_end_usage
== VPX_VBR
)
298 oxcf
->end_usage
= USAGE_LOCAL_FILE_PLAYBACK
;
300 else if (cfg
.rc_end_usage
== VPX_CBR
)
302 oxcf
->end_usage
= USAGE_STREAM_FROM_SERVER
;
304 else if (cfg
.rc_end_usage
== VPX_CQ
)
306 oxcf
->end_usage
= USAGE_CONSTRAINED_QUALITY
;
309 oxcf
->target_bandwidth
= cfg
.rc_target_bitrate
;
310 oxcf
->rc_max_intra_bitrate_pct
= vp8_cfg
.rc_max_intra_bitrate_pct
;
312 oxcf
->best_allowed_q
= cfg
.rc_min_quantizer
;
313 oxcf
->worst_allowed_q
= cfg
.rc_max_quantizer
;
314 oxcf
->cq_level
= vp8_cfg
.cq_level
;
317 oxcf
->under_shoot_pct
= cfg
.rc_undershoot_pct
;
318 oxcf
->over_shoot_pct
= cfg
.rc_overshoot_pct
;
320 oxcf
->maximum_buffer_size
= cfg
.rc_buf_sz
;
321 oxcf
->starting_buffer_level
= cfg
.rc_buf_initial_sz
;
322 oxcf
->optimal_buffer_level
= cfg
.rc_buf_optimal_sz
;
324 oxcf
->two_pass_vbrbias
= cfg
.rc_2pass_vbr_bias_pct
;
325 oxcf
->two_pass_vbrmin_section
= cfg
.rc_2pass_vbr_minsection_pct
;
326 oxcf
->two_pass_vbrmax_section
= cfg
.rc_2pass_vbr_maxsection_pct
;
328 oxcf
->auto_key
= cfg
.kf_mode
== VPX_KF_AUTO
329 && cfg
.kf_min_dist
!= cfg
.kf_max_dist
;
330 //oxcf->kf_min_dist = cfg.kf_min_dis;
331 oxcf
->key_freq
= cfg
.kf_max_dist
;
333 //oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
334 //strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
336 oxcf
->cpu_used
= vp8_cfg
.cpu_used
;
337 oxcf
->encode_breakout
= vp8_cfg
.static_thresh
;
338 oxcf
->play_alternate
= vp8_cfg
.enable_auto_alt_ref
;
339 oxcf
->noise_sensitivity
= vp8_cfg
.noise_sensitivity
;
340 oxcf
->Sharpness
= vp8_cfg
.Sharpness
;
341 oxcf
->token_partitions
= vp8_cfg
.token_partitions
;
343 oxcf
->two_pass_stats_in
= cfg
.rc_twopass_stats_in
;
344 oxcf
->output_pkt_list
= vp8_cfg
.pkt_list
;
346 oxcf
->arnr_max_frames
= vp8_cfg
.arnr_max_frames
;
347 oxcf
->arnr_strength
= vp8_cfg
.arnr_strength
;
348 oxcf
->arnr_type
= vp8_cfg
.arnr_type
;
350 oxcf
->tuning
= vp8_cfg
.tuning
;
353 printf("Current VP8 Settings: \n");
354 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
355 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
356 printf("Sharpness: %d\n", oxcf->Sharpness);
357 printf("cpu_used: %d\n", oxcf->cpu_used);
358 printf("Mode: %d\n", oxcf->Mode);
359 printf("delete_first_pass_file: %d\n", oxcf->delete_first_pass_file);
360 printf("auto_key: %d\n", oxcf->auto_key);
361 printf("key_freq: %d\n", oxcf->key_freq);
362 printf("end_usage: %d\n", oxcf->end_usage);
363 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
364 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
365 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
366 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
367 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
368 printf("fixed_q: %d\n", oxcf->fixed_q);
369 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
370 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
371 printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
372 printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark);
373 printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark);
374 printf("allow_df: %d\n", oxcf->allow_df);
375 printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark);
376 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
377 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
378 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
379 printf("allow_lag: %d\n", oxcf->allow_lag);
380 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
381 printf("play_alternate: %d\n", oxcf->play_alternate);
382 printf("Version: %d\n", oxcf->Version);
383 printf("multi_threaded: %d\n", oxcf->multi_threaded);
384 printf("encode_breakout: %d\n", oxcf->encode_breakout);
389 static vpx_codec_err_t
vp8e_set_config(vpx_codec_alg_priv_t
*ctx
,
390 const vpx_codec_enc_cfg_t
*cfg
)
394 if ((cfg
->g_w
!= ctx
->cfg
.g_w
) || (cfg
->g_h
!= ctx
->cfg
.g_h
))
395 ERROR("Cannot change width or height after initialization");
397 /* Prevent increasing lag_in_frames. This check is stricter than it needs
398 * to be -- the limit is not increasing past the first lag_in_frames
399 * value, but we don't track the initial config, only the last successful
402 if ((cfg
->g_lag_in_frames
> ctx
->cfg
.g_lag_in_frames
))
403 ERROR("Cannot increase lag_in_frames");
405 res
= validate_config(ctx
, cfg
, &ctx
->vp8_cfg
);
410 set_vp8e_config(&ctx
->oxcf
, ctx
->cfg
, ctx
->vp8_cfg
);
411 vp8_change_config(ctx
->cpi
, &ctx
->oxcf
);
418 int vp8_reverse_trans(int);
421 static vpx_codec_err_t
get_param(vpx_codec_alg_priv_t
*ctx
,
425 void *arg
= va_arg(args
, void *);
427 #define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
430 return VPX_CODEC_INVALID_PARAM
;
434 MAP(VP8E_GET_LAST_QUANTIZER
, vp8_get_quantizer(ctx
->cpi
));
435 MAP(VP8E_GET_LAST_QUANTIZER_64
, vp8_reverse_trans(vp8_get_quantizer(ctx
->cpi
)));
443 static vpx_codec_err_t
set_param(vpx_codec_alg_priv_t
*ctx
,
447 vpx_codec_err_t res
= VPX_CODEC_OK
;
448 struct vp8_extracfg xcfg
= ctx
->vp8_cfg
;
450 #define MAP(id, var) case id: var = CAST(id, args); break;
454 MAP(VP8E_SET_ENCODING_MODE
, ctx
->deprecated_mode
);
455 MAP(VP8E_SET_CPUUSED
, xcfg
.cpu_used
);
456 MAP(VP8E_SET_ENABLEAUTOALTREF
, xcfg
.enable_auto_alt_ref
);
457 MAP(VP8E_SET_NOISE_SENSITIVITY
, xcfg
.noise_sensitivity
);
458 MAP(VP8E_SET_SHARPNESS
, xcfg
.Sharpness
);
459 MAP(VP8E_SET_STATIC_THRESHOLD
, xcfg
.static_thresh
);
460 MAP(VP8E_SET_TOKEN_PARTITIONS
, xcfg
.token_partitions
);
462 MAP(VP8E_SET_ARNR_MAXFRAMES
, xcfg
.arnr_max_frames
);
463 MAP(VP8E_SET_ARNR_STRENGTH
, xcfg
.arnr_strength
);
464 MAP(VP8E_SET_ARNR_TYPE
, xcfg
.arnr_type
);
465 MAP(VP8E_SET_TUNING
, xcfg
.tuning
);
466 MAP(VP8E_SET_CQ_LEVEL
, xcfg
.cq_level
);
467 MAP(VP8E_SET_MAX_INTRA_BITRATE_PCT
, xcfg
.rc_max_intra_bitrate_pct
);
471 res
= validate_config(ctx
, &ctx
->cfg
, &xcfg
);
476 set_vp8e_config(&ctx
->oxcf
, ctx
->cfg
, ctx
->vp8_cfg
);
477 vp8_change_config(ctx
->cpi
, &ctx
->oxcf
);
483 static vpx_codec_err_t
vp8e_init(vpx_codec_ctx_t
*ctx
)
485 vpx_codec_err_t res
= VPX_DEC_OK
;
486 struct vpx_codec_alg_priv
*priv
;
487 vpx_codec_enc_cfg_t
*cfg
;
494 priv
= calloc(1, sizeof(struct vpx_codec_alg_priv
));
498 return VPX_CODEC_MEM_ERROR
;
501 ctx
->priv
= &priv
->base
;
502 ctx
->priv
->sz
= sizeof(*ctx
->priv
);
503 ctx
->priv
->iface
= ctx
->iface
;
504 ctx
->priv
->alg_priv
= priv
;
505 ctx
->priv
->init_flags
= ctx
->init_flags
;
509 /* Update the reference to the config structure to an
512 ctx
->priv
->alg_priv
->cfg
= *ctx
->config
.enc
;
513 ctx
->config
.enc
= &ctx
->priv
->alg_priv
->cfg
;
516 cfg
= &ctx
->priv
->alg_priv
->cfg
;
518 /* Select the extra vp6 configuration table based on the current
519 * usage value. If the current usage value isn't found, use the
520 * values for usage case 0.
523 extracfg_map
[i
].usage
&& extracfg_map
[i
].usage
!= cfg
->g_usage
;
526 priv
->vp8_cfg
= extracfg_map
[i
].cfg
;
527 priv
->vp8_cfg
.pkt_list
= &priv
->pkt_list
.head
;
529 priv
->cx_data_sz
= priv
->cfg
.g_w
* priv
->cfg
.g_h
* 3 / 2 * 2;
531 if (priv
->cx_data_sz
< 4096) priv
->cx_data_sz
= 4096;
533 priv
->cx_data
= malloc(priv
->cx_data_sz
);
537 return VPX_CODEC_MEM_ERROR
;
540 priv
->deprecated_mode
= NO_MODE_SET
;
544 res
= validate_config(priv
, &priv
->cfg
, &priv
->vp8_cfg
);
548 set_vp8e_config(&ctx
->priv
->alg_priv
->oxcf
,
549 ctx
->priv
->alg_priv
->cfg
,
550 ctx
->priv
->alg_priv
->vp8_cfg
);
551 optr
= vp8_create_compressor(&ctx
->priv
->alg_priv
->oxcf
);
554 res
= VPX_CODEC_MEM_ERROR
;
556 ctx
->priv
->alg_priv
->cpi
= optr
;
563 static vpx_codec_err_t
vp8e_destroy(vpx_codec_alg_priv_t
*ctx
)
567 vp8_remove_compressor(&ctx
->cpi
);
572 static vpx_codec_err_t
image2yuvconfig(const vpx_image_t
*img
,
573 YV12_BUFFER_CONFIG
*yv12
)
575 vpx_codec_err_t res
= VPX_CODEC_OK
;
576 yv12
->y_buffer
= img
->planes
[VPX_PLANE_Y
];
577 yv12
->u_buffer
= img
->planes
[VPX_PLANE_U
];
578 yv12
->v_buffer
= img
->planes
[VPX_PLANE_V
];
580 yv12
->y_width
= img
->d_w
;
581 yv12
->y_height
= img
->d_h
;
582 yv12
->uv_width
= (1 + yv12
->y_width
) / 2;
583 yv12
->uv_height
= (1 + yv12
->y_height
) / 2;
585 yv12
->y_stride
= img
->stride
[VPX_PLANE_Y
];
586 yv12
->uv_stride
= img
->stride
[VPX_PLANE_U
];
588 yv12
->border
= (img
->stride
[VPX_PLANE_Y
] - img
->w
) / 2;
589 yv12
->clrtype
= (img
->fmt
== VPX_IMG_FMT_VPXI420
|| img
->fmt
== VPX_IMG_FMT_VPXYV12
); //REG_YUV = 0
593 static void pick_quickcompress_mode(vpx_codec_alg_priv_t
*ctx
,
594 unsigned long duration
,
595 unsigned long deadline
)
599 #if !(CONFIG_REALTIME_ONLY)
600 /* Use best quality mode if no deadline is given. */
601 new_qc
= MODE_BESTQUALITY
;
605 uint64_t duration_us
;
607 /* Convert duration parameter from stream timebase to microseconds */
608 duration_us
= (uint64_t)duration
* 1000000
609 * (uint64_t)ctx
->cfg
.g_timebase
.num
610 / (uint64_t)ctx
->cfg
.g_timebase
.den
;
612 /* If the deadline is more that the duration this frame is to be shown,
613 * use good quality mode. Otherwise use realtime mode.
615 new_qc
= (deadline
> duration_us
) ? MODE_GOODQUALITY
: MODE_REALTIME
;
619 new_qc
= MODE_REALTIME
;
622 switch (ctx
->deprecated_mode
)
624 case VP8_BEST_QUALITY_ENCODING
:
625 new_qc
= MODE_BESTQUALITY
;
627 case VP8_GOOD_QUALITY_ENCODING
:
628 new_qc
= MODE_GOODQUALITY
;
630 case VP8_REAL_TIME_ENCODING
:
631 new_qc
= MODE_REALTIME
;
635 if (ctx
->cfg
.g_pass
== VPX_RC_FIRST_PASS
)
636 new_qc
= MODE_FIRSTPASS
;
637 else if (ctx
->cfg
.g_pass
== VPX_RC_LAST_PASS
)
638 new_qc
= (new_qc
== MODE_BESTQUALITY
)
639 ? MODE_SECONDPASS_BEST
642 if (ctx
->oxcf
.Mode
!= new_qc
)
644 ctx
->oxcf
.Mode
= new_qc
;
645 vp8_change_config(ctx
->cpi
, &ctx
->oxcf
);
650 static vpx_codec_err_t
vp8e_encode(vpx_codec_alg_priv_t
*ctx
,
651 const vpx_image_t
*img
,
653 unsigned long duration
,
654 vpx_enc_frame_flags_t flags
,
655 unsigned long deadline
)
657 vpx_codec_err_t res
= VPX_CODEC_OK
;
660 res
= validate_img(ctx
, img
);
662 pick_quickcompress_mode(ctx
, duration
, deadline
);
663 vpx_codec_pkt_list_init(&ctx
->pkt_list
);
666 if (((flags
& VP8_EFLAG_NO_UPD_GF
) && (flags
& VP8_EFLAG_FORCE_GF
))
667 || ((flags
& VP8_EFLAG_NO_UPD_ARF
) && (flags
& VP8_EFLAG_FORCE_ARF
)))
669 ctx
->base
.err_detail
= "Conflicting flags.";
670 return VPX_CODEC_INVALID_PARAM
;
673 if (flags
& (VP8_EFLAG_NO_REF_LAST
| VP8_EFLAG_NO_REF_GF
674 | VP8_EFLAG_NO_REF_ARF
))
678 if (flags
& VP8_EFLAG_NO_REF_LAST
)
679 ref
^= VP8_LAST_FLAG
;
681 if (flags
& VP8_EFLAG_NO_REF_GF
)
682 ref
^= VP8_GOLD_FLAG
;
684 if (flags
& VP8_EFLAG_NO_REF_ARF
)
687 vp8_use_as_reference(ctx
->cpi
, ref
);
690 if (flags
& (VP8_EFLAG_NO_UPD_LAST
| VP8_EFLAG_NO_UPD_GF
691 | VP8_EFLAG_NO_UPD_ARF
| VP8_EFLAG_FORCE_GF
692 | VP8_EFLAG_FORCE_ARF
))
696 if (flags
& VP8_EFLAG_NO_UPD_LAST
)
697 upd
^= VP8_LAST_FLAG
;
699 if (flags
& VP8_EFLAG_NO_UPD_GF
)
700 upd
^= VP8_GOLD_FLAG
;
702 if (flags
& VP8_EFLAG_NO_UPD_ARF
)
705 vp8_update_reference(ctx
->cpi
, upd
);
708 if (flags
& VP8_EFLAG_NO_UPD_ENTROPY
)
710 vp8_update_entropy(ctx
->cpi
, 0);
713 /* Handle fixed keyframe intervals */
714 if (ctx
->cfg
.kf_mode
== VPX_KF_AUTO
715 && ctx
->cfg
.kf_min_dist
== ctx
->cfg
.kf_max_dist
)
717 if (++ctx
->fixed_kf_cntr
> ctx
->cfg
.kf_min_dist
)
719 flags
|= VPX_EFLAG_FORCE_KF
;
720 ctx
->fixed_kf_cntr
= 1;
724 /* Initialize the encoder instance on the first frame*/
725 if (!res
&& ctx
->cpi
)
727 unsigned int lib_flags
;
728 YV12_BUFFER_CONFIG sd
;
729 int64_t dst_time_stamp
, dst_end_time_stamp
;
730 unsigned long size
, cx_data_sz
;
731 unsigned char *cx_data
;
733 /* Set up internal flags */
734 if (ctx
->base
.init_flags
& VPX_CODEC_USE_PSNR
)
735 ((VP8_COMP
*)ctx
->cpi
)->b_calculate_psnr
= 1;
737 if (ctx
->base
.init_flags
& VPX_CODEC_USE_OUTPUT_PARTITION
)
738 ((VP8_COMP
*)ctx
->cpi
)->output_partition
= 1;
740 /* Convert API flags to internal codec lib flags */
741 lib_flags
= (flags
& VPX_EFLAG_FORCE_KF
) ? FRAMEFLAGS_KEY
: 0;
743 /* vp8 use 10,000,000 ticks/second as time stamp */
744 dst_time_stamp
= pts
* 10000000 * ctx
->cfg
.g_timebase
.num
/ ctx
->cfg
.g_timebase
.den
;
745 dst_end_time_stamp
= (pts
+ duration
) * 10000000 * ctx
->cfg
.g_timebase
.num
/ ctx
->cfg
.g_timebase
.den
;
749 res
= image2yuvconfig(img
, &sd
);
751 if (vp8_receive_raw_frame(ctx
->cpi
, ctx
->next_frame_flag
| lib_flags
,
752 &sd
, dst_time_stamp
, dst_end_time_stamp
))
754 VP8_COMP
*cpi
= (VP8_COMP
*)ctx
->cpi
;
755 res
= update_error_state(ctx
, &cpi
->common
.error
);
758 /* reset for next frame */
759 ctx
->next_frame_flag
= 0;
762 cx_data
= ctx
->cx_data
;
763 cx_data_sz
= ctx
->cx_data_sz
;
766 while (cx_data_sz
>= ctx
->cx_data_sz
/ 2
767 && -1 != vp8_get_compressed_data(ctx
->cpi
, &lib_flags
, &size
, cx_data
, &dst_time_stamp
, &dst_end_time_stamp
, !img
))
771 vpx_codec_pts_t round
, delta
;
772 vpx_codec_cx_pkt_t pkt
;
773 VP8_COMP
*cpi
= (VP8_COMP
*)ctx
->cpi
;
775 /* Add the frame packet to the list of returned packets. */
776 round
= 1000000 * ctx
->cfg
.g_timebase
.num
/ 2 - 1;
777 delta
= (dst_end_time_stamp
- dst_time_stamp
);
778 pkt
.kind
= VPX_CODEC_CX_FRAME_PKT
;
780 (dst_time_stamp
* ctx
->cfg
.g_timebase
.den
+ round
)
781 / ctx
->cfg
.g_timebase
.num
/ 10000000;
782 pkt
.data
.frame
.duration
=
783 (delta
* ctx
->cfg
.g_timebase
.den
+ round
)
784 / ctx
->cfg
.g_timebase
.num
/ 10000000;
785 pkt
.data
.frame
.flags
= lib_flags
<< 16;
787 if (lib_flags
& FRAMEFLAGS_KEY
)
788 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_KEY
;
790 if (!cpi
->common
.show_frame
)
792 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_INVISIBLE
;
794 // This timestamp should be as close as possible to the
795 // prior PTS so that if a decoder uses pts to schedule when
796 // to do this, we start right after last frame was decoded.
797 // Invisible frames have no duration.
798 pkt
.data
.frame
.pts
= ((cpi
->last_time_stamp_seen
799 * ctx
->cfg
.g_timebase
.den
+ round
)
800 / ctx
->cfg
.g_timebase
.num
/ 10000000) + 1;
801 pkt
.data
.frame
.duration
= 0;
805 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_DROPPABLE
;
807 if (cpi
->output_partition
)
810 const int num_partitions
=
811 (1 << cpi
->common
.multi_token_partition
) + 1;
813 pkt
.data
.frame
.flags
|= VPX_FRAME_IS_FRAGMENT
;
815 for (i
= 0; i
< num_partitions
; ++i
)
817 pkt
.data
.frame
.buf
= cx_data
;
818 pkt
.data
.frame
.sz
= cpi
->partition_sz
[i
];
819 pkt
.data
.frame
.partition_id
= i
;
820 /* don't set the fragment bit for the last partition */
821 if (i
== (num_partitions
- 1))
822 pkt
.data
.frame
.flags
&= ~VPX_FRAME_IS_FRAGMENT
;
823 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt
);
824 cx_data
+= cpi
->partition_sz
[i
];
825 cx_data_sz
-= cpi
->partition_sz
[i
];
830 pkt
.data
.frame
.buf
= cx_data
;
831 pkt
.data
.frame
.sz
= size
;
832 pkt
.data
.frame
.partition_id
= -1;
833 vpx_codec_pkt_list_add(&ctx
->pkt_list
.head
, &pkt
);
838 //printf("timestamp: %lld, duration: %d\n", pkt->data.frame.pts, pkt->data.frame.duration);
847 static const vpx_codec_cx_pkt_t
*vp8e_get_cxdata(vpx_codec_alg_priv_t
*ctx
,
848 vpx_codec_iter_t
*iter
)
850 return vpx_codec_pkt_list_get(&ctx
->pkt_list
.head
, iter
);
853 static vpx_codec_err_t
vp8e_set_reference(vpx_codec_alg_priv_t
*ctx
,
857 vpx_ref_frame_t
*data
= va_arg(args
, vpx_ref_frame_t
*);
861 vpx_ref_frame_t
*frame
= (vpx_ref_frame_t
*)data
;
862 YV12_BUFFER_CONFIG sd
;
864 image2yuvconfig(&frame
->img
, &sd
);
865 vp8_set_reference(ctx
->cpi
, frame
->frame_type
, &sd
);
869 return VPX_CODEC_INVALID_PARAM
;
873 static vpx_codec_err_t
vp8e_get_reference(vpx_codec_alg_priv_t
*ctx
,
878 vpx_ref_frame_t
*data
= va_arg(args
, vpx_ref_frame_t
*);
882 vpx_ref_frame_t
*frame
= (vpx_ref_frame_t
*)data
;
883 YV12_BUFFER_CONFIG sd
;
885 image2yuvconfig(&frame
->img
, &sd
);
886 vp8_get_reference(ctx
->cpi
, frame
->frame_type
, &sd
);
890 return VPX_CODEC_INVALID_PARAM
;
893 static vpx_codec_err_t
vp8e_set_previewpp(vpx_codec_alg_priv_t
*ctx
,
898 vp8_postproc_cfg_t
*data
= va_arg(args
, vp8_postproc_cfg_t
*);
903 ctx
->preview_ppcfg
= *((vp8_postproc_cfg_t
*)data
);
907 return VPX_CODEC_INVALID_PARAM
;
912 return VPX_CODEC_INCAPABLE
;
917 static vpx_image_t
*vp8e_get_preview(vpx_codec_alg_priv_t
*ctx
)
920 YV12_BUFFER_CONFIG sd
;
921 vp8_ppflags_t flags
= {0};
923 if (ctx
->preview_ppcfg
.post_proc_flag
)
925 flags
.post_proc_flag
= ctx
->preview_ppcfg
.post_proc_flag
;
926 flags
.deblocking_level
= ctx
->preview_ppcfg
.deblocking_level
;
927 flags
.noise_level
= ctx
->preview_ppcfg
.noise_level
;
930 if (0 == vp8_get_preview_raw_frame(ctx
->cpi
, &sd
, &flags
))
934 vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12,
935 sd.y_width + 2*VP8BORDERINPIXELS,
936 sd.y_height + 2*VP8BORDERINPIXELS,
939 vpx_img_set_rect(&ctx->preview_img,
940 VP8BORDERINPIXELS, VP8BORDERINPIXELS,
941 sd.y_width, sd.y_height);
944 ctx
->preview_img
.bps
= 12;
945 ctx
->preview_img
.planes
[VPX_PLANE_Y
] = sd
.y_buffer
;
946 ctx
->preview_img
.planes
[VPX_PLANE_U
] = sd
.u_buffer
;
947 ctx
->preview_img
.planes
[VPX_PLANE_V
] = sd
.v_buffer
;
949 if (sd
.clrtype
== REG_YUV
)
950 ctx
->preview_img
.fmt
= VPX_IMG_FMT_I420
;
952 ctx
->preview_img
.fmt
= VPX_IMG_FMT_VPXI420
;
954 ctx
->preview_img
.x_chroma_shift
= 1;
955 ctx
->preview_img
.y_chroma_shift
= 1;
957 ctx
->preview_img
.d_w
= sd
.y_width
;
958 ctx
->preview_img
.d_h
= sd
.y_height
;
959 ctx
->preview_img
.stride
[VPX_PLANE_Y
] = sd
.y_stride
;
960 ctx
->preview_img
.stride
[VPX_PLANE_U
] = sd
.uv_stride
;
961 ctx
->preview_img
.stride
[VPX_PLANE_V
] = sd
.uv_stride
;
962 ctx
->preview_img
.w
= sd
.y_width
;
963 ctx
->preview_img
.h
= sd
.y_height
;
965 return &ctx
->preview_img
;
971 static vpx_codec_err_t
vp8e_update_entropy(vpx_codec_alg_priv_t
*ctx
,
975 int update
= va_arg(args
, int);
976 vp8_update_entropy(ctx
->cpi
, update
);
981 static vpx_codec_err_t
vp8e_update_reference(vpx_codec_alg_priv_t
*ctx
,
985 int update
= va_arg(args
, int);
986 vp8_update_reference(ctx
->cpi
, update
);
990 static vpx_codec_err_t
vp8e_use_reference(vpx_codec_alg_priv_t
*ctx
,
994 int reference_flag
= va_arg(args
, int);
995 vp8_use_as_reference(ctx
->cpi
, reference_flag
);
999 static vpx_codec_err_t
vp8e_set_roi_map(vpx_codec_alg_priv_t
*ctx
,
1003 vpx_roi_map_t
*data
= va_arg(args
, vpx_roi_map_t
*);
1007 vpx_roi_map_t
*roi
= (vpx_roi_map_t
*)data
;
1009 if (!vp8_set_roimap(ctx
->cpi
, roi
->roi_map
, roi
->rows
, roi
->cols
, roi
->delta_q
, roi
->delta_lf
, roi
->static_threshold
))
1010 return VPX_CODEC_OK
;
1012 return VPX_CODEC_INVALID_PARAM
;
1015 return VPX_CODEC_INVALID_PARAM
;
1019 static vpx_codec_err_t
vp8e_set_activemap(vpx_codec_alg_priv_t
*ctx
,
1023 vpx_active_map_t
*data
= va_arg(args
, vpx_active_map_t
*);
1028 vpx_active_map_t
*map
= (vpx_active_map_t
*)data
;
1030 if (!vp8_set_active_map(ctx
->cpi
, map
->active_map
, map
->rows
, map
->cols
))
1031 return VPX_CODEC_OK
;
1033 return VPX_CODEC_INVALID_PARAM
;
1036 return VPX_CODEC_INVALID_PARAM
;
1039 static vpx_codec_err_t
vp8e_set_scalemode(vpx_codec_alg_priv_t
*ctx
,
1044 vpx_scaling_mode_t
*data
= va_arg(args
, vpx_scaling_mode_t
*);
1049 vpx_scaling_mode_t scalemode
= *(vpx_scaling_mode_t
*)data
;
1050 res
= vp8_set_internal_size(ctx
->cpi
, scalemode
.h_scaling_mode
, scalemode
.v_scaling_mode
);
1054 /*force next frame a key frame to effect scaling mode */
1055 ctx
->next_frame_flag
|= FRAMEFLAGS_KEY
;
1056 return VPX_CODEC_OK
;
1059 return VPX_CODEC_INVALID_PARAM
;
1062 return VPX_CODEC_INVALID_PARAM
;
1066 static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps
[] =
1068 {VP8_SET_REFERENCE
, vp8e_set_reference
},
1069 {VP8_COPY_REFERENCE
, vp8e_get_reference
},
1070 {VP8_SET_POSTPROC
, vp8e_set_previewpp
},
1071 {VP8E_UPD_ENTROPY
, vp8e_update_entropy
},
1072 {VP8E_UPD_REFERENCE
, vp8e_update_reference
},
1073 {VP8E_USE_REFERENCE
, vp8e_use_reference
},
1074 {VP8E_SET_ROI_MAP
, vp8e_set_roi_map
},
1075 {VP8E_SET_ACTIVEMAP
, vp8e_set_activemap
},
1076 {VP8E_SET_SCALEMODE
, vp8e_set_scalemode
},
1077 {VP8E_SET_ENCODING_MODE
, set_param
},
1078 {VP8E_SET_CPUUSED
, set_param
},
1079 {VP8E_SET_NOISE_SENSITIVITY
, set_param
},
1080 {VP8E_SET_ENABLEAUTOALTREF
, set_param
},
1081 {VP8E_SET_SHARPNESS
, set_param
},
1082 {VP8E_SET_STATIC_THRESHOLD
, set_param
},
1083 {VP8E_SET_TOKEN_PARTITIONS
, set_param
},
1084 {VP8E_GET_LAST_QUANTIZER
, get_param
},
1085 {VP8E_GET_LAST_QUANTIZER_64
, get_param
},
1086 {VP8E_SET_ARNR_MAXFRAMES
, set_param
},
1087 {VP8E_SET_ARNR_STRENGTH
, set_param
},
1088 {VP8E_SET_ARNR_TYPE
, set_param
},
1089 {VP8E_SET_TUNING
, set_param
},
1090 {VP8E_SET_CQ_LEVEL
, set_param
},
1091 {VP8E_SET_MAX_INTRA_BITRATE_PCT
, set_param
},
1095 static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map
[] =
1106 {1, 30}, /* g_timebase */
1108 0, /* g_error_resilient */
1110 VPX_RC_ONE_PASS
, /* g_pass */
1112 0, /* g_lag_in_frames */
1114 0, /* rc_dropframe_thresh */
1115 0, /* rc_resize_allowed */
1116 60, /* rc_resize_down_thresold */
1117 30, /* rc_resize_up_thresold */
1119 VPX_VBR
, /* rc_end_usage */
1120 #if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
1121 {0}, /* rc_twopass_stats_in */
1123 256, /* rc_target_bandwidth */
1124 4, /* rc_min_quantizer */
1125 63, /* rc_max_quantizer */
1126 100, /* rc_undershoot_pct */
1127 100, /* rc_overshoot_pct */
1129 6000, /* rc_max_buffer_size */
1130 4000, /* rc_buffer_initial_size; */
1131 5000, /* rc_buffer_optimal_size; */
1133 50, /* rc_two_pass_vbrbias */
1134 0, /* rc_two_pass_vbrmin_section */
1135 400, /* rc_two_pass_vbrmax_section */
1137 /* keyframing settings (kf) */
1138 VPX_KF_AUTO
, /* g_kfmode*/
1139 0, /* kf_min_dist */
1140 9999, /* kf_max_dist */
1142 #if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
1143 1, /* g_delete_first_pass_file */
1144 "vp8.fpf" /* first pass filename */
1147 { -1, {NOT_IMPLEMENTED
}}
1151 #ifndef VERSION_STRING
1152 #define VERSION_STRING
1154 CODEC_INTERFACE(vpx_codec_vp8_cx
) =
1156 "WebM Project VP8 Encoder" VERSION_STRING
,
1157 VPX_CODEC_INTERNAL_ABI_VERSION
,
1158 VPX_CODEC_CAP_ENCODER
| VPX_CODEC_CAP_PSNR
|
1159 VPX_CODEC_CAP_OUTPUT_PARTITION
,
1160 /* vpx_codec_caps_t caps; */
1161 vp8e_init
, /* vpx_codec_init_fn_t init; */
1162 vp8e_destroy
, /* vpx_codec_destroy_fn_t destroy; */
1163 vp8e_ctf_maps
, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1164 NOT_IMPLEMENTED
, /* vpx_codec_get_mmap_fn_t get_mmap; */
1165 NOT_IMPLEMENTED
, /* vpx_codec_set_mmap_fn_t set_mmap; */
1167 NOT_IMPLEMENTED
, /* vpx_codec_peek_si_fn_t peek_si; */
1168 NOT_IMPLEMENTED
, /* vpx_codec_get_si_fn_t get_si; */
1169 NOT_IMPLEMENTED
, /* vpx_codec_decode_fn_t decode; */
1170 NOT_IMPLEMENTED
, /* vpx_codec_frame_get_fn_t frame_get; */
1173 vp8e_usage_cfg_map
, /* vpx_codec_enc_cfg_map_t peek_si; */
1174 vp8e_encode
, /* vpx_codec_encode_fn_t encode; */
1175 vp8e_get_cxdata
, /* vpx_codec_get_cx_data_fn_t frame_get; */
1179 } /* encoder functions */
1184 * BEGIN BACKWARDS COMPATIBILITY SHIM.
1187 static vpx_codec_err_t
api1_control(vpx_codec_alg_priv_t
*ctx
,
1191 vpx_codec_ctrl_fn_map_t
*entry
;
1195 case VP8E_SET_FLUSHFLAG
:
1196 /* VP8 sample code did VP8E_SET_FLUSHFLAG followed by
1197 * vpx_codec_get_cx_data() rather than vpx_codec_encode().
1199 return vp8e_encode(ctx
, NULL
, 0, 0, 0, 0);
1200 case VP8E_SET_FRAMETYPE
:
1201 ctx
->base
.enc
.tbd
|= FORCE_KEY
;
1202 return VPX_CODEC_OK
;
1205 for (entry
= vp8e_ctf_maps
; entry
&& entry
->fn
; entry
++)
1207 if (!entry
->ctrl_id
|| entry
->ctrl_id
== ctrl_id
)
1209 return entry
->fn(ctx
, ctrl_id
, args
);
1213 return VPX_CODEC_ERROR
;
1217 static vpx_codec_ctrl_fn_map_t api1_ctrl_maps
[] =
1224 static vpx_codec_err_t
api1_encode(vpx_codec_alg_priv_t
*ctx
,
1225 const vpx_image_t
*img
,
1226 vpx_codec_pts_t pts
,
1227 unsigned long duration
,
1228 vpx_enc_frame_flags_t flags
,
1229 unsigned long deadline
)
1231 int force
= ctx
->base
.enc
.tbd
;
1233 ctx
->base
.enc
.tbd
= 0;
1239 flags
| ((force
& FORCE_KEY
) ? VPX_EFLAG_FORCE_KF
: 0),
1244 vpx_codec_iface_t vpx_enc_vp8_algo
=
1246 "WebM Project VP8 Encoder (Deprecated API)" VERSION_STRING
,
1247 VPX_CODEC_INTERNAL_ABI_VERSION
,
1248 VPX_CODEC_CAP_ENCODER
,
1249 /* vpx_codec_caps_t caps; */
1250 vp8e_init
, /* vpx_codec_init_fn_t init; */
1251 vp8e_destroy
, /* vpx_codec_destroy_fn_t destroy; */
1252 api1_ctrl_maps
, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1253 NOT_IMPLEMENTED
, /* vpx_codec_get_mmap_fn_t get_mmap; */
1254 NOT_IMPLEMENTED
, /* vpx_codec_set_mmap_fn_t set_mmap; */
1255 {NOT_IMPLEMENTED
}, /* decoder functions */
1257 vp8e_usage_cfg_map
, /* vpx_codec_enc_cfg_map_t peek_si; */
1258 api1_encode
, /* vpx_codec_encode_fn_t encode; */
1259 vp8e_get_cxdata
, /* vpx_codec_get_cx_data_fn_t frame_get; */
1263 } /* encoder functions */