| OLD | NEW |
| 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 |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 } | 295 } |
| 296 strncpy(si->options, options, sizeof(si->options)); | 296 strncpy(si->options, options, sizeof(si->options)); |
| 297 si->options[sizeof(si->options) - 1] = '\0'; | 297 si->options[sizeof(si->options) - 1] = '\0'; |
| 298 return VPX_CODEC_OK; | 298 return VPX_CODEC_OK; |
| 299 } | 299 } |
| 300 | 300 |
| 301 void assign_layer_bitrates(const SvcContext *svc_ctx, | 301 void assign_layer_bitrates(const SvcContext *svc_ctx, |
| 302 vpx_codec_enc_cfg_t *const enc_cfg) { | 302 vpx_codec_enc_cfg_t *const enc_cfg) { |
| 303 int i; | 303 int i; |
| 304 const SvcInternal_t *const si = get_const_svc_internal(svc_ctx); | 304 const SvcInternal_t *const si = get_const_svc_internal(svc_ctx); |
| 305 int sl, tl, spatial_layer_target; |
| 305 | 306 |
| 306 if (si->bitrates[0] != 0) { | 307 if (svc_ctx->temporal_layering_mode != 0) { |
| 307 enc_cfg->rc_target_bitrate = 0; | 308 if (si->bitrates[0] != 0) { |
| 308 for (i = 0; i < svc_ctx->spatial_layers; ++i) { | 309 enc_cfg->rc_target_bitrate = 0; |
| 309 enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i]; | 310 for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) { |
| 310 enc_cfg->rc_target_bitrate += si->bitrates[i]; | 311 enc_cfg->ss_target_bitrate[sl*svc_ctx->temporal_layers] = 0; |
| 312 for (tl = 0; tl < svc_ctx->temporal_layers; ++tl) { |
| 313 enc_cfg->ss_target_bitrate[sl*svc_ctx->temporal_layers] |
| 314 += (unsigned int)si->bitrates[sl * svc_ctx->temporal_layers + tl]; |
| 315 enc_cfg->layer_target_bitrate[sl*svc_ctx->temporal_layers + tl] |
| 316 = si->bitrates[sl * svc_ctx->temporal_layers + tl]; |
| 317 } |
| 318 } |
| 319 } else { |
| 320 float total = 0; |
| 321 float alloc_ratio[VPX_MAX_LAYERS] = {0}; |
| 322 |
| 323 for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) { |
| 324 if (si->svc_params.scaling_factor_den[sl] > 0) { |
| 325 alloc_ratio[sl] = (float)(si->svc_params.scaling_factor_num[sl] * |
| 326 1.0 / si->svc_params.scaling_factor_den[sl]); |
| 327 total += alloc_ratio[sl]; |
| 328 } |
| 329 } |
| 330 |
| 331 for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) { |
| 332 enc_cfg->ss_target_bitrate[sl] = spatial_layer_target = |
| 333 (unsigned int)(enc_cfg->rc_target_bitrate * |
| 334 alloc_ratio[sl] / total); |
| 335 if (svc_ctx->temporal_layering_mode == 3) { |
| 336 enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] = |
| 337 spatial_layer_target >> 1; |
| 338 enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] = |
| 339 (spatial_layer_target >> 1) + (spatial_layer_target >> 2); |
| 340 enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 2] = |
| 341 spatial_layer_target; |
| 342 } else if (svc_ctx->temporal_layering_mode == 2) { |
| 343 enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] = |
| 344 spatial_layer_target * 2 / 3; |
| 345 enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] = |
| 346 spatial_layer_target; |
| 347 } else { |
| 348 // User should explicitly assign bitrates in this case. |
| 349 assert(0); |
| 350 } |
| 351 } |
| 311 } | 352 } |
| 312 } else { | 353 } else { |
| 313 float total = 0; | 354 if (si->bitrates[0] != 0) { |
| 314 float alloc_ratio[VPX_SS_MAX_LAYERS] = {0}; | 355 enc_cfg->rc_target_bitrate = 0; |
| 356 for (i = 0; i < svc_ctx->spatial_layers; ++i) { |
| 357 enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i]; |
| 358 enc_cfg->rc_target_bitrate += si->bitrates[i]; |
| 359 } |
| 360 } else { |
| 361 float total = 0; |
| 362 float alloc_ratio[VPX_MAX_LAYERS] = {0}; |
| 315 | 363 |
| 316 for (i = 0; i < svc_ctx->spatial_layers; ++i) { | 364 for (i = 0; i < svc_ctx->spatial_layers; ++i) { |
| 317 if (si->svc_params.scaling_factor_den[i] > 0) { | 365 if (si->svc_params.scaling_factor_den[i] > 0) { |
| 318 alloc_ratio[i] = (float)(si->svc_params.scaling_factor_num[i] * 1.0 / | 366 alloc_ratio[i] = (float)(si->svc_params.scaling_factor_num[i] * 1.0 / |
| 319 si->svc_params.scaling_factor_den[i]); | 367 si->svc_params.scaling_factor_den[i]); |
| 320 | 368 |
| 321 alloc_ratio[i] *= alloc_ratio[i]; | 369 alloc_ratio[i] *= alloc_ratio[i]; |
| 322 total += alloc_ratio[i]; | 370 total += alloc_ratio[i]; |
| 371 } |
| 323 } | 372 } |
| 324 } | 373 for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) { |
| 325 | 374 if (total > 0) { |
| 326 for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) { | 375 enc_cfg->layer_target_bitrate[i] = (unsigned int) |
| 327 if (total > 0) { | 376 (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total); |
| 328 enc_cfg->ss_target_bitrate[i] = (unsigned int) | 377 } |
| 329 (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total); | |
| 330 } | 378 } |
| 331 } | 379 } |
| 332 } | 380 } |
| 333 } | 381 } |
| 334 | 382 |
| 335 vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, | 383 vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, |
| 336 vpx_codec_iface_t *iface, | 384 vpx_codec_iface_t *iface, |
| 337 vpx_codec_enc_cfg_t *enc_cfg) { | 385 vpx_codec_enc_cfg_t *enc_cfg) { |
| 338 vpx_codec_err_t res; | 386 vpx_codec_err_t res; |
| 339 int i; | 387 int i; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 358 | 406 |
| 359 if (svc_ctx->spatial_layers == 0) | 407 if (svc_ctx->spatial_layers == 0) |
| 360 svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS; | 408 svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS; |
| 361 if (svc_ctx->spatial_layers < 1 || | 409 if (svc_ctx->spatial_layers < 1 || |
| 362 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) { | 410 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) { |
| 363 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n", | 411 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n", |
| 364 svc_ctx->spatial_layers); | 412 svc_ctx->spatial_layers); |
| 365 return VPX_CODEC_INVALID_PARAM; | 413 return VPX_CODEC_INVALID_PARAM; |
| 366 } | 414 } |
| 367 | 415 |
| 416 // Note: temporal_layering_mode only applies to one-pass CBR |
| 417 // si->svc_params.temporal_layering_mode = svc_ctx->temporal_layering_mode; |
| 418 if (svc_ctx->temporal_layering_mode == 3) { |
| 419 svc_ctx->temporal_layers = 3; |
| 420 } else if (svc_ctx->temporal_layering_mode == 2) { |
| 421 svc_ctx->temporal_layers = 2; |
| 422 } |
| 423 |
| 368 for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) { | 424 for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) { |
| 369 si->svc_params.max_quantizers[i] = MAX_QUANTIZER; | 425 si->svc_params.max_quantizers[i] = MAX_QUANTIZER; |
| 370 si->svc_params.min_quantizers[i] = 0; | 426 si->svc_params.min_quantizers[i] = 0; |
| 371 si->svc_params.scaling_factor_num[i] = DEFAULT_SCALE_FACTORS_NUM[i]; | 427 si->svc_params.scaling_factor_num[i] = DEFAULT_SCALE_FACTORS_NUM[i]; |
| 372 si->svc_params.scaling_factor_den[i] = DEFAULT_SCALE_FACTORS_DEN[i]; | 428 si->svc_params.scaling_factor_den[i] = DEFAULT_SCALE_FACTORS_DEN[i]; |
| 373 } | 429 } |
| 374 | 430 |
| 375 // Parse aggregate command line options. Options must start with | 431 // Parse aggregate command line options. Options must start with |
| 376 // "layers=xx" then followed by other options | 432 // "layers=xx" then followed by other options |
| 377 res = parse_options(svc_ctx, si->options); | 433 res = parse_options(svc_ctx, si->options); |
| 378 if (res != VPX_CODEC_OK) return res; | 434 if (res != VPX_CODEC_OK) return res; |
| 379 | 435 |
| 380 if (svc_ctx->spatial_layers < 1) | 436 if (svc_ctx->spatial_layers < 1) |
| 381 svc_ctx->spatial_layers = 1; | 437 svc_ctx->spatial_layers = 1; |
| 382 if (svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) | 438 if (svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) |
| 383 svc_ctx->spatial_layers = VPX_SS_MAX_LAYERS; | 439 svc_ctx->spatial_layers = VPX_SS_MAX_LAYERS; |
| 384 | 440 |
| 385 if (svc_ctx->temporal_layers < 1) | 441 if (svc_ctx->temporal_layers < 1) |
| 386 svc_ctx->temporal_layers = 1; | 442 svc_ctx->temporal_layers = 1; |
| 387 if (svc_ctx->temporal_layers > VPX_TS_MAX_LAYERS) | 443 if (svc_ctx->temporal_layers > VPX_TS_MAX_LAYERS) |
| 388 svc_ctx->temporal_layers = VPX_TS_MAX_LAYERS; | 444 svc_ctx->temporal_layers = VPX_TS_MAX_LAYERS; |
| 389 | 445 |
| 446 if (svc_ctx->temporal_layers * svc_ctx->spatial_layers > VPX_MAX_LAYERS) { |
| 447 svc_log(svc_ctx, SVC_LOG_ERROR, |
| 448 "spatial layers * temporal layers exceeds the maximum number of " |
| 449 "allowed layers of %d\n", |
| 450 svc_ctx->spatial_layers * svc_ctx->temporal_layers, |
| 451 (int) VPX_MAX_LAYERS); |
| 452 return VPX_CODEC_INVALID_PARAM; |
| 453 } |
| 390 assign_layer_bitrates(svc_ctx, enc_cfg); | 454 assign_layer_bitrates(svc_ctx, enc_cfg); |
| 391 | 455 |
| 392 #if CONFIG_SPATIAL_SVC | 456 #if CONFIG_SPATIAL_SVC |
| 393 for (i = 0; i < svc_ctx->spatial_layers; ++i) | 457 for (i = 0; i < svc_ctx->spatial_layers; ++i) |
| 394 enc_cfg->ss_enable_auto_alt_ref[i] = si->enable_auto_alt_ref[i]; | 458 enc_cfg->ss_enable_auto_alt_ref[i] = si->enable_auto_alt_ref[i]; |
| 395 #endif | 459 #endif |
| 396 | 460 |
| 397 if (svc_ctx->temporal_layers > 1) { | 461 if (svc_ctx->temporal_layers > 1) { |
| 398 int i; | 462 int i; |
| 399 for (i = 0; i < svc_ctx->temporal_layers; ++i) { | 463 for (i = 0; i < svc_ctx->temporal_layers; ++i) { |
| 400 enc_cfg->ts_target_bitrate[i] = enc_cfg->rc_target_bitrate / | 464 enc_cfg->ts_target_bitrate[i] = enc_cfg->rc_target_bitrate / |
| 401 svc_ctx->temporal_layers; | 465 svc_ctx->temporal_layers; |
| 402 enc_cfg->ts_rate_decimator[i] = 1 << (svc_ctx->temporal_layers - 1 - i); | 466 enc_cfg->ts_rate_decimator[i] = 1 << (svc_ctx->temporal_layers - 1 - i); |
| 403 } | 467 } |
| 404 } | 468 } |
| 405 | 469 |
| 406 // modify encoder configuration | 470 if (svc_ctx->threads) |
| 471 enc_cfg->g_threads = svc_ctx->threads; |
| 472 |
| 473 // Modify encoder configuration |
| 407 enc_cfg->ss_number_layers = svc_ctx->spatial_layers; | 474 enc_cfg->ss_number_layers = svc_ctx->spatial_layers; |
| 408 enc_cfg->ts_number_layers = svc_ctx->temporal_layers; | 475 enc_cfg->ts_number_layers = svc_ctx->temporal_layers; |
| 409 | 476 |
| 477 if (enc_cfg->rc_end_usage == VPX_CBR) { |
| 478 enc_cfg->rc_resize_allowed = 0; |
| 479 enc_cfg->rc_min_quantizer = 2; |
| 480 enc_cfg->rc_max_quantizer = 63; |
| 481 enc_cfg->rc_undershoot_pct = 50; |
| 482 enc_cfg->rc_overshoot_pct = 50; |
| 483 enc_cfg->rc_buf_initial_sz = 20; |
| 484 enc_cfg->rc_buf_optimal_sz = 600; |
| 485 enc_cfg->rc_buf_sz = 1000; |
| 486 } |
| 487 |
| 410 if (enc_cfg->g_error_resilient == 0 && si->use_multiple_frame_contexts == 0) | 488 if (enc_cfg->g_error_resilient == 0 && si->use_multiple_frame_contexts == 0) |
| 411 enc_cfg->g_error_resilient = 1; | 489 enc_cfg->g_error_resilient = 1; |
| 412 | 490 |
| 413 // Initialize codec | 491 // Initialize codec |
| 414 res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR); | 492 res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR); |
| 415 if (res != VPX_CODEC_OK) { | 493 if (res != VPX_CODEC_OK) { |
| 416 svc_log(svc_ctx, SVC_LOG_ERROR, "svc_enc_init error\n"); | 494 svc_log(svc_ctx, SVC_LOG_ERROR, "svc_enc_init error\n"); |
| 417 return res; | 495 return res; |
| 418 } | 496 } |
| 419 | 497 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 444 | 522 |
| 445 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0, | 523 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0, |
| 446 deadline); | 524 deadline); |
| 447 if (res != VPX_CODEC_OK) { | 525 if (res != VPX_CODEC_OK) { |
| 448 return res; | 526 return res; |
| 449 } | 527 } |
| 450 // save compressed data | 528 // save compressed data |
| 451 iter = NULL; | 529 iter = NULL; |
| 452 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) { | 530 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) { |
| 453 switch (cx_pkt->kind) { | 531 switch (cx_pkt->kind) { |
| 532 #if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION) |
| 454 #if CONFIG_SPATIAL_SVC | 533 #if CONFIG_SPATIAL_SVC |
| 455 case VPX_CODEC_SPATIAL_SVC_LAYER_PSNR: { | 534 case VPX_CODEC_SPATIAL_SVC_LAYER_PSNR: { |
| 456 int i; | 535 int i; |
| 457 for (i = 0; i < svc_ctx->spatial_layers; ++i) { | 536 for (i = 0; i < svc_ctx->spatial_layers; ++i) { |
| 458 int j; | 537 int j; |
| 459 svc_log(svc_ctx, SVC_LOG_DEBUG, | 538 svc_log(svc_ctx, SVC_LOG_DEBUG, |
| 460 "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): " | 539 "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): " |
| 461 "%2.3f %2.3f %2.3f %2.3f \n", | 540 "%2.3f %2.3f %2.3f %2.3f \n", |
| 462 si->psnr_pkt_received, i, | 541 si->psnr_pkt_received, i, |
| 463 cx_pkt->data.layer_psnr[i].psnr[0], | 542 cx_pkt->data.layer_psnr[i].psnr[0], |
| (...skipping 18 matching lines...) Expand all Loading... |
| 482 ++si->psnr_pkt_received; | 561 ++si->psnr_pkt_received; |
| 483 break; | 562 break; |
| 484 } | 563 } |
| 485 case VPX_CODEC_SPATIAL_SVC_LAYER_SIZES: { | 564 case VPX_CODEC_SPATIAL_SVC_LAYER_SIZES: { |
| 486 int i; | 565 int i; |
| 487 for (i = 0; i < svc_ctx->spatial_layers; ++i) | 566 for (i = 0; i < svc_ctx->spatial_layers; ++i) |
| 488 si->bytes_sum[i] += cx_pkt->data.layer_sizes[i]; | 567 si->bytes_sum[i] += cx_pkt->data.layer_sizes[i]; |
| 489 break; | 568 break; |
| 490 } | 569 } |
| 491 #endif | 570 #endif |
| 571 #endif |
| 492 default: { | 572 default: { |
| 493 break; | 573 break; |
| 494 } | 574 } |
| 495 } | 575 } |
| 496 } | 576 } |
| 497 | 577 |
| 498 return VPX_CODEC_OK; | 578 return VPX_CODEC_OK; |
| 499 } | 579 } |
| 500 | 580 |
| 501 const char *vpx_svc_get_message(const SvcContext *svc_ctx) { | 581 const char *vpx_svc_get_message(const SvcContext *svc_ctx) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 mse[j] = si->sse_sum[i][j] * 255.0 * 255.0 / scale[j]; | 627 mse[j] = si->sse_sum[i][j] * 255.0 * 255.0 / scale[j]; |
| 548 } | 628 } |
| 549 svc_log(svc_ctx, SVC_LOG_INFO, | 629 svc_log(svc_ctx, SVC_LOG_INFO, |
| 550 "Layer %d Overall PSNR=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, psnr[0], | 630 "Layer %d Overall PSNR=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, psnr[0], |
| 551 psnr[1], psnr[2], psnr[3]); | 631 psnr[1], psnr[2], psnr[3]); |
| 552 svc_log(svc_ctx, SVC_LOG_INFO, | 632 svc_log(svc_ctx, SVC_LOG_INFO, |
| 553 "Layer %d Overall MSE=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, mse[0], | 633 "Layer %d Overall MSE=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, mse[0], |
| 554 mse[1], mse[2], mse[3]); | 634 mse[1], mse[2], mse[3]); |
| 555 | 635 |
| 556 bytes_total += si->bytes_sum[i]; | 636 bytes_total += si->bytes_sum[i]; |
| 557 // clear sums for next time | 637 // Clear sums for next time. |
| 558 si->bytes_sum[i] = 0; | 638 si->bytes_sum[i] = 0; |
| 559 for (j = 0; j < COMPONENTS; ++j) { | 639 for (j = 0; j < COMPONENTS; ++j) { |
| 560 si->psnr_sum[i][j] = 0; | 640 si->psnr_sum[i][j] = 0; |
| 561 si->sse_sum[i][j] = 0; | 641 si->sse_sum[i][j] = 0; |
| 562 } | 642 } |
| 563 } | 643 } |
| 564 | 644 |
| 565 // only display statistics once | 645 // only display statistics once |
| 566 si->psnr_pkt_received = 0; | 646 si->psnr_pkt_received = 0; |
| 567 | 647 |
| 568 svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total); | 648 svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total); |
| 569 return vpx_svc_get_message(svc_ctx); | 649 return vpx_svc_get_message(svc_ctx); |
| 570 } | 650 } |
| 571 | 651 |
| 572 void vpx_svc_release(SvcContext *svc_ctx) { | 652 void vpx_svc_release(SvcContext *svc_ctx) { |
| 573 SvcInternal_t *si; | 653 SvcInternal_t *si; |
| 574 if (svc_ctx == NULL) return; | 654 if (svc_ctx == NULL) return; |
| 575 // do not use get_svc_internal as it will unnecessarily allocate an | 655 // do not use get_svc_internal as it will unnecessarily allocate an |
| 576 // SvcInternal_t if it was not already allocated | 656 // SvcInternal_t if it was not already allocated |
| 577 si = (SvcInternal_t *)svc_ctx->internal; | 657 si = (SvcInternal_t *)svc_ctx->internal; |
| 578 if (si != NULL) { | 658 if (si != NULL) { |
| 579 free(si); | 659 free(si); |
| 580 svc_ctx->internal = NULL; | 660 svc_ctx->internal = NULL; |
| 581 } | 661 } |
| 582 } | 662 } |
| 583 | 663 |
| OLD | NEW |