Add pyramid level check in subgop unit test This patch extends subgop unit test to validate pyramid level and corresponding qindex assignment of each frame. Change-Id: I5c18e513aaab86c11a4f0e6af0544419f4d183e2
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c index ec920db..76568cf 100644 --- a/av1/av1_dx_iface.c +++ b/av1/av1_dx_iface.c
@@ -1168,17 +1168,20 @@ FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; const AV1Decoder *const pbi = frame_worker_data->pbi; const SubGOPStatsDec *const subgop_stats = &pbi->subgop_stats; - SubGOPStepData *step_data = subgop_data->step; + SubGOPStepData *subgop_step = subgop_data->step; const int stat_count = subgop_stats->stat_count; // Collects already decoded out of order frames info along with in-order // frame - step_data += subgop_data->step_idx_dec; + subgop_step += subgop_data->step_idx_dec; for (int step_idx = 0; step_idx < stat_count; step_idx++) { - step_data[step_idx].disp_frame_idx = subgop_stats->disp_frame_idx[step_idx]; - step_data[step_idx].show_existing_frame = + SubGOPStepData *step_data = &subgop_step[step_idx]; + step_data->disp_frame_idx = subgop_stats->disp_frame_idx[step_idx]; + step_data->show_existing_frame = subgop_stats->show_existing_frame[step_idx]; - step_data[step_idx].show_frame = subgop_stats->show_frame[step_idx]; + step_data->show_frame = subgop_stats->show_frame[step_idx]; + step_data->qindex = subgop_stats->qindex[step_idx]; + subgop_data->step_idx_dec++; } return AOM_CODEC_OK;
diff --git a/av1/av1_iface_common.h b/av1/av1_iface_common.h index 18c3eb4..af1f48d 100644 --- a/av1/av1_iface_common.h +++ b/av1/av1_iface_common.h
@@ -24,6 +24,7 @@ int show_frame; int show_existing_frame; int pyramid_level; + int qindex; } SubGOPStepData; typedef struct {
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c index 608b1a7..c13fa15 100644 --- a/av1/decoder/decoder.c +++ b/av1/decoder/decoder.c
@@ -55,6 +55,7 @@ subgop_stats->show_existing_frame[subgop_stats->stat_count] = cm->show_existing_frame; subgop_stats->show_frame[subgop_stats->stat_count] = cm->show_frame; + subgop_stats->qindex[subgop_stats->stat_count] = cm->quant_params.base_qindex; assert(subgop_stats->stat_count < MAX_SUBGOP_STATS_SIZE); subgop_stats->stat_count++; }
diff --git a/av1/decoder/decoder.h b/av1/decoder/decoder.h index b4dabce..e483623 100644 --- a/av1/decoder/decoder.h +++ b/av1/decoder/decoder.h
@@ -225,6 +225,7 @@ unsigned char disp_frame_idx[MAX_SUBGOP_STATS_SIZE]; int show_existing_frame[MAX_SUBGOP_STATS_SIZE]; int show_frame[MAX_SUBGOP_STATS_SIZE]; + int qindex[MAX_SUBGOP_STATS_SIZE]; int refresh_frame_flags[MAX_SUBGOP_STATS_SIZE]; unsigned char stat_count; } SubGOPStatsDec;
diff --git a/test/subgop_test.cc b/test/subgop_test.cc index 29a4b54..0b9f769 100644 --- a/test/subgop_test.cc +++ b/test/subgop_test.cc
@@ -252,6 +252,8 @@ subgop_data_.step[idx].show_existing_frame = -1; subgop_data_.step[idx].show_frame = -1; subgop_data_.step[idx].is_filtered = -1; + subgop_data_.step[idx].pyramid_level = 0; + subgop_data_.step[idx].qindex = 0; } subgop_data_.num_steps = 0; subgop_data_.step_idx_enc = 0; @@ -309,6 +311,8 @@ for (int idx = 0; idx < subgop_data_.num_steps; idx++) { subgop_cfg_test_.step[idx].disp_frame_idx = (int8_t)(subgop_data_.step[idx].disp_frame_idx - frames_from_key_); + subgop_cfg_test_.step[idx].pyr_level = + (int8_t)subgop_data_.step[idx].pyramid_level; if (subgop_data_.step[idx].is_filtered) { filtered_frames[buf_idx++] = subgop_data_.step[idx].disp_frame_idx - frames_from_key_; @@ -380,6 +384,47 @@ return 1; } + // Validates Pyramid level with user config + void ValidatePyramidLevel() { + int8_t max_pyramid_level = 0; + for (int idx = 0; idx < subgop_cfg_ref_->num_steps; idx++) { + if (max_pyramid_level < subgop_cfg_ref_->step[idx].pyr_level) + max_pyramid_level = subgop_cfg_ref_->step[idx].pyr_level; + } + for (int idx = 0; idx < subgop_cfg_ref_->num_steps; idx++) { + int8_t ref_pyramid_level = + (subgop_cfg_ref_->step[idx].pyr_level == max_pyramid_level) + ? 6 + : subgop_cfg_ref_->step[idx].pyr_level; + EXPECT_EQ(subgop_cfg_test_.step[idx].pyr_level, ref_pyramid_level) + << "Error:pyramid level doesn't match"; + } + } + + // Validates Pyramid level along with qindex assignment + void ValidatePyramidLevelQIndex() { + int level_qindex[REF_FRAMES] = { 0 }; + int8_t pyramid_level; + for (int idx = 0; idx < subgop_cfg_ref_->num_steps; idx++) { + pyramid_level = subgop_cfg_test_.step[idx].pyr_level; + if (!level_qindex[pyramid_level]) { + level_qindex[pyramid_level] = subgop_data_.step[idx].qindex; + } else if (!subgop_data_.step[idx].show_existing_frame && + !subgop_data_.step[idx].is_filtered) { + EXPECT_EQ(level_qindex[pyramid_level], subgop_data_.step[idx].qindex) + << "Error:qindex in a pyramid level doesn't match"; + } + } + pyramid_level = 1; + for (int idx = 1; idx < REF_FRAMES; idx++) { + if (level_qindex[pyramid_level]) { + EXPECT_LT(level_qindex[pyramid_level - 1], level_qindex[pyramid_level]) + << "Error:qindex should be higher in hierarchical pyramid level"; + pyramid_level++; + } + } + } + bool IsInputSubgopCfgUsed() { int num_ooo_frames_ref = 0; int num_ooo_frames_test = 0; @@ -428,6 +473,8 @@ EXPECT_EQ(subgop_code_test_, subgop_info_.pos_code) << "Error:subgop code doesn't match"; ValidateSubgopFrametype(); + ValidatePyramidLevel(); + if (rc_end_usage_ == AOM_Q) ValidatePyramidLevelQIndex(); } } frames_from_key_ += subgop_info_.size;