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