Home | History | Annotate | Download | only in src
      1 /*
      2  *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 /**
     12  * @file
     13  * VP9 SVC encoding support via libvpx
     14  */
     15 
     16 #include <stdarg.h>
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <string.h>
     20 #define VPX_DISABLE_CTRL_TYPECHECKS 1
     21 #define VPX_CODEC_DISABLE_COMPAT 1
     22 #include "vpx/svc_context.h"
     23 #include "vpx/vp8cx.h"
     24 #include "vpx/vpx_encoder.h"
     25 
     26 #if defined(__MINGW32__) && !defined(MINGW_HAS_SECURE_API)
     27 #define strtok_r strtok_s
     28 // proto from /usr/x86_64-w64-mingw32/include/sec_api/string_s.h
     29 _CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context);
     30 #endif
     31 
     32 #ifdef _MSC_VER
     33 #define strdup _strdup
     34 #define strtok_r strtok_s
     35 #endif
     36 
     37 #define SVC_REFERENCE_FRAMES 8
     38 #define SUPERFRAME_SLOTS (8)
     39 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2)
     40 #define OPTION_BUFFER_SIZE 256
     41 
     42 static const char *DEFAULT_QUANTIZER_VALUES = "60,53,39,33,27";
     43 static const char *DEFAULT_SCALE_FACTORS = "4/16,5/16,7/16,11/16,16/16";
     44 
     45 typedef struct SvcInternal {
     46   char options[OPTION_BUFFER_SIZE];        // set by vpx_svc_set_options
     47   char quantizers[OPTION_BUFFER_SIZE];     // set by vpx_svc_set_quantizers
     48   char scale_factors[OPTION_BUFFER_SIZE];  // set by vpx_svc_set_scale_factors
     49 
     50   // values extracted from option, quantizers
     51   int scaling_factor_num[VPX_SS_MAX_LAYERS];
     52   int scaling_factor_den[VPX_SS_MAX_LAYERS];
     53   int quantizer[VPX_SS_MAX_LAYERS];
     54 
     55   // accumulated statistics
     56   double psnr_in_layer[VPX_SS_MAX_LAYERS];
     57   uint32_t bytes_in_layer[VPX_SS_MAX_LAYERS];
     58 
     59   // codec encoding values
     60   int width;    // width of highest layer
     61   int height;   // height of highest layer
     62   int kf_dist;  // distance between keyframes
     63 
     64   // state variables
     65   int encode_frame_count;
     66   int frame_within_gop;
     67   vpx_enc_frame_flags_t enc_frame_flags;
     68   int layers;
     69   int layer;
     70   int is_keyframe;
     71 
     72   size_t frame_size;
     73   size_t buffer_size;
     74   void *buffer;
     75 
     76   char message_buffer[2048];
     77   vpx_codec_ctx_t *codec_ctx;
     78 } SvcInternal;
     79 
     80 // Superframe is used to generate an index of individual frames (i.e., layers)
     81 struct Superframe {
     82   int count;
     83   uint32_t sizes[SUPERFRAME_SLOTS];
     84   uint32_t magnitude;
     85   uint8_t buffer[SUPERFRAME_BUFFER_SIZE];
     86   size_t index_size;
     87 };
     88 
     89 // One encoded frame layer
     90 struct LayerData {
     91   void *buf;    // compressed data buffer
     92   size_t size;  // length of compressed data
     93   struct LayerData *next;
     94 };
     95 
     96 // create LayerData from encoder output
     97 static struct LayerData *ld_create(void *buf, size_t size) {
     98   struct LayerData *const layer_data = malloc(sizeof(*layer_data));
     99   if (layer_data == NULL) {
    100     return NULL;
    101   }
    102   layer_data->buf = malloc(size);
    103   if (layer_data->buf == NULL) {
    104     free(layer_data);
    105     return NULL;
    106   }
    107   memcpy(layer_data->buf, buf, size);
    108   layer_data->size = size;
    109   return layer_data;
    110 }
    111 
    112 // free LayerData
    113 static void ld_free(struct LayerData *layer_data) {
    114   if (layer_data) {
    115     if (layer_data->buf) {
    116       free(layer_data->buf);
    117       layer_data->buf = NULL;
    118     }
    119     free(layer_data);
    120   }
    121 }
    122 
    123 // add layer data to list
    124 static void ld_list_add(struct LayerData **list, struct LayerData *layer_data) {
    125   struct LayerData **p = list;
    126 
    127   while (*p != NULL) p = &(*p)->next;
    128   *p = layer_data;
    129   layer_data->next = NULL;
    130 }
    131 
    132 // get accumulated size of layer data
    133 static size_t ld_list_get_buffer_size(struct LayerData *list) {
    134   struct LayerData *p;
    135   size_t size = 0;
    136 
    137   for (p = list; p != NULL; p = p->next) {
    138     size += p->size;
    139   }
    140   return size;
    141 }
    142 
    143 // copy layer data to buffer
    144 static void ld_list_copy_to_buffer(struct LayerData *list, uint8_t *buffer) {
    145   struct LayerData *p;
    146 
    147   for (p = list; p != NULL; p = p->next) {
    148     buffer[0] = 1;
    149     memcpy(buffer, p->buf, p->size);
    150     buffer += p->size;
    151   }
    152 }
    153 
    154 // free layer data list
    155 static void ld_list_free(struct LayerData *list) {
    156   struct LayerData *p = list;
    157 
    158   while (p) {
    159     list = list->next;
    160     ld_free(p);
    161     p = list;
    162   }
    163 }
    164 
    165 static void sf_create_index(struct Superframe *sf) {
    166   uint8_t marker = 0xc0;
    167   int i;
    168   uint32_t mag, mask;
    169   uint8_t *bufp;
    170 
    171   if (sf->count == 0 || sf->count >= 8) return;
    172 
    173   // Add the number of frames to the marker byte
    174   marker |= sf->count - 1;
    175 
    176   // Choose the magnitude
    177   for (mag = 0, mask = 0xff; mag < 4; ++mag) {
    178     if (sf->magnitude < mask) break;
    179     mask <<= 8;
    180     mask |= 0xff;
    181   }
    182   marker |= mag << 3;
    183 
    184   // Write the index
    185   sf->index_size = 2 + (mag + 1) * sf->count;
    186   bufp = sf->buffer;
    187 
    188   *bufp++ = marker;
    189   for (i = 0; i < sf->count; ++i) {
    190     int this_sz = sf->sizes[i];
    191     uint32_t j;
    192 
    193     for (j = 0; j <= mag; ++j) {
    194       *bufp++ = this_sz & 0xff;
    195       this_sz >>= 8;
    196     }
    197   }
    198   *bufp++ = marker;
    199 }
    200 
    201 static SvcInternal *get_svc_internal(SvcContext *svc_ctx) {
    202   if (svc_ctx == NULL) return NULL;
    203   if (svc_ctx->internal == NULL) {
    204     SvcInternal *const si = malloc(sizeof(*si));
    205     if (si != NULL) {
    206       memset(si, 0, sizeof(*si));
    207     }
    208     svc_ctx->internal = si;
    209   }
    210   return svc_ctx->internal;
    211 }
    212 
    213 static const SvcInternal *get_const_svc_internal(const SvcContext *svc_ctx) {
    214   if (svc_ctx == NULL) return NULL;
    215   return svc_ctx->internal;
    216 }
    217 
    218 static void svc_log_reset(SvcContext *svc_ctx) {
    219   SvcInternal *const si = (SvcInternal *)svc_ctx->internal;
    220   si->message_buffer[0] = '\0';
    221 }
    222 
    223 static int svc_log(SvcContext *svc_ctx, int level, const char *fmt, ...) {
    224   char buf[512];
    225   int retval = 0;
    226   va_list ap;
    227   SvcInternal *const si = get_svc_internal(svc_ctx);
    228 
    229   if (level > svc_ctx->log_level) {
    230     return retval;
    231   }
    232 
    233   va_start(ap, fmt);
    234   retval = vsnprintf(buf, sizeof(buf), fmt, ap);
    235   va_end(ap);
    236 
    237   if (svc_ctx->log_print) {
    238     printf("%s", buf);
    239   } else {
    240     strncat(si->message_buffer, buf,
    241             sizeof(si->message_buffer) - strlen(si->message_buffer) - 1);
    242   }
    243 
    244   if (level == SVC_LOG_ERROR) {
    245     si->codec_ctx->err_detail = si->message_buffer;
    246   }
    247   return retval;
    248 }
    249 
    250 static vpx_codec_err_t set_option_encoding_mode(SvcContext *svc_ctx,
    251                                                 const char *value_str) {
    252   if (strcmp(value_str, "i") == 0) {
    253     svc_ctx->encoding_mode = INTER_LAYER_PREDICTION_I;
    254   } else if (strcmp(value_str, "alt-ip") == 0) {
    255     svc_ctx->encoding_mode = ALT_INTER_LAYER_PREDICTION_IP;
    256   } else if (strcmp(value_str, "ip") == 0) {
    257     svc_ctx->encoding_mode = INTER_LAYER_PREDICTION_IP;
    258   } else if (strcmp(value_str, "gf") == 0) {
    259     svc_ctx->encoding_mode = USE_GOLDEN_FRAME;
    260   } else {
    261     svc_log(svc_ctx, SVC_LOG_ERROR, "invalid encoding mode: %s", value_str);
    262     return VPX_CODEC_INVALID_PARAM;
    263   }
    264   return VPX_CODEC_OK;
    265 }
    266 
    267 static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx,
    268                                               const char *quantizer_values) {
    269   char *input_string;
    270   char *token;
    271   const char *delim = ",";
    272   char *save_ptr;
    273   int found = 0;
    274   int i, q;
    275   int res = VPX_CODEC_OK;
    276   SvcInternal *const si = get_svc_internal(svc_ctx);
    277 
    278   if (quantizer_values == NULL || strlen(quantizer_values) == 0) {
    279     input_string = strdup(DEFAULT_QUANTIZER_VALUES);
    280   } else {
    281     input_string = strdup(quantizer_values);
    282   }
    283 
    284   token = strtok_r(input_string, delim, &save_ptr);
    285   for (i = 0; i < svc_ctx->spatial_layers; ++i) {
    286     if (token != NULL) {
    287       q = atoi(token);
    288       if (q <= 0 || q > 100) {
    289         svc_log(svc_ctx, SVC_LOG_ERROR,
    290                 "svc-quantizer-values: invalid value %s\n", token);
    291         res = VPX_CODEC_INVALID_PARAM;
    292         break;
    293       }
    294       token = strtok_r(NULL, delim, &save_ptr);
    295       found = i + 1;
    296     } else {
    297       q = 0;
    298     }
    299     si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q;
    300   }
    301   if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
    302     svc_log(svc_ctx, SVC_LOG_ERROR,
    303             "svc: quantizers: %d values required, but only %d specified\n",
    304             svc_ctx->spatial_layers, found);
    305     res = VPX_CODEC_INVALID_PARAM;
    306   }
    307   free(input_string);
    308   return res;
    309 }
    310 
    311 static void log_invalid_scale_factor(SvcContext *svc_ctx, const char *value) {
    312   svc_log(svc_ctx, SVC_LOG_ERROR, "svc scale-factors: invalid value %s\n",
    313           value);
    314 }
    315 
    316 static vpx_codec_err_t parse_scale_factors(SvcContext *svc_ctx,
    317                                            const char *scale_factors) {
    318   char *input_string;
    319   char *token;
    320   const char *delim = ",";
    321   char *save_ptr;
    322   int found = 0;
    323   int i;
    324   int64_t num, den;
    325   int res = VPX_CODEC_OK;
    326   SvcInternal *const si = get_svc_internal(svc_ctx);
    327 
    328   if (scale_factors == NULL || strlen(scale_factors) == 0) {
    329     input_string = strdup(DEFAULT_SCALE_FACTORS);
    330   } else {
    331     input_string = strdup(scale_factors);
    332   }
    333   token = strtok_r(input_string, delim, &save_ptr);
    334   for (i = 0; i < svc_ctx->spatial_layers; ++i) {
    335     num = den = 0;
    336     if (token != NULL) {
    337       num = strtol(token, &token, 10);
    338       if (num <= 0) {
    339         log_invalid_scale_factor(svc_ctx, token);
    340         res = VPX_CODEC_INVALID_PARAM;
    341         break;
    342       }
    343       if (*token++ != '/') {
    344         log_invalid_scale_factor(svc_ctx, token);
    345         res = VPX_CODEC_INVALID_PARAM;
    346         break;
    347       }
    348       den = strtol(token, &token, 10);
    349       if (den <= 0) {
    350         log_invalid_scale_factor(svc_ctx, token);
    351         res = VPX_CODEC_INVALID_PARAM;
    352         break;
    353       }
    354       token = strtok_r(NULL, delim, &save_ptr);
    355       found = i + 1;
    356     }
    357     si->scaling_factor_num[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] =
    358         (int)num;
    359     si->scaling_factor_den[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] =
    360         (int)den;
    361   }
    362   if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
    363     svc_log(svc_ctx, SVC_LOG_ERROR,
    364             "svc: scale-factors: %d values required, but only %d specified\n",
    365             svc_ctx->spatial_layers, found);
    366     res = VPX_CODEC_INVALID_PARAM;
    367   }
    368   free(input_string);
    369   return res;
    370 }
    371 
    372 /**
    373  * Parse SVC encoding options
    374  * Format: encoding-mode=<svc_mode>,layers=<layer_count>
    375  *         scale-factors=<n1>/<d1>,<n2>/<d2>,...
    376  *         quantizers=<q1>,<q2>,...
    377  * svc_mode = [i|ip|alt_ip|gf]
    378  */
    379 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
    380   char *input_string;
    381   char *option_name;
    382   char *option_value;
    383   char *input_ptr;
    384   int res = VPX_CODEC_OK;
    385 
    386   if (options == NULL) return VPX_CODEC_OK;
    387   input_string = strdup(options);
    388 
    389   // parse option name
    390   option_name = strtok_r(input_string, "=", &input_ptr);
    391   while (option_name != NULL) {
    392     // parse option value
    393     option_value = strtok_r(NULL, " ", &input_ptr);
    394     if (option_value == NULL) {
    395       svc_log(svc_ctx, SVC_LOG_ERROR, "option missing value: %s\n",
    396               option_name);
    397       res = VPX_CODEC_INVALID_PARAM;
    398       break;
    399     }
    400     if (strcmp("encoding-mode", option_name) == 0) {
    401       res = set_option_encoding_mode(svc_ctx, option_value);
    402       if (res != VPX_CODEC_OK) break;
    403     } else if (strcmp("layers", option_name) == 0) {
    404       svc_ctx->spatial_layers = atoi(option_value);
    405     } else if (strcmp("scale-factors", option_name) == 0) {
    406       res = parse_scale_factors(svc_ctx, option_value);
    407       if (res != VPX_CODEC_OK) break;
    408     } else if (strcmp("quantizers", option_name) == 0) {
    409       res = parse_quantizer_values(svc_ctx, option_value);
    410       if (res != VPX_CODEC_OK) break;
    411     } else {
    412       svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name);
    413       res = VPX_CODEC_INVALID_PARAM;
    414       break;
    415     }
    416     option_name = strtok_r(NULL, "=", &input_ptr);
    417   }
    418   free(input_string);
    419   return res;
    420 }
    421 
    422 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) {
    423   SvcInternal *const si = get_svc_internal(svc_ctx);
    424   if (svc_ctx == NULL || options == NULL || si == NULL) {
    425     return VPX_CODEC_INVALID_PARAM;
    426   }
    427   strncpy(si->options, options, sizeof(si->options));
    428   si->options[sizeof(si->options) - 1] = '\0';
    429   return VPX_CODEC_OK;
    430 }
    431 
    432 vpx_codec_err_t vpx_svc_set_quantizers(SvcContext *svc_ctx,
    433                                        const char *quantizers) {
    434   SvcInternal *const si = get_svc_internal(svc_ctx);
    435   if (svc_ctx == NULL || quantizers == NULL || si == NULL) {
    436     return VPX_CODEC_INVALID_PARAM;
    437   }
    438   strncpy(si->quantizers, quantizers, sizeof(si->quantizers));
    439   si->quantizers[sizeof(si->quantizers) - 1] = '\0';
    440   return VPX_CODEC_OK;
    441 }
    442 
    443 vpx_codec_err_t vpx_svc_set_scale_factors(SvcContext *svc_ctx,
    444                                           const char *scale_factors) {
    445   SvcInternal *const si = get_svc_internal(svc_ctx);
    446   if (svc_ctx == NULL || scale_factors == NULL || si == NULL) {
    447     return VPX_CODEC_INVALID_PARAM;
    448   }
    449   strncpy(si->scale_factors, scale_factors, sizeof(si->scale_factors));
    450   si->scale_factors[sizeof(si->scale_factors) - 1] = '\0';
    451   return VPX_CODEC_OK;
    452 }
    453 
    454 vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
    455                              vpx_codec_iface_t *iface,
    456                              vpx_codec_enc_cfg_t *enc_cfg) {
    457   int max_intra_size_pct;
    458   vpx_codec_err_t res;
    459   SvcInternal *const si = get_svc_internal(svc_ctx);
    460   if (svc_ctx == NULL || codec_ctx == NULL || iface == NULL ||
    461       enc_cfg == NULL) {
    462     return VPX_CODEC_INVALID_PARAM;
    463   }
    464   if (si == NULL) return VPX_CODEC_MEM_ERROR;
    465 
    466   si->codec_ctx = codec_ctx;
    467 
    468   si->width = enc_cfg->g_w;
    469   si->height = enc_cfg->g_h;
    470 
    471   if (enc_cfg->kf_max_dist < 2) {
    472     svc_log(svc_ctx, SVC_LOG_ERROR, "key frame distance too small: %d\n",
    473             enc_cfg->kf_max_dist);
    474     return VPX_CODEC_INVALID_PARAM;
    475   }
    476   si->kf_dist = enc_cfg->kf_max_dist;
    477 
    478   if (svc_ctx->spatial_layers == 0)
    479     svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS;
    480   if (svc_ctx->spatial_layers < 1 ||
    481       svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) {
    482     svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n",
    483             svc_ctx->spatial_layers);
    484     return VPX_CODEC_INVALID_PARAM;
    485   }
    486   // use SvcInternal value for number of layers to enable forcing single layer
    487   // for first frame
    488   si->layers = svc_ctx->spatial_layers;
    489 
    490   res = parse_quantizer_values(svc_ctx, si->quantizers);
    491   if (res != VPX_CODEC_OK) return res;
    492 
    493   res = parse_scale_factors(svc_ctx, si->scale_factors);
    494   if (res != VPX_CODEC_OK) return res;
    495 
    496   // parse aggregate command line options
    497   res = parse_options(svc_ctx, si->options);
    498   if (res != VPX_CODEC_OK) return res;
    499 
    500   // modify encoder configuration
    501   enc_cfg->ss_number_layers = si->layers;
    502   enc_cfg->kf_mode = VPX_KF_DISABLED;
    503   enc_cfg->g_pass = VPX_RC_ONE_PASS;
    504   // Lag in frames not currently supported
    505   enc_cfg->g_lag_in_frames = 0;
    506 
    507   // TODO(ivanmaltz): determine if these values need to be set explicitly for
    508   // svc, or if the normal default/override mechanism can be used
    509   enc_cfg->rc_dropframe_thresh = 0;
    510   enc_cfg->rc_end_usage = VPX_CBR;
    511   enc_cfg->rc_resize_allowed = 0;
    512   enc_cfg->rc_min_quantizer = 33;
    513   enc_cfg->rc_max_quantizer = 33;
    514   enc_cfg->rc_undershoot_pct = 100;
    515   enc_cfg->rc_overshoot_pct = 15;
    516   enc_cfg->rc_buf_initial_sz = 500;
    517   enc_cfg->rc_buf_optimal_sz = 600;
    518   enc_cfg->rc_buf_sz = 1000;
    519   enc_cfg->g_error_resilient = 1;
    520 
    521   // Initialize codec
    522   res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR);
    523   if (res != VPX_CODEC_OK) {
    524     svc_log(svc_ctx, SVC_LOG_ERROR, "svc_enc_init error\n");
    525     return res;
    526   }
    527 
    528   vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1);
    529   vpx_codec_control(codec_ctx, VP8E_SET_CPUUSED, 1);
    530   vpx_codec_control(codec_ctx, VP8E_SET_STATIC_THRESHOLD, 1);
    531   vpx_codec_control(codec_ctx, VP8E_SET_NOISE_SENSITIVITY, 1);
    532   vpx_codec_control(codec_ctx, VP8E_SET_TOKEN_PARTITIONS, 1);
    533 
    534   max_intra_size_pct =
    535       (int)(((double)enc_cfg->rc_buf_optimal_sz * 0.5) *
    536             ((double)enc_cfg->g_timebase.den / enc_cfg->g_timebase.num) / 10.0);
    537   vpx_codec_control(codec_ctx, VP8E_SET_MAX_INTRA_BITRATE_PCT,
    538                     max_intra_size_pct);
    539   return VPX_CODEC_OK;
    540 }
    541 
    542 // SVC Algorithm flags - these get mapped to VP8_EFLAG_* defined in vp8cx.h
    543 
    544 // encoder should reference the last frame
    545 #define USE_LAST (1 << 0)
    546 
    547 // encoder should reference the alt ref frame
    548 #define USE_ARF (1 << 1)
    549 
    550 // encoder should reference the golden frame
    551 #define USE_GF (1 << 2)
    552 
    553 // encoder should copy current frame to the last frame buffer
    554 #define UPDATE_LAST (1 << 3)
    555 
    556 // encoder should copy current frame to the alt ref frame buffer
    557 #define UPDATE_ARF (1 << 4)
    558 
    559 // encoder should copy current frame to the golden frame
    560 #define UPDATE_GF (1 << 5)
    561 
    562 static int map_vp8_flags(int svc_flags) {
    563   int flags = 0;
    564 
    565   if (!(svc_flags & USE_LAST)) flags |= VP8_EFLAG_NO_REF_LAST;
    566   if (!(svc_flags & USE_ARF)) flags |= VP8_EFLAG_NO_REF_ARF;
    567   if (!(svc_flags & USE_GF)) flags |= VP8_EFLAG_NO_REF_GF;
    568 
    569   if (svc_flags & UPDATE_LAST) {
    570     // last is updated automatically
    571   } else {
    572     flags |= VP8_EFLAG_NO_UPD_LAST;
    573   }
    574   if (svc_flags & UPDATE_ARF) {
    575     flags |= VP8_EFLAG_FORCE_ARF;
    576   } else {
    577     flags |= VP8_EFLAG_NO_UPD_ARF;
    578   }
    579   if (svc_flags & UPDATE_GF) {
    580     flags |= VP8_EFLAG_FORCE_GF;
    581   } else {
    582     flags |= VP8_EFLAG_NO_UPD_GF;
    583   }
    584   return flags;
    585 }
    586 
    587 /**
    588  * Helper to check if the current frame is the first, full resolution dummy.
    589  */
    590 static int vpx_svc_dummy_frame(SvcContext *svc_ctx) {
    591   SvcInternal *const si = get_svc_internal(svc_ctx);
    592   return svc_ctx->first_frame_full_size == 1 && si->encode_frame_count == 0;
    593 }
    594 
    595 static void calculate_enc_frame_flags(SvcContext *svc_ctx) {
    596   vpx_enc_frame_flags_t flags = VPX_EFLAG_FORCE_KF;
    597   SvcInternal *const si = get_svc_internal(svc_ctx);
    598   const int is_keyframe = (si->frame_within_gop == 0);
    599 
    600   // keyframe layer zero is identical for all modes
    601   if ((is_keyframe && si->layer == 0) || vpx_svc_dummy_frame(svc_ctx)) {
    602     si->enc_frame_flags = VPX_EFLAG_FORCE_KF;
    603     return;
    604   }
    605 
    606   switch (svc_ctx->encoding_mode) {
    607     case ALT_INTER_LAYER_PREDICTION_IP:
    608       if (si->layer == 0) {
    609         flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
    610       } else if (is_keyframe) {
    611         if (si->layer == si->layers - 1) {
    612           flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
    613         } else {
    614           flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF);
    615         }
    616       } else {
    617         flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST);
    618       }
    619       break;
    620     case INTER_LAYER_PREDICTION_I:
    621       if (si->layer == 0) {
    622         flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
    623       } else if (is_keyframe) {
    624         flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
    625       } else {
    626         flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
    627       }
    628       break;
    629     case INTER_LAYER_PREDICTION_IP:
    630       if (si->layer == 0) {
    631         flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
    632       } else if (is_keyframe) {
    633         flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
    634       } else {
    635         flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST);
    636       }
    637       break;
    638     case USE_GOLDEN_FRAME:
    639       if (2 * si->layers - SVC_REFERENCE_FRAMES <= si->layer) {
    640         if (si->layer == 0) {
    641           flags = map_vp8_flags(USE_LAST | USE_GF | UPDATE_LAST);
    642         } else if (is_keyframe) {
    643           flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF);
    644         } else {
    645           flags = map_vp8_flags(USE_LAST | USE_ARF | USE_GF | UPDATE_LAST);
    646         }
    647       } else {
    648         if (si->layer == 0) {
    649           flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
    650         } else if (is_keyframe) {
    651           flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
    652         } else {
    653           flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
    654         }
    655       }
    656       break;
    657     default:
    658       svc_log(svc_ctx, SVC_LOG_ERROR, "unexpected encoding mode: %d\n",
    659               svc_ctx->encoding_mode);
    660       break;
    661   }
    662   si->enc_frame_flags = flags;
    663 }
    664 
    665 vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx,
    666                                              int layer,
    667                                              unsigned int *width,
    668                                              unsigned int *height) {
    669   int w, h, index, num, den;
    670   const SvcInternal *const si = get_const_svc_internal(svc_ctx);
    671 
    672   if (svc_ctx == NULL || si == NULL || width == NULL || height == NULL) {
    673     return VPX_CODEC_INVALID_PARAM;
    674   }
    675   if (layer < 0 || layer >= si->layers) return VPX_CODEC_INVALID_PARAM;
    676 
    677   index = layer + VPX_SS_MAX_LAYERS - si->layers;
    678   num = si->scaling_factor_num[index];
    679   den = si->scaling_factor_den[index];
    680   if (num == 0 || den == 0) return VPX_CODEC_INVALID_PARAM;
    681 
    682   w = si->width * num / den;
    683   h = si->height * num / den;
    684 
    685   // make height and width even to make chrome player happy
    686   w += w % 2;
    687   h += h % 2;
    688 
    689   *width = w;
    690   *height = h;
    691 
    692   return VPX_CODEC_OK;
    693 }
    694 
    695 static void set_svc_parameters(SvcContext *svc_ctx,
    696                                vpx_codec_ctx_t *codec_ctx) {
    697   int layer, layer_index;
    698   vpx_svc_parameters_t svc_params;
    699   SvcInternal *const si = get_svc_internal(svc_ctx);
    700 
    701   memset(&svc_params, 0, sizeof(svc_params));
    702   svc_params.layer = si->layer;
    703   svc_params.flags = si->enc_frame_flags;
    704 
    705   layer = si->layer;
    706   if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
    707       si->frame_within_gop == 0) {
    708     // layers 1 & 3 don't exist in this mode, use the higher one
    709     if (layer == 0 || layer == 2) {
    710       layer += 1;
    711     }
    712   }
    713   if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer,
    714                                                    &svc_params.width,
    715                                                    &svc_params.height)) {
    716     svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n");
    717   }
    718   layer_index = layer + VPX_SS_MAX_LAYERS - si->layers;
    719   svc_params.min_quantizer = si->quantizer[layer_index];
    720   svc_params.max_quantizer = si->quantizer[layer_index];
    721   svc_params.distance_from_i_frame = si->frame_within_gop;
    722 
    723   // Use buffer i for layer i LST
    724   svc_params.lst_fb_idx = si->layer;
    725 
    726   // Use buffer i-1 for layer i Alt (Inter-layer prediction)
    727   if (si->layer != 0) {
    728     const int use_higher_layer =
    729         svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
    730         si->frame_within_gop == 0;
    731     svc_params.alt_fb_idx = use_higher_layer ? si->layer - 2 : si->layer - 1;
    732   }
    733 
    734   if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP) {
    735     svc_params.gld_fb_idx = si->layer + 1;
    736   } else {
    737     if (si->layer < 2 * si->layers - SVC_REFERENCE_FRAMES)
    738       svc_params.gld_fb_idx = svc_params.lst_fb_idx;
    739     else
    740       svc_params.gld_fb_idx = 2 * si->layers - 1 - si->layer;
    741   }
    742 
    743   svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, layer: %d, %dx%d, q: %d\n",
    744           si->encode_frame_count, si->layer, svc_params.width,
    745           svc_params.height, svc_params.min_quantizer);
    746 
    747   if (svc_params.flags == VPX_EFLAG_FORCE_KF) {
    748     svc_log(svc_ctx, SVC_LOG_DEBUG, "flags == VPX_EFLAG_FORCE_KF\n");
    749   } else {
    750     svc_log(
    751         svc_ctx, SVC_LOG_DEBUG, "Using:    LST/GLD/ALT [%2d|%2d|%2d]\n",
    752         svc_params.flags & VP8_EFLAG_NO_REF_LAST ? -1 : svc_params.lst_fb_idx,
    753         svc_params.flags & VP8_EFLAG_NO_REF_GF ? -1 : svc_params.gld_fb_idx,
    754         svc_params.flags & VP8_EFLAG_NO_REF_ARF ? -1 : svc_params.alt_fb_idx);
    755     svc_log(
    756         svc_ctx, SVC_LOG_DEBUG, "Updating: LST/GLD/ALT [%2d|%2d|%2d]\n",
    757         svc_params.flags & VP8_EFLAG_NO_UPD_LAST ? -1 : svc_params.lst_fb_idx,
    758         svc_params.flags & VP8_EFLAG_NO_UPD_GF ? -1 : svc_params.gld_fb_idx,
    759         svc_params.flags & VP8_EFLAG_NO_UPD_ARF ? -1 : svc_params.alt_fb_idx);
    760   }
    761 
    762   vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &svc_params);
    763 }
    764 
    765 /**
    766  * Encode a frame into multiple layers
    767  * Create a superframe containing the individual layers
    768  */
    769 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
    770                                struct vpx_image *rawimg, vpx_codec_pts_t pts,
    771                                int64_t duration, int deadline) {
    772   vpx_codec_err_t res;
    773   vpx_codec_iter_t iter;
    774   const vpx_codec_cx_pkt_t *cx_pkt;
    775   struct LayerData *cx_layer_list = NULL;
    776   struct LayerData *layer_data;
    777   struct Superframe superframe;
    778   SvcInternal *const si = get_svc_internal(svc_ctx);
    779   if (svc_ctx == NULL || codec_ctx == NULL || rawimg == NULL || si == NULL) {
    780     return VPX_CODEC_INVALID_PARAM;
    781   }
    782 
    783   memset(&superframe, 0, sizeof(superframe));
    784   svc_log_reset(svc_ctx);
    785 
    786   si->layers = vpx_svc_dummy_frame(svc_ctx) ? 1 : svc_ctx->spatial_layers;
    787   if (si->frame_within_gop >= si->kf_dist ||
    788       si->encode_frame_count == 0 ||
    789       (si->encode_frame_count == 1 && svc_ctx->first_frame_full_size == 1)) {
    790     si->frame_within_gop = 0;
    791   }
    792   si->is_keyframe = (si->frame_within_gop == 0);
    793   si->frame_size = 0;
    794 
    795   svc_log(svc_ctx, SVC_LOG_DEBUG,
    796           "vpx_svc_encode  layers: %d, frame_count: %d, frame_within_gop: %d\n",
    797           si->layers, si->encode_frame_count, si->frame_within_gop);
    798 
    799   // encode each layer
    800   for (si->layer = 0; si->layer < si->layers; ++si->layer) {
    801     if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
    802         si->is_keyframe && (si->layer == 1 || si->layer == 3)) {
    803       svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer);
    804       continue;
    805     }
    806     calculate_enc_frame_flags(svc_ctx);
    807 
    808     if (vpx_svc_dummy_frame(svc_ctx)) {
    809       // do not set svc parameters, use normal encode
    810       svc_log(svc_ctx, SVC_LOG_DEBUG, "encoding full size first frame\n");
    811     } else {
    812       set_svc_parameters(svc_ctx, codec_ctx);
    813     }
    814     res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration,
    815                            si->enc_frame_flags, deadline);
    816     if (res != VPX_CODEC_OK) {
    817       return res;
    818     }
    819     // save compressed data
    820     iter = NULL;
    821     while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
    822       switch (cx_pkt->kind) {
    823         case VPX_CODEC_CX_FRAME_PKT: {
    824           const uint32_t frame_pkt_size = (uint32_t)(cx_pkt->data.frame.sz);
    825           if (!vpx_svc_dummy_frame(svc_ctx)) {
    826             si->bytes_in_layer[si->layer] += frame_pkt_size;
    827             svc_log(svc_ctx, SVC_LOG_DEBUG,
    828                     "SVC frame: %d, layer: %d, size: %u\n",
    829                     si->encode_frame_count, si->layer, frame_pkt_size);
    830           }
    831           layer_data =
    832               ld_create(cx_pkt->data.frame.buf, (size_t)frame_pkt_size);
    833           if (layer_data == NULL) {
    834             svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating LayerData\n");
    835             return 0;
    836           }
    837           ld_list_add(&cx_layer_list, layer_data);
    838 
    839           // save layer size in superframe index
    840           superframe.sizes[superframe.count++] = frame_pkt_size;
    841           superframe.magnitude |= frame_pkt_size;
    842           break;
    843         }
    844         case VPX_CODEC_PSNR_PKT: {
    845           if (!vpx_svc_dummy_frame(svc_ctx)) {
    846             svc_log(svc_ctx, SVC_LOG_DEBUG,
    847                     "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
    848                     "%2.3f  %2.3f  %2.3f  %2.3f \n",
    849                     si->encode_frame_count, si->layer,
    850                     cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1],
    851                     cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]);
    852             si->psnr_in_layer[si->layer] += cx_pkt->data.psnr.psnr[0];
    853           }
    854           break;
    855         }
    856         default: {
    857           break;
    858         }
    859       }
    860     }
    861   }
    862   // add superframe index to layer data list
    863   if (!vpx_svc_dummy_frame(svc_ctx)) {
    864     sf_create_index(&superframe);
    865     layer_data = ld_create(superframe.buffer, superframe.index_size);
    866     ld_list_add(&cx_layer_list, layer_data);
    867   }
    868   // get accumulated size of layer data
    869   si->frame_size = ld_list_get_buffer_size(cx_layer_list);
    870   if (si->frame_size == 0) return VPX_CODEC_ERROR;
    871 
    872   // all layers encoded, create single buffer with concatenated layers
    873   if (si->frame_size > si->buffer_size) {
    874     free(si->buffer);
    875     si->buffer = malloc(si->frame_size);
    876     if (si->buffer == NULL) {
    877       ld_list_free(cx_layer_list);
    878       return VPX_CODEC_MEM_ERROR;
    879     }
    880     si->buffer_size = si->frame_size;
    881   }
    882   // copy layer data into packet
    883   ld_list_copy_to_buffer(cx_layer_list, si->buffer);
    884 
    885   ld_list_free(cx_layer_list);
    886 
    887   svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, pts: %d\n",
    888           si->encode_frame_count, si->is_keyframe, (int)si->frame_size,
    889           (int)pts);
    890   ++si->frame_within_gop;
    891   ++si->encode_frame_count;
    892 
    893   return VPX_CODEC_OK;
    894 }
    895 
    896 const char *vpx_svc_get_message(const SvcContext *svc_ctx) {
    897   const SvcInternal *const si = get_const_svc_internal(svc_ctx);
    898   if (svc_ctx == NULL || si == NULL) return NULL;
    899   return si->message_buffer;
    900 }
    901 
    902 void *vpx_svc_get_buffer(const SvcContext *svc_ctx) {
    903   const SvcInternal *const si = get_const_svc_internal(svc_ctx);
    904   if (svc_ctx == NULL || si == NULL) return NULL;
    905   return si->buffer;
    906 }
    907 
    908 size_t vpx_svc_get_frame_size(const SvcContext *svc_ctx) {
    909   const SvcInternal *const si = get_const_svc_internal(svc_ctx);
    910   if (svc_ctx == NULL || si == NULL) return 0;
    911   return si->frame_size;
    912 }
    913 
    914 int vpx_svc_get_encode_frame_count(const SvcContext *svc_ctx) {
    915   const SvcInternal *const si = get_const_svc_internal(svc_ctx);
    916   if (svc_ctx == NULL || si == NULL) return 0;
    917   return si->encode_frame_count;
    918 }
    919 
    920 int vpx_svc_is_keyframe(const SvcContext *svc_ctx) {
    921   const SvcInternal *const si = get_const_svc_internal(svc_ctx);
    922   if (svc_ctx == NULL || si == NULL) return 0;
    923   return si->is_keyframe;
    924 }
    925 
    926 void vpx_svc_set_keyframe(SvcContext *svc_ctx) {
    927   SvcInternal *const si = get_svc_internal(svc_ctx);
    928   if (svc_ctx == NULL || si == NULL) return;
    929   si->frame_within_gop = 0;
    930 }
    931 
    932 // dump accumulated statistics and reset accumulated values
    933 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
    934   int number_of_frames, number_of_keyframes, encode_frame_count;
    935   int i;
    936   uint32_t bytes_total = 0;
    937   SvcInternal *const si = get_svc_internal(svc_ctx);
    938   if (svc_ctx == NULL || si == NULL) return NULL;
    939 
    940   svc_log_reset(svc_ctx);
    941 
    942   encode_frame_count = si->encode_frame_count;
    943   if (svc_ctx->first_frame_full_size) encode_frame_count--;
    944   if (si->encode_frame_count <= 0) return vpx_svc_get_message(svc_ctx);
    945 
    946   svc_log(svc_ctx, SVC_LOG_INFO, "\n");
    947   number_of_keyframes = encode_frame_count / si->kf_dist + 1;
    948   for (i = 0; i < si->layers; ++i) {
    949     number_of_frames = encode_frame_count;
    950 
    951     if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
    952         (i == 1 || i == 3)) {
    953       number_of_frames -= number_of_keyframes;
    954     }
    955     svc_log(svc_ctx, SVC_LOG_INFO, "Layer %d PSNR=[%2.3f], Bytes=[%u]\n", i,
    956             (double)si->psnr_in_layer[i] / number_of_frames,
    957             si->bytes_in_layer[i]);
    958     bytes_total += si->bytes_in_layer[i];
    959     si->psnr_in_layer[i] = 0;
    960     si->bytes_in_layer[i] = 0;
    961   }
    962 
    963   // only display statistics once
    964   si->encode_frame_count = 0;
    965 
    966   svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total);
    967   return vpx_svc_get_message(svc_ctx);
    968 }
    969 
    970 void vpx_svc_release(SvcContext *svc_ctx) {
    971   SvcInternal *si;
    972   if (svc_ctx == NULL) return;
    973   // do not use get_svc_internal as it will unnecessarily allocate an
    974   // SvcInternal if it was not already allocated
    975   si = (SvcInternal *)svc_ctx->internal;
    976   if (si != NULL) {
    977     free(si->buffer);
    978     free(si);
    979     svc_ctx->internal = NULL;
    980   }
    981 }
    982