diff --git a/src/bitstream.c b/src/bitstream.c index e1bb3102..30b10125 100644 --- a/src/bitstream.c +++ b/src/bitstream.c @@ -67,15 +67,18 @@ int floor_log2(unsigned int n) { /** * \brief Initialize the Exp Golomb code table with desired number of values * \param len table length to init - * + * \return 1 on success, 0 on failure + * * Allocates g_exp_table with len*sizeof(bit_table) and fills it with exponential golomb codes */ -void init_exp_golomb(uint32_t len) +int init_exp_golomb(uint32_t len) { uint32_t code_num; uint32_t M; uint32_t info; g_exp_table = (bit_table*)malloc(len*sizeof(bit_table)); + if(!g_exp_table) + return 0; for (code_num = 0; code_num < len; code_num++) { M = (uint32_t)floor_log2(code_num + 1); @@ -83,12 +86,55 @@ void init_exp_golomb(uint32_t len) g_exp_table[code_num].len = M * 2 + 1; g_exp_table[code_num].value = (1<output = NULL; + stream->buffer = NULL; + stream->buffer_pos = 0; + stream->bufferlen = 0; + + // Alloc 2kB*width for bitstream buffer (for one coded frame) + bitstream_alloc(stream, 1024*2*width); + if (!stream->buffer) { + fprintf(stderr, "Failed to allocate the bitstream buffer!\n"); + goto creation_failure; + } + + //Clear buffer just to be sure + bitstream_clear_buffer(stream); + + // Return the created bitstream + return stream; + +creation_failure: + // In case of failure, free whatever was allocated + free(stream->buffer); + free(stream); + + return NULL; +} + +/** + * \brief Reinitialize bitstream + */ +void bitstream_reinit(bitstream *stream) { stream->cur_byte = 0; stream->cur_bit = 0; @@ -103,9 +149,8 @@ void bitstream_init(bitstream *stream) void bitstream_alloc(bitstream *stream, uint32_t alloc) { stream->buffer = (uint8_t*)malloc(alloc); - stream->bufferlen = alloc; - //Clear just to be sure - bitstream_clear_buffer(stream); + if (stream->buffer) + stream->bufferlen = alloc; } /** @@ -216,6 +261,6 @@ void bitstream_flush(bitstream *stream) } } //Stream flushed, zero out the values - bitstream_init(stream); + bitstream_reinit(stream); } diff --git a/src/bitstream.h b/src/bitstream.h index 36df138d..77896cc2 100644 --- a/src/bitstream.h +++ b/src/bitstream.h @@ -47,10 +47,11 @@ typedef struct extern bit_table *g_exp_table; int floor_log2(unsigned int n); - + +bitstream *create_bitstream(int32_t width); void bitstream_alloc(bitstream* stream, uint32_t alloc); void bitstream_clear_buffer(bitstream* stream); -void bitstream_init(bitstream* stream); +void bitstream_reinit(bitstream *stream); void bitstream_put(bitstream* stream, uint32_t data, uint8_t bits); /* Use macros to force inlining */ @@ -61,7 +62,7 @@ void bitstream_put(bitstream* stream, uint32_t data, uint8_t bits); void bitstream_align(bitstream* stream); void bitstream_align_zero(bitstream* stream); void bitstream_flush(bitstream* stream); -void init_exp_golomb(uint32_t len); +int init_exp_golomb(uint32_t len); /* In debug mode print out some extra info */ @@ -78,4 +79,4 @@ static int WRITE_VALUE = 0; #endif -#endif \ No newline at end of file +#endif diff --git a/src/encmain.c b/src/encmain.c index 5ebaef8d..315ece94 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -66,15 +66,13 @@ int main(int argc, char *argv[]) config *cfg = NULL; //!< Global configuration FILE *input = NULL; //!< input file (YUV) FILE *output = NULL; //!< output file (HEVC NAL stream) + encoder_control *encoder = NULL; //!< Encoder control struct double psnr[3] = { 0.0, 0.0, 0.0 }; uint64_t curpos = 0; uint64_t lastpos = 0; #ifdef _DEBUG FILE *recout = fopen("encrec_832x480_60.yuv","wb"); //!< reconstructed YUV output (only on debug mode) #endif - encoder_control *encoder = (encoder_control*)malloc(sizeof(encoder_control)); - if (!encoder) - fprintf(stderr, "Failed to allocate the encoder_control object!\n"); // Windows needs all of the standard in/outputs to be set to _O_BINARY #ifdef _WIN32 @@ -87,7 +85,7 @@ int main(int argc, char *argv[]) cfg = config_alloc(); // If problem with configuration, print banner and shutdown - if (!cfg || !encoder || !config_init(cfg) || !config_read(cfg,argc,argv)) { + if (!cfg || !config_init(cfg) || !config_read(cfg,argc,argv)) { fprintf(stderr, "/***********************************************/\r\n"); fprintf(stderr, " * Kvazaar HEVC Encoder v. " VERSION_STRING "*\r\n"); fprintf(stderr, " * Tampere University of Technology 2014 *\r\n"); @@ -106,7 +104,6 @@ int main(int argc, char *argv[]) if (cfg) config_destroy(cfg); - free(encoder); return EXIT_FAILURE; } @@ -152,27 +149,12 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - // Initialization - init_tables(); - init_exp_golomb(4096*8); //Allocate and init exp golomb table - scalinglist_init(); - init_encoder_control(encoder, (bitstream*)malloc(sizeof(bitstream))); - encoder->ref = picture_list_init(MAX_REF_PIC_COUNT); - - // Init bitstream - bitstream_init(encoder->stream); - encoder->stream->buffer_pos = 0; - encoder->stream->output = 0; + encoder = init_encoder_control(cfg); + if (!encoder) + return EXIT_FAILURE; - // Alloc 2kB*width for bitstream buffer (for one coded frame) - bitstream_alloc(encoder->stream, 1024*2*cfg->width); - - // Config pointer to encoder struct - encoder->cfg = cfg; // Set output file encoder->output = output; - // Set CABAC output bitstream - cabac.stream = encoder->stream; // input init (TODO: read from commandline / config) encoder->bitdepth = 8; diff --git a/src/encoder.c b/src/encoder.c index c8f237bb..4e351e20 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -220,9 +220,80 @@ void init_tables(void) } -void init_encoder_control(encoder_control* control,bitstream* output) +encoder_control *init_encoder_control(config *cfg) { - control->stream = output; + encoder_control *enc_c = NULL; + bitstream *stream = NULL; + picture_list *pic_list = NULL; + + if (!cfg) { + fprintf(stderr, "Config object must not be null!\n"); + goto init_failure; + } + + // Allocate the main struct + enc_c = malloc(sizeof(encoder_control)); + if(!enc_c){ + fprintf(stderr, "Failed to allocate encoder_control!\n"); + goto init_failure; + } + + // Config pointer to encoder struct + enc_c->cfg = cfg; + + // input init (TODO: read from commandline / config) + enc_c->bitdepth = 8; + enc_c->frame = 0; + enc_c->QP = enc_c->cfg->qp; + enc_c->in.video_format = FORMAT_420; + // deblocking filter + enc_c->deblock_enable = 1; + enc_c->beta_offset_div2 = 0; + enc_c->tc_offset_div2 = 0; + // SAO + enc_c->sao_enable = 1; + + // Allocate the bitstream struct + stream = create_bitstream(enc_c->cfg->width); + if (!stream) { + fprintf(stderr, "Failed to allocate the bitstream object!\n"); + goto init_failure; + } + + enc_c->stream = stream; + + // Set CABAC output bitstream + cabac.stream = enc_c->stream; + + // Initialize tables + init_tables(); + + //Allocate and init exp golomb table + if (!init_exp_golomb(4096*8)) { + fprintf(stderr, "Failed to allocate the exp golomb code table, shutting down!\n"); + goto init_failure; + } + + // Initialize the scaling list + scalinglist_init(); + + pic_list = picture_list_init(MAX_REF_PIC_COUNT); + if(!pic_list) { + fprintf(stderr, "Failed to allocate the picture list!\n"); + goto init_failure; + } + + enc_c->ref = pic_list; + + return enc_c; + +init_failure: + // Free everything allocated in this function + free(pic_list); + free(stream); + free(enc_c); + + return NULL; } void init_encoder_input(encoder_input *input, FILE *inputfile, diff --git a/src/encoder.h b/src/encoder.h index 84e2a400..782eb38d 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -81,7 +81,7 @@ typedef struct } encoder_control; void init_tables(void); -void init_encoder_control(encoder_control *control, bitstream *output); +encoder_control *init_encoder_control(config *cfg); void init_encoder_input(encoder_input *input, FILE* inputfile, int32_t width, int32_t height); void encode_one_frame(encoder_control *encoder);