• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "./vpx_config.h"
15 #include "vpx/vpx_codec.h"
16 #include "vpx/internal/vpx_codec_internal.h"
17 #include "./vpx_version.h"
18 #include "vp9/encoder/vp9_encoder.h"
19 #include "vpx/vp8cx.h"
20 #include "vp9/encoder/vp9_firstpass.h"
21 #include "vp9/vp9_iface_common.h"
22 
23 struct vp9_extracfg {
24   int                         cpu_used;  // available cpu percentage in 1/16
25   unsigned int                enable_auto_alt_ref;
26   unsigned int                noise_sensitivity;
27   unsigned int                sharpness;
28   unsigned int                static_thresh;
29   unsigned int                tile_columns;
30   unsigned int                tile_rows;
31   unsigned int                arnr_max_frames;
32   unsigned int                arnr_strength;
33   vp8e_tuning                 tuning;
34   unsigned int                cq_level;  // constrained quality level
35   unsigned int                rc_max_intra_bitrate_pct;
36   unsigned int                lossless;
37   unsigned int                frame_parallel_decoding_mode;
38   AQ_MODE                     aq_mode;
39   unsigned int                frame_periodic_boost;
40   vpx_bit_depth_t             bit_depth;
41   vp9e_tune_content           content;
42 };
43 
44 static struct vp9_extracfg default_extra_cfg = {
45   0,                          // cpu_used
46   1,                          // enable_auto_alt_ref
47   0,                          // noise_sensitivity
48   0,                          // sharpness
49   0,                          // static_thresh
50   0,                          // tile_columns
51   0,                          // tile_rows
52   7,                          // arnr_max_frames
53   5,                          // arnr_strength
54   VP8_TUNE_PSNR,              // tuning
55   10,                         // cq_level
56   0,                          // rc_max_intra_bitrate_pct
57   0,                          // lossless
58   0,                          // frame_parallel_decoding_mode
59   NO_AQ,                      // aq_mode
60   0,                          // frame_periodic_delta_q
61   VPX_BITS_8,                 // Bit depth
62   VP9E_CONTENT_DEFAULT        // content
63 };
64 
65 struct vpx_codec_alg_priv {
66   vpx_codec_priv_t        base;
67   vpx_codec_enc_cfg_t     cfg;
68   struct vp9_extracfg     extra_cfg;
69   VP9EncoderConfig        oxcf;
70   VP9_COMP               *cpi;
71   unsigned char          *cx_data;
72   size_t                  cx_data_sz;
73   unsigned char          *pending_cx_data;
74   size_t                  pending_cx_data_sz;
75   int                     pending_frame_count;
76   size_t                  pending_frame_sizes[8];
77   size_t                  pending_frame_magnitude;
78   vpx_image_t             preview_img;
79   vp8_postproc_cfg_t      preview_ppcfg;
80   vpx_codec_pkt_list_decl(256) pkt_list;
81   unsigned int                 fixed_kf_cntr;
82 };
83 
ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame)84 static VP9_REFFRAME ref_frame_to_vp9_reframe(vpx_ref_frame_type_t frame) {
85   switch (frame) {
86     case VP8_LAST_FRAME:
87       return VP9_LAST_FLAG;
88     case VP8_GOLD_FRAME:
89       return VP9_GOLD_FLAG;
90     case VP8_ALTR_FRAME:
91       return VP9_ALT_FLAG;
92   }
93   assert(0 && "Invalid Reference Frame");
94   return VP9_LAST_FLAG;
95 }
96 
update_error_state(vpx_codec_alg_priv_t * ctx,const struct vpx_internal_error_info * error)97 static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
98     const struct vpx_internal_error_info *error) {
99   const vpx_codec_err_t res = error->error_code;
100 
101   if (res != VPX_CODEC_OK)
102     ctx->base.err_detail = error->has_detail ? error->detail : NULL;
103 
104   return res;
105 }
106 
107 
108 #undef ERROR
109 #define ERROR(str) do {\
110     ctx->base.err_detail = str;\
111     return VPX_CODEC_INVALID_PARAM;\
112   } while (0)
113 
114 #define RANGE_CHECK(p, memb, lo, hi) do {\
115     if (!(((p)->memb == lo || (p)->memb > (lo)) && (p)->memb <= hi)) \
116       ERROR(#memb " out of range ["#lo".."#hi"]");\
117   } while (0)
118 
119 #define RANGE_CHECK_HI(p, memb, hi) do {\
120     if (!((p)->memb <= (hi))) \
121       ERROR(#memb " out of range [.."#hi"]");\
122   } while (0)
123 
124 #define RANGE_CHECK_LO(p, memb, lo) do {\
125     if (!((p)->memb >= (lo))) \
126       ERROR(#memb " out of range ["#lo"..]");\
127   } while (0)
128 
129 #define RANGE_CHECK_BOOL(p, memb) do {\
130     if (!!((p)->memb) != (p)->memb) ERROR(#memb " expected boolean");\
131   } while (0)
132 
validate_config(vpx_codec_alg_priv_t * ctx,const vpx_codec_enc_cfg_t * cfg,const struct vp9_extracfg * extra_cfg)133 static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
134                                        const vpx_codec_enc_cfg_t *cfg,
135                                        const struct vp9_extracfg *extra_cfg) {
136   RANGE_CHECK(cfg, g_w,                   1, 65535);  // 16 bits available
137   RANGE_CHECK(cfg, g_h,                   1, 65535);  // 16 bits available
138   RANGE_CHECK(cfg, g_timebase.den,        1, 1000000000);
139   RANGE_CHECK(cfg, g_timebase.num,        1, cfg->g_timebase.den);
140   RANGE_CHECK_HI(cfg, g_profile,          3);
141 
142   RANGE_CHECK_HI(cfg, rc_max_quantizer,   63);
143   RANGE_CHECK_HI(cfg, rc_min_quantizer,   cfg->rc_max_quantizer);
144   RANGE_CHECK_BOOL(extra_cfg, lossless);
145   RANGE_CHECK(extra_cfg, aq_mode,           0, AQ_MODE_COUNT - 1);
146   RANGE_CHECK(extra_cfg, frame_periodic_boost, 0, 1);
147   RANGE_CHECK_HI(cfg, g_threads,          64);
148   RANGE_CHECK_HI(cfg, g_lag_in_frames,    MAX_LAG_BUFFERS);
149   RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_Q);
150   RANGE_CHECK_HI(cfg, rc_undershoot_pct,  1000);
151   RANGE_CHECK_HI(cfg, rc_overshoot_pct,   1000);
152   RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
153   RANGE_CHECK(cfg, kf_mode,               VPX_KF_DISABLED, VPX_KF_AUTO);
154   RANGE_CHECK_BOOL(cfg,                   rc_resize_allowed);
155   RANGE_CHECK_HI(cfg, rc_dropframe_thresh,   100);
156   RANGE_CHECK_HI(cfg, rc_resize_up_thresh,   100);
157   RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100);
158   RANGE_CHECK(cfg,        g_pass,         VPX_RC_ONE_PASS, VPX_RC_LAST_PASS);
159 
160   if (cfg->rc_resize_allowed == 1) {
161     RANGE_CHECK(cfg, rc_scaled_width, 1, cfg->g_w);
162     RANGE_CHECK(cfg, rc_scaled_height, 1, cfg->g_h);
163   }
164 
165   RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
166   RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
167 
168   if (cfg->ts_number_layers > 1) {
169     unsigned int i;
170     for (i = 1; i < cfg->ts_number_layers; ++i)
171       if (cfg->ts_target_bitrate[i] < cfg->ts_target_bitrate[i - 1])
172         ERROR("ts_target_bitrate entries are not increasing");
173 
174     RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
175     for (i = cfg->ts_number_layers - 2; i > 0; --i)
176       if (cfg->ts_rate_decimator[i - 1] != 2 * cfg->ts_rate_decimator[i])
177         ERROR("ts_rate_decimator factors are not powers of 2");
178   }
179 
180 #if CONFIG_SPATIAL_SVC
181 
182   if ((cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) &&
183       cfg->g_pass == VPX_RC_LAST_PASS) {
184     unsigned int i, alt_ref_sum = 0;
185     for (i = 0; i < cfg->ss_number_layers; ++i) {
186       if (cfg->ss_enable_auto_alt_ref[i])
187         ++alt_ref_sum;
188     }
189     if (alt_ref_sum > REF_FRAMES - cfg->ss_number_layers)
190       ERROR("Not enough ref buffers for svc alt ref frames");
191     if ((cfg->ss_number_layers > 3 ||
192          cfg->ss_number_layers * cfg->ts_number_layers > 4) &&
193         cfg->g_error_resilient == 0)
194     ERROR("Multiple frame context are not supported for more than 3 spatial "
195           "layers or more than 4 spatial x temporal layers");
196   }
197 #endif
198 
199   // VP9 does not support a lower bound on the keyframe interval in
200   // automatic keyframe placement mode.
201   if (cfg->kf_mode != VPX_KF_DISABLED &&
202       cfg->kf_min_dist != cfg->kf_max_dist &&
203       cfg->kf_min_dist > 0)
204     ERROR("kf_min_dist not supported in auto mode, use 0 "
205           "or kf_max_dist instead.");
206 
207   RANGE_CHECK_BOOL(extra_cfg,  enable_auto_alt_ref);
208   RANGE_CHECK(extra_cfg, cpu_used, -16, 16);
209   RANGE_CHECK_HI(extra_cfg, noise_sensitivity, 6);
210   RANGE_CHECK(extra_cfg, tile_columns, 0, 6);
211   RANGE_CHECK(extra_cfg, tile_rows, 0, 2);
212   RANGE_CHECK_HI(extra_cfg, sharpness, 7);
213   RANGE_CHECK(extra_cfg, arnr_max_frames, 0, 15);
214   RANGE_CHECK_HI(extra_cfg, arnr_strength, 6);
215   RANGE_CHECK(extra_cfg, cq_level, 0, 63);
216   RANGE_CHECK(cfg, g_bit_depth, VPX_BITS_8, VPX_BITS_12);
217   RANGE_CHECK(cfg, g_input_bit_depth, 8, 12);
218   RANGE_CHECK(extra_cfg, content,
219               VP9E_CONTENT_DEFAULT, VP9E_CONTENT_INVALID - 1);
220 
221   // TODO(yaowu): remove this when ssim tuning is implemented for vp9
222   if (extra_cfg->tuning == VP8_TUNE_SSIM)
223       ERROR("Option --tune=ssim is not currently supported in VP9.");
224 
225   if (cfg->g_pass == VPX_RC_LAST_PASS) {
226     const size_t packet_sz = sizeof(FIRSTPASS_STATS);
227     const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
228     const FIRSTPASS_STATS *stats;
229 
230     if (cfg->rc_twopass_stats_in.buf == NULL)
231       ERROR("rc_twopass_stats_in.buf not set.");
232 
233     if (cfg->rc_twopass_stats_in.sz % packet_sz)
234       ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
235 
236     if (cfg->ss_number_layers > 1 || cfg->ts_number_layers > 1) {
237       int i;
238       unsigned int n_packets_per_layer[VPX_SS_MAX_LAYERS] = {0};
239 
240       stats = cfg->rc_twopass_stats_in.buf;
241       for (i = 0; i < n_packets; ++i) {
242         const int layer_id = (int)stats[i].spatial_layer_id;
243         if (layer_id >= 0 && layer_id < (int)cfg->ss_number_layers) {
244           ++n_packets_per_layer[layer_id];
245         }
246       }
247 
248       for (i = 0; i < (int)cfg->ss_number_layers; ++i) {
249         unsigned int layer_id;
250         if (n_packets_per_layer[i] < 2) {
251           ERROR("rc_twopass_stats_in requires at least two packets for each "
252                 "layer.");
253         }
254 
255         stats = (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf +
256                 n_packets - cfg->ss_number_layers + i;
257         layer_id = (int)stats->spatial_layer_id;
258 
259         if (layer_id >= cfg->ss_number_layers
260             ||(unsigned int)(stats->count + 0.5) !=
261                n_packets_per_layer[layer_id] - 1)
262           ERROR("rc_twopass_stats_in missing EOS stats packet");
263       }
264     } else {
265       if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
266         ERROR("rc_twopass_stats_in requires at least two packets.");
267 
268       stats =
269           (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
270 
271       if ((int)(stats->count + 0.5) != n_packets - 1)
272         ERROR("rc_twopass_stats_in missing EOS stats packet");
273     }
274   }
275 
276 #if !CONFIG_VP9_HIGHBITDEPTH
277   if (cfg->g_profile > (unsigned int)PROFILE_1)
278     ERROR("Profile > 1 not supported in this build configuration");
279 #endif
280   if (cfg->g_profile <= (unsigned int)PROFILE_1 &&
281       extra_cfg->bit_depth > VPX_BITS_8)
282     ERROR("Codec high bit-depth not supported in profile < 2");
283   if (cfg->g_profile > (unsigned int)PROFILE_1 &&
284       extra_cfg->bit_depth == VPX_BITS_8)
285     ERROR("Codec bit-depth 8 not supported in profile > 1");
286 
287   return VPX_CODEC_OK;
288 }
289 
290 
validate_img(vpx_codec_alg_priv_t * ctx,const vpx_image_t * img)291 static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx,
292                                     const vpx_image_t *img) {
293   switch (img->fmt) {
294     case VPX_IMG_FMT_YV12:
295     case VPX_IMG_FMT_I420:
296     case VPX_IMG_FMT_I422:
297     case VPX_IMG_FMT_I444:
298       break;
299     default:
300       ERROR("Invalid image format. Only YV12, I420, I422, I444 images are "
301             "supported.");
302       break;
303   }
304 
305   if (img->d_w != ctx->cfg.g_w || img->d_h != ctx->cfg.g_h)
306     ERROR("Image size must match encoder init configuration size");
307 
308   return VPX_CODEC_OK;
309 }
310 
get_image_bps(const vpx_image_t * img)311 static int get_image_bps(const vpx_image_t *img) {
312   switch (img->fmt) {
313     case VPX_IMG_FMT_YV12:
314     case VPX_IMG_FMT_I420: return 12;
315     case VPX_IMG_FMT_I422: return 16;
316     case VPX_IMG_FMT_I444: return 24;
317     case VPX_IMG_FMT_I42016: return 24;
318     case VPX_IMG_FMT_I42216: return 32;
319     case VPX_IMG_FMT_I44416: return 48;
320     default: assert(0 && "Invalid image format"); break;
321   }
322   return 0;
323 }
324 
set_encoder_config(VP9EncoderConfig * oxcf,const vpx_codec_enc_cfg_t * cfg,const struct vp9_extracfg * extra_cfg)325 static vpx_codec_err_t set_encoder_config(
326     VP9EncoderConfig *oxcf,
327     const vpx_codec_enc_cfg_t *cfg,
328     const struct vp9_extracfg *extra_cfg) {
329   const int is_vbr = cfg->rc_end_usage == VPX_VBR;
330   oxcf->profile = cfg->g_profile;
331   oxcf->width   = cfg->g_w;
332   oxcf->height  = cfg->g_h;
333   oxcf->bit_depth = extra_cfg->bit_depth;
334   oxcf->input_bit_depth = cfg->g_input_bit_depth;
335   // guess a frame rate if out of whack, use 30
336   oxcf->init_framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num;
337   if (oxcf->init_framerate > 180)
338     oxcf->init_framerate = 30;
339 
340   oxcf->mode = GOOD;
341 
342   switch (cfg->g_pass) {
343     case VPX_RC_ONE_PASS:
344       oxcf->pass = 0;
345       break;
346     case VPX_RC_FIRST_PASS:
347       oxcf->pass = 1;
348       break;
349     case VPX_RC_LAST_PASS:
350       oxcf->pass = 2;
351       break;
352   }
353 
354   oxcf->lag_in_frames = cfg->g_pass == VPX_RC_FIRST_PASS ? 0
355                                                          : cfg->g_lag_in_frames;
356   oxcf->rc_mode = cfg->rc_end_usage;
357 
358   // Convert target bandwidth from Kbit/s to Bit/s
359   oxcf->target_bandwidth = 1000 * cfg->rc_target_bitrate;
360   oxcf->rc_max_intra_bitrate_pct = extra_cfg->rc_max_intra_bitrate_pct;
361 
362   oxcf->best_allowed_q =
363       extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_min_quantizer);
364   oxcf->worst_allowed_q =
365       extra_cfg->lossless ? 0 : vp9_quantizer_to_qindex(cfg->rc_max_quantizer);
366   oxcf->cq_level        = vp9_quantizer_to_qindex(extra_cfg->cq_level);
367   oxcf->fixed_q = -1;
368 
369   oxcf->under_shoot_pct         = cfg->rc_undershoot_pct;
370   oxcf->over_shoot_pct          = cfg->rc_overshoot_pct;
371 
372   oxcf->allow_spatial_resampling = cfg->rc_resize_allowed;
373   oxcf->scaled_frame_width       = cfg->rc_scaled_width;
374   oxcf->scaled_frame_height      = cfg->rc_scaled_height;
375 
376   oxcf->maximum_buffer_size_ms   = is_vbr ? 240000 : cfg->rc_buf_sz;
377   oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
378   oxcf->optimal_buffer_level_ms  = is_vbr ? 60000 : cfg->rc_buf_optimal_sz;
379 
380   oxcf->drop_frames_water_mark   = cfg->rc_dropframe_thresh;
381 
382   oxcf->two_pass_vbrbias         = cfg->rc_2pass_vbr_bias_pct;
383   oxcf->two_pass_vbrmin_section  = cfg->rc_2pass_vbr_minsection_pct;
384   oxcf->two_pass_vbrmax_section  = cfg->rc_2pass_vbr_maxsection_pct;
385 
386   oxcf->auto_key               = cfg->kf_mode == VPX_KF_AUTO &&
387                                  cfg->kf_min_dist != cfg->kf_max_dist;
388 
389   oxcf->key_freq               = cfg->kf_max_dist;
390 
391   oxcf->speed                  =  abs(extra_cfg->cpu_used);
392   oxcf->encode_breakout        =  extra_cfg->static_thresh;
393   oxcf->play_alternate         =  extra_cfg->enable_auto_alt_ref;
394   oxcf->noise_sensitivity      =  extra_cfg->noise_sensitivity;
395   oxcf->sharpness              =  extra_cfg->sharpness;
396 
397   oxcf->two_pass_stats_in      =  cfg->rc_twopass_stats_in;
398 
399 #if CONFIG_FP_MB_STATS
400   oxcf->firstpass_mb_stats_in  = cfg->rc_firstpass_mb_stats_in;
401 #endif
402 
403   oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
404   oxcf->arnr_strength   = extra_cfg->arnr_strength;
405 
406   oxcf->tuning = extra_cfg->tuning;
407   oxcf->content = extra_cfg->content;
408 
409   oxcf->tile_columns = extra_cfg->tile_columns;
410   oxcf->tile_rows    = extra_cfg->tile_rows;
411 
412   oxcf->error_resilient_mode         = cfg->g_error_resilient;
413   oxcf->frame_parallel_decoding_mode = extra_cfg->frame_parallel_decoding_mode;
414 
415   oxcf->aq_mode = extra_cfg->aq_mode;
416 
417   oxcf->frame_periodic_boost =  extra_cfg->frame_periodic_boost;
418 
419   oxcf->ss_number_layers = cfg->ss_number_layers;
420 
421   if (oxcf->ss_number_layers > 1) {
422     int i;
423     for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
424       oxcf->ss_target_bitrate[i] =  1000 * cfg->ss_target_bitrate[i];
425 #if CONFIG_SPATIAL_SVC
426       oxcf->ss_play_alternate[i] =  cfg->ss_enable_auto_alt_ref[i];
427 #endif
428     }
429   } else if (oxcf->ss_number_layers == 1) {
430     oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
431 #if CONFIG_SPATIAL_SVC
432     oxcf->ss_play_alternate[0] = extra_cfg->enable_auto_alt_ref;
433 #endif
434   }
435 
436   oxcf->ts_number_layers = cfg->ts_number_layers;
437 
438   if (oxcf->ts_number_layers > 1) {
439     int i;
440     for (i = 0; i < VPX_TS_MAX_LAYERS; ++i) {
441       oxcf->ts_target_bitrate[i] = 1000 * cfg->ts_target_bitrate[i];
442       oxcf->ts_rate_decimator[i] = cfg->ts_rate_decimator[i];
443     }
444   } else if (oxcf->ts_number_layers == 1) {
445     oxcf->ts_target_bitrate[0] = (int)oxcf->target_bandwidth;
446     oxcf->ts_rate_decimator[0] = 1;
447   }
448 
449   /*
450   printf("Current VP9 Settings: \n");
451   printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
452   printf("noise_sensitivity: %d\n", oxcf->noise_sensitivity);
453   printf("sharpness: %d\n",    oxcf->sharpness);
454   printf("cpu_used: %d\n",  oxcf->cpu_used);
455   printf("Mode: %d\n",     oxcf->mode);
456   printf("auto_key: %d\n",  oxcf->auto_key);
457   printf("key_freq: %d\n", oxcf->key_freq);
458   printf("end_usage: %d\n", oxcf->end_usage);
459   printf("under_shoot_pct: %d\n", oxcf->under_shoot_pct);
460   printf("over_shoot_pct: %d\n", oxcf->over_shoot_pct);
461   printf("starting_buffer_level: %d\n", oxcf->starting_buffer_level);
462   printf("optimal_buffer_level: %d\n",  oxcf->optimal_buffer_level);
463   printf("maximum_buffer_size: %d\n", oxcf->maximum_buffer_size);
464   printf("fixed_q: %d\n",  oxcf->fixed_q);
465   printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q);
466   printf("best_allowed_q: %d\n", oxcf->best_allowed_q);
467   printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling);
468   printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width);
469   printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height);
470   printf("two_pass_vbrbias: %d\n",  oxcf->two_pass_vbrbias);
471   printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section);
472   printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section);
473   printf("lag_in_frames: %d\n", oxcf->lag_in_frames);
474   printf("play_alternate: %d\n", oxcf->play_alternate);
475   printf("Version: %d\n", oxcf->Version);
476   printf("encode_breakout: %d\n", oxcf->encode_breakout);
477   printf("error resilient: %d\n", oxcf->error_resilient_mode);
478   printf("frame parallel detokenization: %d\n",
479          oxcf->frame_parallel_decoding_mode);
480   */
481   return VPX_CODEC_OK;
482 }
483 
encoder_set_config(vpx_codec_alg_priv_t * ctx,const vpx_codec_enc_cfg_t * cfg)484 static vpx_codec_err_t encoder_set_config(vpx_codec_alg_priv_t *ctx,
485                                           const vpx_codec_enc_cfg_t  *cfg) {
486   vpx_codec_err_t res;
487 
488   if (cfg->g_w != ctx->cfg.g_w || cfg->g_h != ctx->cfg.g_h)
489     ERROR("Cannot change width or height after initialization");
490 
491   // Prevent increasing lag_in_frames. This check is stricter than it needs
492   // to be -- the limit is not increasing past the first lag_in_frames
493   // value, but we don't track the initial config, only the last successful
494   // config.
495   if (cfg->g_lag_in_frames > ctx->cfg.g_lag_in_frames)
496     ERROR("Cannot increase lag_in_frames");
497 
498   res = validate_config(ctx, cfg, &ctx->extra_cfg);
499 
500   if (res == VPX_CODEC_OK) {
501     ctx->cfg = *cfg;
502     set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
503     vp9_change_config(ctx->cpi, &ctx->oxcf);
504   }
505 
506   return res;
507 }
508 
ctrl_get_quantizer(vpx_codec_alg_priv_t * ctx,va_list args)509 static vpx_codec_err_t ctrl_get_quantizer(vpx_codec_alg_priv_t *ctx,
510                                           va_list args) {
511   int *const arg = va_arg(args, int *);
512   if (arg == NULL)
513     return VPX_CODEC_INVALID_PARAM;
514   *arg = vp9_get_quantizer(ctx->cpi);
515   return VPX_CODEC_OK;
516 }
517 
ctrl_get_quantizer64(vpx_codec_alg_priv_t * ctx,va_list args)518 static vpx_codec_err_t ctrl_get_quantizer64(vpx_codec_alg_priv_t *ctx,
519                                             va_list args) {
520   int *const arg = va_arg(args, int *);
521   if (arg == NULL)
522     return VPX_CODEC_INVALID_PARAM;
523   *arg = vp9_qindex_to_quantizer(vp9_get_quantizer(ctx->cpi));
524   return VPX_CODEC_OK;
525 }
526 
update_extra_cfg(vpx_codec_alg_priv_t * ctx,const struct vp9_extracfg * extra_cfg)527 static vpx_codec_err_t update_extra_cfg(vpx_codec_alg_priv_t *ctx,
528                                         const struct vp9_extracfg *extra_cfg) {
529   const vpx_codec_err_t res = validate_config(ctx, &ctx->cfg, extra_cfg);
530   if (res == VPX_CODEC_OK) {
531     ctx->extra_cfg = *extra_cfg;
532     set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg);
533     vp9_change_config(ctx->cpi, &ctx->oxcf);
534   }
535   return res;
536 }
537 
ctrl_set_cpuused(vpx_codec_alg_priv_t * ctx,va_list args)538 static vpx_codec_err_t ctrl_set_cpuused(vpx_codec_alg_priv_t *ctx,
539                                         va_list args) {
540   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
541   extra_cfg.cpu_used = CAST(VP8E_SET_CPUUSED, args);
542   return update_extra_cfg(ctx, &extra_cfg);
543 }
544 
ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t * ctx,va_list args)545 static vpx_codec_err_t ctrl_set_enable_auto_alt_ref(vpx_codec_alg_priv_t *ctx,
546                                                     va_list args) {
547   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
548   extra_cfg.enable_auto_alt_ref = CAST(VP8E_SET_ENABLEAUTOALTREF, args);
549   return update_extra_cfg(ctx, &extra_cfg);
550 }
551 
ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t * ctx,va_list args)552 static vpx_codec_err_t ctrl_set_noise_sensitivity(vpx_codec_alg_priv_t *ctx,
553                                                   va_list args) {
554   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
555   extra_cfg.noise_sensitivity = CAST(VP9E_SET_NOISE_SENSITIVITY, args);
556   return update_extra_cfg(ctx, &extra_cfg);
557 }
558 
ctrl_set_sharpness(vpx_codec_alg_priv_t * ctx,va_list args)559 static vpx_codec_err_t ctrl_set_sharpness(vpx_codec_alg_priv_t *ctx,
560                                           va_list args) {
561   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
562   extra_cfg.sharpness = CAST(VP8E_SET_SHARPNESS, args);
563   return update_extra_cfg(ctx, &extra_cfg);
564 }
565 
ctrl_set_static_thresh(vpx_codec_alg_priv_t * ctx,va_list args)566 static vpx_codec_err_t ctrl_set_static_thresh(vpx_codec_alg_priv_t *ctx,
567                                               va_list args) {
568   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
569   extra_cfg.static_thresh = CAST(VP8E_SET_STATIC_THRESHOLD, args);
570   return update_extra_cfg(ctx, &extra_cfg);
571 }
572 
ctrl_set_tile_columns(vpx_codec_alg_priv_t * ctx,va_list args)573 static vpx_codec_err_t ctrl_set_tile_columns(vpx_codec_alg_priv_t *ctx,
574                                              va_list args) {
575   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
576   extra_cfg.tile_columns = CAST(VP9E_SET_TILE_COLUMNS, args);
577   return update_extra_cfg(ctx, &extra_cfg);
578 }
579 
ctrl_set_tile_rows(vpx_codec_alg_priv_t * ctx,va_list args)580 static vpx_codec_err_t ctrl_set_tile_rows(vpx_codec_alg_priv_t *ctx,
581                                           va_list args) {
582   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
583   extra_cfg.tile_rows = CAST(VP9E_SET_TILE_ROWS, args);
584   return update_extra_cfg(ctx, &extra_cfg);
585 }
586 
ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t * ctx,va_list args)587 static vpx_codec_err_t ctrl_set_arnr_max_frames(vpx_codec_alg_priv_t *ctx,
588                                                 va_list args) {
589   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
590   extra_cfg.arnr_max_frames = CAST(VP8E_SET_ARNR_MAXFRAMES, args);
591   return update_extra_cfg(ctx, &extra_cfg);
592 }
593 
ctrl_set_arnr_strength(vpx_codec_alg_priv_t * ctx,va_list args)594 static vpx_codec_err_t ctrl_set_arnr_strength(vpx_codec_alg_priv_t *ctx,
595                                               va_list args) {
596   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
597   extra_cfg.arnr_strength = CAST(VP8E_SET_ARNR_STRENGTH, args);
598   return update_extra_cfg(ctx, &extra_cfg);
599 }
600 
ctrl_set_arnr_type(vpx_codec_alg_priv_t * ctx,va_list args)601 static vpx_codec_err_t ctrl_set_arnr_type(vpx_codec_alg_priv_t *ctx,
602                                           va_list args) {
603   (void)ctx;
604   (void)args;
605   return VPX_CODEC_OK;
606 }
607 
ctrl_set_tuning(vpx_codec_alg_priv_t * ctx,va_list args)608 static vpx_codec_err_t ctrl_set_tuning(vpx_codec_alg_priv_t *ctx,
609                                        va_list args) {
610   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
611   extra_cfg.tuning = CAST(VP8E_SET_TUNING, args);
612   return update_extra_cfg(ctx, &extra_cfg);
613 }
614 
ctrl_set_cq_level(vpx_codec_alg_priv_t * ctx,va_list args)615 static vpx_codec_err_t ctrl_set_cq_level(vpx_codec_alg_priv_t *ctx,
616                                          va_list args) {
617   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
618   extra_cfg.cq_level = CAST(VP8E_SET_CQ_LEVEL, args);
619   return update_extra_cfg(ctx, &extra_cfg);
620 }
621 
ctrl_set_rc_max_intra_bitrate_pct(vpx_codec_alg_priv_t * ctx,va_list args)622 static vpx_codec_err_t ctrl_set_rc_max_intra_bitrate_pct(
623     vpx_codec_alg_priv_t *ctx, va_list args) {
624   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
625   extra_cfg.rc_max_intra_bitrate_pct =
626       CAST(VP8E_SET_MAX_INTRA_BITRATE_PCT, args);
627   return update_extra_cfg(ctx, &extra_cfg);
628 }
629 
ctrl_set_lossless(vpx_codec_alg_priv_t * ctx,va_list args)630 static vpx_codec_err_t ctrl_set_lossless(vpx_codec_alg_priv_t *ctx,
631                                          va_list args) {
632   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
633   extra_cfg.lossless = CAST(VP9E_SET_LOSSLESS, args);
634   return update_extra_cfg(ctx, &extra_cfg);
635 }
636 
ctrl_set_frame_parallel_decoding_mode(vpx_codec_alg_priv_t * ctx,va_list args)637 static vpx_codec_err_t ctrl_set_frame_parallel_decoding_mode(
638     vpx_codec_alg_priv_t *ctx, va_list args) {
639   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
640   extra_cfg.frame_parallel_decoding_mode =
641       CAST(VP9E_SET_FRAME_PARALLEL_DECODING, args);
642   return update_extra_cfg(ctx, &extra_cfg);
643 }
644 
ctrl_set_aq_mode(vpx_codec_alg_priv_t * ctx,va_list args)645 static vpx_codec_err_t ctrl_set_aq_mode(vpx_codec_alg_priv_t *ctx,
646                                         va_list args) {
647   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
648   extra_cfg.aq_mode = CAST(VP9E_SET_AQ_MODE, args);
649   return update_extra_cfg(ctx, &extra_cfg);
650 }
651 
ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t * ctx,va_list args)652 static vpx_codec_err_t ctrl_set_frame_periodic_boost(vpx_codec_alg_priv_t *ctx,
653                                                      va_list args) {
654   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
655   extra_cfg.frame_periodic_boost = CAST(VP9E_SET_FRAME_PERIODIC_BOOST, args);
656   return update_extra_cfg(ctx, &extra_cfg);
657 }
658 
encoder_init(vpx_codec_ctx_t * ctx,vpx_codec_priv_enc_mr_cfg_t * data)659 static vpx_codec_err_t encoder_init(vpx_codec_ctx_t *ctx,
660                                     vpx_codec_priv_enc_mr_cfg_t *data) {
661   vpx_codec_err_t res = VPX_CODEC_OK;
662   (void)data;
663 
664   if (ctx->priv == NULL) {
665     vpx_codec_alg_priv_t *const priv = vpx_calloc(1, sizeof(*priv));
666     if (priv == NULL)
667       return VPX_CODEC_MEM_ERROR;
668 
669     ctx->priv = (vpx_codec_priv_t *)priv;
670     ctx->priv->init_flags = ctx->init_flags;
671     ctx->priv->enc.total_encoders = 1;
672 
673     if (ctx->config.enc) {
674       // Update the reference to the config structure to an internal copy.
675       priv->cfg = *ctx->config.enc;
676       ctx->config.enc = &priv->cfg;
677     }
678 
679     priv->extra_cfg = default_extra_cfg;
680     vp9_initialize_enc();
681 
682     res = validate_config(priv, &priv->cfg, &priv->extra_cfg);
683 
684     if (res == VPX_CODEC_OK) {
685       set_encoder_config(&priv->oxcf, &priv->cfg, &priv->extra_cfg);
686 #if CONFIG_VP9_HIGHBITDEPTH
687       priv->oxcf.use_highbitdepth =
688           (ctx->init_flags & VPX_CODEC_USE_HIGHBITDEPTH) ? 1 : 0;
689 #endif
690       priv->cpi = vp9_create_compressor(&priv->oxcf);
691       if (priv->cpi == NULL)
692         res = VPX_CODEC_MEM_ERROR;
693       else
694         priv->cpi->output_pkt_list = &priv->pkt_list.head;
695     }
696   }
697 
698   return res;
699 }
700 
encoder_destroy(vpx_codec_alg_priv_t * ctx)701 static vpx_codec_err_t encoder_destroy(vpx_codec_alg_priv_t *ctx) {
702   free(ctx->cx_data);
703   vp9_remove_compressor(ctx->cpi);
704   vpx_free(ctx);
705   return VPX_CODEC_OK;
706 }
707 
pick_quickcompress_mode(vpx_codec_alg_priv_t * ctx,unsigned long duration,unsigned long deadline)708 static void pick_quickcompress_mode(vpx_codec_alg_priv_t *ctx,
709                                     unsigned long duration,
710                                     unsigned long deadline) {
711   MODE new_mode = BEST;
712 
713   switch (ctx->cfg.g_pass) {
714     case VPX_RC_ONE_PASS:
715       if (deadline > 0) {
716         const vpx_codec_enc_cfg_t *const cfg = &ctx->cfg;
717 
718         // Convert duration parameter from stream timebase to microseconds.
719         const uint64_t duration_us = (uint64_t)duration * 1000000 *
720            (uint64_t)cfg->g_timebase.num /(uint64_t)cfg->g_timebase.den;
721 
722         // If the deadline is more that the duration this frame is to be shown,
723         // use good quality mode. Otherwise use realtime mode.
724         new_mode = (deadline > duration_us) ? GOOD : REALTIME;
725       } else {
726         new_mode = BEST;
727       }
728       break;
729     case VPX_RC_FIRST_PASS:
730       break;
731     case VPX_RC_LAST_PASS:
732       new_mode = deadline > 0 ? GOOD : BEST;
733       break;
734   }
735 
736   if (ctx->oxcf.mode != new_mode) {
737     ctx->oxcf.mode = new_mode;
738     vp9_change_config(ctx->cpi, &ctx->oxcf);
739   }
740 }
741 
742 // Turn on to test if supplemental superframe data breaks decoding
743 // #define TEST_SUPPLEMENTAL_SUPERFRAME_DATA
write_superframe_index(vpx_codec_alg_priv_t * ctx)744 static int write_superframe_index(vpx_codec_alg_priv_t *ctx) {
745   uint8_t marker = 0xc0;
746   unsigned int mask;
747   int mag, index_sz;
748 
749   assert(ctx->pending_frame_count);
750   assert(ctx->pending_frame_count <= 8);
751 
752   // Add the number of frames to the marker byte
753   marker |= ctx->pending_frame_count - 1;
754 
755   // Choose the magnitude
756   for (mag = 0, mask = 0xff; mag < 4; mag++) {
757     if (ctx->pending_frame_magnitude < mask)
758       break;
759     mask <<= 8;
760     mask |= 0xff;
761   }
762   marker |= mag << 3;
763 
764   // Write the index
765   index_sz = 2 + (mag + 1) * ctx->pending_frame_count;
766   if (ctx->pending_cx_data_sz + index_sz < ctx->cx_data_sz) {
767     uint8_t *x = ctx->pending_cx_data + ctx->pending_cx_data_sz;
768     int i, j;
769 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
770     uint8_t marker_test = 0xc0;
771     int mag_test = 2;     // 1 - 4
772     int frames_test = 4;  // 1 - 8
773     int index_sz_test = 2 + mag_test * frames_test;
774     marker_test |= frames_test - 1;
775     marker_test |= (mag_test - 1) << 3;
776     *x++ = marker_test;
777     for (i = 0; i < mag_test * frames_test; ++i)
778       *x++ = 0;  // fill up with arbitrary data
779     *x++ = marker_test;
780     ctx->pending_cx_data_sz += index_sz_test;
781     printf("Added supplemental superframe data\n");
782 #endif
783 
784     *x++ = marker;
785     for (i = 0; i < ctx->pending_frame_count; i++) {
786       unsigned int this_sz = (unsigned int)ctx->pending_frame_sizes[i];
787 
788       for (j = 0; j <= mag; j++) {
789         *x++ = this_sz & 0xff;
790         this_sz >>= 8;
791       }
792     }
793     *x++ = marker;
794     ctx->pending_cx_data_sz += index_sz;
795 #ifdef TEST_SUPPLEMENTAL_SUPERFRAME_DATA
796     index_sz += index_sz_test;
797 #endif
798   }
799   return index_sz;
800 }
801 
802 // vp9 uses 10,000,000 ticks/second as time stamp
803 #define TICKS_PER_SEC 10000000LL
804 
timebase_units_to_ticks(const vpx_rational_t * timebase,int64_t n)805 static int64_t timebase_units_to_ticks(const vpx_rational_t *timebase,
806                                        int64_t n) {
807   return n * TICKS_PER_SEC * timebase->num / timebase->den;
808 }
809 
ticks_to_timebase_units(const vpx_rational_t * timebase,int64_t n)810 static int64_t ticks_to_timebase_units(const vpx_rational_t *timebase,
811                                        int64_t n) {
812   const int64_t round = TICKS_PER_SEC * timebase->num / 2 - 1;
813   return (n * timebase->den + round) / timebase->num / TICKS_PER_SEC;
814 }
815 
get_frame_pkt_flags(const VP9_COMP * cpi,unsigned int lib_flags)816 static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP9_COMP *cpi,
817                                                    unsigned int lib_flags) {
818   vpx_codec_frame_flags_t flags = lib_flags << 16;
819 
820   if (lib_flags & FRAMEFLAGS_KEY
821 #if CONFIG_SPATIAL_SVC
822       || (is_two_pass_svc(cpi) && cpi->svc.layer_context[0].is_key_frame)
823 #endif
824         )
825     flags |= VPX_FRAME_IS_KEY;
826 
827   if (cpi->droppable)
828     flags |= VPX_FRAME_IS_DROPPABLE;
829 
830   return flags;
831 }
832 
encoder_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)833 static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t  *ctx,
834                                       const vpx_image_t *img,
835                                       vpx_codec_pts_t pts,
836                                       unsigned long duration,
837                                       vpx_enc_frame_flags_t flags,
838                                       unsigned long deadline) {
839   vpx_codec_err_t res = VPX_CODEC_OK;
840   VP9_COMP *const cpi = ctx->cpi;
841   const vpx_rational_t *const timebase = &ctx->cfg.g_timebase;
842 
843   if (img != NULL) {
844     res = validate_img(ctx, img);
845     // TODO(jzern) the checks related to cpi's validity should be treated as a
846     // failure condition, encoder setup is done fully in init() currently.
847     if (res == VPX_CODEC_OK && cpi != NULL && ctx->cx_data == NULL) {
848       // There's no codec control for multiple alt-refs so check the encoder
849       // instance for its status to determine the compressed data size.
850       ctx->cx_data_sz = ctx->cfg.g_w * ctx->cfg.g_h *
851                         get_image_bps(img) / 8 *
852                         (cpi->multi_arf_allowed ? 8 : 2);
853       if (ctx->cx_data_sz < 4096) ctx->cx_data_sz = 4096;
854 
855       ctx->cx_data = (unsigned char *)malloc(ctx->cx_data_sz);
856       if (ctx->cx_data == NULL) {
857         return VPX_CODEC_MEM_ERROR;
858       }
859     }
860   }
861 
862   pick_quickcompress_mode(ctx, duration, deadline);
863   vpx_codec_pkt_list_init(&ctx->pkt_list);
864 
865   // Handle Flags
866   if (((flags & VP8_EFLAG_NO_UPD_GF) && (flags & VP8_EFLAG_FORCE_GF)) ||
867        ((flags & VP8_EFLAG_NO_UPD_ARF) && (flags & VP8_EFLAG_FORCE_ARF))) {
868     ctx->base.err_detail = "Conflicting flags.";
869     return VPX_CODEC_INVALID_PARAM;
870   }
871 
872   vp9_apply_encoding_flags(cpi, flags);
873 
874   // Handle fixed keyframe intervals
875   if (ctx->cfg.kf_mode == VPX_KF_AUTO &&
876       ctx->cfg.kf_min_dist == ctx->cfg.kf_max_dist) {
877     if (++ctx->fixed_kf_cntr > ctx->cfg.kf_min_dist) {
878       flags |= VPX_EFLAG_FORCE_KF;
879       ctx->fixed_kf_cntr = 1;
880     }
881   }
882 
883   // Initialize the encoder instance on the first frame.
884   if (res == VPX_CODEC_OK && cpi != NULL) {
885     unsigned int lib_flags = 0;
886     YV12_BUFFER_CONFIG sd;
887     int64_t dst_time_stamp = timebase_units_to_ticks(timebase, pts);
888     int64_t dst_end_time_stamp =
889         timebase_units_to_ticks(timebase, pts + duration);
890     size_t size, cx_data_sz;
891     unsigned char *cx_data;
892 
893     // Set up internal flags
894     if (ctx->base.init_flags & VPX_CODEC_USE_PSNR)
895       cpi->b_calculate_psnr = 1;
896 
897     if (img != NULL) {
898       res = image2yuvconfig(img, &sd);
899 
900       // Store the original flags in to the frame buffer. Will extract the
901       // key frame flag when we actually encode this frame.
902       if (vp9_receive_raw_frame(cpi, flags,
903                                 &sd, dst_time_stamp, dst_end_time_stamp)) {
904         res = update_error_state(ctx, &cpi->common.error);
905       }
906     }
907 
908     cx_data = ctx->cx_data;
909     cx_data_sz = ctx->cx_data_sz;
910 
911     /* Any pending invisible frames? */
912     if (ctx->pending_cx_data) {
913       memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
914       ctx->pending_cx_data = cx_data;
915       cx_data += ctx->pending_cx_data_sz;
916       cx_data_sz -= ctx->pending_cx_data_sz;
917 
918       /* TODO: this is a minimal check, the underlying codec doesn't respect
919        * the buffer size anyway.
920        */
921       if (cx_data_sz < ctx->cx_data_sz / 2) {
922         ctx->base.err_detail = "Compressed data buffer too small";
923         return VPX_CODEC_ERROR;
924       }
925     }
926 
927     while (cx_data_sz >= ctx->cx_data_sz / 2 &&
928            -1 != vp9_get_compressed_data(cpi, &lib_flags, &size,
929                                          cx_data, &dst_time_stamp,
930                                          &dst_end_time_stamp, !img)) {
931       if (size) {
932         vpx_codec_cx_pkt_t pkt;
933 
934 #if CONFIG_SPATIAL_SVC
935         if (is_two_pass_svc(cpi))
936           cpi->svc.layer_context[cpi->svc.spatial_layer_id].layer_size += size;
937 #endif
938 
939         // Pack invisible frames with the next visible frame
940         if (!cpi->common.show_frame
941 #if CONFIG_SPATIAL_SVC
942             || (is_two_pass_svc(cpi) &&
943                 cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)
944 #endif
945             ) {
946           if (ctx->pending_cx_data == 0)
947             ctx->pending_cx_data = cx_data;
948           ctx->pending_cx_data_sz += size;
949           ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
950           ctx->pending_frame_magnitude |= size;
951           cx_data += size;
952           cx_data_sz -= size;
953           continue;
954         }
955 
956         // Add the frame packet to the list of returned packets.
957         pkt.kind = VPX_CODEC_CX_FRAME_PKT;
958         pkt.data.frame.pts = ticks_to_timebase_units(timebase, dst_time_stamp);
959         pkt.data.frame.duration =
960            (unsigned long)ticks_to_timebase_units(timebase,
961                dst_end_time_stamp - dst_time_stamp);
962         pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
963 
964         if (ctx->pending_cx_data) {
965           ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
966           ctx->pending_frame_magnitude |= size;
967           ctx->pending_cx_data_sz += size;
968           size += write_superframe_index(ctx);
969           pkt.data.frame.buf = ctx->pending_cx_data;
970           pkt.data.frame.sz  = ctx->pending_cx_data_sz;
971           ctx->pending_cx_data = NULL;
972           ctx->pending_cx_data_sz = 0;
973           ctx->pending_frame_count = 0;
974           ctx->pending_frame_magnitude = 0;
975         } else {
976           pkt.data.frame.buf = cx_data;
977           pkt.data.frame.sz  = size;
978         }
979         pkt.data.frame.partition_id = -1;
980         vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
981         cx_data += size;
982         cx_data_sz -= size;
983 #if CONFIG_SPATIAL_SVC
984         if (is_two_pass_svc(cpi)) {
985           vpx_codec_cx_pkt_t pkt_sizes, pkt_psnr;
986           int i;
987           vp9_zero(pkt_sizes);
988           vp9_zero(pkt_psnr);
989           pkt_sizes.kind = VPX_CODEC_SPATIAL_SVC_LAYER_SIZES;
990           pkt_psnr.kind = VPX_CODEC_SPATIAL_SVC_LAYER_PSNR;
991           for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
992             LAYER_CONTEXT *lc = &cpi->svc.layer_context[i];
993             pkt_sizes.data.layer_sizes[i] = lc->layer_size;
994             pkt_psnr.data.layer_psnr[i] = lc->psnr_pkt;
995             lc->layer_size = 0;
996           }
997           vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_sizes);
998           vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_psnr);
999         }
1000 #endif
1001       }
1002     }
1003   }
1004 
1005   return res;
1006 }
1007 
encoder_get_cxdata(vpx_codec_alg_priv_t * ctx,vpx_codec_iter_t * iter)1008 static const vpx_codec_cx_pkt_t *encoder_get_cxdata(vpx_codec_alg_priv_t *ctx,
1009                                                     vpx_codec_iter_t *iter) {
1010   return vpx_codec_pkt_list_get(&ctx->pkt_list.head, iter);
1011 }
1012 
ctrl_set_reference(vpx_codec_alg_priv_t * ctx,va_list args)1013 static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
1014                                           va_list args) {
1015   vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
1016 
1017   if (frame != NULL) {
1018     YV12_BUFFER_CONFIG sd;
1019 
1020     image2yuvconfig(&frame->img, &sd);
1021     vp9_set_reference_enc(ctx->cpi, ref_frame_to_vp9_reframe(frame->frame_type),
1022                           &sd);
1023     return VPX_CODEC_OK;
1024   } else {
1025     return VPX_CODEC_INVALID_PARAM;
1026   }
1027 }
1028 
ctrl_copy_reference(vpx_codec_alg_priv_t * ctx,va_list args)1029 static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
1030                                            va_list args) {
1031   vpx_ref_frame_t *const frame = va_arg(args, vpx_ref_frame_t *);
1032 
1033   if (frame != NULL) {
1034     YV12_BUFFER_CONFIG sd;
1035 
1036     image2yuvconfig(&frame->img, &sd);
1037     vp9_copy_reference_enc(ctx->cpi,
1038                            ref_frame_to_vp9_reframe(frame->frame_type), &sd);
1039     return VPX_CODEC_OK;
1040   } else {
1041     return VPX_CODEC_INVALID_PARAM;
1042   }
1043 }
1044 
ctrl_get_reference(vpx_codec_alg_priv_t * ctx,va_list args)1045 static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
1046                                           va_list args) {
1047   vp9_ref_frame_t *const frame = va_arg(args, vp9_ref_frame_t *);
1048 
1049   if (frame != NULL) {
1050     YV12_BUFFER_CONFIG *fb = get_ref_frame(&ctx->cpi->common, frame->idx);
1051     if (fb == NULL) return VPX_CODEC_ERROR;
1052 
1053     yuvconfig2image(&frame->img, fb, NULL);
1054     return VPX_CODEC_OK;
1055   } else {
1056     return VPX_CODEC_INVALID_PARAM;
1057   }
1058 }
1059 
ctrl_set_previewpp(vpx_codec_alg_priv_t * ctx,va_list args)1060 static vpx_codec_err_t ctrl_set_previewpp(vpx_codec_alg_priv_t *ctx,
1061                                           va_list args) {
1062 #if CONFIG_VP9_POSTPROC
1063   vp8_postproc_cfg_t *config = va_arg(args, vp8_postproc_cfg_t *);
1064   if (config != NULL) {
1065     ctx->preview_ppcfg = *config;
1066     return VPX_CODEC_OK;
1067   } else {
1068     return VPX_CODEC_INVALID_PARAM;
1069   }
1070 #else
1071   (void)ctx;
1072   (void)args;
1073   return VPX_CODEC_INCAPABLE;
1074 #endif
1075 }
1076 
1077 
encoder_get_preview(vpx_codec_alg_priv_t * ctx)1078 static vpx_image_t *encoder_get_preview(vpx_codec_alg_priv_t *ctx) {
1079   YV12_BUFFER_CONFIG sd;
1080   vp9_ppflags_t flags;
1081   vp9_zero(flags);
1082 
1083   if (ctx->preview_ppcfg.post_proc_flag) {
1084     flags.post_proc_flag   = ctx->preview_ppcfg.post_proc_flag;
1085     flags.deblocking_level = ctx->preview_ppcfg.deblocking_level;
1086     flags.noise_level      = ctx->preview_ppcfg.noise_level;
1087   }
1088 
1089   if (vp9_get_preview_raw_frame(ctx->cpi, &sd, &flags) == 0) {
1090     yuvconfig2image(&ctx->preview_img, &sd, NULL);
1091     return &ctx->preview_img;
1092   } else {
1093     return NULL;
1094   }
1095 }
1096 
ctrl_update_entropy(vpx_codec_alg_priv_t * ctx,va_list args)1097 static vpx_codec_err_t ctrl_update_entropy(vpx_codec_alg_priv_t *ctx,
1098                                            va_list args) {
1099   const int update = va_arg(args, int);
1100 
1101   vp9_update_entropy(ctx->cpi, update);
1102   return VPX_CODEC_OK;
1103 }
1104 
ctrl_update_reference(vpx_codec_alg_priv_t * ctx,va_list args)1105 static vpx_codec_err_t ctrl_update_reference(vpx_codec_alg_priv_t *ctx,
1106                                              va_list args) {
1107   const int ref_frame_flags = va_arg(args, int);
1108 
1109   vp9_update_reference(ctx->cpi, ref_frame_flags);
1110   return VPX_CODEC_OK;
1111 }
1112 
ctrl_use_reference(vpx_codec_alg_priv_t * ctx,va_list args)1113 static vpx_codec_err_t ctrl_use_reference(vpx_codec_alg_priv_t *ctx,
1114                                           va_list args) {
1115   const int reference_flag = va_arg(args, int);
1116 
1117   vp9_use_as_reference(ctx->cpi, reference_flag);
1118   return VPX_CODEC_OK;
1119 }
1120 
ctrl_set_roi_map(vpx_codec_alg_priv_t * ctx,va_list args)1121 static vpx_codec_err_t ctrl_set_roi_map(vpx_codec_alg_priv_t *ctx,
1122                                         va_list args) {
1123   (void)ctx;
1124   (void)args;
1125 
1126   // TODO(yaowu): Need to re-implement and test for VP9.
1127   return VPX_CODEC_INVALID_PARAM;
1128 }
1129 
1130 
ctrl_set_active_map(vpx_codec_alg_priv_t * ctx,va_list args)1131 static vpx_codec_err_t ctrl_set_active_map(vpx_codec_alg_priv_t *ctx,
1132                                            va_list args) {
1133   vpx_active_map_t *const map = va_arg(args, vpx_active_map_t *);
1134 
1135   if (map) {
1136     if (!vp9_set_active_map(ctx->cpi, map->active_map,
1137                             (int)map->rows, (int)map->cols))
1138       return VPX_CODEC_OK;
1139     else
1140       return VPX_CODEC_INVALID_PARAM;
1141   } else {
1142     return VPX_CODEC_INVALID_PARAM;
1143   }
1144 }
1145 
ctrl_set_scale_mode(vpx_codec_alg_priv_t * ctx,va_list args)1146 static vpx_codec_err_t ctrl_set_scale_mode(vpx_codec_alg_priv_t *ctx,
1147                                            va_list args) {
1148   vpx_scaling_mode_t *const mode = va_arg(args, vpx_scaling_mode_t *);
1149 
1150   if (mode) {
1151     const int res = vp9_set_internal_size(ctx->cpi,
1152                                           (VPX_SCALING)mode->h_scaling_mode,
1153                                           (VPX_SCALING)mode->v_scaling_mode);
1154     return (res == 0) ? VPX_CODEC_OK : VPX_CODEC_INVALID_PARAM;
1155   } else {
1156     return VPX_CODEC_INVALID_PARAM;
1157   }
1158 }
1159 
ctrl_set_svc(vpx_codec_alg_priv_t * ctx,va_list args)1160 static vpx_codec_err_t ctrl_set_svc(vpx_codec_alg_priv_t *ctx, va_list args) {
1161   int data = va_arg(args, int);
1162   const vpx_codec_enc_cfg_t *cfg = &ctx->cfg;
1163 
1164   vp9_set_svc(ctx->cpi, data);
1165   // CBR or two pass mode for SVC with both temporal and spatial layers
1166   // not yet supported.
1167   if (data == 1 &&
1168       (cfg->rc_end_usage == VPX_CBR ||
1169        cfg->g_pass == VPX_RC_FIRST_PASS ||
1170        cfg->g_pass == VPX_RC_LAST_PASS) &&
1171       cfg->ss_number_layers > 1 &&
1172       cfg->ts_number_layers > 1) {
1173     return VPX_CODEC_INVALID_PARAM;
1174   }
1175   return VPX_CODEC_OK;
1176 }
1177 
ctrl_set_svc_layer_id(vpx_codec_alg_priv_t * ctx,va_list args)1178 static vpx_codec_err_t ctrl_set_svc_layer_id(vpx_codec_alg_priv_t *ctx,
1179                                              va_list args) {
1180   vpx_svc_layer_id_t *const data = va_arg(args, vpx_svc_layer_id_t *);
1181   VP9_COMP *const cpi = (VP9_COMP *)ctx->cpi;
1182   SVC *const svc = &cpi->svc;
1183 
1184   svc->spatial_layer_id = data->spatial_layer_id;
1185   svc->temporal_layer_id = data->temporal_layer_id;
1186   // Checks on valid layer_id input.
1187   if (svc->temporal_layer_id < 0 ||
1188       svc->temporal_layer_id >= (int)ctx->cfg.ts_number_layers) {
1189     return VPX_CODEC_INVALID_PARAM;
1190   }
1191   if (svc->spatial_layer_id < 0 ||
1192       svc->spatial_layer_id >= (int)ctx->cfg.ss_number_layers) {
1193     return VPX_CODEC_INVALID_PARAM;
1194   }
1195   return VPX_CODEC_OK;
1196 }
1197 
ctrl_set_svc_parameters(vpx_codec_alg_priv_t * ctx,va_list args)1198 static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
1199                                                va_list args) {
1200   VP9_COMP *const cpi = ctx->cpi;
1201   vpx_svc_extra_cfg_t *const params = va_arg(args, vpx_svc_extra_cfg_t *);
1202   int i;
1203 
1204   for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
1205     LAYER_CONTEXT *lc = &cpi->svc.layer_context[i];
1206 
1207     lc->max_q = params->max_quantizers[i];
1208     lc->min_q = params->min_quantizers[i];
1209     lc->scaling_factor_num = params->scaling_factor_num[i];
1210     lc->scaling_factor_den = params->scaling_factor_den[i];
1211   }
1212 
1213   return VPX_CODEC_OK;
1214 }
1215 
ctrl_set_tune_content(vpx_codec_alg_priv_t * ctx,va_list args)1216 static vpx_codec_err_t ctrl_set_tune_content(vpx_codec_alg_priv_t *ctx,
1217                                              va_list args) {
1218   struct vp9_extracfg extra_cfg = ctx->extra_cfg;
1219   extra_cfg.content = CAST(VP9E_SET_TUNE_CONTENT, args);
1220   return update_extra_cfg(ctx, &extra_cfg);
1221 }
1222 
1223 static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
1224   {VP8_COPY_REFERENCE,                ctrl_copy_reference},
1225   {VP8E_UPD_ENTROPY,                  ctrl_update_entropy},
1226   {VP8E_UPD_REFERENCE,                ctrl_update_reference},
1227   {VP8E_USE_REFERENCE,                ctrl_use_reference},
1228 
1229   // Setters
1230   {VP8_SET_REFERENCE,                 ctrl_set_reference},
1231   {VP8_SET_POSTPROC,                  ctrl_set_previewpp},
1232   {VP8E_SET_ROI_MAP,                  ctrl_set_roi_map},
1233   {VP8E_SET_ACTIVEMAP,                ctrl_set_active_map},
1234   {VP8E_SET_SCALEMODE,                ctrl_set_scale_mode},
1235   {VP8E_SET_CPUUSED,                  ctrl_set_cpuused},
1236   {VP8E_SET_ENABLEAUTOALTREF,         ctrl_set_enable_auto_alt_ref},
1237   {VP8E_SET_SHARPNESS,                ctrl_set_sharpness},
1238   {VP8E_SET_STATIC_THRESHOLD,         ctrl_set_static_thresh},
1239   {VP9E_SET_TILE_COLUMNS,             ctrl_set_tile_columns},
1240   {VP9E_SET_TILE_ROWS,                ctrl_set_tile_rows},
1241   {VP8E_SET_ARNR_MAXFRAMES,           ctrl_set_arnr_max_frames},
1242   {VP8E_SET_ARNR_STRENGTH,            ctrl_set_arnr_strength},
1243   {VP8E_SET_ARNR_TYPE,                ctrl_set_arnr_type},
1244   {VP8E_SET_TUNING,                   ctrl_set_tuning},
1245   {VP8E_SET_CQ_LEVEL,                 ctrl_set_cq_level},
1246   {VP8E_SET_MAX_INTRA_BITRATE_PCT,    ctrl_set_rc_max_intra_bitrate_pct},
1247   {VP9E_SET_LOSSLESS,                 ctrl_set_lossless},
1248   {VP9E_SET_FRAME_PARALLEL_DECODING,  ctrl_set_frame_parallel_decoding_mode},
1249   {VP9E_SET_AQ_MODE,                  ctrl_set_aq_mode},
1250   {VP9E_SET_FRAME_PERIODIC_BOOST,     ctrl_set_frame_periodic_boost},
1251   {VP9E_SET_SVC,                      ctrl_set_svc},
1252   {VP9E_SET_SVC_PARAMETERS,           ctrl_set_svc_parameters},
1253   {VP9E_SET_SVC_LAYER_ID,             ctrl_set_svc_layer_id},
1254   {VP9E_SET_TUNE_CONTENT,             ctrl_set_tune_content},
1255   {VP9E_SET_NOISE_SENSITIVITY,        ctrl_set_noise_sensitivity},
1256 
1257   // Getters
1258   {VP8E_GET_LAST_QUANTIZER,           ctrl_get_quantizer},
1259   {VP8E_GET_LAST_QUANTIZER_64,        ctrl_get_quantizer64},
1260   {VP9_GET_REFERENCE,                 ctrl_get_reference},
1261 
1262   { -1, NULL},
1263 };
1264 
1265 static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
1266   {
1267     0,
1268     {  // NOLINT
1269       0,                  // g_usage
1270       0,                  // g_threads
1271       0,                  // g_profile
1272 
1273       320,                // g_width
1274       240,                // g_height
1275       VPX_BITS_8,         // g_bit_depth
1276       8,                  // g_input_bit_depth
1277 
1278       {1, 30},            // g_timebase
1279 
1280       0,                  // g_error_resilient
1281 
1282       VPX_RC_ONE_PASS,    // g_pass
1283 
1284       25,                 // g_lag_in_frames
1285 
1286       0,                  // rc_dropframe_thresh
1287       0,                  // rc_resize_allowed
1288       1,                  // rc_scaled_width
1289       1,                  // rc_scaled_height
1290       60,                 // rc_resize_down_thresold
1291       30,                 // rc_resize_up_thresold
1292 
1293       VPX_VBR,            // rc_end_usage
1294 #if VPX_ENCODER_ABI_VERSION > (1 + VPX_CODEC_ABI_VERSION)
1295       {NULL, 0},          // rc_twopass_stats_in
1296       {NULL, 0},          // rc_firstpass_mb_stats_in
1297 #endif
1298       256,                // rc_target_bandwidth
1299       0,                  // rc_min_quantizer
1300       63,                 // rc_max_quantizer
1301       100,                // rc_undershoot_pct
1302       100,                // rc_overshoot_pct
1303 
1304       6000,               // rc_max_buffer_size
1305       4000,               // rc_buffer_initial_size
1306       5000,               // rc_buffer_optimal_size
1307 
1308       50,                 // rc_two_pass_vbrbias
1309       0,                  // rc_two_pass_vbrmin_section
1310       2000,               // rc_two_pass_vbrmax_section
1311 
1312       // keyframing settings (kf)
1313       VPX_KF_AUTO,        // g_kfmode
1314       0,                  // kf_min_dist
1315       9999,               // kf_max_dist
1316 
1317       VPX_SS_DEFAULT_LAYERS,  // ss_number_layers
1318       {0},
1319       {0},                    // ss_target_bitrate
1320       1,                      // ts_number_layers
1321       {0},                    // ts_target_bitrate
1322       {0},                    // ts_rate_decimator
1323       0,                      // ts_periodicity
1324       {0},                    // ts_layer_id
1325 #if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
1326       "vp8.fpf"           // first pass filename
1327 #endif
1328     }
1329   },
1330 };
1331 
1332 #ifndef VERSION_STRING
1333 #define VERSION_STRING
1334 #endif
1335 CODEC_INTERFACE(vpx_codec_vp9_cx) = {
1336   "WebM Project VP9 Encoder" VERSION_STRING,
1337   VPX_CODEC_INTERNAL_ABI_VERSION,
1338 #if CONFIG_VP9_HIGHBITDEPTH
1339   VPX_CODEC_CAP_HIGHBITDEPTH |
1340 #endif
1341   VPX_CODEC_CAP_ENCODER | VPX_CODEC_CAP_PSNR,  // vpx_codec_caps_t
1342   encoder_init,       // vpx_codec_init_fn_t
1343   encoder_destroy,    // vpx_codec_destroy_fn_t
1344   encoder_ctrl_maps,  // vpx_codec_ctrl_fn_map_t
1345   {  // NOLINT
1346     NULL,  // vpx_codec_peek_si_fn_t
1347     NULL,  // vpx_codec_get_si_fn_t
1348     NULL,  // vpx_codec_decode_fn_t
1349     NULL,  // vpx_codec_frame_get_fn_t
1350     NULL   // vpx_codec_set_fb_fn_t
1351   },
1352   {  // NOLINT
1353     1,                      // 1 cfg map
1354     encoder_usage_cfg_map,  // vpx_codec_enc_cfg_map_t
1355     encoder_encode,         // vpx_codec_encode_fn_t
1356     encoder_get_cxdata,     // vpx_codec_get_cx_data_fn_t
1357     encoder_set_config,     // vpx_codec_enc_config_set_fn_t
1358     NULL,        // vpx_codec_get_global_headers_fn_t
1359     encoder_get_preview,    // vpx_codec_get_preview_frame_fn_t
1360     NULL         // vpx_codec_enc_mr_get_mem_loc_fn_t
1361   }
1362 };
1363