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