vp8_cx_iface.c 47.3 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
6
 *  that can be found in the LICENSE file in the root of the source
 *  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.
John Koleszar's avatar
John Koleszar committed
9
10
11
 */


12
#include "./vpx_config.h"
13
#include "./vp8_rtcd.h"
Johann's avatar
Johann committed
14
#include "./vpx_dsp_rtcd.h"
15
#include "./vpx_scale_rtcd.h"
16
17
#include "vpx/vpx_codec.h"
#include "vpx/internal/vpx_codec_internal.h"
John Koleszar's avatar
John Koleszar committed
18
#include "vpx_version.h"
19
#include "vpx_mem/vpx_mem.h"
John Koleszar's avatar
John Koleszar committed
20
#include "vp8/encoder/onyx_int.h"
21
#include "vpx/vp8cx.h"
22
#include "vp8/encoder/firstpass.h"
John Koleszar's avatar
John Koleszar committed
23
#include "vp8/common/onyx.h"
John Koleszar's avatar
John Koleszar committed
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdlib.h>
#include <string.h>

struct vp8_extracfg
{
    struct vpx_codec_pkt_list *pkt_list;
    int                         cpu_used;                    /** available cpu percentage in 1/16*/
    unsigned int                enable_auto_alt_ref;           /** if encoder decides to uses alternate reference frame */
    unsigned int                noise_sensitivity;
    unsigned int                Sharpness;
    unsigned int                static_thresh;
    unsigned int                token_partitions;
    unsigned int                arnr_max_frames;    /* alt_ref Noise Reduction Max Frame Count */
    unsigned int                arnr_strength;    /* alt_ref Noise Reduction Strength */
    unsigned int                arnr_type;        /* alt_ref filter type */
John Koleszar's avatar
John Koleszar committed
39
    vp8e_tuning                 tuning;
Paul Wilkins's avatar
CQ Mode    
Paul Wilkins committed
40
    unsigned int                cq_level;         /* constrained quality level */
41
    unsigned int                rc_max_intra_bitrate_pct;
Marco's avatar
Marco committed
42
    unsigned int                screen_content_mode;
John Koleszar's avatar
John Koleszar committed
43
44
45

};

46
47
static struct vp8_extracfg default_extracfg = {
  NULL,
John Koleszar's avatar
John Koleszar committed
48
#if !(CONFIG_REALTIME_ONLY)
49
  0,                          /* cpu_used      */
John Koleszar's avatar
John Koleszar committed
50
#else
51
  4,                          /* cpu_used      */
John Koleszar's avatar
John Koleszar committed
52
#endif
53
54
55
56
  0,                          /* enable_auto_alt_ref */
  0,                          /* noise_sensitivity */
  0,                          /* Sharpness */
  0,                          /* static_thresh */
57
#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
58
  VP8_EIGHT_TOKENPARTITION,
59
#else
60
  VP8_ONE_TOKENPARTITION,     /* token_partitions */
61
#endif
62
63
64
65
66
67
  0,                          /* arnr_max_frames */
  3,                          /* arnr_strength */
  3,                          /* arnr_type*/
  0,                          /* tuning*/
  10,                         /* cq_level */
  0,                          /* rc_max_intra_bitrate_pct */
Marco's avatar
Marco committed
68
  0,                          /* screen_content_mode */
John Koleszar's avatar
John Koleszar committed
69
70
71
72
73
74
75
76
};

struct vpx_codec_alg_priv
{
    vpx_codec_priv_t        base;
    vpx_codec_enc_cfg_t     cfg;
    struct vp8_extracfg     vp8_cfg;
    VP8_CONFIG              oxcf;
John Koleszar's avatar
John Koleszar committed
77
    struct VP8_COMP        *cpi;
John Koleszar's avatar
John Koleszar committed
78
79
80
81
82
    unsigned char          *cx_data;
    unsigned int            cx_data_sz;
    vpx_image_t             preview_img;
    unsigned int            next_frame_flag;
    vp8_postproc_cfg_t      preview_ppcfg;
John Koleszar's avatar
John Koleszar committed
83
84
    /* pkt_list size depends on the maximum number of lagged frames allowed. */
    vpx_codec_pkt_list_decl(64) pkt_list;
John Koleszar's avatar
John Koleszar committed
85
    unsigned int                fixed_kf_cntr;
Marco's avatar
Marco committed
86
    vpx_enc_frame_flags_t   control_frame_flags;
John Koleszar's avatar
John Koleszar committed
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
};


static vpx_codec_err_t
update_error_state(vpx_codec_alg_priv_t                 *ctx,
                   const struct vpx_internal_error_info *error)
{
    vpx_codec_err_t res;

    if ((res = error->error_code))
        ctx->base.err_detail = error->has_detail
                               ? error->detail
                               : NULL;

    return res;
}


105
#undef ERROR
John Koleszar's avatar
John Koleszar committed
106
107
108
109
110
111
#define ERROR(str) do {\
        ctx->base.err_detail = str;\
        return VPX_CODEC_INVALID_PARAM;\
    } while(0)

#define RANGE_CHECK(p,memb,lo,hi) do {\
112
        if(!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
John Koleszar's avatar
John Koleszar committed
113
114
115
            ERROR(#memb " out of range ["#lo".."#hi"]");\
    } while(0)

116
117
118
119
120
#define RANGE_CHECK_HI(p,memb,hi) do {\
        if(!((p)->memb <= (hi))) \
            ERROR(#memb " out of range [.."#hi"]");\
    } while(0)

John Koleszar's avatar
John Koleszar committed
121
122
123
124
125
126
127
128
129
130
131
#define RANGE_CHECK_LO(p,memb,lo) do {\
        if(!((p)->memb >= (lo))) \
            ERROR(#memb " out of range ["#lo"..]");\
    } while(0)

#define RANGE_CHECK_BOOL(p,memb) do {\
        if(!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
    } while(0)

static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t      *ctx,
                                       const vpx_codec_enc_cfg_t *cfg,
132
133
                                       const struct vp8_extracfg *vp8_cfg,
                                       int                        finalize)
John Koleszar's avatar
John Koleszar committed
134
{
135
136
    RANGE_CHECK(cfg, g_w,                   1, 16383); /* 14 bits available */
    RANGE_CHECK(cfg, g_h,                   1, 16383); /* 14 bits available */
John Koleszar's avatar
John Koleszar committed
137
    RANGE_CHECK(cfg, g_timebase.den,        1, 1000000000);
138
    RANGE_CHECK(cfg, g_timebase.num,        1, 1000000000);
139
140
    RANGE_CHECK_HI(cfg, g_profile,          3);
    RANGE_CHECK_HI(cfg, rc_max_quantizer,   63);
John Koleszar's avatar
John Koleszar committed
141
    RANGE_CHECK_HI(cfg, rc_min_quantizer,   cfg->rc_max_quantizer);
142
    RANGE_CHECK_HI(cfg, g_threads,          64);
143
#if CONFIG_REALTIME_ONLY
144
    RANGE_CHECK_HI(cfg, g_lag_in_frames,    0);
145
146
147
148
149
#elif CONFIG_MULTI_RES_ENCODING
    if (ctx->base.enc.total_encoders > 1)
        RANGE_CHECK_HI(cfg, g_lag_in_frames,    0);
#else
    RANGE_CHECK_HI(cfg, g_lag_in_frames,    25);
John Koleszar's avatar
John Koleszar committed
150
#endif
151
    RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_Q);
152
153
    RANGE_CHECK_HI(cfg, rc_undershoot_pct,  1000);
    RANGE_CHECK_HI(cfg, rc_overshoot_pct,   1000);
154
    RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
John Koleszar's avatar
John Koleszar committed
155
    RANGE_CHECK(cfg, kf_mode,               VPX_KF_DISABLED, VPX_KF_AUTO);
156
157
158
159
160
161
162
163
164

/* TODO: add spatial re-sampling support and frame dropping in
 * multi-res-encoder.*/
#if CONFIG_MULTI_RES_ENCODING
    if (ctx->base.enc.total_encoders > 1)
        RANGE_CHECK_HI(cfg, rc_resize_allowed,     0);
#else
    RANGE_CHECK_BOOL(cfg, rc_resize_allowed);
#endif
165
    RANGE_CHECK_HI(cfg, rc_dropframe_thresh,   100);
166
167
    RANGE_CHECK_HI(cfg, rc_resize_up_thresh,   100);
    RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
168
169

#if CONFIG_REALTIME_ONLY
John Koleszar's avatar
John Koleszar committed
170
    RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
171
172
173
174
175
#elif CONFIG_MULTI_RES_ENCODING
    if (ctx->base.enc.total_encoders > 1)
        RANGE_CHECK(cfg,    g_pass,         VPX_RC_ONE_PASS, VPX_RC_ONE_PASS);
#else
    RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
John Koleszar's avatar
John Koleszar committed
176
177
178
179
180
181
182
183
184
185
186
#endif

    /* VP8 does not support a lower bound on the keyframe interval in
     * automatic keyframe placement mode.
     */
    if (cfg->kf_mode != VPX_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist
        && cfg->kf_min_dist > 0)
        ERROR("kf_min_dist not supported in auto mode, use 0 "
              "or kf_max_dist instead.");

    RANGE_CHECK_BOOL(vp8_cfg,               enable_auto_alt_ref);
187
    RANGE_CHECK(vp8_cfg, cpu_used,           -16, 16);
188
189
190
191
192

#if CONFIG_REALTIME_ONLY && !CONFIG_TEMPORAL_DENOISING
    RANGE_CHECK(vp8_cfg, noise_sensitivity,  0, 0);
#else
    RANGE_CHECK_HI(vp8_cfg, noise_sensitivity,  6);
John Koleszar's avatar
John Koleszar committed
193
194
#endif

195
196
    RANGE_CHECK(vp8_cfg, token_partitions,   VP8_ONE_TOKENPARTITION,
                VP8_EIGHT_TOKENPARTITION);
197
    RANGE_CHECK_HI(vp8_cfg, Sharpness,       7);
198
    RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
199
    RANGE_CHECK_HI(vp8_cfg, arnr_strength,   6);
200
    RANGE_CHECK(vp8_cfg, arnr_type,       1, 3);
Paul Wilkins's avatar
CQ Mode    
Paul Wilkins committed
201
    RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
202
    RANGE_CHECK_HI(vp8_cfg, screen_content_mode, 2);
203
    if (finalize && (cfg->rc_end_usage == VPX_CQ || cfg->rc_end_usage == VPX_Q))
204
205
        RANGE_CHECK(vp8_cfg, cq_level,
                    cfg->rc_min_quantizer, cfg->rc_max_quantizer);
John Koleszar's avatar
John Koleszar committed
206

207
#if !(CONFIG_REALTIME_ONLY)
John Koleszar's avatar
John Koleszar committed
208
209
    if (cfg->g_pass == VPX_RC_LAST_PASS)
    {
Adrian Grange's avatar
Adrian Grange committed
210
        size_t           packet_sz = sizeof(FIRSTPASS_STATS);
211
212
        int              n_packets = (int)(cfg->rc_twopass_stats_in.sz /
                                          packet_sz);
213
        FIRSTPASS_STATS *stats;
John Koleszar's avatar
John Koleszar committed
214
215
216
217

        if (!cfg->rc_twopass_stats_in.buf)
            ERROR("rc_twopass_stats_in.buf not set.");

218
        if (cfg->rc_twopass_stats_in.sz % packet_sz)
John Koleszar's avatar
John Koleszar committed
219
220
            ERROR("rc_twopass_stats_in.sz indicates truncated packet.");

221
        if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
John Koleszar's avatar
John Koleszar committed
222
223
            ERROR("rc_twopass_stats_in requires at least two packets.");

224
225
        stats = (void*)((char *)cfg->rc_twopass_stats_in.buf
                + (n_packets - 1) * packet_sz);
John Koleszar's avatar
John Koleszar committed
226

227
        if ((int)(stats->count + 0.5) != n_packets - 1)
John Koleszar's avatar
John Koleszar committed
228
229
            ERROR("rc_twopass_stats_in missing EOS stats packet");
    }
230
#endif
John Koleszar's avatar
John Koleszar committed
231

232
233
234
235
    RANGE_CHECK(cfg, ts_number_layers, 1, 5);

    if (cfg->ts_number_layers > 1)
    {
236
        unsigned int i;
237
238
239
        RANGE_CHECK_HI(cfg, ts_periodicity, 16);

        for (i=1; i<cfg->ts_number_layers; i++)
Marco's avatar
Marco committed
240
241
            if (cfg->ts_target_bitrate[i] <= cfg->ts_target_bitrate[i-1] && 
                cfg->rc_target_bitrate > 0)
242
243
244
245
246
247
248
249
250
251
                ERROR("ts_target_bitrate entries are not strictly increasing");

        RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1);
        for (i=cfg->ts_number_layers-2; i>0; i--)
            if (cfg->ts_rate_decimator[i-1] != 2*cfg->ts_rate_decimator[i])
                ERROR("ts_rate_decimator factors are not powers of 2");

        RANGE_CHECK_HI(cfg, ts_layer_id[i], cfg->ts_number_layers-1);
    }

252
253
254
255
256
#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)
    if(cfg->g_threads > (1 << vp8_cfg->token_partitions))
        ERROR("g_threads cannot be bigger than number of token partitions");
#endif

John Koleszar's avatar
John Koleszar committed
257
258
259
260
261
262
263
264
265
    return VPX_CODEC_OK;
}


static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
                                    const vpx_image_t    *img)
{
    switch (img->fmt)
    {
James Zern's avatar
James Zern committed
266
267
268
269
    case VPX_IMG_FMT_YV12:
    case VPX_IMG_FMT_I420:
    case VPX_IMG_FMT_VPXI420:
    case VPX_IMG_FMT_VPXYV12:
John Koleszar's avatar
John Koleszar committed
270
271
272
273
274
275
276
277
278
279
280
281
282
283
        break;
    default:
        ERROR("Invalid image format. Only YV12 and I420 images are supported");
    }

    if ((img->d_w != ctx->cfg.g_w) || (img->d_h != ctx->cfg.g_h))
        ERROR("Image size must match encoder init configuration size");

    return VPX_CODEC_OK;
}


static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
                                       vpx_codec_enc_cfg_t cfg,
Yunqing Wang's avatar
Yunqing Wang committed
284
285
                                       struct vp8_extracfg vp8_cfg,
                                       vpx_codec_priv_enc_mr_cfg_t *mr_cfg)
John Koleszar's avatar
John Koleszar committed
286
287
288
289
290
291
{
    oxcf->multi_threaded         = cfg.g_threads;
    oxcf->Version               = cfg.g_profile;

    oxcf->Width                 = cfg.g_w;
    oxcf->Height                = cfg.g_h;
292
    oxcf->timebase              = cfg.g_timebase;
John Koleszar's avatar
John Koleszar committed
293

294
    oxcf->error_resilient_mode = cfg.g_error_resilient;
John Koleszar's avatar
John Koleszar committed
295
296
297
298
299
300
301
302
303
304
305
306
307
308

    switch (cfg.g_pass)
    {
    case VPX_RC_ONE_PASS:
        oxcf->Mode = MODE_BESTQUALITY;
        break;
    case VPX_RC_FIRST_PASS:
        oxcf->Mode = MODE_FIRSTPASS;
        break;
    case VPX_RC_LAST_PASS:
        oxcf->Mode = MODE_SECONDPASS_BEST;
        break;
    }

309
    if (cfg.g_pass == VPX_RC_FIRST_PASS || cfg.g_pass == VPX_RC_ONE_PASS)
John Koleszar's avatar
John Koleszar committed
310
    {
311
312
        oxcf->allow_lag     = 0;
        oxcf->lag_in_frames = 0;
John Koleszar's avatar
John Koleszar committed
313
314
315
    }
    else
    {
316
317
        oxcf->allow_lag     = (cfg.g_lag_in_frames) > 0;
        oxcf->lag_in_frames = cfg.g_lag_in_frames;
John Koleszar's avatar
John Koleszar committed
318
319
320
321
322
323
324
325
326
    }

    oxcf->allow_df               = (cfg.rc_dropframe_thresh > 0);
    oxcf->drop_frames_water_mark   = cfg.rc_dropframe_thresh;

    oxcf->allow_spatial_resampling = cfg.rc_resize_allowed;
    oxcf->resample_up_water_mark   = cfg.rc_resize_up_thresh;
    oxcf->resample_down_water_mark = cfg.rc_resize_down_thresh;

327
328
329
330
331
332
333
334
    if (cfg.rc_end_usage == VPX_VBR) {
      oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
    } else if (cfg.rc_end_usage == VPX_CBR) {
      oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
    } else if (cfg.rc_end_usage == VPX_CQ) {
      oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
    } else if (cfg.rc_end_usage == VPX_Q) {
      oxcf->end_usage = USAGE_CONSTANT_QUALITY;
Paul Wilkins's avatar
CQ Mode    
Paul Wilkins committed
335
    }
John Koleszar's avatar
John Koleszar committed
336

337
    oxcf->target_bandwidth         = cfg.rc_target_bitrate;
338
    oxcf->rc_max_intra_bitrate_pct = vp8_cfg.rc_max_intra_bitrate_pct;
John Koleszar's avatar
John Koleszar committed
339

340
341
342
    oxcf->best_allowed_q           = cfg.rc_min_quantizer;
    oxcf->worst_allowed_q          = cfg.rc_max_quantizer;
    oxcf->cq_level                 = vp8_cfg.cq_level;
John Koleszar's avatar
John Koleszar committed
343
344
    oxcf->fixed_q = -1;

345
346
    oxcf->under_shoot_pct          = cfg.rc_undershoot_pct;
    oxcf->over_shoot_pct           = cfg.rc_overshoot_pct;
John Koleszar's avatar
John Koleszar committed
347

348
349
350
351
    oxcf->maximum_buffer_size_in_ms   = cfg.rc_buf_sz;
    oxcf->starting_buffer_level_in_ms = cfg.rc_buf_initial_sz;
    oxcf->optimal_buffer_level_in_ms  = cfg.rc_buf_optimal_sz;

352
353
354
    oxcf->maximum_buffer_size      = cfg.rc_buf_sz;
    oxcf->starting_buffer_level    = cfg.rc_buf_initial_sz;
    oxcf->optimal_buffer_level     = cfg.rc_buf_optimal_sz;
John Koleszar's avatar
John Koleszar committed
355

356
    oxcf->two_pass_vbrbias         = cfg.rc_2pass_vbr_bias_pct;
John Koleszar's avatar
John Koleszar committed
357
358
359
    oxcf->two_pass_vbrmin_section  = cfg.rc_2pass_vbr_minsection_pct;
    oxcf->two_pass_vbrmax_section  = cfg.rc_2pass_vbr_maxsection_pct;

360
361
362
363
364
365
366
367
368
369
    oxcf->auto_key                 = cfg.kf_mode == VPX_KF_AUTO
                                       && cfg.kf_min_dist != cfg.kf_max_dist;
    oxcf->key_freq                 = cfg.kf_max_dist;

    oxcf->number_of_layers         = cfg.ts_number_layers;
    oxcf->periodicity              = cfg.ts_periodicity;

    if (oxcf->number_of_layers > 1)
    {
        memcpy (oxcf->target_bitrate, cfg.ts_target_bitrate,
James Zern's avatar
James Zern committed
370
                sizeof(cfg.ts_target_bitrate));
371
        memcpy (oxcf->rate_decimator, cfg.ts_rate_decimator,
James Zern's avatar
James Zern committed
372
                sizeof(cfg.ts_rate_decimator));
373
374
        memcpy (oxcf->layer_id, cfg.ts_layer_id, sizeof(cfg.ts_layer_id));
    }
John Koleszar's avatar
John Koleszar committed
375

Yunqing Wang's avatar
Yunqing Wang committed
376
#if CONFIG_MULTI_RES_ENCODING
377
378
379
380
    /* When mr_cfg is NULL, oxcf->mr_total_resolutions and oxcf->mr_encoder_id
     * are both memset to 0, which ensures the correct logic under this
     * situation.
     */
Yunqing Wang's avatar
Yunqing Wang committed
381
382
383
384
385
386
387
388
    if(mr_cfg)
    {
        oxcf->mr_total_resolutions        = mr_cfg->mr_total_resolutions;
        oxcf->mr_encoder_id               = mr_cfg->mr_encoder_id;
        oxcf->mr_down_sampling_factor.num = mr_cfg->mr_down_sampling_factor.num;
        oxcf->mr_down_sampling_factor.den = mr_cfg->mr_down_sampling_factor.den;
        oxcf->mr_low_res_mode_info        = mr_cfg->mr_low_res_mode_info;
    }
Johann's avatar
Johann committed
389
390
#else
    (void)mr_cfg;
Yunqing Wang's avatar
Yunqing Wang committed
391
392
#endif

393
394
395
396
397
398
    oxcf->cpu_used               = vp8_cfg.cpu_used;
    oxcf->encode_breakout        = vp8_cfg.static_thresh;
    oxcf->play_alternate         = vp8_cfg.enable_auto_alt_ref;
    oxcf->noise_sensitivity      = vp8_cfg.noise_sensitivity;
    oxcf->Sharpness              = vp8_cfg.Sharpness;
    oxcf->token_partitions       = vp8_cfg.token_partitions;
John Koleszar's avatar
John Koleszar committed
399

400
401
    oxcf->two_pass_stats_in      = cfg.rc_twopass_stats_in;
    oxcf->output_pkt_list        = vp8_cfg.pkt_list;
John Koleszar's avatar
John Koleszar committed
402

403
404
405
    oxcf->arnr_max_frames        = vp8_cfg.arnr_max_frames;
    oxcf->arnr_strength          = vp8_cfg.arnr_strength;
    oxcf->arnr_type              = vp8_cfg.arnr_type;
John Koleszar's avatar
John Koleszar committed
406

407
    oxcf->tuning                 = vp8_cfg.tuning;
John Koleszar's avatar
John Koleszar committed
408

Marco's avatar
Marco committed
409
410
    oxcf->screen_content_mode    = vp8_cfg.screen_content_mode;

John Koleszar's avatar
John Koleszar committed
411
412
413
414
415
416
417
418
419
420
421
    /*
        printf("Current VP8 Settings: \n");
        printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
        printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
        printf("Sharpness: %d\n",    oxcf->Sharpness);
        printf("cpu_used: %d\n",  oxcf->cpu_used);
        printf("Mode: %d\n",     oxcf->Mode);
        printf("auto_key: %d\n",  oxcf->auto_key);
        printf("key_freq: %d\n", oxcf->key_freq);
        printf("end_usage: %d\n", oxcf->end_usage);
        printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
422
        printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
John Koleszar's avatar
John Koleszar committed
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
        printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
        printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
        printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
        printf("fixed_q: %d\n",  oxcf->fixed_q);
        printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
        printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
        printf("allow_spatial_resampling: %d\n",  oxcf->allow_spatial_resampling);
        printf("resample_down_water_mark: %d\n", oxcf->resample_down_water_mark);
        printf("resample_up_water_mark: %d\n", oxcf->resample_up_water_mark);
        printf("allow_df: %d\n", oxcf->allow_df);
        printf("drop_frames_water_mark: %d\n", oxcf->drop_frames_water_mark);
        printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
        printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
        printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
        printf("allow_lag: %d\n", oxcf->allow_lag);
        printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
        printf("play_alternate: %d\n", oxcf->play_alternate);
        printf("Version: %d\n", oxcf->Version);
        printf("multi_threaded: %d\n",   oxcf->multi_threaded);
        printf("encode_breakout: %d\n", oxcf->encode_breakout);
    */
    return VPX_CODEC_OK;
}

static vpx_codec_err_t vp8e_set_config(vpx_codec_alg_priv_t       *ctx,
                                       const vpx_codec_enc_cfg_t  *cfg)
{
    vpx_codec_err_t res;

452
453
454
455
456
457
    if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h)
    {
        if (cfg->g_lag_in_frames > 1 || cfg->g_pass != VPX_RC_ONE_PASS)
            ERROR("Cannot change width or height after initialization");
        if ((ctx->cpi->initial_width && (int)cfg->g_w > ctx->cpi->initial_width) ||
            (ctx->cpi->initial_height && (int)cfg->g_h > ctx->cpi->initial_height))
Yaowu Xu's avatar
Yaowu Xu committed
458
            ERROR("Cannot increase width or height larger than their initial values");
459
    }
John Koleszar's avatar
John Koleszar committed
460
461
462
463
464
465
466
467
468

    /* Prevent increasing lag_in_frames. This check is stricter than it needs
     * to be -- the limit is not increasing past the first lag_in_frames
     * value, but we don't track the initial config, only the last successful
     * config.
     */
    if ((cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames))
        ERROR("Cannot increase lag_in_frames");

469
    res = validate_config(ctx, cfg, &ctx->vp8_cfg, 0);
John Koleszar's avatar
John Koleszar committed
470
471
472
473

    if (!res)
    {
        ctx->cfg = *cfg;
Yunqing Wang's avatar
Yunqing Wang committed
474
        set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
John Koleszar's avatar
John Koleszar committed
475
476
477
478
479
480
        vp8_change_config(ctx->cpi, &ctx->oxcf);
    }

    return res;
}

481
482
483
484
485
486
487
488
static vpx_codec_err_t get_quantizer(vpx_codec_alg_priv_t *ctx, va_list args)
{
  int *const arg = va_arg(args, int *);
  if (arg == NULL)
    return VPX_CODEC_INVALID_PARAM;
  *arg = vp8_get_quantizer(ctx->cpi);
  return VPX_CODEC_OK;
}
John Koleszar's avatar
John Koleszar committed
489

490
static vpx_codec_err_t get_quantizer64(vpx_codec_alg_priv_t *ctx, va_list args)
John Koleszar's avatar
John Koleszar committed
491
{
492
493
494
495
496
497
  int *const arg = va_arg(args, int *);
  if (arg == NULL)
    return VPX_CODEC_INVALID_PARAM;
  *arg = vp8_reverse_trans(vp8_get_quantizer(ctx->cpi));
  return VPX_CODEC_OK;
}
John Koleszar's avatar
John Koleszar committed
498

499
500
501
502
503
504
505
506
507
508
509
static vpx_codec_err_t update_extracfg(vpx_codec_alg_priv_t *ctx,
                                       const struct vp8_extracfg *extra_cfg)
{
  const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg, 0);
  if (res == VPX_CODEC_OK) {
    ctx->vp8_cfg = *extra_cfg;
    set_vp8e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg, NULL);
    vp8_change_config(ctx->cpi, &ctx->oxcf);
  }
  return res;
}
John Koleszar's avatar
John Koleszar committed
510

511
512
513
514
515
516
static vpx_codec_err_t set_cpu_used(vpx_codec_alg_priv_t *ctx, va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args);
  return update_extracfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
517

518
519
520
521
522
523
524
static vpx_codec_err_t set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx,
                                               va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args);
  return update_extracfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
525

526
527
528
529
530
531
static vpx_codec_err_t set_noise_sensitivity(vpx_codec_alg_priv_t *ctx,
                                             va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.noise_sensitivity = CAST(VP8E_SET_NOISE_SENSITIVITY, args);
  return update_extracfg(ctx, &extra_cfg);
John Koleszar's avatar
John Koleszar committed
532
533
}

534
535
536
537
538
539
540
541
542
543
544
545
546
547
static vpx_codec_err_t set_sharpness(vpx_codec_alg_priv_t *ctx, va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.Sharpness = CAST(VP8E_SET_SHARPNESS, args);
  return update_extracfg(ctx, &extra_cfg);
}

static vpx_codec_err_t set_static_thresh(vpx_codec_alg_priv_t *ctx,
                                         va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args);
  return update_extracfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
548

549
550
static vpx_codec_err_t set_token_partitions(vpx_codec_alg_priv_t *ctx,
                                            va_list args)
John Koleszar's avatar
John Koleszar committed
551
{
552
553
554
555
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.token_partitions = CAST(VP8E_SET_TOKEN_PARTITIONS, args);
  return update_extracfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
556

557
558
559
560
561
562
563
static vpx_codec_err_t set_arnr_max_frames(vpx_codec_alg_priv_t *ctx,
                                           va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args);
  return update_extracfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
564

565
566
567
568
569
570
571
static vpx_codec_err_t set_arnr_strength(vpx_codec_alg_priv_t *ctx,
                                         va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args);
  return update_extracfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
572

573
574
575
576
577
578
static vpx_codec_err_t set_arnr_type(vpx_codec_alg_priv_t *ctx, va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.arnr_type = CAST(VP8E_SET_ARNR_TYPE, args);
  return update_extracfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
579

580
581
582
583
584
585
static vpx_codec_err_t set_tuning(vpx_codec_alg_priv_t *ctx, va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.tuning = CAST(VP8E_SET_TUNING, args);
  return update_extracfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
586

587
588
589
590
591
592
static vpx_codec_err_t set_cq_level(vpx_codec_alg_priv_t *ctx, va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args);
  return update_extracfg(ctx, &extra_cfg);
}
John Koleszar's avatar
John Koleszar committed
593

594
595
596
597
598
599
600
static vpx_codec_err_t set_rc_max_intra_bitrate_pct(vpx_codec_alg_priv_t *ctx,
                                                    va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.rc_max_intra_bitrate_pct =
      CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args);
  return update_extracfg(ctx, &extra_cfg);
John Koleszar's avatar
John Koleszar committed
601
}
Yunqing Wang's avatar
Yunqing Wang committed
602

Marco's avatar
Marco committed
603
604
605
606
607
608
609
610
611
static vpx_codec_err_t set_screen_content_mode(vpx_codec_alg_priv_t *ctx,
                                               va_list args)
{
  struct vp8_extracfg extra_cfg = ctx->vp8_cfg;
  extra_cfg.screen_content_mode =
      CAST(VP8E_SET_SCREEN_CONTENT_MODE, args);
  return update_extracfg(ctx, &extra_cfg);
}

Yunqing Wang's avatar
Yunqing Wang committed
612
613
614
static vpx_codec_err_t vp8e_mr_alloc_mem(const vpx_codec_enc_cfg_t *cfg,
                                        void **mem_loc)
{
615
616
    vpx_codec_err_t res = 0;

Yunqing Wang's avatar
Yunqing Wang committed
617
#if CONFIG_MULTI_RES_ENCODING
618
    LOWER_RES_FRAME_INFO *shared_mem_loc;
Yunqing Wang's avatar
Yunqing Wang committed
619
620
621
    int mb_rows = ((cfg->g_w + 15) >>4);
    int mb_cols = ((cfg->g_h + 15) >>4);

622
623
    shared_mem_loc = calloc(1, sizeof(LOWER_RES_FRAME_INFO));
    if(!shared_mem_loc)
Yunqing Wang's avatar
Yunqing Wang committed
624
    {
625
        res = VPX_CODEC_MEM_ERROR;
626
627
628
629
630
    }

    shared_mem_loc->mb_info = calloc(mb_rows*mb_cols, sizeof(LOWER_RES_MB_INFO));
    if(!(shared_mem_loc->mb_info))
    {
631
        res = VPX_CODEC_MEM_ERROR;
Yunqing Wang's avatar
Yunqing Wang committed
632
633
    }
    else
634
635
    {
        *mem_loc = (void *)shared_mem_loc;
636
        res = VPX_CODEC_OK;
637
    }
Johann's avatar
Johann committed
638
639
640
#else
    (void)cfg;
    (void)mem_loc;
Yunqing Wang's avatar
Yunqing Wang committed
641
#endif
642
    return res;
Yunqing Wang's avatar
Yunqing Wang committed
643
644
645
646
}

static vpx_codec_err_t vp8e_init(vpx_codec_ctx_t *ctx,
                                 vpx_codec_priv_enc_mr_cfg_t *mr_cfg)
John Koleszar's avatar
John Koleszar committed
647
{
648
    vpx_codec_err_t        res = VPX_CODEC_OK;
649

John Koleszar's avatar
John Koleszar committed
650

651
    vp8_rtcd();
Johann's avatar
Johann committed
652
    vpx_dsp_rtcd();
653
    vpx_scale_rtcd();
654

John Koleszar's avatar
John Koleszar committed
655
656
    if (!ctx->priv)
    {
657
658
        struct vpx_codec_alg_priv *priv =
            (struct vpx_codec_alg_priv *)vpx_calloc(1, sizeof(*priv));
John Koleszar's avatar
John Koleszar committed
659

660
        if (!priv)
John Koleszar's avatar
John Koleszar committed
661
        {
662
663
664
            return VPX_CODEC_MEM_ERROR;
        }

665
        ctx->priv = (vpx_codec_priv_t *)priv;
666
667
668
669
670
671
        ctx->priv->init_flags = ctx->init_flags;

        if (ctx->config.enc)
        {
            /* Update the reference to the config structure to an
             * internal copy.
John Koleszar's avatar
John Koleszar committed
672
             */
673
674
            priv->cfg = *ctx->config.enc;
            ctx->config.enc = &priv->cfg;
675
        }
John Koleszar's avatar
John Koleszar committed
676

677
        priv->vp8_cfg = default_extracfg;
678
        priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
John Koleszar's avatar
John Koleszar committed
679

680
        priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
John Koleszar's avatar
John Koleszar committed
681

682
        if (priv->cx_data_sz < 32768) priv->cx_data_sz = 32768;
John Koleszar's avatar
John Koleszar committed
683

684
        priv->cx_data = malloc(priv->cx_data_sz);
John Koleszar's avatar
John Koleszar committed
685

686
687
688
689
690
        if (!priv->cx_data)
        {
            return VPX_CODEC_MEM_ERROR;
        }

691
692
693
694
695
        if(mr_cfg)
            ctx->priv->enc.total_encoders   = mr_cfg->mr_total_resolutions;
        else
            ctx->priv->enc.total_encoders   = 1;

696
        res = validate_config(priv, &priv->cfg, &priv->vp8_cfg, 0);
697
698
699

        if (!res)
        {
700
701
702
            set_vp8e_config(&priv->oxcf, priv->cfg, priv->vp8_cfg, mr_cfg);
            priv->cpi = vp8_create_compressor(&priv->oxcf);
            if (!priv->cpi)
703
                res = VPX_CODEC_MEM_ERROR;
John Koleszar's avatar
John Koleszar committed
704
705
706
707
708
709
710
711
        }
    }

    return res;
}

static vpx_codec_err_t vp8e_destroy(vpx_codec_alg_priv_t *ctx)
{
Yunqing Wang's avatar
Yunqing Wang committed
712
713
714
#if CONFIG_MULTI_RES_ENCODING
    /* Free multi-encoder shared memory */
    if (ctx->oxcf.mr_total_resolutions > 0 && (ctx->oxcf.mr_encoder_id == ctx->oxcf.mr_total_resolutions-1))
715
716
717
    {
        LOWER_RES_FRAME_INFO *shared_mem_loc = (LOWER_RES_FRAME_INFO *)ctx->oxcf.mr_low_res_mode_info;
        free(shared_mem_loc->mb_info);
Yunqing Wang's avatar
Yunqing Wang committed
718
        free(ctx->oxcf.mr_low_res_mode_info);
719
    }
Yunqing Wang's avatar
Yunqing Wang committed
720
#endif
John Koleszar's avatar
John Koleszar committed
721
722
723

    free(ctx->cx_data);
    vp8_remove_compressor(&ctx->cpi);
724
    vpx_free(ctx);
John Koleszar's avatar
John Koleszar committed
725
726
727
728
729
730
    return VPX_CODEC_OK;
}

static vpx_codec_err_t image2yuvconfig(const vpx_image_t   *img,
                                       YV12_BUFFER_CONFIG  *yv12)
{
731
732
733
734
    const int y_w = img->d_w;
    const int y_h = img->d_h;
    const int uv_w = (img->d_w + 1) / 2;
    const int uv_h = (img->d_h + 1) / 2;
John Koleszar's avatar
John Koleszar committed
735
    vpx_codec_err_t        res = VPX_CODEC_OK;
736
737
738
    yv12->y_buffer = img->planes[VPX_PLANE_Y];
    yv12->u_buffer = img->planes[VPX_PLANE_U];
    yv12->v_buffer = img->planes[VPX_PLANE_V];
John Koleszar's avatar
John Koleszar committed
739

740
741
742
743
744
745
746
747
    yv12->y_crop_width  = y_w;
    yv12->y_crop_height = y_h;
    yv12->y_width  = y_w;
    yv12->y_height = y_h;
    yv12->uv_crop_width = uv_w;
    yv12->uv_crop_height = uv_h;
    yv12->uv_width = uv_w;
    yv12->uv_height = uv_h;
John Koleszar's avatar
John Koleszar committed
748

749
750
    yv12->y_stride = img->stride[VPX_PLANE_Y];
    yv12->uv_stride = img->stride[VPX_PLANE_U];
John Koleszar's avatar
John Koleszar committed
751

752
    yv12->border  = (img->stride[VPX_PLANE_Y] - img->w) / 2;
John Koleszar's avatar
John Koleszar committed
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
    return res;
}

static void pick_quickcompress_mode(vpx_codec_alg_priv_t  *ctx,
                                    unsigned long          duration,
                                    unsigned long          deadline)
{
    unsigned int new_qc;

#if !(CONFIG_REALTIME_ONLY)
    /* Use best quality mode if no deadline is given. */
    new_qc = MODE_BESTQUALITY;

    if (deadline)
    {
        uint64_t     duration_us;

        /* Convert duration parameter from stream timebase to microseconds */
        duration_us = (uint64_t)duration * 1000000
                      * (uint64_t)ctx->cfg.g_timebase.num
                      / (uint64_t)ctx->cfg.g_timebase.den;

        /* If the deadline is more that the duration this frame is to be shown,
         * use good quality mode. Otherwise use realtime mode.
         */
        new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
    }

#else
    new_qc = MODE_REALTIME;
#endif

    if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
        new_qc = MODE_FIRSTPASS;
    else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
        new_qc = (new_qc == MODE_BESTQUALITY)
                 ? MODE_SECONDPASS_BEST
                 : MODE_SECONDPASS;

    if (ctx->oxcf.Mode != new_qc)
    {
        ctx->oxcf.Mode = new_qc;
        vp8_change_config(ctx->cpi, &ctx->oxcf);
    }
}

Marco's avatar
Marco committed
799
800
static vpx_codec_err_t set_reference_and_update(vpx_codec_alg_priv_t *ctx,
                                                int flags)
John Koleszar's avatar
John Koleszar committed
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
{

    /* Handle Flags */
    if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF))
        || ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF)))
    {
        ctx->base.err_detail = "Conflicting flags.";
        return VPX_CODEC_INVALID_PARAM;
    }

    if (flags & (VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF
                 | VP8_EFLAG_NO_REF_ARF))
    {
        int ref = 7;

        if (flags & VP8_EFLAG_NO_REF_LAST)
Johann's avatar
Johann committed
817
            ref ^= VP8_LAST_FRAME;
John Koleszar's avatar
John Koleszar committed
818
819

        if (flags & VP8_EFLAG_NO_REF_GF)
Johann's avatar
Johann committed
820
            ref ^= VP8_GOLD_FRAME;
John Koleszar's avatar
John Koleszar committed
821
822

        if (flags & VP8_EFLAG_NO_REF_ARF)
Johann's avatar
Johann committed
823
            ref ^= VP8_ALTR_FRAME;
John Koleszar's avatar
John Koleszar committed
824
825
826
827
828
829
830
831
832
833
834

        vp8_use_as_reference(ctx->cpi, ref);
    }

    if (flags & (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF
                 | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_FORCE_GF
                 | VP8_EFLAG_FORCE_ARF))
    {
        int upd = 7;

        if (flags & VP8_EFLAG_NO_UPD_LAST)
Johann's avatar
Johann committed
835
            upd ^= VP8_LAST_FRAME;
John Koleszar's avatar
John Koleszar committed
836
837

        if (flags & VP8_EFLAG_NO_UPD_GF)
Johann's avatar
Johann committed
838
            upd ^= VP8_GOLD_FRAME;
John Koleszar's avatar
John Koleszar committed
839
840

        if (flags & VP8_EFLAG_NO_UPD_ARF)
Johann's avatar
Johann committed
841
            upd ^= VP8_ALTR_FRAME;
John Koleszar's avatar
John Koleszar committed
842
843
844
845
846
847
848
849
850

        vp8_update_reference(ctx->cpi, upd);
    }

    if (flags & VP8_EFLAG_NO_UPD_ENTROPY)
    {
        vp8_update_entropy(ctx->cpi, 0);
    }

Marco's avatar
Marco committed
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
    return VPX_CODEC_OK;
}

static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t  *ctx,
                                   const vpx_image_t     *img,
                                   vpx_codec_pts_t        pts,
                                   unsigned long          duration,
                                   vpx_enc_frame_flags_t  flags,
                                   unsigned long          deadline)
{
    vpx_codec_err_t res = VPX_CODEC_OK;

    if (!ctx->cfg.rc_target_bitrate)
        return res;

    if (img)
        res = validate_img(ctx, img);

    if (!res)
        res = validate_config(ctx, &ctx->cfg, &ctx->vp8_cfg, 1);

    pick_quickcompress_mode(ctx, duration, deadline);
    vpx_codec_pkt_list_init(&ctx->pkt_list);

    // If no flags are set in the encode call, then use the frame flags as
    // defined via the control function: vp8e_set_frame_flags.
    if (!flags) {
        flags = ctx->control_frame_flags;
    }
    ctx->control_frame_flags = 0;

882
883
    if (!res)
        res = set_reference_and_update(ctx, flags);
Marco's avatar
Marco committed
884

John Koleszar's avatar
John Koleszar committed
885
886
887
888
889
890
891
    /* Handle fixed keyframe intervals */
    if (ctx->cfg.kf_mode == VPX_KF_AUTO
        && ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist)
    {
        if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist)
        {
            flags |= VPX_EFLAG_FORCE_KF;
892
            ctx->fixed_kf_cntr = 1;
John Koleszar's avatar
John Koleszar committed
893
894
895
896
897
898
899
900
        }
    }

    /* Initialize the encoder instance on the first frame*/
    if (!res && ctx->cpi)
    {
        unsigned int lib_flags;
        YV12_BUFFER_CONFIG sd;
901
        int64_t dst_time_stamp, dst_end_time_stamp;
John Koleszar's avatar
John Koleszar committed
902
903
        unsigned long size, cx_data_sz;
        unsigned char *cx_data;
904
905
        unsigned char *cx_data_end;
        int comp_data_state = 0;
John Koleszar's avatar
John Koleszar committed
906
907
908
909
910

        /* Set up internal flags */
        if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
            ((VP8_COMP *)ctx->cpi)->b_calculate_psnr = 1;

911
912
913
        if (ctx->base.init_flags & VPX_CODEC_USE_OUTPUT_PARTITION)
            ((VP8_COMP *)ctx->cpi)->output_partition = 1;

John Koleszar's avatar
John Koleszar committed
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
        /* Convert API flags to internal codec lib flags */
        lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0;

        /* vp8 use 10,000,000 ticks/second as time stamp */
        dst_time_stamp    = pts * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;
        dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den;

        if (img != NULL)
        {
            res = image2yuvconfig(img, &sd);

            if (vp8_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags,
                                      &sd, dst_time_stamp, dst_end_time_stamp))
            {
                VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;
                res = update_error_state(ctx, &cpi->common.error);
            }

            /* reset for next frame */
            ctx->next_frame_flag = 0;
        }

        cx_data = ctx->cx_data;
        cx_data_sz = ctx->cx_data_sz;
938
        cx_data_end = ctx->cx_data + cx_data_sz;
John Koleszar's avatar
John Koleszar committed
939
940
        lib_flags = 0;

941
        while (cx_data_sz >= ctx->cx_data_sz / 2)
John Koleszar's avatar
John Koleszar committed
942
        {
943
944
945
946
947
948
949
950
951
952
953
954
955
956
            comp_data_state = vp8_get_compressed_data(ctx->cpi,
                                                  &lib_flags,
                                                  &size,
                                                  cx_data,
                                                  cx_data_end,
                                                  &dst_time_stamp,
                                                  &dst_end_time_stamp,
                                                  !img);

            if(comp_data_state == VPX_CODEC_CORRUPT_FRAME)
                return VPX_CODEC_CORRUPT_FRAME;
            else if(comp_data_state == -1)
                break;

John Koleszar's avatar
John Koleszar committed
957
958
959
960
961
962
963
            if (size)
            {
                vpx_codec_pts_t    round, delta;
                vpx_codec_cx_pkt_t pkt;
                VP8_COMP *cpi = (VP8_COMP *)ctx->cpi;

                /* Add the frame packet to the list of returned packets. */
964
                round = (vpx_codec_pts_t)10000000
965
                        * ctx->cfg.g_timebase.num / 2 - 1;
John Koleszar's avatar
John Koleszar committed
966
967
968
969
970
                delta = (dst_end_time_stamp - dst_time_stamp);
                pkt.kind = VPX_CODEC_CX_FRAME_PKT;
                pkt.data.frame.pts =
                    (dst_time_stamp * ctx->cfg.g_timebase.den + round)
                    / ctx->cfg.g_timebase.num / 10000000;
971
972
973
                pkt.data.frame.duration = (unsigned long)
                    ((delta * ctx->cfg.g_timebase.den + round)
                    / ctx->cfg.g_timebase.num / 10000000);
John Koleszar's avatar
John Koleszar committed
974
975
976
977
978
979
980
981
982
                pkt.data.frame.flags = lib_flags << 16;

                if (lib_flags & FRAMEFLAGS_KEY)
                    pkt.data.frame.flags |= VPX_FRAME_IS_KEY;

                if (!cpi->common.show_frame)
                {
                    pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;

John Koleszar's avatar
John Koleszar committed
983
984
985
986
987
                    /* This timestamp should be as close as possible to the
                     * prior PTS so that if a decoder uses pts to schedule when
                     * to do this, we start right after last frame was decoded.
                     * Invisible frames have no duration.
                     */
988
989
990
                    pkt.data.frame.pts = ((cpi->last_time_stamp_seen
                        * ctx->cfg.g_timebase.den + round)
                        / ctx->cfg.g_timebase.num / 10000000) + 1;
John Koleszar's avatar
John Koleszar committed
991
992
993
                    pkt.data.frame.duration = 0;
                }

John Koleszar's avatar
John Koleszar committed
994
995
996
                if (cpi->droppable)
                    pkt.data.frame.flags |= VPX_FRAME_IS_DROPPABLE;

997
998
999
1000
                if (cpi->output_partition)
                {
                    int i;
                    const int num_partitions =
For faster browsing, not all history is shown. View entire blame