From d8d44e5bcd0ed5cc7d6093a8ef7cdf42ccf9d832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 31 Jan 2014 17:17:44 +0200 Subject: [PATCH 1/6] encoder: Remove a non-UTF-8 symbol from the code Silences a Visual Studio warning on systems where the symbol is not in the local code page --- src/encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/encoder.c b/src/encoder.c index 19543735..c8f237bb 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -1298,7 +1298,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 From 271c08f963b35bec1fc4f58c7b44944d434f083a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 31 Jan 2014 17:24:04 +0200 Subject: [PATCH 2/6] config: Add a string copying helper function Removes the need to add the same code into multiple places --- src/config.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/config.c b/src/config.c index e2535e91..92b9de0b 100644 --- a/src/config.c +++ b/src/config.c @@ -72,6 +72,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 +115,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]); From 7db28fad846288b5e23da3bf9705d116dbb4233c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 31 Jan 2014 17:26:09 +0200 Subject: [PATCH 3/6] encmain: Make the main function more resilient to allocation failures Application will no longer crash if config or encoder_control allocation fails. --- src/encmain.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/encmain.c b/src/encmain.c index 49d36311..5ebaef8d 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -73,6 +73,8 @@ int main(int argc, char *argv[]) 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 @@ -85,7 +87,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 || !encoder || !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,7 +103,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); + if (cfg) + config_destroy(cfg); + free(encoder); return EXIT_FAILURE; } From 007986974a64bec4f6839f32c93a5d4736f1e146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 31 Jan 2014 17:30:27 +0200 Subject: [PATCH 4/6] config: Make config_alloc() no longer crash if allocation fails --- src/config.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/config.c b/src/config.c index 92b9de0b..049de61d 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; } From ac8fbc051918c2c6346286a4b3c31a746f4d0e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= Date: Fri, 31 Jan 2014 20:34:50 +0200 Subject: [PATCH 5/6] Move initialization away from main() --- src/bitstream.c | 61 ++++++++++++++++++++++++++++++++++------ src/bitstream.h | 9 +++--- src/encmain.c | 28 ++++-------------- src/encoder.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++-- src/encoder.h | 2 +- 5 files changed, 137 insertions(+), 38 deletions(-) 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); From 478740cf2143ccd7ba8a56f524574b4fb69e13c4 Mon Sep 17 00:00:00 2001 From: Ari Koivula Date: Mon, 3 Feb 2014 16:32:54 +0200 Subject: [PATCH 6/6] Add missing new lines to ends of files. --- src/bitstream.c | 1 - src/config.c | 2 +- src/config.h | 2 +- src/global.h | 2 +- src/inter.c | 1 - src/nal.c | 2 +- src/sao.h | 2 +- tests/sad_tests.c | 1 - 8 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/bitstream.c b/src/bitstream.c index 30b10125..9d8196b8 100644 --- a/src/bitstream.c +++ b/src/bitstream.c @@ -263,4 +263,3 @@ void bitstream_flush(bitstream *stream) //Stream flushed, zero out the values bitstream_reinit(stream); } - diff --git a/src/config.c b/src/config.c index 049de61d..6104da5c 100644 --- a/src/config.c +++ b/src/config.c @@ -157,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/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); } -