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 |