Strategy selector for array_checksum, basic implementation using precomputed 256*256 block with larger accesses than byte

This commit is contained in:
Laurent Fasnacht 2014-06-02 11:20:20 +02:00
parent a483e8cb0f
commit 5ed69b063b
6 changed files with 207 additions and 34 deletions

View file

@ -22,6 +22,7 @@
*/ */
#include "nal.h" #include "nal.h"
#include "strategyselector.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -64,40 +65,6 @@ void nal_write(bitstream * const bitstream, const uint8_t nal_type,
bitstream_writebyte(bitstream, byte); 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. \brief Calculate checksums for all colors of the picture.
\param pic The picture that checksum is calculated for. \param pic The picture that checksum is calculated for.

View file

@ -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 <http://www.gnu.org/licenses/>.
****************************************************************************/
/*
* \file
*/
#include <stdlib.h>
#include "nal.h"
#include <assert.h>
#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;
}

14
src/strategies/nal.c Normal file
View file

@ -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;
}

39
src/strategies/nal.h Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#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_

View file

@ -33,6 +33,7 @@ static void* strategyselector_choose_for(const strategy_list * const strategies,
//Strategies to include (add new file here) //Strategies to include (add new file here)
#include "strategies/picture.c" #include "strategies/picture.c"
#include "strategies/nal.c"
//Returns 1 if successful //Returns 1 if successful
int strategyselector_init() { int strategyselector_init() {
@ -51,6 +52,11 @@ int strategyselector_init() {
return 0; return 0;
} }
if (!strategy_register_nal(&strategies)) {
fprintf(stderr, "strategy_register_nal failed!\n");
return 0;
}
while(cur_strategy_to_select->fptr) { while(cur_strategy_to_select->fptr) {
*(cur_strategy_to_select->fptr) = strategyselector_choose_for(&strategies, cur_strategy_to_select->strategy_type); *(cur_strategy_to_select->fptr) = strategyselector_choose_for(&strategies, cur_strategy_to_select->strategy_type);

View file

@ -127,9 +127,11 @@ int strategyselector_register(void *opaque, const char *type, const char *strate
//Strategy to include //Strategy to include
#include "strategies/nal.h"
#include "strategies/picture.h" #include "strategies/picture.h"
static const strategy_to_select strategies_to_select[] = { static const strategy_to_select strategies_to_select[] = {
STRATEGIES_NAL_EXPORTS,
STRATEGIES_PICTURE_EXPORTS, STRATEGIES_PICTURE_EXPORTS,
{NULL, NULL}, {NULL, NULL},
}; };