Move hard-coded MV limits to encoder_control_t

Adds field max_inter_ref_lcu to encoder_control_t. It is used to set up
inter-LCU dependencies in encoder_state_encode_leaf and restrict motion
vectors in fracmv_within_tile.
This commit is contained in:
Arttu Ylä-Outinen 2017-06-26 11:44:17 +03:00
parent bb5354f7e2
commit 2a85f0f5a4
4 changed files with 25 additions and 20 deletions

View file

@ -574,6 +574,9 @@ encoder_control_t* kvz_encoder_control_init(const kvz_config *const cfg)
encoder->cfg.trskip_enable = false; encoder->cfg.trskip_enable = false;
} }
encoder->max_inter_ref_lcu.right = 1;
encoder->max_inter_ref_lcu.down = 1;
// If fractional framerate is set, use that instead of the floating point framerate. // If fractional framerate is set, use that instead of the floating point framerate.
if (encoder->cfg.framerate_num != 0) { if (encoder->cfg.framerate_num != 0) {
encoder->vui.timing_info_present_flag = 1; encoder->vui.timing_info_present_flag = 1;

View file

@ -127,6 +127,12 @@ typedef struct encoder_control_t
uint8_t dependent_slice_segments_enabled_flag; uint8_t dependent_slice_segments_enabled_flag;
} pps; } pps;
//! Maximum motion vector distance as number of LCUs.
struct {
int right;
int down;
} max_inter_ref_lcu;
} encoder_control_t; } encoder_control_t;
encoder_control_t* kvz_encoder_control_init(const kvz_config *cfg); encoder_control_t* kvz_encoder_control_init(const kvz_config *cfg);

View file

@ -729,7 +729,8 @@ static void encoder_state_encode_leaf(encoder_state_t * const state)
assert(state->is_leaf); assert(state->is_leaf);
assert(state->lcu_order_count > 0); assert(state->lcu_order_count > 0);
const kvz_config *cfg = &state->encoder_control->cfg; const encoder_control_t *ctrl = state->encoder_control;
const kvz_config *cfg = &ctrl->cfg;
state->ref_qp = state->frame->QP; state->ref_qp = state->frame->QP;
@ -754,7 +755,7 @@ static void encoder_state_encode_leaf(encoder_state_t * const state)
#ifdef KVZ_DEBUG #ifdef KVZ_DEBUG
{ {
const lcu_order_element_t * const lcu = &state->lcu_order[i]; const lcu_order_element_t * const lcu = &state->lcu_order[i];
PERFORMANCE_MEASURE_END(KVZ_PERF_LCU, state->encoder_control->threadqueue, "type=encode_lcu,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", state->frame->num, state->tile->id, state->slice->id, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH + lcu->size.x - 1, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH + lcu->size.y - 1); PERFORMANCE_MEASURE_END(KVZ_PERF_LCU, ctrl->threadqueue, "type=encode_lcu,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", state->frame->num, state->tile->id, state->slice->id, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH + lcu->size.x - 1, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH + lcu->size.y - 1);
} }
#endif //KVZ_DEBUG #endif //KVZ_DEBUG
} }
@ -769,7 +770,7 @@ static void encoder_state_encode_leaf(encoder_state_t * const state)
{ {
// For LP-gop, depend on the state of the first reference. // For LP-gop, depend on the state of the first reference.
int ref_neg = cfg->gop[(state->frame->poc - 1) % cfg->gop_len].ref_neg[0]; int ref_neg = cfg->gop[(state->frame->poc - 1) % cfg->gop_len].ref_neg[0];
if (ref_neg > state->encoder_control->cfg.owf) { if (ref_neg > cfg->owf) {
// If frame is not within OWF range, it's already done. // If frame is not within OWF range, it's already done.
ref_state = NULL; ref_state = NULL;
} else { } else {
@ -794,7 +795,7 @@ static void encoder_state_encode_leaf(encoder_state_t * const state)
char* job_description = NULL; char* job_description = NULL;
#endif #endif
kvz_threadqueue_free_job(&state->tile->wf_jobs[lcu->id]); kvz_threadqueue_free_job(&state->tile->wf_jobs[lcu->id]);
state->tile->wf_jobs[lcu->id] = kvz_threadqueue_submit(state->encoder_control->threadqueue, encoder_state_worker_encode_lcu, (void*)lcu, 1, job_description); state->tile->wf_jobs[lcu->id] = kvz_threadqueue_submit(ctrl->threadqueue, encoder_state_worker_encode_lcu, (void*)lcu, 1, job_description);
threadqueue_job_t **job = &state->tile->wf_jobs[lcu->id]; threadqueue_job_t **job = &state->tile->wf_jobs[lcu->id];
// If job object was returned, add dependancies and allow it to run. // If job object was returned, add dependancies and allow it to run.
@ -809,19 +810,14 @@ static void encoder_state_encode_leaf(encoder_state_t * const state)
{ {
// We need to wait until the CTUs whose pixels we refer to are // We need to wait until the CTUs whose pixels we refer to are
// done before we can start this CTU. // done before we can start this CTU.
if (lcu->below) { const lcu_order_element_t *dep_lcu = lcu;
if (lcu->below->right) { for (int i = 0; dep_lcu->below && i < ctrl->max_inter_ref_lcu.down; i++) {
kvz_threadqueue_job_dep_add(job[0], ref_state->tile->wf_jobs[lcu->below->right->id]); dep_lcu = dep_lcu->below;
} else {
kvz_threadqueue_job_dep_add(job[0], ref_state->tile->wf_jobs[lcu->below->id]);
}
} else {
if (lcu->right) {
kvz_threadqueue_job_dep_add(job[0], ref_state->tile->wf_jobs[lcu->right->id]);
} else {
kvz_threadqueue_job_dep_add(job[0], ref_state->tile->wf_jobs[lcu->id]);
}
} }
for (int i = 0; dep_lcu->right && i < ctrl->max_inter_ref_lcu.right; i++) {
dep_lcu = dep_lcu->right;
}
kvz_threadqueue_job_dep_add(job[0], ref_state->tile->wf_jobs[dep_lcu->id]);
} }
// Add local WPP dependancy to the LCU on the left. // Add local WPP dependancy to the LCU on the left.

View file

@ -70,13 +70,13 @@ static INLINE bool fracmv_within_tile(const encoder_state_t *state, const vector
.y = (((orig->y + height + margin) << 2) + y) / (LCU_WIDTH << 2) - orig_lcu.y, .y = (((orig->y + height + margin) << 2) + y) / (LCU_WIDTH << 2) - orig_lcu.y,
}; };
// TODO: Remove hard coded constants. if (mv_lcu.y > ctrl->max_inter_ref_lcu.down) {
if (mv_lcu.y > 1) {
return false; return false;
} }
// TODO: Remove hard coded constants. if (mv_lcu.x + mv_lcu.y >
if (mv_lcu.x + mv_lcu.y > 2) { ctrl->max_inter_ref_lcu.down + ctrl->max_inter_ref_lcu.right)
{
return false; return false;
} }
} }