| 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 26 matching lines...) Expand all Loading... |
| 37 #endif /* __MINGW32__ */ | 37 #endif /* __MINGW32__ */ |
| 38 | 38 |
| 39 #ifdef _MSC_VER | 39 #ifdef _MSC_VER |
| 40 #define strdup _strdup | 40 #define strdup _strdup |
| 41 #define strtok_r strtok_s | 41 #define strtok_r strtok_s |
| 42 #endif | 42 #endif |
| 43 | 43 |
| 44 #define SVC_REFERENCE_FRAMES 8 | 44 #define SVC_REFERENCE_FRAMES 8 |
| 45 #define SUPERFRAME_SLOTS (8) | 45 #define SUPERFRAME_SLOTS (8) |
| 46 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2) | 46 #define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2) |
| 47 #define OPTION_BUFFER_SIZE 1024 | |
| 48 #define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v | |
| 49 | 47 |
| 50 #define MAX_QUANTIZER 63 | 48 #define MAX_QUANTIZER 63 |
| 51 | 49 |
| 52 static const int DEFAULT_SCALE_FACTORS_NUM[VPX_SS_MAX_LAYERS] = { | 50 static const int DEFAULT_SCALE_FACTORS_NUM[VPX_SS_MAX_LAYERS] = { |
| 53 4, 5, 7, 11, 16 | 51 4, 5, 7, 11, 16 |
| 54 }; | 52 }; |
| 55 | 53 |
| 56 static const int DEFAULT_SCALE_FACTORS_DEN[VPX_SS_MAX_LAYERS] = { | 54 static const int DEFAULT_SCALE_FACTORS_DEN[VPX_SS_MAX_LAYERS] = { |
| 57 16, 16, 16, 16, 16 | 55 16, 16, 16, 16, 16 |
| 58 }; | 56 }; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 74 }; | 72 }; |
| 75 | 73 |
| 76 // One encoded frame | 74 // One encoded frame |
| 77 typedef struct FrameData { | 75 typedef struct FrameData { |
| 78 void *buf; // compressed data buffer | 76 void *buf; // compressed data buffer |
| 79 size_t size; // length of compressed data | 77 size_t size; // length of compressed data |
| 80 vpx_codec_frame_flags_t flags; /**< flags for this frame */ | 78 vpx_codec_frame_flags_t flags; /**< flags for this frame */ |
| 81 struct FrameData *next; | 79 struct FrameData *next; |
| 82 } FrameData; | 80 } FrameData; |
| 83 | 81 |
| 84 typedef struct SvcInternal { | 82 static SvcInternal_t *get_svc_internal(SvcContext *svc_ctx) { |
| 85 char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options | |
| 86 | |
| 87 // values extracted from option, quantizers | |
| 88 vpx_svc_extra_cfg_t svc_params; | |
| 89 int enable_auto_alt_ref[VPX_SS_MAX_LAYERS]; | |
| 90 int bitrates[VPX_SS_MAX_LAYERS]; | |
| 91 | |
| 92 // accumulated statistics | |
| 93 double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V | |
| 94 uint64_t sse_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; | |
| 95 uint32_t bytes_sum[VPX_SS_MAX_LAYERS]; | |
| 96 | |
| 97 // codec encoding values | |
| 98 int width; // width of highest layer | |
| 99 int height; // height of highest layer | |
| 100 int kf_dist; // distance between keyframes | |
| 101 | |
| 102 // state variables | |
| 103 int psnr_pkt_received; | |
| 104 int layer; | |
| 105 int use_multiple_frame_contexts; | |
| 106 | |
| 107 char message_buffer[2048]; | |
| 108 vpx_codec_ctx_t *codec_ctx; | |
| 109 } SvcInternal; | |
| 110 | |
| 111 static SvcInternal *get_svc_internal(SvcContext *svc_ctx) { | |
| 112 if (svc_ctx == NULL) return NULL; | 83 if (svc_ctx == NULL) return NULL; |
| 113 if (svc_ctx->internal == NULL) { | 84 if (svc_ctx->internal == NULL) { |
| 114 SvcInternal *const si = (SvcInternal *)malloc(sizeof(*si)); | 85 SvcInternal_t *const si = (SvcInternal_t *)malloc(sizeof(*si)); |
| 115 if (si != NULL) { | 86 if (si != NULL) { |
| 116 memset(si, 0, sizeof(*si)); | 87 memset(si, 0, sizeof(*si)); |
| 117 } | 88 } |
| 118 svc_ctx->internal = si; | 89 svc_ctx->internal = si; |
| 119 } | 90 } |
| 120 return (SvcInternal *)svc_ctx->internal; | 91 return (SvcInternal_t *)svc_ctx->internal; |
| 121 } | 92 } |
| 122 | 93 |
| 123 static const SvcInternal *get_const_svc_internal(const SvcContext *svc_ctx) { | 94 static const SvcInternal_t *get_const_svc_internal( |
| 95 const SvcContext *svc_ctx) { |
| 124 if (svc_ctx == NULL) return NULL; | 96 if (svc_ctx == NULL) return NULL; |
| 125 return (const SvcInternal *)svc_ctx->internal; | 97 return (const SvcInternal_t *)svc_ctx->internal; |
| 126 } | 98 } |
| 127 | 99 |
| 128 static void svc_log_reset(SvcContext *svc_ctx) { | 100 static void svc_log_reset(SvcContext *svc_ctx) { |
| 129 SvcInternal *const si = (SvcInternal *)svc_ctx->internal; | 101 SvcInternal_t *const si = (SvcInternal_t *)svc_ctx->internal; |
| 130 si->message_buffer[0] = '\0'; | 102 si->message_buffer[0] = '\0'; |
| 131 } | 103 } |
| 132 | 104 |
| 133 static int svc_log(SvcContext *svc_ctx, SVC_LOG_LEVEL level, | 105 static int svc_log(SvcContext *svc_ctx, SVC_LOG_LEVEL level, |
| 134 const char *fmt, ...) { | 106 const char *fmt, ...) { |
| 135 char buf[512]; | 107 char buf[512]; |
| 136 int retval = 0; | 108 int retval = 0; |
| 137 va_list ap; | 109 va_list ap; |
| 138 SvcInternal *const si = get_svc_internal(svc_ctx); | 110 SvcInternal_t *const si = get_svc_internal(svc_ctx); |
| 139 | 111 |
| 140 if (level > svc_ctx->log_level) { | 112 if (level > svc_ctx->log_level) { |
| 141 return retval; | 113 return retval; |
| 142 } | 114 } |
| 143 | 115 |
| 144 va_start(ap, fmt); | 116 va_start(ap, fmt); |
| 145 retval = vsnprintf(buf, sizeof(buf), fmt, ap); | 117 retval = vsnprintf(buf, sizeof(buf), fmt, ap); |
| 146 va_end(ap); | 118 va_end(ap); |
| 147 | 119 |
| 148 if (svc_ctx->log_print) { | 120 if (svc_ctx->log_print) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 * Format: encoding-mode=<svc_mode>,layers=<layer_count> | 198 * Format: encoding-mode=<svc_mode>,layers=<layer_count> |
| 227 * scale-factors=<n1>/<d1>,<n2>/<d2>,... | 199 * scale-factors=<n1>/<d1>,<n2>/<d2>,... |
| 228 * quantizers=<q1>,<q2>,... | 200 * quantizers=<q1>,<q2>,... |
| 229 * svc_mode = [i|ip|alt_ip|gf] | 201 * svc_mode = [i|ip|alt_ip|gf] |
| 230 */ | 202 */ |
| 231 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) { | 203 static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) { |
| 232 char *input_string; | 204 char *input_string; |
| 233 char *option_name; | 205 char *option_name; |
| 234 char *option_value; | 206 char *option_value; |
| 235 char *input_ptr; | 207 char *input_ptr; |
| 236 SvcInternal *const si = get_svc_internal(svc_ctx); | 208 SvcInternal_t *const si = get_svc_internal(svc_ctx); |
| 237 vpx_codec_err_t res = VPX_CODEC_OK; | 209 vpx_codec_err_t res = VPX_CODEC_OK; |
| 238 int i, alt_ref_enabled = 0; | 210 int i, alt_ref_enabled = 0; |
| 239 | 211 |
| 240 if (options == NULL) return VPX_CODEC_OK; | 212 if (options == NULL) return VPX_CODEC_OK; |
| 241 input_string = strdup(options); | 213 input_string = strdup(options); |
| 242 | 214 |
| 243 // parse option name | 215 // parse option name |
| 244 option_name = strtok_r(input_string, "=", &input_ptr); | 216 option_name = strtok_r(input_string, "=", &input_ptr); |
| 245 while (option_name != NULL) { | 217 while (option_name != NULL) { |
| 246 // parse option value | 218 // parse option value |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 svc_log(svc_ctx, SVC_LOG_ERROR, | 280 svc_log(svc_ctx, SVC_LOG_ERROR, |
| 309 "svc: auto alt ref: Maxinum %d(REF_FRAMES - layers) layers could" | 281 "svc: auto alt ref: Maxinum %d(REF_FRAMES - layers) layers could" |
| 310 "enabled auto alt reference frame, but % layers are enabled\n", | 282 "enabled auto alt reference frame, but % layers are enabled\n", |
| 311 REF_FRAMES - svc_ctx->spatial_layers, alt_ref_enabled); | 283 REF_FRAMES - svc_ctx->spatial_layers, alt_ref_enabled); |
| 312 res = VPX_CODEC_INVALID_PARAM; | 284 res = VPX_CODEC_INVALID_PARAM; |
| 313 } | 285 } |
| 314 | 286 |
| 315 return res; | 287 return res; |
| 316 } | 288 } |
| 317 | 289 |
| 318 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options) { | 290 vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, |
| 319 SvcInternal *const si = get_svc_internal(svc_ctx); | 291 const char *options) { |
| 292 SvcInternal_t *const si = get_svc_internal(svc_ctx); |
| 320 if (svc_ctx == NULL || options == NULL || si == NULL) { | 293 if (svc_ctx == NULL || options == NULL || si == NULL) { |
| 321 return VPX_CODEC_INVALID_PARAM; | 294 return VPX_CODEC_INVALID_PARAM; |
| 322 } | 295 } |
| 323 strncpy(si->options, options, sizeof(si->options)); | 296 strncpy(si->options, options, sizeof(si->options)); |
| 324 si->options[sizeof(si->options) - 1] = '\0'; | 297 si->options[sizeof(si->options) - 1] = '\0'; |
| 325 return VPX_CODEC_OK; | 298 return VPX_CODEC_OK; |
| 326 } | 299 } |
| 327 | 300 |
| 328 void assign_layer_bitrates(const SvcContext *svc_ctx, | 301 void assign_layer_bitrates(const SvcContext *svc_ctx, |
| 329 vpx_codec_enc_cfg_t *const enc_cfg) { | 302 vpx_codec_enc_cfg_t *const enc_cfg) { |
| 330 int i; | 303 int i; |
| 331 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 304 const SvcInternal_t *const si = get_const_svc_internal(svc_ctx); |
| 332 | 305 |
| 333 if (si->bitrates[0] != 0) { | 306 if (si->bitrates[0] != 0) { |
| 334 enc_cfg->rc_target_bitrate = 0; | 307 enc_cfg->rc_target_bitrate = 0; |
| 335 for (i = 0; i < svc_ctx->spatial_layers; ++i) { | 308 for (i = 0; i < svc_ctx->spatial_layers; ++i) { |
| 336 enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i]; | 309 enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i]; |
| 337 enc_cfg->rc_target_bitrate += si->bitrates[i]; | 310 enc_cfg->rc_target_bitrate += si->bitrates[i]; |
| 338 } | 311 } |
| 339 } else { | 312 } else { |
| 340 float total = 0; | 313 float total = 0; |
| 341 float alloc_ratio[VPX_SS_MAX_LAYERS] = {0}; | 314 float alloc_ratio[VPX_SS_MAX_LAYERS] = {0}; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 357 } | 330 } |
| 358 } | 331 } |
| 359 } | 332 } |
| 360 } | 333 } |
| 361 | 334 |
| 362 vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, | 335 vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, |
| 363 vpx_codec_iface_t *iface, | 336 vpx_codec_iface_t *iface, |
| 364 vpx_codec_enc_cfg_t *enc_cfg) { | 337 vpx_codec_enc_cfg_t *enc_cfg) { |
| 365 vpx_codec_err_t res; | 338 vpx_codec_err_t res; |
| 366 int i; | 339 int i; |
| 367 SvcInternal *const si = get_svc_internal(svc_ctx); | 340 SvcInternal_t *const si = get_svc_internal(svc_ctx); |
| 368 if (svc_ctx == NULL || codec_ctx == NULL || iface == NULL || | 341 if (svc_ctx == NULL || codec_ctx == NULL || iface == NULL || |
| 369 enc_cfg == NULL) { | 342 enc_cfg == NULL) { |
| 370 return VPX_CODEC_INVALID_PARAM; | 343 return VPX_CODEC_INVALID_PARAM; |
| 371 } | 344 } |
| 372 if (si == NULL) return VPX_CODEC_MEM_ERROR; | 345 if (si == NULL) return VPX_CODEC_MEM_ERROR; |
| 373 | 346 |
| 374 si->codec_ctx = codec_ctx; | 347 si->codec_ctx = codec_ctx; |
| 375 | 348 |
| 376 si->width = enc_cfg->g_w; | 349 si->width = enc_cfg->g_w; |
| 377 si->height = enc_cfg->g_h; | 350 si->height = enc_cfg->g_h; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1); | 420 vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1); |
| 448 vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &si->svc_params); | 421 vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &si->svc_params); |
| 449 | 422 |
| 450 return VPX_CODEC_OK; | 423 return VPX_CODEC_OK; |
| 451 } | 424 } |
| 452 | 425 |
| 453 /** | 426 /** |
| 454 * Encode a frame into multiple layers | 427 * Encode a frame into multiple layers |
| 455 * Create a superframe containing the individual layers | 428 * Create a superframe containing the individual layers |
| 456 */ | 429 */ |
| 457 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, | 430 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, |
| 458 struct vpx_image *rawimg, vpx_codec_pts_t pts, | 431 vpx_codec_ctx_t *codec_ctx, |
| 432 struct vpx_image *rawimg, |
| 433 vpx_codec_pts_t pts, |
| 459 int64_t duration, int deadline) { | 434 int64_t duration, int deadline) { |
| 460 vpx_codec_err_t res; | 435 vpx_codec_err_t res; |
| 461 vpx_codec_iter_t iter; | 436 vpx_codec_iter_t iter; |
| 462 const vpx_codec_cx_pkt_t *cx_pkt; | 437 const vpx_codec_cx_pkt_t *cx_pkt; |
| 463 SvcInternal *const si = get_svc_internal(svc_ctx); | 438 SvcInternal_t *const si = get_svc_internal(svc_ctx); |
| 464 if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) { | 439 if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) { |
| 465 return VPX_CODEC_INVALID_PARAM; | 440 return VPX_CODEC_INVALID_PARAM; |
| 466 } | 441 } |
| 467 | 442 |
| 468 svc_log_reset(svc_ctx); | 443 svc_log_reset(svc_ctx); |
| 469 | 444 |
| 470 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0, | 445 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0, |
| 471 deadline); | 446 deadline); |
| 472 if (res != VPX_CODEC_OK) { | 447 if (res != VPX_CODEC_OK) { |
| 473 return res; | 448 return res; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 default: { | 492 default: { |
| 518 break; | 493 break; |
| 519 } | 494 } |
| 520 } | 495 } |
| 521 } | 496 } |
| 522 | 497 |
| 523 return VPX_CODEC_OK; | 498 return VPX_CODEC_OK; |
| 524 } | 499 } |
| 525 | 500 |
| 526 const char *vpx_svc_get_message(const SvcContext *svc_ctx) { | 501 const char *vpx_svc_get_message(const SvcContext *svc_ctx) { |
| 527 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 502 const SvcInternal_t *const si = get_const_svc_internal(svc_ctx); |
| 528 if (svc_ctx == NULL || si == NULL) return NULL; | 503 if (svc_ctx == NULL || si == NULL) return NULL; |
| 529 return si->message_buffer; | 504 return si->message_buffer; |
| 530 } | 505 } |
| 531 | 506 |
| 532 static double calc_psnr(double d) { | 507 static double calc_psnr(double d) { |
| 533 if (d == 0) return 100; | 508 if (d == 0) return 100; |
| 534 return -10.0 * log(d) / log(10.0); | 509 return -10.0 * log(d) / log(10.0); |
| 535 } | 510 } |
| 536 | 511 |
| 537 // dump accumulated statistics and reset accumulated values | 512 // dump accumulated statistics and reset accumulated values |
| 538 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) { | 513 const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) { |
| 539 int number_of_frames; | 514 int number_of_frames; |
| 540 int i, j; | 515 int i, j; |
| 541 uint32_t bytes_total = 0; | 516 uint32_t bytes_total = 0; |
| 542 double scale[COMPONENTS]; | 517 double scale[COMPONENTS]; |
| 543 double psnr[COMPONENTS]; | 518 double psnr[COMPONENTS]; |
| 544 double mse[COMPONENTS]; | 519 double mse[COMPONENTS]; |
| 545 double y_scale; | 520 double y_scale; |
| 546 | 521 |
| 547 SvcInternal *const si = get_svc_internal(svc_ctx); | 522 SvcInternal_t *const si = get_svc_internal(svc_ctx); |
| 548 if (svc_ctx == NULL || si == NULL) return NULL; | 523 if (svc_ctx == NULL || si == NULL) return NULL; |
| 549 | 524 |
| 550 svc_log_reset(svc_ctx); | 525 svc_log_reset(svc_ctx); |
| 551 | 526 |
| 552 number_of_frames = si->psnr_pkt_received; | 527 number_of_frames = si->psnr_pkt_received; |
| 553 if (number_of_frames <= 0) return vpx_svc_get_message(svc_ctx); | 528 if (number_of_frames <= 0) return vpx_svc_get_message(svc_ctx); |
| 554 | 529 |
| 555 svc_log(svc_ctx, SVC_LOG_INFO, "\n"); | 530 svc_log(svc_ctx, SVC_LOG_INFO, "\n"); |
| 556 for (i = 0; i < svc_ctx->spatial_layers; ++i) { | 531 for (i = 0; i < svc_ctx->spatial_layers; ++i) { |
| 557 | 532 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 588 } | 563 } |
| 589 | 564 |
| 590 // only display statistics once | 565 // only display statistics once |
| 591 si->psnr_pkt_received = 0; | 566 si->psnr_pkt_received = 0; |
| 592 | 567 |
| 593 svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total); | 568 svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total); |
| 594 return vpx_svc_get_message(svc_ctx); | 569 return vpx_svc_get_message(svc_ctx); |
| 595 } | 570 } |
| 596 | 571 |
| 597 void vpx_svc_release(SvcContext *svc_ctx) { | 572 void vpx_svc_release(SvcContext *svc_ctx) { |
| 598 SvcInternal *si; | 573 SvcInternal_t *si; |
| 599 if (svc_ctx == NULL) return; | 574 if (svc_ctx == NULL) return; |
| 600 // do not use get_svc_internal as it will unnecessarily allocate an | 575 // do not use get_svc_internal as it will unnecessarily allocate an |
| 601 // SvcInternal if it was not already allocated | 576 // SvcInternal_t if it was not already allocated |
| 602 si = (SvcInternal *)svc_ctx->internal; | 577 si = (SvcInternal_t *)svc_ctx->internal; |
| 603 if (si != NULL) { | 578 if (si != NULL) { |
| 604 free(si); | 579 free(si); |
| 605 svc_ctx->internal = NULL; | 580 svc_ctx->internal = NULL; |
| 606 } | 581 } |
| 607 } | 582 } |
| 608 | 583 |
| OLD | NEW |