mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-24 02:24:07 +00:00
Moved reference list sorting and parsing to encoder_state_new_frame()
* fixed a bug in reference verification and added an error state
This commit is contained in:
parent
c40ca49b6c
commit
5071b5c990
|
@ -21,6 +21,7 @@
|
|||
#include "encoder_state-bitstream.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "checkpoint.h"
|
||||
#include "encoderstate.h"
|
||||
|
@ -611,13 +612,17 @@ void encoder_state_write_bitstream_slice_header(encoder_state_t * const state)
|
|||
int8_t found = 0;
|
||||
do {
|
||||
delta_poc = state->encoder_control->cfg->gop[state->global->gop_offset].ref_neg[j + poc_shift];
|
||||
for (j = 0; j < state->global->ref->used_size; j++) {
|
||||
if (state->global->ref->images[j]->poc == state->global->poc - delta_poc) {
|
||||
for (int i = 0; i < state->global->ref->used_size; i++) {
|
||||
if (state->global->ref->images[i]->poc == state->global->poc - delta_poc) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
poc_shift++;
|
||||
if (!found) poc_shift++;
|
||||
if (j + poc_shift == ref_negative) {
|
||||
fprintf(stderr, "Failure, reference not found!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} while (!found);
|
||||
}
|
||||
|
||||
|
@ -636,13 +641,17 @@ void encoder_state_write_bitstream_slice_header(encoder_state_t * const state)
|
|||
int8_t found = 0;
|
||||
do {
|
||||
delta_poc = state->encoder_control->cfg->gop[state->global->gop_offset].ref_pos[j + poc_shift];
|
||||
for (j = 0; j < state->global->ref->used_size; j++) {
|
||||
if (state->global->ref->images[j]->poc == state->global->poc + delta_poc) {
|
||||
for (int i = 0; i < state->global->ref->used_size; i++) {
|
||||
if (state->global->ref->images[i]->poc == state->global->poc + delta_poc) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
poc_shift++;
|
||||
if (!found) poc_shift++;
|
||||
if (j + poc_shift == ref_positive) {
|
||||
fprintf(stderr, "Failure, reference not found!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} while (!found);
|
||||
}
|
||||
|
||||
|
|
|
@ -659,6 +659,95 @@ static void encoder_state_encode(encoder_state_t * const main_state) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void encoder_ref_insertion_sort(int reflist[16], int length) {
|
||||
|
||||
for (uint8_t i = 1; i < length; ++i) {
|
||||
const int16_t cur_poc = reflist[i];
|
||||
int16_t j = i;
|
||||
while (j > 0 && cur_poc < reflist[j - 1]) {
|
||||
reflist[j] = reflist[j - 1];
|
||||
--j;
|
||||
}
|
||||
reflist[j] = cur_poc;
|
||||
}
|
||||
}
|
||||
static void encoder_state_ref_sort(encoder_state_t *state) {
|
||||
int j, ref_list[2] = { 0, 0 }, ref_list_poc[2][16];
|
||||
|
||||
// List all pocs of lists
|
||||
for (j = 0; j < state->global->ref->used_size; j++) {
|
||||
if (state->global->ref->images[j]->poc < state->global->poc) {
|
||||
ref_list_poc[0][ref_list[0]] = state->global->ref->images[j]->poc;
|
||||
ref_list[0]++;
|
||||
} else {
|
||||
ref_list_poc[1][ref_list[1]] = state->global->ref->images[j]->poc;
|
||||
ref_list[1]++;
|
||||
}
|
||||
}
|
||||
|
||||
encoder_ref_insertion_sort(ref_list_poc[0], ref_list[0]);
|
||||
encoder_ref_insertion_sort(ref_list_poc[1], ref_list[1]);
|
||||
|
||||
for (j = 0; j < state->global->ref->used_size; j++) {
|
||||
if (state->global->ref->images[j]->poc < state->global->poc) {
|
||||
int idx = ref_list[0];
|
||||
for (int ref_idx = 0; ref_idx < ref_list[0]; ref_idx++) {
|
||||
if (ref_list_poc[0][ref_idx] == state->global->ref->images[j]->poc) {
|
||||
state->global->refmap[j].idx = ref_list[0] - ref_idx - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
state->global->refmap[j].list = 1;
|
||||
|
||||
} else {
|
||||
int idx = ref_list[1];
|
||||
for (int ref_idx = 0; ref_idx < ref_list[1]; ref_idx++) {
|
||||
if (ref_list_poc[1][ref_idx] == state->global->ref->images[j]->poc) {
|
||||
state->global->refmap[j].idx = ref_idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
state->global->refmap[j].list = 2;
|
||||
}
|
||||
state->global->refmap[j].poc = state->global->ref->images[j]->poc;
|
||||
}
|
||||
}
|
||||
|
||||
static void encoder_state_remove_refs(encoder_state_t *state) {
|
||||
const encoder_control_t * const encoder = state->encoder_control;
|
||||
int8_t refnumber = encoder->cfg->ref_frames;
|
||||
if (encoder->cfg->gop_len) {
|
||||
refnumber = encoder->cfg->gop[state->global->gop_offset].ref_neg_count + encoder->cfg->gop[state->global->gop_offset].ref_pos_count;
|
||||
}
|
||||
// Remove the ref pic (if present)
|
||||
while (state->global->ref->used_size > (uint32_t)refnumber) {
|
||||
int8_t ref_to_remove = state->global->ref->used_size - 1;
|
||||
if (encoder->cfg->gop_len) {
|
||||
for (int ref = 0; ref < state->global->ref->used_size; ref++) {
|
||||
uint8_t found = 0;
|
||||
for (int i = 0; i < encoder->cfg->gop[state->global->gop_offset].ref_neg_count; i++) {
|
||||
if (state->global->ref->images[ref]->poc == state->global->poc - encoder->cfg->gop[state->global->gop_offset].ref_neg[i]) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
for (int i = 0; i < encoder->cfg->gop[state->global->gop_offset].ref_pos_count; i++) {
|
||||
if (state->global->ref->images[ref]->poc == state->global->poc + encoder->cfg->gop[state->global->gop_offset].ref_pos[i]) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
image_list_rem(state->global->ref, ref);
|
||||
ref--;
|
||||
}
|
||||
}
|
||||
} else image_list_rem(state->global->ref, ref_to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
static void encoder_state_clear_refs(encoder_state_t *state) {
|
||||
int i;
|
||||
|
||||
|
@ -681,7 +770,14 @@ static void encoder_state_new_frame(encoder_state_t * const state) {
|
|||
const int is_i_radl = (encoder->cfg->intra_period == 1 && state->global->frame % 2 == 0);
|
||||
const int is_p_radl = (encoder->cfg->intra_period > 1 && (state->global->frame % encoder->cfg->intra_period) == 0);
|
||||
state->global->is_radl_frame = is_first_frame || is_i_radl || is_p_radl;
|
||||
|
||||
|
||||
if (state->global->frame && encoder->cfg->gop_len) {
|
||||
// Calculate POC according to the global frame counter and GOP structure
|
||||
state->global->poc = (state->global->frame - 1) - (state->global->frame - 1) % encoder->cfg->gop_len +
|
||||
encoder->cfg->gop[state->global->gop_offset].poc_offset;
|
||||
videoframe_set_poc(state->tile->frame, state->global->poc);
|
||||
}
|
||||
|
||||
if (state->global->is_radl_frame) {
|
||||
// Clear the reference list
|
||||
encoder_state_clear_refs(state);
|
||||
|
@ -689,6 +785,8 @@ static void encoder_state_new_frame(encoder_state_t * const state) {
|
|||
state->global->slicetype = SLICE_I;
|
||||
state->global->pictype = NAL_IDR_W_RADL;
|
||||
} else {
|
||||
encoder_state_remove_refs(state);
|
||||
encoder_state_ref_sort(state);
|
||||
state->global->slicetype = encoder->cfg->intra_period==1 ? SLICE_I : (state->encoder_control->cfg->gop_len?SLICE_B:SLICE_P);
|
||||
state->global->pictype = NAL_TRAIL_R;
|
||||
}
|
||||
|
@ -827,16 +925,20 @@ int read_one_frame(FILE* file, const encoder_state_t * const state)
|
|||
unsigned array_height = state->tile->frame->height;
|
||||
|
||||
// storing GOP pictures
|
||||
static int8_t gop_init = 0;
|
||||
static int8_t gop_pictures_available = 0;
|
||||
static videoframe_t gop_pictures[MAX_GOP];
|
||||
static int8_t gop_skip_frames = 0;
|
||||
static int8_t gop_skipped = 0;
|
||||
|
||||
// On first frame, init structures
|
||||
if (!state->global->frame) {
|
||||
// Initialize GOP structure when gop is enabled and not initialized
|
||||
if (state->encoder_control->cfg->gop_len && !gop_init) {
|
||||
int i;
|
||||
for (i = 0; i < state->encoder_control->cfg->gop_len; i++) {
|
||||
gop_pictures[i].source = image_alloc(array_width, array_height, 0);
|
||||
}
|
||||
state->global->gop_offset = 0;
|
||||
gop_init = 1;
|
||||
}
|
||||
|
||||
// If GOP is present but no pictures found
|
||||
|
@ -883,13 +985,16 @@ int read_one_frame(FILE* file, const encoder_state_t * const state)
|
|||
|
||||
// If GOP is present, fetch the data from our GOP picture buffer
|
||||
if (state->global->frame && state->encoder_control->cfg->gop_len) {
|
||||
int cur_gop_idx = state->encoder_control->cfg->gop_len - (gop_pictures_available + gop_skip_frames);
|
||||
int cur_gop_idx = state->encoder_control->cfg->gop_len - (gop_pictures_available + gop_skip_frames) + gop_skipped;
|
||||
int cur_gop = state->encoder_control->cfg->gop[cur_gop_idx].poc_offset - 1;
|
||||
// Special case when end of the sequence and not all pictures are available
|
||||
if (gop_skip_frames) {
|
||||
for (;cur_gop >= state->encoder_control->cfg->gop_len - gop_skip_frames; cur_gop_idx++) {
|
||||
if (gop_skip_frames && cur_gop >= state->encoder_control->cfg->gop_len - gop_skip_frames) {
|
||||
for (; cur_gop >= state->encoder_control->cfg->gop_len - gop_skip_frames; cur_gop_idx++) {
|
||||
cur_gop = state->encoder_control->cfg->gop[cur_gop_idx].poc_offset - 1;
|
||||
gop_skipped++;
|
||||
}
|
||||
cur_gop_idx--;
|
||||
gop_skipped--;
|
||||
}
|
||||
state->global->gop_offset = cur_gop_idx;
|
||||
memcpy(state->tile->frame->source->y, gop_pictures[cur_gop].source->y, width * height);
|
||||
|
@ -985,95 +1090,6 @@ void encoder_compute_stats(encoder_state_t *state, FILE * const recout, uint32_t
|
|||
*bitstream_length += state->stats_bitstream_length;
|
||||
}
|
||||
|
||||
static void encoder_ref_insertion_sort(int reflist[16], int length) {
|
||||
|
||||
for (uint8_t i = 1; i < length; ++i) {
|
||||
const int16_t cur_poc = reflist[i];
|
||||
int16_t j = i;
|
||||
while (j > 0 && cur_poc < reflist[j - 1]) {
|
||||
reflist[j] = reflist[j - 1];
|
||||
--j;
|
||||
}
|
||||
reflist[j] = cur_poc;
|
||||
}
|
||||
}
|
||||
static void encoder_state_ref_sort(encoder_state_t *state) {
|
||||
int j, ref_list[2] = { 0, 0 },ref_list_poc[2][16];
|
||||
|
||||
// List all pocs of lists
|
||||
for (j = 0; j < state->global->ref->used_size; j++) {
|
||||
if (state->global->ref->images[j]->poc < state->global->poc) {
|
||||
ref_list_poc[0][ref_list[0]] = state->global->ref->images[j]->poc;
|
||||
ref_list[0]++;
|
||||
} else {
|
||||
ref_list_poc[1][ref_list[1]] = state->global->ref->images[j]->poc;
|
||||
ref_list[1]++;
|
||||
}
|
||||
}
|
||||
|
||||
encoder_ref_insertion_sort(ref_list_poc[0], ref_list[0]);
|
||||
encoder_ref_insertion_sort(ref_list_poc[1], ref_list[1]);
|
||||
|
||||
for (j = 0; j < state->global->ref->used_size; j++) {
|
||||
if (state->global->ref->images[j]->poc < state->global->poc) {
|
||||
int idx = ref_list[0];
|
||||
for (int ref_idx = 0; ref_idx < ref_list[0]; ref_idx++) {
|
||||
if (ref_list_poc[0][ref_idx] == state->global->ref->images[j]->poc) {
|
||||
state->global->refmap[j].idx = ref_list[0] - ref_idx - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
state->global->refmap[j].list = 1;
|
||||
|
||||
} else {
|
||||
int idx = ref_list[1];
|
||||
for (int ref_idx = 0; ref_idx < ref_list[1]; ref_idx++) {
|
||||
if (ref_list_poc[1][ref_idx] == state->global->ref->images[j]->poc) {
|
||||
state->global->refmap[j].idx = ref_idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
state->global->refmap[j].list = 2;
|
||||
}
|
||||
state->global->refmap[j].poc = state->global->ref->images[j]->poc;
|
||||
}
|
||||
}
|
||||
|
||||
static void encoder_state_remove_refs(encoder_state_t *state) {
|
||||
const encoder_control_t * const encoder = state->encoder_control;
|
||||
int8_t refnumber = encoder->cfg->ref_frames;
|
||||
if (encoder->cfg->gop_len) {
|
||||
refnumber = encoder->cfg->gop[state->global->gop_offset].ref_neg_count + encoder->cfg->gop[state->global->gop_offset].ref_pos_count;
|
||||
}
|
||||
// Remove the ref pic (if present)
|
||||
while (state->global->ref->used_size > (uint32_t)refnumber) {
|
||||
int8_t ref_to_remove = state->global->ref->used_size - 1;
|
||||
if (encoder->cfg->gop_len) {
|
||||
for (int ref = 0; ref < state->global->ref->used_size; ref++) {
|
||||
uint8_t found = 0;
|
||||
for (int i = 0; i < encoder->cfg->gop[state->global->gop_offset].ref_neg_count; i++) {
|
||||
if (state->global->ref->images[ref]->poc == state->global->poc - encoder->cfg->gop[state->global->gop_offset].ref_neg[i]) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
for (int i = 0; i < encoder->cfg->gop[state->global->gop_offset].ref_pos_count; i++) {
|
||||
if (state->global->ref->images[ref]->poc == state->global->poc + encoder->cfg->gop[state->global->gop_offset].ref_pos[i]) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
image_list_rem(state->global->ref, ref);
|
||||
ref--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else image_list_rem(state->global->ref, ref_to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
void encoder_next_frame(encoder_state_t *state) {
|
||||
const encoder_control_t * const encoder = state->encoder_control;
|
||||
int8_t use_as_ref[8] = { 1, 0, 1, 0, 1, 0, 1, 0 };
|
||||
|
@ -1097,12 +1113,6 @@ void encoder_next_frame(encoder_state_t *state) {
|
|||
//We have a "real" previous encoder
|
||||
state->global->frame = state->previous_encoder_state->global->frame + 1;
|
||||
state->global->poc = state->previous_encoder_state->global->poc + 1;
|
||||
if (encoder->cfg->gop_len) {
|
||||
// Calculate POC according to the global frame counter and GOP structure
|
||||
state->global->poc = state->previous_encoder_state->global->frame -
|
||||
state->global->gop_offset +
|
||||
encoder->cfg->gop[state->global->gop_offset].poc_offset;
|
||||
}
|
||||
|
||||
image_free(state->tile->frame->rec);
|
||||
cu_array_free(state->tile->frame->cu_array);
|
||||
|
@ -1116,31 +1126,20 @@ void encoder_next_frame(encoder_state_t *state) {
|
|||
}
|
||||
videoframe_set_poc(state->tile->frame, state->global->poc);
|
||||
image_list_copy_contents(state->global->ref, state->previous_encoder_state->global->ref);
|
||||
|
||||
if (!encoder->cfg->gop_len || !state->previous_encoder_state->global->poc || encoder->cfg->gop[state->global->gop_offset].is_ref) {
|
||||
image_list_add(state->global->ref, state->previous_encoder_state->tile->frame->rec, state->previous_encoder_state->tile->frame->cu_array);
|
||||
}
|
||||
encoder_state_remove_refs(state);
|
||||
encoder_state_ref_sort(state);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
state->global->frame++;
|
||||
state->global->poc++;
|
||||
if (encoder->cfg->gop_len) {
|
||||
// Calculate POC according to the global frame counter and GOP structure
|
||||
state->global->poc = state->global->frame - 1 -
|
||||
(state->global->gop_offset) +
|
||||
encoder->cfg->gop[state->global->gop_offset].poc_offset;
|
||||
}
|
||||
|
||||
if (!encoder->cfg->gop_len || !lastpoc || encoder->cfg->gop[state->global->gop_offset].is_ref) {
|
||||
if (!encoder->cfg->gop_len || !state->previous_encoder_state->global->poc || encoder->cfg->gop[state->global->gop_offset].is_ref) {
|
||||
// Add current reconstructed picture as reference
|
||||
image_list_add(state->global->ref, state->tile->frame->rec, state->tile->frame->cu_array);
|
||||
}
|
||||
encoder_state_remove_refs(state);
|
||||
encoder_state_ref_sort(state);
|
||||
|
||||
//Remove current reconstructed picture, and alloc a new one
|
||||
image_free(state->tile->frame->rec);
|
||||
|
|
Loading…
Reference in a new issue