2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
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.
13 * VP9 SVC encoding support via libvpx
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"
27 #define strtok_r strtok_s
28 #ifndef MINGW_HAS_SECURE_API
29 // proto from /usr/x86_64-w64-mingw32/include/sec_api/string_s.h
30 _CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context);
31 #endif /* MINGW_HAS_SECURE_API */
32 #endif /* __MINGW32__ */
35 #define strdup _strdup
36 #define strtok_r strtok_s
39 #define SVC_REFERENCE_FRAMES 8
40 #define SUPERFRAME_SLOTS (8)
41 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2)
42 #define OPTION_BUFFER_SIZE 256
44 static const char *DEFAULT_QUANTIZER_VALUES = "60,53,39,33,27";
45 static const char *DEFAULT_SCALE_FACTORS = "4/16,5/16,7/16,11/16,16/16";
47 typedef struct SvcInternal {
48 char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options
49 char quantizers[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_quantizers
50 char quantizers_keyframe[OPTION_BUFFER_SIZE]; // set by
51 // vpx_svc_set_quantizers
52 char scale_factors[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_scale_factors
54 // values extracted from option, quantizers
55 int scaling_factor_num[VPX_SS_MAX_LAYERS];
56 int scaling_factor_den[VPX_SS_MAX_LAYERS];
57 int quantizer_keyframe[VPX_SS_MAX_LAYERS];
58 int quantizer[VPX_SS_MAX_LAYERS];
60 // accumulated statistics
61 double psnr_in_layer[VPX_SS_MAX_LAYERS];
62 uint32_t bytes_in_layer[VPX_SS_MAX_LAYERS];
64 // codec encoding values
65 int width; // width of highest layer
66 int height; // height of highest layer
67 int kf_dist; // distance between keyframes
70 int encode_frame_count;
72 vpx_enc_frame_flags_t enc_frame_flags;
81 char message_buffer[2048];
82 vpx_codec_ctx_t *codec_ctx;
85 // Superframe is used to generate an index of individual frames (i.e., layers)
88 uint32_t sizes[SUPERFRAME_SLOTS];
90 uint8_t buffer[SUPERFRAME_BUFFER_SIZE];
94 // One encoded frame layer
96 void *buf; // compressed data buffer
97 size_t size; // length of compressed data
98 struct LayerData *next;
101 // create LayerData from encoder output
102 static struct LayerData *ld_create(void *buf, size_t size) {
103 struct LayerData *const layer_data =
104 (struct LayerData *)malloc(sizeof(*layer_data));
105 if (layer_data == NULL) {
108 layer_data->buf = malloc(size);
109 if (layer_data->buf == NULL) {
113 memcpy(layer_data->buf, buf, size);
114 layer_data->size = size;
119 static void ld_free(struct LayerData *layer_data) {
121 if (layer_data->buf) {
122 free(layer_data->buf);
123 layer_data->buf = NULL;
129 // add layer data to list
130 static void ld_list_add(struct LayerData **list, struct LayerData *layer_data) {
131 struct LayerData **p = list;
133 while (*p != NULL) p = &(*p)->next;
135 layer_data->next = NULL;
138 // get accumulated size of layer data
139 static size_t ld_list_get_buffer_size(struct LayerData *list) {
143 for (p = list; p != NULL; p = p->next) {
149 // copy layer data to buffer
150 static void ld_list_copy_to_buffer(struct LayerData *list, uint8_t *buffer) {
153 for (p = list; p != NULL; p = p->next) {
155 memcpy(buffer, p->buf, p->size);
160 // free layer data list
161 static void ld_list_free(struct LayerData *list) {
162 struct LayerData *p = list;
171 static void sf_create_index(struct Superframe *sf) {
172 uint8_t marker = 0xc0;
177 if (sf->count == 0 || sf->count >= 8) return;
179 // Add the number of frames to the marker byte
180 marker |= sf->count - 1;
182 // Choose the magnitude
183 for (mag = 0, mask = 0xff; mag < 4; ++mag) {
184 if (sf->magnitude < mask) break;
191 sf->index_size = 2 + (mag + 1) * sf->count;
195 for (i = 0; i < sf->count; ++i) {
196 int this_sz = sf->sizes[i];
199 for (j = 0; j <= mag; ++j) {
200 *bufp++ = this_sz & 0xff;
207 static SvcInternal *get_svc_internal(SvcContext *svc_ctx) {
208 if (svc_ctx == NULL) return NULL;
209 if (svc_ctx->internal == NULL) {
210 SvcInternal *const si = (SvcInternal *)malloc(sizeof(*si));
212 memset(si, 0, sizeof(*si));
214 svc_ctx->internal = si;
216 return (SvcInternal *)svc_ctx->internal;
219 static const SvcInternal *get_const_svc_internal(const SvcContext *svc_ctx) {
220 if (svc_ctx == NULL) return NULL;
221 return (const SvcInternal *)svc_ctx->internal;
224 static void svc_log_reset(SvcContext *svc_ctx) {
225 SvcInternal *const si = (SvcInternal *)svc_ctx->internal;
226 si->message_buffer[0] = '\0';
229 static int svc_log(SvcContext *svc_ctx, int level, const char *fmt, ...) {
233 SvcInternal *const si = get_svc_internal(svc_ctx);
235 if (level > svc_ctx->log_level) {
240 retval = vsnprintf(buf, sizeof(buf), fmt, ap);
243 if (svc_ctx->log_print) {
246 strncat(si->message_buffer, buf,
247 sizeof(si->message_buffer) - strlen(si->message_buffer) - 1);
250 if (level == SVC_LOG_ERROR) {
251 si->codec_ctx->err_detail = si->message_buffer;
256 static vpx_codec_err_t set_option_encoding_mode(SvcContext *svc_ctx,
257 const char *value_str) {
258 if (strcmp(value_str, "i") == 0) {
259 svc_ctx->encoding_mode = INTER_LAYER_PREDICTION_I;
260 } else if (strcmp(value_str, "alt-ip") == 0) {
261 svc_ctx->encoding_mode = ALT_INTER_LAYER_PREDICTION_IP;
262 } else if (strcmp(value_str, "ip") == 0) {
263 svc_ctx->encoding_mode = INTER_LAYER_PREDICTION_IP;
264 } else if (strcmp(value_str, "gf") == 0) {
265 svc_ctx->encoding_mode = USE_GOLDEN_FRAME;
267 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid encoding mode: %s", value_str);
268 return VPX_CODEC_INVALID_PARAM;
273 static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx,
274 const char *quantizer_values,
275 const int is_keyframe) {
278 const char *delim = ",";
282 vpx_codec_err_t res = VPX_CODEC_OK;
283 SvcInternal *const si = get_svc_internal(svc_ctx);
285 if (quantizer_values == NULL || strlen(quantizer_values) == 0) {
287 // If there non settings for key frame, we will apply settings from
288 // non key frame. So just simply return here.
289 return VPX_CODEC_INVALID_PARAM;
291 input_string = strdup(DEFAULT_QUANTIZER_VALUES);
293 input_string = strdup(quantizer_values);
296 token = strtok_r(input_string, delim, &save_ptr);
297 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
300 if (q <= 0 || q > 100) {
301 svc_log(svc_ctx, SVC_LOG_ERROR,
302 "svc-quantizer-values: invalid value %s\n", token);
303 res = VPX_CODEC_INVALID_PARAM;
306 token = strtok_r(NULL, delim, &save_ptr);
312 si->quantizer_keyframe[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers]
315 si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q;
318 if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
319 svc_log(svc_ctx, SVC_LOG_ERROR,
320 "svc: quantizers: %d values required, but only %d specified\n",
321 svc_ctx->spatial_layers, found);
322 res = VPX_CODEC_INVALID_PARAM;
328 static void log_invalid_scale_factor(SvcContext *svc_ctx, const char *value) {
329 svc_log(svc_ctx, SVC_LOG_ERROR, "svc scale-factors: invalid value %s\n",
333 static vpx_codec_err_t parse_scale_factors(SvcContext *svc_ctx,
334 const char *scale_factors) {
337 const char *delim = ",";
342 vpx_codec_err_t res = VPX_CODEC_OK;
343 SvcInternal *const si = get_svc_internal(svc_ctx);
345 if (scale_factors == NULL || strlen(scale_factors) == 0) {
346 input_string = strdup(DEFAULT_SCALE_FACTORS);
348 input_string = strdup(scale_factors);
350 token = strtok_r(input_string, delim, &save_ptr);
351 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
354 num = strtol(token, &token, 10);
356 log_invalid_scale_factor(svc_ctx, token);
357 res = VPX_CODEC_INVALID_PARAM;
360 if (*token++ != '/') {
361 log_invalid_scale_factor(svc_ctx, token);
362 res = VPX_CODEC_INVALID_PARAM;
365 den = strtol(token, &token, 10);
367 log_invalid_scale_factor(svc_ctx, token);
368 res = VPX_CODEC_INVALID_PARAM;
371 token = strtok_r(NULL, delim, &save_ptr);
374 si->scaling_factor_num[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] =
376 si->scaling_factor_den[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] =
379 if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
380 svc_log(svc_ctx, SVC_LOG_ERROR,
381 "svc: scale-factors: %d values required, but only %d specified\n",
382 svc_ctx->spatial_layers, found);
383 res = VPX_CODEC_INVALID_PARAM;
390 * Parse SVC encoding options
391 * Format: encoding-mode=<svc_mode>,layers=<layer_count>
392 * scale-factors=<n1>/<d1>,<n2>/<d2>,...
393 * quantizers=<q1>,<q2>,...
394 * svc_mode = [i|ip|alt_ip|gf]
396 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
401 int is_keyframe_qaunt_set = 0;
402 vpx_codec_err_t res = VPX_CODEC_OK;
404 if (options == NULL) return VPX_CODEC_OK;
405 input_string = strdup(options);
408 option_name = strtok_r(input_string, "=", &input_ptr);
409 while (option_name != NULL) {
410 // parse option value
411 option_value = strtok_r(NULL, " ", &input_ptr);
412 if (option_value == NULL) {
413 svc_log(svc_ctx, SVC_LOG_ERROR, "option missing value: %s\n",
415 res = VPX_CODEC_INVALID_PARAM;
418 if (strcmp("encoding-mode", option_name) == 0) {
419 res = set_option_encoding_mode(svc_ctx, option_value);
420 if (res != VPX_CODEC_OK) break;
421 } else if (strcmp("layers", option_name) == 0) {
422 svc_ctx->spatial_layers = atoi(option_value);
423 } else if (strcmp("scale-factors", option_name) == 0) {
424 res = parse_scale_factors(svc_ctx, option_value);
425 if (res != VPX_CODEC_OK) break;
426 } else if (strcmp("quantizers", option_name) == 0) {
427 res = parse_quantizer_values(svc_ctx, option_value, 0);
428 if (res != VPX_CODEC_OK) break;
429 if (!is_keyframe_qaunt_set) {
430 SvcInternal *const si = get_svc_internal(svc_ctx);
431 memcpy(get_svc_internal(svc_ctx)->quantizer_keyframe, si->quantizer,
432 sizeof(si->quantizer));
434 } else if (strcmp("quantizers-keyframe", option_name) == 0) {
435 res = parse_quantizer_values(svc_ctx, option_value, 1);
436 if (res != VPX_CODEC_OK) break;
437 is_keyframe_qaunt_set = 1;
439 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name);
440 res = VPX_CODEC_INVALID_PARAM;
443 option_name = strtok_r(NULL, "=", &input_ptr);
449 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) {
450 SvcInternal *const si = get_svc_internal(svc_ctx);
451 if (svc_ctx == NULL || options == NULL || si == NULL) {
452 return VPX_CODEC_INVALID_PARAM;
454 strncpy(si->options, options, sizeof(si->options));
455 si->options[sizeof(si->options) - 1] = '\0';
459 vpx_codec_err_t vpx_svc_set_quantizers(SvcContext *svc_ctx,
460 const char *quantizers,
461 const int is_for_keyframe) {
462 SvcInternal *const si = get_svc_internal(svc_ctx);
463 if (svc_ctx == NULL || quantizers == NULL || si == NULL) {
464 return VPX_CODEC_INVALID_PARAM;
466 if (is_for_keyframe) {
467 strncpy(si->quantizers_keyframe, quantizers, sizeof(si->quantizers));
468 si->quantizers_keyframe[sizeof(si->quantizers_keyframe) - 1] = '\0';
470 strncpy(si->quantizers, quantizers, sizeof(si->quantizers));
471 si->quantizers[sizeof(si->quantizers) - 1] = '\0';
476 vpx_codec_err_t vpx_svc_set_scale_factors(SvcContext *svc_ctx,
477 const char *scale_factors) {
478 SvcInternal *const si = get_svc_internal(svc_ctx);
479 if (svc_ctx == NULL || scale_factors == NULL || si == NULL) {
480 return VPX_CODEC_INVALID_PARAM;
482 strncpy(si->scale_factors, scale_factors, sizeof(si->scale_factors));
483 si->scale_factors[sizeof(si->scale_factors) - 1] = '\0';
487 vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
488 vpx_codec_iface_t *iface,
489 vpx_codec_enc_cfg_t *enc_cfg) {
490 int max_intra_size_pct;
492 SvcInternal *const si = get_svc_internal(svc_ctx);
493 if (svc_ctx == NULL || codec_ctx == NULL || iface == NULL ||
495 return VPX_CODEC_INVALID_PARAM;
497 if (si == NULL) return VPX_CODEC_MEM_ERROR;
499 si->codec_ctx = codec_ctx;
501 si->width = enc_cfg->g_w;
502 si->height = enc_cfg->g_h;
504 if (enc_cfg->kf_max_dist < 2) {
505 svc_log(svc_ctx, SVC_LOG_ERROR, "key frame distance too small: %d\n",
506 enc_cfg->kf_max_dist);
507 return VPX_CODEC_INVALID_PARAM;
509 si->kf_dist = enc_cfg->kf_max_dist;
511 if (svc_ctx->spatial_layers == 0)
512 svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS;
513 if (svc_ctx->spatial_layers < 1 ||
514 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) {
515 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n",
516 svc_ctx->spatial_layers);
517 return VPX_CODEC_INVALID_PARAM;
519 // use SvcInternal value for number of layers to enable forcing single layer
521 si->layers = svc_ctx->spatial_layers;
523 res = parse_quantizer_values(svc_ctx, si->quantizers, 0);
524 if (res != VPX_CODEC_OK) return res;
526 res = parse_quantizer_values(svc_ctx, si->quantizers_keyframe, 1);
527 if (res != VPX_CODEC_OK)
528 memcpy(si->quantizer_keyframe, si->quantizer, sizeof(si->quantizer));
530 res = parse_scale_factors(svc_ctx, si->scale_factors);
531 if (res != VPX_CODEC_OK) return res;
533 // parse aggregate command line options
534 res = parse_options(svc_ctx, si->options);
535 if (res != VPX_CODEC_OK) return res;
537 // modify encoder configuration
538 enc_cfg->ss_number_layers = si->layers;
539 enc_cfg->ts_number_layers = 1; // Temporal layers not used in this encoder.
540 enc_cfg->kf_mode = VPX_KF_DISABLED;
541 enc_cfg->g_pass = VPX_RC_ONE_PASS;
542 // Lag in frames not currently supported
543 enc_cfg->g_lag_in_frames = 0;
545 // TODO(ivanmaltz): determine if these values need to be set explicitly for
546 // svc, or if the normal default/override mechanism can be used
547 enc_cfg->rc_dropframe_thresh = 0;
548 enc_cfg->rc_end_usage = VPX_CBR;
549 enc_cfg->rc_resize_allowed = 0;
550 enc_cfg->rc_min_quantizer = 33;
551 enc_cfg->rc_max_quantizer = 33;
552 enc_cfg->rc_undershoot_pct = 100;
553 enc_cfg->rc_overshoot_pct = 15;
554 enc_cfg->rc_buf_initial_sz = 500;
555 enc_cfg->rc_buf_optimal_sz = 600;
556 enc_cfg->rc_buf_sz = 1000;
557 enc_cfg->g_error_resilient = 1;
560 res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR);
561 if (res != VPX_CODEC_OK) {
562 svc_log(svc_ctx, SVC_LOG_ERROR, "svc_enc_init error\n");
566 vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1);
567 vpx_codec_control(codec_ctx, VP8E_SET_CPUUSED, 1);
568 vpx_codec_control(codec_ctx, VP8E_SET_STATIC_THRESHOLD, 1);
569 vpx_codec_control(codec_ctx, VP8E_SET_NOISE_SENSITIVITY, 1);
570 vpx_codec_control(codec_ctx, VP8E_SET_TOKEN_PARTITIONS, 1);
573 (int)(((double)enc_cfg->rc_buf_optimal_sz * 0.5) *
574 ((double)enc_cfg->g_timebase.den / enc_cfg->g_timebase.num) / 10.0);
575 vpx_codec_control(codec_ctx, VP8E_SET_MAX_INTRA_BITRATE_PCT,
580 // SVC Algorithm flags - these get mapped to VP8_EFLAG_* defined in vp8cx.h
582 // encoder should reference the last frame
583 #define USE_LAST (1 << 0)
585 // encoder should reference the alt ref frame
586 #define USE_ARF (1 << 1)
588 // encoder should reference the golden frame
589 #define USE_GF (1 << 2)
591 // encoder should copy current frame to the last frame buffer
592 #define UPDATE_LAST (1 << 3)
594 // encoder should copy current frame to the alt ref frame buffer
595 #define UPDATE_ARF (1 << 4)
597 // encoder should copy current frame to the golden frame
598 #define UPDATE_GF (1 << 5)
600 static int map_vp8_flags(int svc_flags) {
603 if (!(svc_flags & USE_LAST)) flags |= VP8_EFLAG_NO_REF_LAST;
604 if (!(svc_flags & USE_ARF)) flags |= VP8_EFLAG_NO_REF_ARF;
605 if (!(svc_flags & USE_GF)) flags |= VP8_EFLAG_NO_REF_GF;
607 if (svc_flags & UPDATE_LAST) {
608 // last is updated automatically
610 flags |= VP8_EFLAG_NO_UPD_LAST;
612 if (svc_flags & UPDATE_ARF) {
613 flags |= VP8_EFLAG_FORCE_ARF;
615 flags |= VP8_EFLAG_NO_UPD_ARF;
617 if (svc_flags & UPDATE_GF) {
618 flags |= VP8_EFLAG_FORCE_GF;
620 flags |= VP8_EFLAG_NO_UPD_GF;
625 static void calculate_enc_frame_flags(SvcContext *svc_ctx) {
626 vpx_enc_frame_flags_t flags = VPX_EFLAG_FORCE_KF;
627 SvcInternal *const si = get_svc_internal(svc_ctx);
628 const int is_keyframe = (si->frame_within_gop == 0);
630 // keyframe layer zero is identical for all modes
631 if (is_keyframe && si->layer == 0) {
632 si->enc_frame_flags = VPX_EFLAG_FORCE_KF;
636 switch (svc_ctx->encoding_mode) {
637 case ALT_INTER_LAYER_PREDICTION_IP:
638 if (si->layer == 0) {
639 flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
640 } else if (is_keyframe) {
641 if (si->layer == si->layers - 1) {
642 flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
644 flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF);
647 flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST);
650 case INTER_LAYER_PREDICTION_I:
651 if (si->layer == 0) {
652 flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
653 } else if (is_keyframe) {
654 flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
656 flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
659 case INTER_LAYER_PREDICTION_IP:
660 if (si->layer == 0) {
661 flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
662 } else if (is_keyframe) {
663 flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
665 flags = map_vp8_flags(USE_LAST | USE_ARF | UPDATE_LAST);
668 case USE_GOLDEN_FRAME:
669 if (2 * si->layers - SVC_REFERENCE_FRAMES <= si->layer) {
670 if (si->layer == 0) {
671 flags = map_vp8_flags(USE_LAST | USE_GF | UPDATE_LAST);
672 } else if (is_keyframe) {
673 flags = map_vp8_flags(USE_ARF | UPDATE_LAST | UPDATE_GF);
675 flags = map_vp8_flags(USE_LAST | USE_ARF | USE_GF | UPDATE_LAST);
678 if (si->layer == 0) {
679 flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
680 } else if (is_keyframe) {
681 flags = map_vp8_flags(USE_ARF | UPDATE_LAST);
683 flags = map_vp8_flags(USE_LAST | UPDATE_LAST);
688 svc_log(svc_ctx, SVC_LOG_ERROR, "unexpected encoding mode: %d\n",
689 svc_ctx->encoding_mode);
692 si->enc_frame_flags = flags;
695 vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx,
698 unsigned int *height) {
699 int w, h, index, num, den;
700 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
702 if (svc_ctx == NULL || si == NULL || width == NULL || height == NULL) {
703 return VPX_CODEC_INVALID_PARAM;
705 if (layer < 0 || layer >= si->layers) return VPX_CODEC_INVALID_PARAM;
707 index = layer + VPX_SS_MAX_LAYERS - si->layers;
708 num = si->scaling_factor_num[index];
709 den = si->scaling_factor_den[index];
710 if (num == 0 || den == 0) return VPX_CODEC_INVALID_PARAM;
712 w = si->width * num / den;
713 h = si->height * num / den;
715 // make height and width even to make chrome player happy
725 static void set_svc_parameters(SvcContext *svc_ctx,
726 vpx_codec_ctx_t *codec_ctx) {
727 int layer, layer_index;
728 vpx_svc_parameters_t svc_params;
729 SvcInternal *const si = get_svc_internal(svc_ctx);
731 memset(&svc_params, 0, sizeof(svc_params));
732 svc_params.temporal_layer = 0;
733 svc_params.spatial_layer = si->layer;
734 svc_params.flags = si->enc_frame_flags;
737 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
738 si->frame_within_gop == 0) {
739 // layers 1 & 3 don't exist in this mode, use the higher one
740 if (layer == 0 || layer == 2) {
744 if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer,
746 &svc_params.height)) {
747 svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n");
749 layer_index = layer + VPX_SS_MAX_LAYERS - si->layers;
751 if (vpx_svc_is_keyframe(svc_ctx)) {
752 svc_params.min_quantizer = si->quantizer_keyframe[layer_index];
753 svc_params.max_quantizer = si->quantizer_keyframe[layer_index];
755 svc_params.min_quantizer = si->quantizer[layer_index];
756 svc_params.max_quantizer = si->quantizer[layer_index];
759 svc_params.distance_from_i_frame = si->frame_within_gop;
761 // Use buffer i for layer i LST
762 svc_params.lst_fb_idx = si->layer;
764 // Use buffer i-1 for layer i Alt (Inter-layer prediction)
765 if (si->layer != 0) {
766 const int use_higher_layer =
767 svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
768 si->frame_within_gop == 0;
769 svc_params.alt_fb_idx = use_higher_layer ? si->layer - 2 : si->layer - 1;
772 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP) {
773 svc_params.gld_fb_idx = si->layer + 1;
775 if (si->layer < 2 * si->layers - SVC_REFERENCE_FRAMES)
776 svc_params.gld_fb_idx = svc_params.lst_fb_idx;
778 svc_params.gld_fb_idx = 2 * si->layers - 1 - si->layer;
781 svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, layer: %d, %dx%d, q: %d\n",
782 si->encode_frame_count, si->layer, svc_params.width,
783 svc_params.height, svc_params.min_quantizer);
785 if (svc_params.flags == VPX_EFLAG_FORCE_KF) {
786 svc_log(svc_ctx, SVC_LOG_DEBUG, "flags == VPX_EFLAG_FORCE_KF\n");
789 svc_ctx, SVC_LOG_DEBUG, "Using: LST/GLD/ALT [%2d|%2d|%2d]\n",
790 svc_params.flags & VP8_EFLAG_NO_REF_LAST ? -1 : svc_params.lst_fb_idx,
791 svc_params.flags & VP8_EFLAG_NO_REF_GF ? -1 : svc_params.gld_fb_idx,
792 svc_params.flags & VP8_EFLAG_NO_REF_ARF ? -1 : svc_params.alt_fb_idx);
794 svc_ctx, SVC_LOG_DEBUG, "Updating: LST/GLD/ALT [%2d|%2d|%2d]\n",
795 svc_params.flags & VP8_EFLAG_NO_UPD_LAST ? -1 : svc_params.lst_fb_idx,
796 svc_params.flags & VP8_EFLAG_NO_UPD_GF ? -1 : svc_params.gld_fb_idx,
797 svc_params.flags & VP8_EFLAG_NO_UPD_ARF ? -1 : svc_params.alt_fb_idx);
800 vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &svc_params);
804 * Encode a frame into multiple layers
805 * Create a superframe containing the individual layers
807 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
808 struct vpx_image *rawimg, vpx_codec_pts_t pts,
809 int64_t duration, int deadline) {
811 vpx_codec_iter_t iter;
812 const vpx_codec_cx_pkt_t *cx_pkt;
813 struct LayerData *cx_layer_list = NULL;
814 struct LayerData *layer_data;
815 struct Superframe superframe;
816 SvcInternal *const si = get_svc_internal(svc_ctx);
817 if (svc_ctx == NULL || codec_ctx == NULL || rawimg == NULL || si == NULL) {
818 return VPX_CODEC_INVALID_PARAM;
821 memset(&superframe, 0, sizeof(superframe));
822 svc_log_reset(svc_ctx);
824 si->layers = svc_ctx->spatial_layers;
825 if (si->frame_within_gop >= si->kf_dist ||
826 si->encode_frame_count == 0) {
827 si->frame_within_gop = 0;
829 si->is_keyframe = (si->frame_within_gop == 0);
832 svc_log(svc_ctx, SVC_LOG_DEBUG,
833 "vpx_svc_encode layers: %d, frame_count: %d, frame_within_gop: %d\n",
834 si->layers, si->encode_frame_count, si->frame_within_gop);
837 for (si->layer = 0; si->layer < si->layers; ++si->layer) {
838 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
839 si->is_keyframe && (si->layer == 1 || si->layer == 3)) {
840 svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer);
843 calculate_enc_frame_flags(svc_ctx);
845 set_svc_parameters(svc_ctx, codec_ctx);
847 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration,
848 si->enc_frame_flags, deadline);
849 if (res != VPX_CODEC_OK) {
852 // save compressed data
854 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
855 switch (cx_pkt->kind) {
856 case VPX_CODEC_CX_FRAME_PKT: {
857 const uint32_t frame_pkt_size = (uint32_t)(cx_pkt->data.frame.sz);
858 si->bytes_in_layer[si->layer] += frame_pkt_size;
859 svc_log(svc_ctx, SVC_LOG_DEBUG,
860 "SVC frame: %d, layer: %d, size: %u\n",
861 si->encode_frame_count, si->layer, frame_pkt_size);
863 ld_create(cx_pkt->data.frame.buf, (size_t)frame_pkt_size);
864 if (layer_data == NULL) {
865 svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating LayerData\n");
868 ld_list_add(&cx_layer_list, layer_data);
870 // save layer size in superframe index
871 superframe.sizes[superframe.count++] = frame_pkt_size;
872 superframe.magnitude |= frame_pkt_size;
875 case VPX_CODEC_PSNR_PKT: {
876 svc_log(svc_ctx, SVC_LOG_DEBUG,
877 "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
878 "%2.3f %2.3f %2.3f %2.3f \n",
879 si->encode_frame_count, si->layer,
880 cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1],
881 cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]);
882 si->psnr_in_layer[si->layer] += cx_pkt->data.psnr.psnr[0];
891 // add superframe index to layer data list
892 sf_create_index(&superframe);
893 layer_data = ld_create(superframe.buffer, superframe.index_size);
894 ld_list_add(&cx_layer_list, layer_data);
896 // get accumulated size of layer data
897 si->frame_size = ld_list_get_buffer_size(cx_layer_list);
898 if (si->frame_size == 0) return VPX_CODEC_ERROR;
900 // all layers encoded, create single buffer with concatenated layers
901 if (si->frame_size > si->buffer_size) {
903 si->buffer = malloc(si->frame_size);
904 if (si->buffer == NULL) {
905 ld_list_free(cx_layer_list);
906 return VPX_CODEC_MEM_ERROR;
908 si->buffer_size = si->frame_size;
910 // copy layer data into packet
911 ld_list_copy_to_buffer(cx_layer_list, (uint8_t *)si->buffer);
913 ld_list_free(cx_layer_list);
915 svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, pts: %d\n",
916 si->encode_frame_count, si->is_keyframe, (int)si->frame_size,
918 ++si->frame_within_gop;
919 ++si->encode_frame_count;
924 const char *vpx_svc_get_message(const SvcContext *svc_ctx) {
925 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
926 if (svc_ctx == NULL || si == NULL) return NULL;
927 return si->message_buffer;
930 void *vpx_svc_get_buffer(const SvcContext *svc_ctx) {
931 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
932 if (svc_ctx == NULL || si == NULL) return NULL;
936 size_t vpx_svc_get_frame_size(const SvcContext *svc_ctx) {
937 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
938 if (svc_ctx == NULL || si == NULL) return 0;
939 return si->frame_size;
942 int vpx_svc_get_encode_frame_count(const SvcContext *svc_ctx) {
943 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
944 if (svc_ctx == NULL || si == NULL) return 0;
945 return si->encode_frame_count;
948 int vpx_svc_is_keyframe(const SvcContext *svc_ctx) {
949 const SvcInternal *const si = get_const_svc_internal(svc_ctx);
950 if (svc_ctx == NULL || si == NULL) return 0;
951 return si->is_keyframe;
954 void vpx_svc_set_keyframe(SvcContext *svc_ctx) {
955 SvcInternal *const si = get_svc_internal(svc_ctx);
956 if (svc_ctx == NULL || si == NULL) return;
957 si->frame_within_gop = 0;
960 // dump accumulated statistics and reset accumulated values
961 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
962 int number_of_frames, number_of_keyframes, encode_frame_count;
964 uint32_t bytes_total = 0;
965 SvcInternal *const si = get_svc_internal(svc_ctx);
966 if (svc_ctx == NULL || si == NULL) return NULL;
968 svc_log_reset(svc_ctx);
970 encode_frame_count = si->encode_frame_count;
971 if (si->encode_frame_count <= 0) return vpx_svc_get_message(svc_ctx);
973 svc_log(svc_ctx, SVC_LOG_INFO, "\n");
974 number_of_keyframes = encode_frame_count / si->kf_dist + 1;
975 for (i = 0; i < si->layers; ++i) {
976 number_of_frames = encode_frame_count;
978 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
979 (i == 1 || i == 3)) {
980 number_of_frames -= number_of_keyframes;
982 svc_log(svc_ctx, SVC_LOG_INFO, "Layer %d PSNR=[%2.3f], Bytes=[%u]\n", i,
983 (double)si->psnr_in_layer[i] / number_of_frames,
984 si->bytes_in_layer[i]);
985 bytes_total += si->bytes_in_layer[i];
986 si->psnr_in_layer[i] = 0;
987 si->bytes_in_layer[i] = 0;
990 // only display statistics once
991 si->encode_frame_count = 0;
993 svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total);
994 return vpx_svc_get_message(svc_ctx);
997 void vpx_svc_release(SvcContext *svc_ctx) {
999 if (svc_ctx == NULL) return;
1000 // do not use get_svc_internal as it will unnecessarily allocate an
1001 // SvcInternal if it was not already allocated
1002 si = (SvcInternal *)svc_ctx->internal;
1006 svc_ctx->internal = NULL;