mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-12-18 11:14:05 +00:00
Fix picture and slice types
Changes handling of intra pictures for --gop=8 so that every picture with POC divisible by the intra period is intra. The first picture is IDR and the rest of the intra pictures are CRA. POC is not reset at CRA pictures. The leading pictures that follow the CRA picture are changed to RASL so they are allowed to refer to pictures before the CRA picture. Changes inter slice types to P when the L1 reference list is empty and to B otherwise. In all-intra, all pictures are now IDR pictures with POC zero.
This commit is contained in:
parent
957b6850c3
commit
841597e123
|
@ -731,7 +731,7 @@ static void kvz_encoder_state_write_bitstream_slice_header_independent(
|
||||||
|
|
||||||
WRITE_UE(stream, encoder->cfg.gop_len?delta_poc - last_poc - 1:0, "delta_poc_s0_minus1");
|
WRITE_UE(stream, encoder->cfg.gop_len?delta_poc - last_poc - 1:0, "delta_poc_s0_minus1");
|
||||||
last_poc = delta_poc;
|
last_poc = delta_poc;
|
||||||
WRITE_U(stream,1,1, "used_by_curr_pic_s0_flag");
|
WRITE_U(stream, !state->frame->is_irap, 1, "used_by_curr_pic_s0_flag");
|
||||||
}
|
}
|
||||||
last_poc = 0;
|
last_poc = 0;
|
||||||
poc_shift = 0;
|
poc_shift = 0;
|
||||||
|
@ -758,12 +758,12 @@ static void kvz_encoder_state_write_bitstream_slice_header_independent(
|
||||||
|
|
||||||
WRITE_UE(stream, encoder->cfg.gop_len ? delta_poc - last_poc - 1 : 0, "delta_poc_s1_minus1");
|
WRITE_UE(stream, encoder->cfg.gop_len ? delta_poc - last_poc - 1 : 0, "delta_poc_s1_minus1");
|
||||||
last_poc = delta_poc;
|
last_poc = delta_poc;
|
||||||
WRITE_U(stream, 1, 1, "used_by_curr_pic_s1_flag");
|
WRITE_U(stream, !state->frame->is_irap, 1, "used_by_curr_pic_s1_flag");
|
||||||
}
|
}
|
||||||
//WRITE_UE(stream, 0, "short_term_ref_pic_set_idx");
|
//WRITE_UE(stream, 0, "short_term_ref_pic_set_idx");
|
||||||
|
|
||||||
if (state->encoder_control->cfg.tmvp_enable) {
|
if (state->encoder_control->cfg.tmvp_enable) {
|
||||||
WRITE_U(stream, ref_negative?1:0, 1, "slice_temporal_mvp_enabled_flag");
|
WRITE_U(stream, ref_negative ? 1 : 0, 1, "slice_temporal_mvp_enabled_flag");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -996,7 +996,7 @@ void kvz_encoder_create_ref_lists(const encoder_state_t *const state)
|
||||||
*/
|
*/
|
||||||
static void encoder_state_remove_refs(encoder_state_t *state) {
|
static void encoder_state_remove_refs(encoder_state_t *state) {
|
||||||
const encoder_control_t * const encoder = state->encoder_control;
|
const encoder_control_t * const encoder = state->encoder_control;
|
||||||
|
|
||||||
int neg_refs = encoder->cfg.gop[state->frame->gop_offset].ref_neg_count;
|
int neg_refs = encoder->cfg.gop[state->frame->gop_offset].ref_neg_count;
|
||||||
int pos_refs = encoder->cfg.gop[state->frame->gop_offset].ref_pos_count;
|
int pos_refs = encoder->cfg.gop[state->frame->gop_offset].ref_pos_count;
|
||||||
|
|
||||||
|
@ -1006,7 +1006,10 @@ static void encoder_state_remove_refs(encoder_state_t *state) {
|
||||||
} else {
|
} else {
|
||||||
target_ref_num = encoder->cfg.ref_frames;
|
target_ref_num = encoder->cfg.ref_frames;
|
||||||
}
|
}
|
||||||
if (state->frame->slicetype == KVZ_SLICE_I) {
|
|
||||||
|
if (state->frame->pictype == KVZ_NAL_IDR_W_RADL ||
|
||||||
|
state->frame->pictype == KVZ_NAL_IDR_N_LP)
|
||||||
|
{
|
||||||
target_ref_num = 0;
|
target_ref_num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1018,7 +1021,7 @@ static void encoder_state_remove_refs(encoder_state_t *state) {
|
||||||
bool is_referenced = false;
|
bool is_referenced = false;
|
||||||
|
|
||||||
int ref_poc = state->frame->ref->pocs[ref];
|
int ref_poc = state->frame->ref->pocs[ref];
|
||||||
|
|
||||||
for (int i = 0; i < neg_refs; i++) {
|
for (int i = 0; i < neg_refs; i++) {
|
||||||
int ref_relative_poc = -encoder->cfg.gop[state->frame->gop_offset].ref_neg[i];
|
int ref_relative_poc = -encoder->cfg.gop[state->frame->gop_offset].ref_neg[i];
|
||||||
if (ref_poc == state->frame->poc + ref_relative_poc) {
|
if (ref_poc == state->frame->poc + ref_relative_poc) {
|
||||||
|
@ -1027,7 +1030,6 @@ static void encoder_state_remove_refs(encoder_state_t *state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < pos_refs; i++) {
|
for (int i = 0; i < pos_refs; i++) {
|
||||||
int ref_relative_poc = encoder->cfg.gop[state->frame->gop_offset].ref_pos[i];
|
int ref_relative_poc = encoder->cfg.gop[state->frame->gop_offset].ref_pos[i];
|
||||||
if (ref_poc == state->frame->poc + ref_relative_poc) {
|
if (ref_poc == state->frame->poc + ref_relative_poc) {
|
||||||
|
@ -1043,6 +1045,13 @@ static void encoder_state_remove_refs(encoder_state_t *state) {
|
||||||
is_referenced = false;
|
is_referenced = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (encoder->cfg.intra_period > 0 &&
|
||||||
|
ref_poc < state->frame->irap_poc - encoder->cfg.intra_period)
|
||||||
|
{
|
||||||
|
// No frame can refer past the two preceding IRAP frames.
|
||||||
|
is_referenced = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_referenced) {
|
if (!is_referenced) {
|
||||||
// This reference is not referred to by this frame, it must be removed.
|
// This reference is not referred to by this frame, it must be removed.
|
||||||
kvz_image_list_rem(state->frame->ref, ref);
|
kvz_image_list_rem(state->frame->ref, ref);
|
||||||
|
@ -1059,16 +1068,6 @@ static void encoder_state_remove_refs(encoder_state_t *state) {
|
||||||
assert(state->frame->ref->used_size <= target_ref_num);
|
assert(state->frame->ref->used_size <= target_ref_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void encoder_state_reset_poc(encoder_state_t *state) {
|
|
||||||
state->frame->poc = 0;
|
|
||||||
kvz_videoframe_set_poc(state->tile->frame, 0);
|
|
||||||
|
|
||||||
for (int i = 0; state->children[i].encoder_control; ++i) {
|
|
||||||
encoder_state_t *sub_state = &(state->children[i]);
|
|
||||||
encoder_state_reset_poc(sub_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void encoder_set_source_picture(encoder_state_t * const state, kvz_picture* frame)
|
static void encoder_set_source_picture(encoder_state_t * const state, kvz_picture* frame)
|
||||||
{
|
{
|
||||||
assert(!state->tile->frame->source);
|
assert(!state->tile->frame->source);
|
||||||
|
@ -1134,63 +1133,46 @@ static void encoder_state_init_new_frame(encoder_state_t * const state, kvz_pict
|
||||||
state->tile->frame->height
|
state->tile->frame->height
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Set POC.
|
||||||
|
if (state->frame->num == 0) {
|
||||||
|
state->frame->poc = 0;
|
||||||
|
} else if (cfg->gop_len && !cfg->gop_lowdelay) {
|
||||||
|
// Calculate POC according to the global frame counter and GOP structure
|
||||||
|
int32_t poc = state->frame->num - 1;
|
||||||
|
int32_t poc_offset = cfg->gop[state->frame->gop_offset].poc_offset;
|
||||||
|
state->frame->poc = poc - poc % cfg->gop_len + poc_offset;
|
||||||
|
kvz_videoframe_set_poc(state->tile->frame, state->frame->poc);
|
||||||
|
} else if (cfg->intra_period > 0) {
|
||||||
|
state->frame->poc = state->frame->num % cfg->intra_period;
|
||||||
|
} else {
|
||||||
|
state->frame->poc = state->frame->num;
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether the frame is a keyframe or not.
|
// Check whether the frame is a keyframe or not.
|
||||||
if (state->frame->num == 0) {
|
if (state->frame->num == 0) {
|
||||||
state->frame->is_irap = true;
|
state->frame->is_irap = true;
|
||||||
} else if (cfg->intra_period == 1) {
|
|
||||||
state->frame->is_irap = state->frame->num % 2 == 0;
|
|
||||||
} else if (cfg->intra_period > 1) {
|
|
||||||
if (cfg->gop_len > 0 && !cfg->gop_lowdelay) {
|
|
||||||
state->frame->is_irap = (state->frame->num - 1) % cfg->intra_period == 0;
|
|
||||||
} else {
|
|
||||||
state->frame->is_irap = state->frame->num % cfg->intra_period == 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
state->frame->is_irap = false;
|
state->frame->is_irap =
|
||||||
|
cfg->intra_period > 0 &&
|
||||||
|
(state->frame->poc % cfg->intra_period) == 0;
|
||||||
}
|
}
|
||||||
|
if (state->frame->is_irap) {
|
||||||
// Set slicetype.
|
state->frame->irap_poc = state->frame->poc;
|
||||||
if (state->frame->is_irap || cfg->intra_period == 1) {
|
|
||||||
state->frame->slicetype = KVZ_SLICE_I;
|
|
||||||
} else if (cfg->gop_len > 0 && !cfg->gop_lowdelay) {
|
|
||||||
state->frame->slicetype = KVZ_SLICE_B;
|
|
||||||
} else {
|
|
||||||
state->frame->slicetype = KVZ_SLICE_P;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set POC.
|
|
||||||
if (cfg->intra_period != 1 &&
|
|
||||||
cfg->gop_len > 0 &&
|
|
||||||
!cfg->gop_lowdelay &&
|
|
||||||
state->frame->num > 0)
|
|
||||||
{
|
|
||||||
// Calculate POC according to the global frame counter and GOP
|
|
||||||
// structure.
|
|
||||||
if (cfg->intra_period > 0) {
|
|
||||||
int32_t poc = (state->frame->num - 1) % cfg->intra_period;
|
|
||||||
int poc_offset = cfg->gop[state->frame->gop_offset].poc_offset - 1;
|
|
||||||
state->frame->poc = poc - poc % cfg->gop_len + poc_offset;
|
|
||||||
} else {
|
|
||||||
int32_t poc = state->frame->num;
|
|
||||||
int poc_offset = cfg->gop[state->frame->gop_offset].poc_offset - 1;
|
|
||||||
state->frame->poc = poc - (poc - 1) % cfg->gop_len + poc_offset;
|
|
||||||
}
|
|
||||||
kvz_videoframe_set_poc(state->tile->frame, state->frame->poc);
|
|
||||||
} else if (state->frame->is_irap) {
|
|
||||||
encoder_state_reset_poc(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set pictype.
|
// Set pictype.
|
||||||
if (state->frame->is_irap) {
|
if (state->frame->is_irap) {
|
||||||
if (cfg->gop_len > 0 && !cfg->gop_lowdelay && state->frame->num > 0) {
|
if (state->frame->num == 0 ||
|
||||||
state->frame->pictype = KVZ_NAL_BLA_W_RADL;
|
cfg->intra_period == 1 ||
|
||||||
} else {
|
cfg->gop_len == 0 ||
|
||||||
|
cfg->gop_lowdelay)
|
||||||
|
{
|
||||||
state->frame->pictype = KVZ_NAL_IDR_W_RADL;
|
state->frame->pictype = KVZ_NAL_IDR_W_RADL;
|
||||||
|
} else {
|
||||||
|
state->frame->pictype = KVZ_NAL_CRA_NUT;
|
||||||
}
|
}
|
||||||
state->frame->irap_poc = state->frame->poc;
|
|
||||||
|
|
||||||
} else if (state->frame->poc < state->frame->irap_poc) {
|
} else if (state->frame->poc < state->frame->irap_poc) {
|
||||||
state->frame->pictype = KVZ_NAL_RADL_R;
|
state->frame->pictype = KVZ_NAL_RASL_R;
|
||||||
} else {
|
} else {
|
||||||
state->frame->pictype = KVZ_NAL_TRAIL_R;
|
state->frame->pictype = KVZ_NAL_TRAIL_R;
|
||||||
}
|
}
|
||||||
|
@ -1198,6 +1180,15 @@ static void encoder_state_init_new_frame(encoder_state_t * const state, kvz_pict
|
||||||
encoder_state_remove_refs(state);
|
encoder_state_remove_refs(state);
|
||||||
kvz_encoder_create_ref_lists(state);
|
kvz_encoder_create_ref_lists(state);
|
||||||
|
|
||||||
|
// Set slicetype.
|
||||||
|
if (state->frame->is_irap) {
|
||||||
|
state->frame->slicetype = KVZ_SLICE_I;
|
||||||
|
} else if (state->frame->ref_LX_size[1] > 0) {
|
||||||
|
state->frame->slicetype = KVZ_SLICE_B;
|
||||||
|
} else {
|
||||||
|
state->frame->slicetype = KVZ_SLICE_P;
|
||||||
|
}
|
||||||
|
|
||||||
if (cfg->target_bitrate > 0 && state->frame->num > cfg->owf) {
|
if (cfg->target_bitrate > 0 && state->frame->num > cfg->owf) {
|
||||||
normalize_lcu_weights(state);
|
normalize_lcu_weights(state);
|
||||||
}
|
}
|
||||||
|
@ -1278,6 +1269,7 @@ void kvz_encoder_prepare(encoder_state_t *state)
|
||||||
state->tile->frame->cu_array = kvz_cu_array_alloc(width, height);
|
state->tile->frame->cu_array = kvz_cu_array_alloc(width, height);
|
||||||
|
|
||||||
kvz_image_list_copy_contents(state->frame->ref, prev_state->frame->ref);
|
kvz_image_list_copy_contents(state->frame->ref, prev_state->frame->ref);
|
||||||
|
kvz_encoder_create_ref_lists(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!encoder->cfg.gop_len ||
|
if (!encoder->cfg.gop_len ||
|
||||||
|
|
Loading…
Reference in a new issue