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
This commit is contained in:
Ari Koivula 2015-05-19 17:48:37 +03:00 committed by Arttu Ylä-Outinen
parent 9a3edce3fc
commit 4e5326d3d5
3 changed files with 38 additions and 22 deletions

View file

@ -203,7 +203,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
encoder_state_t *state = &enc->states[current_encoder_state]; encoder_state_t *state = &enc->states[current_encoder_state];
while (cfg->frames == 0 || frames_started < cfg->frames) { while (cfg->frames == 0 || frames_started < cfg->frames) {
image_t *img_out = NULL;
frames_started += 1; frames_started += 1;
@ -223,24 +222,11 @@ int main(int argc, char *argv[])
break; 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) { if (img_out != NULL) {
state = &enc->states[enc->cur_state_num];
double frame_psnr[3] = { 0.0, 0.0, 0.0 }; double frame_psnr[3] = { 0.0, 0.0, 0.0 };
encoder_compute_stats(state, recout, frame_psnr, &bitstream_length); encoder_compute_stats(state, recout, frame_psnr, &bitstream_length);
@ -262,14 +248,20 @@ int main(int argc, char *argv[])
do { do {
double frame_psnr[3] = { 0.0, 0.0, 0.0 }; double frame_psnr[3] = { 0.0, 0.0, 0.0 };
encoder_state_t *state = &enc->states[current_encoder_state]; 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); encoder_compute_stats(state, recout, frame_psnr, &bitstream_length);
print_frame_info(state, frame_psnr); print_frame_info(state, frame_psnr);
frames_done += 1; frames_done += 1;
psnr_sum[0] += frame_psnr[0]; psnr_sum[0] += frame_psnr[0];
psnr_sum[1] += frame_psnr[1]; psnr_sum[1] += frame_psnr[1];
psnr_sum[2] += frame_psnr[2]; psnr_sum[2] += frame_psnr[2];
image_free(img_out);
} }
current_encoder_state = (current_encoder_state + 1) % (encoder->owf + 1); current_encoder_state = (current_encoder_state + 1) % (encoder->owf + 1);

View file

@ -26,6 +26,7 @@
#include "encoder.h" #include "encoder.h"
#include "strategyselector.h" #include "strategyselector.h"
#include "encoderstate.h" #include "encoderstate.h"
#include "checkpoint.h"
static void kvazaar_close(kvz_encoder *encoder) 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->num_encoder_states = cfg->owf + 1;
encoder->cur_state_num = 0; encoder->cur_state_num = 0;
encoder->frames_started = 0;
encoder->states = MALLOC(encoder_state_t, encoder->num_encoder_states); encoder->states = MALLOC(encoder_state_t, encoder->num_encoder_states);
if (!encoder->states) { if (!encoder->states) {
goto kvazaar_open_failure; 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; return 0;
} }

View file

@ -90,8 +90,9 @@ typedef struct image_t {
typedef struct kvz_encoder { typedef struct kvz_encoder {
encoder_control_t* control; encoder_control_t* control;
encoder_state_t* states; encoder_state_t* states;
int num_encoder_states; unsigned num_encoder_states;
int cur_state_num; unsigned cur_state_num;
unsigned frames_started;
size_t bitstream_length; size_t bitstream_length;
} kvz_encoder; } kvz_encoder;
@ -115,7 +116,7 @@ typedef struct kvz_api {
// \param pic_out Picture containing the reconstructed data. // \param pic_out Picture containing the reconstructed data.
// \param nals_out The first NAL containing bitstream generated, or NULL. // \param nals_out The first NAL containing bitstream generated, or NULL.
// \return 1 on success, negative on error. // \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; } kvz_api;
// Append API version to the getters name to prevent linking against incompatible versions. // Append API version to the getters name to prevent linking against incompatible versions.