diff --git a/src/bitstream.h b/src/bitstream.h index 0b345f24..dcb1560c 100644 --- a/src/bitstream.h +++ b/src/bitstream.h @@ -53,7 +53,7 @@ typedef struct uint32_t allocated_length; } bitstream_mem_t; -typedef union +typedef union bitstream_t { bitstream_base_t base; bitstream_file_t file; diff --git a/src/encmain.c b/src/encmain.c index 79a6edef..97d31469 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -117,13 +117,19 @@ int main(int argc, char *argv[]) } else { // Otherwise we try to open the output file output = fopen(cfg->output, "wb"); + // Check that output was opened correctly + if (output == NULL) { + fprintf(stderr, "Could not open output file, shutting down!\n"); + goto exit_failure; + } } - // Check that output was opened correctly - if (output == NULL) { - fprintf(stderr, "Could not open output file, shutting down!\n"); - goto exit_failure; + bitstream_t output_stream; + if (!bitstream_init(&output_stream, BITSTREAM_TYPE_FILE)) { + fprintf(stderr, "Could not initialize stream!\n"); + return 0; } + output_stream.file.output = output; if (cfg->debug != NULL) { recout = fopen(cfg->debug, "wb"); @@ -147,11 +153,6 @@ int main(int argc, char *argv[]) goto exit_failure; } - - for (unsigned i = 0; i <= cfg->owf; ++i) { - enc->states[i].stream.file.output = output; - } - encoder_control_t *encoder = enc->control; fprintf(stderr, "Input: %s, output: %s\n", cfg->input, cfg->output); @@ -223,7 +224,7 @@ int main(int argc, char *argv[]) } image_t *img_out = NULL; - api->encoder_encode(enc, img_in, &img_out, NULL); + api->encoder_encode(enc, img_in, &img_out, &output_stream); if (img_out != NULL) { state = &enc->states[enc->cur_state_num]; @@ -247,9 +248,8 @@ int main(int argc, char *argv[]) int first_enc = current_encoder_state; 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); + api->encoder_encode(enc, NULL, &img_out, &output_stream); if (img_out != NULL) { encoder_state_t *state = &enc->states[current_encoder_state]; @@ -292,6 +292,8 @@ int main(int argc, char *argv[]) fprintf(stderr, " FPS: %.2f\n", ((double)frames_done)/wall_time); } + bitstream_finalize(&output_stream); + fclose(input); fclose(output); if(recout != NULL) fclose(recout); diff --git a/src/encoder_state-bitstream.c b/src/encoder_state-bitstream.c index 203b9169..77366e0c 100644 --- a/src/encoder_state-bitstream.c +++ b/src/encoder_state-bitstream.c @@ -817,9 +817,6 @@ static void encoder_state_write_bitstream_main(encoder_state_t * const state) { state->global->cur_gop_bits_coded = 0; } state->global->cur_gop_bits_coded += newpos - curpos; - - // Flush the output in case someone is reading the file on the other end. - fflush(state->stream.file.output); } void encoder_state_write_bitstream_leaf(encoder_state_t * const state) { diff --git a/src/encoder_state-ctors_dtors.c b/src/encoder_state-ctors_dtors.c index 0101be6a..bc532fbc 100644 --- a/src/encoder_state-ctors_dtors.c +++ b/src/encoder_state-ctors_dtors.c @@ -322,20 +322,9 @@ int encoder_state_init(encoder_state_t * const child_state, encoder_state_t * co if (!child_state->wfrow) child_state->wfrow = parent_state->wfrow; } - //Allocate bitstream - if (child_state->type == ENCODER_STATE_TYPE_MAIN) { - //Main encoder outputs to file - if (!bitstream_init(&child_state->stream, BITSTREAM_TYPE_FILE)) { - fprintf(stderr, "Could not initialize stream!\n"); - return 0; - } - child_state->stream.file.output = NULL; - } else { - //Other encoders use a memory bitstream - if (!bitstream_init(&child_state->stream, BITSTREAM_TYPE_MEMORY)) { - fprintf(stderr, "Could not initialize stream!\n"); - return 0; - } + if (!bitstream_init(&child_state->stream, BITSTREAM_TYPE_MEMORY)) { + fprintf(stderr, "Could not initialize stream!\n"); + return 0; } // Set CABAC output bitstream diff --git a/src/encoderstate.c b/src/encoderstate.c index 0739b26d..2cb5a119 100644 --- a/src/encoderstate.c +++ b/src/encoderstate.c @@ -786,7 +786,8 @@ static void encoder_state_new_frame(encoder_state_t * const state) { state->global->cur_lambda_cost = lambda; state->global->cur_lambda_cost_sqrt = sqrt(lambda); - } else { + } + if (state->stream.base.type == BITSTREAM_TYPE_MEMORY) { //Clear the bitstream if it's not the main encoder bitstream_clear(&state->stream); } diff --git a/src/kvazaar.c b/src/kvazaar.c index d87b258f..ac374e2b 100644 --- a/src/kvazaar.c +++ b/src/kvazaar.c @@ -27,6 +27,7 @@ #include "strategyselector.h" #include "encoderstate.h" #include "checkpoint.h" +#include "bitstream.h" static void kvazaar_close(kvz_encoder *encoder) @@ -106,7 +107,7 @@ kvazaar_open_failure: } -static int kvazaar_encode(kvz_encoder *enc, kvz_picture *img_in, kvz_picture **img_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) { @@ -126,6 +127,14 @@ static int kvazaar_encode(kvz_encoder *enc, kvz_picture *img_in, kvz_picture **i if (enc->frames_started >= enc->num_encoder_states && !state->stats_done) { threadqueue_waitfor(enc->control->threadqueue, state->tqj_bitstream_written); + + bitstream_append(payload, &state->stream); + + // Flush the output in case someone is reading the file on the other end. + if (payload->base.type == BITSTREAM_TYPE_FILE) { + fflush(payload->file.output); + } + *img_out = image_make_subimage(state->tile->frame->rec, 0, 0, state->tile->frame->width, state->tile->frame->height); } diff --git a/src/kvazaar.h b/src/kvazaar.h index 7d55d370..7f0ea1f5 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -36,7 +36,7 @@ extern "C" { typedef struct config_t kvz_cfg; typedef struct encoder_state_t encoder_state_t; -typedef struct kvz_payload kvz_payload; +typedef union bitstream_t kvz_payload; typedef struct encoder_control_t encoder_control_t; typedef struct image_t kvz_picture; @@ -49,17 +49,6 @@ typedef uint16_t pixel_t; #endif -/** -* A payload unit containing at most a single frame. -* If next is not NULL, the bytestream continues in that payload unit. -*/ -typedef struct kvz_payload { - uint32_t type; - uint32_t size_bytes; - uint8_t *payload; - kvz_payload *next; -} kvz_payload; - /** * \brief Struct which contains all picture data */ @@ -113,7 +102,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.