[svc] Verify and store input two pass stats data in 2nd pass rc
Change-Id: Ib09eedc17ea0ea2eec75d78112e4786d98f382aa
This commit is contained in:
parent
143b09558c
commit
6b2e406123
@ -31,6 +31,7 @@ class SvcTest : public ::testing::Test {
|
|||||||
SvcTest()
|
SvcTest()
|
||||||
: codec_iface_(0),
|
: codec_iface_(0),
|
||||||
test_file_name_("hantro_collage_w352h288.yuv"),
|
test_file_name_("hantro_collage_w352h288.yuv"),
|
||||||
|
stats_file_name_("hantro_collage_w352h288.stat"),
|
||||||
codec_initialized_(false),
|
codec_initialized_(false),
|
||||||
decoder_(0) {
|
decoder_(0) {
|
||||||
memset(&svc_, 0, sizeof(svc_));
|
memset(&svc_, 0, sizeof(svc_));
|
||||||
@ -73,6 +74,7 @@ class SvcTest : public ::testing::Test {
|
|||||||
struct vpx_codec_enc_cfg codec_enc_;
|
struct vpx_codec_enc_cfg codec_enc_;
|
||||||
vpx_codec_iface_t *codec_iface_;
|
vpx_codec_iface_t *codec_iface_;
|
||||||
std::string test_file_name_;
|
std::string test_file_name_;
|
||||||
|
std::string stats_file_name_;
|
||||||
bool codec_initialized_;
|
bool codec_initialized_;
|
||||||
Decoder *decoder_;
|
Decoder *decoder_;
|
||||||
};
|
};
|
||||||
@ -397,4 +399,31 @@ TEST_F(SvcTest, FirstPassEncode) {
|
|||||||
EXPECT_GT(vpx_svc_get_rc_stats_buffer_size(&svc_), 0U);
|
EXPECT_GT(vpx_svc_get_rc_stats_buffer_size(&svc_), 0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SvcTest, SecondPassEncode) {
|
||||||
|
svc_.spatial_layers = 2;
|
||||||
|
codec_enc_.g_pass = VPX_RC_LAST_PASS;
|
||||||
|
|
||||||
|
FILE *const stats_file = libvpx_test::OpenTestDataFile(stats_file_name_);
|
||||||
|
ASSERT_TRUE(stats_file != NULL) << "Stats file open failed. Filename: "
|
||||||
|
<< stats_file;
|
||||||
|
|
||||||
|
struct vpx_fixed_buf stats_buf;
|
||||||
|
fseek(stats_file, 0, SEEK_END);
|
||||||
|
stats_buf.sz = static_cast<size_t>(ftell(stats_file));
|
||||||
|
fseek(stats_file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
stats_buf.buf = malloc(stats_buf.sz);
|
||||||
|
ASSERT_TRUE(stats_buf.buf != NULL);
|
||||||
|
const size_t bytes_read = fread(stats_buf.buf, 1, stats_buf.sz, stats_file);
|
||||||
|
ASSERT_EQ(bytes_read, stats_buf.sz);
|
||||||
|
fclose(stats_file);
|
||||||
|
codec_enc_.rc_twopass_stats_in = stats_buf;
|
||||||
|
|
||||||
|
const vpx_codec_err_t res =
|
||||||
|
vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
|
||||||
|
ASSERT_EQ(VPX_CODEC_OK, res);
|
||||||
|
|
||||||
|
free(stats_buf.buf);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
d5dfb0151c9051f8c85999255645d7a23916d3c0 hantro_collage_w352h288.yuv
|
d5dfb0151c9051f8c85999255645d7a23916d3c0 hantro_collage_w352h288.yuv
|
||||||
|
2752863aa6330a93eaeb30f883310f87aa3de87c hantro_collage_w352h288.stat
|
||||||
b87815bf86020c592ccc7a846ba2e28ec8043902 hantro_odd.yuv
|
b87815bf86020c592ccc7a846ba2e28ec8043902 hantro_odd.yuv
|
||||||
b1f1c3ec79114b9a0651af24ce634afb44a9a419 rush_hour_444.y4m
|
b1f1c3ec79114b9a0651af24ce634afb44a9a419 rush_hour_444.y4m
|
||||||
5184c46ddca8b1fadd16742e8500115bc8f749da vp80-00-comprehensive-001.ivf
|
5184c46ddca8b1fadd16742e8500115bc8f749da vp80-00-comprehensive-001.ivf
|
||||||
|
@ -122,6 +122,7 @@ endif # CONFIG_SHARED
|
|||||||
## TEST DATA
|
## TEST DATA
|
||||||
##
|
##
|
||||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288.yuv
|
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288.yuv
|
||||||
|
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288.stat
|
||||||
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_odd.yuv
|
LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_odd.yuv
|
||||||
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m
|
LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m
|
||||||
|
|
||||||
|
@ -177,6 +177,7 @@ void vp9_initialize_enc() {
|
|||||||
|
|
||||||
static void dealloc_compressor_data(VP9_COMP *cpi) {
|
static void dealloc_compressor_data(VP9_COMP *cpi) {
|
||||||
VP9_COMMON *const cm = &cpi->common;
|
VP9_COMMON *const cm = &cpi->common;
|
||||||
|
int i;
|
||||||
|
|
||||||
// Delete sementation map
|
// Delete sementation map
|
||||||
vpx_free(cpi->segmentation_map);
|
vpx_free(cpi->segmentation_map);
|
||||||
@ -210,6 +211,13 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
|
|||||||
cpi->mb_activity_map = 0;
|
cpi->mb_activity_map = 0;
|
||||||
vpx_free(cpi->mb_norm_activity_map);
|
vpx_free(cpi->mb_norm_activity_map);
|
||||||
cpi->mb_norm_activity_map = 0;
|
cpi->mb_norm_activity_map = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
|
||||||
|
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[i];
|
||||||
|
vpx_free(lc->rc_twopass_stats_in.buf);
|
||||||
|
lc->rc_twopass_stats_in.buf = NULL;
|
||||||
|
lc->rc_twopass_stats_in.sz = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes a q delta (in "q index" terms) to get from a starting q value
|
// Computes a q delta (in "q index" terms) to get from a starting q value
|
||||||
@ -1750,9 +1758,47 @@ VP9_COMP *vp9_create_compressor(VP9_CONFIG *oxcf) {
|
|||||||
const size_t packet_sz = sizeof(FIRSTPASS_STATS);
|
const size_t packet_sz = sizeof(FIRSTPASS_STATS);
|
||||||
const int packets = (int)(oxcf->two_pass_stats_in.sz / packet_sz);
|
const int packets = (int)(oxcf->two_pass_stats_in.sz / packet_sz);
|
||||||
|
|
||||||
cpi->twopass.stats_in_start = oxcf->two_pass_stats_in.buf;
|
if (cpi->svc.number_spatial_layers > 1
|
||||||
cpi->twopass.stats_in = cpi->twopass.stats_in_start;
|
&& cpi->svc.number_temporal_layers == 1) {
|
||||||
cpi->twopass.stats_in_end = &cpi->twopass.stats_in[packets - 1];
|
FIRSTPASS_STATS *const stats = oxcf->two_pass_stats_in.buf;
|
||||||
|
FIRSTPASS_STATS *stats_copy[VPX_SS_MAX_LAYERS] = {0};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < oxcf->ss_number_layers; ++i) {
|
||||||
|
FIRSTPASS_STATS *const last_packet_for_layer =
|
||||||
|
&stats[packets - oxcf->ss_number_layers + i];
|
||||||
|
const int layer_id = last_packet_for_layer->spatial_layer_id;
|
||||||
|
const int packets_in_layer = (int)last_packet_for_layer->count + 1;
|
||||||
|
if (layer_id >= 0 && layer_id < oxcf->ss_number_layers) {
|
||||||
|
LAYER_CONTEXT *const lc = &cpi->svc.layer_context[layer_id];
|
||||||
|
|
||||||
|
vpx_free(lc->rc_twopass_stats_in.buf);
|
||||||
|
|
||||||
|
lc->rc_twopass_stats_in.sz = packets_in_layer * packet_sz;
|
||||||
|
CHECK_MEM_ERROR(cm, lc->rc_twopass_stats_in.buf,
|
||||||
|
vpx_malloc(lc->rc_twopass_stats_in.sz));
|
||||||
|
lc->twopass.stats_in_start = lc->rc_twopass_stats_in.buf;
|
||||||
|
lc->twopass.stats_in = lc->twopass.stats_in_start;
|
||||||
|
lc->twopass.stats_in_end = lc->twopass.stats_in_start
|
||||||
|
+ packets_in_layer - 1;
|
||||||
|
stats_copy[layer_id] = lc->rc_twopass_stats_in.buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < packets; ++i) {
|
||||||
|
const int layer_id = stats[i].spatial_layer_id;
|
||||||
|
if (layer_id >= 0 && layer_id < oxcf->ss_number_layers
|
||||||
|
&& stats_copy[layer_id] != NULL) {
|
||||||
|
*stats_copy[layer_id] = stats[i];
|
||||||
|
++stats_copy[layer_id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cpi->twopass.stats_in_start = oxcf->two_pass_stats_in.buf;
|
||||||
|
cpi->twopass.stats_in = cpi->twopass.stats_in_start;
|
||||||
|
cpi->twopass.stats_in_end = &cpi->twopass.stats_in[packets - 1];
|
||||||
|
}
|
||||||
|
|
||||||
vp9_init_second_pass(cpi);
|
vp9_init_second_pass(cpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ typedef struct {
|
|||||||
double framerate;
|
double framerate;
|
||||||
int avg_frame_size;
|
int avg_frame_size;
|
||||||
struct twopass_rc twopass;
|
struct twopass_rc twopass;
|
||||||
|
struct vpx_fixed_buf rc_twopass_stats_in;
|
||||||
} LAYER_CONTEXT;
|
} LAYER_CONTEXT;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -221,14 +221,43 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
|
|||||||
if (cfg->rc_twopass_stats_in.sz % packet_sz)
|
if (cfg->rc_twopass_stats_in.sz % packet_sz)
|
||||||
ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
|
ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
|
||||||
|
|
||||||
if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
|
if (cfg->ss_number_layers > 1) {
|
||||||
ERROR("rc_twopass_stats_in requires at least two packets.");
|
int i;
|
||||||
|
unsigned int n_packets_per_layer[VPX_SS_MAX_LAYERS] = {0};
|
||||||
|
|
||||||
stats =
|
stats = cfg->rc_twopass_stats_in.buf;
|
||||||
(const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
|
for (i = 0; i < n_packets; ++i) {
|
||||||
|
const int layer_id = stats[i].spatial_layer_id;
|
||||||
|
if (layer_id >= 0 && layer_id < (int)cfg->ss_number_layers) {
|
||||||
|
++n_packets_per_layer[layer_id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((int)(stats->count + 0.5) != n_packets - 1)
|
for (i = 0; i < (int)cfg->ss_number_layers; ++i) {
|
||||||
ERROR("rc_twopass_stats_in missing EOS stats packet");
|
unsigned int layer_id;
|
||||||
|
if (n_packets_per_layer[i] < 2) {
|
||||||
|
ERROR("rc_twopass_stats_in requires at least two packets for each "
|
||||||
|
"layer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
stats = (const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf +
|
||||||
|
n_packets - cfg->ss_number_layers + i;
|
||||||
|
layer_id = stats->spatial_layer_id;
|
||||||
|
|
||||||
|
if (layer_id >= cfg->ss_number_layers
|
||||||
|
||(int)(stats->count + 0.5) != n_packets_per_layer[layer_id] - 1)
|
||||||
|
ERROR("rc_twopass_stats_in missing EOS stats packet");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cfg->rc_twopass_stats_in.sz < 2 * packet_sz)
|
||||||
|
ERROR("rc_twopass_stats_in requires at least two packets.");
|
||||||
|
|
||||||
|
stats =
|
||||||
|
(const FIRSTPASS_STATS *)cfg->rc_twopass_stats_in.buf + n_packets - 1;
|
||||||
|
|
||||||
|
if ((int)(stats->count + 0.5) != n_packets - 1)
|
||||||
|
ERROR("rc_twopass_stats_in missing EOS stats packet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return VPX_CODEC_OK;
|
return VPX_CODEC_OK;
|
||||||
@ -990,9 +1019,12 @@ static vpx_codec_err_t vp9e_set_svc(vpx_codec_alg_priv_t *ctx, int ctr_id,
|
|||||||
va_list args) {
|
va_list args) {
|
||||||
int data = va_arg(args, int);
|
int data = va_arg(args, int);
|
||||||
vp9_set_svc(ctx->cpi, data);
|
vp9_set_svc(ctx->cpi, data);
|
||||||
// CBR mode for SVC with both temporal and spatial layers not yet supported.
|
// CBR or two pass mode for SVC with both temporal and spatial layers
|
||||||
|
// not yet supported.
|
||||||
if (data == 1 &&
|
if (data == 1 &&
|
||||||
ctx->cfg.rc_end_usage == VPX_CBR &&
|
(ctx->cfg.rc_end_usage == VPX_CBR ||
|
||||||
|
ctx->cfg.g_pass == VPX_RC_FIRST_PASS ||
|
||||||
|
ctx->cfg.g_pass == VPX_RC_LAST_PASS) &&
|
||||||
ctx->cfg.ss_number_layers > 1 &&
|
ctx->cfg.ss_number_layers > 1 &&
|
||||||
ctx->cfg.ts_number_layers > 1) {
|
ctx->cfg.ts_number_layers > 1) {
|
||||||
return VPX_CODEC_INVALID_PARAM;
|
return VPX_CODEC_INVALID_PARAM;
|
||||||
|
Loading…
Reference in New Issue
Block a user