From 5ed69b063bb2d8ffc25e69cb7ec2b6a9970a1348 Mon Sep 17 00:00:00 2001 From: Laurent Fasnacht Date: Mon, 2 Jun 2014 11:20:20 +0200 Subject: [PATCH] Strategy selector for array_checksum, basic implementation using precomputed 256*256 block with larger accesses than byte --- src/nal.c | 35 +-------- src/strategies/nal-generic.c | 145 +++++++++++++++++++++++++++++++++++ src/strategies/nal.c | 14 ++++ src/strategies/nal.h | 39 ++++++++++ src/strategyselector.c | 6 ++ src/strategyselector.h | 2 + 6 files changed, 207 insertions(+), 34 deletions(-) create mode 100644 src/strategies/nal-generic.c create mode 100644 src/strategies/nal.c create mode 100644 src/strategies/nal.h diff --git a/src/nal.c b/src/nal.c index 11907f30..2ca940f0 100644 --- a/src/nal.c +++ b/src/nal.c @@ -22,6 +22,7 @@ */ #include "nal.h" +#include "strategyselector.h" #include #include @@ -64,40 +65,6 @@ void nal_write(bitstream * const bitstream, const uint8_t nal_type, bitstream_writebyte(bitstream, byte); } - -/** - * \brief Calculate checksum for one color of the picture. - * \param data Beginning of the pixel data for the picture. - * \param height Height of the picture. - * \param width Width of the picture. - * \param stride Width of one row in the pixel array. - */ -static void array_checksum(const pixel* data, - const int height, const int width, - const int stride, - unsigned char checksum_out[SEI_HASH_MAX_LENGTH]) -{ - uint8_t mask; - uint32_t checksum = 0; - int y, x; - - assert(SEI_HASH_MAX_LENGTH >= 4); - - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - mask = (uint8_t)((x & 0xff) ^ (y & 0xff) ^ (x >> 8) ^ (y >> 8)); - checksum += (data[(y * stride) + x] & 0xff) ^ mask; - } - } - - // Unpack uint into byte-array. - checksum_out[0] = (checksum >> 24) & 0xff; - checksum_out[1] = (checksum >> 16) & 0xff; - checksum_out[2] = (checksum >> 8) & 0xff; - checksum_out[3] = (checksum) & 0xff; -} - - /*! \brief Calculate checksums for all colors of the picture. \param pic The picture that checksum is calculated for. diff --git a/src/strategies/nal-generic.c b/src/strategies/nal-generic.c new file mode 100644 index 00000000..e40282a9 --- /dev/null +++ b/src/strategies/nal-generic.c @@ -0,0 +1,145 @@ +/***************************************************************************** + * This file is part of Kvazaar HEVC encoder. + * + * Copyright (C) 2013-2014 Tampere University of Technology and others (see + * COPYING file). + * + * Kvazaar is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Kvazaar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kvazaar. If not, see . + ****************************************************************************/ + +/* + * \file + */ + +#include + +#include "nal.h" +#include +#include "../strategyselector.h" + + +static void array_checksum_generic(const pixel* data, + const int height, const int width, + const int stride, + unsigned char checksum_out[SEI_HASH_MAX_LENGTH]) { + int x, y; + int checksum = 0; + + assert(SEI_HASH_MAX_LENGTH >= 4); + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + const uint8_t mask = (uint8_t)((x & 0xff) ^ (y & 0xff) ^ (x >> 8) ^ (y >> 8)); + checksum += (data[(y * stride) + x] & 0xff) ^ mask; + } + } + + // Unpack uint into byte-array. + checksum_out[0] = (checksum >> 24) & 0xff; + checksum_out[1] = (checksum >> 16) & 0xff; + checksum_out[2] = (checksum >> 8) & 0xff; + checksum_out[3] = (checksum) & 0xff; +} + +static void array_checksum_generic4(const pixel* data, + const int height, const int width, + const int stride, + unsigned char checksum_out[SEI_HASH_MAX_LENGTH]) { + uint32_t checksum = 0; + int y, x, xp; + + static uint8_t ckmap_initialized = 0; + static uint32_t ckmap[64*256]; + + if (!ckmap_initialized) { + uint8_t * const ckmap_uint8 = (uint8_t*)&ckmap; + int x, y; + for (y = 0; y < 256; ++y) { + for (x = 0; x < 256; ++x) { + ckmap_uint8[y*256+x] = x^y; + } + } + ckmap_initialized = 1; + } + + assert(SEI_HASH_MAX_LENGTH >= 4); + + for (y = 0; y < height; ++y) { + for (xp = 0; xp < width/4; ++xp) { + const int x = xp * 4; + const uint32_t mask = ckmap[(xp&63)+64*(y&255)] ^ (((x >> 8) ^ (y >> 8)) * 0x1010101); + const uint32_t cksumbytes = (*((uint32_t*)(&data[(y * stride) + x]))) ^ mask; + checksum += ((cksumbytes >> 24) & 0xff) + ((cksumbytes >> 16) & 0xff) + ((cksumbytes >> 8) & 0xff) + (cksumbytes & 0xff); + } + for (x = xp*4; x < width; ++x) { + uint8_t mask = (uint8_t)((x & 0xff) ^ (y & 0xff) ^ (x >> 8) ^ (y >> 8)); + checksum += (data[(y * stride) + x] & 0xff) ^ mask; + } + } + + // Unpack uint into byte-array. + checksum_out[0] = (checksum >> 24) & 0xff; + checksum_out[1] = (checksum >> 16) & 0xff; + checksum_out[2] = (checksum >> 8) & 0xff; + checksum_out[3] = (checksum) & 0xff; +} + +static void array_checksum_generic8(const pixel* data, + const int height, const int width, + const int stride, + unsigned char checksum_out[SEI_HASH_MAX_LENGTH]) { + uint32_t checksum = 0; + int y, x, xp; + + static uint8_t ckmap_initialized = 0; + static uint64_t ckmap[32*256]; + + if (!ckmap_initialized) { + uint8_t * const ckmap_uint8 = (uint8_t*)&ckmap; + int x, y; + for (y = 0; y < 256; ++y) { + for (x = 0; x < 256; ++x) { + ckmap_uint8[y*256+x] = x^y; + } + } + ckmap_initialized = 1; + } + + assert(SEI_HASH_MAX_LENGTH >= 4); + + for (y = 0; y < height; ++y) { + for (xp = 0; xp < width/8; ++xp) { + const int x = xp * 8; + const uint64_t mask = ckmap[(xp&31)+32*(y&255)] ^ ((uint64_t)((x >> 8) ^ (y >> 8)) * 0x101010101010101); + const uint64_t cksumbytes = (*((uint64_t*)(&data[(y * stride) + x]))) ^ mask; + checksum += ((cksumbytes >> 56) & 0xff) + ((cksumbytes >> 48) & 0xff) + ((cksumbytes >> 40) & 0xff) + ((cksumbytes >> 32) & 0xff) + ((cksumbytes >> 24) & 0xff) + ((cksumbytes >> 16) & 0xff) + ((cksumbytes >> 8) & 0xff) + (cksumbytes & 0xff); + } + for (x = xp*8; x < width; ++x) { + uint8_t mask = (uint8_t)((x & 0xff) ^ (y & 0xff) ^ (x >> 8) ^ (y >> 8)); + checksum += (data[(y * stride) + x] & 0xff) ^ mask; + } + } + + // Unpack uint into byte-array. + checksum_out[0] = (checksum >> 24) & 0xff; + checksum_out[1] = (checksum >> 16) & 0xff; + checksum_out[2] = (checksum >> 8) & 0xff; + checksum_out[3] = (checksum) & 0xff; +} + +static int strategy_register_nal_generic(void* opaque) { + if (!strategyselector_register(opaque, "array_checksum", "generic", 0, &array_checksum_generic)) return 0; + if (!strategyselector_register(opaque, "array_checksum", "generic4", 1, &array_checksum_generic4)) return 0; + if (!strategyselector_register(opaque, "array_checksum", "generic8", 2, &array_checksum_generic8)) return 0; + return 1; +} diff --git a/src/strategies/nal.c b/src/strategies/nal.c new file mode 100644 index 00000000..d0a15e48 --- /dev/null +++ b/src/strategies/nal.c @@ -0,0 +1,14 @@ +#include "nal.h" +#include "nal-generic.c" + +void (*array_checksum)(const pixel* data, + const int height, const int width, + const int stride, + unsigned char checksum_out[SEI_HASH_MAX_LENGTH]); + + +static int strategy_register_nal(void* opaque) { + if (!strategy_register_nal_generic(opaque)) return 0; + + return 1; +} diff --git a/src/strategies/nal.h b/src/strategies/nal.h new file mode 100644 index 00000000..c8baea3a --- /dev/null +++ b/src/strategies/nal.h @@ -0,0 +1,39 @@ +#ifndef STRATEGIES_NAL_H_ +#define STRATEGIES_NAL_H_ +/***************************************************************************** + * This file is part of Kvazaar HEVC encoder. + * + * Copyright (C) 2013-2014 Tampere University of Technology and others (see + * COPYING file). + * + * Kvazaar is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Kvazaar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kvazaar. If not, see . + ****************************************************************************/ + +#include "../nal.h" + +//Function pointer to array_checksum +/** + * \brief Calculate checksum for one color of the picture. + * \param data Beginning of the pixel data for the picture. + * \param height Height of the picture. + * \param width Width of the picture. + * \param stride Width of one row in the pixel array. + */ +extern void (*array_checksum)(const pixel* data, + const int height, const int width, + const int stride, + unsigned char checksum_out[SEI_HASH_MAX_LENGTH]); + +#define STRATEGIES_NAL_EXPORTS {"array_checksum", (void**) &array_checksum} + +#endif //STRATEGIES_NAL_H_ diff --git a/src/strategyselector.c b/src/strategyselector.c index e4da6ea6..46b92610 100644 --- a/src/strategyselector.c +++ b/src/strategyselector.c @@ -33,6 +33,7 @@ static void* strategyselector_choose_for(const strategy_list * const strategies, //Strategies to include (add new file here) #include "strategies/picture.c" +#include "strategies/nal.c" //Returns 1 if successful int strategyselector_init() { @@ -51,6 +52,11 @@ int strategyselector_init() { return 0; } + if (!strategy_register_nal(&strategies)) { + fprintf(stderr, "strategy_register_nal failed!\n"); + return 0; + } + while(cur_strategy_to_select->fptr) { *(cur_strategy_to_select->fptr) = strategyselector_choose_for(&strategies, cur_strategy_to_select->strategy_type); diff --git a/src/strategyselector.h b/src/strategyselector.h index 514e900d..519526d1 100644 --- a/src/strategyselector.h +++ b/src/strategyselector.h @@ -127,9 +127,11 @@ int strategyselector_register(void *opaque, const char *type, const char *strate //Strategy to include +#include "strategies/nal.h" #include "strategies/picture.h" static const strategy_to_select strategies_to_select[] = { + STRATEGIES_NAL_EXPORTS, STRATEGIES_PICTURE_EXPORTS, {NULL, NULL}, };