Fix statistics with OWF

This commit is contained in:
Laurent Fasnacht 2014-06-16 09:22:59 +02:00
parent 0522a3d8e5
commit bf6024734a
4 changed files with 75 additions and 46 deletions

View file

@ -58,8 +58,8 @@ int main(int argc, char *argv[])
FILE *output = NULL; //!< output file (HEVC NAL stream) FILE *output = NULL; //!< output file (HEVC NAL stream)
encoder_control encoder; encoder_control encoder;
double psnr[3] = { 0.0, 0.0, 0.0 }; double psnr[3] = { 0.0, 0.0, 0.0 };
uint64_t curpos = 0; uint32_t stat_frames = 0;
uint64_t lastpos = 0; uint64_t curpos = 0;
FILE *recout = NULL; //!< reconstructed YUV output, --debug FILE *recout = NULL; //!< reconstructed YUV output, --debug
clock_t start_time = clock(); clock_t start_time = clock();
@ -313,9 +313,6 @@ int main(int argc, char *argv[])
// Start coding cycle while data on input and not on the last frame // Start coding cycle while data on input and not on the last frame
while(!cfg->frames || encoder_states[current_encoder_state].global->frame < cfg->frames) { while(!cfg->frames || encoder_states[current_encoder_state].global->frame < cfg->frames) {
int32_t diff;
double temp_psnr[3];
// Skip '--seek' frames before input. // Skip '--seek' frames before input.
// This block can be moved outside this while loop when there is a // This block can be moved outside this while loop when there is a
// mechanism to skip the while loop on error. // mechanism to skip the while loop on error.
@ -339,6 +336,9 @@ int main(int argc, char *argv[])
} }
} }
//Compute stats
encoder_compute_stats(&encoder_states[current_encoder_state], recout, &stat_frames, psnr);
//Clear encoder //Clear encoder
encoder_next_frame(&encoder_states[current_encoder_state]); encoder_next_frame(&encoder_states[current_encoder_state]);
@ -356,46 +356,8 @@ int main(int argc, char *argv[])
if (cfg->debug != NULL) {
const videoframe * const frame = encoder_states[current_encoder_state].tile->frame;
// Write reconstructed frame out.
// Use conformance-window dimensions instead of internal ones.
const int width = frame->width;
const int out_width = encoder.in.real_width;
const int out_height = encoder.in.real_height;
int y;
const pixel *y_rec = frame->rec->y;
const pixel *u_rec = frame->rec->u;
const pixel *v_rec = frame->rec->v;
for (y = 0; y < out_height; ++y) {
fwrite(&y_rec[y * width], sizeof(*y_rec), out_width, recout);
}
for (y = 0; y < out_height / 2; ++y) {
fwrite(&u_rec[y * width / 2], sizeof(*u_rec), out_width / 2, recout);
}
for (y = 0; y < out_height / 2; ++y) {
fwrite(&v_rec[y * width / 2], sizeof(*v_rec), out_width / 2, recout);
}
}
// Calculate the bytes pushed to output for this frame
fgetpos(output,(fpos_t*)&curpos);
diff = (int32_t)(curpos-lastpos);
lastpos = curpos;
//FIXME Stats are completely broken!!! //FIXME Stats are completely broken!!!
// PSNR calculations
videoframe_compute_psnr(encoder_states[current_encoder_state].tile->frame, temp_psnr);
fprintf(stderr, "POC %4d (%c-frame) %10d bits PSNR: %2.4f %2.4f %2.4f\n", encoder_states[current_encoder_state].global->frame,
"BPI"[encoder_states[current_encoder_state].global->slicetype%3], diff<<3,
temp_psnr[0], temp_psnr[1], temp_psnr[2]);
// Increment total PSNR
psnr[0] += temp_psnr[0];
psnr[1] += temp_psnr[1];
psnr[2] += temp_psnr[2];
//Stop otherwise we will end up doing too much work //Stop otherwise we will end up doing too much work
if (encoder_states[current_encoder_state].global->frame >= cfg->frames - 1) { if (encoder_states[current_encoder_state].global->frame >= cfg->frames - 1) {
@ -404,14 +366,25 @@ int main(int argc, char *argv[])
//Switch to the next encoder //Switch to the next encoder
current_encoder_state = (current_encoder_state + 1) % (encoder.owf + 1); current_encoder_state = (current_encoder_state + 1) % (encoder.owf + 1);
} }
//Compute stats for the remaining encoders
{
int first_enc = current_encoder_state;
do {
current_encoder_state = (current_encoder_state + 1) % (encoder.owf + 1);
encoder_compute_stats(&encoder_states[current_encoder_state], recout, &stat_frames, psnr);
} while (current_encoder_state != first_enc);
}
threadqueue_flush(encoder.threadqueue); threadqueue_flush(encoder.threadqueue);
// Coding finished // Coding finished
fgetpos(output,(fpos_t*)&curpos); fgetpos(output,(fpos_t*)&curpos);
// Print statistics of the coding // Print statistics of the coding
fprintf(stderr, " Processed %d frames, %10llu bits AVG PSNR: %2.4f %2.4f %2.4f\n", encoder_states[current_encoder_state].global->frame, (long long unsigned int) curpos<<3, fprintf(stderr, " Processed %d frames, %10llu bits AVG PSNR: %2.4f %2.4f %2.4f\n", stat_frames, (long long unsigned int) curpos<<3,
psnr[0] / encoder_states[current_encoder_state].global->frame, psnr[1] / encoder_states[current_encoder_state].global->frame, psnr[2] / encoder_states[current_encoder_state].global->frame); psnr[0] / stat_frames, psnr[1] / stat_frames, psnr[2] / stat_frames);
fprintf(stderr, " Total time: %.3f s.\n", ((float)(clock() - start_time)) / CLOCKS_PER_SEC); fprintf(stderr, " Total time: %.3f s.\n", ((float)(clock() - start_time)) / CLOCKS_PER_SEC);
fclose(input); fclose(input);

View file

@ -286,6 +286,7 @@ int encoder_state_init(encoder_state * const child_state, encoder_state * const
child_state->children[0].encoder_control = NULL; child_state->children[0].encoder_control = NULL;
child_state->tqj_bitstream_written = NULL; child_state->tqj_bitstream_written = NULL;
child_state->tqj_recon_done = NULL; child_state->tqj_recon_done = NULL;
child_state->stats_done = 1; //It avoids printing meaningless stats at the beginning
if (!parent_state) { if (!parent_state) {
const encoder_control * const encoder = child_state->encoder_control; const encoder_control * const encoder = child_state->encoder_control;

View file

@ -782,6 +782,58 @@ int read_one_frame(FILE* file, const encoder_state * const encoder_state)
return 1; return 1;
} }
void encoder_compute_stats(encoder_state *encoder_state, FILE * const recout, uint32_t *stat_frames, double psnr[3]) {
const encoder_control * const encoder = encoder_state->encoder_control;
if (encoder_state->stats_done) return;
encoder_state->stats_done = 1;
++(*stat_frames);
//Blocking call
threadqueue_waitfor(encoder->threadqueue, encoder_state->tqj_bitstream_written);
if (recout) {
const videoframe * const frame = encoder_state->tile->frame;
// Write reconstructed frame out.
// Use conformance-window dimensions instead of internal ones.
const int width = frame->width;
const int out_width = encoder->in.real_width;
const int out_height = encoder->in.real_height;
int y;
const pixel *y_rec = frame->rec->y;
const pixel *u_rec = frame->rec->u;
const pixel *v_rec = frame->rec->v;
for (y = 0; y < out_height; ++y) {
fwrite(&y_rec[y * width], sizeof(*y_rec), out_width, recout);
}
for (y = 0; y < out_height / 2; ++y) {
fwrite(&u_rec[y * width / 2], sizeof(*u_rec), out_width / 2, recout);
}
for (y = 0; y < out_height / 2; ++y) {
fwrite(&v_rec[y * width / 2], sizeof(*v_rec), out_width / 2, recout);
}
}
// PSNR calculations
{
int32_t diff=0; //FIXME: get the correct length of bitstream
double temp_psnr[3];
videoframe_compute_psnr(encoder_state->tile->frame, temp_psnr);
fprintf(stderr, "POC %4d (%c-frame) %10d bits PSNR: %2.4f %2.4f %2.4f\n", encoder_state->global->frame,
"BPI"[encoder_state->global->slicetype%3], diff<<3,
temp_psnr[0], temp_psnr[1], temp_psnr[2]);
// Increment total PSNR
psnr[0] += temp_psnr[0];
psnr[1] += temp_psnr[1];
psnr[2] += temp_psnr[2];
}
}
void encoder_next_frame(encoder_state *encoder_state) { void encoder_next_frame(encoder_state *encoder_state) {
const encoder_control * const encoder = encoder_state->encoder_control; const encoder_control * const encoder = encoder_state->encoder_control;
@ -789,7 +841,7 @@ void encoder_next_frame(encoder_state *encoder_state) {
//Blocking call //Blocking call
threadqueue_waitfor(encoder->threadqueue, encoder_state->tqj_bitstream_written); threadqueue_waitfor(encoder->threadqueue, encoder_state->tqj_bitstream_written);
//FIXME FIXME FIXME Compute statistics here encoder_state->stats_done = 0;
if (encoder_state->global->frame == -1) { if (encoder_state->global->frame == -1) {
//We're at the first frame, so don't care about all this stuff; //We're at the first frame, so don't care about all this stuff;

View file

@ -162,6 +162,8 @@ typedef struct encoder_state {
bitstream stream; bitstream stream;
cabac_data cabac; cabac_data cabac;
int stats_done;
//Jobs to wait for //Jobs to wait for
threadqueue_job * tqj_recon_done; //Reconstruction is done threadqueue_job * tqj_recon_done; //Reconstruction is done
threadqueue_job * tqj_bitstream_written; //Bitstream is written threadqueue_job * tqj_bitstream_written; //Bitstream is written
@ -172,6 +174,7 @@ typedef struct encoder_state {
void encode_one_frame(encoder_state *encoder_state); void encode_one_frame(encoder_state *encoder_state);
int read_one_frame(FILE* file, const encoder_state *encoder); int read_one_frame(FILE* file, const encoder_state *encoder);
void encoder_compute_stats(encoder_state *encoder_state, FILE * const recout, uint32_t *stat_frames, double psnr[3]);
void encoder_next_frame(encoder_state *encoder_state); void encoder_next_frame(encoder_state *encoder_state);