diff --git a/src/bitstream.c b/src/bitstream.c index cbb9bd19..6466bfca 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; } /** @@ -225,6 +270,5 @@ 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 d5e84716..023ac2f3 100644 --- a/src/bitstream.h +++ b/src/bitstream.h @@ -47,11 +47,12 @@ 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_free(bitstream *stream); 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 */ @@ -62,7 +63,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 */ @@ -79,4 +80,4 @@ static int WRITE_VALUE = 0; #endif -#endif \ No newline at end of file +#endif diff --git a/src/config.c b/src/config.c index e2535e91..6104da5c 100644 --- a/src/config.c +++ b/src/config.c @@ -35,6 +35,11 @@ config *config_alloc() { config *cfg = (config *)malloc(sizeof(config)); + if (!cfg) { + fprintf(stderr, "Failed to allocate a config object!\n"); + return cfg; + } + memset(cfg, 0, sizeof(config)); return cfg; } @@ -72,6 +77,26 @@ int config_destroy(config *cfg) return 1; } +/** + * \brief Allocates memory space for a string, and copies it + * \param char * string to copy + * \return a pointer to the copied string on success, null on failure + */ +char *copy_string(char *string) +{ + // Allocate +1 for \0 + char *allocated_string = (char *)malloc(strlen(string) + 1); + if (!allocated_string) { + fprintf(stderr, "Failed to allocate a string!\n"); + return allocated_string; + } + + // Copy the string to the new buffer + memcpy(allocated_string, string, strlen(string) + 1); + + return allocated_string; +} + /** * \brief Read configuration options from argv to the config struct * \param cfg config object @@ -95,17 +120,13 @@ int config_read(config *cfg,int argc, char *argv[]) arg++; switch(option) { case 'i': // Input - // Allocate +1 for \0 - cfg->input = (char *)malloc(strlen(argv[arg]) + 1); - memcpy(cfg->input, argv[arg], strlen(argv[arg]) + 1); + cfg->input = copy_string(argv[arg]); break; case 'o': // Output - cfg->output = (char *)malloc(strlen(argv[arg]) + 1); - memcpy(cfg->output, argv[arg], strlen(argv[arg]) + 1); + cfg->output = copy_string(argv[arg]); break; case 'd': // Debug - cfg->debug = (char *)malloc(strlen(argv[arg]) + 1); - memcpy(cfg->debug, argv[arg], strlen(argv[arg]) + 1); + cfg->debug = copy_string(argv[arg]); break; case 'w': // width cfg->width = atoi(argv[arg]); @@ -136,4 +157,4 @@ int config_read(config *cfg,int argc, char *argv[]) if(cfg->input == NULL || cfg->output == NULL) return 0; return 1; -} \ No newline at end of file +} diff --git a/src/config.h b/src/config.h index 74e09fa9..449030db 100644 --- a/src/config.h +++ b/src/config.h @@ -49,4 +49,4 @@ int config_init(config *cfg); int config_destroy(config *cfg); int config_read(config *cfg,int argc, char *argv[]); -#endif \ No newline at end of file +#endif diff --git a/src/encmain.c b/src/encmain.c index 4c6fd5e4..30f5a4d5 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -66,13 +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)); // Windows needs all of the standard in/outputs to be set to _O_BINARY #ifdef _WIN32 @@ -85,7 +85,7 @@ int main(int argc, char *argv[]) cfg = config_alloc(); // If problem with configuration, print banner and shutdown - if (!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"); @@ -101,8 +101,9 @@ int main(int argc, char *argv[]) fprintf(stderr, " 1: all pictures are intra\r\n"); fprintf(stderr, " 2-N: every Nth picture is intra\r\n"); - config_destroy(cfg); - free(encoder); + if (cfg) + config_destroy(cfg); + return EXIT_FAILURE; } @@ -148,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 28b1799a..d624edbe 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -229,10 +229,80 @@ void free_tables(void) free(g_sig_last_scan[2][i]); } } - -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, @@ -1315,7 +1385,7 @@ void encode_coding_tree(encoder_control *encoder, uint16_t x_ctb, } /** - * Table 9-35 – Binarization for intra_chroma_pred_mode + * Table 9-35 - Binarization for intra_chroma_pred_mode * intra_chroma_pred_mode bin_string * 4 0 * 0 100 diff --git a/src/encoder.h b/src/encoder.h index 1a48dddb..7edd94dc 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -82,7 +82,7 @@ typedef struct void init_tables(void); void free_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); diff --git a/src/global.h b/src/global.h index 216a94e4..94f67137 100644 --- a/src/global.h +++ b/src/global.h @@ -160,4 +160,4 @@ typedef int16_t coefficient; #define MAX_DOUBLE 1.7e+308 #endif -#endif \ No newline at end of file +#endif diff --git a/src/inter.c b/src/inter.c index cf89e298..2ab5b2ab 100644 --- a/src/inter.c +++ b/src/inter.c @@ -441,4 +441,3 @@ uint8_t inter_get_merge_cand(encoder_control *encoder, int32_t x_cu, int32_t y_c return candidates; } - diff --git a/src/nal.c b/src/nal.c index 7f536b8d..c9616467 100644 --- a/src/nal.c +++ b/src/nal.c @@ -133,4 +133,4 @@ void picture_checksum(const picture* pic, unsigned char checksum_out[][SEI_HASH_ /* The number of chroma pixels is half that of luma. */ array_checksum(pic->u_recdata, pic->height >> 1, pic->width >> 1, pic->width >> 1, checksum_out[1]); array_checksum(pic->v_recdata, pic->height >> 1, pic->width >> 1, pic->width >> 1, checksum_out[2]); -} \ No newline at end of file +} diff --git a/src/sao.h b/src/sao.h index 0d0a6c2c..fdf87f33 100644 --- a/src/sao.h +++ b/src/sao.h @@ -50,4 +50,4 @@ void sao_reconstruct(picture *pic, const pixel *old_rec, unsigned x_ctb, unsigned y_ctb, const sao_info *sao, color_index color_i); -#endif \ No newline at end of file +#endif diff --git a/tests/sad_tests.c b/tests/sad_tests.c index 124edba4..7c0787b0 100644 --- a/tests/sad_tests.c +++ b/tests/sad_tests.c @@ -236,4 +236,3 @@ SUITE(sad_tests) sad_setup(0); } -