Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: source/libvpx/vpx/src/svc_encodeframe.c

Issue 181493009: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « source/libvpx/vpx/internal/vpx_psnr.h ('k') | source/libvpx/vpx/src/vpx_encoder.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved. 2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 /** 11 /**
12 * @file 12 * @file
13 * VP9 SVC encoding support via libvpx 13 * VP9 SVC encoding support via libvpx
14 */ 14 */
15 15
16 #include <math.h>
16 #include <stdarg.h> 17 #include <stdarg.h>
17 #include <stdio.h> 18 #include <stdio.h>
18 #include <stdlib.h> 19 #include <stdlib.h>
19 #include <string.h> 20 #include <string.h>
20 #define VPX_DISABLE_CTRL_TYPECHECKS 1 21 #define VPX_DISABLE_CTRL_TYPECHECKS 1
21 #define VPX_CODEC_DISABLE_COMPAT 1 22 #define VPX_CODEC_DISABLE_COMPAT 1
22 #include "vpx/svc_context.h" 23 #include "vpx/svc_context.h"
23 #include "vpx/vp8cx.h" 24 #include "vpx/vp8cx.h"
24 #include "vpx/vpx_encoder.h" 25 #include "vpx/vpx_encoder.h"
25 26
26 #if defined(__MINGW32__) && !defined(MINGW_HAS_SECURE_API) 27 #ifdef __MINGW32__
27 #define strtok_r strtok_s 28 #define strtok_r strtok_s
29 #ifndef MINGW_HAS_SECURE_API
28 // proto from /usr/x86_64-w64-mingw32/include/sec_api/string_s.h 30 // 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); 31 _CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context);
30 #endif 32 #endif /* MINGW_HAS_SECURE_API */
33 #endif /* __MINGW32__ */
31 34
32 #ifdef _MSC_VER 35 #ifdef _MSC_VER
33 #define strdup _strdup 36 #define strdup _strdup
34 #define strtok_r strtok_s 37 #define strtok_r strtok_s
35 #endif 38 #endif
36 39
37 #define SVC_REFERENCE_FRAMES 8 40 #define SVC_REFERENCE_FRAMES 8
38 #define SUPERFRAME_SLOTS (8) 41 #define SUPERFRAME_SLOTS (8)
39 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2) 42 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2)
40 #define OPTION_BUFFER_SIZE 256 43 #define OPTION_BUFFER_SIZE 256
44 #define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v
41 45
42 static const char *DEFAULT_QUANTIZER_VALUES = "60,53,39,33,27"; 46 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"; 47 static const char *DEFAULT_SCALE_FACTORS = "4/16,5/16,7/16,11/16,16/16";
44 48
45 typedef struct SvcInternal { 49 typedef struct SvcInternal {
46 char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options 50 char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options
47 char quantizers[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_quantizers 51 char quantizers[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_quantizers
52 char quantizers_keyframe[OPTION_BUFFER_SIZE]; // set by
53 // vpx_svc_set_quantizers
48 char scale_factors[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_scale_factors 54 char scale_factors[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_scale_factors
49 55
50 // values extracted from option, quantizers 56 // values extracted from option, quantizers
51 int scaling_factor_num[VPX_SS_MAX_LAYERS]; 57 int scaling_factor_num[VPX_SS_MAX_LAYERS];
52 int scaling_factor_den[VPX_SS_MAX_LAYERS]; 58 int scaling_factor_den[VPX_SS_MAX_LAYERS];
59 int quantizer_keyframe[VPX_SS_MAX_LAYERS];
53 int quantizer[VPX_SS_MAX_LAYERS]; 60 int quantizer[VPX_SS_MAX_LAYERS];
54 61
55 // accumulated statistics 62 // accumulated statistics
56 double psnr_in_layer[VPX_SS_MAX_LAYERS]; 63 double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V
57 uint32_t bytes_in_layer[VPX_SS_MAX_LAYERS]; 64 uint64_t sse_sum[VPX_SS_MAX_LAYERS][COMPONENTS];
65 uint32_t bytes_sum[VPX_SS_MAX_LAYERS];
58 66
59 // codec encoding values 67 // codec encoding values
60 int width; // width of highest layer 68 int width; // width of highest layer
61 int height; // height of highest layer 69 int height; // height of highest layer
62 int kf_dist; // distance between keyframes 70 int kf_dist; // distance between keyframes
63 71
64 // state variables 72 // state variables
65 int encode_frame_count; 73 int encode_frame_count;
66 int frame_within_gop; 74 int frame_within_gop;
67 vpx_enc_frame_flags_t enc_frame_flags; 75 vpx_enc_frame_flags_t enc_frame_flags;
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 } else if (strcmp(value_str, "gf") == 0) { 267 } else if (strcmp(value_str, "gf") == 0) {
260 svc_ctx->encoding_mode = USE_GOLDEN_FRAME; 268 svc_ctx->encoding_mode = USE_GOLDEN_FRAME;
261 } else { 269 } else {
262 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid encoding mode: %s", value_str); 270 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid encoding mode: %s", value_str);
263 return VPX_CODEC_INVALID_PARAM; 271 return VPX_CODEC_INVALID_PARAM;
264 } 272 }
265 return VPX_CODEC_OK; 273 return VPX_CODEC_OK;
266 } 274 }
267 275
268 static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx, 276 static vpx_codec_err_t parse_quantizer_values(SvcContext *svc_ctx,
269 const char *quantizer_values) { 277 const char *quantizer_values,
278 const int is_keyframe) {
270 char *input_string; 279 char *input_string;
271 char *token; 280 char *token;
272 const char *delim = ","; 281 const char *delim = ",";
273 char *save_ptr; 282 char *save_ptr;
274 int found = 0; 283 int found = 0;
275 int i, q; 284 int i, q;
276 vpx_codec_err_t res = VPX_CODEC_OK; 285 vpx_codec_err_t res = VPX_CODEC_OK;
277 SvcInternal *const si = get_svc_internal(svc_ctx); 286 SvcInternal *const si = get_svc_internal(svc_ctx);
278 287
279 if (quantizer_values == NULL || strlen(quantizer_values) == 0) { 288 if (quantizer_values == NULL || strlen(quantizer_values) == 0) {
289 if (is_keyframe) {
290 // If there non settings for key frame, we will apply settings from
291 // non key frame. So just simply return here.
292 return VPX_CODEC_INVALID_PARAM;
293 }
280 input_string = strdup(DEFAULT_QUANTIZER_VALUES); 294 input_string = strdup(DEFAULT_QUANTIZER_VALUES);
281 } else { 295 } else {
282 input_string = strdup(quantizer_values); 296 input_string = strdup(quantizer_values);
283 } 297 }
284 298
285 token = strtok_r(input_string, delim, &save_ptr); 299 token = strtok_r(input_string, delim, &save_ptr);
286 for (i = 0; i < svc_ctx->spatial_layers; ++i) { 300 for (i = 0; i < svc_ctx->spatial_layers; ++i) {
287 if (token != NULL) { 301 if (token != NULL) {
288 q = atoi(token); 302 q = atoi(token);
289 if (q <= 0 || q > 100) { 303 if (q <= 0 || q > 100) {
290 svc_log(svc_ctx, SVC_LOG_ERROR, 304 svc_log(svc_ctx, SVC_LOG_ERROR,
291 "svc-quantizer-values: invalid value %s\n", token); 305 "svc-quantizer-values: invalid value %s\n", token);
292 res = VPX_CODEC_INVALID_PARAM; 306 res = VPX_CODEC_INVALID_PARAM;
293 break; 307 break;
294 } 308 }
295 token = strtok_r(NULL, delim, &save_ptr); 309 token = strtok_r(NULL, delim, &save_ptr);
296 found = i + 1; 310 found = i + 1;
297 } else { 311 } else {
298 q = 0; 312 q = 0;
299 } 313 }
300 si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q; 314 if (is_keyframe) {
315 si->quantizer_keyframe[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers]
316 = q;
317 } else {
318 si->quantizer[i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers] = q;
319 }
301 } 320 }
302 if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) { 321 if (res == VPX_CODEC_OK && found != svc_ctx->spatial_layers) {
303 svc_log(svc_ctx, SVC_LOG_ERROR, 322 svc_log(svc_ctx, SVC_LOG_ERROR,
304 "svc: quantizers: %d values required, but only %d specified\n", 323 "svc: quantizers: %d values required, but only %d specified\n",
305 svc_ctx->spatial_layers, found); 324 svc_ctx->spatial_layers, found);
306 res = VPX_CODEC_INVALID_PARAM; 325 res = VPX_CODEC_INVALID_PARAM;
307 } 326 }
308 free(input_string); 327 free(input_string);
309 return res; 328 return res;
310 } 329 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 * Format: encoding-mode=<svc_mode>,layers=<layer_count> 394 * Format: encoding-mode=<svc_mode>,layers=<layer_count>
376 * scale-factors=<n1>/<d1>,<n2>/<d2>,... 395 * scale-factors=<n1>/<d1>,<n2>/<d2>,...
377 * quantizers=<q1>,<q2>,... 396 * quantizers=<q1>,<q2>,...
378 * svc_mode = [i|ip|alt_ip|gf] 397 * svc_mode = [i|ip|alt_ip|gf]
379 */ 398 */
380 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) { 399 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
381 char *input_string; 400 char *input_string;
382 char *option_name; 401 char *option_name;
383 char *option_value; 402 char *option_value;
384 char *input_ptr; 403 char *input_ptr;
404 int is_keyframe_qaunt_set = 0;
385 vpx_codec_err_t res = VPX_CODEC_OK; 405 vpx_codec_err_t res = VPX_CODEC_OK;
386 406
387 if (options == NULL) return VPX_CODEC_OK; 407 if (options == NULL) return VPX_CODEC_OK;
388 input_string = strdup(options); 408 input_string = strdup(options);
389 409
390 // parse option name 410 // parse option name
391 option_name = strtok_r(input_string, "=", &input_ptr); 411 option_name = strtok_r(input_string, "=", &input_ptr);
392 while (option_name != NULL) { 412 while (option_name != NULL) {
393 // parse option value 413 // parse option value
394 option_value = strtok_r(NULL, " ", &input_ptr); 414 option_value = strtok_r(NULL, " ", &input_ptr);
395 if (option_value == NULL) { 415 if (option_value == NULL) {
396 svc_log(svc_ctx, SVC_LOG_ERROR, "option missing value: %s\n", 416 svc_log(svc_ctx, SVC_LOG_ERROR, "option missing value: %s\n",
397 option_name); 417 option_name);
398 res = VPX_CODEC_INVALID_PARAM; 418 res = VPX_CODEC_INVALID_PARAM;
399 break; 419 break;
400 } 420 }
401 if (strcmp("encoding-mode", option_name) == 0) { 421 if (strcmp("encoding-mode", option_name) == 0) {
402 res = set_option_encoding_mode(svc_ctx, option_value); 422 res = set_option_encoding_mode(svc_ctx, option_value);
403 if (res != VPX_CODEC_OK) break; 423 if (res != VPX_CODEC_OK) break;
404 } else if (strcmp("layers", option_name) == 0) { 424 } else if (strcmp("layers", option_name) == 0) {
405 svc_ctx->spatial_layers = atoi(option_value); 425 svc_ctx->spatial_layers = atoi(option_value);
406 } else if (strcmp("scale-factors", option_name) == 0) { 426 } else if (strcmp("scale-factors", option_name) == 0) {
407 res = parse_scale_factors(svc_ctx, option_value); 427 res = parse_scale_factors(svc_ctx, option_value);
408 if (res != VPX_CODEC_OK) break; 428 if (res != VPX_CODEC_OK) break;
409 } else if (strcmp("quantizers", option_name) == 0) { 429 } else if (strcmp("quantizers", option_name) == 0) {
410 res = parse_quantizer_values(svc_ctx, option_value); 430 res = parse_quantizer_values(svc_ctx, option_value, 0);
411 if (res != VPX_CODEC_OK) break; 431 if (res != VPX_CODEC_OK) break;
432 if (!is_keyframe_qaunt_set) {
433 SvcInternal *const si = get_svc_internal(svc_ctx);
434 memcpy(get_svc_internal(svc_ctx)->quantizer_keyframe, si->quantizer,
435 sizeof(si->quantizer));
436 }
437 } else if (strcmp("quantizers-keyframe", option_name) == 0) {
438 res = parse_quantizer_values(svc_ctx, option_value, 1);
439 if (res != VPX_CODEC_OK) break;
440 is_keyframe_qaunt_set = 1;
412 } else { 441 } else {
413 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name); 442 svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name);
414 res = VPX_CODEC_INVALID_PARAM; 443 res = VPX_CODEC_INVALID_PARAM;
415 break; 444 break;
416 } 445 }
417 option_name = strtok_r(NULL, "=", &input_ptr); 446 option_name = strtok_r(NULL, "=", &input_ptr);
418 } 447 }
419 free(input_string); 448 free(input_string);
420 return res; 449 return res;
421 } 450 }
422 451
423 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) { 452 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) {
424 SvcInternal *const si = get_svc_internal(svc_ctx); 453 SvcInternal *const si = get_svc_internal(svc_ctx);
425 if (svc_ctx == NULL || options == NULL || si == NULL) { 454 if (svc_ctx == NULL || options == NULL || si == NULL) {
426 return VPX_CODEC_INVALID_PARAM; 455 return VPX_CODEC_INVALID_PARAM;
427 } 456 }
428 strncpy(si->options, options, sizeof(si->options)); 457 strncpy(si->options, options, sizeof(si->options));
429 si->options[sizeof(si->options) - 1] = '\0'; 458 si->options[sizeof(si->options) - 1] = '\0';
430 return VPX_CODEC_OK; 459 return VPX_CODEC_OK;
431 } 460 }
432 461
433 vpx_codec_err_t vpx_svc_set_quantizers(SvcContext *svc_ctx, 462 vpx_codec_err_t vpx_svc_set_quantizers(SvcContext *svc_ctx,
434 const char *quantizers) { 463 const char *quantizers,
464 const int is_for_keyframe) {
435 SvcInternal *const si = get_svc_internal(svc_ctx); 465 SvcInternal *const si = get_svc_internal(svc_ctx);
436 if (svc_ctx == NULL || quantizers == NULL || si == NULL) { 466 if (svc_ctx == NULL || quantizers == NULL || si == NULL) {
437 return VPX_CODEC_INVALID_PARAM; 467 return VPX_CODEC_INVALID_PARAM;
438 } 468 }
439 strncpy(si->quantizers, quantizers, sizeof(si->quantizers)); 469 if (is_for_keyframe) {
440 si->quantizers[sizeof(si->quantizers) - 1] = '\0'; 470 strncpy(si->quantizers_keyframe, quantizers, sizeof(si->quantizers));
471 si->quantizers_keyframe[sizeof(si->quantizers_keyframe) - 1] = '\0';
472 } else {
473 strncpy(si->quantizers, quantizers, sizeof(si->quantizers));
474 si->quantizers[sizeof(si->quantizers) - 1] = '\0';
475 }
441 return VPX_CODEC_OK; 476 return VPX_CODEC_OK;
442 } 477 }
443 478
444 vpx_codec_err_t vpx_svc_set_scale_factors(SvcContext *svc_ctx, 479 vpx_codec_err_t vpx_svc_set_scale_factors(SvcContext *svc_ctx,
445 const char *scale_factors) { 480 const char *scale_factors) {
446 SvcInternal *const si = get_svc_internal(svc_ctx); 481 SvcInternal *const si = get_svc_internal(svc_ctx);
447 if (svc_ctx == NULL || scale_factors == NULL || si == NULL) { 482 if (svc_ctx == NULL || scale_factors == NULL || si == NULL) {
448 return VPX_CODEC_INVALID_PARAM; 483 return VPX_CODEC_INVALID_PARAM;
449 } 484 }
450 strncpy(si->scale_factors, scale_factors, sizeof(si->scale_factors)); 485 strncpy(si->scale_factors, scale_factors, sizeof(si->scale_factors));
(...skipping 30 matching lines...) Expand all
481 if (svc_ctx->spatial_layers < 1 || 516 if (svc_ctx->spatial_layers < 1 ||
482 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) { 517 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) {
483 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n", 518 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n",
484 svc_ctx->spatial_layers); 519 svc_ctx->spatial_layers);
485 return VPX_CODEC_INVALID_PARAM; 520 return VPX_CODEC_INVALID_PARAM;
486 } 521 }
487 // use SvcInternal value for number of layers to enable forcing single layer 522 // use SvcInternal value for number of layers to enable forcing single layer
488 // for first frame 523 // for first frame
489 si->layers = svc_ctx->spatial_layers; 524 si->layers = svc_ctx->spatial_layers;
490 525
491 res = parse_quantizer_values(svc_ctx, si->quantizers); 526 res = parse_quantizer_values(svc_ctx, si->quantizers, 0);
492 if (res != VPX_CODEC_OK) return res; 527 if (res != VPX_CODEC_OK) return res;
493 528
529 res = parse_quantizer_values(svc_ctx, si->quantizers_keyframe, 1);
530 if (res != VPX_CODEC_OK)
531 memcpy(si->quantizer_keyframe, si->quantizer, sizeof(si->quantizer));
532
494 res = parse_scale_factors(svc_ctx, si->scale_factors); 533 res = parse_scale_factors(svc_ctx, si->scale_factors);
495 if (res != VPX_CODEC_OK) return res; 534 if (res != VPX_CODEC_OK) return res;
496 535
497 // parse aggregate command line options 536 // parse aggregate command line options
498 res = parse_options(svc_ctx, si->options); 537 res = parse_options(svc_ctx, si->options);
499 if (res != VPX_CODEC_OK) return res; 538 if (res != VPX_CODEC_OK) return res;
500 539
540 // Assign target bitrate for each layer. We calculate the ratio
541 // from the resolution for now.
542 // TODO(Minghai): Optimize the mechanism of allocating bits after
543 // implementing svc two pass rate control.
544 if (si->layers > 1) {
545 int i;
546 float total = 0;
547 float alloc_ratio[VPX_SS_MAX_LAYERS] = {0};
548
549 for (i = 0; i < si->layers; ++i) {
550 int pos = i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers;
551 if (pos < VPX_SS_MAX_LAYERS && si->scaling_factor_den[pos] > 0) {
552 alloc_ratio[i] = (float)(si->scaling_factor_num[pos] * 1.0 /
553 si->scaling_factor_den[pos]);
554
555 alloc_ratio[i] *= alloc_ratio[i];
556 total += alloc_ratio[i];
557 }
558 }
559
560 for (i = 0; i < si->layers; ++i) {
561 if (total > 0) {
562 enc_cfg->ss_target_bitrate[i] = (unsigned int)
563 (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total);
564 }
565 }
566 }
567
501 // modify encoder configuration 568 // modify encoder configuration
502 enc_cfg->ss_number_layers = si->layers; 569 enc_cfg->ss_number_layers = si->layers;
503 enc_cfg->ts_number_layers = 1; // Temporal layers not used in this encoder. 570 enc_cfg->ts_number_layers = 1; // Temporal layers not used in this encoder.
504 enc_cfg->kf_mode = VPX_KF_DISABLED; 571 enc_cfg->kf_mode = VPX_KF_DISABLED;
505 enc_cfg->g_pass = VPX_RC_ONE_PASS; 572 enc_cfg->g_pass = VPX_RC_ONE_PASS;
506 // Lag in frames not currently supported 573 // Lag in frames not currently supported
507 enc_cfg->g_lag_in_frames = 0; 574 enc_cfg->g_lag_in_frames = 0;
508 575
509 // TODO(ivanmaltz): determine if these values need to be set explicitly for 576 // TODO(ivanmaltz): determine if these values need to be set explicitly for
510 // svc, or if the normal default/override mechanism can be used 577 // svc, or if the normal default/override mechanism can be used
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 if (layer == 0 || layer == 2) { 771 if (layer == 0 || layer == 2) {
705 layer += 1; 772 layer += 1;
706 } 773 }
707 } 774 }
708 if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer, 775 if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer,
709 &svc_params.width, 776 &svc_params.width,
710 &svc_params.height)) { 777 &svc_params.height)) {
711 svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n"); 778 svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n");
712 } 779 }
713 layer_index = layer + VPX_SS_MAX_LAYERS - si->layers; 780 layer_index = layer + VPX_SS_MAX_LAYERS - si->layers;
714 svc_params.min_quantizer = si->quantizer[layer_index]; 781
715 svc_params.max_quantizer = si->quantizer[layer_index]; 782 if (vpx_svc_is_keyframe(svc_ctx)) {
783 svc_params.min_quantizer = si->quantizer_keyframe[layer_index];
784 svc_params.max_quantizer = si->quantizer_keyframe[layer_index];
785 } else {
786 svc_params.min_quantizer = si->quantizer[layer_index];
787 svc_params.max_quantizer = si->quantizer[layer_index];
788 }
789
716 svc_params.distance_from_i_frame = si->frame_within_gop; 790 svc_params.distance_from_i_frame = si->frame_within_gop;
717 791
718 // Use buffer i for layer i LST 792 // Use buffer i for layer i LST
719 svc_params.lst_fb_idx = si->layer; 793 svc_params.lst_fb_idx = si->layer;
720 794
721 // Use buffer i-1 for layer i Alt (Inter-layer prediction) 795 // Use buffer i-1 for layer i Alt (Inter-layer prediction)
722 if (si->layer != 0) { 796 if (si->layer != 0) {
723 const int use_higher_layer = 797 const int use_higher_layer =
724 svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP && 798 svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
725 si->frame_within_gop == 0; 799 si->frame_within_gop == 0;
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 si->enc_frame_flags, deadline); 879 si->enc_frame_flags, deadline);
806 if (res != VPX_CODEC_OK) { 880 if (res != VPX_CODEC_OK) {
807 return res; 881 return res;
808 } 882 }
809 // save compressed data 883 // save compressed data
810 iter = NULL; 884 iter = NULL;
811 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) { 885 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
812 switch (cx_pkt->kind) { 886 switch (cx_pkt->kind) {
813 case VPX_CODEC_CX_FRAME_PKT: { 887 case VPX_CODEC_CX_FRAME_PKT: {
814 const uint32_t frame_pkt_size = (uint32_t)(cx_pkt->data.frame.sz); 888 const uint32_t frame_pkt_size = (uint32_t)(cx_pkt->data.frame.sz);
815 si->bytes_in_layer[si->layer] += frame_pkt_size; 889 si->bytes_sum[si->layer] += frame_pkt_size;
816 svc_log(svc_ctx, SVC_LOG_DEBUG, 890 svc_log(svc_ctx, SVC_LOG_DEBUG,
817 "SVC frame: %d, layer: %d, size: %u\n", 891 "SVC frame: %d, layer: %d, size: %u\n",
818 si->encode_frame_count, si->layer, frame_pkt_size); 892 si->encode_frame_count, si->layer, frame_pkt_size);
819 layer_data = 893 layer_data =
820 ld_create(cx_pkt->data.frame.buf, (size_t)frame_pkt_size); 894 ld_create(cx_pkt->data.frame.buf, (size_t)frame_pkt_size);
821 if (layer_data == NULL) { 895 if (layer_data == NULL) {
822 svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating LayerData\n"); 896 svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating LayerData\n");
823 return VPX_CODEC_OK; 897 return VPX_CODEC_OK;
824 } 898 }
825 ld_list_add(&cx_layer_list, layer_data); 899 ld_list_add(&cx_layer_list, layer_data);
826 900
827 // save layer size in superframe index 901 // save layer size in superframe index
828 superframe.sizes[superframe.count++] = frame_pkt_size; 902 superframe.sizes[superframe.count++] = frame_pkt_size;
829 superframe.magnitude |= frame_pkt_size; 903 superframe.magnitude |= frame_pkt_size;
830 break; 904 break;
831 } 905 }
832 case VPX_CODEC_PSNR_PKT: { 906 case VPX_CODEC_PSNR_PKT: {
907 int i;
833 svc_log(svc_ctx, SVC_LOG_DEBUG, 908 svc_log(svc_ctx, SVC_LOG_DEBUG,
834 "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): " 909 "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
835 "%2.3f %2.3f %2.3f %2.3f \n", 910 "%2.3f %2.3f %2.3f %2.3f \n",
836 si->encode_frame_count, si->layer, 911 si->encode_frame_count, si->layer,
837 cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1], 912 cx_pkt->data.psnr.psnr[0], cx_pkt->data.psnr.psnr[1],
838 cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]); 913 cx_pkt->data.psnr.psnr[2], cx_pkt->data.psnr.psnr[3]);
839 si->psnr_in_layer[si->layer] += cx_pkt->data.psnr.psnr[0]; 914 svc_log(svc_ctx, SVC_LOG_DEBUG,
915 "SVC frame: %d, layer: %d, SSE(Total/Y/U/V): "
916 "%2.3f %2.3f %2.3f %2.3f \n",
917 si->encode_frame_count, si->layer,
918 cx_pkt->data.psnr.sse[0], cx_pkt->data.psnr.sse[1],
919 cx_pkt->data.psnr.sse[2], cx_pkt->data.psnr.sse[3]);
920 for (i = 0; i < COMPONENTS; i++) {
921 si->psnr_sum[si->layer][i] += cx_pkt->data.psnr.psnr[i];
922 si->sse_sum[si->layer][i] += cx_pkt->data.psnr.sse[i];
923 }
840 break; 924 break;
841 } 925 }
842 default: { 926 default: {
843 break; 927 break;
844 } 928 }
845 } 929 }
846 } 930 }
847 } 931 }
848 // add superframe index to layer data list 932 // add superframe index to layer data list
849 sf_create_index(&superframe); 933 sf_create_index(&superframe);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
907 if (svc_ctx == NULL || si == NULL) return 0; 991 if (svc_ctx == NULL || si == NULL) return 0;
908 return si->is_keyframe; 992 return si->is_keyframe;
909 } 993 }
910 994
911 void vpx_svc_set_keyframe(SvcContext *svc_ctx) { 995 void vpx_svc_set_keyframe(SvcContext *svc_ctx) {
912 SvcInternal *const si = get_svc_internal(svc_ctx); 996 SvcInternal *const si = get_svc_internal(svc_ctx);
913 if (svc_ctx == NULL || si == NULL) return; 997 if (svc_ctx == NULL || si == NULL) return;
914 si->frame_within_gop = 0; 998 si->frame_within_gop = 0;
915 } 999 }
916 1000
1001 static double calc_psnr(double d) {
1002 if (d == 0) return 100;
1003 return -10.0 * log(d) / log(10.0);
1004 }
1005
917 // dump accumulated statistics and reset accumulated values 1006 // dump accumulated statistics and reset accumulated values
918 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) { 1007 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
919 int number_of_frames, number_of_keyframes, encode_frame_count; 1008 int number_of_frames, number_of_keyframes, encode_frame_count;
920 int i; 1009 int i, j;
921 uint32_t bytes_total = 0; 1010 uint32_t bytes_total = 0;
1011 double scale[COMPONENTS];
1012 double psnr[COMPONENTS];
1013 double mse[COMPONENTS];
1014 double y_scale;
1015
922 SvcInternal *const si = get_svc_internal(svc_ctx); 1016 SvcInternal *const si = get_svc_internal(svc_ctx);
923 if (svc_ctx == NULL || si == NULL) return NULL; 1017 if (svc_ctx == NULL || si == NULL) return NULL;
924 1018
925 svc_log_reset(svc_ctx); 1019 svc_log_reset(svc_ctx);
926 1020
927 encode_frame_count = si->encode_frame_count; 1021 encode_frame_count = si->encode_frame_count;
928 if (si->encode_frame_count <= 0) return vpx_svc_get_message(svc_ctx); 1022 if (si->encode_frame_count <= 0) return vpx_svc_get_message(svc_ctx);
929 1023
930 svc_log(svc_ctx, SVC_LOG_INFO, "\n"); 1024 svc_log(svc_ctx, SVC_LOG_INFO, "\n");
931 number_of_keyframes = encode_frame_count / si->kf_dist + 1; 1025 number_of_keyframes = encode_frame_count / si->kf_dist + 1;
932 for (i = 0; i < si->layers; ++i) { 1026 for (i = 0; i < si->layers; ++i) {
933 number_of_frames = encode_frame_count; 1027 number_of_frames = encode_frame_count;
934 1028
935 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP && 1029 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP &&
936 (i == 1 || i == 3)) { 1030 (i == 1 || i == 3)) {
937 number_of_frames -= number_of_keyframes; 1031 number_of_frames -= number_of_keyframes;
938 } 1032 }
939 svc_log(svc_ctx, SVC_LOG_INFO, "Layer %d PSNR=[%2.3f], Bytes=[%u]\n", i, 1033 svc_log(svc_ctx, SVC_LOG_INFO,
940 (double)si->psnr_in_layer[i] / number_of_frames, 1034 "Layer %d Average PSNR=[%2.3f, %2.3f, %2.3f, %2.3f], Bytes=[%u]\n",
941 si->bytes_in_layer[i]); 1035 i, (double)si->psnr_sum[i][0] / number_of_frames,
942 bytes_total += si->bytes_in_layer[i]; 1036 (double)si->psnr_sum[i][1] / number_of_frames,
943 si->psnr_in_layer[i] = 0; 1037 (double)si->psnr_sum[i][2] / number_of_frames,
944 si->bytes_in_layer[i] = 0; 1038 (double)si->psnr_sum[i][3] / number_of_frames, si->bytes_sum[i]);
1039 // the following psnr calculation is deduced from ffmpeg.c#print_report
1040 y_scale = si->width * si->height * 255.0 * 255.0 * number_of_frames;
1041 scale[1] = y_scale;
1042 scale[2] = scale[3] = y_scale / 4; // U or V
1043 scale[0] = y_scale * 1.5; // total
1044
1045 for (j = 0; j < COMPONENTS; j++) {
1046 psnr[j] = calc_psnr(si->sse_sum[i][j] / scale[j]);
1047 mse[j] = si->sse_sum[i][j] * 255.0 * 255.0 / scale[j];
1048 }
1049 svc_log(svc_ctx, SVC_LOG_INFO,
1050 "Layer %d Overall PSNR=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, psnr[0],
1051 psnr[1], psnr[2], psnr[3]);
1052 svc_log(svc_ctx, SVC_LOG_INFO,
1053 "Layer %d Overall MSE=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, mse[0],
1054 mse[1], mse[2], mse[3]);
1055
1056 bytes_total += si->bytes_sum[i];
1057 // clear sums for next time
1058 si->bytes_sum[i] = 0;
1059 for (j = 0; j < COMPONENTS; ++j) {
1060 si->psnr_sum[i][j] = 0;
1061 si->sse_sum[i][j] = 0;
1062 }
945 } 1063 }
946 1064
947 // only display statistics once 1065 // only display statistics once
948 si->encode_frame_count = 0; 1066 si->encode_frame_count = 0;
949 1067
950 svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total); 1068 svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total);
951 return vpx_svc_get_message(svc_ctx); 1069 return vpx_svc_get_message(svc_ctx);
952 } 1070 }
953 1071
954 void vpx_svc_release(SvcContext *svc_ctx) { 1072 void vpx_svc_release(SvcContext *svc_ctx) {
955 SvcInternal *si; 1073 SvcInternal *si;
956 if (svc_ctx == NULL) return; 1074 if (svc_ctx == NULL) return;
957 // do not use get_svc_internal as it will unnecessarily allocate an 1075 // do not use get_svc_internal as it will unnecessarily allocate an
958 // SvcInternal if it was not already allocated 1076 // SvcInternal if it was not already allocated
959 si = (SvcInternal *)svc_ctx->internal; 1077 si = (SvcInternal *)svc_ctx->internal;
960 if (si != NULL) { 1078 if (si != NULL) {
961 free(si->buffer); 1079 free(si->buffer);
962 free(si); 1080 free(si);
963 svc_ctx->internal = NULL; 1081 svc_ctx->internal = NULL;
964 } 1082 }
965 } 1083 }
OLDNEW
« no previous file with comments | « source/libvpx/vpx/internal/vpx_psnr.h ('k') | source/libvpx/vpx/src/vpx_encoder.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698