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