| 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 |
| 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 <assert.h> |
| 16 #include <math.h> | 17 #include <math.h> |
| 17 #include <stdarg.h> | 18 #include <stdarg.h> |
| 18 #include <stdio.h> | 19 #include <stdio.h> |
| 19 #include <stdlib.h> | 20 #include <stdlib.h> |
| 20 #include <string.h> | 21 #include <string.h> |
| 21 #define VPX_DISABLE_CTRL_TYPECHECKS 1 | 22 #define VPX_DISABLE_CTRL_TYPECHECKS 1 |
| 22 #define VPX_CODEC_DISABLE_COMPAT 1 | 23 #define VPX_CODEC_DISABLE_COMPAT 1 |
| 23 #include "vpx/svc_context.h" | 24 #include "vpx/svc_context.h" |
| 24 #include "vpx/vp8cx.h" | 25 #include "vpx/vp8cx.h" |
| 25 #include "vpx/vpx_encoder.h" | 26 #include "vpx/vpx_encoder.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 int frame_within_gop; | 75 int frame_within_gop; |
| 75 vpx_enc_frame_flags_t enc_frame_flags; | 76 vpx_enc_frame_flags_t enc_frame_flags; |
| 76 int layers; | 77 int layers; |
| 77 int layer; | 78 int layer; |
| 78 int is_keyframe; | 79 int is_keyframe; |
| 79 | 80 |
| 80 size_t frame_size; | 81 size_t frame_size; |
| 81 size_t buffer_size; | 82 size_t buffer_size; |
| 82 void *buffer; | 83 void *buffer; |
| 83 | 84 |
| 85 char *rc_stats_buf; |
| 86 size_t rc_stats_buf_size; |
| 87 size_t rc_stats_buf_used; |
| 88 |
| 84 char message_buffer[2048]; | 89 char message_buffer[2048]; |
| 85 vpx_codec_ctx_t *codec_ctx; | 90 vpx_codec_ctx_t *codec_ctx; |
| 86 } SvcInternal; | 91 } SvcInternal; |
| 87 | 92 |
| 88 // Superframe is used to generate an index of individual frames (i.e., layers) | 93 // Superframe is used to generate an index of individual frames (i.e., layers) |
| 89 struct Superframe { | 94 struct Superframe { |
| 90 int count; | 95 int count; |
| 91 uint32_t sizes[SUPERFRAME_SLOTS]; | 96 uint32_t sizes[SUPERFRAME_SLOTS]; |
| 92 uint32_t magnitude; | 97 uint32_t magnitude; |
| 93 uint8_t buffer[SUPERFRAME_BUFFER_SIZE]; | 98 uint8_t buffer[SUPERFRAME_BUFFER_SIZE]; |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 si->kf_dist = enc_cfg->kf_max_dist; | 517 si->kf_dist = enc_cfg->kf_max_dist; |
| 513 | 518 |
| 514 if (svc_ctx->spatial_layers == 0) | 519 if (svc_ctx->spatial_layers == 0) |
| 515 svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS; | 520 svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS; |
| 516 if (svc_ctx->spatial_layers < 1 || | 521 if (svc_ctx->spatial_layers < 1 || |
| 517 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) { | 522 svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) { |
| 518 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n", | 523 svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n", |
| 519 svc_ctx->spatial_layers); | 524 svc_ctx->spatial_layers); |
| 520 return VPX_CODEC_INVALID_PARAM; | 525 return VPX_CODEC_INVALID_PARAM; |
| 521 } | 526 } |
| 522 // use SvcInternal value for number of layers to enable forcing single layer | |
| 523 // for first frame | |
| 524 si->layers = svc_ctx->spatial_layers; | |
| 525 | 527 |
| 526 res = parse_quantizer_values(svc_ctx, si->quantizers, 0); | 528 res = parse_quantizer_values(svc_ctx, si->quantizers, 0); |
| 527 if (res != VPX_CODEC_OK) return res; | 529 if (res != VPX_CODEC_OK) return res; |
| 528 | 530 |
| 529 res = parse_quantizer_values(svc_ctx, si->quantizers_keyframe, 1); | 531 res = parse_quantizer_values(svc_ctx, si->quantizers_keyframe, 1); |
| 530 if (res != VPX_CODEC_OK) | 532 if (res != VPX_CODEC_OK) |
| 531 memcpy(si->quantizer_keyframe, si->quantizer, sizeof(si->quantizer)); | 533 memcpy(si->quantizer_keyframe, si->quantizer, sizeof(si->quantizer)); |
| 532 | 534 |
| 533 res = parse_scale_factors(svc_ctx, si->scale_factors); | 535 res = parse_scale_factors(svc_ctx, si->scale_factors); |
| 534 if (res != VPX_CODEC_OK) return res; | 536 if (res != VPX_CODEC_OK) return res; |
| 535 | 537 |
| 536 // parse aggregate command line options | 538 // Parse aggregate command line options. Options must start with |
| 539 // "layers=xx" then followed by other options |
| 537 res = parse_options(svc_ctx, si->options); | 540 res = parse_options(svc_ctx, si->options); |
| 538 if (res != VPX_CODEC_OK) return res; | 541 if (res != VPX_CODEC_OK) return res; |
| 539 | 542 |
| 543 si->layers = svc_ctx->spatial_layers; |
| 544 |
| 540 // Assign target bitrate for each layer. We calculate the ratio | 545 // Assign target bitrate for each layer. We calculate the ratio |
| 541 // from the resolution for now. | 546 // from the resolution for now. |
| 542 // TODO(Minghai): Optimize the mechanism of allocating bits after | 547 // TODO(Minghai): Optimize the mechanism of allocating bits after |
| 543 // implementing svc two pass rate control. | 548 // implementing svc two pass rate control. |
| 544 if (si->layers > 1) { | 549 if (si->layers > 1) { |
| 545 int i; | 550 int i; |
| 546 float total = 0; | 551 float total = 0; |
| 547 float alloc_ratio[VPX_SS_MAX_LAYERS] = {0}; | 552 float alloc_ratio[VPX_SS_MAX_LAYERS] = {0}; |
| 548 | 553 |
| 554 assert(si->layers <= VPX_SS_MAX_LAYERS); |
| 549 for (i = 0; i < si->layers; ++i) { | 555 for (i = 0; i < si->layers; ++i) { |
| 550 int pos = i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers; | 556 int pos = i + VPX_SS_MAX_LAYERS - svc_ctx->spatial_layers; |
| 551 if (pos < VPX_SS_MAX_LAYERS && si->scaling_factor_den[pos] > 0) { | 557 if (pos < VPX_SS_MAX_LAYERS && si->scaling_factor_den[pos] > 0) { |
| 552 alloc_ratio[i] = (float)(si->scaling_factor_num[pos] * 1.0 / | 558 alloc_ratio[i] = (float)(si->scaling_factor_num[pos] * 1.0 / |
| 553 si->scaling_factor_den[pos]); | 559 si->scaling_factor_den[pos]); |
| 554 | 560 |
| 555 alloc_ratio[i] *= alloc_ratio[i]; | 561 alloc_ratio[i] *= alloc_ratio[i]; |
| 556 total += alloc_ratio[i]; | 562 total += alloc_ratio[i]; |
| 557 } | 563 } |
| 558 } | 564 } |
| 559 | 565 |
| 560 for (i = 0; i < si->layers; ++i) { | 566 for (i = 0; i < si->layers; ++i) { |
| 561 if (total > 0) { | 567 if (total > 0) { |
| 562 enc_cfg->ss_target_bitrate[i] = (unsigned int) | 568 enc_cfg->ss_target_bitrate[i] = (unsigned int) |
| 563 (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total); | 569 (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total); |
| 564 } | 570 } |
| 565 } | 571 } |
| 566 } | 572 } |
| 567 | 573 |
| 568 // modify encoder configuration | 574 // modify encoder configuration |
| 569 enc_cfg->ss_number_layers = si->layers; | 575 enc_cfg->ss_number_layers = si->layers; |
| 570 enc_cfg->ts_number_layers = 1; // Temporal layers not used in this encoder. | 576 enc_cfg->ts_number_layers = 1; // Temporal layers not used in this encoder. |
| 571 enc_cfg->kf_mode = VPX_KF_DISABLED; | 577 enc_cfg->kf_mode = VPX_KF_DISABLED; |
| 572 enc_cfg->g_pass = VPX_RC_ONE_PASS; | |
| 573 // Lag in frames not currently supported | 578 // Lag in frames not currently supported |
| 574 enc_cfg->g_lag_in_frames = 0; | 579 enc_cfg->g_lag_in_frames = 0; |
| 575 | 580 |
| 576 // TODO(ivanmaltz): determine if these values need to be set explicitly for | 581 // TODO(ivanmaltz): determine if these values need to be set explicitly for |
| 577 // svc, or if the normal default/override mechanism can be used | 582 // svc, or if the normal default/override mechanism can be used |
| 578 enc_cfg->rc_dropframe_thresh = 0; | 583 enc_cfg->rc_dropframe_thresh = 0; |
| 579 enc_cfg->rc_end_usage = VPX_CBR; | 584 enc_cfg->rc_end_usage = VPX_CBR; |
| 580 enc_cfg->rc_resize_allowed = 0; | 585 enc_cfg->rc_resize_allowed = 0; |
| 581 enc_cfg->rc_min_quantizer = 33; | 586 |
| 582 enc_cfg->rc_max_quantizer = 33; | 587 if (enc_cfg->g_pass == VPX_RC_ONE_PASS) { |
| 588 enc_cfg->rc_min_quantizer = 33; |
| 589 enc_cfg->rc_max_quantizer = 33; |
| 590 } |
| 591 |
| 583 enc_cfg->rc_undershoot_pct = 100; | 592 enc_cfg->rc_undershoot_pct = 100; |
| 584 enc_cfg->rc_overshoot_pct = 15; | 593 enc_cfg->rc_overshoot_pct = 15; |
| 585 enc_cfg->rc_buf_initial_sz = 500; | 594 enc_cfg->rc_buf_initial_sz = 500; |
| 586 enc_cfg->rc_buf_optimal_sz = 600; | 595 enc_cfg->rc_buf_optimal_sz = 600; |
| 587 enc_cfg->rc_buf_sz = 1000; | 596 enc_cfg->rc_buf_sz = 1000; |
| 588 enc_cfg->g_error_resilient = 1; | 597 enc_cfg->g_error_resilient = 1; |
| 589 | 598 |
| 590 // Initialize codec | 599 // Initialize codec |
| 591 res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR); | 600 res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR); |
| 592 if (res != VPX_CODEC_OK) { | 601 if (res != VPX_CODEC_OK) { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 layer += 1; | 781 layer += 1; |
| 773 } | 782 } |
| 774 } | 783 } |
| 775 if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer, | 784 if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(svc_ctx, layer, |
| 776 &svc_params.width, | 785 &svc_params.width, |
| 777 &svc_params.height)) { | 786 &svc_params.height)) { |
| 778 svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n"); | 787 svc_log(svc_ctx, SVC_LOG_ERROR, "vpx_svc_get_layer_resolution failed\n"); |
| 779 } | 788 } |
| 780 layer_index = layer + VPX_SS_MAX_LAYERS - si->layers; | 789 layer_index = layer + VPX_SS_MAX_LAYERS - si->layers; |
| 781 | 790 |
| 782 if (vpx_svc_is_keyframe(svc_ctx)) { | 791 if (codec_ctx->config.enc->g_pass == VPX_RC_ONE_PASS) { |
| 783 svc_params.min_quantizer = si->quantizer_keyframe[layer_index]; | 792 if (vpx_svc_is_keyframe(svc_ctx)) { |
| 784 svc_params.max_quantizer = si->quantizer_keyframe[layer_index]; | 793 svc_params.min_quantizer = si->quantizer_keyframe[layer_index]; |
| 794 svc_params.max_quantizer = si->quantizer_keyframe[layer_index]; |
| 795 } else { |
| 796 svc_params.min_quantizer = si->quantizer[layer_index]; |
| 797 svc_params.max_quantizer = si->quantizer[layer_index]; |
| 798 } |
| 785 } else { | 799 } else { |
| 786 svc_params.min_quantizer = si->quantizer[layer_index]; | 800 svc_params.min_quantizer = codec_ctx->config.enc->rc_min_quantizer; |
| 787 svc_params.max_quantizer = si->quantizer[layer_index]; | 801 svc_params.max_quantizer = codec_ctx->config.enc->rc_max_quantizer; |
| 788 } | 802 } |
| 789 | 803 |
| 790 svc_params.distance_from_i_frame = si->frame_within_gop; | 804 svc_params.distance_from_i_frame = si->frame_within_gop; |
| 791 | 805 |
| 792 // Use buffer i for layer i LST | 806 // Use buffer i for layer i LST |
| 793 svc_params.lst_fb_idx = si->layer; | 807 svc_params.lst_fb_idx = si->layer; |
| 794 | 808 |
| 795 // Use buffer i-1 for layer i Alt (Inter-layer prediction) | 809 // Use buffer i-1 for layer i Alt (Inter-layer prediction) |
| 796 if (si->layer != 0) { | 810 if (si->layer != 0) { |
| 797 const int use_higher_layer = | 811 const int use_higher_layer = |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, | 852 vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, |
| 839 struct vpx_image *rawimg, vpx_codec_pts_t pts, | 853 struct vpx_image *rawimg, vpx_codec_pts_t pts, |
| 840 int64_t duration, int deadline) { | 854 int64_t duration, int deadline) { |
| 841 vpx_codec_err_t res; | 855 vpx_codec_err_t res; |
| 842 vpx_codec_iter_t iter; | 856 vpx_codec_iter_t iter; |
| 843 const vpx_codec_cx_pkt_t *cx_pkt; | 857 const vpx_codec_cx_pkt_t *cx_pkt; |
| 844 struct LayerData *cx_layer_list = NULL; | 858 struct LayerData *cx_layer_list = NULL; |
| 845 struct LayerData *layer_data; | 859 struct LayerData *layer_data; |
| 846 struct Superframe superframe; | 860 struct Superframe superframe; |
| 847 SvcInternal *const si = get_svc_internal(svc_ctx); | 861 SvcInternal *const si = get_svc_internal(svc_ctx); |
| 848 if (svc_ctx == NULL || codec_ctx == NULL || rawimg == NULL || si == NULL) { | 862 if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) { |
| 849 return VPX_CODEC_INVALID_PARAM; | 863 return VPX_CODEC_INVALID_PARAM; |
| 850 } | 864 } |
| 851 | 865 |
| 852 memset(&superframe, 0, sizeof(superframe)); | 866 memset(&superframe, 0, sizeof(superframe)); |
| 853 svc_log_reset(svc_ctx); | 867 svc_log_reset(svc_ctx); |
| 868 si->rc_stats_buf_used = 0; |
| 854 | 869 |
| 855 si->layers = svc_ctx->spatial_layers; | 870 si->layers = svc_ctx->spatial_layers; |
| 856 if (si->frame_within_gop >= si->kf_dist || | 871 if (si->frame_within_gop >= si->kf_dist || |
| 857 si->encode_frame_count == 0) { | 872 si->encode_frame_count == 0) { |
| 858 si->frame_within_gop = 0; | 873 si->frame_within_gop = 0; |
| 859 } | 874 } |
| 860 si->is_keyframe = (si->frame_within_gop == 0); | 875 si->is_keyframe = (si->frame_within_gop == 0); |
| 861 si->frame_size = 0; | 876 si->frame_size = 0; |
| 862 | 877 |
| 863 svc_log(svc_ctx, SVC_LOG_DEBUG, | 878 if (rawimg != NULL) { |
| 864 "vpx_svc_encode layers: %d, frame_count: %d, frame_within_gop: %d\n", | 879 svc_log(svc_ctx, SVC_LOG_DEBUG, |
| 865 si->layers, si->encode_frame_count, si->frame_within_gop); | 880 "vpx_svc_encode layers: %d, frame_count: %d, " |
| 881 "frame_within_gop: %d\n", si->layers, si->encode_frame_count, |
| 882 si->frame_within_gop); |
| 883 } |
| 866 | 884 |
| 867 // encode each layer | 885 // encode each layer |
| 868 for (si->layer = 0; si->layer < si->layers; ++si->layer) { | 886 for (si->layer = 0; si->layer < si->layers; ++si->layer) { |
| 869 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP && | 887 if (svc_ctx->encoding_mode == ALT_INTER_LAYER_PREDICTION_IP && |
| 870 si->is_keyframe && (si->layer == 1 || si->layer == 3)) { | 888 si->is_keyframe && (si->layer == 1 || si->layer == 3)) { |
| 871 svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer); | 889 svc_log(svc_ctx, SVC_LOG_DEBUG, "Skip encoding layer %d\n", si->layer); |
| 872 continue; | 890 continue; |
| 873 } | 891 } |
| 874 calculate_enc_frame_flags(svc_ctx); | |
| 875 | 892 |
| 876 set_svc_parameters(svc_ctx, codec_ctx); | 893 if (rawimg != NULL) { |
| 894 calculate_enc_frame_flags(svc_ctx); |
| 895 set_svc_parameters(svc_ctx, codec_ctx); |
| 896 } |
| 877 | 897 |
| 878 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, | 898 res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, |
| 879 si->enc_frame_flags, deadline); | 899 si->enc_frame_flags, deadline); |
| 880 if (res != VPX_CODEC_OK) { | 900 if (res != VPX_CODEC_OK) { |
| 881 return res; | 901 return res; |
| 882 } | 902 } |
| 883 // save compressed data | 903 // save compressed data |
| 884 iter = NULL; | 904 iter = NULL; |
| 885 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) { | 905 while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) { |
| 886 switch (cx_pkt->kind) { | 906 switch (cx_pkt->kind) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 916 "%2.3f %2.3f %2.3f %2.3f \n", | 936 "%2.3f %2.3f %2.3f %2.3f \n", |
| 917 si->encode_frame_count, si->layer, | 937 si->encode_frame_count, si->layer, |
| 918 cx_pkt->data.psnr.sse[0], cx_pkt->data.psnr.sse[1], | 938 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]); | 939 cx_pkt->data.psnr.sse[2], cx_pkt->data.psnr.sse[3]); |
| 920 for (i = 0; i < COMPONENTS; i++) { | 940 for (i = 0; i < COMPONENTS; i++) { |
| 921 si->psnr_sum[si->layer][i] += cx_pkt->data.psnr.psnr[i]; | 941 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]; | 942 si->sse_sum[si->layer][i] += cx_pkt->data.psnr.sse[i]; |
| 923 } | 943 } |
| 924 break; | 944 break; |
| 925 } | 945 } |
| 946 case VPX_CODEC_STATS_PKT: { |
| 947 size_t new_size = si->rc_stats_buf_used + |
| 948 cx_pkt->data.twopass_stats.sz; |
| 949 |
| 950 if (new_size > si->rc_stats_buf_size) { |
| 951 char *p = (char*)realloc(si->rc_stats_buf, new_size); |
| 952 if (p == NULL) { |
| 953 svc_log(svc_ctx, SVC_LOG_ERROR, "Error allocating stats buf\n"); |
| 954 break; |
| 955 } |
| 956 si->rc_stats_buf = p; |
| 957 si->rc_stats_buf_size = new_size; |
| 958 } |
| 959 |
| 960 memcpy(si->rc_stats_buf + si->rc_stats_buf_used, |
| 961 cx_pkt->data.twopass_stats.buf, cx_pkt->data.twopass_stats.sz); |
| 962 si->rc_stats_buf_used += cx_pkt->data.twopass_stats.sz; |
| 963 break; |
| 964 } |
| 926 default: { | 965 default: { |
| 927 break; | 966 break; |
| 928 } | 967 } |
| 929 } | 968 } |
| 930 } | 969 } |
| 970 if (rawimg == NULL) { |
| 971 break; |
| 972 } |
| 931 } | 973 } |
| 932 // add superframe index to layer data list | 974 if (codec_ctx->config.enc->g_pass != VPX_RC_FIRST_PASS) { |
| 933 sf_create_index(&superframe); | 975 // add superframe index to layer data list |
| 934 layer_data = ld_create(superframe.buffer, superframe.index_size); | 976 sf_create_index(&superframe); |
| 935 ld_list_add(&cx_layer_list, layer_data); | 977 layer_data = ld_create(superframe.buffer, superframe.index_size); |
| 978 ld_list_add(&cx_layer_list, layer_data); |
| 936 | 979 |
| 937 // get accumulated size of layer data | 980 // get accumulated size of layer data |
| 938 si->frame_size = ld_list_get_buffer_size(cx_layer_list); | 981 si->frame_size = ld_list_get_buffer_size(cx_layer_list); |
| 939 if (si->frame_size == 0) return VPX_CODEC_ERROR; | 982 if (si->frame_size > 0) { |
| 983 // all layers encoded, create single buffer with concatenated layers |
| 984 if (si->frame_size > si->buffer_size) { |
| 985 free(si->buffer); |
| 986 si->buffer = malloc(si->frame_size); |
| 987 if (si->buffer == NULL) { |
| 988 ld_list_free(cx_layer_list); |
| 989 return VPX_CODEC_MEM_ERROR; |
| 990 } |
| 991 si->buffer_size = si->frame_size; |
| 992 } |
| 993 // copy layer data into packet |
| 994 ld_list_copy_to_buffer(cx_layer_list, (uint8_t *)si->buffer); |
| 940 | 995 |
| 941 // all layers encoded, create single buffer with concatenated layers | |
| 942 if (si->frame_size > si->buffer_size) { | |
| 943 free(si->buffer); | |
| 944 si->buffer = malloc(si->frame_size); | |
| 945 if (si->buffer == NULL) { | |
| 946 ld_list_free(cx_layer_list); | 996 ld_list_free(cx_layer_list); |
| 947 return VPX_CODEC_MEM_ERROR; | 997 |
| 998 svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, " |
| 999 "pts: %d\n", si->encode_frame_count, si->is_keyframe, |
| 1000 (int)si->frame_size, (int)pts); |
| 948 } | 1001 } |
| 949 si->buffer_size = si->frame_size; | |
| 950 } | 1002 } |
| 951 // copy layer data into packet | |
| 952 ld_list_copy_to_buffer(cx_layer_list, (uint8_t *)si->buffer); | |
| 953 | |
| 954 ld_list_free(cx_layer_list); | |
| 955 | |
| 956 svc_log(svc_ctx, SVC_LOG_DEBUG, "SVC frame: %d, kf: %d, size: %d, pts: %d\n", | |
| 957 si->encode_frame_count, si->is_keyframe, (int)si->frame_size, | |
| 958 (int)pts); | |
| 959 ++si->frame_within_gop; | 1003 ++si->frame_within_gop; |
| 960 ++si->encode_frame_count; | 1004 ++si->encode_frame_count; |
| 961 | 1005 |
| 962 return VPX_CODEC_OK; | 1006 return VPX_CODEC_OK; |
| 963 } | 1007 } |
| 964 | 1008 |
| 965 const char *vpx_svc_get_message(const SvcContext *svc_ctx) { | 1009 const char *vpx_svc_get_message(const SvcContext *svc_ctx) { |
| 966 const SvcInternal *const si = get_const_svc_internal(svc_ctx); | 1010 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
| 967 if (svc_ctx == NULL || si == NULL) return NULL; | 1011 if (svc_ctx == NULL || si == NULL) return NULL; |
| 968 return si->message_buffer; | 1012 return si->message_buffer; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 } | 1114 } |
| 1071 | 1115 |
| 1072 void vpx_svc_release(SvcContext *svc_ctx) { | 1116 void vpx_svc_release(SvcContext *svc_ctx) { |
| 1073 SvcInternal *si; | 1117 SvcInternal *si; |
| 1074 if (svc_ctx == NULL) return; | 1118 if (svc_ctx == NULL) return; |
| 1075 // do not use get_svc_internal as it will unnecessarily allocate an | 1119 // do not use get_svc_internal as it will unnecessarily allocate an |
| 1076 // SvcInternal if it was not already allocated | 1120 // SvcInternal if it was not already allocated |
| 1077 si = (SvcInternal *)svc_ctx->internal; | 1121 si = (SvcInternal *)svc_ctx->internal; |
| 1078 if (si != NULL) { | 1122 if (si != NULL) { |
| 1079 free(si->buffer); | 1123 free(si->buffer); |
| 1124 if (si->rc_stats_buf) { |
| 1125 free(si->rc_stats_buf); |
| 1126 } |
| 1080 free(si); | 1127 free(si); |
| 1081 svc_ctx->internal = NULL; | 1128 svc_ctx->internal = NULL; |
| 1082 } | 1129 } |
| 1083 } | 1130 } |
| 1131 |
| 1132 size_t vpx_svc_get_rc_stats_buffer_size(const SvcContext *svc_ctx) { |
| 1133 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
| 1134 if (svc_ctx == NULL || si == NULL) return 0; |
| 1135 return si->rc_stats_buf_used; |
| 1136 } |
| 1137 |
| 1138 char *vpx_svc_get_rc_stats_buffer(const SvcContext *svc_ctx) { |
| 1139 const SvcInternal *const si = get_const_svc_internal(svc_ctx); |
| 1140 if (svc_ctx == NULL || si == NULL) return NULL; |
| 1141 return si->rc_stats_buf; |
| 1142 } |
| 1143 |
| 1144 |
| OLD | NEW |