1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
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.
9 */
10
11
12 #include "./vpx_config.h"
13 #include "vp8_rtcd.h"
14 #include "vpx/vpx_codec.h"
15 #include "vpx/internal/vpx_codec_internal.h"
16 #include "vpx_version.h"
17 #include "vpx_mem/vpx_mem.h"
18 #include "vp8/encoder/onyx_int.h"
19 #include "vpx/vp8cx.h"
20 #include "vp8/encoder/firstpass.h"
21 #include "vp8/common/onyx.h"
22 #include <stdlib.h>
23 #include <string.h>
24
25 struct vp8_extracfg
26 {
27 struct vpx_codec_pkt_list *pkt_list;
28 int cpu_used; /** available cpu percentage in 1/16*/
29 unsigned int enable_auto_alt_ref; /** if encoder decides to uses alternate reference frame */
30 unsigned int noise_sensitivity;
31 unsigned int Sharpness;
32 unsigned int static_thresh;
33 unsigned int token_partitions;
34 unsigned int arnr_max_frames; /* alt_ref Noise Reduction Max Frame Count */
35 unsigned int arnr_strength; /* alt_ref Noise Reduction Strength */
36 unsigned int arnr_type; /* alt_ref filter type */
37 vp8e_tuning tuning;
38 unsigned int cq_level; /* constrained quality level */
39 unsigned int rc_max_intra_bitrate_pct;
40
41 };
42
43 static struct vp8_extracfg default_extracfg = {
44 NULL,
45 #if !(CONFIG_REALTIME_ONLY)
46 0, /* cpu_used */
47 #else
48 4, /* cpu_used */
49 #endif
50 0, /* enable_auto_alt_ref */
51 0, /* noise_sensitivity */
52 0, /* Sharpness */
53 0, /* static_thresh */
54 #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
55 VP8_EIGHT_TOKENPARTITION,
56 #else
57 VP8_ONE_TOKENPARTITION, /* token_partitions */
58 #endif
59 0, /* arnr_max_frames */
60 3, /* arnr_strength */
61 3, /* arnr_type*/
62 0, /* tuning*/
63 10, /* cq_level */
64 0, /* rc_max_intra_bitrate_pct */
65 };
66
67 struct vpx_codec_alg_priv
68 {
69 vpx_codec_priv_t base;
70 vpx_codec_enc_cfg_t cfg;
71 struct vp8_extracfg vp8_cfg;
72 VP8_CONFIG oxcf;
73 struct VP8_COMP *cpi;
74 unsigned char *cx_data;
75 unsigned int cx_data_sz;
76 vpx_image_t preview_img;
77 unsigned int next_frame_flag;
78 vp8_postproc_cfg_t preview_ppcfg;
79 /* pkt_list size depends on the maximum number of lagged frames allowed. */
80 vpx_codec_pkt_list_decl(64) pkt_list;
81 unsigned int fixed_kf_cntr;
82 };
83
84
85 static vpx_codec_err_t
update_error_state(vpx_codec_alg_priv_t * ctx,const struct vpx_internal_error_info * error)86 update_error_state(vpx_codec_alg_priv_t *ctx,
87 const struct vpx_internal_error_info *error)
88 {
89 vpx_codec_err_t res;
90
91 if ((res = error->error_code))
92 ctx->base.err_detail = error->has_detail
93 ? error->detail
94 : NULL;
95
96 return res;
97 }
98
99
100 #undef ERROR
101 #define ERROR(str) do {\
102 ctx->base.err_detail = str;\
103 return VPX_CODEC_INVALID_PARAM;\
104 } while(0)
105
106 #define RANGE_CHECK(p,memb,lo,hi) do {\
107 if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
108 ERROR(#memb " out of range ["#lo".."#hi"]");\
109 } while(0)
110
111 #define RANGE_CHECK_HI(p,memb,hi) do {\
112 if(!((p)->memb <= (hi))) \
113 ERROR(#memb " out of range [.."#hi"]");\
114 } while(0)
115
116 #define RANGE_CHECK_LO(p,memb,lo) do {\
117 if(!((p)->memb >= (lo))) \
118 ERROR(#memb " out of range ["#lo"..]");\
119 } while(0)
120
121 #define RANGE_CHECK_BOOL(p,memb) do {\
122 if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
123 } while(0)
124
validate_config(vpx_codec_alg_priv_t * ctx,const vpx_codec_enc_cfg_t * cfg,const struct vp8_extracfg * vp8_cfg,int finalize)125 static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
126 const vpx_codec_enc_cfg_t *cfg,
127 const struct vp8_extracfg *vp8_cfg,
128 int finalize)
129 {
130 RANGE_CHECK(cfg, g_w, 1, 16383); /* 14 bits available */
131 RANGE_CHECK(cfg, g_h, 1, 16383); /* 14 bits available */
132 RANGE_CHECK(cfg, g_timebase.den, 1, 1000000000);
133 RANGE_CHECK(cfg, g_timebase.num, 1, cfg->g_timebase.den);
134 RANGE_CHECK_HI(cfg, g_profile, 3);
135 RANGE_CHECK_HI(cfg, rc_max_quantizer, 63);
136 RANGE_CHECK_HI(cfg, rc_min_quantizer, cfg->rc_max_quantizer);
137 RANGE_CHECK_HI(cfg, g_threads, 64);
138 #if CONFIG_REALTIME_ONLY
139 RANGE_CHECK_HI(cfg, g_lag_in_frames, 0);
140 #elif CONFIG_MULTI_RES_ENCODING
141 if (ctx->base.enc.total_encoders > 1)
142 RANGE_CHECK_HI(cfg, g_lag_in_frames, 0);
143 #else
144 RANGE_CHECK_HI(cfg, g_lag_in_frames, 25);
145 #endif
146 RANGE_CHECK(cfg, rc_end_usage, VPX_VBR, VPX_Q);
147 RANGE_CHECK_HI(cfg, rc_undershoot_pct, 1000);
148 RANGE_CHECK_HI(cfg, rc_overshoot_pct, 1000);
149 RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
150 RANGE_CHECK(cfg, kf_mode, VPX_KF_DISABLED, VPX_KF_AUTO);
151
152 /* TODO: add spatial re-sampling support and frame dropping in
153 * multi-res-encoder.*/
154 #if CONFIG_MULTI_RES_ENCODING
155 if (ctx->base.enc.total_encoders > 1)
156 RANGE_CHECK_HI(cfg, rc_resize_allowed, 0);
157 #else
158 RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
159 #endif
160 RANGE_CHECK_HI(cfg, rc_dropframe_thresh, 100);
161 RANGE_CHECK_HI(cfg, rc_resize_up_thresh, 100);
162 RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
163
164 #if CONFIG_REALTIME_ONLY
165 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
166 #elif CONFIG_MULTI_RES_ENCODING
167 if (ctx->base.enc.total_encoders > 1)
168 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
169 #else
170 RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
171 #endif
172
173 /* VP8 does not support a lower bound on the keyframe interval in
174 * automatic keyframe placement mode.
175 */
176 if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist
177 && cfg->kf_min_dist > 0)
178 ERROR("kf_min_dist not supported in auto mode, use 0 "
179 "or kf_max_dist instead.");
180
181 RANGE_CHECK_BOOL(vp8_cfg, enable_auto_alt_ref);
182 RANGE_CHECK(vp8_cfg, cpu_used, -16, 16);
183
184 #if CONFIG_REALTIME_ONLY && !CONFIG_TEMPORAL_DENOISING
185 RANGE_CHECK(vp8_cfg, noise_sensitivity, 0, 0);
186 #else
187 RANGE_CHECK_HI(vp8_cfg, noise_sensitivity, 6);
188 #endif
189
190 RANGE_CHECK(vp8_cfg, token_partitions, VP8_ONE_TOKENPARTITION,
191 VP8_EIGHT_TOKENPARTITION);
192 RANGE_CHECK_HI(vp8_cfg, Sharpness, 7);
193 RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
194 RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6);
195 RANGE_CHECK(vp8_cfg, arnr_type, 1, 3);
196 RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
197 if (finalize && (cfg->rc_end_usage == VPX_CQ || cfg->rc_end_usage == VPX_Q))
198 RANGE_CHECK(vp8_cfg, cq_level,
199 cfg->rc_min_quantizer, cfg->rc_max_quantizer);
200
201 #if !(CONFIG_REALTIME_ONLY)
202 if (cfg->g_pass == VPX_RC_LAST_PASS)
203 {
204 size_t packet_sz = sizeof(FIRSTPASS_STATS);
205 int n_packets = (int)(cfg->rc_twopass_stats_in.sz /
206 packet_sz);
207 FIRSTPASS_STATS *stats;
208
209 if (!cfg->rc_twopass_stats_in.buf)
210 ERROR("rc_twopass_stats_in.buf not set.");
211
212 if (cfg->rc_twopass_stats_in.sz % packet_sz)
213 ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
214
215 if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
216 ERROR("rc_twopass_stats_in requires at least two packets.");
217
218 stats = (void*)((char *)cfg->rc_twopass_stats_in.buf
219 + (n_packets - 1) * packet_sz);
220
221 if ((int)(stats->count + 0.5) != n_packets - 1)
222 ERROR("rc_twopass_stats_in missing EOS stats packet");
223 }
224 #endif
225
226 RANGE_CHECK(cfg, ts_number_layers, 1, 5);
227
228 if (cfg->ts_number_layers > 1)
229 {
230 unsigned int i;
231 RANGE_CHECK_HI(cfg, ts_periodicity, 16);
232
233 for (i=1; i<cfg->ts_number_layers; i++)
234 if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i-1])
235 ERROR("ts_target_bitrate entries are not strictly increasing");
236
237 RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1);
238 for (i=cfg->ts_number_layers-2; i>0; i--)
239 if (cfg->ts_rate_decimator[i-1] != 2*cfg->ts_rate_decimator[i])
240 ERROR("ts_rate_decimator factors are not powers of 2");
241
242 RANGE_CHECK_HI(cfg, ts_layer_id[i], cfg->ts_number_layers-1);
243 }
244
245 #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
246 if(cfg->g_threads > (1 << vp8_cfg->token_partitions))
247 ERROR("g_threads cannot be bigger than number of token partitions");
248 #endif
249
250 return VPX_CODEC_OK;
251 }
252
253
validate_img(vpx_codec_alg_priv_t * ctx,const vpx_image_t * img)254 static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
255 const vpx_image_t *img)
256 {
257 switch (img->fmt)
258 {
259 case VPX_IMG_FMT_YV12:
260 case VPX_IMG_FMT_I420:
261 case VPX_IMG_FMT_VPXI420:
262 case VPX_IMG_FMT_VPXYV12:
263 break;
264 default:
265 ERROR("Invalid image format. Only YV12 and I420 images are supported");
266 }
267
268 if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
269 ERROR("Image size must match encoder init configuration size");
270
271 return VPX_CODEC_OK;
272 }
273
274
set_vp8e_config(VP8_CONFIG * oxcf,vpx_codec_enc_cfg_t cfg,struct vp8_extracfg vp8_cfg,vpx_codec_priv_enc_mr_cfg_t * mr_cfg)275 static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
276 vpx_codec_enc_cfg_t cfg,
277 struct vp8_extracfg vp8_cfg,
278 vpx_codec_priv_enc_mr_cfg_t *mr_cfg)
279 {
280 oxcf->multi_threaded = cfg.g_threads;
281 oxcf->Version = cfg.g_profile;
282
283 oxcf->Width = cfg.g_w;
284 oxcf->Height = cfg.g_h;
285 oxcf->timebase = cfg.g_timebase;
286
287 oxcf->error_resilient_mode = cfg.g_error_resilient;
288
289 switch (cfg.g_pass)
290 {
291 case VPX_RC_ONE_PASS:
292 oxcf->Mode = MODE_BESTQUALITY;
293 break;
294 case VPX_RC_FIRST_PASS:
295 oxcf->Mode = MODE_FIRSTPASS;
296 break;
297 case VPX_RC_LAST_PASS:
298 oxcf->Mode = MODE_SECONDPASS_BEST;
299 break;
300 }
301
302 if (cfg.g_pass == VPX_RC_FIRST_PASS || cfg.g_pass == VPX_RC_ONE_PASS)
303 {
304 oxcf->allow_lag = 0;
305 oxcf->lag_in_frames = 0;
306 }
307 else
308 {
309 oxcf->allow_lag = (cfg.g_lag_in_frames) > 0;
310 oxcf->lag_in_frames = cfg.g_lag_in_frames;
311 }
312
313 oxcf->allow_df = (cfg.rc_dropframe_thresh > 0);
314 oxcf->drop_frames_water_mark = cfg.rc_dropframe_thresh;
315
316 oxcf->allow_spatial_resampling = cfg.rc_resize_allowed;
317 oxcf->resample_up_water_mark = cfg.rc_resize_up_thresh;
318 oxcf->resample_down_water_mark = cfg.rc_resize_down_thresh;
319
320 if (cfg.rc_end_usage == VPX_VBR) {
321 oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
322 } else if (cfg.rc_end_usage == VPX_CBR) {
323 oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
324 } else if (cfg.rc_end_usage == VPX_CQ) {
325 oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
326 } else if (cfg.rc_end_usage == VPX_Q) {
327 oxcf->end_usage = USAGE_CONSTANT_QUALITY;
328 }
329
330 oxcf->target_bandwidth = cfg.rc_target_bitrate;
331 oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
332
333 oxcf->best_allowed_q = cfg.rc_min_quantizer;
334 oxcf->worst_allowed_q = cfg.rc_max_quantizer;
335 oxcf->cq_level = vp8_cfg.cq_level;
336 oxcf->fixed_q = -1;
337
338 oxcf->under_shoot_pct = cfg.rc_undershoot_pct;
339 oxcf->over_shoot_pct = cfg.rc_overshoot_pct;
340
341 oxcf->maximum_buffer_size_in_ms = cfg.rc_buf_sz;
342 oxcf->starting_buffer_level_in_ms = cfg.rc_buf_initial_sz;
343 oxcf->optimal_buffer_level_in_ms = cfg.rc_buf_optimal_sz;
344
345 oxcf->maximum_buffer_size = cfg.rc_buf_sz;
346 oxcf->starting_buffer_level = cfg.rc_buf_initial_sz;
347 oxcf->optimal_buffer_level = cfg.rc_buf_optimal_sz;
348
349 oxcf->two_pass_vbrbias = cfg.rc_2pass_vbr_bias_pct;
350 oxcf->two_pass_vbrmin_section = cfg.rc_2pass_vbr_minsection_pct;
351 oxcf->two_pass_vbrmax_section = cfg.rc_2pass_vbr_maxsection_pct;
352
353 oxcf->auto_key = cfg.kf_mode == VPX_KF_AUTO
354 && cfg.kf_min_dist != cfg.kf_max_dist;
355 oxcf->key_freq = cfg.kf_max_dist;
356
357 oxcf->number_of_layers = cfg.ts_number_layers;
358 oxcf->periodicity = cfg.ts_periodicity;
359
360 if (oxcf->number_of_layers > 1)
361 {
362 memcpy (oxcf->target_bitrate, cfg.ts_target_bitrate,
363 sizeof(cfg.ts_target_bitrate));
364 memcpy (oxcf->rate_decimator, cfg.ts_rate_decimator,
365 sizeof(cfg.ts_rate_decimator));
366 memcpy (oxcf->layer_id, cfg.ts_layer_id, sizeof(cfg.ts_layer_id));
367 }
368
369 #if CONFIG_MULTI_RES_ENCODING
370 /* When mr_cfg is NULL, oxcf->mr_total_resolutions and oxcf->mr_encoder_id
371 * are both memset to 0, which ensures the correct logic under this
372 * situation.
373 */
374 if(mr_cfg)
375 {
376 oxcf->mr_total_resolutions = mr_cfg->mr_total_resolutions;
377 oxcf->mr_encoder_id = mr_cfg->mr_encoder_id;
378 oxcf->mr_down_sampling_factor.num = mr_cfg->mr_down_sampling_factor.num;
379 oxcf->mr_down_sampling_factor.den = mr_cfg->mr_down_sampling_factor.den;
380 oxcf->mr_low_res_mode_info = mr_cfg->mr_low_res_mode_info;
381 }
382 #endif
383
384 oxcf->cpu_used = vp8_cfg.cpu_used;
385 oxcf->encode_breakout = vp8_cfg.static_thresh;
386 oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
387 oxcf->noise_sensitivity = vp8_cfg.noise_sensitivity;
388 oxcf->Sharpness = vp8_cfg.Sharpness;
389 oxcf->token_partitions = vp8_cfg.token_partitions;
390
391 oxcf->two_pass_stats_in = cfg.rc_twopass_stats_in;
392 oxcf->output_pkt_list = vp8_cfg.pkt_list;
393
394 oxcf->arnr_max_frames = vp8_cfg.arnr_max_frames;
395 oxcf->arnr_strength = vp8_cfg.arnr_strength;
396 oxcf->arnr_type = vp8_cfg.arnr_type;
397
398 oxcf->tuning = vp8_cfg.tuning;
399
400 /*
401 printf("Current VP8 Settings: \n");
402 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
403 printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
404 printf("Sharpness: %d\n", oxcf->Sharpness);
405 printf("cpu_used: %d\n", oxcf->cpu_used);
406 printf("Mode: %d\n", oxcf->Mode);
407 printf("auto_key: %d\n", oxcf->auto_key);
408 printf("key_freq: %d\n", oxcf->key_freq);
409 printf("end_usage: %d\n", oxcf->end_usage);
410 printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
411 printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
412 printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
413 printf("optimal_buffer_level: %d\n", oxcf->optimal_buffer_level);
414 printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
415 printf("fixed_q: %d\n", oxcf->fixed_q);
416 printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
417 printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
418 printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
419 printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark);
420 printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark);
421 printf("allow_df: %d\n", oxcf->allow_df);
422 printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark);
423 printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias);
424 printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
425 printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
426 printf("allow_lag: %d\n", oxcf->allow_lag);
427 printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
428 printf("play_alternate: %d\n", oxcf->play_alternate);
429 printf("Version: %d\n", oxcf->Version);
430 printf("multi_threaded: %d\n", oxcf->multi_threaded);
431 printf("encode_breakout: %d\n", oxcf->encode_breakout);
432 */
433 return VPX_CODEC_OK;
434 }
435
vp8e_set_config(vpx_codec_alg_priv_t * ctx,const vpx_codec_enc_cfg_t * cfg)436 static vpx_codec_err_t vp8e_set_config(vpx_codec_alg_priv_t *ctx,
437 const vpx_codec_enc_cfg_t *cfg)
438 {
439 vpx_codec_err_t res;
440
441 if (((cfg->g_w != ctx->cfg.g_w) || (cfg->g_h != ctx->cfg.g_h))
442 && (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS))
443 ERROR("Cannot change width or height after initialization");
444
445 /* Prevent increasing lag_in_frames. This check is stricter than it needs
446 * to be -- the limit is not increasing past the first lag_in_frames
447 * value, but we don't track the initial config, only the last successful
448 * config.
449 */
450 if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames))
451 ERROR("Cannot increase lag_in_frames");
452
453 res = validate_config(ctx, cfg, &ctx->vp8_cfg, 0);
454
455 if (!res)
456 {
457 ctx->cfg = *cfg;
458 set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
459 vp8_change_config(ctx->cpi, &ctx->oxcf);
460 }
461
462 return res;
463 }
464
465 int vp8_reverse_trans(int);
466
get_quantizer(vpx_codec_alg_priv_t * ctx,va_list args)467 static vpx_codec_err_t get_quantizer(vpx_codec_alg_priv_t *ctx, va_list args)
468 {
469 int *const arg = va_arg(args, int *);
470 if (arg == NULL)
471 return VPX_CODEC_INVALID_PARAM;
472 *arg = vp8_get_quantizer(ctx->cpi);
473 return VPX_CODEC_OK;
474 }
475
get_quantizer64(vpx_codec_alg_priv_t * ctx,va_list args)476 static vpx_codec_err_t get_quantizer64(vpx_codec_alg_priv_t *ctx, va_list args)
477 {
478 int *const arg = va_arg(args, int *);
479 if (arg == NULL)
480 return VPX_CODEC_INVALID_PARAM;
481 *arg = vp8_reverse_trans(vp8_get_quantizer(ctx->cpi));
482 return VPX_CODEC_OK;
483 }
484
update_extracfg(vpx_codec_alg_priv_t * ctx,const struct vp8_extracfg * extra_cfg)485 static vpx_codec_err_t update_extracfg(vpx_codec_alg_priv_t *ctx,
486 const struct vp8_extracfg *extra_cfg)
487 {
488 const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg, 0);
489 if (res == VPX_CODEC_OK) {
490 ctx->vp8_cfg = *extra_cfg;
491 set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
492 vp8_change_config(ctx->cpi, &ctx->oxcf);
493 }
494 return res;
495 }
496
set_cpu_used(vpx_codec_alg_priv_t * ctx,va_list args)497 static vpx_codec_err_t set_cpu_used(vpx_codec_alg_priv_t *ctx, va_list args)
498 {
499 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
500 extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args);
501 return update_extracfg(ctx, &extra_cfg);
502 }
503
set_enable_auto_alt_ref(vpx_codec_alg_priv_t * ctx,va_list args)504 static vpx_codec_err_t set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx,
505 va_list args)
506 {
507 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
508 extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args);
509 return update_extracfg(ctx, &extra_cfg);
510 }
511
set_noise_sensitivity(vpx_codec_alg_priv_t * ctx,va_list args)512 static vpx_codec_err_t set_noise_sensitivity(vpx_codec_alg_priv_t *ctx,
513 va_list args)
514 {
515 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
516 extra_cfg.noise_sensitivity = CAST(VP8E_SET_NOISE_SENSITIVITY, args);
517 return update_extracfg(ctx, &extra_cfg);
518 }
519
set_sharpness(vpx_codec_alg_priv_t * ctx,va_list args)520 static vpx_codec_err_t set_sharpness(vpx_codec_alg_priv_t *ctx, va_list args)
521 {
522 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
523 extra_cfg.Sharpness = CAST(VP8E_SET_SHARPNESS, args);
524 return update_extracfg(ctx, &extra_cfg);
525 }
526
set_static_thresh(vpx_codec_alg_priv_t * ctx,va_list args)527 static vpx_codec_err_t set_static_thresh(vpx_codec_alg_priv_t *ctx,
528 va_list args)
529 {
530 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
531 extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args);
532 return update_extracfg(ctx, &extra_cfg);
533 }
534
set_token_partitions(vpx_codec_alg_priv_t * ctx,va_list args)535 static vpx_codec_err_t set_token_partitions(vpx_codec_alg_priv_t *ctx,
536 va_list args)
537 {
538 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
539 extra_cfg.token_partitions = CAST(VP8E_SET_TOKEN_PARTITIONS, args);
540 return update_extracfg(ctx, &extra_cfg);
541 }
542
set_arnr_max_frames(vpx_codec_alg_priv_t * ctx,va_list args)543 static vpx_codec_err_t set_arnr_max_frames(vpx_codec_alg_priv_t *ctx,
544 va_list args)
545 {
546 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
547 extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args);
548 return update_extracfg(ctx, &extra_cfg);
549 }
550
set_arnr_strength(vpx_codec_alg_priv_t * ctx,va_list args)551 static vpx_codec_err_t set_arnr_strength(vpx_codec_alg_priv_t *ctx,
552 va_list args)
553 {
554 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
555 extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args);
556 return update_extracfg(ctx, &extra_cfg);
557 }
558
set_arnr_type(vpx_codec_alg_priv_t * ctx,va_list args)559 static vpx_codec_err_t set_arnr_type(vpx_codec_alg_priv_t *ctx, va_list args)
560 {
561 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
562 extra_cfg.arnr_type = CAST(VP8E_SET_ARNR_TYPE, args);
563 return update_extracfg(ctx, &extra_cfg);
564 }
565
set_tuning(vpx_codec_alg_priv_t * ctx,va_list args)566 static vpx_codec_err_t set_tuning(vpx_codec_alg_priv_t *ctx, va_list args)
567 {
568 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
569 extra_cfg.tuning = CAST(VP8E_SET_TUNING, args);
570 return update_extracfg(ctx, &extra_cfg);
571 }
572
set_cq_level(vpx_codec_alg_priv_t * ctx,va_list args)573 static vpx_codec_err_t set_cq_level(vpx_codec_alg_priv_t *ctx, va_list args)
574 {
575 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
576 extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args);
577 return update_extracfg(ctx, &extra_cfg);
578 }
579
set_rc_max_intra_bitrate_pct(vpx_codec_alg_priv_t * ctx,va_list args)580 static vpx_codec_err_t set_rc_max_intra_bitrate_pct(vpx_codec_alg_priv_t *ctx,
581 va_list args)
582 {
583 struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
584 extra_cfg.rc_max_intra_bitrate_pct =
585 CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args);
586 return update_extracfg(ctx, &extra_cfg);
587 }
588
vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t * cfg,void ** mem_loc)589 static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg,
590 void **mem_loc)
591 {
592 vpx_codec_err_t res = 0;
593
594 #if CONFIG_MULTI_RES_ENCODING
595 LOWER_RES_FRAME_INFO *shared_mem_loc;
596 int mb_rows = ((cfg->g_w + 15) >>4);
597 int mb_cols = ((cfg->g_h + 15) >>4);
598
599 shared_mem_loc = calloc(1, sizeof(LOWER_RES_FRAME_INFO));
600 if(!shared_mem_loc)
601 {
602 res = VPX_CODEC_MEM_ERROR;
603 }
604
605 shared_mem_loc->mb_info = calloc(mb_rows*mb_cols, sizeof(LOWER_RES_MB_INFO));
606 if(!(shared_mem_loc->mb_info))
607 {
608 res = VPX_CODEC_MEM_ERROR;
609 }
610 else
611 {
612 *mem_loc = (void *)shared_mem_loc;
613 res = VPX_CODEC_OK;
614 }
615 #endif
616 return res;
617 }
618
vp8e_init(vpx_codec_ctx_t * ctx,vpx_codec_priv_enc_mr_cfg_t * mr_cfg)619 static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx,
620 vpx_codec_priv_enc_mr_cfg_t *mr_cfg)
621 {
622 vpx_codec_err_t res = VPX_CODEC_OK;
623
624
625 vp8_rtcd();
626
627 if (!ctx->priv)
628 {
629 struct vpx_codec_alg_priv *priv =
630 (struct vpx_codec_alg_priv *)vpx_calloc(1, sizeof(*priv));
631
632 if (!priv)
633 {
634 return VPX_CODEC_MEM_ERROR;
635 }
636
637 ctx->priv = (vpx_codec_priv_t *)priv;
638 ctx->priv->init_flags = ctx->init_flags;
639
640 if (ctx->config.enc)
641 {
642 /* Update the reference to the config structure to an
643 * internal copy.
644 */
645 priv->cfg = *ctx->config.enc;
646 ctx->config.enc = &priv->cfg;
647 }
648
649 priv->vp8_cfg = default_extracfg;
650 priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
651
652 priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
653
654 if (priv->cx_data_sz < 32768) priv->cx_data_sz = 32768;
655
656 priv->cx_data = malloc(priv->cx_data_sz);
657
658 if (!priv->cx_data)
659 {
660 return VPX_CODEC_MEM_ERROR;
661 }
662
663 if(mr_cfg)
664 ctx->priv->enc.total_encoders = mr_cfg->mr_total_resolutions;
665 else
666 ctx->priv->enc.total_encoders = 1;
667
668 res = validate_config(priv, &priv->cfg, &priv->vp8_cfg, 0);
669
670 if (!res)
671 {
672 set_vp8e_config(&priv->oxcf, priv->cfg, priv->vp8_cfg, mr_cfg);
673 priv->cpi = vp8_create_compressor(&priv->oxcf);
674 if (!priv->cpi)
675 res = VPX_CODEC_MEM_ERROR;
676 }
677 }
678
679 return res;
680 }
681
vp8e_destroy(vpx_codec_alg_priv_t * ctx)682 static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx)
683 {
684 #if CONFIG_MULTI_RES_ENCODING
685 /* Free multi-encoder shared memory */
686 if (ctx->oxcf.mr_total_resolutions > 0 && (ctx->oxcf.mr_encoder_id == ctx->oxcf.mr_total_resolutions-1))
687 {
688 LOWER_RES_FRAME_INFO *shared_mem_loc = (LOWER_RES_FRAME_INFO *)ctx->oxcf.mr_low_res_mode_info;
689 free(shared_mem_loc->mb_info);
690 free(ctx->oxcf.mr_low_res_mode_info);
691 }
692 #endif
693
694 free(ctx->cx_data);
695 vp8_remove_compressor(&ctx->cpi);
696 vpx_free(ctx);
697 return VPX_CODEC_OK;
698 }
699
image2yuvconfig(const vpx_image_t * img,YV12_BUFFER_CONFIG * yv12)700 static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
701 YV12_BUFFER_CONFIG *yv12)
702 {
703 const int y_w = img->d_w;
704 const int y_h = img->d_h;
705 const int uv_w = (img->d_w + 1) / 2;
706 const int uv_h = (img->d_h + 1) / 2;
707 vpx_codec_err_t res = VPX_CODEC_OK;
708 yv12->y_buffer = img->planes[VPX_PLANE_Y];
709 yv12->u_buffer = img->planes[VPX_PLANE_U];
710 yv12->v_buffer = img->planes[VPX_PLANE_V];
711
712 yv12->y_crop_width = y_w;
713 yv12->y_crop_height = y_h;
714 yv12->y_width = y_w;
715 yv12->y_height = y_h;
716 yv12->uv_crop_width = uv_w;
717 yv12->uv_crop_height = uv_h;
718 yv12->uv_width = uv_w;
719 yv12->uv_height = uv_h;
720
721 yv12->y_stride = img->stride[VPX_PLANE_Y];
722 yv12->uv_stride = img->stride[VPX_PLANE_U];
723
724 yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2;
725 return res;
726 }
727
pick_quickcompress_mode(vpx_codec_alg_priv_t * ctx,unsigned long duration,unsigned long deadline)728 static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
729 unsigned long duration,
730 unsigned long deadline)
731 {
732 unsigned int new_qc;
733
734 #if !(CONFIG_REALTIME_ONLY)
735 /* Use best quality mode if no deadline is given. */
736 new_qc = MODE_BESTQUALITY;
737
738 if (deadline)
739 {
740 uint64_t duration_us;
741
742 /* Convert duration parameter from stream timebase to microseconds */
743 duration_us = (uint64_t)duration * 1000000
744 * (uint64_t)ctx->cfg.g_timebase.num
745 / (uint64_t)ctx->cfg.g_timebase.den;
746
747 /* If the deadline is more that the duration this frame is to be shown,
748 * use good quality mode. Otherwise use realtime mode.
749 */
750 new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
751 }
752
753 #else
754 new_qc = MODE_REALTIME;
755 #endif
756
757 if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
758 new_qc = MODE_FIRSTPASS;
759 else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
760 new_qc = (new_qc == MODE_BESTQUALITY)
761 ? MODE_SECONDPASS_BEST
762 : MODE_SECONDPASS;
763
764 if (ctx->oxcf.Mode != new_qc)
765 {
766 ctx->oxcf.Mode = new_qc;
767 vp8_change_config(ctx->cpi, &ctx->oxcf);
768 }
769 }
770
771
vp8e_encode(vpx_codec_alg_priv_t * ctx,const vpx_image_t * img,vpx_codec_pts_t pts,unsigned long duration,vpx_enc_frame_flags_t flags,unsigned long deadline)772 static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
773 const vpx_image_t *img,
774 vpx_codec_pts_t pts,
775 unsigned long duration,
776 vpx_enc_frame_flags_t flags,
777 unsigned long deadline)
778 {
779 vpx_codec_err_t res = VPX_CODEC_OK;
780
781 if (!ctx->cfg.rc_target_bitrate)
782 return res;
783
784 if (img)
785 res = validate_img(ctx, img);
786
787 if (!res)
788 res = validate_config(ctx, &ctx->cfg, &ctx->vp8_cfg, 1);
789
790 pick_quickcompress_mode(ctx, duration, deadline);
791 vpx_codec_pkt_list_init(&ctx->pkt_list);
792
793 /* Handle Flags */
794 if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF))
795 || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF)))
796 {
797 ctx->base.err_detail = "Conflicting flags.";
798 return VPX_CODEC_INVALID_PARAM;
799 }
800
801 if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF
802 | VP8_EFLAG_NO_REF_ARF))
803 {
804 int ref = 7;
805
806 if (flags & VP8_EFLAG_NO_REF_LAST)
807 ref ^= VP8_LAST_FRAME;
808
809 if (flags & VP8_EFLAG_NO_REF_GF)
810 ref ^= VP8_GOLD_FRAME;
811
812 if (flags & VP8_EFLAG_NO_REF_ARF)
813 ref ^= VP8_ALTR_FRAME;
814
815 vp8_use_as_reference(ctx->cpi, ref);
816 }
817
818 if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF
819 | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF
820 | VP8_EFLAG_FORCE_ARF))
821 {
822 int upd = 7;
823
824 if (flags & VP8_EFLAG_NO_UPD_LAST)
825 upd ^= VP8_LAST_FRAME;
826
827 if (flags & VP8_EFLAG_NO_UPD_GF)
828 upd ^= VP8_GOLD_FRAME;
829
830 if (flags & VP8_EFLAG_NO_UPD_ARF)
831 upd ^= VP8_ALTR_FRAME;
832
833 vp8_update_reference(ctx->cpi, upd);
834 }
835
836 if (flags & VP8_EFLAG_NO_UPD_ENTROPY)
837 {
838 vp8_update_entropy(ctx->cpi, 0);
839 }
840
841 /* Handle fixed keyframe intervals */
842 if (ctx->cfg.kf_mode == VPX_KF_AUTO
843 && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist)
844 {
845 if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist)
846 {
847 flags |= VPX_EFLAG_FORCE_KF;
848 ctx->fixed_kf_cntr = 1;
849 }
850 }
851
852 /* Initialize the encoder instance on the first frame*/
853 if (!res && ctx->cpi)
854 {
855 unsigned int lib_flags;
856 YV12_BUFFER_CONFIG sd;
857 int64_t dst_time_stamp, dst_end_time_stamp;
858 unsigned long size, cx_data_sz;
859 unsigned char *cx_data;
860 unsigned char *cx_data_end;
861 int comp_data_state = 0;
862
863 /* Set up internal flags */
864 if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
865 ((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 1;
866
867 if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
868 ((VP8_COMP *)ctx->cpi)->output_partition = 1;
869
870 /* Convert API flags to internal codec lib flags */
871 lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;
872
873 /* vp8 use 10,000,000 ticks/second as time stamp */
874 dst_time_stamp = pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
875 dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
876
877 if (img != NULL)
878 {
879 res = image2yuvconfig(img, &sd);
880
881 if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags,
882 &sd, dst_time_stamp, dst_end_time_stamp))
883 {
884 VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
885 res = update_error_state(ctx, &cpi->common.error);
886 }
887
888 /* reset for next frame */
889 ctx->next_frame_flag = 0;
890 }
891
892 cx_data = ctx->cx_data;
893 cx_data_sz = ctx->cx_data_sz;
894 cx_data_end = ctx->cx_data + cx_data_sz;
895 lib_flags = 0;
896
897 while (cx_data_sz >= ctx->cx_data_sz / 2)
898 {
899 comp_data_state = vp8_get_compressed_data(ctx->cpi,
900 &lib_flags,
901 &size,
902 cx_data,
903 cx_data_end,
904 &dst_time_stamp,
905 &dst_end_time_stamp,
906 !img);
907
908 if(comp_data_state == VPX_CODEC_CORRUPT_FRAME)
909 return VPX_CODEC_CORRUPT_FRAME;
910 else if(comp_data_state == -1)
911 break;
912
913 if (size)
914 {
915 vpx_codec_pts_t round, delta;
916 vpx_codec_cx_pkt_t pkt;
917 VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
918
919 /* Add the frame packet to the list of returned packets. */
920 round = (vpx_codec_pts_t)10000000
921 * ctx->cfg.g_timebase.num / 2 - 1;
922 delta = (dst_end_time_stamp - dst_time_stamp);
923 pkt.kind = VPX_CODEC_CX_FRAME_PKT;
924 pkt.data.frame.pts =
925 (dst_time_stamp * ctx->cfg.g_timebase.den + round)
926 / ctx->cfg.g_timebase.num / 10000000;
927 pkt.data.frame.duration = (unsigned long)
928 ((delta * ctx->cfg.g_timebase.den + round)
929 / ctx->cfg.g_timebase.num / 10000000);
930 pkt.data.frame.flags = lib_flags << 16;
931
932 if (lib_flags & FRAMEFLAGS_KEY)
933 pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
934
935 if (!cpi->common.show_frame)
936 {
937 pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
938
939 /* This timestamp should be as close as possible to the
940 * prior PTS so that if a decoder uses pts to schedule when
941 * to do this, we start right after last frame was decoded.
942 * Invisible frames have no duration.
943 */
944 pkt.data.frame.pts = ((cpi->last_time_stamp_seen
945 * ctx->cfg.g_timebase.den + round)
946 / ctx->cfg.g_timebase.num / 10000000) + 1;
947 pkt.data.frame.duration = 0;
948 }
949
950 if (cpi->droppable)
951 pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;
952
953 if (cpi->output_partition)
954 {
955 int i;
956 const int num_partitions =
957 (1 << cpi->common.multi_token_partition) + 1;
958
959 pkt.data.frame.flags |= VPX_FRAME_IS_FRAGMENT;
960
961 for (i = 0; i < num_partitions; ++i)
962 {
963 #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
964 pkt.data.frame.buf = cpi->partition_d[i];
965 #else
966 pkt.data.frame.buf = cx_data;
967 cx_data += cpi->partition_sz[i];
968 cx_data_sz -= cpi->partition_sz[i];
969 #endif
970 pkt.data.frame.sz = cpi->partition_sz[i];
971 pkt.data.frame.partition_id = i;
972 /* don't set the fragment bit for the last partition */
973 if (i == (num_partitions - 1))
974 pkt.data.frame.flags &= ~VPX_FRAME_IS_FRAGMENT;
975 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
976 }
977 #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
978 /* In lagged mode the encoder can buffer multiple frames.
979 * We don't want this in partitioned output because
980 * partitions are spread all over the output buffer.
981 * So, force an exit!
982 */
983 cx_data_sz -= ctx->cx_data_sz / 2;
984 #endif
985 }
986 else
987 {
988 pkt.data.frame.buf = cx_data;
989 pkt.data.frame.sz = size;
990 pkt.data.frame.partition_id = -1;
991 vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
992 cx_data += size;
993 cx_data_sz -= size;
994 }
995 }
996 }
997 }
998
999 return res;
1000 }
1001
1002
vp8e_get_cxdata(vpx_codec_alg_priv_t * ctx,vpx_codec_iter_t * iter)1003 static const vpx_codec_cx_pkt_t *vp8e_get_cxdata(vpx_codec_alg_priv_t *ctx,
1004 vpx_codec_iter_t *iter)
1005 {
1006 return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
1007 }
1008
vp8e_set_reference(vpx_codec_alg_priv_t * ctx,va_list args)1009 static vpx_codec_err_t vp8e_set_reference(vpx_codec_alg_priv_t *ctx,
1010 va_list args)
1011 {
1012 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
1013
1014 if (data)
1015 {
1016 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
1017 YV12_BUFFER_CONFIG sd;
1018
1019 image2yuvconfig(&frame->img, &sd);
1020 vp8_set_reference(ctx->cpi, frame->frame_type, &sd);
1021 return VPX_CODEC_OK;
1022 }
1023 else
1024 return VPX_CODEC_INVALID_PARAM;
1025
1026 }
1027
vp8e_get_reference(vpx_codec_alg_priv_t * ctx,va_list args)1028 static vpx_codec_err_t vp8e_get_reference(vpx_codec_alg_priv_t *ctx,
1029 va_list args)
1030 {
1031
1032 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
1033
1034 if (data)
1035 {
1036 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
1037 YV12_BUFFER_CONFIG sd;
1038
1039 image2yuvconfig(&frame->img, &sd);
1040 vp8_get_reference(ctx->cpi, frame->frame_type, &sd);
1041 return VPX_CODEC_OK;
1042 }
1043 else
1044 return VPX_CODEC_INVALID_PARAM;
1045 }
1046
vp8e_set_previewpp(vpx_codec_alg_priv_t * ctx,va_list args)1047 static vpx_codec_err_t vp8e_set_previewpp(vpx_codec_alg_priv_t *ctx,
1048 va_list args)
1049 {
1050 #if CONFIG_POSTPROC
1051 vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
1052
1053 if (data)
1054 {
1055 ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
1056 return VPX_CODEC_OK;
1057 }
1058 else
1059 return VPX_CODEC_INVALID_PARAM;
1060 #else
1061 (void)ctx;
1062 (void)args;
1063 return VPX_CODEC_INCAPABLE;
1064 #endif
1065 }
1066
1067
vp8e_get_preview(vpx_codec_alg_priv_t * ctx)1068 static vpx_image_t *vp8e_get_preview(vpx_codec_alg_priv_t *ctx)
1069 {
1070
1071 YV12_BUFFER_CONFIG sd;
1072 vp8_ppflags_t flags = {0};
1073
1074 if (ctx->preview_ppcfg.post_proc_flag)
1075 {
1076 flags.post_proc_flag = ctx->preview_ppcfg.post_proc_flag;
1077 flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
1078 flags.noise_level = ctx->preview_ppcfg.noise_level;
1079 }
1080
1081 if (0 == vp8_get_preview_raw_frame(ctx->cpi, &sd, &flags))
1082 {
1083
1084 /*
1085 vpx_img_wrap(&ctx->preview_img, VPX_IMG_FMT_YV12,
1086 sd.y_width + 2*VP8BORDERINPIXELS,
1087 sd.y_height + 2*VP8BORDERINPIXELS,
1088 1,
1089 sd.buffer_alloc);
1090 vpx_img_set_rect(&ctx->preview_img,
1091 VP8BORDERINPIXELS, VP8BORDERINPIXELS,
1092 sd.y_width, sd.y_height);
1093 */
1094
1095 ctx->preview_img.bps = 12;
1096 ctx->preview_img.planes[VPX_PLANE_Y] = sd.y_buffer;
1097 ctx->preview_img.planes[VPX_PLANE_U] = sd.u_buffer;
1098 ctx->preview_img.planes[VPX_PLANE_V] = sd.v_buffer;
1099
1100 ctx->preview_img.fmt = VPX_IMG_FMT_I420;
1101 ctx->preview_img.x_chroma_shift = 1;
1102 ctx->preview_img.y_chroma_shift = 1;
1103
1104 ctx->preview_img.d_w = sd.y_width;
1105 ctx->preview_img.d_h = sd.y_height;
1106 ctx->preview_img.stride[VPX_PLANE_Y] = sd.y_stride;
1107 ctx->preview_img.stride[VPX_PLANE_U] = sd.uv_stride;
1108 ctx->preview_img.stride[VPX_PLANE_V] = sd.uv_stride;
1109 ctx->preview_img.w = sd.y_width;
1110 ctx->preview_img.h = sd.y_height;
1111
1112 return &ctx->preview_img;
1113 }
1114 else
1115 return NULL;
1116 }
1117
vp8e_update_entropy(vpx_codec_alg_priv_t * ctx,va_list args)1118 static vpx_codec_err_t vp8e_update_entropy(vpx_codec_alg_priv_t *ctx,
1119 va_list args)
1120 {
1121 int update = va_arg(args, int);
1122 vp8_update_entropy(ctx->cpi, update);
1123 return VPX_CODEC_OK;
1124
1125 }
1126
vp8e_update_reference(vpx_codec_alg_priv_t * ctx,va_list args)1127 static vpx_codec_err_t vp8e_update_reference(vpx_codec_alg_priv_t *ctx,
1128 va_list args)
1129 {
1130 int update = va_arg(args, int);
1131 vp8_update_reference(ctx->cpi, update);
1132 return VPX_CODEC_OK;
1133 }
1134
vp8e_use_reference(vpx_codec_alg_priv_t * ctx,va_list args)1135 static vpx_codec_err_t vp8e_use_reference(vpx_codec_alg_priv_t *ctx,
1136 va_list args)
1137 {
1138 int reference_flag = va_arg(args, int);
1139 vp8_use_as_reference(ctx->cpi, reference_flag);
1140 return VPX_CODEC_OK;
1141 }
1142
vp8e_set_roi_map(vpx_codec_alg_priv_t * ctx,va_list args)1143 static vpx_codec_err_t vp8e_set_roi_map(vpx_codec_alg_priv_t *ctx,
1144 va_list args)
1145 {
1146 vpx_roi_map_t *data = va_arg(args, vpx_roi_map_t *);
1147
1148 if (data)
1149 {
1150 vpx_roi_map_t *roi = (vpx_roi_map_t *)data;
1151
1152 if (!vp8_set_roimap(ctx->cpi, roi->roi_map, roi->rows, roi->cols, roi->delta_q, roi->delta_lf, roi->static_threshold))
1153 return VPX_CODEC_OK;
1154 else
1155 return VPX_CODEC_INVALID_PARAM;
1156 }
1157 else
1158 return VPX_CODEC_INVALID_PARAM;
1159 }
1160
1161
vp8e_set_activemap(vpx_codec_alg_priv_t * ctx,va_list args)1162 static vpx_codec_err_t vp8e_set_activemap(vpx_codec_alg_priv_t *ctx,
1163 va_list args)
1164 {
1165 vpx_active_map_t *data = va_arg(args, vpx_active_map_t *);
1166
1167 if (data)
1168 {
1169
1170 vpx_active_map_t *map = (vpx_active_map_t *)data;
1171
1172 if (!vp8_set_active_map(ctx->cpi, map->active_map, map->rows, map->cols))
1173 return VPX_CODEC_OK;
1174 else
1175 return VPX_CODEC_INVALID_PARAM;
1176 }
1177 else
1178 return VPX_CODEC_INVALID_PARAM;
1179 }
1180
vp8e_set_scalemode(vpx_codec_alg_priv_t * ctx,va_list args)1181 static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx,
1182 va_list args)
1183 {
1184
1185 vpx_scaling_mode_t *data = va_arg(args, vpx_scaling_mode_t *);
1186
1187 if (data)
1188 {
1189 int res;
1190 vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data ;
1191 res = vp8_set_internal_size(ctx->cpi,
1192 (VPX_SCALING)scalemode.h_scaling_mode,
1193 (VPX_SCALING)scalemode.v_scaling_mode);
1194
1195 if (!res)
1196 {
1197 /*force next frame a key frame to effect scaling mode */
1198 ctx->next_frame_flag |= FRAMEFLAGS_KEY;
1199 return VPX_CODEC_OK;
1200 }
1201 else
1202 return VPX_CODEC_INVALID_PARAM;
1203 }
1204 else
1205 return VPX_CODEC_INVALID_PARAM;
1206 }
1207
1208
1209 static vpx_codec_ctrl_fn_map_t vp8e_ctf_maps[] =
1210 {
1211 {VP8_SET_REFERENCE, vp8e_set_reference},
1212 {VP8_COPY_REFERENCE, vp8e_get_reference},
1213 {VP8_SET_POSTPROC, vp8e_set_previewpp},
1214 {VP8E_UPD_ENTROPY, vp8e_update_entropy},
1215 {VP8E_UPD_REFERENCE, vp8e_update_reference},
1216 {VP8E_USE_REFERENCE, vp8e_use_reference},
1217 {VP8E_SET_ROI_MAP, vp8e_set_roi_map},
1218 {VP8E_SET_ACTIVEMAP, vp8e_set_activemap},
1219 {VP8E_SET_SCALEMODE, vp8e_set_scalemode},
1220 {VP8E_SET_CPUUSED, set_cpu_used},
1221 {VP8E_SET_NOISE_SENSITIVITY, set_noise_sensitivity},
1222 {VP8E_SET_ENABLEAUTOALTREF, set_enable_auto_alt_ref},
1223 {VP8E_SET_SHARPNESS, set_sharpness},
1224 {VP8E_SET_STATIC_THRESHOLD, set_static_thresh},
1225 {VP8E_SET_TOKEN_PARTITIONS, set_token_partitions},
1226 {VP8E_GET_LAST_QUANTIZER, get_quantizer},
1227 {VP8E_GET_LAST_QUANTIZER_64, get_quantizer64},
1228 {VP8E_SET_ARNR_MAXFRAMES, set_arnr_max_frames},
1229 {VP8E_SET_ARNR_STRENGTH , set_arnr_strength},
1230 {VP8E_SET_ARNR_TYPE , set_arnr_type},
1231 {VP8E_SET_TUNING, set_tuning},
1232 {VP8E_SET_CQ_LEVEL, set_cq_level},
1233 {VP8E_SET_MAX_INTRA_BITRATE_PCT, set_rc_max_intra_bitrate_pct},
1234 { -1, NULL},
1235 };
1236
1237 static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] =
1238 {
1239 {
1240 0,
1241 {
1242 0, /* g_usage */
1243 0, /* g_threads */
1244 0, /* g_profile */
1245
1246 320, /* g_width */
1247 240, /* g_height */
1248 VPX_BITS_8, /* g_bit_depth */
1249 8, /* g_input_bit_depth */
1250
1251 {1, 30}, /* g_timebase */
1252
1253 0, /* g_error_resilient */
1254
1255 VPX_RC_ONE_PASS, /* g_pass */
1256
1257 0, /* g_lag_in_frames */
1258
1259 0, /* rc_dropframe_thresh */
1260 0, /* rc_resize_allowed */
1261 1, /* rc_scaled_width */
1262 1, /* rc_scaled_height */
1263 60, /* rc_resize_down_thresold */
1264 30, /* rc_resize_up_thresold */
1265
1266 VPX_VBR, /* rc_end_usage */
1267 #if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
1268 {0}, /* rc_twopass_stats_in */
1269 {0}, /* rc_firstpass_mb_stats_in */
1270 #endif
1271 256, /* rc_target_bandwidth */
1272 4, /* rc_min_quantizer */
1273 63, /* rc_max_quantizer */
1274 100, /* rc_undershoot_pct */
1275 100, /* rc_overshoot_pct */
1276
1277 6000, /* rc_max_buffer_size */
1278 4000, /* rc_buffer_initial_size; */
1279 5000, /* rc_buffer_optimal_size; */
1280
1281 50, /* rc_two_pass_vbrbias */
1282 0, /* rc_two_pass_vbrmin_section */
1283 400, /* rc_two_pass_vbrmax_section */
1284
1285 /* keyframing settings (kf) */
1286 VPX_KF_AUTO, /* g_kfmode*/
1287 0, /* kf_min_dist */
1288 128, /* kf_max_dist */
1289
1290 #if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
1291 "vp8.fpf" /* first pass filename */
1292 #endif
1293 VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */
1294 {0},
1295 {0}, /* ss_target_bitrate */
1296 1, /* ts_number_layers */
1297 {0}, /* ts_target_bitrate */
1298 {0}, /* ts_rate_decimator */
1299 0, /* ts_periodicity */
1300 {0}, /* ts_layer_id */
1301 }},
1302 };
1303
1304
1305 #ifndef VERSION_STRING
1306 #define VERSION_STRING
1307 #endif
1308 CODEC_INTERFACE(vpx_codec_vp8_cx) =
1309 {
1310 "WebM Project VP8 Encoder" VERSION_STRING,
1311 VPX_CODEC_INTERNAL_ABI_VERSION,
1312 VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR |
1313 VPX_CODEC_CAP_OUTPUT_PARTITION,
1314 /* vpx_codec_caps_t caps; */
1315 vp8e_init, /* vpx_codec_init_fn_t init; */
1316 vp8e_destroy, /* vpx_codec_destroy_fn_t destroy; */
1317 vp8e_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */
1318 {
1319 NULL, /* vpx_codec_peek_si_fn_t peek_si; */
1320 NULL, /* vpx_codec_get_si_fn_t get_si; */
1321 NULL, /* vpx_codec_decode_fn_t decode; */
1322 NULL, /* vpx_codec_frame_get_fn_t frame_get; */
1323 },
1324 {
1325 1, /* 1 cfg map */
1326 vp8e_usage_cfg_map, /* vpx_codec_enc_cfg_map_t peek_si; */
1327 vp8e_encode, /* vpx_codec_encode_fn_t encode; */
1328 vp8e_get_cxdata, /* vpx_codec_get_cx_data_fn_t frame_get; */
1329 vp8e_set_config,
1330 NULL,
1331 vp8e_get_preview,
1332 vp8e_mr_alloc_mem,
1333 } /* encoder functions */
1334 };
1335