From 4e5326d3d521e810ea0e89eee2354ae08a991a47 Mon Sep 17 00:00:00 2001 From: Ari Koivula Date: Tue, 19 May 2015 17:48:37 +0300 Subject: [PATCH] Move encoding to API. - Api->encoder_encode can now be called repeatedly to start encoder jobs and to retrieve the results. Conflicts: src/encmain.c --- src/encmain.c | 28 ++++++++++------------------ src/kvazaar.c | 25 ++++++++++++++++++++++++- src/kvazaar.h | 7 ++++--- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/encmain.c b/src/encmain.c index f39836e8..79a6edef 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -203,7 +203,6 @@ int main(int argc, char *argv[]) // Start coding cycle while data on input and not on the last frame encoder_state_t *state = &enc->states[current_encoder_state]; while (cfg->frames == 0 || frames_started < cfg->frames) { - image_t *img_out = NULL; frames_started += 1; @@ -223,24 +222,11 @@ int main(int argc, char *argv[]) break; } - encoder_next_frame(&enc->states[current_encoder_state], img_in); + image_t *img_out = NULL; + api->encoder_encode(enc, img_in, &img_out, NULL); - CHECKPOINT_MARK("read source frame: %d", encoder_states[current_encoder_state].global->frame + cfg->seek); - - // The actual coding happens here, after this function we have a coded frame - encode_one_frame(&enc->states[current_encoder_state]); - - //Switch to the next encoder - current_encoder_state = (current_encoder_state + 1) % (encoder->owf + 1); - state = &enc->states[current_encoder_state]; - - if (frames_started >= enc->num_encoder_states && !state->stats_done) { - threadqueue_waitfor(encoder->threadqueue, state->tqj_bitstream_written); - img_out = image_make_subimage(state->tile->frame->rec, 0, 0, state->tile->frame->width, state->tile->frame->height); - } - - // If all frame encoders are in use, wait for the next encoder to finish. if (img_out != NULL) { + state = &enc->states[enc->cur_state_num]; double frame_psnr[3] = { 0.0, 0.0, 0.0 }; encoder_compute_stats(state, recout, frame_psnr, &bitstream_length); @@ -262,14 +248,20 @@ int main(int argc, char *argv[]) do { double frame_psnr[3] = { 0.0, 0.0, 0.0 }; encoder_state_t *state = &enc->states[current_encoder_state]; + image_t *img_out = NULL; + api->encoder_encode(enc, NULL, &img_out, NULL); + + if (img_out != NULL) { + encoder_state_t *state = &enc->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]; + + image_free(img_out); } current_encoder_state = (current_encoder_state + 1) % (encoder->owf + 1); diff --git a/src/kvazaar.c b/src/kvazaar.c index c18f920b..3e7efd15 100644 --- a/src/kvazaar.c +++ b/src/kvazaar.c @@ -26,6 +26,7 @@ #include "encoder.h" #include "strategyselector.h" #include "encoderstate.h" +#include "checkpoint.h" static void kvazaar_close(kvz_encoder *encoder) @@ -70,6 +71,7 @@ static kvz_encoder * kvazaar_open(config_t *cfg) encoder->num_encoder_states = cfg->owf + 1; encoder->cur_state_num = 0; + encoder->frames_started = 0; encoder->states = MALLOC(encoder_state_t, encoder->num_encoder_states); if (!encoder->states) { goto kvazaar_open_failure; @@ -104,8 +106,29 @@ kvazaar_open_failure: } -static int kvazaar_encode(kvz_encoder *encoder, kvz_picture *pic_in, kvz_picture *pic_out, kvz_payload **payload) +static int kvazaar_encode(kvz_encoder *enc, kvz_picture *img_in, kvz_picture **img_out, kvz_payload **payload) { + // If img_in is NULL, just return the next unfinished frame. + if (img_in != NULL) { + encoder_state_t *state = &enc->states[enc->cur_state_num]; + + enc->frames_started += 1; + encoder_next_frame(state, img_in); + + CHECKPOINT_MARK("read source frame: %d", state->global->frame + enc->control->cfg->seek); + + // The actual coding happens here, after this function we have a coded frame + encode_one_frame(state); + } + + enc->cur_state_num = (enc->cur_state_num + 1) % (enc->num_encoder_states); + encoder_state_t *state = &enc->states[enc->cur_state_num]; + + if (enc->frames_started >= enc->num_encoder_states && !state->stats_done) { + threadqueue_waitfor(enc->control->threadqueue, state->tqj_bitstream_written); + *img_out = image_make_subimage(state->tile->frame->rec, 0, 0, state->tile->frame->width, state->tile->frame->height); + } + return 0; } diff --git a/src/kvazaar.h b/src/kvazaar.h index 677f7a86..e28d264c 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -90,8 +90,9 @@ typedef struct image_t { typedef struct kvz_encoder { encoder_control_t* control; encoder_state_t* states; - int num_encoder_states; - int cur_state_num; + unsigned num_encoder_states; + unsigned cur_state_num; + unsigned frames_started; size_t bitstream_length; } kvz_encoder; @@ -115,7 +116,7 @@ typedef struct kvz_api { // \param pic_out Picture containing the reconstructed data. // \param nals_out The first NAL containing bitstream generated, or NULL. // \return 1 on success, negative on error. - int (*encoder_encode)(kvz_encoder *encoder, kvz_picture *pic_in, kvz_picture *pic_out, kvz_payload **payload); + int (*encoder_encode)(kvz_encoder *encoder, kvz_picture *pic_in, kvz_picture **pic_out, kvz_payload **payload); } kvz_api; // Append API version to the getters name to prevent linking against incompatible versions.