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