Move OWF logic and CLI stuff out of encoder_compute_stats.

- CLI stuff is moved to either cli-module or to main function.
- OWF stuff is made more explicit by counting the frames instead of
  communicating through encoder_state_t.stats_done.
This commit is contained in:
Ari Koivula 2015-05-14 18:33:57 +03:00 committed by Arttu Ylä-Outinen
parent ea50d03e52
commit 5c28745457
5 changed files with 84 additions and 73 deletions

View file

@ -27,6 +27,8 @@
#include <stdio.h> #include <stdio.h>
#include "encoderstate.h"
void print_version(void) void print_version(void)
{ {
@ -146,3 +148,42 @@ void print_help(void)
" -w, --width : Width of input in pixels\n" " -w, --width : Width of input in pixels\n"
" -h, --height : Height of input in pixels\n"); " -h, --height : Height of input in pixels\n");
} }
void print_frame_info(encoder_state_t *state, double frame_psnr[3])
{
fprintf(stderr, "POC %4d QP %2d (%c-frame) %10d bits PSNR: %2.4f %2.4f %2.4f",
state->global->poc,
state->global->QP,
"BPI"[state->global->slicetype % 3], state->stats_bitstream_length << 3,
frame_psnr[0], frame_psnr[1], frame_psnr[2]);
// Print reference picture lists
if (state->global->slicetype != SLICE_I) {
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]);
fprintf(stderr, " [L0 ");
for (j = ref_list[0] - 1; j >= 0; j--) {
fprintf(stderr, "%d ", ref_list_poc[0][j]);
}
fprintf(stderr, "] [L1 ");
for (j = 0; j < ref_list[1]; j++) {
fprintf(stderr, "%d ", ref_list_poc[1][j]);
}
fprintf(stderr, "]");
}
fprintf(stderr, "\n");
}

View file

@ -30,5 +30,6 @@
void print_version(void); void print_version(void);
void print_help(void); void print_help(void);
void print_frame_info(encoder_state_t *state, double frame_psnr[3]);
#endif #endif

View file

@ -48,6 +48,7 @@
#include "strategyselector.h" #include "strategyselector.h"
#include "cli.h" #include "cli.h"
/** /**
* \brief Program main function. * \brief Program main function.
* \param argc Argument count from commandline * \param argc Argument count from commandline
@ -60,8 +61,6 @@ int main(int argc, char *argv[])
FILE *input = NULL; //!< input file (YUV) FILE *input = NULL; //!< input file (YUV)
FILE *output = NULL; //!< output file (HEVC NAL stream) FILE *output = NULL; //!< output file (HEVC NAL stream)
encoder_control_t encoder; encoder_control_t encoder;
double psnr[3] = { 0.0, 0.0, 0.0 };
uint32_t stat_frames = 0;
uint64_t curpos = 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();
@ -246,25 +245,22 @@ int main(int argc, char *argv[])
//Initial frame //Initial frame
encoder_states[current_encoder_state].global->frame = -1; encoder_states[current_encoder_state].global->frame = -1;
// Only the code that handles conformance window coding needs to know
// the real dimensions. As a quick fix for broken non-multiple of 8 videos,
// change the input values here to be the real values. For a real fix
// encoder.in probably needs to be merged into cfg.
// The real fix would be: never go dig in cfg
//cfg->width = encoder.in.width;
//cfg->height = encoder.in.height;
GET_TIME(&encoding_start_real_time); GET_TIME(&encoding_start_real_time);
encoding_start_cpu_time = clock(); encoding_start_cpu_time = clock();
uint64_t bitstream_length = 0; uint64_t bitstream_length = 0;
uint32_t frames_started = 0;
uint32_t frames_done = 0;
double psnr_sum[3] = { 0.0, 0.0, 0.0 };
// 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 - 1) { while (cfg->frames == 0 || frames_started < cfg->frames) {
encoder_state_t *state = &encoder_states[current_encoder_state];
// 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.
if (encoder_states[current_encoder_state].global->frame == 0 && cfg->seek > 0) { if (frames_started == 0 && cfg->seek > 0) {
int frame_bytes = cfg->width * cfg->height * 3 / 2; int frame_bytes = cfg->width * cfg->height * 3 / 2;
int error = 0; int error = 0;
@ -286,19 +282,23 @@ int main(int argc, char *argv[])
encoding_start_cpu_time = clock(); encoding_start_cpu_time = clock();
} }
//Compute stats // If we have started as many frames as we are going to encode in parallel, wait for the first one we started encoding to finish before
encoder_compute_stats(&encoder_states[current_encoder_state], recout, &stat_frames, psnr, &bitstream_length); // encoding more.
if (frames_started > cfg->owf) {
double frame_psnr[3] = { 0.0, 0.0, 0.0 };
encoder_compute_stats(&encoder_states[current_encoder_state], recout, frame_psnr, &bitstream_length);
frames_done += 1;
psnr_sum[0] += frame_psnr[0];
psnr_sum[1] += frame_psnr[1];
psnr_sum[2] += frame_psnr[2];
print_frame_info(state, frame_psnr);
}
frames_started += 1;
//Clear encoder //Clear encoder
encoder_next_frame(&encoder_states[current_encoder_state]); encoder_next_frame(&encoder_states[current_encoder_state]);
//Abort if enough frames
if (cfg->frames && encoder_states[current_encoder_state].global->frame >= cfg->frames) {
//Ignore this frame, which is not valid...
encoder_states[current_encoder_state].stats_done = 1;
break;
}
CHECKPOINT_MARK("read source frame: %d", encoder_states[current_encoder_state].global->frame + cfg->seek); CHECKPOINT_MARK("read source frame: %d", encoder_states[current_encoder_state].global->frame + cfg->seek);
// Read one frame from the input // Read one frame from the input
@ -322,8 +322,18 @@ int main(int argc, char *argv[])
{ {
int first_enc = current_encoder_state; int first_enc = current_encoder_state;
do { do {
double frame_psnr[3] = { 0.0, 0.0, 0.0 };
current_encoder_state = (current_encoder_state + 1) % (encoder.owf + 1); current_encoder_state = (current_encoder_state + 1) % (encoder.owf + 1);
encoder_compute_stats(&encoder_states[current_encoder_state], recout, &stat_frames, psnr, &bitstream_length); encoder_state_t *state = &encoder_states[current_encoder_state];
if (!state->stats_done) {
encoder_compute_stats(state, recout, frame_psnr, &bitstream_length);
print_frame_info(state, frame_psnr);
frames_done += 1;
psnr_sum[0] += frame_psnr[0];
psnr_sum[1] += frame_psnr[1];
psnr_sum[2] += frame_psnr[2];
}
} while (current_encoder_state != first_enc); } while (current_encoder_state != first_enc);
} }
@ -338,8 +348,8 @@ int main(int argc, char *argv[])
// 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", fprintf(stderr, " Processed %d frames, %10llu bits AVG PSNR: %2.4f %2.4f %2.4f\n",
stat_frames, (long long unsigned int)bitstream_length * 8, frames_done, (long long unsigned int)bitstream_length * 8,
psnr[0] / stat_frames, psnr[1] / stat_frames, psnr[2] / stat_frames); psnr_sum[0] / frames_done, psnr_sum[1] / frames_done, psnr_sum[2] / frames_done);
fprintf(stderr, " Total CPU time: %.3f s.\n", ((float)(clock() - start_time)) / CLOCKS_PER_SEC); fprintf(stderr, " Total CPU time: %.3f s.\n", ((float)(clock() - start_time)) / CLOCKS_PER_SEC);
{ {
@ -348,7 +358,7 @@ int main(int argc, char *argv[])
fprintf(stderr, " Encoding time: %.3f s.\n", encoding_time); fprintf(stderr, " Encoding time: %.3f s.\n", encoding_time);
fprintf(stderr, " Encoding wall time: %.3f s.\n", wall_time); fprintf(stderr, " Encoding wall time: %.3f s.\n", wall_time);
fprintf(stderr, " Encoding CPU usage: %.2f%%\n", encoding_time/wall_time*100.f); fprintf(stderr, " Encoding CPU usage: %.2f%%\n", encoding_time/wall_time*100.f);
fprintf(stderr, " FPS: %.2f\n", ((double)stat_frames)/wall_time); fprintf(stderr, " FPS: %.2f\n", ((double)frames_done)/wall_time);
} }
fclose(input); fclose(input);

View file

@ -623,7 +623,7 @@ static void encoder_state_encode(encoder_state_t * const main_state) {
} }
static void encoder_ref_insertion_sort(int reflist[16], int length) { void encoder_ref_insertion_sort(int reflist[16], int length) {
for (uint8_t i = 1; i < length; ++i) { for (uint8_t i = 1; i < length; ++i) {
const int16_t cur_poc = reflist[i]; const int16_t cur_poc = reflist[i];
@ -1016,14 +1016,12 @@ int read_one_frame(FILE* file, const encoder_state_t * const state)
return 1; return 1;
} }
void encoder_compute_stats(encoder_state_t *state, FILE * const recout, uint32_t *stat_frames, double psnr[3], uint64_t *bitstream_length) { void encoder_compute_stats(encoder_state_t *state, FILE * const recout, double frame_psnr[3], uint64_t *bitstream_length) {
const encoder_control_t * const encoder = state->encoder_control; const encoder_control_t * const encoder = state->encoder_control;
if (state->stats_done) return; if (state->stats_done) return;
state->stats_done = 1; state->stats_done = 1;
++(*stat_frames);
//Blocking call //Blocking call
threadqueue_waitfor(encoder->threadqueue, state->tqj_bitstream_written); threadqueue_waitfor(encoder->threadqueue, state->tqj_bitstream_written);
@ -1050,48 +1048,7 @@ void encoder_compute_stats(encoder_state_t *state, FILE * const recout, uint32_t
} }
} }
// PSNR calculations videoframe_compute_psnr(state->tile->frame, frame_psnr);
{
double temp_psnr[3];
videoframe_compute_psnr(state->tile->frame, temp_psnr);
fprintf(stderr, "POC %4d QP %2d (%c-frame) %10d bits PSNR: %2.4f %2.4f %2.4f", state->global->poc,
state->global->QP,
"BPI"[state->global->slicetype%3], state->stats_bitstream_length<<3,
temp_psnr[0], temp_psnr[1], temp_psnr[2]);
// Print reference picture lists
if (state->global->slicetype != SLICE_I) {
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]);
fprintf(stderr, " [L0 ");
for (j = ref_list[0]-1; j >= 0; j--) {
fprintf(stderr, "%d ", ref_list_poc[0][j]);
}
fprintf(stderr, "] [L1 ");
for (j = 0; j < ref_list[1]; j++) {
fprintf(stderr, "%d ", ref_list_poc[1][j]);
}
fprintf(stderr, "]");
}
fprintf(stderr, "\n");
// Increment total PSNR
psnr[0] += temp_psnr[0];
psnr[1] += temp_psnr[1];
psnr[2] += temp_psnr[2];
}
*bitstream_length += state->stats_bitstream_length; *bitstream_length += state->stats_bitstream_length;
} }

View file

@ -197,7 +197,7 @@ typedef struct encoder_state_t {
void encode_one_frame(encoder_state_t *state); void encode_one_frame(encoder_state_t *state);
int read_one_frame(FILE* file, const encoder_state_t *state); int read_one_frame(FILE* file, const encoder_state_t *state);
void encoder_compute_stats(encoder_state_t *state, FILE * const recout, uint32_t *stat_frames, double psnr[3], uint64_t *bitstream_length); void encoder_compute_stats(encoder_state_t *state, FILE * const recout, double psnr[3], uint64_t *bitstream_length);
void encoder_next_frame(encoder_state_t *state); void encoder_next_frame(encoder_state_t *state);
@ -219,6 +219,8 @@ int encoder_state_match_children_of_previous_frame(encoder_state_t * const state
coeff_scan_order_t get_scan_order(int8_t cu_type, int intra_mode, int depth); coeff_scan_order_t get_scan_order(int8_t cu_type, int intra_mode, int depth);
void encoder_ref_insertion_sort(int reflist[16], int length);
static const uint8_t g_group_idx[32] = { static const uint8_t g_group_idx[32] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 0, 1, 2, 3, 4, 4, 5, 5, 6, 6,
6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,