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 |